ruleutils.c
来自「postgresql8.3.4源码,开源数据库」· C语言 代码 · 共 2,446 行 · 第 1/5 页
C
2,446 行
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 = DatumGetByteaP(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, ", "); /* * We form the string literal according to the prevailing setting * of standard_conforming_strings; we never use E''. User is * responsible for making sure result is used correctly. */ appendStringInfoChar(&buf, '\''); while (*p) { char ch = *p++; if (SQL_STR_DOUBLE(ch, !standard_conforming_strings)) appendStringInfoChar(&buf, ch); appendStringInfoChar(&buf, ch); } appendStringInfoChar(&buf, '\''); /* advance p to next string embedded in tgargs */ p++; } } /* We deliberately do not put semi-colon at end */ appendStringInfo(&buf, ")"); /* Clean up */ systable_endscan(tgscan); heap_close(tgrel, AccessShareLock); PG_RETURN_TEXT_P(string_to_text(buf.data));}/* ---------- * 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. * * Note that the SQL-function versions of this omit any info about the * index tablespace; this is intentional because pg_dump wants it that way. * However pg_get_indexdef_string() includes index tablespace if not default. * ---------- */Datumpg_get_indexdef(PG_FUNCTION_ARGS){ Oid indexrelid = PG_GETARG_OID(0); PG_RETURN_TEXT_P(string_to_text(pg_get_indexdef_worker(indexrelid, 0, false, 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; PG_RETURN_TEXT_P(string_to_text(pg_get_indexdef_worker(indexrelid, colno, false, prettyFlags)));}/* Internal version that returns a palloc'd C string */char *pg_get_indexdef_string(Oid indexrelid){ return pg_get_indexdef_worker(indexrelid, 0, true, 0);}static char *pg_get_indexdef_worker(Oid indexrelid, int colno, bool showTblSpc, int prettyFlags){ HeapTuple ht_idx; HeapTuple ht_idxrel; HeapTuple ht_am; Form_pg_index idxrec; Form_pg_class idxrelrec; Form_pg_am amrec; List *indexprs; ListCell *indexpr_item; List *context; Oid indrelid; int keyno; Oid keycoltype; Datum indclassDatum; Datum indoptionDatum; bool isnull; oidvector *indclass; int2vector *indoption; 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); /* Must get indclass and indoption the hard way */ indclassDatum = SysCacheGetAttr(INDEXRELID, ht_idx, Anum_pg_index_indclass, &isnull); Assert(!isnull); indclass = (oidvector *) DatumGetPointer(indclassDatum); indoptionDatum = SysCacheGetAttr(INDEXRELID, ht_idx, Anum_pg_index_indoption, &isnull); Assert(!isnull); indoption = (int2vector *) DatumGetPointer(indoptionDatum); /* * 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; indexpr_item = list_head(indexprs); 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.values[keyno]; int16 opt = indoption->values[keyno]; if (!colno) appendStringInfoString(&buf, sep); sep = ", "; if (attnum != 0) { /* Simple index column */ char *attname; attname = get_relid_attribute_name(indrelid, attnum); if (!colno || colno == keyno + 1) appendStringInfoString(&buf, quote_identifier(attname)); keycoltype = get_atttype(indrelid, attnum); } else { /* expressional index */ Node *indexkey; if (indexpr_item == NULL) elog(ERROR, "too few entries in indexprs list"); indexkey = (Node *) lfirst(indexpr_item); indexpr_item = lnext(indexpr_item); /* 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) appendStringInfoString(&buf, str); else appendStringInfo(&buf, "(%s)", str); } keycoltype = exprType(indexkey); } /* Provide decoration only in the colno=0 case */ if (!colno) { /* Add the operator class name, if not default */ get_opclass_name(indclass->values[keyno], keycoltype, &buf); /* Add options if relevant */ if (amrec->amcanorder) { /* if it supports sort ordering, report DESC and NULLS opts */ if (opt & INDOPTION_DESC) { appendStringInfo(&buf, " DESC"); /* NULLS FIRST is the default in this case */ if (!(opt & INDOPTION_NULLS_FIRST)) appendStringInfo(&buf, " NULLS LAST"); } else { if (opt & INDOPTION_NULLS_FIRST) appendStringInfo(&buf, " NULLS FIRST"); } } } } if (!colno) { appendStringInfoChar(&buf, ')'); /* * If it has options, append "WITH (options)" */ str = flatten_reloptions(indexrelid); if (str) { appendStringInfo(&buf, " WITH (%s)", str); pfree(str); } /* * If it's in a nondefault tablespace, say so, but only if requested */ if (showTblSpc) { Oid tblspc; tblspc = get_rel_tablespace(indexrelid); if (OidIsValid(tblspc)) appendStringInfo(&buf, " TABLESPACE %s", quote_identifier(get_tablespace_name(tblspc))); } /* * 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); /* Deparse */ str = deparse_expression_pretty(node, context, false, false, prettyFlags, 0); appendStringInfo(&buf, " WHERE %s", str); } } /* Clean up */ ReleaseSysCache(ht_idx); ReleaseSysCache(ht_idxrel); ReleaseSysCache(ht_am); return buf.data;}/* * 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); PG_RETURN_TEXT_P(string_to_text(pg_get_constraintdef_worker(constraintId, false, 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; PG_RETURN_TEXT_P(string_to_text(pg_get_constraintdef_worker(constraintId, false, prettyFlags)));}/* Internal version that returns a palloc'd C string */char *pg_get_constraintdef_string(Oid constraintId){ return pg_get_constraintdef_worker(constraintId, true, 0);}static char *pg_get_constraintdef_worker(Oid constraintId, bool fullCommand, int prettyFlags){ HeapTuple tup; Form_pg_constraint conForm; StringInfoData buf; tup = SearchSysCache(CONSTROID, ObjectIdGetDatum(constraintId), 0, 0, 0); if (!HeapTupleIsValid(tup)) /* should not happen */ elog(ERROR, "cache lookup failed for constraint %u", constraintId); conForm = (Form_pg_constraint) GETSTRUCT(tup); initStringInfo(&buf); if (fullCommand && OidIsValid(conForm->conrelid)) { appendStringInfo(&buf, "ALTER TABLE ONLY %s ADD CONSTRAINT %s ", generate_relation_name(conForm->conrelid), quote_identifier(NameStr(conForm->conname))); } 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 = SysCacheGetAttr(CONSTROID, tup, Anum_pg_constraint_conkey, &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 = SysCacheGetAttr(CONSTROID, tup, Anum_pg_constraint_confkey, &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; } appendStringInfoString(&buf, 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";
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?