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