aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/adt/ruleutils.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/utils/adt/ruleutils.c')
-rw-r--r--src/backend/utils/adt/ruleutils.c126
1 files changed, 73 insertions, 53 deletions
diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c
index e41d3245818..1040ff3e238 100644
--- a/src/backend/utils/adt/ruleutils.c
+++ b/src/backend/utils/adt/ruleutils.c
@@ -3,7 +3,7 @@
* back to source text
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.140 2003/05/20 20:35:10 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.141 2003/05/28 16:03:59 tgl Exp $
*
* This software is copyrighted by Jan Wieck - Hamburg.
*
@@ -535,12 +535,14 @@ pg_get_indexdef(PG_FUNCTION_ARGS)
Form_pg_index idxrec;
Form_pg_class idxrelrec;
Form_pg_am amrec;
+ List *indexprs;
+ List *context;
Oid indrelid;
int len;
int keyno;
- Oid keycoltypes[INDEX_MAX_KEYS];
+ Oid keycoltype;
StringInfoData buf;
- StringInfoData keybuf;
+ char *str;
char *sep;
/*
@@ -577,6 +579,30 @@ pg_get_indexdef(PG_FUNCTION_ARGS)
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.
*/
@@ -588,76 +614,72 @@ pg_get_indexdef(PG_FUNCTION_ARGS)
quote_identifier(NameStr(amrec->amname)));
/*
- * Collect the indexed attributes in keybuf
+ * Report the indexed attributes
*/
- initStringInfo(&keybuf);
sep = "";
- for (keyno = 0; keyno < INDEX_MAX_KEYS; keyno++)
+ for (keyno = 0; keyno < idxrec->indnatts; keyno++)
{
AttrNumber attnum = idxrec->indkey[keyno];
- char *attname;
-
- if (attnum == InvalidAttrNumber)
- break;
-
- attname = get_relid_attribute_name(indrelid, attnum);
- keycoltypes[keyno] = get_atttype(indrelid, attnum);
- appendStringInfo(&keybuf, sep);
+ appendStringInfo(&buf, sep);
sep = ", ";
- /*
- * Add the indexed field name
- */
- appendStringInfo(&keybuf, "%s", quote_identifier(attname));
+ if (attnum != 0)
+ {
+ /* Simple index column */
+ char *attname;
- /*
- * If not a functional index, add the operator class name
- */
- if (idxrec->indproc == InvalidOid)
- get_opclass_name(idxrec->indclass[keyno],
- keycoltypes[keyno],
- &keybuf);
- }
+ attname = get_relid_attribute_name(indrelid, attnum);
+ 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(indexkey, context, false, false);
+ /* 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);
+ }
- if (idxrec->indproc != InvalidOid)
- {
/*
- * For functional index say 'func (attrs) opclass'
+ * Add the operator class name
*/
- appendStringInfo(&buf, "%s(%s)",
- generate_function_name(idxrec->indproc,
- keyno, keycoltypes),
- keybuf.data);
- get_opclass_name(idxrec->indclass[0],
- get_func_rettype(idxrec->indproc),
+ get_opclass_name(idxrec->indclass[keyno], keycoltype,
&buf);
}
- else
- {
- /*
- * Otherwise say 'attr opclass [, ...]'
- */
- appendStringInfo(&buf, "%s", keybuf.data);
- }
appendStringInfoChar(&buf, ')');
/*
* If it's a partial index, decompile and append the predicate
*/
- if (VARSIZE(&idxrec->indpred) > VARHDRSZ)
+ if (!heap_attisnull(ht_idx, Anum_pg_index_indpred))
{
Node *node;
- List *context;
- char *exprstr;
- char *str;
+ Datum predDatum;
+ bool isnull;
+ char *predString;
- /* Convert TEXT object to C string */
- exprstr = DatumGetCString(DirectFunctionCall1(textout,
- PointerGetDatum(&idxrec->indpred)));
- /* Convert expression to node tree */
- node = (Node *) stringToNode(exprstr);
+ /* 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,
@@ -667,7 +689,6 @@ pg_get_indexdef(PG_FUNCTION_ARGS)
if (node && IsA(node, List))
node = (Node *) make_ands_explicit((List *) node);
/* Deparse */
- context = deparse_context_for(get_rel_name(indrelid), indrelid);
str = deparse_expression(node, context, false, false);
appendStringInfo(&buf, " WHERE %s", str);
}
@@ -681,7 +702,6 @@ pg_get_indexdef(PG_FUNCTION_ARGS)
memcpy(VARDATA(indexdef), buf.data, buf.len);
pfree(buf.data);
- pfree(keybuf.data);
ReleaseSysCache(ht_idx);
ReleaseSysCache(ht_idxrel);