@@ -422,17 +422,6 @@ CoerceSubscriptToText(struct ParseState *pstate, A_Indices *subscript, const cha
422
422
return coerced_expr;
423
423
}
424
424
425
- Node *
426
- CoerceRowSubscriptToText (struct ParseState *pstate, A_Indices *subscript) {
427
- return CoerceSubscriptToText (pstate, subscript, " duckdb.row" );
428
- }
429
-
430
- // Cloned implementation from CoerceRowSubscriptToText
431
- Node *
432
- CoerceStructSubscriptToText (struct ParseState *pstate, A_Indices *subscript) {
433
- return CoerceSubscriptToText (pstate, subscript, " duckdb.struct" );
434
- }
435
-
436
425
/*
437
426
* In Postgres all index operations in a row ar all slices or all plain
438
427
* index operations. If you mix them, all are converted to slices.
@@ -473,9 +462,9 @@ AddSubscriptExpressions(SubscriptingRef *sbsref, struct ParseState *pstate, A_In
473
462
474
463
/*
475
464
* DuckdbSubscriptTransform is called by the parser when a subscripting
476
- * operation is performed on a duckdb.row. It has two main puprposes:
477
- * 1. Ensure that the row is being indexed using a string literal
478
- * 2. Ensure that the return type of this index operation is duckdb.unresolved_type
465
+ * operation is performed on a duckdb type that can be indexed by arbitrary
466
+ * expressions. All this does is parse those expressions and make sure the
467
+ * subscript returns an an duckdb.unresolved_type again.
479
468
*/
480
469
void
481
470
DuckdbSubscriptTransform (SubscriptingRef *sbsref, List *indirection, struct ParseState *pstate, bool isSlice,
@@ -497,6 +486,46 @@ DuckdbSubscriptTransform(SubscriptingRef *sbsref, List *indirection, struct Pars
497
486
elog (ERROR, " Subscripting %s with an empty subscript is not supported" , type_name);
498
487
}
499
488
489
+ // Transform each subscript expression
490
+ foreach_node (A_Indices, subscript, indirection) {
491
+ AddSubscriptExpressions (sbsref, pstate, subscript, isSlice);
492
+ }
493
+
494
+ // Set the result type of the subscripting operation
495
+ sbsref->refrestype = pgduckdb::DuckdbUnresolvedTypeOid ();
496
+ sbsref->reftypmod = -1 ;
497
+ }
498
+
499
+ /*
500
+ * DuckdbTextSubscriptTransform is called by the parser when a subscripting
501
+ * operation is performed on type that can only be indexed by string literals.
502
+ * It has two main puprposes:
503
+ * 1. Ensure that the row is being indexed using a string literal
504
+ * 2. Ensure that the return type of this index operation is
505
+ * duckdb.unresolved_type
506
+ *
507
+ * Currently this is used for duckdb.row and duckdb.struct types.
508
+ */
509
+ void
510
+ DuckdbTextSubscriptTransform (SubscriptingRef *sbsref, List *indirection, struct ParseState *pstate, bool isSlice,
511
+ bool isAssignment, const char *type_name) {
512
+ /*
513
+ * We need to populate our cache for some of the code below. Normally this
514
+ * cache is populated at the start of our planner hook, but this function
515
+ * is being called from the parser.
516
+ */
517
+ if (!pgduckdb::IsExtensionRegistered ()) {
518
+ elog (ERROR, " BUG: Using %s but the pg_duckdb extension is not installed" , type_name);
519
+ }
520
+
521
+ if (isAssignment) {
522
+ elog (ERROR, " Assignment to %s is not supported" , type_name);
523
+ }
524
+
525
+ if (indirection == NIL) {
526
+ elog (ERROR, " Subscripting %s with an empty subscript is not supported" , type_name);
527
+ }
528
+
500
529
bool first = true ;
501
530
502
531
// Transform each subscript expression
@@ -505,7 +534,8 @@ DuckdbSubscriptTransform(SubscriptingRef *sbsref, List *indirection, struct Pars
505
534
* a column reference. But the subscripts after that can be anything,
506
535
* DuckDB should interpret those. */
507
536
if (first) {
508
- sbsref->refupperindexpr = lappend (sbsref->refupperindexpr , CoerceRowSubscriptToText (pstate, subscript));
537
+ sbsref->refupperindexpr =
538
+ lappend (sbsref->refupperindexpr , CoerceSubscriptToText (pstate, subscript, type_name));
509
539
if (isSlice) {
510
540
sbsref->reflowerindexpr = lappend (sbsref->reflowerindexpr , NULL );
511
541
}
@@ -524,13 +554,13 @@ DuckdbSubscriptTransform(SubscriptingRef *sbsref, List *indirection, struct Pars
524
554
void
525
555
DuckdbRowSubscriptTransform (SubscriptingRef *sbsref, List *indirection, struct ParseState *pstate, bool isSlice,
526
556
bool isAssignment) {
527
- DuckdbSubscriptTransform (sbsref, indirection, pstate, isSlice, isAssignment, " duckdb.row" );
557
+ DuckdbTextSubscriptTransform (sbsref, indirection, pstate, isSlice, isAssignment, " duckdb.row" );
528
558
}
529
559
530
560
void
531
561
DuckdbStructSubscriptTransform (SubscriptingRef *sbsref, List *indirection, struct ParseState *pstate, bool isSlice,
532
562
bool isAssignment) {
533
- DuckdbSubscriptTransform (sbsref, indirection, pstate, isSlice, isAssignment, " duckdb.struct" );
563
+ DuckdbTextSubscriptTransform (sbsref, indirection, pstate, isSlice, isAssignment, " duckdb.struct" );
534
564
}
535
565
536
566
static bool
@@ -617,52 +647,40 @@ DECLARE_PG_FUNCTION(duckdb_struct_subscript) {
617
647
PG_RETURN_POINTER (&duckdb_struct_subscript_routines);
618
648
}
619
649
620
- /*
621
- * DuckdbUnresolvedTypeSubscriptTransform is called by the parser when a
622
- * subscripting operation is performed on a duckdb.unresolved_type. All this
623
- * does is parse ensre that any subscript on duckdb.unresolved_type returns an
624
- * unrsolved type again.
625
- */
626
650
void
627
- DuckdbUnresolvedTypeSubscriptTransform (SubscriptingRef *sbsref, List *indirection, struct ParseState *pstate,
628
- bool isSlice, bool isAssignment) {
629
- /*
630
- * We need to populate our cache for some of the code below. Normally this
631
- * cache is populated at the start of our planner hook, but this function
632
- * is being called from the parser.
633
- */
634
- if (!pgduckdb::IsExtensionRegistered ()) {
635
- elog (ERROR, " BUG: Using duckdb.unresolved_type but the pg_duckdb extension is not installed" );
636
- }
651
+ DuckdbMapSubscriptExecSetup (const SubscriptingRef *sbsref, SubscriptingRefState *sbsrefstate,
652
+ SubscriptExecSteps *methods) {
653
+ DuckdbSubscriptExecSetup (sbsref, sbsrefstate, methods, " duckdb.map" );
654
+ }
637
655
638
- if (isAssignment) {
639
- elog (ERROR, " Assignment to duckdb.unresolved_type is not supported" );
640
- }
656
+ void
657
+ DuckdbMapSubscriptTransform (SubscriptingRef *sbsref, List *indirection, struct ParseState *pstate, bool isSlice,
658
+ bool isAssignment) {
659
+ DuckdbSubscriptTransform (sbsref, indirection, pstate, isSlice, isAssignment, " duckdb.map" );
660
+ }
641
661
642
- if (indirection == NIL) {
643
- elog (ERROR, " Subscripting duckdb.row with an empty subscript is not supported" );
644
- }
662
+ static SubscriptRoutines duckdb_map_subscript_routines = {
663
+ .transform = DuckdbMapSubscriptTransform,
664
+ .exec_setup = DuckdbMapSubscriptExecSetup,
665
+ .fetch_strict = false ,
666
+ .fetch_leakproof = true ,
667
+ .store_leakproof = true ,
668
+ };
645
669
646
- // Transform each subscript expression
647
- foreach_node (A_Indices, subscript, indirection) {
648
- AddSubscriptExpressions (sbsref, pstate, subscript, isSlice);
649
- }
670
+ DECLARE_PG_FUNCTION (duckdb_map_subscript) {
671
+ PG_RETURN_POINTER (&duckdb_map_subscript_routines);
672
+ }
650
673
651
- // Set the result type of the subscripting operation
652
- sbsref->refrestype = pgduckdb::DuckdbUnresolvedTypeOid ();
653
- sbsref->reftypmod = -1 ;
674
+ void
675
+ DuckdbUnresolvedTypeSubscriptTransform (SubscriptingRef *sbsref, List *indirection, struct ParseState *pstate,
676
+ bool isSlice, bool isAssignment) {
677
+ DuckdbSubscriptTransform (sbsref, indirection, pstate, isSlice, isAssignment, " duckdb.unresolved_type" );
654
678
}
655
679
656
- /*
657
- * DuckdbUnresolvedTypeSubscriptExecSetup is called by the executor when a
658
- * subscripting operation is performed on a duckdb.unresolved_type. This should
659
- * never happen, because any query that contains a duckdb.unresolved_type should
660
- * automatically be use DuckDB execution.
661
- */
662
680
void
663
- DuckdbUnresolvedTypeSubscriptExecSetup (const SubscriptingRef * /* sbsref*/ , SubscriptingRefState * /* sbsrefstate*/ ,
664
- SubscriptExecSteps * /* exprstate */ ) {
665
- elog (ERROR, " Subscripting duckdb.unresolved_type is not supported in the Postgres Executor " );
681
+ DuckdbUnresolvedTypeSubscriptExecSetup (const SubscriptingRef *sbsref, SubscriptingRefState *sbsrefstate,
682
+ SubscriptExecSteps *methods ) {
683
+ DuckdbSubscriptExecSetup (sbsref, sbsrefstate, methods, " duckdb.unresolved_type" );
666
684
}
667
685
668
686
static SubscriptRoutines duckdb_unresolved_type_subscript_routines = {
0 commit comments