pg_operator.c
上传用户:blenddy
上传日期:2007-01-07
资源大小:6495k
文件大小:30k
源码类别:

数据库系统

开发平台:

Unix_Linux

  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: /usr/local/cvsroot/pgsql/src/backend/catalog/pg_operator.c,v 1.37.2.1 1999/08/02 05:56:55 scrappy 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. #include "access/heapam.h"
  19. #include "catalog/catname.h"
  20. #include "catalog/pg_operator.h"
  21. #include "catalog/pg_proc.h"
  22. #include "catalog/pg_type.h"
  23. #include "miscadmin.h"
  24. #include "parser/parse_func.h"
  25. #include "utils/builtins.h"
  26. #include "utils/syscache.h"
  27. static Oid OperatorGetWithOpenRelation(Relation pg_operator_desc,
  28. const char *operatorName,
  29. Oid leftObjectId,
  30. Oid rightObjectId,
  31. bool *defined);
  32. static Oid OperatorGet(char *operatorName,
  33. char *leftTypeName,
  34. char *rightTypeName,
  35. bool *defined);
  36. static Oid OperatorShellMakeWithOpenRelation(Relation pg_operator_desc,
  37.   char *operatorName,
  38.   Oid leftObjectId,
  39.   Oid rightObjectId);
  40. static Oid OperatorShellMake(char *operatorName,
  41.   char *leftTypeName,
  42.   char *rightTypeName);
  43. static void OperatorDef(char *operatorName,
  44. char *leftTypeName,
  45. char *rightTypeName,
  46. char *procedureName,
  47. uint16 precedence,
  48. bool isLeftAssociative,
  49. char *commutatorName,
  50. char *negatorName,
  51. char *restrictionName,
  52. char *oinName,
  53. bool canHash,
  54. char *leftSortName,
  55. char *rightSortName);
  56. static void OperatorUpd(Oid baseId, Oid commId, Oid negId);
  57. /* ----------------------------------------------------------------
  58.  * OperatorGetWithOpenRelation
  59.  *
  60.  * preforms a scan on pg_operator for an operator tuple
  61.  * with given name and left/right type oids.
  62.  * ----------------------------------------------------------------
  63.  *   pg_operator_desc -- reldesc for pg_operator
  64.  *   operatorName -- name of operator to fetch
  65.  *   leftObjectId -- left data type oid of operator to fetch
  66.  *   rightObjectId -- right data type oid of operator to fetch
  67.  *   defined -- set TRUE if defined (not a shell)
  68.  */
  69. static Oid
  70. OperatorGetWithOpenRelation(Relation pg_operator_desc,
  71. const char *operatorName,
  72. Oid leftObjectId,
  73. Oid rightObjectId,
  74. bool *defined)
  75. {
  76. HeapScanDesc pg_operator_scan;
  77. Oid operatorObjectId;
  78. HeapTuple tup;
  79. static ScanKeyData opKey[3] = {
  80. {0, Anum_pg_operator_oprname, F_NAMEEQ},
  81. {0, Anum_pg_operator_oprleft, F_OIDEQ},
  82. {0, Anum_pg_operator_oprright, F_OIDEQ},
  83. };
  84. fmgr_info(F_NAMEEQ, &opKey[0].sk_func);
  85. fmgr_info(F_OIDEQ, &opKey[1].sk_func);
  86. fmgr_info(F_OIDEQ, &opKey[2].sk_func);
  87. opKey[0].sk_nargs = opKey[0].sk_func.fn_nargs;
  88. opKey[1].sk_nargs = opKey[1].sk_func.fn_nargs;
  89. opKey[2].sk_nargs = opKey[2].sk_func.fn_nargs;
  90. /* ----------------
  91.  * form scan key
  92.  * ----------------
  93.  */
  94. opKey[0].sk_argument = PointerGetDatum(operatorName);
  95. opKey[1].sk_argument = ObjectIdGetDatum(leftObjectId);
  96. opKey[2].sk_argument = ObjectIdGetDatum(rightObjectId);
  97. /* ----------------
  98.  * begin the scan
  99.  * ----------------
  100.  */
  101. pg_operator_scan = heap_beginscan(pg_operator_desc,
  102.   0,
  103.   SnapshotSelf, /* no cache? */
  104.   3,
  105.   opKey);
  106. /* ----------------
  107.  * fetch the operator tuple, if it exists, and determine
  108.  * the proper return oid value.
  109.  * ----------------
  110.  */
  111. tup = heap_getnext(pg_operator_scan, 0);
  112. if (HeapTupleIsValid(tup))
  113. {
  114. regproc oprcode = ((Form_pg_operator) GETSTRUCT(tup))->oprcode;
  115. operatorObjectId = tup->t_data->t_oid;
  116. *defined = RegProcedureIsValid(oprcode);
  117. }
  118. else
  119. {
  120. operatorObjectId = InvalidOid;
  121. *defined = false;
  122. }
  123. /* ----------------
  124.  * close the scan and return the oid.
  125.  * ----------------
  126.  */
  127. heap_endscan(pg_operator_scan);
  128. return operatorObjectId;
  129. }
  130. /* ----------------------------------------------------------------
  131.  * OperatorGet
  132.  *
  133.  * finds the operator associated with the specified name
  134.  * and left and right type names.
  135.  * ----------------------------------------------------------------
  136.  */
  137. static Oid
  138. OperatorGet(char *operatorName,
  139. char *leftTypeName,
  140. char *rightTypeName,
  141. bool *defined)
  142. {
  143. Relation pg_operator_desc;
  144. Oid operatorObjectId;
  145. Oid leftObjectId = InvalidOid;
  146. Oid rightObjectId = InvalidOid;
  147. bool leftDefined = false;
  148. bool rightDefined = false;
  149. /* ----------------
  150.  * look up the operator data types.
  151.  *
  152.  * Note: types must be defined before operators
  153.  * ----------------
  154.  */
  155. if (leftTypeName)
  156. {
  157. leftObjectId = TypeGet(leftTypeName, &leftDefined);
  158. if (!OidIsValid(leftObjectId) || !leftDefined)
  159. elog(ERROR, "OperatorGet: left type '%s' nonexistent",
  160.  leftTypeName);
  161. }
  162. if (rightTypeName)
  163. {
  164. rightObjectId = TypeGet(rightTypeName, &rightDefined);
  165. if (!OidIsValid(rightObjectId) || !rightDefined)
  166. elog(ERROR, "OperatorGet: right type '%s' nonexistent",
  167.  rightTypeName);
  168. }
  169. if (!((OidIsValid(leftObjectId) && leftDefined) ||
  170.   (OidIsValid(rightObjectId) && rightDefined)))
  171. elog(ERROR, "OperatorGet: must have at least one argument type");
  172. /* ----------------
  173.  * open the pg_operator relation
  174.  * ----------------
  175.  */
  176. pg_operator_desc = heap_openr(OperatorRelationName);
  177. /* ----------------
  178.  * get the oid for the operator with the appropriate name
  179.  * and left/right types.
  180.  * ----------------
  181.  */
  182. operatorObjectId = OperatorGetWithOpenRelation(pg_operator_desc,
  183.    operatorName,
  184.    leftObjectId,
  185.    rightObjectId,
  186.    defined);
  187. /* ----------------
  188.  * close the relation and return the operator oid.
  189.  * ----------------
  190.  */
  191. heap_close(pg_operator_desc);
  192. return operatorObjectId;
  193. }
  194. /* ----------------------------------------------------------------
  195.  * OperatorShellMakeWithOpenRelation
  196.  *
  197.  * ----------------------------------------------------------------
  198.  */
  199. static Oid
  200. OperatorShellMakeWithOpenRelation(Relation pg_operator_desc,
  201.   char *operatorName,
  202.   Oid leftObjectId,
  203.   Oid rightObjectId)
  204. {
  205. int i;
  206. HeapTuple tup;
  207. Datum values[Natts_pg_operator];
  208. char nulls[Natts_pg_operator];
  209. Oid operatorObjectId;
  210. NameData oname;
  211. TupleDesc tupDesc;
  212. /* ----------------
  213.  * initialize our *nulls and *values arrays
  214.  * ----------------
  215.  */
  216. for (i = 0; i < Natts_pg_operator; ++i)
  217. {
  218. nulls[i] = ' ';
  219. values[i] = (Datum) NULL; /* redundant, but safe */
  220. }
  221. /* ----------------
  222.  * initialize *values with the operator name and input data types.
  223.  * Note that oprcode is set to InvalidOid, indicating it's a shell.
  224.  * ----------------
  225.  */
  226. i = 0;
  227. namestrcpy(&oname, operatorName);
  228. values[i++] = NameGetDatum(&oname);
  229. values[i++] = Int32GetDatum(GetUserId());
  230. values[i++] = (Datum) (uint16) 0;
  231. values[i++] = (Datum) 'b'; /* assume it's binary */
  232. values[i++] = (Datum) (bool) 0;
  233. values[i++] = (Datum) (bool) 0;
  234. values[i++] = ObjectIdGetDatum(leftObjectId); /* <-- left oid */
  235. values[i++] = ObjectIdGetDatum(rightObjectId); /* <-- right oid */
  236. values[i++] = ObjectIdGetDatum(InvalidOid);
  237. values[i++] = ObjectIdGetDatum(InvalidOid);
  238. values[i++] = ObjectIdGetDatum(InvalidOid);
  239. values[i++] = ObjectIdGetDatum(InvalidOid);
  240. values[i++] = ObjectIdGetDatum(InvalidOid);
  241. values[i++] = ObjectIdGetDatum(InvalidOid);
  242. values[i++] = ObjectIdGetDatum(InvalidOid);
  243. values[i++] = ObjectIdGetDatum(InvalidOid);
  244. /* ----------------
  245.  * create a new operator tuple
  246.  * ----------------
  247.  */
  248. tupDesc = pg_operator_desc->rd_att;
  249. tup = heap_formtuple(tupDesc,
  250.  values,
  251.  nulls);
  252. /* ----------------
  253.  * insert our "shell" operator tuple and
  254.  * close the relation
  255.  * ----------------
  256.  */
  257. heap_insert(pg_operator_desc, tup);
  258. operatorObjectId = tup->t_data->t_oid;
  259. /* ----------------
  260.  * free the tuple and return the operator oid
  261.  * ----------------
  262.  */
  263. pfree(tup);
  264. return operatorObjectId;
  265. }
  266. /* ----------------------------------------------------------------
  267.  * OperatorShellMake
  268.  *
  269.  * Specify operator name and left and right type names,
  270.  * fill an operator struct with this info and NULL's,
  271.  * call heap_insert and return the Oid
  272.  * to the caller.
  273.  * ----------------------------------------------------------------
  274.  */
  275. static Oid
  276. OperatorShellMake(char *operatorName,
  277.   char *leftTypeName,
  278.   char *rightTypeName)
  279. {
  280. Relation pg_operator_desc;
  281. Oid operatorObjectId;
  282. Oid leftObjectId = InvalidOid;
  283. Oid rightObjectId = InvalidOid;
  284. bool leftDefined = false;
  285. bool rightDefined = false;
  286. /* ----------------
  287.  * get the left and right type oid's for this operator
  288.  * ----------------
  289.  */
  290. if (leftTypeName)
  291. leftObjectId = TypeGet(leftTypeName, &leftDefined);
  292. if (rightTypeName)
  293. rightObjectId = TypeGet(rightTypeName, &rightDefined);
  294. if (!((OidIsValid(leftObjectId) && leftDefined) ||
  295.   (OidIsValid(rightObjectId) && rightDefined)))
  296. elog(ERROR, "OperatorShellMake: no valid argument types??");
  297. /* ----------------
  298.  * open pg_operator
  299.  * ----------------
  300.  */
  301. pg_operator_desc = heap_openr(OperatorRelationName);
  302. /* ----------------
  303.  * add a "shell" operator tuple to the operator relation
  304.  * and recover the shell tuple's oid.
  305.  * ----------------
  306.  */
  307. operatorObjectId = OperatorShellMakeWithOpenRelation(pg_operator_desc,
  308.  operatorName,
  309.  leftObjectId,
  310.  rightObjectId);
  311. /* ----------------
  312.  * close the operator relation and return the oid.
  313.  * ----------------
  314.  */
  315. heap_close(pg_operator_desc);
  316. return operatorObjectId;
  317. }
  318. /* --------------------------------
  319.  * OperatorDef
  320.  *
  321.  * This routine gets complicated because it allows the user to
  322.  * specify operators that do not exist.  For example, if operator
  323.  * "op" is being defined, the negator operator "negop" and the
  324.  * commutator "commop" can also be defined without specifying
  325.  * any information other than their names. Since in order to
  326.  * add "op" to the PG_OPERATOR catalog, all the Oid's for these
  327.  * operators must be placed in the fields of "op", a forward
  328.  * declaration is done on the commutator and negator operators.
  329.  * This is called creating a shell, and its main effect is to
  330.  * create a tuple in the PG_OPERATOR catalog with minimal
  331.  * information about the operator (just its name and types).
  332.  * Forward declaration is used only for this purpose, it is
  333.  * not available to the user as it is for type definition.
  334.  *
  335.  * Algorithm:
  336.  *
  337.  * check if operator already defined
  338.  *   if so, but oprcode is null, save the Oid -- we are filling in a shell
  339.  *   otherwise error
  340.  * get the attribute types from relation descriptor for pg_operator
  341.  * assign values to the fields of the operator:
  342.  *  operatorName
  343.  *  owner id (simply the user id of the caller)
  344.  *  precedence
  345.  *  operator "kind" either "b" for binary or "l" for left unary
  346.  *  isLeftAssociative boolean
  347.  *  canHash boolean
  348.  *  leftTypeObjectId -- type must already be defined
  349.  *  rightTypeObjectId -- this is optional, enter ObjectId=0 if none specified
  350.  *  resultType -- defer this, since it must be determined from
  351.  *    the pg_procedure catalog
  352.  *  commutatorObjectId -- if this is NULL, enter ObjectId=0
  353.  *   else if this already exists, enter it's ObjectId
  354.  *   else if this does not yet exist, and is not
  355.  * the same as the main operatorName, then create
  356.  * a shell and enter the new ObjectId
  357.  *   else if this does not exist but IS the same
  358.  * name & types as the main operator, set the ObjectId=0.
  359.  * (We are creating a self-commutating operator.)
  360.  * The link will be fixed later by OperatorUpd.
  361.  *  negatorObjectId   -- same as for commutatorObjectId
  362.  *  leftSortObjectId  -- same as for commutatorObjectId
  363.  *  rightSortObjectId -- same as for commutatorObjectId
  364.  *  operatorProcedure -- must access the pg_procedure catalog to get the
  365.  *    ObjectId of the procedure that actually does the operator
  366.  *    actions this is required.  Do an amgetattr to find out the
  367.  *    return type of the procedure
  368.  *  restrictionProcedure -- must access the pg_procedure catalog to get
  369.  *    the ObjectId but this is optional
  370.  *  joinProcedure -- same as restrictionProcedure
  371.  * now either insert or replace the operator into the pg_operator catalog
  372.  * if the operator shell is being filled in
  373.  *  access the catalog in order to get a valid buffer
  374.  *  create a tuple using ModifyHeapTuple
  375.  *  get the t_self from the modified tuple and call RelationReplaceHeapTuple
  376.  * else if a new operator is being created
  377.  *  create a tuple using heap_formtuple
  378.  *  call heap_insert
  379.  * --------------------------------
  380.  * "X" indicates an optional argument (i.e. one that can be NULL)
  381.  * operatorName; -- operator name
  382.  * leftTypeName; -- X left type name
  383.  * rightTypeName; -- X right type name
  384.  * procedureName; -- procedure name for operator code
  385.  * precedence; -- operator precedence
  386.  * isLeftAssociative; -- operator is left associative?
  387.  * commutatorName; -- X commutator operator name
  388.  * negatorName; -- X negator operator name
  389.  * restrictionName; -- X restriction sel. procedure name
  390.  * joinName; -- X join sel. procedure name
  391.  * canHash; -- can hash join be used with operator?
  392.  * leftSortName; -- X left sort operator (for merge join)
  393.  * rightSortName; -- X right sort operator (for merge join)
  394.  */
  395. static void
  396. OperatorDef(char *operatorName,
  397. char *leftTypeName,
  398. char *rightTypeName,
  399. char *procedureName,
  400. uint16 precedence,
  401. bool isLeftAssociative,
  402. char *commutatorName,
  403. char *negatorName,
  404. char *restrictionName,
  405. char *joinName,
  406. bool canHash,
  407. char *leftSortName,
  408. char *rightSortName)
  409. {
  410. int i,
  411. j;
  412. Relation pg_operator_desc;
  413. HeapScanDesc pg_operator_scan;
  414. HeapTuple tup;
  415. char nulls[Natts_pg_operator];
  416. char replaces[Natts_pg_operator];
  417. Datum values[Natts_pg_operator];
  418. Oid operatorObjectId;
  419. bool operatorAlreadyDefined;
  420. Oid leftTypeId = InvalidOid;
  421. Oid rightTypeId = InvalidOid;
  422. Oid commutatorId = InvalidOid;
  423. Oid negatorId = InvalidOid;
  424. bool leftDefined = false;
  425. bool rightDefined = false;
  426. bool selfCommutator = false;
  427. char    *name[4];
  428. Oid typeId[8];
  429. int nargs;
  430. NameData oname;
  431. TupleDesc tupDesc;
  432. static ScanKeyData opKey[3] = {
  433. {0, Anum_pg_operator_oprname, F_NAMEEQ},
  434. {0, Anum_pg_operator_oprleft, F_OIDEQ},
  435. {0, Anum_pg_operator_oprright, F_OIDEQ},
  436. };
  437. fmgr_info(F_NAMEEQ, &opKey[0].sk_func);
  438. fmgr_info(F_OIDEQ, &opKey[1].sk_func);
  439. fmgr_info(F_OIDEQ, &opKey[2].sk_func);
  440. opKey[0].sk_nargs = opKey[0].sk_func.fn_nargs;
  441. opKey[1].sk_nargs = opKey[1].sk_func.fn_nargs;
  442. opKey[2].sk_nargs = opKey[2].sk_func.fn_nargs;
  443. operatorObjectId = OperatorGet(operatorName,
  444.    leftTypeName,
  445.    rightTypeName,
  446.    &operatorAlreadyDefined);
  447. if (operatorAlreadyDefined)
  448. elog(ERROR, "OperatorDef: operator "%s" already defined",
  449.  operatorName);
  450. /*
  451.  * At this point, if operatorObjectId is not InvalidOid then we are
  452.  * filling in a previously-created shell.
  453.  */
  454. /* ----------------
  455.  * look up the operator data types.
  456.  *
  457.  * Note: types must be defined before operators
  458.  * ----------------
  459.  */
  460. if (leftTypeName)
  461. {
  462. leftTypeId = TypeGet(leftTypeName, &leftDefined);
  463. if (!OidIsValid(leftTypeId) || !leftDefined)
  464. elog(ERROR, "OperatorDef: left type '%s' nonexistent",
  465.  leftTypeName);
  466. }
  467. if (rightTypeName)
  468. {
  469. rightTypeId = TypeGet(rightTypeName, &rightDefined);
  470. if (!OidIsValid(rightTypeId) || !rightDefined)
  471. elog(ERROR, "OperatorDef: right type '%s' nonexistent",
  472.  rightTypeName);
  473. }
  474. if (!((OidIsValid(leftTypeId) && leftDefined) ||
  475.   (OidIsValid(rightTypeId) && rightDefined)))
  476. elog(ERROR, "OperatorDef: must have at least one argument type");
  477. for (i = 0; i < Natts_pg_operator; ++i)
  478. {
  479. values[i] = (Datum) NULL;
  480. replaces[i] = 'r';
  481. nulls[i] = ' ';
  482. }
  483. /* ----------------
  484.  * Look up registered procedures -- find the return type
  485.  * of procedureName to place in "result" field.
  486.  * Do this before shells are created so we don't
  487.  * have to worry about deleting them later.
  488.  * ----------------
  489.  */
  490. MemSet(typeId, 0, 8 * sizeof(Oid));
  491. if (!leftTypeName)
  492. {
  493. typeId[0] = rightTypeId;
  494. nargs = 1;
  495. }
  496. else if (!rightTypeName)
  497. {
  498. typeId[0] = leftTypeId;
  499. nargs = 1;
  500. }
  501. else
  502. {
  503. typeId[0] = leftTypeId;
  504. typeId[1] = rightTypeId;
  505. nargs = 2;
  506. }
  507. tup = SearchSysCacheTuple(PRONAME,
  508.   PointerGetDatum(procedureName),
  509.   Int32GetDatum(nargs),
  510.   PointerGetDatum(typeId),
  511.   0);
  512. if (!HeapTupleIsValid(tup))
  513. func_error("OperatorDef", procedureName, nargs, typeId, NULL);
  514. values[Anum_pg_operator_oprcode - 1] = ObjectIdGetDatum(tup->t_data->t_oid);
  515. values[Anum_pg_operator_oprresult - 1] = ObjectIdGetDatum(((Form_pg_proc)
  516. GETSTRUCT(tup))->prorettype);
  517. /* ----------------
  518.  * find restriction
  519.  * ----------------
  520.  */
  521. if (restrictionName)
  522. { /* optional */
  523. MemSet(typeId, 0, 8 * sizeof(Oid));
  524. typeId[0] = OIDOID; /* operator OID */
  525. typeId[1] = OIDOID; /* relation OID */
  526. typeId[2] = INT2OID; /* attribute number */
  527. typeId[3] = 0; /* value - can be any type */
  528. typeId[4] = INT4OID; /* flags - left or right selectivity */
  529. tup = SearchSysCacheTuple(PRONAME,
  530.   PointerGetDatum(restrictionName),
  531.   Int32GetDatum(5),
  532.   PointerGetDatum(typeId),
  533.   0);
  534. if (!HeapTupleIsValid(tup))
  535. func_error("OperatorDef", restrictionName, 5, typeId, NULL);
  536. values[Anum_pg_operator_oprrest - 1] = ObjectIdGetDatum(tup->t_data->t_oid);
  537. }
  538. else
  539. values[Anum_pg_operator_oprrest - 1] = ObjectIdGetDatum(InvalidOid);
  540. /* ----------------
  541.  * find join - only valid for binary operators
  542.  * ----------------
  543.  */
  544. if (joinName)
  545. { /* optional */
  546. MemSet(typeId, 0, 8 * sizeof(Oid));
  547. typeId[0] = OIDOID; /* operator OID */
  548. typeId[1] = OIDOID; /* relation OID 1 */
  549. typeId[2] = INT2OID; /* attribute number 1 */
  550. typeId[3] = OIDOID; /* relation OID 2 */
  551. typeId[4] = INT2OID; /* attribute number 2 */
  552. tup = SearchSysCacheTuple(PRONAME,
  553.   PointerGetDatum(joinName),
  554.   Int32GetDatum(5),
  555.   PointerGetDatum(typeId),
  556.   0);
  557. if (!HeapTupleIsValid(tup))
  558. func_error("OperatorDef", joinName, 5, typeId, NULL);
  559. values[Anum_pg_operator_oprjoin - 1] = ObjectIdGetDatum(tup->t_data->t_oid);
  560. }
  561. else
  562. values[Anum_pg_operator_oprjoin - 1] = ObjectIdGetDatum(InvalidOid);
  563. /* ----------------
  564.  * set up values in the operator tuple
  565.  * ----------------
  566.  */
  567. i = 0;
  568. namestrcpy(&oname, operatorName);
  569. values[i++] = NameGetDatum(&oname);
  570. values[i++] = Int32GetDatum(GetUserId());
  571. values[i++] = UInt16GetDatum(precedence);
  572. values[i++] = leftTypeName ? (rightTypeName ? 'b' : 'r') : 'l';
  573. values[i++] = Int8GetDatum(isLeftAssociative);
  574. values[i++] = Int8GetDatum(canHash);
  575. values[i++] = ObjectIdGetDatum(leftTypeId);
  576. values[i++] = ObjectIdGetDatum(rightTypeId);
  577. ++i; /* Skip "oprresult", it was filled in
  578.  * above */
  579. /*
  580.  * Set up the other operators. If they do not currently exist, create
  581.  * shells in order to get ObjectId's.
  582.  */
  583. name[0] = commutatorName;
  584. name[1] = negatorName;
  585. name[2] = leftSortName;
  586. name[3] = rightSortName;
  587. for (j = 0; j < 4; ++j)
  588. {
  589. if (name[j])
  590. {
  591. char    *otherLeftTypeName = NULL;
  592. char    *otherRightTypeName = NULL;
  593. Oid otherLeftTypeId = InvalidOid;
  594. Oid otherRightTypeId = InvalidOid;
  595. Oid other_oid = InvalidOid;
  596. bool otherDefined = false;
  597. switch (j)
  598. {
  599. case 0: /* commutator has reversed arg types */
  600. otherLeftTypeName = rightTypeName;
  601. otherRightTypeName = leftTypeName;
  602. otherLeftTypeId = rightTypeId;
  603. otherRightTypeId = leftTypeId;
  604. other_oid = OperatorGet(name[j],
  605. otherLeftTypeName,
  606. otherRightTypeName,
  607. &otherDefined);
  608. commutatorId = other_oid;
  609. break;
  610. case 1: /* negator has same arg types */
  611. otherLeftTypeName = leftTypeName;
  612. otherRightTypeName = rightTypeName;
  613. otherLeftTypeId = leftTypeId;
  614. otherRightTypeId = rightTypeId;
  615. other_oid = OperatorGet(name[j],
  616. otherLeftTypeName,
  617. otherRightTypeName,
  618. &otherDefined);
  619. negatorId = other_oid;
  620. break;
  621. case 2: /* left sort op takes left-side data type */
  622. otherLeftTypeName = leftTypeName;
  623. otherRightTypeName = leftTypeName;
  624. otherLeftTypeId = leftTypeId;
  625. otherRightTypeId = leftTypeId;
  626. other_oid = OperatorGet(name[j],
  627. otherLeftTypeName,
  628. otherRightTypeName,
  629. &otherDefined);
  630. break;
  631. case 3: /* right sort op takes right-side data
  632.  * type */
  633. otherLeftTypeName = rightTypeName;
  634. otherRightTypeName = rightTypeName;
  635. otherLeftTypeId = rightTypeId;
  636. otherRightTypeId = rightTypeId;
  637. other_oid = OperatorGet(name[j],
  638. otherLeftTypeName,
  639. otherRightTypeName,
  640. &otherDefined);
  641. break;
  642. }
  643. if (OidIsValid(other_oid))
  644. {
  645. /* other op already in catalogs */
  646. values[i++] = ObjectIdGetDatum(other_oid);
  647. }
  648. else if (strcmp(operatorName, name[j]) != 0 ||
  649.  otherLeftTypeId != leftTypeId ||
  650.  otherRightTypeId != rightTypeId)
  651. {
  652. /* not in catalogs, different from operator */
  653. other_oid = OperatorShellMake(name[j],
  654.   otherLeftTypeName,
  655.   otherRightTypeName);
  656. if (!OidIsValid(other_oid))
  657. elog(ERROR,
  658.  "OperatorDef: can't create operator shell '%s'",
  659.  name[j]);
  660. values[i++] = ObjectIdGetDatum(other_oid);
  661. }
  662. else
  663. {
  664. /*
  665.  * self-linkage to this operator; will fix below. Note
  666.  * that only self-linkage for commutation makes sense.
  667.  */
  668. if (j != 0)
  669. elog(ERROR,
  670.  "OperatorDef: operator can't be its own negator or sort op");
  671. selfCommutator = true;
  672. values[i++] = ObjectIdGetDatum(InvalidOid);
  673. }
  674. }
  675. else
  676. {
  677. /* other operator is omitted */
  678. values[i++] = ObjectIdGetDatum(InvalidOid);
  679. }
  680. }
  681. /* last three fields were filled in above */
  682. /*
  683.  * If we are adding to an operator shell, get its t_self
  684.  */
  685. pg_operator_desc = heap_openr(OperatorRelationName);
  686. if (operatorObjectId)
  687. {
  688. opKey[0].sk_argument = PointerGetDatum(operatorName);
  689. opKey[1].sk_argument = ObjectIdGetDatum(leftTypeId);
  690. opKey[2].sk_argument = ObjectIdGetDatum(rightTypeId);
  691. pg_operator_scan = heap_beginscan(pg_operator_desc,
  692.   0,
  693.   SnapshotSelf, /* no cache? */
  694.   3,
  695.   opKey);
  696. tup = heap_getnext(pg_operator_scan, 0);
  697. if (HeapTupleIsValid(tup))
  698. {
  699. tup = heap_modifytuple(tup,
  700.    pg_operator_desc,
  701.    values,
  702.    nulls,
  703.    replaces);
  704. setheapoverride(true);
  705. heap_replace(pg_operator_desc, &tup->t_self, tup, NULL);
  706. setheapoverride(false);
  707. }
  708. else
  709. elog(ERROR, "OperatorDef: no operator %u", operatorObjectId);
  710. heap_endscan(pg_operator_scan);
  711. }
  712. else
  713. {
  714. tupDesc = pg_operator_desc->rd_att;
  715. tup = heap_formtuple(tupDesc, values, nulls);
  716. heap_insert(pg_operator_desc, tup);
  717. operatorObjectId = tup->t_data->t_oid;
  718. }
  719. heap_close(pg_operator_desc);
  720. /*
  721.  * If a commutator and/or negator link is provided, update the other
  722.  * operator(s) to point at this one, if they don't already have a
  723.  * link. This supports an alternate style of operator definition
  724.  * wherein the user first defines one operator without giving negator
  725.  * or commutator, then defines the other operator of the pair with the
  726.  * proper commutator or negator attribute. That style doesn't require
  727.  * creation of a shell, and it's the only style that worked right
  728.  * before Postgres version 6.5. This code also takes care of the
  729.  * situation where the new operator is its own commutator.
  730.  */
  731. if (selfCommutator)
  732. commutatorId = operatorObjectId;
  733. if (OidIsValid(commutatorId) || OidIsValid(negatorId))
  734. OperatorUpd(operatorObjectId, commutatorId, negatorId);
  735. }
  736. /* ----------------------------------------------------------------
  737.  * OperatorUpd
  738.  *
  739.  * For a given operator, look up its negator and commutator operators.
  740.  * If they are defined, but their negator and commutator fields
  741.  * (respectively) are empty, then use the new operator for neg or comm.
  742.  * This solves a problem for users who need to insert two new operators
  743.  * which are the negator or commutator of each other.
  744.  * ----------------------------------------------------------------
  745.  */
  746. static void
  747. OperatorUpd(Oid baseId, Oid commId, Oid negId)
  748. {
  749. int i;
  750. Relation pg_operator_desc;
  751. HeapScanDesc pg_operator_scan;
  752. HeapTuple tup;
  753. char nulls[Natts_pg_operator];
  754. char replaces[Natts_pg_operator];
  755. Datum values[Natts_pg_operator];
  756. static ScanKeyData opKey[1] = {
  757. {0, ObjectIdAttributeNumber, F_OIDEQ},
  758. };
  759. fmgr_info(F_OIDEQ, &opKey[0].sk_func);
  760. opKey[0].sk_nargs = opKey[0].sk_func.fn_nargs;
  761. for (i = 0; i < Natts_pg_operator; ++i)
  762. {
  763. values[i] = (Datum) NULL;
  764. replaces[i] = ' ';
  765. nulls[i] = ' ';
  766. }
  767. pg_operator_desc = heap_openr(OperatorRelationName);
  768. /* check and update the commutator, if necessary */
  769. opKey[0].sk_argument = ObjectIdGetDatum(commId);
  770. pg_operator_scan = heap_beginscan(pg_operator_desc,
  771.   0,
  772.   SnapshotSelf, /* no cache? */
  773.   1,
  774.   opKey);
  775. tup = heap_getnext(pg_operator_scan, 0);
  776. /*
  777.  * if the commutator and negator are the same operator, do one update.
  778.  * XXX this is probably useless code --- I doubt it ever makes sense
  779.  * for commutator and negator to be the same thing...
  780.  */
  781. if (commId == negId)
  782. {
  783. if (HeapTupleIsValid(tup))
  784. {
  785. Form_pg_operator t;
  786. t = (Form_pg_operator) GETSTRUCT(tup);
  787. if (!OidIsValid(t->oprcom)
  788. || !OidIsValid(t->oprnegate))
  789. {
  790. if (!OidIsValid(t->oprnegate))
  791. {
  792. values[Anum_pg_operator_oprnegate - 1] = ObjectIdGetDatum(baseId);
  793. replaces[Anum_pg_operator_oprnegate - 1] = 'r';
  794. }
  795. if (!OidIsValid(t->oprcom))
  796. {
  797. values[Anum_pg_operator_oprcom - 1] = ObjectIdGetDatum(baseId);
  798. replaces[Anum_pg_operator_oprcom - 1] = 'r';
  799. }
  800. tup = heap_modifytuple(tup,
  801.    pg_operator_desc,
  802.    values,
  803.    nulls,
  804.    replaces);
  805. setheapoverride(true);
  806. heap_replace(pg_operator_desc, &tup->t_self, tup, NULL);
  807. setheapoverride(false);
  808. }
  809. }
  810. heap_endscan(pg_operator_scan);
  811. heap_close(pg_operator_desc);
  812. return;
  813. }
  814. /* if commutator and negator are different, do two updates */
  815. if (HeapTupleIsValid(tup) &&
  816. !(OidIsValid(((Form_pg_operator) GETSTRUCT(tup))->oprcom)))
  817. {
  818. values[Anum_pg_operator_oprcom - 1] = ObjectIdGetDatum(baseId);
  819. replaces[Anum_pg_operator_oprcom - 1] = 'r';
  820. tup = heap_modifytuple(tup,
  821.    pg_operator_desc,
  822.    values,
  823.    nulls,
  824.    replaces);
  825. setheapoverride(true);
  826. heap_replace(pg_operator_desc, &tup->t_self, tup, NULL);
  827. setheapoverride(false);
  828. values[Anum_pg_operator_oprcom - 1] = (Datum) NULL;
  829. replaces[Anum_pg_operator_oprcom - 1] = ' ';
  830. }
  831. heap_endscan(pg_operator_scan);
  832. /* check and update the negator, if necessary */
  833. opKey[0].sk_argument = ObjectIdGetDatum(negId);
  834. pg_operator_scan = heap_beginscan(pg_operator_desc,
  835.   0,
  836.   SnapshotSelf, /* no cache? */
  837.   1,
  838.   opKey);
  839. tup = heap_getnext(pg_operator_scan, 0);
  840. if (HeapTupleIsValid(tup) &&
  841. !(OidIsValid(((Form_pg_operator) GETSTRUCT(tup))->oprnegate)))
  842. {
  843. values[Anum_pg_operator_oprnegate - 1] = ObjectIdGetDatum(baseId);
  844. replaces[Anum_pg_operator_oprnegate - 1] = 'r';
  845. tup = heap_modifytuple(tup,
  846.    pg_operator_desc,
  847.    values,
  848.    nulls,
  849.    replaces);
  850. setheapoverride(true);
  851. heap_replace(pg_operator_desc, &tup->t_self, tup, NULL);
  852. setheapoverride(false);
  853. }
  854. heap_endscan(pg_operator_scan);
  855. heap_close(pg_operator_desc);
  856. }
  857. /* ----------------------------------------------------------------
  858.  * OperatorCreate
  859.  *
  860.  * This is now just an interface procedure for OperatorDef ...
  861.  *
  862.  * "X" indicates an optional argument (i.e. one that can be NULL)
  863.  * operatorName; -- operator name
  864.  * leftTypeName; -- X left type name
  865.  * rightTypeName; -- X right type name
  866.  * procedureName; -- procedure for operator
  867.  * precedence; -- operator precedence
  868.  * isLeftAssociative; -- operator is left associative
  869.  * commutatorName; -- X commutator operator name
  870.  * negatorName; -- X negator operator name
  871.  * restrictionName; -- X restriction sel. procedure
  872.  * joinName; -- X join sel. procedure
  873.  * canHash; -- hash join can be used with this operator
  874.  * leftSortName; -- X left sort operator (for merge join)
  875.  * rightSortName; -- X right sort operator (for merge join)
  876.  */
  877. void
  878. OperatorCreate(char *operatorName,
  879.    char *leftTypeName,
  880.    char *rightTypeName,
  881.    char *procedureName,
  882.    uint16 precedence,
  883.    bool isLeftAssociative,
  884.    char *commutatorName,
  885.    char *negatorName,
  886.    char *restrictionName,
  887.    char *joinName,
  888.    bool canHash,
  889.    char *leftSortName,
  890.    char *rightSortName)
  891. {
  892. if (!leftTypeName && !rightTypeName)
  893. elog(ERROR, "OperatorCreate: at least one of leftarg or rightarg must be defined");
  894. if (!(leftTypeName && rightTypeName))
  895. {
  896. /* If it's not a binary op, these things mustn't be set: */
  897. if (commutatorName)
  898. elog(ERROR, "OperatorCreate: only binary operators can have commutators");
  899. if (negatorName)
  900. elog(ERROR, "OperatorCreate: only binary operators can have negators");
  901. if (restrictionName || joinName)
  902. elog(ERROR, "OperatorCreate: only binary operators can have selectivity");
  903. if (canHash)
  904. elog(ERROR, "OperatorCreate: only binary operators can hash");
  905. if (leftSortName || rightSortName)
  906. elog(ERROR, "OperatorCreate: only binary operators can have sort links");
  907. }
  908. /* ----------------
  909.  * Use OperatorDef() to define the specified operator and
  910.  * also create shells for the operator's associated operators
  911.  * if they don't already exist.
  912.  * ----------------
  913.  */
  914. OperatorDef(operatorName,
  915. leftTypeName,
  916. rightTypeName,
  917. procedureName,
  918. precedence,
  919. isLeftAssociative,
  920. commutatorName,
  921. negatorName,
  922. restrictionName,
  923. joinName,
  924. canHash,
  925. leftSortName,
  926. rightSortName);
  927. }