@@ -241,10 +241,76 @@ static void
241
241
analyzeCTE (ParseState * pstate , CommonTableExpr * cte )
242
242
{
243
243
Query * query ;
244
+ CTESearchClause * search_clause = cte -> search_clause ;
245
+ CTECycleClause * cycle_clause = cte -> cycle_clause ;
244
246
245
247
/* Analysis not done already */
246
248
Assert (!IsA (cte -> ctequery , Query ));
247
249
250
+ /*
251
+ * Before analyzing the CTE's query, we'd better identify the data type of
252
+ * the cycle mark column if any, since the query could refer to that.
253
+ * Other validity checks on the cycle clause will be done afterwards.
254
+ */
255
+ if (cycle_clause )
256
+ {
257
+ TypeCacheEntry * typentry ;
258
+ Oid op ;
259
+
260
+ cycle_clause -> cycle_mark_value =
261
+ transformExpr (pstate , cycle_clause -> cycle_mark_value ,
262
+ EXPR_KIND_CYCLE_MARK );
263
+ cycle_clause -> cycle_mark_default =
264
+ transformExpr (pstate , cycle_clause -> cycle_mark_default ,
265
+ EXPR_KIND_CYCLE_MARK );
266
+
267
+ cycle_clause -> cycle_mark_type =
268
+ select_common_type (pstate ,
269
+ list_make2 (cycle_clause -> cycle_mark_value ,
270
+ cycle_clause -> cycle_mark_default ),
271
+ "CYCLE" , NULL );
272
+ cycle_clause -> cycle_mark_value =
273
+ coerce_to_common_type (pstate ,
274
+ cycle_clause -> cycle_mark_value ,
275
+ cycle_clause -> cycle_mark_type ,
276
+ "CYCLE/SET/TO" );
277
+ cycle_clause -> cycle_mark_default =
278
+ coerce_to_common_type (pstate ,
279
+ cycle_clause -> cycle_mark_default ,
280
+ cycle_clause -> cycle_mark_type ,
281
+ "CYCLE/SET/DEFAULT" );
282
+
283
+ cycle_clause -> cycle_mark_typmod =
284
+ select_common_typmod (pstate ,
285
+ list_make2 (cycle_clause -> cycle_mark_value ,
286
+ cycle_clause -> cycle_mark_default ),
287
+ cycle_clause -> cycle_mark_type );
288
+
289
+ cycle_clause -> cycle_mark_collation =
290
+ select_common_collation (pstate ,
291
+ list_make2 (cycle_clause -> cycle_mark_value ,
292
+ cycle_clause -> cycle_mark_default ),
293
+ true);
294
+
295
+ /* Might as well look up the relevant <> operator while we are at it */
296
+ typentry = lookup_type_cache (cycle_clause -> cycle_mark_type ,
297
+ TYPECACHE_EQ_OPR );
298
+ if (!OidIsValid (typentry -> eq_opr ))
299
+ ereport (ERROR ,
300
+ errcode (ERRCODE_UNDEFINED_FUNCTION ),
301
+ errmsg ("could not identify an equality operator for type %s" ,
302
+ format_type_be (cycle_clause -> cycle_mark_type )));
303
+ op = get_negator (typentry -> eq_opr );
304
+ if (!OidIsValid (op ))
305
+ ereport (ERROR ,
306
+ errcode (ERRCODE_UNDEFINED_FUNCTION ),
307
+ errmsg ("could not identify an inequality operator for type %s" ,
308
+ format_type_be (cycle_clause -> cycle_mark_type )));
309
+
310
+ cycle_clause -> cycle_mark_neop = op ;
311
+ }
312
+
313
+ /* Now we can get on with analyzing the CTE's query */
248
314
query = parse_sub_analyze (cte -> ctequery , pstate , cte , false, true);
249
315
cte -> ctequery = (Node * ) query ;
250
316
@@ -339,7 +405,10 @@ analyzeCTE(ParseState *pstate, CommonTableExpr *cte)
339
405
elog (ERROR , "wrong number of output columns in WITH" );
340
406
}
341
407
342
- if (cte -> search_clause || cte -> cycle_clause )
408
+ /*
409
+ * Now make validity checks on the SEARCH and CYCLE clauses, if present.
410
+ */
411
+ if (search_clause || cycle_clause )
343
412
{
344
413
Query * ctequery ;
345
414
SetOperationStmt * sos ;
@@ -386,12 +455,12 @@ analyzeCTE(ParseState *pstate, CommonTableExpr *cte)
386
455
errmsg ("with a SEARCH or CYCLE clause, the right side of the UNION must be a SELECT" )));
387
456
}
388
457
389
- if (cte -> search_clause )
458
+ if (search_clause )
390
459
{
391
460
ListCell * lc ;
392
461
List * seen = NIL ;
393
462
394
- foreach (lc , cte -> search_clause -> search_col_list )
463
+ foreach (lc , search_clause -> search_col_list )
395
464
{
396
465
Value * colname = lfirst (lc );
397
466
@@ -400,33 +469,31 @@ analyzeCTE(ParseState *pstate, CommonTableExpr *cte)
400
469
(errcode (ERRCODE_SYNTAX_ERROR ),
401
470
errmsg ("search column \"%s\" not in WITH query column list" ,
402
471
strVal (colname )),
403
- parser_errposition (pstate , cte -> search_clause -> location )));
472
+ parser_errposition (pstate , search_clause -> location )));
404
473
405
474
if (list_member (seen , colname ))
406
475
ereport (ERROR ,
407
476
(errcode (ERRCODE_DUPLICATE_COLUMN ),
408
477
errmsg ("search column \"%s\" specified more than once" ,
409
478
strVal (colname )),
410
- parser_errposition (pstate , cte -> search_clause -> location )));
479
+ parser_errposition (pstate , search_clause -> location )));
411
480
seen = lappend (seen , colname );
412
481
}
413
482
414
- if (list_member (cte -> ctecolnames , makeString (cte -> search_clause -> search_seq_column )))
483
+ if (list_member (cte -> ctecolnames , makeString (search_clause -> search_seq_column )))
415
484
ereport (ERROR ,
416
485
errcode (ERRCODE_SYNTAX_ERROR ),
417
486
errmsg ("search sequence column name \"%s\" already used in WITH query column list" ,
418
- cte -> search_clause -> search_seq_column ),
419
- parser_errposition (pstate , cte -> search_clause -> location ));
487
+ search_clause -> search_seq_column ),
488
+ parser_errposition (pstate , search_clause -> location ));
420
489
}
421
490
422
- if (cte -> cycle_clause )
491
+ if (cycle_clause )
423
492
{
424
493
ListCell * lc ;
425
494
List * seen = NIL ;
426
- TypeCacheEntry * typentry ;
427
- Oid op ;
428
495
429
- foreach (lc , cte -> cycle_clause -> cycle_col_list )
496
+ foreach (lc , cycle_clause -> cycle_col_list )
430
497
{
431
498
Value * colname = lfirst (lc );
432
499
@@ -435,97 +502,54 @@ analyzeCTE(ParseState *pstate, CommonTableExpr *cte)
435
502
(errcode (ERRCODE_SYNTAX_ERROR ),
436
503
errmsg ("cycle column \"%s\" not in WITH query column list" ,
437
504
strVal (colname )),
438
- parser_errposition (pstate , cte -> cycle_clause -> location )));
505
+ parser_errposition (pstate , cycle_clause -> location )));
439
506
440
507
if (list_member (seen , colname ))
441
508
ereport (ERROR ,
442
509
(errcode (ERRCODE_DUPLICATE_COLUMN ),
443
510
errmsg ("cycle column \"%s\" specified more than once" ,
444
511
strVal (colname )),
445
- parser_errposition (pstate , cte -> cycle_clause -> location )));
512
+ parser_errposition (pstate , cycle_clause -> location )));
446
513
seen = lappend (seen , colname );
447
514
}
448
515
449
- if (list_member (cte -> ctecolnames , makeString (cte -> cycle_clause -> cycle_mark_column )))
516
+ if (list_member (cte -> ctecolnames , makeString (cycle_clause -> cycle_mark_column )))
450
517
ereport (ERROR ,
451
518
errcode (ERRCODE_SYNTAX_ERROR ),
452
519
errmsg ("cycle mark column name \"%s\" already used in WITH query column list" ,
453
- cte -> cycle_clause -> cycle_mark_column ),
454
- parser_errposition (pstate , cte -> cycle_clause -> location ));
455
-
456
- cte -> cycle_clause -> cycle_mark_value = transformExpr (pstate , cte -> cycle_clause -> cycle_mark_value ,
457
- EXPR_KIND_CYCLE_MARK );
458
- cte -> cycle_clause -> cycle_mark_default = transformExpr (pstate , cte -> cycle_clause -> cycle_mark_default ,
459
- EXPR_KIND_CYCLE_MARK );
520
+ cycle_clause -> cycle_mark_column ),
521
+ parser_errposition (pstate , cycle_clause -> location ));
460
522
461
- if (list_member (cte -> ctecolnames , makeString (cte -> cycle_clause -> cycle_path_column )))
523
+ if (list_member (cte -> ctecolnames , makeString (cycle_clause -> cycle_path_column )))
462
524
ereport (ERROR ,
463
525
errcode (ERRCODE_SYNTAX_ERROR ),
464
526
errmsg ("cycle path column name \"%s\" already used in WITH query column list" ,
465
- cte -> cycle_clause -> cycle_path_column ),
466
- parser_errposition (pstate , cte -> cycle_clause -> location ));
527
+ cycle_clause -> cycle_path_column ),
528
+ parser_errposition (pstate , cycle_clause -> location ));
467
529
468
- if (strcmp (cte -> cycle_clause -> cycle_mark_column ,
469
- cte -> cycle_clause -> cycle_path_column ) == 0 )
530
+ if (strcmp (cycle_clause -> cycle_mark_column ,
531
+ cycle_clause -> cycle_path_column ) == 0 )
470
532
ereport (ERROR ,
471
533
errcode (ERRCODE_SYNTAX_ERROR ),
472
534
errmsg ("cycle mark column name and cycle path column name are the same" ),
473
- parser_errposition (pstate , cte -> cycle_clause -> location ));
474
-
475
- cte -> cycle_clause -> cycle_mark_type = select_common_type (pstate ,
476
- list_make2 (cte -> cycle_clause -> cycle_mark_value ,
477
- cte -> cycle_clause -> cycle_mark_default ),
478
- "CYCLE" , NULL );
479
- cte -> cycle_clause -> cycle_mark_value = coerce_to_common_type (pstate ,
480
- cte -> cycle_clause -> cycle_mark_value ,
481
- cte -> cycle_clause -> cycle_mark_type ,
482
- "CYCLE/SET/TO" );
483
- cte -> cycle_clause -> cycle_mark_default = coerce_to_common_type (pstate ,
484
- cte -> cycle_clause -> cycle_mark_default ,
485
- cte -> cycle_clause -> cycle_mark_type ,
486
- "CYCLE/SET/DEFAULT" );
487
-
488
- cte -> cycle_clause -> cycle_mark_typmod = select_common_typmod (pstate ,
489
- list_make2 (cte -> cycle_clause -> cycle_mark_value ,
490
- cte -> cycle_clause -> cycle_mark_default ),
491
- cte -> cycle_clause -> cycle_mark_type );
492
-
493
- cte -> cycle_clause -> cycle_mark_collation = select_common_collation (pstate ,
494
- list_make2 (cte -> cycle_clause -> cycle_mark_value ,
495
- cte -> cycle_clause -> cycle_mark_default ),
496
- true);
497
-
498
- typentry = lookup_type_cache (cte -> cycle_clause -> cycle_mark_type , TYPECACHE_EQ_OPR );
499
- if (!typentry -> eq_opr )
500
- ereport (ERROR ,
501
- errcode (ERRCODE_UNDEFINED_FUNCTION ),
502
- errmsg ("could not identify an equality operator for type %s" ,
503
- format_type_be (cte -> cycle_clause -> cycle_mark_type )));
504
- op = get_negator (typentry -> eq_opr );
505
- if (!op )
506
- ereport (ERROR ,
507
- errcode (ERRCODE_UNDEFINED_FUNCTION ),
508
- errmsg ("could not identify an inequality operator for type %s" ,
509
- format_type_be (cte -> cycle_clause -> cycle_mark_type )));
510
-
511
- cte -> cycle_clause -> cycle_mark_neop = op ;
535
+ parser_errposition (pstate , cycle_clause -> location ));
512
536
}
513
537
514
- if (cte -> search_clause && cte -> cycle_clause )
538
+ if (search_clause && cycle_clause )
515
539
{
516
- if (strcmp (cte -> search_clause -> search_seq_column ,
517
- cte -> cycle_clause -> cycle_mark_column ) == 0 )
540
+ if (strcmp (search_clause -> search_seq_column ,
541
+ cycle_clause -> cycle_mark_column ) == 0 )
518
542
ereport (ERROR ,
519
543
errcode (ERRCODE_SYNTAX_ERROR ),
520
544
errmsg ("search sequence column name and cycle mark column name are the same" ),
521
- parser_errposition (pstate , cte -> search_clause -> location ));
545
+ parser_errposition (pstate , search_clause -> location ));
522
546
523
- if (strcmp (cte -> search_clause -> search_seq_column ,
524
- cte -> cycle_clause -> cycle_path_column ) == 0 )
547
+ if (strcmp (search_clause -> search_seq_column ,
548
+ cycle_clause -> cycle_path_column ) == 0 )
525
549
ereport (ERROR ,
526
550
errcode (ERRCODE_SYNTAX_ERROR ),
527
551
errmsg ("search sequence column name and cycle path column name are the same" ),
528
- parser_errposition (pstate , cte -> search_clause -> location ));
552
+ parser_errposition (pstate , search_clause -> location ));
529
553
}
530
554
}
531
555
0 commit comments