ruleutils.c
来自「PostgreSQL7.4.6 for Linux」· C语言 代码 · 共 2,475 行 · 第 1/5 页
C
2,475 行
SnapshotNow, 1, skey); ht_trig = systable_getnext(tgscan); if (!HeapTupleIsValid(ht_trig)) elog(ERROR, "could not find tuple for trigger %u", trigid); trigrec = (Form_pg_trigger) GETSTRUCT(ht_trig); /* * Start the trigger definition. Note that the trigger's name should * never be schema-qualified, but the trigger rel's name may be. */ initStringInfo(&buf); tgname = NameStr(trigrec->tgname); appendStringInfo(&buf, "CREATE %sTRIGGER %s ", trigrec->tgisconstraint ? "CONSTRAINT " : "", quote_identifier(tgname)); if (TRIGGER_FOR_BEFORE(trigrec->tgtype)) appendStringInfo(&buf, "BEFORE"); else appendStringInfo(&buf, "AFTER"); if (TRIGGER_FOR_INSERT(trigrec->tgtype)) { appendStringInfo(&buf, " INSERT"); findx++; } if (TRIGGER_FOR_DELETE(trigrec->tgtype)) { if (findx > 0) appendStringInfo(&buf, " OR DELETE"); else appendStringInfo(&buf, " DELETE"); findx++; } if (TRIGGER_FOR_UPDATE(trigrec->tgtype)) { if (findx > 0) appendStringInfo(&buf, " OR UPDATE"); else appendStringInfo(&buf, " UPDATE"); } appendStringInfo(&buf, " ON %s ", generate_relation_name(trigrec->tgrelid)); if (trigrec->tgisconstraint) { if (trigrec->tgconstrrelid != InvalidOid) appendStringInfo(&buf, "FROM %s ", generate_relation_name(trigrec->tgconstrrelid)); if (!trigrec->tgdeferrable) appendStringInfo(&buf, "NOT "); appendStringInfo(&buf, "DEFERRABLE INITIALLY "); if (trigrec->tginitdeferred) appendStringInfo(&buf, "DEFERRED "); else appendStringInfo(&buf, "IMMEDIATE "); } if (TRIGGER_FOR_ROW(trigrec->tgtype)) appendStringInfo(&buf, "FOR EACH ROW "); else appendStringInfo(&buf, "FOR EACH STATEMENT "); appendStringInfo(&buf, "EXECUTE PROCEDURE %s(", generate_function_name(trigrec->tgfoid, 0, NULL)); if (trigrec->tgnargs > 0) { bytea *val; bool isnull; char *p; int i; val = (bytea *) fastgetattr(ht_trig, Anum_pg_trigger_tgargs, tgrel->rd_att, &isnull); if (isnull) elog(ERROR, "tgargs is null for trigger %u", trigid); p = (char *) VARDATA(val); for (i = 0; i < trigrec->tgnargs; i++) { if (i > 0) appendStringInfo(&buf, ", "); appendStringInfoChar(&buf, '\''); while (*p) { /* escape quotes and backslashes */ if (*p == '\'' || *p == '\\') appendStringInfoChar(&buf, '\\'); appendStringInfoChar(&buf, *p++); } p++; appendStringInfoChar(&buf, '\''); } } /* We deliberately do not put semi-colon at end */ appendStringInfo(&buf, ")"); /* * Create the result as a TEXT datum, and free working data */ len = buf.len + VARHDRSZ; trigdef = (text *) palloc(len); VARATT_SIZEP(trigdef) = len; memcpy(VARDATA(trigdef), buf.data, buf.len); pfree(buf.data); systable_endscan(tgscan); heap_close(tgrel, AccessShareLock); PG_RETURN_TEXT_P(trigdef);}/* ---------- * get_indexdef - Get the definition of an index * * In the extended version, there is a colno argument as well as pretty bool. * if colno == 0, we want a complete index definition. * if colno > 0, we only want the Nth index key's variable or expression. * ---------- */Datumpg_get_indexdef(PG_FUNCTION_ARGS){ Oid indexrelid = PG_GETARG_OID(0); return pg_get_indexdef_worker(indexrelid, 0, 0);}Datumpg_get_indexdef_ext(PG_FUNCTION_ARGS){ Oid indexrelid = PG_GETARG_OID(0); int32 colno = PG_GETARG_INT32(1); bool pretty = PG_GETARG_BOOL(2); int prettyFlags; prettyFlags = pretty ? PRETTYFLAG_PAREN | PRETTYFLAG_INDENT : 0; return pg_get_indexdef_worker(indexrelid, colno, prettyFlags);}static Datumpg_get_indexdef_worker(Oid indexrelid, int colno, int prettyFlags){ text *indexdef; HeapTuple ht_idx; HeapTuple ht_idxrel; HeapTuple ht_am; Form_pg_index idxrec; Form_pg_class idxrelrec; Form_pg_am amrec; List *indexprs; List *context; Oid indrelid; int len; int keyno; Oid keycoltype; StringInfoData buf; char *str; char *sep; /* * Fetch the pg_index tuple by the Oid of the index */ ht_idx = SearchSysCache(INDEXRELID, ObjectIdGetDatum(indexrelid), 0, 0, 0); if (!HeapTupleIsValid(ht_idx)) elog(ERROR, "cache lookup failed for index %u", indexrelid); idxrec = (Form_pg_index) GETSTRUCT(ht_idx); indrelid = idxrec->indrelid; Assert(indexrelid == idxrec->indexrelid); /* * Fetch the pg_class tuple of the index relation */ ht_idxrel = SearchSysCache(RELOID, ObjectIdGetDatum(indexrelid), 0, 0, 0); if (!HeapTupleIsValid(ht_idxrel)) elog(ERROR, "cache lookup failed for relation %u", indexrelid); idxrelrec = (Form_pg_class) GETSTRUCT(ht_idxrel); /* * Fetch the pg_am tuple of the index' access method */ ht_am = SearchSysCache(AMOID, ObjectIdGetDatum(idxrelrec->relam), 0, 0, 0); if (!HeapTupleIsValid(ht_am)) elog(ERROR, "cache lookup failed for access method %u", idxrelrec->relam); amrec = (Form_pg_am) GETSTRUCT(ht_am); /* * Get the index expressions, if any. (NOTE: we do not use the * relcache versions of the expressions and predicate, because we want * to display non-const-folded expressions.) */ if (!heap_attisnull(ht_idx, Anum_pg_index_indexprs)) { Datum exprsDatum; bool isnull; char *exprsString; exprsDatum = SysCacheGetAttr(INDEXRELID, ht_idx, Anum_pg_index_indexprs, &isnull); Assert(!isnull); exprsString = DatumGetCString(DirectFunctionCall1(textout, exprsDatum)); indexprs = (List *) stringToNode(exprsString); pfree(exprsString); } else indexprs = NIL; context = deparse_context_for(get_rel_name(indrelid), indrelid); /* * Start the index definition. Note that the index's name should * never be schema-qualified, but the indexed rel's name may be. */ initStringInfo(&buf); if (!colno) appendStringInfo(&buf, "CREATE %sINDEX %s ON %s USING %s (", idxrec->indisunique ? "UNIQUE " : "", quote_identifier(NameStr(idxrelrec->relname)), generate_relation_name(indrelid), quote_identifier(NameStr(amrec->amname))); /* * Report the indexed attributes */ sep = ""; for (keyno = 0; keyno < idxrec->indnatts; keyno++) { AttrNumber attnum = idxrec->indkey[keyno]; if (!colno) appendStringInfo(&buf, sep); sep = ", "; if (attnum != 0) { /* Simple index column */ char *attname; attname = get_relid_attribute_name(indrelid, attnum); if (!colno || colno == keyno + 1) appendStringInfo(&buf, "%s", quote_identifier(attname)); keycoltype = get_atttype(indrelid, attnum); } else { /* expressional index */ Node *indexkey; if (indexprs == NIL) elog(ERROR, "too few entries in indexprs list"); indexkey = (Node *) lfirst(indexprs); indexprs = lnext(indexprs); /* Deparse */ str = deparse_expression_pretty(indexkey, context, false, false, prettyFlags, 0); if (!colno || colno == keyno + 1) { /* Need parens if it's not a bare function call */ if (indexkey && IsA(indexkey, FuncExpr) && ((FuncExpr *) indexkey)->funcformat == COERCE_EXPLICIT_CALL) appendStringInfo(&buf, "%s", str); else appendStringInfo(&buf, "(%s)", str); } keycoltype = exprType(indexkey); } /* * Add the operator class name */ if (!colno) get_opclass_name(idxrec->indclass[keyno], keycoltype, &buf); } if (!colno) { appendStringInfoChar(&buf, ')'); /* * If it's a partial index, decompile and append the predicate */ if (!heap_attisnull(ht_idx, Anum_pg_index_indpred)) { Node *node; Datum predDatum; bool isnull; char *predString; /* Convert text string to node tree */ predDatum = SysCacheGetAttr(INDEXRELID, ht_idx, Anum_pg_index_indpred, &isnull); Assert(!isnull); predString = DatumGetCString(DirectFunctionCall1(textout, predDatum)); node = (Node *) stringToNode(predString); pfree(predString); /* * If top level is a List, assume it is an implicit-AND * structure, and convert to explicit AND. This is needed for * partial index predicates. */ if (node && IsA(node, List)) node = (Node *) make_ands_explicit((List *) node); /* Deparse */ str = deparse_expression_pretty(node, context, false, false, prettyFlags, 0); appendStringInfo(&buf, " WHERE %s", str); } } /* * Create the result as a TEXT datum, and free working data */ len = buf.len + VARHDRSZ; indexdef = (text *) palloc(len); VARATT_SIZEP(indexdef) = len; memcpy(VARDATA(indexdef), buf.data, buf.len); pfree(buf.data); ReleaseSysCache(ht_idx); ReleaseSysCache(ht_idxrel); ReleaseSysCache(ht_am); PG_RETURN_TEXT_P(indexdef);}/* * pg_get_constraintdef * * Returns the definition for the constraint, ie, everything that needs to * appear after "ALTER TABLE ... ADD CONSTRAINT <constraintname>". */Datumpg_get_constraintdef(PG_FUNCTION_ARGS){ Oid constraintId = PG_GETARG_OID(0); return pg_get_constraintdef_worker(constraintId, 0);}Datumpg_get_constraintdef_ext(PG_FUNCTION_ARGS){ Oid constraintId = PG_GETARG_OID(0); bool pretty = PG_GETARG_BOOL(1); int prettyFlags; prettyFlags = pretty ? PRETTYFLAG_PAREN | PRETTYFLAG_INDENT : 0; return pg_get_constraintdef_worker(constraintId, prettyFlags);}static Datumpg_get_constraintdef_worker(Oid constraintId, int prettyFlags){ text *result; StringInfoData buf; int len; Relation conDesc; SysScanDesc conscan; ScanKeyData skey[1]; HeapTuple tup; Form_pg_constraint conForm; /* * Fetch the pg_constraint row. There's no syscache for pg_constraint * so we must do it the hard way. */ conDesc = heap_openr(ConstraintRelationName, AccessShareLock); ScanKeyEntryInitialize(&skey[0], 0x0, ObjectIdAttributeNumber, F_OIDEQ, ObjectIdGetDatum(constraintId)); conscan = systable_beginscan(conDesc, ConstraintOidIndex, true, SnapshotNow, 1, skey); tup = systable_getnext(conscan); if (!HeapTupleIsValid(tup)) elog(ERROR, "could not find tuple for constraint %u", constraintId); conForm = (Form_pg_constraint) GETSTRUCT(tup); initStringInfo(&buf); switch (conForm->contype) { case CONSTRAINT_FOREIGN: { Datum val; bool isnull; const char *string; /* Start off the constraint definition */ appendStringInfo(&buf, "FOREIGN KEY ("); /* Fetch and build referencing-column list */ val = heap_getattr(tup, Anum_pg_constraint_conkey, RelationGetDescr(conDesc), &isnull); if (isnull) elog(ERROR, "null conkey for constraint %u", constraintId); decompile_column_index_array(val, conForm->conrelid, &buf); /* add foreign relation name */ appendStringInfo(&buf, ") REFERENCES %s(", generate_relation_name(conForm->confrelid)); /* Fetch and build referenced-column list */ val = heap_getattr(tup, Anum_pg_constraint_confkey, RelationGetDescr(conDesc), &isnull); if (isnull) elog(ERROR, "null confkey for constraint %u", constraintId); decompile_column_index_array(val, conForm->confrelid, &buf); appendStringInfo(&buf, ")"); /* Add match type */ switch (conForm->confmatchtype) { case FKCONSTR_MATCH_FULL: string = " MATCH FULL"; break; case FKCONSTR_MATCH_PARTIAL: string = " MATCH PARTIAL"; break; case FKCONSTR_MATCH_UNSPECIFIED: string = ""; break; default: elog(ERROR, "unrecognized confmatchtype: %d", conForm->confmatchtype); string = ""; /* keep compiler quiet */ break; } appendStringInfo(&buf, "%s", string); /* Add ON UPDATE and ON DELETE clauses, if needed */ switch (conForm->confupdtype) { case FKCONSTR_ACTION_NOACTION: string = NULL; /* suppress default */ break; case FKCONSTR_ACTION_RESTRICT: string = "RESTRICT"; break; case FKCONSTR_ACTION_CASCADE: string = "CASCADE"; break; case FKCONSTR_ACTION_SETNULL: string = "SET NULL"; break; case FKCONSTR_ACTION_SETDEFAULT: string = "SET DEFAULT"; break; default: elog(ERROR, "unrecognized confupdtype: %d", conForm->confupdtype); string = NULL; /* keep compiler quiet */ break; } if (string) appendStringInfo(&buf, " ON UPDATE %s", string); switch (conForm->confdeltype) { case FKCONSTR_ACTION_NOACTION: string = NULL; /* suppress default */ break; case FKCONSTR_ACTION_RESTRICT: string = "RESTRICT";
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?