]> granicus.if.org Git - postgresql/blob - src/backend/catalog/pg_operator.c
Change parameters to func_error().
[postgresql] / src / backend / catalog / pg_operator.c
1 /*-------------------------------------------------------------------------
2  *
3  * pg_operator.c--
4  *        routines to support manipulation of the pg_operator relation
5  *
6  * Copyright (c) 1994, Regents of the University of California
7  *
8  *
9  * IDENTIFICATION
10  *        $Header: /cvsroot/pgsql/src/backend/catalog/pg_operator.c,v 1.25 1998/05/09 23:43:00 thomas Exp $
11  *
12  * NOTES
13  *        these routines moved here from commands/define.c and somewhat cleaned up.
14  *
15  *-------------------------------------------------------------------------
16  */
17 #include "postgres.h"
18
19 #include "access/heapam.h"
20 #include "catalog/catname.h"
21 #include "catalog/pg_operator.h"
22 #include "catalog/pg_proc.h"
23 #include "catalog/pg_type.h"
24 #include "fmgr.h"
25 #include "miscadmin.h"
26 #include "parser/parse_oper.h"
27 #include "storage/bufmgr.h"
28 #include "utils/builtins.h"
29 #include "utils/syscache.h"
30 #include "utils/tqual.h"
31
32 #ifndef HAVE_MEMMOVE
33 #include <regex/utils.h>
34 #else
35 #include <string.h>
36 #endif
37
38 static Oid
39 OperatorGetWithOpenRelation(Relation pg_operator_desc,
40                                                         const char *operatorName,
41                                                         Oid leftObjectId,
42                                                         Oid rightObjectId);
43 static Oid
44 OperatorGet(char *operatorName,
45                         char *leftTypeName,
46                         char *rightTypeName);
47
48 static Oid
49 OperatorShellMakeWithOpenRelation(Relation pg_operator_desc,
50                                                                   char *operatorName,
51                                                                   Oid leftObjectId,
52                                                                   Oid rightObjectId);
53 static Oid
54 OperatorShellMake(char *operatorName,
55                                   char *leftTypeName,
56                                   char *rightTypeName);
57
58 static void
59 OperatorDef(char *operatorName,
60                         int definedOK,
61                         char *leftTypeName,
62                         char *rightTypeName,
63                         char *procedureName,
64                         uint16 precedence,
65                         bool isLeftAssociative,
66                         char *commutatorName,
67                         char *negatorName,
68                         char *restrictionName,
69                         char *oinName,
70                         bool canHash,
71                         char *leftSortName,
72                         char *rightSortName);
73 static void OperatorUpd(Oid baseId, Oid commId, Oid negId);
74
75 /* ----------------------------------------------------------------
76  *              OperatorGetWithOpenRelation
77  *
78  *              preforms a scan on pg_operator for an operator tuple
79  *              with given name and left/right type oids.
80  * ----------------------------------------------------------------
81  *        pg_operator_desc      -- reldesc for pg_operator
82  *        operatorName          -- name of operator to fetch
83  *        leftObjectId          -- left oid of operator to fetch
84  *        rightObjectId         -- right oid of operator to fetch
85  */
86 static Oid
87 OperatorGetWithOpenRelation(Relation pg_operator_desc,
88                                                         const char *operatorName,
89                                                         Oid leftObjectId,
90                                                         Oid rightObjectId)
91 {
92         HeapScanDesc pg_operator_scan;
93         Oid                     operatorObjectId;
94         HeapTuple       tup;
95
96         static ScanKeyData opKey[3] = {
97                 {0, Anum_pg_operator_oprname, F_NAMEEQ},
98                 {0, Anum_pg_operator_oprleft, F_OIDEQ},
99                 {0, Anum_pg_operator_oprright, F_OIDEQ},
100         };
101
102         fmgr_info(F_NAMEEQ, &opKey[0].sk_func);
103         fmgr_info(F_OIDEQ, &opKey[1].sk_func);
104         fmgr_info(F_OIDEQ, &opKey[2].sk_func);
105         opKey[0].sk_nargs = opKey[0].sk_func.fn_nargs;
106         opKey[1].sk_nargs = opKey[1].sk_func.fn_nargs;
107         opKey[2].sk_nargs = opKey[2].sk_func.fn_nargs;
108
109         /* ----------------
110          *      form scan key
111          * ----------------
112          */
113         opKey[0].sk_argument = PointerGetDatum(operatorName);
114         opKey[1].sk_argument = ObjectIdGetDatum(leftObjectId);
115         opKey[2].sk_argument = ObjectIdGetDatum(rightObjectId);
116
117         /* ----------------
118          *      begin the scan
119          * ----------------
120          */
121         pg_operator_scan = heap_beginscan(pg_operator_desc,
122                                                                           0,
123                                                                           true,
124                                                                           3,
125                                                                           opKey);
126
127         /* ----------------
128          *      fetch the operator tuple, if it exists, and determine
129          *      the proper return oid value.
130          * ----------------
131          */
132         tup = heap_getnext(pg_operator_scan, 0, (Buffer *) 0);
133         operatorObjectId = HeapTupleIsValid(tup) ? tup->t_oid : InvalidOid;
134
135         /* ----------------
136          *      close the scan and return the oid.
137          * ----------------
138          */
139         heap_endscan(pg_operator_scan);
140
141         return
142                 operatorObjectId;
143 }
144
145 /* ----------------------------------------------------------------
146  *              OperatorGet
147  *
148  *              finds the operator associated with the specified name
149  *              and left and right type names.
150  * ----------------------------------------------------------------
151  */
152 static Oid
153 OperatorGet(char *operatorName,
154                         char *leftTypeName,
155                         char *rightTypeName)
156 {
157         Relation        pg_operator_desc;
158
159         Oid                     operatorObjectId;
160         Oid                     leftObjectId = InvalidOid;
161         Oid                     rightObjectId = InvalidOid;
162         bool            leftDefined = false;
163         bool            rightDefined = false;
164
165         /* ----------------
166          *      look up the operator types.
167          *
168          *      Note: types must be defined before operators
169          * ----------------
170          */
171         if (leftTypeName)
172         {
173                 leftObjectId = TypeGet(leftTypeName, &leftDefined);
174
175                 if (!OidIsValid(leftObjectId) || !leftDefined)
176                         elog(ERROR, "OperatorGet: left type '%s' nonexistent", leftTypeName);
177         }
178
179         if (rightTypeName)
180         {
181                 rightObjectId = TypeGet(rightTypeName, &rightDefined);
182
183                 if (!OidIsValid(rightObjectId) || !rightDefined)
184                         elog(ERROR, "OperatorGet: right type '%s' nonexistent",
185                                  rightTypeName);
186         }
187
188         if (!((OidIsValid(leftObjectId) && leftDefined) ||
189                   (OidIsValid(rightObjectId) && rightDefined)))
190                 elog(ERROR, "OperatorGet: no argument types??");
191
192         /* ----------------
193          *      open the pg_operator relation
194          * ----------------
195          */
196         pg_operator_desc = heap_openr(OperatorRelationName);
197
198         /* ----------------
199          *      get the oid for the operator with the appropriate name
200          *      and left/right types.
201          * ----------------
202          */
203         operatorObjectId = OperatorGetWithOpenRelation(pg_operator_desc,
204                                                                                                    operatorName,
205                                                                                                    leftObjectId,
206                                                                                                    rightObjectId);
207
208         /* ----------------
209          *      close the relation and return the operator oid.
210          * ----------------
211          */
212         heap_close(pg_operator_desc);
213
214         return
215                 operatorObjectId;
216 }
217
218 /* ----------------------------------------------------------------
219  *              OperatorShellMakeWithOpenRelation
220  *
221  * ----------------------------------------------------------------
222  */
223 static Oid
224 OperatorShellMakeWithOpenRelation(Relation pg_operator_desc,
225                                                                   char *operatorName,
226                                                                   Oid leftObjectId,
227                                                                   Oid rightObjectId)
228 {
229         int                     i;
230         HeapTuple       tup;
231         Datum           values[Natts_pg_operator];
232         char            nulls[Natts_pg_operator];
233         Oid                     operatorObjectId;
234         NameData        oname;
235         TupleDesc       tupDesc;
236
237         /* ----------------
238          *      initialize our nulls[] and values[] arrays
239          * ----------------
240          */
241         for (i = 0; i < Natts_pg_operator; ++i)
242         {
243                 nulls[i] = ' ';
244                 values[i] = (Datum) NULL;               /* redundant, but safe */
245         }
246
247         /* ----------------
248          *      initialize values[] with the type name and
249          * ----------------
250          */
251         i = 0;
252         namestrcpy(&oname, operatorName);
253         values[i++] = NameGetDatum(&oname);
254         values[i++] = Int32GetDatum(GetUserId());
255         values[i++] = (Datum) (uint16) 0;
256
257         values[i++] = (Datum) 'b';      /* fill oprkind with a bogus value */
258
259         values[i++] = (Datum) (bool) 0;
260         values[i++] = (Datum) (bool) 0;
261         values[i++] = ObjectIdGetDatum(leftObjectId);           /* <-- left oid */
262         values[i++] = ObjectIdGetDatum(rightObjectId);          /* <-- right oid */
263         values[i++] = ObjectIdGetDatum(InvalidOid);
264         values[i++] = ObjectIdGetDatum(InvalidOid);
265         values[i++] = ObjectIdGetDatum(InvalidOid);
266         values[i++] = ObjectIdGetDatum(InvalidOid);
267         values[i++] = ObjectIdGetDatum(InvalidOid);
268         values[i++] = ObjectIdGetDatum(InvalidOid);
269         values[i++] = ObjectIdGetDatum(InvalidOid);
270         values[i++] = ObjectIdGetDatum(InvalidOid);
271
272         /* ----------------
273          *      create a new operator tuple
274          * ----------------
275          */
276         tupDesc = pg_operator_desc->rd_att;
277
278         tup = heap_formtuple(tupDesc,
279                                                  values,
280                                                  nulls);
281
282         /* ----------------
283          *      insert our "shell" operator tuple and
284          *      close the relation
285          * ----------------
286          */
287         heap_insert(pg_operator_desc, tup);
288         operatorObjectId = tup->t_oid;
289
290         /* ----------------
291          *      free the tuple and return the operator oid
292          * ----------------
293          */
294         pfree(tup);
295
296         return
297                 operatorObjectId;
298 }
299
300 /* ----------------------------------------------------------------
301  *              OperatorShellMake
302  *
303  *              Specify operator name and left and right type names,
304  *              fill an operator struct with this info and NULL's,
305  *              call heap_insert and return the Oid
306  *              to the caller.
307  * ----------------------------------------------------------------
308  */
309 static Oid
310 OperatorShellMake(char *operatorName,
311                                   char *leftTypeName,
312                                   char *rightTypeName)
313 {
314         Relation        pg_operator_desc;
315         Oid                     operatorObjectId;
316
317         Oid                     leftObjectId = InvalidOid;
318         Oid                     rightObjectId = InvalidOid;
319         bool            leftDefined = false;
320         bool            rightDefined = false;
321
322         /* ----------------
323          *      get the left and right type oid's for this operator
324          * ----------------
325          */
326         if (leftTypeName)
327                 leftObjectId = TypeGet(leftTypeName, &leftDefined);
328
329         if (rightTypeName)
330                 rightObjectId = TypeGet(rightTypeName, &rightDefined);
331
332         if (!((OidIsValid(leftObjectId) && leftDefined) ||
333                   (OidIsValid(rightObjectId) && rightDefined)))
334                 elog(ERROR, "OperatorShellMake: no valid argument types??");
335
336         /* ----------------
337          *      open pg_operator
338          * ----------------
339          */
340         pg_operator_desc = heap_openr(OperatorRelationName);
341
342         /* ----------------
343          *      add a "shell" operator tuple to the operator relation
344          *      and recover the shell tuple's oid.
345          * ----------------
346          */
347         operatorObjectId =
348                 OperatorShellMakeWithOpenRelation(pg_operator_desc,
349                                                                                   operatorName,
350                                                                                   leftObjectId,
351                                                                                   rightObjectId);
352         /* ----------------
353          *      close the operator relation and return the oid.
354          * ----------------
355          */
356         heap_close(pg_operator_desc);
357
358         return
359                 operatorObjectId;
360 }
361
362 /* --------------------------------
363  * OperatorDef
364  *
365  * This routine gets complicated because it allows the user to
366  * specify operators that do not exist.  For example, if operator
367  * "op" is being defined, the negator operator "negop" and the
368  * commutator "commop" can also be defined without specifying
369  * any information other than their names.      Since in order to
370  * add "op" to the PG_OPERATOR catalog, all the Oid's for these
371  * operators must be placed in the fields of "op", a forward
372  * declaration is done on the commutator and negator operators.
373  * This is called creating a shell, and its main effect is to
374  * create a tuple in the PG_OPERATOR catalog with minimal
375  * information about the operator (just its name and types).
376  * Forward declaration is used only for this purpose, it is
377  * not available to the user as it is for type definition.
378  *
379  * Algorithm:
380  *
381  * check if operator already defined
382  *        if so issue error if not definedOk, this is a duplicate
383  *        but if definedOk, save the Oid -- filling in a shell
384  * get the attribute types from relation descriptor for pg_operator
385  * assign values to the fields of the operator:
386  *       operatorName
387  *       owner id (simply the user id of the caller)
388  *       precedence
389  *       operator "kind" either "b" for binary or "l" for left unary
390  *       isLeftAssociative boolean
391  *       canHash boolean
392  *       leftTypeObjectId -- type must already be defined
393  *       rightTypeObjectId -- this is optional, enter ObjectId=0 if none specified
394  *       resultType -- defer this, since it must be determined from
395  *                                 the pg_procedure catalog
396  *       commutatorObjectId -- if this is NULL, enter ObjectId=0
397  *                                        else if this already exists, enter it's ObjectId
398  *                                        else if this does not yet exist, and is not
399  *                                              the same as the main operatorName, then create
400  *                                              a shell and enter the new ObjectId
401  *                                        else if this does not exist but IS the same
402  *                                              name as the main operator, set the ObjectId=0.
403  *                                              Later OperatorCreate will make another call
404  *                                              to OperatorDef which will cause this field
405  *                                              to be filled in (because even though the names
406  *                                              will be switched, they are the same name and
407  *                                              at this point this ObjectId will then be defined)
408  *       negatorObjectId   -- same as for commutatorObjectId
409  *       leftSortObjectId  -- same as for commutatorObjectId
410  *       rightSortObjectId -- same as for commutatorObjectId
411  *       operatorProcedure -- must access the pg_procedure catalog to get the
412  *                                 ObjectId of the procedure that actually does the operator
413  *                                 actions this is required.  Do an amgetattr to find out the
414  *                                 return type of the procedure
415  *       restrictionProcedure -- must access the pg_procedure catalog to get
416  *                                 the ObjectId but this is optional
417  *       joinProcedure -- same as restrictionProcedure
418  * now either insert or replace the operator into the pg_operator catalog
419  * if the operator shell is being filled in
420  *       access the catalog in order to get a valid buffer
421  *       create a tuple using ModifyHeapTuple
422  *       get the t_ctid from the modified tuple and call RelationReplaceHeapTuple
423  * else if a new operator is being created
424  *       create a tuple using heap_formtuple
425  *       call heap_insert
426  * --------------------------------
427  *              "X" indicates an optional argument (i.e. one that can be NULL)
428  *              operatorName;                   -- operator name
429  *              definedOK;                              -- operator can already have an oid?
430  *              leftTypeName;                   -- X left type name
431  *              rightTypeName;                  -- X right type name
432  *              procedureName;                  -- procedure oid for operator code
433  *              precedence;                             -- operator precedence
434  *              isLeftAssociative;              -- operator is left associative?
435  *              commutatorName;                 -- X commutator operator name
436  *              negatorName;                    -- X negator operator name
437  *              restrictionName;                -- X restriction sel. procedure name
438  *              joinName;                               -- X join sel. procedure name
439  *              canHash;                                -- possible hash operator?
440  *              leftSortName;                   -- X left sort operator
441  *              rightSortName;                  -- X right sort operator
442  */
443 static void
444 OperatorDef(char *operatorName,
445                         int definedOK,
446                         char *leftTypeName,
447                         char *rightTypeName,
448                         char *procedureName,
449                         uint16 precedence,
450                         bool isLeftAssociative,
451                         char *commutatorName,
452                         char *negatorName,
453                         char *restrictionName,
454                         char *joinName,
455                         bool canHash,
456                         char *leftSortName,
457                         char *rightSortName)
458 {
459         int                     i,
460                                 j;
461         Relation        pg_operator_desc;
462
463         HeapScanDesc pg_operator_scan;
464         HeapTuple       tup;
465         Buffer          buffer;
466         ItemPointerData itemPointerData;
467         char            nulls[Natts_pg_operator];
468         char            replaces[Natts_pg_operator];
469         Datum           values[Natts_pg_operator];
470         Oid                     other_oid = 0;
471         Oid                     operatorObjectId;
472         Oid                     leftTypeId = InvalidOid;
473         Oid                     rightTypeId = InvalidOid;
474         Oid                     commutatorId = InvalidOid;
475         Oid                     negatorId = InvalidOid;
476         bool            leftDefined = false;
477         bool            rightDefined = false;
478         char       *name[4];
479         Oid                     typeId[8];
480         int                     nargs;
481         NameData                oname;
482         TupleDesc       tupDesc;
483
484         static ScanKeyData opKey[3] = {
485                 {0, Anum_pg_operator_oprname, F_NAMEEQ},
486                 {0, Anum_pg_operator_oprleft, F_OIDEQ},
487                 {0, Anum_pg_operator_oprright, F_OIDEQ},
488         };
489
490         fmgr_info(F_NAMEEQ, &opKey[0].sk_func);
491         fmgr_info(F_OIDEQ, &opKey[1].sk_func);
492         fmgr_info(F_OIDEQ, &opKey[2].sk_func);
493         opKey[0].sk_nargs = opKey[0].sk_func.fn_nargs;
494         opKey[1].sk_nargs = opKey[1].sk_func.fn_nargs;
495         opKey[2].sk_nargs = opKey[2].sk_func.fn_nargs;
496
497         operatorObjectId = OperatorGet(operatorName,
498                                                                    leftTypeName,
499                                                                    rightTypeName);
500
501         if (OidIsValid(operatorObjectId) && !definedOK)
502                 elog(ERROR, "OperatorDef: operator \"%s\" already defined",
503                          operatorName);
504
505         if (leftTypeName)
506                 leftTypeId = TypeGet(leftTypeName, &leftDefined);
507
508         if (rightTypeName)
509                 rightTypeId = TypeGet(rightTypeName, &rightDefined);
510
511         if (!((OidIsValid(leftTypeId && leftDefined)) ||
512                   (OidIsValid(rightTypeId && rightDefined))))
513                 elog(ERROR, "OperatorGet: no argument types??");
514
515         for (i = 0; i < Natts_pg_operator; ++i)
516         {
517                 values[i] = (Datum) NULL;
518                 replaces[i] = 'r';
519                 nulls[i] = ' ';
520         }
521
522         /* ----------------
523          * Look up registered procedures -- find the return type
524          * of procedureName to place in "result" field.
525          * Do this before shells are created so we don't
526          * have to worry about deleting them later.
527          * ----------------
528          */
529         MemSet(typeId, 0, 8 * sizeof(Oid));
530         if (!leftTypeName)
531         {
532                 typeId[0] = rightTypeId;
533                 nargs = 1;
534         }
535         else if (!rightTypeName)
536         {
537                 typeId[0] = leftTypeId;
538                 nargs = 1;
539         }
540         else
541         {
542                 typeId[0] = leftTypeId;
543                 typeId[1] = rightTypeId;
544                 nargs = 2;
545         }
546         tup = SearchSysCacheTuple(PRONAME,
547                                                           PointerGetDatum(procedureName),
548                                                           Int32GetDatum(nargs),
549                                                           PointerGetDatum(typeId),
550                                                           0);
551
552         if (!PointerIsValid(tup))
553                 func_error("OperatorDef", procedureName, nargs, typeId, NULL);
554
555         values[Anum_pg_operator_oprcode - 1] = ObjectIdGetDatum(tup->t_oid);
556         values[Anum_pg_operator_oprresult - 1] =
557                 ObjectIdGetDatum(((Form_pg_proc)
558                                                   GETSTRUCT(tup))->prorettype);
559
560         /* ----------------
561          *      find restriction
562          * ----------------
563          */
564         if (restrictionName)
565         {                                                       /* optional */
566                 MemSet(typeId, 0, 8 * sizeof(Oid));
567                 typeId[0] = OIDOID;             /* operator OID */
568                 typeId[1] = OIDOID;             /* relation OID */
569                 typeId[2] = INT2OID;    /* attribute number */
570                 typeId[3] = 0;                  /* value - can be any type      */
571                 typeId[4] = INT4OID;    /* flags - left or right selectivity */
572                 tup = SearchSysCacheTuple(PRONAME,
573                                                                   PointerGetDatum(restrictionName),
574                                                                   Int32GetDatum(5),
575                                                                   PointerGetDatum(typeId),
576                                                                   0);
577                 if (!HeapTupleIsValid(tup))
578                         func_error("OperatorDef", restrictionName, 5, typeId, NULL);
579
580                 values[Anum_pg_operator_oprrest - 1] = ObjectIdGetDatum(tup->t_oid);
581         }
582         else
583                 values[Anum_pg_operator_oprrest - 1] = ObjectIdGetDatum(InvalidOid);
584
585         /* ----------------
586          *      find join - only valid for binary operators
587          * ----------------
588          */
589         if (joinName)
590         {                                                       /* optional */
591                 MemSet(typeId, 0, 8 * sizeof(Oid));
592                 typeId[0] = OIDOID;             /* operator OID */
593                 typeId[1] = OIDOID;             /* relation OID 1 */
594                 typeId[2] = INT2OID;    /* attribute number 1 */
595                 typeId[3] = OIDOID;             /* relation OID 2 */
596                 typeId[4] = INT2OID;    /* attribute number 2 */
597
598                 tup = SearchSysCacheTuple(PRONAME,
599                                                                   PointerGetDatum(joinName),
600                                                                   Int32GetDatum(5),
601                                                                   PointerGetDatum(typeId),
602                                                                   0);
603                 if (!HeapTupleIsValid(tup))
604                         func_error("OperatorDef", joinName, 5, typeId, NULL);
605
606                 values[Anum_pg_operator_oprjoin - 1] = ObjectIdGetDatum(tup->t_oid);
607         }
608         else
609                 values[Anum_pg_operator_oprjoin - 1] = ObjectIdGetDatum(InvalidOid);
610
611         /* ----------------
612          * set up values in the operator tuple
613          * ----------------
614          */
615         i = 0;
616         namestrcpy(&oname, operatorName);
617         values[i++] = NameGetDatum(&oname);
618         values[i++] = Int32GetDatum(GetUserId());
619         values[i++] = UInt16GetDatum(precedence);
620         values[i++] = leftTypeName ? (rightTypeName ? 'b' : 'r') : 'l';
621         values[i++] = Int8GetDatum(isLeftAssociative);
622         values[i++] = Int8GetDatum(canHash);
623         values[i++] = ObjectIdGetDatum(leftTypeId);
624         values[i++] = ObjectIdGetDatum(rightTypeId);
625
626         ++i;                                            /* Skip "prorettype", this was done above */
627
628         /*
629          * Set up the other operators.  If they do not currently exist, set up
630          * shells in order to get ObjectId's and call OperatorDef again later
631          * to fill in the shells.
632          */
633         name[0] = commutatorName;
634         name[1] = negatorName;
635         name[2] = leftSortName;
636         name[3] = rightSortName;
637
638         for (j = 0; j < 4; ++j)
639         {
640                 if (name[j])
641                 {
642
643                         /* for the commutator, switch order of arguments */
644                         if (j == 0)
645                         {
646                                 other_oid = OperatorGet(name[j], rightTypeName, leftTypeName);
647                                 commutatorId = other_oid;
648                         }
649                         else
650                         {
651                                 other_oid = OperatorGet(name[j], leftTypeName, rightTypeName);
652                                 if (j == 1)
653                                         negatorId = other_oid;
654                         }
655
656                         if (OidIsValid(other_oid))      /* already in catalogs */
657                                 values[i++] = ObjectIdGetDatum(other_oid);
658                         else if (strcmp(operatorName, name[j]) != 0)
659                         {
660                                 /* not in catalogs, different from operator */
661
662                                 /* for the commutator, switch order of arguments */
663                                 if (j == 0)
664                                 {
665                                         other_oid = OperatorShellMake(name[j],
666                                                                                                   rightTypeName,
667                                                                                                   leftTypeName);
668                                 }
669                                 else
670                                 {
671                                         other_oid = OperatorShellMake(name[j],
672                                                                                                   leftTypeName,
673                                                                                                   rightTypeName);
674                                 }
675
676                                 if (!OidIsValid(other_oid))
677                                         elog(ERROR,
678                                                  "OperatorDef: can't create operator '%s'",
679                                                  name[j]);
680                                 values[i++] = ObjectIdGetDatum(other_oid);
681
682                         }
683                         else
684 /* not in catalogs, same as operator ??? */
685                                 values[i++] = ObjectIdGetDatum(InvalidOid);
686
687                 }
688                 else
689 /* new operator is optional */
690                         values[i++] = ObjectIdGetDatum(InvalidOid);
691         }
692
693         /* last three fields were filled in first */
694
695         /*
696          * If we are adding to an operator shell, get its t_ctid and a buffer.
697          */
698         pg_operator_desc = heap_openr(OperatorRelationName);
699
700         if (operatorObjectId)
701         {
702                 opKey[0].sk_argument = PointerGetDatum(operatorName);
703                 opKey[1].sk_argument = ObjectIdGetDatum(leftTypeId);
704                 opKey[2].sk_argument = ObjectIdGetDatum(rightTypeId);
705
706                 pg_operator_scan = heap_beginscan(pg_operator_desc,
707                                                                                   0,
708                                                                                   true,
709                                                                                   3,
710                                                                                   opKey);
711
712                 tup = heap_getnext(pg_operator_scan, 0, &buffer);
713                 if (HeapTupleIsValid(tup))
714                 {
715                         tup = heap_modifytuple(tup,
716                                                                    buffer,
717                                                                    pg_operator_desc,
718                                                                    values,
719                                                                    nulls,
720                                                                    replaces);
721
722                         ItemPointerCopy(&tup->t_ctid, &itemPointerData);
723                         setheapoverride(true);
724                         heap_replace(pg_operator_desc, &itemPointerData, tup);
725                         setheapoverride(false);
726                 }
727                 else
728                         elog(ERROR, "OperatorDef: no operator %d", other_oid);
729
730                 heap_endscan(pg_operator_scan);
731
732         }
733         else
734         {
735                 tupDesc = pg_operator_desc->rd_att;
736                 tup = heap_formtuple(tupDesc, values, nulls);
737
738                 heap_insert(pg_operator_desc, tup);
739                 operatorObjectId = tup->t_oid;
740         }
741
742         heap_close(pg_operator_desc);
743
744         /*
745          * It's possible that we're creating a skeleton operator here for the
746          * commute or negate attributes of a real operator.  If we are, then
747          * we're done.  If not, we may need to update the negator and
748          * commutator for this attribute.  The reason for this is that the
749          * user may want to create two operators (say < and >=).  When he
750          * defines <, if he uses >= as the negator or commutator, he won't be
751          * able to insert it later, since (for some reason) define operator
752          * defines it for him.  So what he does is to define > without a
753          * negator or commutator.  Then he defines >= with < as the negator
754          * and commutator.      As a side effect, this will update the > tuple if
755          * it has no commutator or negator defined.
756          *
757          * Alstublieft, Tom Vijlbrief.
758          */
759         if (!definedOK)
760                 OperatorUpd(operatorObjectId, commutatorId, negatorId);
761 }
762
763 /* ----------------------------------------------------------------
764  * OperatorUpd
765  *
766  *      For a given operator, look up its negator and commutator operators.
767  *      If they are defined, but their negator and commutator operators
768  *      (respectively) are not, then use the new operator for neg and comm.
769  *      This solves a problem for users who need to insert two new operators
770  *      which are the negator or commutator of each other.
771  * ----------------------------------------------------------------
772  */
773 static void
774 OperatorUpd(Oid baseId, Oid commId, Oid negId)
775 {
776         int                     i;
777         Relation        pg_operator_desc;
778         HeapScanDesc pg_operator_scan;
779         HeapTuple       tup;
780         Buffer          buffer;
781         ItemPointerData itemPointerData;
782         char            nulls[Natts_pg_operator];
783         char            replaces[Natts_pg_operator];
784         Datum           values[Natts_pg_operator];
785
786         static ScanKeyData opKey[1] = {
787                 {0, ObjectIdAttributeNumber, F_OIDEQ},
788         };
789
790         fmgr_info(F_OIDEQ, &opKey[0].sk_func);
791         opKey[0].sk_nargs = opKey[0].sk_func.fn_nargs;
792
793         for (i = 0; i < Natts_pg_operator; ++i)
794         {
795                 values[i] = (Datum) NULL;
796                 replaces[i] = ' ';
797                 nulls[i] = ' ';
798         }
799
800         pg_operator_desc = heap_openr(OperatorRelationName);
801
802         /* check and update the commutator, if necessary */
803         opKey[0].sk_argument = ObjectIdGetDatum(commId);
804
805         pg_operator_scan = heap_beginscan(pg_operator_desc,
806                                                                           0,
807                                                                           true,
808                                                                           1,
809                                                                           opKey);
810
811         tup = heap_getnext(pg_operator_scan, 0, &buffer);
812
813         /* if the commutator and negator are the same operator, do one update */
814         if (commId == negId)
815         {
816                 if (HeapTupleIsValid(tup))
817                 {
818                         OperatorTupleForm t;
819
820                         t = (OperatorTupleForm) GETSTRUCT(tup);
821                         if (!OidIsValid(t->oprcom)
822                                 || !OidIsValid(t->oprnegate))
823                         {
824
825                                 if (!OidIsValid(t->oprnegate))
826                                 {
827                                         values[Anum_pg_operator_oprnegate - 1] =
828                                                 ObjectIdGetDatum(baseId);
829                                         replaces[Anum_pg_operator_oprnegate - 1] = 'r';
830                                 }
831
832                                 if (!OidIsValid(t->oprcom))
833                                 {
834                                         values[Anum_pg_operator_oprcom - 1] =
835                                                 ObjectIdGetDatum(baseId);
836                                         replaces[Anum_pg_operator_oprcom - 1] = 'r';
837                                 }
838
839                                 tup = heap_modifytuple(tup,
840                                                                            buffer,
841                                                                            pg_operator_desc,
842                                                                            values,
843                                                                            nulls,
844                                                                            replaces);
845
846                                 ItemPointerCopy(&tup->t_ctid, &itemPointerData);
847
848                                 setheapoverride(true);
849                                 heap_replace(pg_operator_desc, &itemPointerData, tup);
850                                 setheapoverride(false);
851
852                         }
853                 }
854                 heap_endscan(pg_operator_scan);
855
856                 heap_close(pg_operator_desc);
857
858                 /* release the buffer properly */
859                 if (BufferIsValid(buffer))
860                         ReleaseBuffer(buffer);
861
862                 return;
863         }
864
865         /* if commutator and negator are different, do two updates */
866         if (HeapTupleIsValid(tup) &&
867                 !(OidIsValid(((OperatorTupleForm) GETSTRUCT(tup))->oprcom)))
868         {
869                 values[Anum_pg_operator_oprcom - 1] = ObjectIdGetDatum(baseId);
870                 replaces[Anum_pg_operator_oprcom - 1] = 'r';
871                 tup = heap_modifytuple(tup,
872                                                            buffer,
873                                                            pg_operator_desc,
874                                                            values,
875                                                            nulls,
876                                                            replaces);
877
878                 ItemPointerCopy(&tup->t_ctid, &itemPointerData);
879                 setheapoverride(true);
880                 heap_replace(pg_operator_desc, &itemPointerData, tup);
881                 setheapoverride(false);
882
883                 values[Anum_pg_operator_oprcom - 1] = (Datum) NULL;
884                 replaces[Anum_pg_operator_oprcom - 1] = ' ';
885
886                 /* release the buffer properly */
887                 if (BufferIsValid(buffer))
888                         ReleaseBuffer(buffer);
889
890         }
891
892         /* check and update the negator, if necessary */
893         opKey[0].sk_argument = ObjectIdGetDatum(negId);
894
895         pg_operator_scan = heap_beginscan(pg_operator_desc,
896                                                                           0,
897                                                                           true,
898                                                                           1,
899                                                                           opKey);
900
901         tup = heap_getnext(pg_operator_scan, 0, &buffer);
902         if (HeapTupleIsValid(tup) &&
903                 !(OidIsValid(((OperatorTupleForm) GETSTRUCT(tup))->oprnegate)))
904         {
905                 values[Anum_pg_operator_oprnegate - 1] = ObjectIdGetDatum(baseId);
906                 replaces[Anum_pg_operator_oprnegate - 1] = 'r';
907                 tup = heap_modifytuple(tup,
908                                                            buffer,
909                                                            pg_operator_desc,
910                                                            values,
911                                                            nulls,
912                                                            replaces);
913
914                 ItemPointerCopy(&tup->t_ctid, &itemPointerData);
915
916                 setheapoverride(true);
917                 heap_replace(pg_operator_desc, &itemPointerData, tup);
918                 setheapoverride(false);
919         }
920
921         /* release the buffer properly */
922         if (BufferIsValid(buffer))
923                 ReleaseBuffer(buffer);
924
925         heap_endscan(pg_operator_scan);
926
927         heap_close(pg_operator_desc);
928 }
929
930
931 /* ----------------------------------------------------------------
932  * OperatorCreate
933  *
934  * Algorithm:
935  *
936  *      Since the commutator, negator, leftsortoperator, and rightsortoperator
937  *      can be defined implicitly through OperatorCreate, must check before
938  *      the main operator is added to see if they already exist.  If they
939  *      do not already exist, OperatorDef makes a "shell" for each undefined
940  *      one, and then OperatorCreate must call OperatorDef again to fill in
941  *      each shell.  All this is necessary in order to get the right ObjectId's
942  *      filled into the right fields.
943  *
944  *      The "definedOk" flag indicates that OperatorDef can be called on
945  *      the operator even though it already has an entry in the PG_OPERATOR
946  *      relation.  This allows shells to be filled in.  The user cannot
947  *      forward declare operators, this is strictly an internal capability.
948  *
949  *      When the shells are filled in by subsequent calls to OperatorDef,
950  *      all the fields are the same as the definition of the original operator
951  *      except that the target operator name and the original operatorName
952  *      are switched.  In the case of commutator and negator, special flags
953  *      are set to indicate their status, telling the executor(?) that
954  *      the operands are to be switched, or the outcome of the procedure
955  *      negated.
956  *
957  * ************************* NOTE NOTE NOTE ******************************
958  *
959  *      If the execution of this utility is interrupted, the pg_operator
960  *      catalog may be left in an inconsistent state.  Similarly, if
961  *      something is removed from the pg_operator, pg_type, or pg_procedure
962  *      catalog while this is executing, the results may be inconsistent.
963  * ----------------------------------------------------------------
964  *
965  * "X" indicates an optional argument (i.e. one that can be NULL)
966  *              operatorName;                   -- operator name
967  *              leftTypeName;                   -- X left type name
968  *              rightTypeName;                  -- X right type name
969  *              procedureName;                  -- procedure for operator
970  *              precedence;                             -- operator precedence
971  *              isLeftAssociative;              -- operator is left associative
972  *              commutatorName;                 -- X commutator operator name
973  *              negatorName;                    -- X negator operator name
974  *              restrictionName;                -- X restriction sel. procedure
975  *              joinName;                               -- X join sel. procedure name
976  *              canHash;                                -- operator hashes
977  *              leftSortName;                   -- X left sort operator
978  *              rightSortName;                  -- X right sort operator
979  *
980  */
981 void
982 OperatorCreate(char *operatorName,
983                            char *leftTypeName,
984                            char *rightTypeName,
985                            char *procedureName,
986                            uint16 precedence,
987                            bool isLeftAssociative,
988                            char *commutatorName,
989                            char *negatorName,
990                            char *restrictionName,
991                            char *joinName,
992                            bool canHash,
993                            char *leftSortName,
994                            char *rightSortName)
995 {
996         Oid                     commObjectId,
997                                 negObjectId;
998         Oid                     leftSortObjectId,
999                                 rightSortObjectId;
1000         int                     definedOK;
1001
1002         if (!leftTypeName && !rightTypeName)
1003                 elog(ERROR, "OperatorCreate : at least one of leftarg or rightarg must be defined");
1004
1005         /* ----------------
1006          *      get the oid's of the operator's associated operators, if possible.
1007          * ----------------
1008          */
1009         if (commutatorName)
1010                 commObjectId = OperatorGet(commutatorName,              /* commute type order */
1011                                                                    rightTypeName,
1012                                                                    leftTypeName);
1013         else
1014                 commObjectId = 0;
1015
1016         if (negatorName)
1017                 negObjectId = OperatorGet(negatorName,
1018                                                                   leftTypeName,
1019                                                                   rightTypeName);
1020         else
1021                 negObjectId = 0;
1022
1023         if (leftSortName)
1024                 leftSortObjectId = OperatorGet(leftSortName,
1025                                                                            leftTypeName,
1026                                                                            rightTypeName);
1027         else
1028                 leftSortObjectId = 0;
1029
1030         if (rightSortName)
1031                 rightSortObjectId = OperatorGet(rightSortName,
1032                                                                                 rightTypeName,
1033                                                                                 leftTypeName);
1034         else
1035                 rightSortObjectId = 0;
1036
1037         /* ----------------
1038          *      Use OperatorDef() to define the specified operator and
1039          *      also create shells for the operator's associated operators
1040          *      if they don't already exist.
1041          *
1042          *      This operator should not be defined yet.
1043          * ----------------
1044          */
1045         definedOK = 0;
1046
1047         OperatorDef(operatorName,
1048                                 definedOK,
1049                                 leftTypeName,
1050                                 rightTypeName,
1051                                 procedureName,
1052                                 precedence,
1053                                 isLeftAssociative,
1054                                 commutatorName,
1055                                 negatorName,
1056                                 restrictionName,
1057                                 joinName,
1058                                 canHash,
1059                                 leftSortName,
1060                                 rightSortName);
1061
1062         /* ----------------
1063          *      Now fill in information in the operator's associated
1064          *      operators.
1065          *
1066          *      These operators should be defined or have shells defined.
1067          * ----------------
1068          */
1069         definedOK = 1;
1070
1071         if (!OidIsValid(commObjectId) && commutatorName)
1072                 OperatorDef(commutatorName,
1073                                         definedOK,
1074                                         leftTypeName,           /* should eventually */
1075                                         rightTypeName,          /* commute order */
1076                                         procedureName,
1077                                         precedence,
1078                                         isLeftAssociative,
1079                                         operatorName,           /* commutator */
1080                                         negatorName,
1081                                         restrictionName,
1082                                         joinName,
1083                                         canHash,
1084                                         rightSortName,
1085                                         leftSortName);
1086
1087         if (negatorName && !OidIsValid(negObjectId))
1088                 OperatorDef(negatorName,
1089                                         definedOK,
1090                                         leftTypeName,
1091                                         rightTypeName,
1092                                         procedureName,
1093                                         precedence,
1094                                         isLeftAssociative,
1095                                         commutatorName,
1096                                         operatorName,           /* negator */
1097                                         restrictionName,
1098                                         joinName,
1099                                         canHash,
1100                                         leftSortName,
1101                                         rightSortName);
1102
1103         if (leftSortName && !OidIsValid(leftSortObjectId))
1104                 OperatorDef(leftSortName,
1105                                         definedOK,
1106                                         leftTypeName,
1107                                         rightTypeName,
1108                                         procedureName,
1109                                         precedence,
1110                                         isLeftAssociative,
1111                                         commutatorName,
1112                                         negatorName,
1113                                         restrictionName,
1114                                         joinName,
1115                                         canHash,
1116                                         operatorName,           /* left sort */
1117                                         rightSortName);
1118
1119         if (rightSortName && !OidIsValid(rightSortObjectId))
1120                 OperatorDef(rightSortName,
1121                                         definedOK,
1122                                         leftTypeName,
1123                                         rightTypeName,
1124                                         procedureName,
1125                                         precedence,
1126                                         isLeftAssociative,
1127                                         commutatorName,
1128                                         negatorName,
1129                                         restrictionName,
1130                                         joinName,
1131                                         canHash,
1132                                         leftSortName,
1133                                         operatorName);          /* right sort */
1134 }