diff options
Diffstat (limited to 'src/backend/utils/adt/sets.c')
-rw-r--r-- | src/backend/utils/adt/sets.c | 260 |
1 files changed, 135 insertions, 125 deletions
diff --git a/src/backend/utils/adt/sets.c b/src/backend/utils/adt/sets.c index 55ca1f4b643..72f0a615a66 100644 --- a/src/backend/utils/adt/sets.c +++ b/src/backend/utils/adt/sets.c @@ -1,163 +1,173 @@ /*------------------------------------------------------------------------- * * sets.c-- - * Functions for sets, which are defined by queries. - * Example: a set is defined as being the result of the query - * retrieve (X.all) + * Functions for sets, which are defined by queries. + * Example: a set is defined as being the result of the query + * retrieve (X.all) * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/sets.c,v 1.5 1997/08/12 22:54:38 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/sets.c,v 1.6 1997/09/07 04:50:43 momjian Exp $ * *------------------------------------------------------------------------- */ -#include <stdio.h> /* for sprintf() */ +#include <stdio.h> /* for sprintf() */ #include <string.h> #include "postgres.h" #include "access/heapam.h" #include "access/relscan.h" #include "access/xact.h" -#include "catalog/pg_proc.h" /* for Form_pg_proc */ -#include "utils/syscache.h" /* for PROOID */ -#include "catalog/catname.h" /* for ProcedureRelationName */ -#include "catalog/indexing.h" /* for Num_pg_proc_indices */ +#include "catalog/pg_proc.h" /* for Form_pg_proc */ +#include "utils/syscache.h" /* for PROOID */ +#include "catalog/catname.h" /* for ProcedureRelationName */ +#include "catalog/indexing.h" /* for Num_pg_proc_indices */ #include "storage/lmgr.h" -#include "utils/sets.h" /* for GENERICSETNAME */ +#include "utils/sets.h" /* for GENERICSETNAME */ #include "tcop/dest.h" #include "fmgr.h" -extern CommandDest whereToSendOutput; /* defined in tcop/postgres.c */ +extern CommandDest whereToSendOutput; /* defined in tcop/postgres.c */ /* - * SetDefine - converts query string defining set to an oid + * SetDefine - converts query string defining set to an oid * - * The query string is used to store the set as a function in - * pg_proc. The name of the function is then changed to use the - * OID of its tuple in pg_proc. + * The query string is used to store the set as a function in + * pg_proc. The name of the function is then changed to use the + * OID of its tuple in pg_proc. */ Oid SetDefine(char *querystr, char *typename) { - Oid setoid; - char *procname = GENERICSETNAME; - char *fileName = "-"; - char realprocname[16]; - HeapTuple tup, newtup = NULL; - Form_pg_proc proc; - Relation procrel; - int i; - Datum replValue[Natts_pg_proc]; - char replNull[Natts_pg_proc]; - char repl[Natts_pg_proc]; - HeapScanDesc pg_proc_scan; - Buffer buffer; - ItemPointerData ipdata; - - static ScanKeyData oidKey[1] = { - { 0, ObjectIdAttributeNumber, ObjectIdEqualRegProcedure }}; - - - setoid = ProcedureCreate(procname, /* changed below, after oid known */ - true, /* returnsSet */ - typename, /* returnTypeName */ - "sql", /* languageName */ - querystr, /* sourceCode */ - fileName, /* fileName */ - false, /* canCache */ - true, /* trusted */ - 100, /* byte_pct */ - 0, /* perbyte_cpu */ - 0, /* percall_cpu */ - 100, /* outin_ratio */ - NIL, /* argList */ - whereToSendOutput); - /* Since we're still inside this command of the transaction, we can't - * see the results of the procedure definition unless we pretend - * we've started the next command. (Postgres's solution to the - * Halloween problem is to not allow you to see the results of your - * command until you start the next command.) - */ - CommandCounterIncrement(); - tup = SearchSysCacheTuple(PROOID, - ObjectIdGetDatum(setoid), - 0,0,0); - if (!HeapTupleIsValid(tup)) - elog(WARN, "setin: unable to define set %s", querystr); - - /* We can tell whether the set was already defined by checking - * the name. If it's GENERICSETNAME, the set is new. If it's - * "set<some oid>" it's already defined. - */ - proc = (Form_pg_proc)GETSTRUCT(tup); - if (!strcmp((char*)procname, (char*)&(proc->proname))) { - /* make the real proc name */ - sprintf(realprocname, "set%u", setoid); - - /* set up the attributes to be modified or kept the same */ - repl[0] = 'r'; - for (i = 1; i < Natts_pg_proc; i++) repl[i] = ' '; - replValue[0] = (Datum)realprocname; - for (i = 1; i < Natts_pg_proc; i++) replValue[i] = (Datum)0; - for (i = 0; i < Natts_pg_proc; i++) replNull[i] = ' '; - - /* change the pg_proc tuple */ - procrel = heap_openr(ProcedureRelationName); - RelationSetLockForWrite(procrel); - fmgr_info(ObjectIdEqualRegProcedure, - &oidKey[0].sk_func, - &oidKey[0].sk_nargs); - oidKey[0].sk_argument = ObjectIdGetDatum(setoid); - pg_proc_scan = heap_beginscan(procrel, - 0, - SelfTimeQual, - 1, - oidKey); - tup = heap_getnext(pg_proc_scan, 0, &buffer); - if (HeapTupleIsValid(tup)) { - newtup = heap_modifytuple(tup, - buffer, - procrel, - replValue, - replNull, - repl); - - /* XXX may not be necessary */ - ItemPointerCopy(&tup->t_ctid, &ipdata); - - setheapoverride(true); - heap_replace(procrel, &ipdata, newtup); - setheapoverride(false); - - setoid = newtup->t_oid; - } else - elog(WARN, "setin: could not find new set oid tuple"); - heap_endscan(pg_proc_scan); - - if (RelationGetRelationTupleForm(procrel)->relhasindex) - { - Relation idescs[Num_pg_proc_indices]; - - CatalogOpenIndices(Num_pg_proc_indices, Name_pg_proc_indices, idescs); - CatalogIndexInsert(idescs, Num_pg_proc_indices, procrel, newtup); - CatalogCloseIndices(Num_pg_proc_indices, idescs); - } - RelationUnsetLockForWrite(procrel); - heap_close(procrel); - } - return setoid; + Oid setoid; + char *procname = GENERICSETNAME; + char *fileName = "-"; + char realprocname[16]; + HeapTuple tup, + newtup = NULL; + Form_pg_proc proc; + Relation procrel; + int i; + Datum replValue[Natts_pg_proc]; + char replNull[Natts_pg_proc]; + char repl[Natts_pg_proc]; + HeapScanDesc pg_proc_scan; + Buffer buffer; + ItemPointerData ipdata; + + static ScanKeyData oidKey[1] = { + {0, ObjectIdAttributeNumber, ObjectIdEqualRegProcedure}}; + + + setoid = ProcedureCreate(procname, /* changed below, after oid known */ + true, /* returnsSet */ + typename, /* returnTypeName */ + "sql", /* languageName */ + querystr, /* sourceCode */ + fileName, /* fileName */ + false, /* canCache */ + true, /* trusted */ + 100, /* byte_pct */ + 0, /* perbyte_cpu */ + 0, /* percall_cpu */ + 100, /* outin_ratio */ + NIL, /* argList */ + whereToSendOutput); + + /* + * Since we're still inside this command of the transaction, we can't + * see the results of the procedure definition unless we pretend we've + * started the next command. (Postgres's solution to the Halloween + * problem is to not allow you to see the results of your command + * until you start the next command.) + */ + CommandCounterIncrement(); + tup = SearchSysCacheTuple(PROOID, + ObjectIdGetDatum(setoid), + 0, 0, 0); + if (!HeapTupleIsValid(tup)) + elog(WARN, "setin: unable to define set %s", querystr); + + /* + * We can tell whether the set was already defined by checking the + * name. If it's GENERICSETNAME, the set is new. If it's "set<some + * oid>" it's already defined. + */ + proc = (Form_pg_proc) GETSTRUCT(tup); + if (!strcmp((char *) procname, (char *) &(proc->proname))) + { + /* make the real proc name */ + sprintf(realprocname, "set%u", setoid); + + /* set up the attributes to be modified or kept the same */ + repl[0] = 'r'; + for (i = 1; i < Natts_pg_proc; i++) + repl[i] = ' '; + replValue[0] = (Datum) realprocname; + for (i = 1; i < Natts_pg_proc; i++) + replValue[i] = (Datum) 0; + for (i = 0; i < Natts_pg_proc; i++) + replNull[i] = ' '; + + /* change the pg_proc tuple */ + procrel = heap_openr(ProcedureRelationName); + RelationSetLockForWrite(procrel); + fmgr_info(ObjectIdEqualRegProcedure, + &oidKey[0].sk_func, + &oidKey[0].sk_nargs); + oidKey[0].sk_argument = ObjectIdGetDatum(setoid); + pg_proc_scan = heap_beginscan(procrel, + 0, + SelfTimeQual, + 1, + oidKey); + tup = heap_getnext(pg_proc_scan, 0, &buffer); + if (HeapTupleIsValid(tup)) + { + newtup = heap_modifytuple(tup, + buffer, + procrel, + replValue, + replNull, + repl); + + /* XXX may not be necessary */ + ItemPointerCopy(&tup->t_ctid, &ipdata); + + setheapoverride(true); + heap_replace(procrel, &ipdata, newtup); + setheapoverride(false); + + setoid = newtup->t_oid; + } + else + elog(WARN, "setin: could not find new set oid tuple"); + heap_endscan(pg_proc_scan); + + if (RelationGetRelationTupleForm(procrel)->relhasindex) + { + Relation idescs[Num_pg_proc_indices]; + + CatalogOpenIndices(Num_pg_proc_indices, Name_pg_proc_indices, idescs); + CatalogIndexInsert(idescs, Num_pg_proc_indices, procrel, newtup); + CatalogCloseIndices(Num_pg_proc_indices, idescs); + } + RelationUnsetLockForWrite(procrel); + heap_close(procrel); + } + return setoid; } -/* This function is a placeholder. The parser uses the OID of this +/* This function is a placeholder. The parser uses the OID of this * function to fill in the :funcid field of a set. This routine is - * never executed. At runtime, the OID of the actual set is substituted + * never executed. At runtime, the OID of the actual set is substituted * into the :funcid. */ int seteval(Oid funcoid) { - return 17; + return 17; } |