1111#include "postgres.h"
1212
1313#include "access/htup_details.h"
14+ #include "access/stratnum.h"
1415#include "ag_const.h"
1516#include "catalog/ag_graph_fn.h"
1617#include "catalog/ag_label.h"
4849#include "access/genam.h"
4950#include "parser/parse_shortestpath.h"
5051#include "catalog/ag_vertex_d.h"
52+ #include "optimizer/optimizer.h"
5153#include "catalog/ag_edge_d.h"
5254
5355#define EDGE_UNION_START_ID "_start"
@@ -140,6 +142,7 @@ typedef struct
140142
141143/* projection (RETURN and WITH) */
142144static void checkNameInItems (ParseState * pstate , List * items , List * targetList );
145+ static void updateSortOperatorsForJsonb (List * sortClause , List * targetList );
143146
144147/* MATCH - OPTIONAL */
145148static ParseNamespaceItem * transformMatchOptional (ParseState * pstate ,
@@ -451,6 +454,55 @@ transformCypherSubPattern(ParseState *pstate, CypherSubPattern *subpat)
451454 return qry ;
452455}
453456
457+ static void
458+ updateSortOperatorsForJsonb (List * sortClause , List * targetList )
459+ {
460+ ListCell * lc ;
461+
462+ foreach (lc , sortClause )
463+ {
464+ SortGroupClause * sortcl = (SortGroupClause * ) lfirst (lc );
465+ TargetEntry * tle ;
466+ Oid restype ;
467+ Oid sortop ;
468+ Oid eqop ;
469+ bool hashable ;
470+ Oid opfamily ;
471+ Oid opcintype ;
472+ int16 strategy ;
473+
474+ tle = get_sortgroupref_tle (sortcl -> tleSortGroupRef , targetList );
475+ if (!tle )
476+ continue ;
477+
478+ restype = exprType ((Node * ) tle -> expr );
479+
480+ if (!get_ordering_op_properties (sortcl -> sortop ,
481+ & opfamily , & opcintype , & strategy ))
482+ continue ;
483+
484+ if (strategy == BTLessStrategyNumber )
485+ {
486+ get_sort_group_operators (restype ,
487+ true, true, false,
488+ & sortop , & eqop , NULL ,
489+ & hashable );
490+ }
491+ else if (strategy == BTGreaterStrategyNumber )
492+ {
493+ get_sort_group_operators (restype ,
494+ false, true, true,
495+ NULL , & eqop , & sortop ,
496+ & hashable );
497+ }
498+ else
499+ continue ;
500+
501+ sortcl -> eqop = eqop ;
502+ sortcl -> sortop = sortop ;
503+ }
504+ }
505+
454506Query *
455507transformCypherProjection (ParseState * pstate , CypherClause * clause )
456508{
@@ -478,68 +530,43 @@ transformCypherProjection(ParseState *pstate, CypherClause *clause)
478530 qual = transformCypherWhere (pstate , where , EXPR_KIND_WHERE );
479531 qual = resolve_future_vertex (pstate , qual , 0 );
480532 }
481- else if (detail -> distinct != NULL || detail -> order != NULL ||
482- detail -> skip != NULL || detail -> limit != NULL )
533+ else
483534 {
484- List * distinct = detail -> distinct ;
485- List * order = detail -> order ;
486- Node * skip = detail -> skip ;
487- Node * limit = detail -> limit ;
488-
489- /*
490- * detach options so that this function passes through this if
491- * statement when the function is called again recursively
492- */
493- detail -> distinct = NIL ;
494- detail -> order = NIL ;
495- detail -> skip = NULL ;
496- detail -> limit = NULL ;
497- nsitem = transformClause (pstate , (Node * ) clause );
498- detail -> distinct = distinct ;
499- detail -> order = order ;
500- detail -> skip = skip ;
501- detail -> limit = limit ;
535+ if (clause -> prev != NULL )
536+ transformClause (pstate , clause -> prev );
502537
503- qry -> targetList = makeTargetListFromNSItem (pstate , nsitem );
538+ qry -> targetList = transformItemList (pstate , detail -> items ,
539+ EXPR_KIND_SELECT_TARGET );
504540
505- qry -> sortClause = transformCypherOrderBy ( pstate , order ,
506- & qry -> targetList );
541+ if ( detail -> kind == CP_WITH )
542+ checkNameInItems ( pstate , detail -> items , qry -> targetList );
507543
508- if (distinct == NIL )
544+ if (detail -> order )
509545 {
510- /* intentionally blank, do nothing */
546+ qry -> sortClause = transformCypherOrderBy (pstate , detail -> order ,
547+ & qry -> targetList );
511548 }
512- else
549+
550+ if (detail -> distinct )
513551 {
514- Assert (linitial (distinct ) == NULL );
552+ Assert (linitial (detail -> distinct ) == NULL );
515553
516554 qry -> distinctClause = transformDistinctClause (pstate ,
517555 & qry -> targetList ,
518556 qry -> sortClause ,
519557 false);
520558 }
521559
522- qry -> limitOffset = transformCypherLimit (pstate , skip , EXPR_KIND_OFFSET ,
523- "SKIP" );
524- qry -> limitOffset = resolve_future_vertex (pstate , qry -> limitOffset , 0 );
525-
526- qry -> limitCount = transformCypherLimit (pstate , limit , EXPR_KIND_LIMIT ,
527- "LIMIT" );
560+ qry -> limitCount = transformCypherLimit (pstate , detail -> limit ,
561+ EXPR_KIND_LIMIT , "LIMIT" );
528562 qry -> limitCount = resolve_future_vertex (pstate , qry -> limitCount , 0 );
529- }
530- else
531- {
532- if (clause -> prev != NULL )
533- transformClause (pstate , clause -> prev );
534563
535- qry -> targetList = transformItemList (pstate , detail -> items ,
536- EXPR_KIND_SELECT_TARGET );
537-
538- if (detail -> kind == CP_WITH )
539- checkNameInItems (pstate , detail -> items , qry -> targetList );
564+ qry -> limitOffset = transformCypherLimit (pstate , detail -> skip ,
565+ EXPR_KIND_OFFSET , "SKIP" );
566+ qry -> limitOffset = resolve_future_vertex (pstate , qry -> limitOffset , 0 );
540567
541568 qry -> groupClause = generateGroupClause (pstate , & qry -> targetList ,
542- qry -> sortClause );
569+ qry -> sortClause );
543570 }
544571
545572 if (detail -> kind == CP_WITH )
@@ -570,6 +597,7 @@ transformCypherProjection(ParseState *pstate, CypherClause *clause)
570597 {
571598 flags = 0 ;
572599 }
600+
573601 qry -> targetList = (List * ) resolve_future_vertex (pstate ,
574602 (Node * ) qry -> targetList ,
575603 flags );
@@ -578,7 +606,16 @@ transformCypherProjection(ParseState *pstate, CypherClause *clause)
578606 qual = qualAndExpr (qual , pstate -> p_resolved_qual );
579607
580608 if (detail -> kind == CP_RETURN )
609+ {
581610 resolveItemList (pstate , qry -> targetList );
611+ /*
612+ * After applying JSONB coercion, update sort operators in
613+ * sortClause to use JSONB comparison operators instead
614+ * of the original type's operators
615+ */
616+ if (qry -> sortClause )
617+ updateSortOperatorsForJsonb (qry -> sortClause , qry -> targetList );
618+ }
582619
583620 qry -> rtable = pstate -> p_rtable ;
584621 qry -> jointree = makeFromExpr (pstate -> p_joinlist , qual );
@@ -3744,6 +3781,9 @@ resolve_future_vertex(ParseState *pstate, Node *node, int flags)
37443781{
37453782 resolve_future_vertex_context ctx ;
37463783
3784+ if (node == NULL )
3785+ return NULL ;
3786+
37473787 ctx .pstate = pstate ;
37483788 ctx .flags = flags ;
37493789 ctx .sublevels_up = 0 ;
0 commit comments