📄 tgrecipe.c
字号:
/*------------------------------------------------------------------------- * * tgRecipe.c * Tioga recipe-related definitions * these functions can be used in both the frontend and the * backend * * this file must be kept current with recipe-schema.sql * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION * $Header: /usr/local/cvsroot/pgsql/src/backend/tioga/tgRecipe.c,v 1.12 1999/05/10 00:45:49 momjian Exp $ * *------------------------------------------------------------------------- */#include <stdlib.h>#include "postgres.h"#include "tioga/tgRecipe.h"#include "catalog/catalog.h" /* for newoid() */static Arr_TgString *TextArray2ArrTgString(char *str);#define ARRAY_LEFT_DELIM '{'#define ARRAY_RIGHT_DELIM '}'#define ARRAY_ELEM_LEFT '"'#define ARRAY_ELEM_RIGHT '"'#define ARRAY_ELEM_SEPARATOR ','/* maximum length of query string */#define MAX_QBUF_LENGTH 2048/**** the queries being used ********/#define Q_RETRIEVE_RECIPE_BYNAME \ "select * from Recipes where Recipes.elemName = '%s';"#define Q_RETRIEVE_ELEMENTS_IN_RECIPE \ "select e.* from Element e, Node n where n.belongsTo = '%s' and n.nodeElem = e.elemName;"#define Q_RETRIEVE_NODES_IN_RECIPE \ "select * from Node n where n.belongsTo = '%s'"#define Q_LOOKUP_EDGES_IN_RECIPE \ "select * from Edge e where e.belongsTo = '%s'"/* static functions only used here */static void fillTgElement(TgElement * elem, PortalBuffer *pbuf, int tupno);static void fillTgNode(TgRecipe * r, TgNode * node, PortalBuffer *pbuf, int tupno);static TgRecipe *fillTgRecipe(PortalBuffer *pbuf, int tupno);static void lookupEdges(TgRecipe * r, char *name);static void fillAllNodes(TgRecipe * r, char *name);static void fillAllElements(TgRecipe * r, char *name);static TgNode *connectTee(TgRecipe * r, TgNodePtr fromNode, TgNodePtr toNode, int fromPort, int toPort);/* * TextArray2ArrTgString -- take a string of the form: * {"fooo", "bar", "xxxxx"} (for postgres) * and parse it into a Array of TgString's * * always returns a valid Arr_TgString. It could be a newly initialized one with * zero elements */Arr_TgString *TextArray2ArrTgString(char *str){ Arr_TgString *result; char *beginQuote; char *endQuote; int nextlen; char *word; result = newArr_TgString(); if ((str == NULL) || (str[0] == '\0')) return result; if (*str != ARRAY_LEFT_DELIM) { elog(NOTICE, "TextArray2ArrTgString: badly formed string, must have %c as \first character\n", ARRAY_LEFT_DELIM); return result; } str++; /* skip the first { */ while (*str != '}') { if (*str == '\0') { elog(NOTICE, "TextArray2ArrTgString: text string ended prematurely\n"); return result; } if ((beginQuote = index(str, ARRAY_ELEM_LEFT)) == NULL) { elog(NOTICE, "textArray2ArrTgString: missing a begin quote\n"); return result; } if ((endQuote = index(beginQuote + 1, '"')) == NULL) { elog(NOTICE, "textArray2ArrTgString: missing an end quote\n"); return result; } nextlen = endQuote - beginQuote; /* don't subtract one here * because we need the * extra character for \0 * anyway */ word = (char *) malloc(nextlen); StrNCpy(word, beginQuote + 1, nextlen); addArr_TgString(result, (TgString *) & word); free(word); str = endQuote + 1; } return result;}/* -------------------------------------findElemInRecipe() given an element name, find that element in the TgRecipe structure and return it. XXX Currently, this is done by linear search. Change to using a hash table.-------------------------------------- */TgElement *findElemInRecipe(TgRecipe * r, char *elemName){ int i; Arr_TgElementPtr *arr = r->elements; TgElement *e; for (i = 0; i < arr->num; i++) { e = (TgElement *) arr->val[i]; if (strcmp(e->elemName, elemName) == 0) return e; } elog(NOTICE, "Element named %s not found in recipe named %s", elemName, r->elmValue.elemName); return NULL;}/* -------------------------------------findNodeInRecipe() given an node name, find that node in the TgRecipe structure and return it. XXX Currently, this is done by linear search. Change to using a hash table.-------------------------------------- */TgNode *findNodeInRecipe(TgRecipe * r, char *nodeName){ int i; Arr_TgNodePtr *arr = r->allNodes; TgNode *n; for (i = 0; i < arr->num; i++) { n = (TgNode *) arr->val[i]; if (strcmp(n->nodeName, nodeName) == 0) return n; } elog(NOTICE, "Node named %s not found in recipe named %s", nodeName, r->elmValue.elemName); return NULL;}/* -------------------------------------fillTgNode takes a query result in the PortalBuffer containing a Node and converts it to a C Node strcture. The Node structure passed in is 'filled' appropriately-------------------------------------- */voidfillTgNode(TgRecipe * r, TgNode * node, PortalBuffer *pbuf, int tupno){ char *nodeType; char *nodeElem; char *locString; /* ascii string rep of the point */ static int attnums_initialized = 0; static int nodeName_attnum; static int nodeElem_attnum; static int nodeType_attnum; static int loc_attnum; TgNodePtr BlankNodePtr; int i; if (!attnums_initialized) { /* * the first time fillTgNode is called, we find out all the * relevant attribute numbers in a TgNode so subsequent calls are * speeded up, the assumption is that the schema won't change * between calls */ nodeName_attnum = PQfnumber(pbuf, tupno, "nodeName"); nodeElem_attnum = PQfnumber(pbuf, tupno, "nodeElem"); nodeType_attnum = PQfnumber(pbuf, tupno, "nodeType"); loc_attnum = PQfnumber(pbuf, tupno, "loc"); attnums_initialized = 1; } node->nodeName = PQgetAttr(pbuf, tupno, nodeName_attnum); locString = PQgetvalue(pbuf, tupno, loc_attnum); if (locString == NULL || locString[0] == '\0') { node->loc.x = 0; node->loc.y = 0; /* assign to zero for default */ } else { float x, y; sscanf(locString, "(%f, %f)", &x, &y); node->loc.x = x; node->loc.y = y; } nodeElem = PQgetvalue(pbuf, tupno, nodeElem_attnum); node->nodeElem = findElemInRecipe(r, nodeElem); node->inNodes = newArr_TgNodePtr(); node->outNodes = newArr_TgNodePtr(); /* * fill the inNodes array with as many NULL's are there are inPorts in * the underlying element */ BlankNodePtr = (TgNodePtr) NULL; for (i = 0; i < node->nodeElem->inPorts->num; i++) addArr_TgNodePtr(node->inNodes, &BlankNodePtr); /* * fill the outNodes array with as many NULL's are there are inPorts * in the underlying element */ for (i = 0; i < node->nodeElem->outPorts->num; i++) addArr_TgNodePtr(node->outNodes, &BlankNodePtr); nodeType = PQgetvalue(pbuf, tupno, nodeType_attnum); if (strcmp(nodeType, "Ingred") == 0) node->nodeType = TG_INGRED_NODE; else if (strcmp(nodeType, "Eye") == 0) node->nodeType = TG_EYE_NODE; else if (strcmp(nodeType, "Recipe") == 0) node->nodeType = TG_RECIPE_NODE; else elog(NOTICE, "fillTgNode: unknown nodeType field value : %s\n", nodeType);}/* -------------------------------------fillTgElement takes a query result in the PortalBuffer containing a Element and converts it to a C TgElement strcture. The TgElement structure passed in is 'filled' appropriately ------------------------------------ */voidfillTgElement(TgElement * elem, PortalBuffer *pbuf, int tupno){ char *srcLang, *elemType; static int attnums_initialized = 0; static int elemName_attnum; static int elemType_attnum; static int inPorts_attnum; static int inTypes_attnum; static int outPorts_attnum; static int outTypes_attnum; static int doc_attnum; static int keywords_attnum; static int icon_attnum; static int srcLang_attnum; static int src_attnum; static int owner_attnum; if (!attnums_initialized) { /* * the first time fillTgElement is called, we find out all the * relevant attribute numbers in a TgElement so subsequent calls * are speeded up, the assumption is that the schema won't change * between calls */ elemName_attnum = PQfnumber(pbuf, tupno, "elemName"); elemType_attnum = PQfnumber(pbuf, tupno, "elemType"); inPorts_attnum = PQfnumber(pbuf, tupno, "inPorts"); inTypes_attnum = PQfnumber(pbuf, tupno, "inTypes"); outPorts_attnum = PQfnumber(pbuf, tupno, "outPorts"); outTypes_attnum = PQfnumber(pbuf, tupno, "outTypes"); doc_attnum = PQfnumber(pbuf, tupno, "doc"); keywords_attnum = PQfnumber(pbuf, tupno, "keywords"); icon_attnum = PQfnumber(pbuf, tupno, "icon"); srcLang_attnum = PQfnumber(pbuf, tupno, "srcLang"); src_attnum = PQfnumber(pbuf, tupno, "src"); attnums_initialized = 1; } elem->elemName = PQgetAttr(pbuf, tupno, elemName_attnum); elem->inPorts = TextArray2ArrTgString(PQgetvalue(pbuf, tupno, inPorts_attnum)); elem->inTypes = TextArray2ArrTgString(PQgetvalue(pbuf, tupno, inTypes_attnum)); elem->outPorts = TextArray2ArrTgString(PQgetvalue(pbuf, tupno, outPorts_attnum)); elem->outTypes = TextArray2ArrTgString(PQgetvalue(pbuf, tupno, outTypes_attnum)); elem->doc = PQgetAttr(pbuf, tupno, doc_attnum); elem->keywords = TextArray2ArrTgString(PQgetvalue(pbuf, tupno, keywords_attnum)); elem->icon = PQgetAttr(pbuf, tupno, icon_attnum); elem->src = PQgetAttr(pbuf, tupno, src_attnum); elem->owner = PQgetAttr(pbuf, tupno, owner_attnum); /* * we don't need to keep the value returned so use PQgetvalue() * instead of PQgetAttr() */ srcLang = PQgetvalue(pbuf, tupno, srcLang_attnum); if (strcmp(srcLang, "SQL") == 0) elem->srcLang = TG_SQL; else if (strcmp(srcLang, "C") == 0) elem->srcLang = TG_C; else if (strcmp(srcLang, "RecipeGraph") == 0) elem->srcLang = TG_RECIPE_GRAPH; else if (strcmp(srcLang, "Compiled") == 0) elem->srcLang = TG_COMPILED; else elog(NOTICE, "fillTgElement(): unknown srcLang field value : %s\n", srcLang); elemType = PQgetvalue(pbuf, tupno, elemType_attnum); if (strcmp(elemType, "Ingred") == 0) elem->elemType = TG_INGRED; else if (strcmp(elemType, "Eye") == 0) elem->elemType = TG_EYE; else if (strcmp(elemType, "Recipe") == 0) elem->elemType = TG_RECIPE; else elog(NOTICE, "fillTgElement(): unknown elemType field value : %s\n", elemType);}/* -------------------------------------lookupEdges - look up the edges of a recipe and fill in the inNodes and outNodes of each node. In the process of connecting edges, we detect tee's and create teeNodes. We add the teeNodes to the allNodes field of r as well------------------------------------ */voidlookupEdges(TgRecipe * r, char *name){ char qbuf[MAX_QBUF_LENGTH]; int i; char *pqres; char *pbufname; PortalBuffer *pbuf; int ntups; int fromNode_attnum; int fromPort_attnum; int toPort_attnum; int toNode_attnum; char *toNode, *fromNode; char *toPortStr, *fromPortStr; int toPort, fromPort; TgNodePtr fromNodePtr, toNodePtr; sprintf(qbuf, Q_LOOKUP_EDGES_IN_RECIPE, name); pqres = PQexec(qbuf); pqres = PQexec(qbuf); if (*pqres == 'R' || *pqres == 'E') { elog(NOTICE, "lookupEdges(): Error while executing query : %s\n", qbuf); elog(NOTICE, "result = %s, error is %s\n", pqres, PQerrormsg); return; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -