static Node * parseInternalPostgres (void) //TODO make copyObject work first { Node *result; START_TIMER("module - parser"); NEW_AND_ACQUIRE_MEMCONTEXT("PARSER_CONTEXT"); // parse int rc = postgresparse(); if (rc) { ERROR_LOG("parse error!"); return NULL; } STOP_TIMER("module - parser"); DEBUG_LOG("query block model generated by parser is:\n%s\n\n%s", nodeToString(postgresParseResult), beatify(nodeToString(postgresParseResult))); // create copy of parse result in parent context FREE_MEM_CONTEXT_AND_RETURN_COPY(Node,postgresParseResult); }
int main (int argc, char* argv[]) { Node *result; Node *qoModel; char *sql; READ_OPTIONS_AND_INIT("testtranslate", "Run all stages on input except provenance rewrite and output rewritten SQL code."); // read from terminal if (getStringOption("input.sql") == NULL) { result = parseStream(stdin); DEBUG_LOG("Address of returned node is <%p>", result); ERROR_LOG("PARSE RESULT FROM STREAM IS <%s>", beatify(nodeToString(result))); } // parse input string else { result = parseFromString(getStringOption("input.sql")); DEBUG_LOG("Address of returned node is <%p>", result); ERROR_LOG("PARSE RESULT FROM STRING IS:\n%s", beatify(nodeToString(result))); } qoModel = translateParse(result); INFO_LOG("TRANSLATION RESULT FROM STRING IS:\n%s", beatify(nodeToString(qoModel))); ERROR_LOG("SIMPLIFIED OPERATOR TREE:\n%s", operatorToOverviewString(qoModel)); sql = serializeOperatorModel(qoModel); ERROR_LOG("SERIALIZED SQL:\n%s", sql); return shutdownApplication(); }
int main (int argc, char* argv[]) { Node *result; READ_OPTIONS_AND_INIT("testvisit", "Run visit function on input for testing."); // read from terminal if (getStringOption("input.sql") == NULL) { result = parseStream(stdin); DEBUG_LOG("Address of returned node is <%p>", result); ERROR_LOG("PARSE RESULT FROM STREAM IS <%s>", beatify(nodeToString(result))); } // parse input string else { result = parseFromString(getStringOption("input.sql")); DEBUG_LOG("Address of returned node is <%p>", result); ERROR_LOG("PARSE RESULT FROM STRING IS:\n%s", nodeToString(result)); ERROR_LOG("PARSE RESULT FROM STRING IS:\n%s", beatify(nodeToString(result))); } void *state = NULL; visitTheNode(result, state); return shutdownApplication(); }
/* * serializeNode - * This is used on the query dispatcher to serialize Plan and Query Trees for * dispatching to qExecs. * The returned string is palloc'ed in the current memory context. */ char * serializeNode(Node *node, int *size, int *uncompressed_size_out) { char *pszNode; char *sNode; int uncompressed_size; Assert(node != NULL); Assert(size != NULL); START_MEMORY_ACCOUNT(MemoryAccounting_CreateAccount(0, MEMORY_OWNER_TYPE_Serializer)); { pszNode = nodeToBinaryStringFast(node, &uncompressed_size); Assert(pszNode != NULL); if (NULL != uncompressed_size_out) { *uncompressed_size_out = uncompressed_size; } sNode = compress_string(pszNode, uncompressed_size, size); pfree(pszNode); if (DEBUG5 >= log_min_messages) { Node * newnode = NULL; PG_TRY(); { newnode = deserializeNode(sNode, *size); } PG_CATCH(); { elog_node_display(DEBUG5, "Before serialization", node, true); PG_RE_THROW(); } PG_END_TRY(); /* Some plans guarantee these differences (see serialization * of plan nodes -- they avoid sending QD-only info out) */ if (strcmp(nodeToString(node), nodeToString(newnode)) != 0) { elog_node_display(DEBUG5, "Before serialization", node, true); elog_node_display(DEBUG5, "After deserialization", newnode, true); } } } END_MEMORY_ACCOUNT(); return sNode; }
List * postgresGetAttributes (char *tableName) { PGresult *res = NULL; List *attrs = NIL; ASSERT(postgresCatalogTableExists(tableName)); if (MAP_HAS_STRING_KEY(plugin->plugin.cache->tableAttrDefs, tableName)) return (List *) MAP_GET_STRING(plugin->plugin.cache->tableAttrDefs,tableName); // do query ACQUIRE_MEM_CONTEXT(memContext); res = execPrepared(NAME_TABLE_GET_ATTRS, singleton(createConstString(tableName))); // loop through results for(int i = 0; i < PQntuples(res); i++) { AttributeDef *a = createAttributeDef( strdup(PQgetvalue(res,i,0)), postgresOidToDT(strdup(PQgetvalue(res,i,1))) ); attrs = appendToTailOfList(attrs, a); } // clear result PQclear(res); MAP_ADD_STRING_KEY(plugin->plugin.cache->tableAttrDefs, tableName, attrs); DEBUG_LOG("table %s attributes are <%s>", tableName, beatify(nodeToString(attrs))); RELEASE_MEM_CONTEXT(); return attrs; }
bool do_parse(const char* query) { MemoryContext ctx = NULL; List *tree; ctx = AllocSetContextCreate(TopMemoryContext, "RootContext", ALLOCSET_DEFAULT_MINSIZE, ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE); MemoryContextSwitchTo(ctx); tree = raw_parser(query); if (tree != NULL) { char *s; s = nodeToString(tree); printf("%s\n", s); pfree(s); } MemoryContextSwitchTo(TopMemoryContext); MemoryContextDelete(ctx); return (tree != NULL); }
/* -------------------------------- * Execute query cache look up * -------------------------------- */ POOL_STATUS pool_execute_query_cache_lookup(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *backend, Node *node) { SelectStmt *select = (SelectStmt *)node; POOL_STATUS status = POOL_END; /* cache not found */ if (! (select->intoClause || select->lockingClause)) { parsed_query = strdup(nodeToString(node)); if (parsed_query == NULL) { pool_error("pool_execute_query_cache_lookup: malloc failed"); return POOL_ERROR; } status = pool_query_cache_lookup(frontend, parsed_query, backend->info->database, TSTATE(backend, MASTER_NODE_ID)); if (status == POOL_CONTINUE) { free(parsed_query); parsed_query = NULL; free_parser(); } } return status; }
int main(int argc, char **argv) { List *tree; ListCell *l; if (argc != 2) { fprintf(stderr, "./parser-test query\n"); exit(1); } tree = raw_parser(argv[1]); if (tree == NULL) { printf("syntax error: %s\n", argv[1]); } else { foreach(l, tree) { Node *node = (Node *) lfirst(l); printf("%s\n", nodeToString(node)); } }
static QueryOperator * translateInsert(Insert *insert) { List *attr = getAttributeNames(insert->tableName); List *dts = getAttributeDataTypes(insert->tableName); QueryOperator *insertQuery; TableAccessOperator *to; to = createTableAccessOp(insert->tableName, NULL, NULL, NIL, deepCopyStringList(attr), dts); SET_BOOL_STRING_PROP(to,PROP_TABLE_IS_UPDATED); if (isA(insert->query, List)) { ConstRelOperator *co; co = createConstRelOp((List *) insert->query,NIL, deepCopyStringList(attr), dts); insertQuery= (QueryOperator *) co; } else insertQuery = translateQuery((Node *) insert->query); SetOperator *seto; seto = createSetOperator(SETOP_UNION, NIL, NIL, deepCopyStringList(attr)); addChildOperator((QueryOperator *) seto, (QueryOperator *) to); addChildOperator((QueryOperator *) seto, insertQuery); INFO_LOG("translated insert:\n%s", operatorToOverviewString((Node *) seto)); DEBUG_LOG("translated insert:\n%s", nodeToString((Node *) seto)); return (QueryOperator *) seto; }
PixmapSource SkinContext::getPixmapSource(const QDomNode& pixmapNode) const { PixmapSource source; const SvgParser svgParser(*this); if (!pixmapNode.isNull()) { QDomNode svgNode = selectNode(pixmapNode, "svg"); if (!svgNode.isNull()) { // inline svg const QByteArray rslt = svgParser.saveToQByteArray( svgParser.parseSvgTree(svgNode, m_xmlPath)); source.setSVG(rslt); } else { // filename QString pixmapName = nodeToString(pixmapNode); if (!pixmapName.isEmpty()) { source.setPath(getSkinPath(pixmapName)); if (source.isSVG()) { const QByteArray rslt = svgParser.saveToQByteArray( svgParser.parseSvgFile(source.getPath())); source.setSVG(rslt); } } } } return source; }
/* * debug_equality_expression returns the textual representation of an equality * expression generated by a call to MakeOpExpression. */ Datum debug_equality_expression(PG_FUNCTION_ARGS) { Oid distributedTableId = PG_GETARG_OID(0); Var *partitionColumn = PartitionColumn(distributedTableId); OpExpr *equalityExpression = MakeOpExpression(partitionColumn, BTEqualStrategyNumber); PG_RETURN_CSTRING(nodeToString(equalityExpression)); }
bool SkinContext::hasNodeSelectString(const QDomNode& node, const QString& nodeName, QString *value) const { QDomNode child = selectNode(node, nodeName); if (!child.isNull()) { *value = nodeToString(child); return true; } return false; }
std::string Context::demangleTypeAsString(llvm::StringRef MangledName, const DemangleOptions &Options) { NodePointer root = demangleTypeAsNode(MangledName); if (!root) return MangledName.str(); std::string demangling = nodeToString(root, Options); if (demangling.empty()) return MangledName.str(); return demangling; }
bool SkinContext::hasNodeSelectBool(const QDomNode& node, const QString& nodeName, bool *value) const { QDomNode child = selectNode(node, nodeName); if (!child.isNull()) { QString stringValue = nodeToString(child); *value = stringValue.contains("true", Qt::CaseInsensitive); return true; } return false; }
int SkinContext::selectInt(const QDomNode& node, const QString& nodeName, bool* pOk) const { bool ok = false; int conv = nodeToString(selectElement(node, nodeName)).toInt(&ok); if (pOk != NULL) { *pOk = ok; } return ok ? conv : 0; }
QString SkinContext::variableNodeToText(const QDomElement& variableNode) const { if (variableNode.hasAttribute("expression")) { QScriptValue result = m_scriptEngine.evaluate( variableNode.attribute("expression")); return result.toString(); } else if (variableNode.hasAttribute("name")) { QString variableName = variableNode.attribute("name"); if (variableNode.hasAttribute("format")) { QString formatString = variableNode.attribute("format"); return formatString.arg(variable(variableName)); } else if (variableNode.nodeName() == "SetVariable") { // If we are setting the variable name and we didn't get a format // string then return the node text. Use nodeToString to translate // embedded variable references. return nodeToString(variableNode); } else { return variable(variableName); } } return nodeToString(variableNode); }
/* function definitions */ Node * provRewriteQBModel (Node *qbModel) { if (isA(qbModel, List)) return (Node *) provRewriteQueryList((List *) qbModel); else if (IS_OP(qbModel)) return (Node *) provRewriteQuery((QueryOperator *) qbModel); FATAL_LOG("cannot rewrite node <%s>", nodeToString(qbModel)); return NULL; }
/* * pprint * pretty-print contents of Node to stdout */ void pprint(const void *obj) { char *s; char *f; s = nodeToString(obj); f = pretty_format_node_dump(s); pfree(s); printf("%s\n", f); fflush(stdout); pfree(f); }
void printSingleECList(List *l) { DEBUG_LOG("SET LIST: %s, SIZE LIST %d", nodeToString(l), LIST_LENGTH(l)); FOREACH(KeyValue, kv, l) { Set *s = (Set *) kv->key; Constant *c = (Constant *) kv->value; DEBUG_LOG("Set: "); FOREACH_SET(char, n, s) { DEBUG_LOG("%s", (char *)n); }
static void traverseQueryOids ( Query *pquery, HTAB *relhtab, StringInfoData *relbuf, HTAB *funchtab, StringInfoData *funcbuf ) { bool found; const char *whitespace = " \t\n\r"; char *query = nodeToString(pquery); char *token = strtok(query, whitespace); while (token) { if (pg_strcasecmp(token, ":relid") == 0) { token = strtok(NULL, whitespace); if (token) { Oid relid = atooid(token); hash_search(relhtab, (void *)&relid, HASH_ENTER, &found); if (!found) { if (relbuf->len != 0) appendStringInfo(relbuf, "%s", ","); appendStringInfo(relbuf, "%u", relid); } } } else if (pg_strcasecmp(token, ":funcid") == 0) { token = strtok(NULL, whitespace); if (token) { Oid funcid = atooid(token); hash_search(funchtab, (void *)&funcid, HASH_ENTER, &found); if (!found) { if (funcbuf->len != 0) appendStringInfo(funcbuf, "%s", ","); appendStringInfo(funcbuf, "%u", funcid); } } } token = strtok(NULL, whitespace); } }
QString SkinContext::variableNodeToText(const QDomElement& variableNode) const { QString expression = variableNode.attribute("expression"); if (!expression.isNull()) { QScriptValue result = m_pScriptEngine->evaluate( expression, m_xmlPath, variableNode.lineNumber()); return result.toString(); } QString variableName = variableNode.attribute("name"); if (!variableName.isNull()) { QString formatString = variableNode.attribute("format"); if (!formatString.isNull()) { return formatString.arg(variable(variableName)); } else if (variableNode.nodeName() == "SetVariable") { // If we are setting the variable name and we didn't get a format // string then return the node text. Use nodeToString to translate // embedded variable references. return nodeToString(variableNode); } else { return variable(variableName); } } return nodeToString(variableNode); }
/* * elog_node_display * send pretty-printed contents of Node to postmaster log */ void elog_node_display(int lev, const char *title, const void *obj, bool pretty) { char *s; char *f; s = nodeToString(obj); if (pretty) f = pretty_format_node_dump(s); else f = format_node_dump(s); pfree(s); ereport(lev, (errmsg_internal("%s:", title), errdetail_internal("%s", f))); pfree(f); }
static rc testQueryBlockToString(void) { char *toString; QueryBlock *q = createQueryBlock(); q->distinct = NULL; q->fromClause = NIL; q->havingClause = NULL; q->selectClause = NIL; q->whereClause = NULL; toString = nodeToString(q); ASSERT_EQUALS_STRING("{QUERYBLOCK:distinct|<>:selectClause|<>:fromClause|<>" ":whereClause|<>:groupByClause|<>:havingClause|<>:orderByClause|<>" ":limitClause|<>}", toString, ""); return PASS; }
PixmapSource SkinContext::getPixmapSource(const QDomNode& pixmapNode) const { if (!pixmapNode.isNull()) { QDomNode svgNode = selectNode(pixmapNode, "svg"); if (!svgNode.isNull()) { // inline svg SvgParser svgParser(*this); const QByteArray rslt = svgParser.saveToQByteArray( svgParser.parseSvgTree(svgNode, m_xmlPath)); PixmapSource source; source.setSVG(rslt); return source; } else { // filename. return getPixmapSourceInner(nodeToString(pixmapNode)); } } return PixmapSource(); }
QueryOperator * rewriteProvenanceComputation (ProvenanceComputation *op) { // for a sequence of updates of a transaction merge the sequence into a single // query before rewrite. if (op->inputType == PROV_INPUT_UPDATE_SEQUENCE || op->inputType == PROV_INPUT_TRANSACTION) { START_TIMER("rewrite - merge update reenactments"); mergeUpdateSequence(op); STOP_TIMER("rewrite - merge update reenactments"); // need to restrict to updated rows? if (op->inputType == PROV_INPUT_TRANSACTION && HAS_STRING_PROP(op,PROP_PC_ONLY_UPDATED)) { START_TIMER("rewrite - restrict to updated rows"); restrictToUpdatedRows(op); STOP_TIMER("rewrite - restrict to updated rows"); } } if (isRewriteOptionActivated(OPTION_TREEIFY_OPERATOR_MODEL)) { treeify((QueryOperator *) op); INFO_LOG("treeifyed operator model:\n\n%s", operatorToOverviewString((Node *) op)); DEBUG_LOG("treeifyed operator model:\n\n%s", beatify(nodeToString(op))); ASSERT(isTree((QueryOperator *) op)); } switch(op->provType) { case PROV_PI_CS: if (isRewriteOptionActivated(OPTION_PI_CS_USE_COMPOSABLE)) return rewritePI_CSComposable(op); else return rewritePI_CS(op); case PROV_TRANSFORMATION: return rewriteTransformationProvenance((QueryOperator *) op); } return NULL; }
static void fillOidToDTMap (HashMap *oidToDT) { PGresult *res = NULL; int numRes = 0; res = execQuery(QUERY_GET_DT_OIDS); numRes = PQntuples(res); for(int i = 0; i < numRes; i++) { char *oid = PQgetvalue(res,i,0); int oidInt = atoi(oid); char *typName = PQgetvalue(res,i,1); DEBUG_LOG("oid = %s, typename = %s", oid, typName); MAP_ADD_INT_KEY(oidToDT,oidInt, createConstInt(postgresTypenameToDT(typName))); } //TODO FINISH transaction PQclear(res); DEBUG_LOG("oid -> DT map:\n%s", beatify(nodeToString(oidToDT))); }
/* ---------------------------------------------------------------- * ProcedureCreate * * Note: allParameterTypes, parameterModes, parameterNames, trftypes, and proconfig * are either arrays of the proper types or NULL. We declare them Datum, * not "ArrayType *", to avoid importing array.h into pg_proc.h. * ---------------------------------------------------------------- */ ObjectAddress ProcedureCreate(const char *procedureName, Oid procNamespace, bool replace, bool returnsSet, Oid returnType, Oid proowner, Oid languageObjectId, Oid languageValidator, const char *prosrc, const char *probin, char prokind, bool security_definer, bool isLeakProof, bool isStrict, char volatility, char parallel, oidvector *parameterTypes, Datum allParameterTypes, Datum parameterModes, Datum parameterNames, List *parameterDefaults, Datum trftypes, Datum proconfig, float4 procost, float4 prorows) { Oid retval; int parameterCount; int allParamCount; Oid *allParams; char *paramModes = NULL; bool genericInParam = false; bool genericOutParam = false; bool anyrangeInParam = false; bool anyrangeOutParam = false; bool internalInParam = false; bool internalOutParam = false; Oid variadicType = InvalidOid; Acl *proacl = NULL; Relation rel; HeapTuple tup; HeapTuple oldtup; bool nulls[Natts_pg_proc]; Datum values[Natts_pg_proc]; bool replaces[Natts_pg_proc]; NameData procname; TupleDesc tupDesc; bool is_update; ObjectAddress myself, referenced; int i; Oid trfid; /* * sanity checks */ Assert(PointerIsValid(prosrc)); parameterCount = parameterTypes->dim1; if (parameterCount < 0 || parameterCount > FUNC_MAX_ARGS) ereport(ERROR, (errcode(ERRCODE_TOO_MANY_ARGUMENTS), errmsg_plural("functions cannot have more than %d argument", "functions cannot have more than %d arguments", FUNC_MAX_ARGS, FUNC_MAX_ARGS))); /* note: the above is correct, we do NOT count output arguments */ /* Deconstruct array inputs */ if (allParameterTypes != PointerGetDatum(NULL)) { /* * We expect the array to be a 1-D OID array; verify that. We don't * need to use deconstruct_array() since the array data is just going * to look like a C array of OID values. */ ArrayType *allParamArray = (ArrayType *) DatumGetPointer(allParameterTypes); allParamCount = ARR_DIMS(allParamArray)[0]; if (ARR_NDIM(allParamArray) != 1 || allParamCount <= 0 || ARR_HASNULL(allParamArray) || ARR_ELEMTYPE(allParamArray) != OIDOID) elog(ERROR, "allParameterTypes is not a 1-D Oid array"); allParams = (Oid *) ARR_DATA_PTR(allParamArray); Assert(allParamCount >= parameterCount); /* we assume caller got the contents right */ } else { allParamCount = parameterCount; allParams = parameterTypes->values; } if (parameterModes != PointerGetDatum(NULL)) { /* * We expect the array to be a 1-D CHAR array; verify that. We don't * need to use deconstruct_array() since the array data is just going * to look like a C array of char values. */ ArrayType *modesArray = (ArrayType *) DatumGetPointer(parameterModes); if (ARR_NDIM(modesArray) != 1 || ARR_DIMS(modesArray)[0] != allParamCount || ARR_HASNULL(modesArray) || ARR_ELEMTYPE(modesArray) != CHAROID) elog(ERROR, "parameterModes is not a 1-D char array"); paramModes = (char *) ARR_DATA_PTR(modesArray); } /* * Detect whether we have polymorphic or INTERNAL arguments. The first * loop checks input arguments, the second output arguments. */ for (i = 0; i < parameterCount; i++) { switch (parameterTypes->values[i]) { case ANYARRAYOID: case ANYELEMENTOID: case ANYNONARRAYOID: case ANYENUMOID: genericInParam = true; break; case ANYRANGEOID: genericInParam = true; anyrangeInParam = true; break; case INTERNALOID: internalInParam = true; break; } } if (allParameterTypes != PointerGetDatum(NULL)) { for (i = 0; i < allParamCount; i++) { if (paramModes == NULL || paramModes[i] == PROARGMODE_IN || paramModes[i] == PROARGMODE_VARIADIC) continue; /* ignore input-only params */ switch (allParams[i]) { case ANYARRAYOID: case ANYELEMENTOID: case ANYNONARRAYOID: case ANYENUMOID: genericOutParam = true; break; case ANYRANGEOID: genericOutParam = true; anyrangeOutParam = true; break; case INTERNALOID: internalOutParam = true; break; } } } /* * Do not allow polymorphic return type unless at least one input argument * is polymorphic. ANYRANGE return type is even stricter: must have an * ANYRANGE input (since we can't deduce the specific range type from * ANYELEMENT). Also, do not allow return type INTERNAL unless at least * one input argument is INTERNAL. */ if ((IsPolymorphicType(returnType) || genericOutParam) && !genericInParam) ereport(ERROR, (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), errmsg("cannot determine result data type"), errdetail("A function returning a polymorphic type must have at least one polymorphic argument."))); if ((returnType == ANYRANGEOID || anyrangeOutParam) && !anyrangeInParam) ereport(ERROR, (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), errmsg("cannot determine result data type"), errdetail("A function returning \"anyrange\" must have at least one \"anyrange\" argument."))); if ((returnType == INTERNALOID || internalOutParam) && !internalInParam) ereport(ERROR, (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), errmsg("unsafe use of pseudo-type \"internal\""), errdetail("A function returning \"internal\" must have at least one \"internal\" argument."))); if (paramModes != NULL) { /* * Only the last input parameter can be variadic; if it is, save its * element type. Errors here are just elog since caller should have * checked this already. */ for (i = 0; i < allParamCount; i++) { switch (paramModes[i]) { case PROARGMODE_IN: case PROARGMODE_INOUT: if (OidIsValid(variadicType)) elog(ERROR, "variadic parameter must be last"); break; case PROARGMODE_OUT: case PROARGMODE_TABLE: /* okay */ break; case PROARGMODE_VARIADIC: if (OidIsValid(variadicType)) elog(ERROR, "variadic parameter must be last"); switch (allParams[i]) { case ANYOID: variadicType = ANYOID; break; case ANYARRAYOID: variadicType = ANYELEMENTOID; break; default: variadicType = get_element_type(allParams[i]); if (!OidIsValid(variadicType)) elog(ERROR, "variadic parameter is not an array"); break; } break; default: elog(ERROR, "invalid parameter mode '%c'", paramModes[i]); break; } } } /* * All seems OK; prepare the data to be inserted into pg_proc. */ for (i = 0; i < Natts_pg_proc; ++i) { nulls[i] = false; values[i] = (Datum) 0; replaces[i] = true; } namestrcpy(&procname, procedureName); values[Anum_pg_proc_proname - 1] = NameGetDatum(&procname); values[Anum_pg_proc_pronamespace - 1] = ObjectIdGetDatum(procNamespace); values[Anum_pg_proc_proowner - 1] = ObjectIdGetDatum(proowner); values[Anum_pg_proc_prolang - 1] = ObjectIdGetDatum(languageObjectId); values[Anum_pg_proc_procost - 1] = Float4GetDatum(procost); values[Anum_pg_proc_prorows - 1] = Float4GetDatum(prorows); values[Anum_pg_proc_provariadic - 1] = ObjectIdGetDatum(variadicType); values[Anum_pg_proc_protransform - 1] = ObjectIdGetDatum(InvalidOid); values[Anum_pg_proc_prokind - 1] = CharGetDatum(prokind); values[Anum_pg_proc_prosecdef - 1] = BoolGetDatum(security_definer); values[Anum_pg_proc_proleakproof - 1] = BoolGetDatum(isLeakProof); values[Anum_pg_proc_proisstrict - 1] = BoolGetDatum(isStrict); values[Anum_pg_proc_proretset - 1] = BoolGetDatum(returnsSet); values[Anum_pg_proc_provolatile - 1] = CharGetDatum(volatility); values[Anum_pg_proc_proparallel - 1] = CharGetDatum(parallel); values[Anum_pg_proc_pronargs - 1] = UInt16GetDatum(parameterCount); values[Anum_pg_proc_pronargdefaults - 1] = UInt16GetDatum(list_length(parameterDefaults)); values[Anum_pg_proc_prorettype - 1] = ObjectIdGetDatum(returnType); values[Anum_pg_proc_proargtypes - 1] = PointerGetDatum(parameterTypes); if (allParameterTypes != PointerGetDatum(NULL)) values[Anum_pg_proc_proallargtypes - 1] = allParameterTypes; else nulls[Anum_pg_proc_proallargtypes - 1] = true; if (parameterModes != PointerGetDatum(NULL)) values[Anum_pg_proc_proargmodes - 1] = parameterModes; else nulls[Anum_pg_proc_proargmodes - 1] = true; if (parameterNames != PointerGetDatum(NULL)) values[Anum_pg_proc_proargnames - 1] = parameterNames; else nulls[Anum_pg_proc_proargnames - 1] = true; if (parameterDefaults != NIL) values[Anum_pg_proc_proargdefaults - 1] = CStringGetTextDatum(nodeToString(parameterDefaults)); else nulls[Anum_pg_proc_proargdefaults - 1] = true; if (trftypes != PointerGetDatum(NULL)) values[Anum_pg_proc_protrftypes - 1] = trftypes; else nulls[Anum_pg_proc_protrftypes - 1] = true; values[Anum_pg_proc_prosrc - 1] = CStringGetTextDatum(prosrc); if (probin) values[Anum_pg_proc_probin - 1] = CStringGetTextDatum(probin); else nulls[Anum_pg_proc_probin - 1] = true; if (proconfig != PointerGetDatum(NULL)) values[Anum_pg_proc_proconfig - 1] = proconfig; else nulls[Anum_pg_proc_proconfig - 1] = true; /* proacl will be determined later */ rel = table_open(ProcedureRelationId, RowExclusiveLock); tupDesc = RelationGetDescr(rel); /* Check for pre-existing definition */ oldtup = SearchSysCache3(PROCNAMEARGSNSP, PointerGetDatum(procedureName), PointerGetDatum(parameterTypes), ObjectIdGetDatum(procNamespace)); if (HeapTupleIsValid(oldtup)) { /* There is one; okay to replace it? */ Form_pg_proc oldproc = (Form_pg_proc) GETSTRUCT(oldtup); Datum proargnames; bool isnull; const char *dropcmd; if (!replace) ereport(ERROR, (errcode(ERRCODE_DUPLICATE_FUNCTION), errmsg("function \"%s\" already exists with same argument types", procedureName))); if (!pg_proc_ownercheck(oldproc->oid, proowner)) aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_FUNCTION, procedureName); /* Not okay to change routine kind */ if (oldproc->prokind != prokind) ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE), errmsg("cannot change routine kind"), (oldproc->prokind == PROKIND_AGGREGATE ? errdetail("\"%s\" is an aggregate function.", procedureName) : oldproc->prokind == PROKIND_FUNCTION ? errdetail("\"%s\" is a function.", procedureName) : oldproc->prokind == PROKIND_PROCEDURE ? errdetail("\"%s\" is a procedure.", procedureName) : oldproc->prokind == PROKIND_WINDOW ? errdetail("\"%s\" is a window function.", procedureName) : 0))); dropcmd = (prokind == PROKIND_PROCEDURE ? "DROP PROCEDURE" : "DROP FUNCTION"); /* * Not okay to change the return type of the existing proc, since * existing rules, views, etc may depend on the return type. * * In case of a procedure, a changing return type means that whether * the procedure has output parameters was changed. Since there is no * user visible return type, we produce a more specific error message. */ if (returnType != oldproc->prorettype || returnsSet != oldproc->proretset) ereport(ERROR, (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), prokind == PROKIND_PROCEDURE ? errmsg("cannot change whether a procedure has output parameters") : errmsg("cannot change return type of existing function"), /* translator: first %s is DROP FUNCTION or DROP PROCEDURE */ errhint("Use %s %s first.", dropcmd, format_procedure(oldproc->oid)))); /* * If it returns RECORD, check for possible change of record type * implied by OUT parameters */ if (returnType == RECORDOID) { TupleDesc olddesc; TupleDesc newdesc; olddesc = build_function_result_tupdesc_t(oldtup); newdesc = build_function_result_tupdesc_d(prokind, allParameterTypes, parameterModes, parameterNames); if (olddesc == NULL && newdesc == NULL) /* ok, both are runtime-defined RECORDs */ ; else if (olddesc == NULL || newdesc == NULL || !equalTupleDescs(olddesc, newdesc)) ereport(ERROR, (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), errmsg("cannot change return type of existing function"), errdetail("Row type defined by OUT parameters is different."), /* translator: first %s is DROP FUNCTION or DROP PROCEDURE */ errhint("Use %s %s first.", dropcmd, format_procedure(oldproc->oid)))); } /* * If there were any named input parameters, check to make sure the * names have not been changed, as this could break existing calls. We * allow adding names to formerly unnamed parameters, though. */ proargnames = SysCacheGetAttr(PROCNAMEARGSNSP, oldtup, Anum_pg_proc_proargnames, &isnull); if (!isnull) { Datum proargmodes; char **old_arg_names; char **new_arg_names; int n_old_arg_names; int n_new_arg_names; int j; proargmodes = SysCacheGetAttr(PROCNAMEARGSNSP, oldtup, Anum_pg_proc_proargmodes, &isnull); if (isnull) proargmodes = PointerGetDatum(NULL); /* just to be sure */ n_old_arg_names = get_func_input_arg_names(proargnames, proargmodes, &old_arg_names); n_new_arg_names = get_func_input_arg_names(parameterNames, parameterModes, &new_arg_names); for (j = 0; j < n_old_arg_names; j++) { if (old_arg_names[j] == NULL) continue; if (j >= n_new_arg_names || new_arg_names[j] == NULL || strcmp(old_arg_names[j], new_arg_names[j]) != 0) ereport(ERROR, (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), errmsg("cannot change name of input parameter \"%s\"", old_arg_names[j]), /* translator: first %s is DROP FUNCTION or DROP PROCEDURE */ errhint("Use %s %s first.", dropcmd, format_procedure(oldproc->oid)))); } } /* * If there are existing defaults, check compatibility: redefinition * must not remove any defaults nor change their types. (Removing a * default might cause a function to fail to satisfy an existing call. * Changing type would only be possible if the associated parameter is * polymorphic, and in such cases a change of default type might alter * the resolved output type of existing calls.) */ if (oldproc->pronargdefaults != 0) { Datum proargdefaults; List *oldDefaults; ListCell *oldlc; ListCell *newlc; if (list_length(parameterDefaults) < oldproc->pronargdefaults) ereport(ERROR, (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), errmsg("cannot remove parameter defaults from existing function"), /* translator: first %s is DROP FUNCTION or DROP PROCEDURE */ errhint("Use %s %s first.", dropcmd, format_procedure(oldproc->oid)))); proargdefaults = SysCacheGetAttr(PROCNAMEARGSNSP, oldtup, Anum_pg_proc_proargdefaults, &isnull); Assert(!isnull); oldDefaults = castNode(List, stringToNode(TextDatumGetCString(proargdefaults))); Assert(list_length(oldDefaults) == oldproc->pronargdefaults); /* new list can have more defaults than old, advance over 'em */ newlc = list_head(parameterDefaults); for (i = list_length(parameterDefaults) - oldproc->pronargdefaults; i > 0; i--) newlc = lnext(newlc); foreach(oldlc, oldDefaults) { Node *oldDef = (Node *) lfirst(oldlc); Node *newDef = (Node *) lfirst(newlc); if (exprType(oldDef) != exprType(newDef)) ereport(ERROR, (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), errmsg("cannot change data type of existing parameter default value"), /* translator: first %s is DROP FUNCTION or DROP PROCEDURE */ errhint("Use %s %s first.", dropcmd, format_procedure(oldproc->oid)))); newlc = lnext(newlc); } }
/* * InsertRule - * takes the arguments and inserts them as a row into the system * relation "pg_rewrite" */ static Oid InsertRule(char *rulname, int evtype, Oid eventrel_oid, AttrNumber evslot_index, bool evinstead, Node *event_qual, List *action, bool replace) { char *evqual = nodeToString(event_qual); char *actiontree = nodeToString((Node *) action); int i; Datum values[Natts_pg_rewrite]; bool nulls[Natts_pg_rewrite]; bool replaces[Natts_pg_rewrite]; NameData rname; Relation pg_rewrite_desc; HeapTuple tup, oldtup; Oid rewriteObjectId; ObjectAddress myself, referenced; bool is_update = false; /* * Set up *nulls and *values arrays */ MemSet(nulls, false, sizeof(nulls)); i = 0; namestrcpy(&rname, rulname); values[i++] = NameGetDatum(&rname); /* rulename */ values[i++] = ObjectIdGetDatum(eventrel_oid); /* ev_class */ values[i++] = Int16GetDatum(evslot_index); /* ev_attr */ values[i++] = CharGetDatum(evtype + '0'); /* ev_type */ values[i++] = CharGetDatum(RULE_FIRES_ON_ORIGIN); /* ev_enabled */ values[i++] = BoolGetDatum(evinstead); /* is_instead */ values[i++] = CStringGetTextDatum(evqual); /* ev_qual */ values[i++] = CStringGetTextDatum(actiontree); /* ev_action */ /* * Ready to store new pg_rewrite tuple */ pg_rewrite_desc = heap_open(RewriteRelationId, RowExclusiveLock); /* * Check to see if we are replacing an existing tuple */ oldtup = SearchSysCache2(RULERELNAME, ObjectIdGetDatum(eventrel_oid), PointerGetDatum(rulname)); if (HeapTupleIsValid(oldtup)) { if (!replace) ereport(ERROR, (errcode(ERRCODE_DUPLICATE_OBJECT), errmsg("rule \"%s\" for relation \"%s\" already exists", rulname, get_rel_name(eventrel_oid)))); /* * When replacing, we don't need to replace every attribute */ MemSet(replaces, false, sizeof(replaces)); replaces[Anum_pg_rewrite_ev_attr - 1] = true; replaces[Anum_pg_rewrite_ev_type - 1] = true; replaces[Anum_pg_rewrite_is_instead - 1] = true; replaces[Anum_pg_rewrite_ev_qual - 1] = true; replaces[Anum_pg_rewrite_ev_action - 1] = true; tup = heap_modify_tuple(oldtup, RelationGetDescr(pg_rewrite_desc), values, nulls, replaces); simple_heap_update(pg_rewrite_desc, &tup->t_self, tup); ReleaseSysCache(oldtup); rewriteObjectId = HeapTupleGetOid(tup); is_update = true; } else { tup = heap_form_tuple(pg_rewrite_desc->rd_att, values, nulls); rewriteObjectId = simple_heap_insert(pg_rewrite_desc, tup); } /* Need to update indexes in either case */ CatalogUpdateIndexes(pg_rewrite_desc, tup); heap_freetuple(tup); /* If replacing, get rid of old dependencies and make new ones */ if (is_update) deleteDependencyRecordsFor(RewriteRelationId, rewriteObjectId, false); /* * Install dependency on rule's relation to ensure it will go away on * relation deletion. If the rule is ON SELECT, make the dependency * implicit --- this prevents deleting a view's SELECT rule. Other kinds * of rules can be AUTO. */ myself.classId = RewriteRelationId; myself.objectId = rewriteObjectId; myself.objectSubId = 0; referenced.classId = RelationRelationId; referenced.objectId = eventrel_oid; referenced.objectSubId = 0; recordDependencyOn(&myself, &referenced, (evtype == CMD_SELECT) ? DEPENDENCY_INTERNAL : DEPENDENCY_AUTO); /* * Also install dependencies on objects referenced in action and qual. */ recordDependencyOnExpr(&myself, (Node *) action, NIL, DEPENDENCY_NORMAL); if (event_qual != NULL) { /* Find query containing OLD/NEW rtable entries */ Query *qry = (Query *) linitial(action); qry = getInsertSelectQuery(qry, NULL); recordDependencyOnExpr(&myself, event_qual, qry->rtable, DEPENDENCY_NORMAL); } /* Post creation hook for new rule */ InvokeObjectAccessHook(OAT_POST_CREATE, RewriteRelationId, rewriteObjectId, 0); heap_close(pg_rewrite_desc, RowExclusiveLock); return rewriteObjectId; }
double SkinContext::selectDouble(const QDomNode& node, const QString& nodeName) const { bool ok = false; double conv = nodeToString(selectElement(node, nodeName)).toDouble(&ok); return ok ? conv : 0.0; }
{ List *attr = getAttributeNames(delete->nodeName); TableAccessOperator *to; to = createTableAccessOp(strdup(delete->nodeName), NULL, NULL, NIL, deepCopyStringList(attr), NIL); SET_BOOL_STRING_PROP(to,PROP_TABLE_IS_UPDATED); SelectionOperator *so; Node *negatedCond; negatedCond = (Node *) createOpExpr("NOT", singleton(copyObject(delete->cond))); so = createSelectionOp(negatedCond, NULL, NIL, deepCopyStringList(attr)); addChildOperator((QueryOperator *) so, (QueryOperator *) to); INFO_LOG("translated delete:\n%s", operatorToOverviewString((Node *) so)); DEBUG_LOG("translated delete:\n%s", beatify(nodeToString((Node *) so))); return (QueryOperator *) so; } static QueryOperator * translateUpdateUnion(Update *update) { List *attrs = getAttributeNames(update->nodeName); // create table access operator TableAccessOperator *to; to = createTableAccessOp(strdup(update->nodeName), NULL, NULL, NIL, deepCopyStringList(attrs), NIL); SET_BOOL_STRING_PROP(to,PROP_TABLE_IS_UPDATED); // CREATE PROJECTION EXPRESSIONS