8
8
*
9
9
*
10
10
* IDENTIFICATION
11
- * $Header: /cvsroot/pgsql/src/backend/catalog/pg_operator.c,v 1.61 2001/08/10 15:49:39 petere Exp $
11
+ * $Header: /cvsroot/pgsql/src/backend/catalog/pg_operator.c,v 1.62 2001/10/22 19:34:13 tgl Exp $
12
12
*
13
13
* NOTES
14
14
* these routines moved here from commands/define.c and somewhat cleaned up.
@@ -41,11 +41,6 @@ static Oid OperatorGet(char *operatorName,
41
41
char * rightTypeName ,
42
42
bool * defined );
43
43
44
- static Oid OperatorShellMakeWithOpenRelation (Relation pg_operator_desc ,
45
- char * operatorName ,
46
- Oid leftObjectId ,
47
- Oid rightObjectId );
48
-
49
44
static Oid OperatorShellMake (char * operatorName ,
50
45
char * leftTypeName ,
51
46
char * rightTypeName );
@@ -66,6 +61,65 @@ static void OperatorDef(char *operatorName,
66
61
67
62
static void OperatorUpd (Oid baseId , Oid commId , Oid negId );
68
63
64
+
65
+ /*
66
+ * Check whether a proposed operator name is legal
67
+ *
68
+ * This had better match the behavior of parser/scan.l!
69
+ *
70
+ * We need this because the parser is not smart enough to check that
71
+ * the arguments of CREATE OPERATOR's COMMUTATOR, NEGATOR, etc clauses
72
+ * are operator names rather than some other lexical entity.
73
+ */
74
+ static bool
75
+ validOperatorName (const char * name )
76
+ {
77
+ size_t len = strlen (name );
78
+
79
+ /* Can't be empty or too long */
80
+ if (len == 0 || len >= NAMEDATALEN )
81
+ return false;
82
+
83
+ /* Can't contain any invalid characters */
84
+ /* Test string here should match op_chars in scan.l */
85
+ if (strspn (name , "~!@#^&|`?$+-*/%<>=" ) != len )
86
+ return false;
87
+
88
+ /* Can't contain slash-star or dash-dash (comment starts) */
89
+ if (strstr (name , "/*" ) || strstr (name , "--" ))
90
+ return false;
91
+
92
+ /*
93
+ * For SQL92 compatibility, '+' and '-' cannot be the
94
+ * last char of a multi-char operator unless the operator
95
+ * contains chars that are not in SQL92 operators.
96
+ * The idea is to lex '=-' as two operators, but not
97
+ * to forbid operator names like '?-' that could not be
98
+ * sequences of SQL92 operators.
99
+ */
100
+ if (len > 1 &&
101
+ (name [len - 1 ] == '+' ||
102
+ name [len - 1 ] == '-' ))
103
+ {
104
+ int ic ;
105
+
106
+ for (ic = len - 2 ; ic >= 0 ; ic -- )
107
+ {
108
+ if (strchr ("~!@#^&|`?$%" , name [ic ]))
109
+ break ;
110
+ }
111
+ if (ic < 0 )
112
+ return false; /* nope, not valid */
113
+ }
114
+
115
+ /* != isn't valid either, because parser will convert it to <> */
116
+ if (strcmp (name , "!=" ) == 0 )
117
+ return false;
118
+
119
+ return true;
120
+ }
121
+
122
+
69
123
/* ----------------------------------------------------------------
70
124
* OperatorGetWithOpenRelation
71
125
*
@@ -157,7 +211,6 @@ OperatorGet(char *operatorName,
157
211
bool * defined )
158
212
{
159
213
Relation pg_operator_desc ;
160
-
161
214
Oid operatorObjectId ;
162
215
Oid leftObjectId = InvalidOid ;
163
216
Oid rightObjectId = InvalidOid ;
@@ -215,24 +268,55 @@ OperatorGet(char *operatorName,
215
268
}
216
269
217
270
/* ----------------------------------------------------------------
218
- * OperatorShellMakeWithOpenRelation
271
+ * OperatorShellMake
219
272
*
273
+ * Specify operator name and left and right type names,
274
+ * fill an operator struct with this info and NULL's,
275
+ * call heap_insert and return the Oid to the caller.
220
276
* ----------------------------------------------------------------
221
277
*/
222
278
static Oid
223
- OperatorShellMakeWithOpenRelation (Relation pg_operator_desc ,
224
- char * operatorName ,
225
- Oid leftObjectId ,
226
- Oid rightObjectId )
279
+ OperatorShellMake (char * operatorName ,
280
+ char * leftTypeName ,
281
+ char * rightTypeName )
227
282
{
283
+ Relation pg_operator_desc ;
284
+ Oid operatorObjectId ;
285
+ Oid leftObjectId = InvalidOid ;
286
+ Oid rightObjectId = InvalidOid ;
287
+ bool leftDefined = false;
288
+ bool rightDefined = false;
228
289
int i ;
229
290
HeapTuple tup ;
230
291
Datum values [Natts_pg_operator ];
231
292
char nulls [Natts_pg_operator ];
232
- Oid operatorObjectId ;
233
293
NameData oname ;
234
294
TupleDesc tupDesc ;
235
295
296
+ /*
297
+ * validate operator name
298
+ */
299
+ if (!validOperatorName (operatorName ))
300
+ elog (ERROR , "\"%s\" is not a valid operator name" , operatorName );
301
+
302
+ /*
303
+ * get the left and right type oid's for this operator
304
+ */
305
+ if (leftTypeName )
306
+ leftObjectId = TypeGet (leftTypeName , & leftDefined );
307
+
308
+ if (rightTypeName )
309
+ rightObjectId = TypeGet (rightTypeName , & rightDefined );
310
+
311
+ if (!((OidIsValid (leftObjectId ) && leftDefined ) ||
312
+ (OidIsValid (rightObjectId ) && rightDefined )))
313
+ elog (ERROR , "OperatorShellMake: the operand types are not valid" );
314
+
315
+ /*
316
+ * open pg_operator
317
+ */
318
+ pg_operator_desc = heap_openr (OperatorRelationName , RowExclusiveLock );
319
+
236
320
/*
237
321
* initialize our *nulls and *values arrays
238
322
*/
@@ -243,7 +327,7 @@ OperatorShellMakeWithOpenRelation(Relation pg_operator_desc,
243
327
}
244
328
245
329
/*
246
- * initialize * values with the operator name and input data types.
330
+ * initialize values[] with the operator name and input data types.
247
331
* Note that oprcode is set to InvalidOid, indicating it's a shell.
248
332
*/
249
333
i = 0 ;
@@ -270,12 +354,10 @@ OperatorShellMakeWithOpenRelation(Relation pg_operator_desc,
270
354
*/
271
355
tupDesc = pg_operator_desc -> rd_att ;
272
356
273
- tup = heap_formtuple (tupDesc ,
274
- values ,
275
- nulls );
357
+ tup = heap_formtuple (tupDesc , values , nulls );
276
358
277
359
/*
278
- * insert our "shell" operator tuple and close the relation
360
+ * insert our "shell" operator tuple
279
361
*/
280
362
heap_insert (pg_operator_desc , tup );
281
363
operatorObjectId = tup -> t_data -> t_oid ;
@@ -289,63 +371,8 @@ OperatorShellMakeWithOpenRelation(Relation pg_operator_desc,
289
371
CatalogCloseIndices (Num_pg_operator_indices , idescs );
290
372
}
291
373
292
- /*
293
- * free the tuple and return the operator oid
294
- */
295
374
heap_freetuple (tup );
296
375
297
- return 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
- if (leftTypeName )
326
- leftObjectId = TypeGet (leftTypeName , & leftDefined );
327
-
328
- if (rightTypeName )
329
- rightObjectId = TypeGet (rightTypeName , & rightDefined );
330
-
331
- if (!((OidIsValid (leftObjectId ) && leftDefined ) ||
332
- (OidIsValid (rightObjectId ) && rightDefined )))
333
- elog (ERROR , "OperatorShellMake: the operand types are not valid" );
334
-
335
- /*
336
- * open pg_operator
337
- */
338
- pg_operator_desc = heap_openr (OperatorRelationName , RowExclusiveLock );
339
-
340
- /*
341
- * add a "shell" operator tuple to the operator relation and recover
342
- * the shell tuple's oid.
343
- */
344
- operatorObjectId = OperatorShellMakeWithOpenRelation (pg_operator_desc ,
345
- operatorName ,
346
- leftObjectId ,
347
- rightObjectId );
348
-
349
376
/*
350
377
* close the operator relation and return the oid.
351
378
*/
@@ -484,6 +511,12 @@ OperatorDef(char *operatorName,
484
511
* filling in a previously-created shell.
485
512
*/
486
513
514
+ /*
515
+ * validate operator name
516
+ */
517
+ if (!validOperatorName (operatorName ))
518
+ elog (ERROR , "\"%s\" is not a valid operator name" , operatorName );
519
+
487
520
/*
488
521
* look up the operator data types.
489
522
*
0 commit comments