tgRecipe.c
上传用户:blenddy
上传日期:2007-01-07
资源大小:6495k
文件大小:20k
源码类别:

数据库系统

开发平台:

Unix_Linux

  1. /*-------------------------------------------------------------------------
  2.  *
  3.  * tgRecipe.c
  4.  * Tioga recipe-related definitions
  5.  * these functions can be used in both the frontend and the
  6.  * backend
  7.  *
  8.  * this file must be kept current with recipe-schema.sql
  9.  *
  10.  * Copyright (c) 1994, Regents of the University of California
  11.  *
  12.  *
  13.  * IDENTIFICATION
  14.  *   $Header: /usr/local/cvsroot/pgsql/src/backend/tioga/tgRecipe.c,v 1.12 1999/05/10 00:45:49 momjian Exp $
  15.  *
  16.  *-------------------------------------------------------------------------
  17.  */
  18. #include <stdlib.h>
  19. #include "postgres.h"
  20. #include "tioga/tgRecipe.h"
  21. #include "catalog/catalog.h" /* for newoid() */
  22. static Arr_TgString *TextArray2ArrTgString(char *str);
  23. #define ARRAY_LEFT_DELIM '{'
  24. #define ARRAY_RIGHT_DELIM '}'
  25. #define ARRAY_ELEM_LEFT '"'
  26. #define ARRAY_ELEM_RIGHT '"'
  27. #define ARRAY_ELEM_SEPARATOR ','
  28. /* maximum length of query string */
  29. #define MAX_QBUF_LENGTH 2048
  30. /**** the queries being used ********/
  31. #define Q_RETRIEVE_RECIPE_BYNAME 
  32.   "select * from Recipes where Recipes.elemName = '%s';"
  33. #define Q_RETRIEVE_ELEMENTS_IN_RECIPE 
  34.   "select e.* from Element e, Node n where n.belongsTo = '%s' and n.nodeElem = e.elemName;"
  35. #define Q_RETRIEVE_NODES_IN_RECIPE 
  36.   "select * from Node n where n.belongsTo = '%s'"
  37. #define Q_LOOKUP_EDGES_IN_RECIPE 
  38.   "select * from Edge e where e.belongsTo = '%s'"
  39. /* static functions only used here */
  40. static void fillTgElement(TgElement * elem, PortalBuffer *pbuf, int tupno);
  41. static void fillTgNode(TgRecipe * r, TgNode * node, PortalBuffer *pbuf, int tupno);
  42. static TgRecipe *fillTgRecipe(PortalBuffer *pbuf, int tupno);
  43. static void lookupEdges(TgRecipe * r, char *name);
  44. static void fillAllNodes(TgRecipe * r, char *name);
  45. static void fillAllElements(TgRecipe * r, char *name);
  46. static TgNode *connectTee(TgRecipe * r, TgNodePtr fromNode, TgNodePtr toNode,
  47.    int fromPort, int toPort);
  48. /*
  49.  * TextArray2ArrTgString --  take a string of the form:
  50.  * {"fooo", "bar", "xxxxx"} (for postgres)
  51.  * and parse it into a Array of TgString's
  52.  *
  53.  * always returns a valid Arr_TgString.  It could be a newly initialized one with
  54.  * zero elements
  55.  */
  56. Arr_TgString *
  57. TextArray2ArrTgString(char *str)
  58. {
  59. Arr_TgString *result;
  60. char    *beginQuote;
  61. char    *endQuote;
  62. int nextlen;
  63. char    *word;
  64. result = newArr_TgString();
  65. if ((str == NULL) || (str[0] == ''))
  66. return result;
  67. if (*str != ARRAY_LEFT_DELIM)
  68. {
  69. elog(NOTICE, "TextArray2ArrTgString: badly formed string, must have %c as 
  70. first charactern", ARRAY_LEFT_DELIM);
  71. return result;
  72. }
  73. str++; /* skip the first { */
  74. while (*str != '}')
  75. {
  76. if (*str == '')
  77. {
  78. elog(NOTICE, "TextArray2ArrTgString: text string ended prematurelyn");
  79. return result;
  80. }
  81. if ((beginQuote = index(str, ARRAY_ELEM_LEFT)) == NULL)
  82. {
  83. elog(NOTICE, "textArray2ArrTgString:  missing a begin quoten");
  84. return result;
  85. }
  86. if ((endQuote = index(beginQuote + 1, '"')) == NULL)
  87. {
  88. elog(NOTICE, "textArray2ArrTgString:  missing an end quoten");
  89. return result;
  90. }
  91. nextlen = endQuote - beginQuote; /* don't subtract one here
  92.  * because we need the
  93.  * extra character for 
  94.  * anyway */
  95. word = (char *) malloc(nextlen);
  96. StrNCpy(word, beginQuote + 1, nextlen);
  97. addArr_TgString(result, (TgString *) & word);
  98. free(word);
  99. str = endQuote + 1;
  100. }
  101. return result;
  102. }
  103. /* -------------------------------------
  104. findElemInRecipe()
  105.    given an element name, find that element in the TgRecipe structure and return it.
  106.    XXX Currently, this is done by linear search.  Change to using a hash table.
  107. -------------------------------------- */
  108. TgElement  *
  109. findElemInRecipe(TgRecipe * r, char *elemName)
  110. {
  111. int i;
  112. Arr_TgElementPtr *arr = r->elements;
  113. TgElement  *e;
  114. for (i = 0; i < arr->num; i++)
  115. {
  116. e = (TgElement *) arr->val[i];
  117. if (strcmp(e->elemName, elemName) == 0)
  118. return e;
  119. }
  120. elog(NOTICE, "Element named %s not found in recipe named %s", elemName, r->elmValue.elemName);
  121. return NULL;
  122. }
  123. /* -------------------------------------
  124. findNodeInRecipe()
  125.    given an node name, find that node in the TgRecipe structure and return it.
  126.    XXX Currently, this is done by linear search.  Change to using a hash table.
  127. -------------------------------------- */
  128. TgNode *
  129. findNodeInRecipe(TgRecipe * r, char *nodeName)
  130. {
  131. int i;
  132. Arr_TgNodePtr *arr = r->allNodes;
  133. TgNode    *n;
  134. for (i = 0; i < arr->num; i++)
  135. {
  136. n = (TgNode *) arr->val[i];
  137. if (strcmp(n->nodeName, nodeName) == 0)
  138. return n;
  139. }
  140. elog(NOTICE, "Node named %s not found in recipe named %s", nodeName, r->elmValue.elemName);
  141. return NULL;
  142. }
  143. /* -------------------------------------
  144. fillTgNode
  145. takes a query result in the PortalBuffer containing a Node
  146. and converts it to a C Node strcture.
  147. The Node structure passed in is 'filled' appropriately
  148. -------------------------------------- */
  149. void
  150. fillTgNode(TgRecipe * r, TgNode * node, PortalBuffer *pbuf, int tupno)
  151. {
  152. char    *nodeType;
  153. char    *nodeElem;
  154. char    *locString; /* ascii string rep of the point */
  155. static int attnums_initialized = 0;
  156. static int nodeName_attnum;
  157. static int nodeElem_attnum;
  158. static int nodeType_attnum;
  159. static int loc_attnum;
  160. TgNodePtr BlankNodePtr;
  161. int i;
  162. if (!attnums_initialized)
  163. {
  164. /*
  165.  * the first time fillTgNode is called, we find out all the
  166.  * relevant attribute numbers in a TgNode so subsequent calls are
  167.  * speeded up, the assumption is that the schema won't change
  168.  * between calls
  169.  */
  170. nodeName_attnum = PQfnumber(pbuf, tupno, "nodeName");
  171. nodeElem_attnum = PQfnumber(pbuf, tupno, "nodeElem");
  172. nodeType_attnum = PQfnumber(pbuf, tupno, "nodeType");
  173. loc_attnum = PQfnumber(pbuf, tupno, "loc");
  174. attnums_initialized = 1;
  175. }
  176. node->nodeName = PQgetAttr(pbuf, tupno, nodeName_attnum);
  177. locString = PQgetvalue(pbuf, tupno, loc_attnum);
  178. if (locString == NULL || locString[0] == '')
  179. {
  180. node->loc.x = 0;
  181. node->loc.y = 0; /* assign to zero for default */
  182. }
  183. else
  184. {
  185. float x,
  186. y;
  187. sscanf(locString, "(%f, %f)", &x, &y);
  188. node->loc.x = x;
  189. node->loc.y = y;
  190. }
  191. nodeElem = PQgetvalue(pbuf, tupno, nodeElem_attnum);
  192. node->nodeElem = findElemInRecipe(r, nodeElem);
  193. node->inNodes = newArr_TgNodePtr();
  194. node->outNodes = newArr_TgNodePtr();
  195. /*
  196.  * fill the inNodes array with as many NULL's are there are inPorts in
  197.  * the underlying element
  198.  */
  199. BlankNodePtr = (TgNodePtr) NULL;
  200. for (i = 0; i < node->nodeElem->inPorts->num; i++)
  201. addArr_TgNodePtr(node->inNodes, &BlankNodePtr);
  202. /*
  203.  * fill the outNodes array with as many NULL's are there are inPorts
  204.  * in the underlying element
  205.  */
  206. for (i = 0; i < node->nodeElem->outPorts->num; i++)
  207. addArr_TgNodePtr(node->outNodes, &BlankNodePtr);
  208. nodeType = PQgetvalue(pbuf, tupno, nodeType_attnum);
  209. if (strcmp(nodeType, "Ingred") == 0)
  210. node->nodeType = TG_INGRED_NODE;
  211. else if (strcmp(nodeType, "Eye") == 0)
  212. node->nodeType = TG_EYE_NODE;
  213. else if (strcmp(nodeType, "Recipe") == 0)
  214. node->nodeType = TG_RECIPE_NODE;
  215. else
  216. elog(NOTICE, "fillTgNode: unknown nodeType field value : %sn", nodeType);
  217. }
  218. /* -------------------------------------
  219. fillTgElement
  220. takes a query result in the PortalBuffer containing a Element
  221. and converts it to a C TgElement strcture.
  222. The TgElement structure passed in is 'filled' appropriately
  223.   ------------------------------------ */
  224. void
  225. fillTgElement(TgElement * elem, PortalBuffer *pbuf, int tupno)
  226. {
  227. char    *srcLang,
  228.    *elemType;
  229. static int attnums_initialized = 0;
  230. static int elemName_attnum;
  231. static int elemType_attnum;
  232. static int inPorts_attnum;
  233. static int inTypes_attnum;
  234. static int outPorts_attnum;
  235. static int outTypes_attnum;
  236. static int doc_attnum;
  237. static int keywords_attnum;
  238. static int icon_attnum;
  239. static int srcLang_attnum;
  240. static int src_attnum;
  241. static int owner_attnum;
  242. if (!attnums_initialized)
  243. {
  244. /*
  245.  * the first time fillTgElement is called, we find out all the
  246.  * relevant attribute numbers in a TgElement so subsequent calls
  247.  * are speeded up, the assumption is that the schema won't change
  248.  * between calls
  249.  */
  250. elemName_attnum = PQfnumber(pbuf, tupno, "elemName");
  251. elemType_attnum = PQfnumber(pbuf, tupno, "elemType");
  252. inPorts_attnum = PQfnumber(pbuf, tupno, "inPorts");
  253. inTypes_attnum = PQfnumber(pbuf, tupno, "inTypes");
  254. outPorts_attnum = PQfnumber(pbuf, tupno, "outPorts");
  255. outTypes_attnum = PQfnumber(pbuf, tupno, "outTypes");
  256. doc_attnum = PQfnumber(pbuf, tupno, "doc");
  257. keywords_attnum = PQfnumber(pbuf, tupno, "keywords");
  258. icon_attnum = PQfnumber(pbuf, tupno, "icon");
  259. srcLang_attnum = PQfnumber(pbuf, tupno, "srcLang");
  260. src_attnum = PQfnumber(pbuf, tupno, "src");
  261. attnums_initialized = 1;
  262. }
  263. elem->elemName = PQgetAttr(pbuf, tupno, elemName_attnum);
  264. elem->inPorts = TextArray2ArrTgString(PQgetvalue(pbuf, tupno, inPorts_attnum));
  265. elem->inTypes = TextArray2ArrTgString(PQgetvalue(pbuf, tupno, inTypes_attnum));
  266. elem->outPorts = TextArray2ArrTgString(PQgetvalue(pbuf, tupno, outPorts_attnum));
  267. elem->outTypes = TextArray2ArrTgString(PQgetvalue(pbuf, tupno, outTypes_attnum));
  268. elem->doc = PQgetAttr(pbuf, tupno, doc_attnum);
  269. elem->keywords = TextArray2ArrTgString(PQgetvalue(pbuf, tupno, keywords_attnum));
  270. elem->icon = PQgetAttr(pbuf, tupno, icon_attnum);
  271. elem->src = PQgetAttr(pbuf, tupno, src_attnum);
  272. elem->owner = PQgetAttr(pbuf, tupno, owner_attnum);
  273. /*
  274.  * we don't need to keep the value returned so use PQgetvalue()
  275.  * instead of PQgetAttr()
  276.  */
  277. srcLang = PQgetvalue(pbuf, tupno, srcLang_attnum);
  278. if (strcmp(srcLang, "SQL") == 0)
  279. elem->srcLang = TG_SQL;
  280. else if (strcmp(srcLang, "C") == 0)
  281. elem->srcLang = TG_C;
  282. else if (strcmp(srcLang, "RecipeGraph") == 0)
  283. elem->srcLang = TG_RECIPE_GRAPH;
  284. else if (strcmp(srcLang, "Compiled") == 0)
  285. elem->srcLang = TG_COMPILED;
  286. else
  287. elog(NOTICE, "fillTgElement(): unknown srcLang field value : %sn", srcLang);
  288. elemType = PQgetvalue(pbuf, tupno, elemType_attnum);
  289. if (strcmp(elemType, "Ingred") == 0)
  290. elem->elemType = TG_INGRED;
  291. else if (strcmp(elemType, "Eye") == 0)
  292. elem->elemType = TG_EYE;
  293. else if (strcmp(elemType, "Recipe") == 0)
  294. elem->elemType = TG_RECIPE;
  295. else
  296. elog(NOTICE, "fillTgElement(): unknown elemType field value : %sn", elemType);
  297. }
  298. /* -------------------------------------
  299. lookupEdges -
  300. look up the edges of a recipe and fill in the inNodes
  301. and outNodes of each node.
  302. In the process of connecting edges, we detect tee's and create
  303. teeNodes.  We add the teeNodes to the allNodes field of r as well
  304. ------------------------------------ */
  305. void
  306. lookupEdges(TgRecipe * r, char *name)
  307. {
  308. char qbuf[MAX_QBUF_LENGTH];
  309. int i;
  310. char    *pqres;
  311. char    *pbufname;
  312. PortalBuffer *pbuf;
  313. int ntups;
  314. int fromNode_attnum;
  315. int fromPort_attnum;
  316. int toPort_attnum;
  317. int toNode_attnum;
  318. char    *toNode,
  319.    *fromNode;
  320. char    *toPortStr,
  321.    *fromPortStr;
  322. int toPort,
  323. fromPort;
  324. TgNodePtr fromNodePtr,
  325. toNodePtr;
  326. sprintf(qbuf, Q_LOOKUP_EDGES_IN_RECIPE, name);
  327. pqres = PQexec(qbuf);
  328. pqres = PQexec(qbuf);
  329. if (*pqres == 'R' || *pqres == 'E')
  330. {
  331. elog(NOTICE, "lookupEdges(): Error while executing query : %sn", qbuf);
  332. elog(NOTICE, "result = %s, error is %sn", pqres, PQerrormsg);
  333. return;
  334. }
  335. pbufname = ++pqres;
  336. pbuf = PQparray(pbufname);
  337. ntups = PQntuplesGroup(pbuf, 0);
  338. if (ntups == 0)
  339. return;
  340. fromNode_attnum = PQfnumber(pbuf, 0, "fromNode");
  341. fromPort_attnum = PQfnumber(pbuf, 0, "fromPort");
  342. toNode_attnum = PQfnumber(pbuf, 0, "toNode");
  343. toPort_attnum = PQfnumber(pbuf, 0, "toPort");
  344. for (i = 0; i < ntups; i++)
  345. {
  346. fromNode = PQgetvalue(pbuf, i, fromNode_attnum);
  347. toNode = PQgetvalue(pbuf, i, toNode_attnum);
  348. fromPortStr = PQgetvalue(pbuf, i, fromPort_attnum);
  349. toPortStr = PQgetvalue(pbuf, i, toPort_attnum);
  350. if (!fromPortStr || fromPortStr[0] == '')
  351. {
  352. elog(NOTICE, "lookupEdges():  SANITY CHECK failed.  Edge with invalid fromPort value!");
  353. return;
  354. }
  355. if (!toPortStr || toPortStr[0] == '')
  356. {
  357. elog(NOTICE, "lookupEdges():  SANITY CHECK failed.  Edge with invalid toPort value!!");
  358. return;
  359. }
  360. fromPort = atoi(fromPortStr);
  361. toPort = atoi(toPortStr);
  362. fromNodePtr = findNodeInRecipe(r, fromNode);
  363. if (!fromNodePtr)
  364. {
  365. elog(NOTICE, "lookupEdges():  SANITY CHECK failed.  Edge with bad fromNode value!");
  366. return;
  367. }
  368. toNodePtr = findNodeInRecipe(r, toNode);
  369. if (!toNodePtr)
  370. {
  371. elog(NOTICE, "lookupEdges():  SANITY CHECK failed.  Edge with bad toNode value!");
  372. return;
  373. }
  374. /*
  375.  * check to see if the from port is already connected. if it is,
  376.  * then this means we should construct a Tee node
  377.  */
  378. if (fromNodePtr->outNodes->val[fromPort - 1] != NULL)
  379. {
  380. TgNodePtr tn;
  381. tn = connectTee(r, fromNodePtr, toNodePtr, fromPort, toPort);
  382. addArr_TgNodePtr(r->allNodes, &tn);
  383. }
  384. else
  385. {
  386. fromNodePtr->outNodes->val[fromPort - 1] = toNodePtr;
  387. toNodePtr->inNodes->val[toPort - 1] = fromNodePtr;
  388. }
  389. }
  390. PQclear(pbufname);
  391. }
  392. /*
  393.    handle tee connections here
  394.    Everytime an output port is connected multiply,
  395.    we explicitly insert TgTeeNode
  396.    returns the teeNode created
  397. */
  398. static TgNode *
  399. connectTee(TgRecipe * r, TgNodePtr fromNode, TgNodePtr toNode,
  400.    int fromPort, int toPort)
  401. {
  402. TgNodePtr origToNode;
  403. TgNodePtr tn;
  404. TgNodePtr BlankNodePtr;
  405. int origToPort;
  406. int i;
  407. /* the toNode formerly pointed to */
  408. origToNode = fromNode->outNodes->val[fromPort - 1];
  409. if (origToNode == NULL)
  410. {
  411. elog(NOTICE, "Internal Error: connectTee() called with a null origToNode");
  412. return;
  413. }
  414. for (i = 0; i < origToNode->inNodes->num; i++)
  415. {
  416. if (origToNode->inNodes->val[i] == fromNode)
  417. break;
  418. }
  419. /* the inport of the former toNode */
  420. /* ports start with 1, array indices start from 0 */
  421. origToPort = i + 1;
  422. /* add a tee node now. */
  423. tn = malloc(sizeof(TgNode));
  424. /* generate a name for the tee node table */
  425. tn->nodeName = malloc(50);
  426. sprintf(tn->nodeName, "tee_%u", newoid());
  427. /*   tn->nodeName = NULL; */
  428. tn->nodeType = TG_TEE_NODE;
  429. tn->nodeElem = NULL;
  430. tn->inNodes = newArr_TgNodePtr();
  431. tn->outNodes = newArr_TgNodePtr();
  432. BlankNodePtr = (TgNodePtr) NULL;
  433. /* each TgTeeNode has one input and two outputs, NULL them initiallly */
  434. addArr_TgNodePtr(tn->inNodes, &BlankNodePtr);
  435. addArr_TgNodePtr(tn->outNodes, &BlankNodePtr);
  436. addArr_TgNodePtr(tn->outNodes, &BlankNodePtr);
  437. /*
  438.  * make the old toNode the left parent of the tee node add the new
  439.  * toNode as the right parent of the tee node
  440.  */
  441. tn->outNodes->val[0] = origToNode;
  442. origToNode->inNodes->val[origToPort - 1] = tn;
  443. tn->outNodes->val[1] = toNode;
  444. toNode->inNodes->val[toPort - 1] = tn;
  445. /* connect the fromNode to the new tee node */
  446. fromNode->outNodes->val[fromPort - 1] = tn;
  447. tn->inNodes->val[0] = fromNode;
  448. return tn;
  449. }
  450. /* -------------------------------------
  451. fillAllNodes
  452. fill out the nodes of a recipe
  453.   ------------------------------------ */
  454. void
  455. fillAllNodes(TgRecipe * r, char *name)
  456. {
  457. char qbuf[MAX_QBUF_LENGTH];
  458. int i;
  459. char    *pqres;
  460. char    *pbufname;
  461. PortalBuffer *pbuf;
  462. int ntups;
  463. TgElement  *elem;
  464. TgNode    *node;
  465. /* 1) fill out the elements that are in the recipe */
  466. sprintf(qbuf, Q_RETRIEVE_ELEMENTS_IN_RECIPE, name);
  467. pqres = PQexec(qbuf);
  468. if (*pqres == 'R' || *pqres == 'E')
  469. {
  470. elog(NOTICE, "fillAllNodes(): Error while executing query : %sn", qbuf);
  471. elog(NOTICE, "result = %s, error is %sn", pqres, PQerrormsg);
  472. return;
  473. }
  474. pbufname = ++pqres;
  475. pbuf = PQparray(pbufname);
  476. ntups = PQntuplesGroup(pbuf, 0);
  477. for (i = 0; i < ntups; i++)
  478. {
  479. elem = malloc(sizeof(TgElement));
  480. fillTgElement(elem, pbuf, i);
  481. addArr_TgElementPtr(r->elements, &elem);
  482. }
  483. PQclear(pbufname);
  484. sprintf(qbuf, Q_RETRIEVE_NODES_IN_RECIPE, name);
  485. pqres = PQexec(qbuf);
  486. if (*pqres == 'R' || *pqres == 'E')
  487. {
  488. elog(NOTICE, "fillAllNodes(): Error while executing query : %sn", qbuf);
  489. elog(NOTICE, "result = %s, error is %sn", pqres, PQerrormsg);
  490. return;
  491. }
  492. pbufname = ++pqres;
  493. pbuf = PQparray(pbufname);
  494. ntups = PQntuplesGroup(pbuf, 0);
  495. for (i = 0; i < ntups; i++)
  496. {
  497. node = malloc(sizeof(TgNode));
  498. fillTgNode(r, node, pbuf, i);
  499. addArr_TgNodePtr(r->allNodes, &node);
  500. }
  501. PQclear(pbufname);
  502. }
  503. /* -------------------------------------
  504. fillAllElements
  505. fill out the elements of a recipe
  506.   ------------------------------------ */
  507. void
  508. fillAllElements(TgRecipe * r, char *name)
  509. {
  510. char qbuf[MAX_QBUF_LENGTH];
  511. int i;
  512. char    *pqres;
  513. char    *pbufname;
  514. PortalBuffer *pbuf;
  515. int ntups;
  516. TgElement  *elem;
  517. sprintf(qbuf, Q_RETRIEVE_ELEMENTS_IN_RECIPE, name);
  518. pqres = PQexec(qbuf);
  519. if (*pqres == 'R' || *pqres == 'E')
  520. {
  521. elog(NOTICE, "fillAllElements(): Error while executing query : %sn", qbuf);
  522. elog(NOTICE, "result = %s, error is %sn", pqres, PQerrormsg);
  523. return;
  524. }
  525. pbufname = ++pqres;
  526. pbuf = PQparray(pbufname);
  527. ntups = PQntuplesGroup(pbuf, 0);
  528. for (i = 0; i < ntups; i++)
  529. {
  530. elem = malloc(sizeof(TgElement));
  531. fillTgElement(elem, pbuf, i);
  532. addArr_TgElementPtr(r->elements, &elem);
  533. }
  534. PQclear(pbufname);
  535. }
  536. /* -------------------------------------
  537. fillTgRecipe
  538. takes a query result in the PortalBuffer containing a Recipe
  539. and converts it to a C TgRecipe strcture
  540.   ------------------------------------ */
  541. TgRecipe   *
  542. fillTgRecipe(PortalBuffer *pbuf, int tupno)
  543. {
  544. TgRecipe   *r;
  545. int i,
  546. j;
  547. /* 1) set up the recipe structure */
  548. r = (TgRecipe *) malloc(sizeof(TgRecipe));
  549. fillTgElement(&r->elmValue, pbuf, 0);
  550. r->elmValue.elemType = TG_RECIPE;
  551. r->allNodes = newArr_TgNodePtr();
  552. r->rootNodes = newArr_TgNodePtr();
  553. r->eyes = newArr_TgNodePtr();
  554. r->tees = newArr_TgNodePtr();
  555. r->elements = newArr_TgElementPtr();
  556. /*
  557.  * 2) find all the elements. There may be less elements than nodes
  558.  * because you can have multiple instantiations of an element in a
  559.  * recipe
  560.  */
  561. fillAllElements(r, r->elmValue.elemName);
  562. /* 3) find all the nodes in the recipe */
  563. fillAllNodes(r, r->elmValue.elemName);
  564. /*
  565.  * 4) find all the edges, and connect the nodes, may also add tee
  566.  * nodes to the allNodes field
  567.  */
  568. lookupEdges(r, r->elmValue.elemName);
  569. /* 5) find all the rootNodes in the recipe */
  570. /*
  571.  * root nodes are nodes with no incoming nodes or whose incoming nodes
  572.  * are all null
  573.  */
  574. /* 6) find all the eyes in the recipe */
  575. /* eye nodes are nodes with the node type TG_EYE_NODE */
  576. /* 7) find all the tee nodes in the recipe */
  577. /* tee nodes are nodes with the node type TG_TEE_NODE */
  578. for (i = 0; i < r->allNodes->num; i++)
  579. {
  580. TgNode    *nptr = r->allNodes->val[i];
  581. if (nptr->nodeType == TG_EYE_NODE)
  582. addArr_TgNodePtr(r->eyes, &nptr);
  583. else if (nptr->nodeType == TG_TEE_NODE)
  584. addArr_TgNodePtr(r->tees, &nptr);
  585. if (nptr->inNodes->num == 0)
  586. addArr_TgNodePtr(r->rootNodes, &nptr);
  587. else
  588. {
  589. for (j = 0;
  590.    j < nptr->inNodes->num && (nptr->inNodes->val[j] == NULL);
  591.  j++);
  592. if (j == nptr->inNodes->num)
  593. addArr_TgNodePtr(r->rootNodes, &nptr);
  594. }
  595. }
  596. return r;
  597. }
  598. /* -------------------------------------
  599. retrieveRecipe
  600.    find the recipe with the given name
  601.   ------------------------------------ */
  602. TgRecipe   *
  603. retrieveRecipe(char *name)
  604. {
  605. char qbuf[MAX_QBUF_LENGTH];
  606. TgRecipe   *recipe;
  607. char    *pqres;
  608. char    *pbufname;
  609. PortalBuffer *pbuf;
  610. int ntups;
  611. sprintf(qbuf, Q_RETRIEVE_RECIPE_BYNAME, name);
  612. pqres = PQexec(qbuf);
  613. if (*pqres == 'R' || *pqres == 'E')
  614. {
  615. elog(NOTICE, "retrieveRecipe: Error while executing query : %sn", qbuf);
  616. elog(NOTICE, "result = %s, error is %sn", pqres, PQerrormsg);
  617. return NULL;
  618. }
  619. pbufname = ++pqres;
  620. pbuf = PQparray(pbufname);
  621. ntups = PQntuplesGroup(pbuf, 0);
  622. if (ntups == 0)
  623. {
  624. elog(NOTICE, "retrieveRecipe():  No recipe named %s existsn", name);
  625. return NULL;
  626. }
  627. if (ntups != 1)
  628. {
  629. elog(NOTICE, "retrieveRecipe():  Multiple (%d) recipes named %s existsn", ntups, name);
  630. return NULL;
  631. }
  632. recipe = fillTgRecipe(pbuf, 0);
  633. PQclear(pbufname);
  634. return recipe;
  635. }
  636. /* -------------------- copyXXX functions ----------------------- */
  637. void
  638. copyTgElementPtr(TgElementPtr * from, TgElementPtr * to)
  639. {
  640. *to = *from;
  641. }
  642. void
  643. copyTgNodePtr(TgNodePtr * from, TgNodePtr * to)
  644. {
  645. *to = *from;
  646. }
  647. void
  648. copyTgRecipePtr(TgRecipePtr * from, TgRecipePtr * to)
  649. {
  650. *to = *from;
  651. }
  652. void
  653. copyTgString(TgString * from, TgString * to)
  654. {
  655. TgString fromTgString = *from;
  656. TgString toTgString;
  657. toTgString = (TgString) malloc(strlen(fromTgString) + 1);
  658. strcpy(toTgString, fromTgString);
  659. *to = toTgString;
  660. }