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