Skip to content

Commit 55ce4e3

Browse files
committed
Support ORDER BY in SELECT stmts
1 parent 26d1797 commit 55ce4e3

File tree

3 files changed

+182
-13
lines changed

3 files changed

+182
-13
lines changed

regress/expected/new_cypher.out

+11
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,11 @@ SELECT a.* FROM tst as a;
163163
---
164164
(0 rows)
165165

166+
SELECT a.* FROM tst as a ORDER BY a.i DESC;
167+
i
168+
---
169+
(0 rows)
170+
166171
SELECT a.i as j FROM tst a GROUP BY a.i;
167172
j
168173
---
@@ -173,6 +178,12 @@ SELECT a.i as j FROM tst a GROUP BY a.i HAVING a.i = a.i;
173178
---
174179
(0 rows)
175180

181+
SELECT sum(salary) OVER w, avg(salary) OVER w
182+
FROM empsalary
183+
WINDOW w AS (PARTITION BY i ORDER BY i DESC);
184+
ERROR: syntax error at or near "("
185+
LINE 1: SELECT sum(salary) OVER w, avg(salary) OVER w
186+
^
176187
DROP GRAPH new_cypher CASCADE;
177188
NOTICE: drop cascades to 2 other objects
178189
DETAIL: drop cascades to table new_cypher._ag_label_vertex

regress/sql/new_cypher.sql

+5
Original file line numberDiff line numberDiff line change
@@ -82,10 +82,15 @@ SELECT i FROM tst WHERE i > i;
8282
--SELECT a.j FROM tst a(j);
8383
SELECT a.* FROM tst as a;
8484

85+
SELECT a.* FROM tst as a ORDER BY a.i DESC;
8586

8687
SELECT a.i as j FROM tst a GROUP BY a.i;
8788

8889
SELECT a.i as j FROM tst a GROUP BY a.i HAVING a.i = a.i;
8990

91+
SELECT sum(salary) OVER w, avg(salary) OVER w
92+
FROM empsalary
93+
WINDOW w AS (PARTITION BY i ORDER BY i DESC);
94+
9095
DROP GRAPH new_cypher CASCADE;
9196
DROP GRAPH new_cypher_2 CASCADE;

src/backend/parser/cypher_gram.y

+166-13
Original file line numberDiff line numberDiff line change
@@ -52,13 +52,41 @@
5252
#define parser_yyerror(msg) scanner_yyerror(msg, yyscanner)
5353
#define parser_errposition(pos) scanner_errposition(pos, yyscanner)
5454

55+
/* Private struct for the result of privilege_target production */
56+
typedef struct PrivTarget
57+
{
58+
GrantTargetType targtype;
59+
ObjectType objtype;
60+
List *objs;
61+
} PrivTarget;
62+
63+
/* Private struct for the result of import_qualification production */
64+
typedef struct ImportQual
65+
{
66+
ImportForeignSchemaType type;
67+
List *table_names;
68+
} ImportQual;
69+
70+
/* Private struct for the result of opt_select_limit production */
71+
typedef struct SelectLimit
72+
{
73+
Node *limitOffset;
74+
Node *limitCount;
75+
LimitOption limitOption;
76+
} SelectLimit;
77+
5578
/* Private struct for the result of group_clause production */
5679
typedef struct GroupClause
5780
{
5881
bool distinct;
5982
List *list;
6083
} GroupClause;
6184

85+
static void insertSelectOptions(SelectStmt *stmt,
86+
List *sortClause, List *lockingClause,
87+
SelectLimit *limitClause,
88+
WithClause *withClause,
89+
ag_scanner_t yyscanner);
6290
%}
6391

6492
%locations
@@ -91,6 +119,7 @@ typedef struct GroupClause
91119
struct ResTarget *target;
92120
struct Alias *alias;
93121
struct GroupClause *groupclause;
122+
struct SortBy *sortby;
94123
}
95124

96125
%token <integer> INTEGER
@@ -100,7 +129,6 @@ typedef struct GroupClause
100129
%token <string> INET
101130
%token <string> PARAMETER
102131
%token <string> OPERATOR
103-
104132
/* operators that have more than 1 character */
105133
%token NOT_EQ LT_EQ GT_EQ DOT_DOT TYPECAST PLUS_EQ
106134

@@ -227,6 +255,7 @@ typedef struct GroupClause
227255
OptWith
228256
qualified_name_list
229257
reloption_list
258+
sort_clause opt_sort_clause sortby_list
230259
from_clause from_list
231260
target_list opt_target_list
232261
opt_collate
@@ -238,8 +267,8 @@ typedef struct GroupClause
238267
%type <string> NonReservedWord_or_Sconst name
239268
%type <list> create_extension_opt_list
240269
%type <defelt> create_extension_opt_item
241-
242-
%type <integer> OptTemp
270+
%type <sortby> sortby
271+
%type <integer> OptTemp opt_asc_desc
243272

244273
%type <typnam> Typename SimpleTypename GenericType func_type
245274

@@ -436,59 +465,59 @@ select_with_parens:
436465
*/
437466
select_no_parens:
438467
simple_select { $$ = $1; }
439-
/* | select_clause sort_clause
468+
| select_clause sort_clause
440469
{
441470
insertSelectOptions((SelectStmt *) $1, $2, NIL,
442471
NULL, NULL,
443-
yyscanner);
472+
scanner);
444473
$$ = $1;
445474
}
446-
| select_clause opt_sort_clause for_locking_clause opt_select_limit
475+
/* | select_clause opt_sort_clause for_locking_clause opt_select_limit
447476
{
448477
insertSelectOptions((SelectStmt *) $1, $2, $3,
449478
$4,
450479
NULL,
451-
yyscanner);
480+
scanner);
452481
$$ = $1;
453482
}
454483
| select_clause opt_sort_clause select_limit opt_for_locking_clause
455484
{
456485
insertSelectOptions((SelectStmt *) $1, $2, $4,
457486
$3,
458487
NULL,
459-
yyscanner);
488+
scanner);
460489
$$ = $1;
461490
}
462491
| with_clause select_clause
463492
{
464493
insertSelectOptions((SelectStmt *) $2, NULL, NIL,
465494
NULL,
466495
$1,
467-
yyscanner);
496+
scanner);
468497
$$ = $2;
469498
}
470499
| with_clause select_clause sort_clause
471500
{
472501
insertSelectOptions((SelectStmt *) $2, $3, NIL,
473502
NULL,
474503
$1,
475-
yyscanner);
504+
scanner);
476505
$$ = $2;
477506
}
478507
| with_clause select_clause opt_sort_clause for_locking_clause opt_select_limit
479508
{
480509
insertSelectOptions((SelectStmt *) $2, $3, $4,
481510
$5,
482511
$1,
483-
yyscanner);
512+
scanner);
484513
$$ = $2;
485514
}
486515
| with_clause select_clause opt_sort_clause select_limit opt_for_locking_clause
487516
{
488517
insertSelectOptions((SelectStmt *) $2, $3, $5,
489518
$4,
490519
$1,
491-
yyscanner);
520+
scanner);
492521
$$ = $2;
493522
}*/
494523
;
@@ -875,6 +904,40 @@ where_clause:
875904
| /*EMPTY*/ { $$ = NULL; }
876905
;
877906

907+
opt_sort_clause:
908+
sort_clause { $$ = $1; }
909+
| /*EMPTY*/ { $$ = NIL; }
910+
;
911+
912+
sort_clause:
913+
ORDER BY sortby_list { $$ = $3; }
914+
;
915+
916+
sortby_list:
917+
sortby { $$ = list_make1($1); }
918+
| sortby_list ',' sortby { $$ = lappend($1, $3); }
919+
;
920+
921+
sortby: a_expr USING all_op opt_nulls_order
922+
{
923+
$$ = makeNode(SortBy);
924+
$$->node = $1;
925+
$$->sortby_dir = SORTBY_USING;
926+
$$->sortby_nulls = $4;
927+
$$->useOp = $3;
928+
$$->location = @3;
929+
}
930+
| a_expr opt_asc_desc opt_nulls_order
931+
{
932+
$$ = makeNode(SortBy);
933+
$$->node = $1;
934+
$$->sortby_dir = $2;
935+
$$->sortby_nulls = $3;
936+
$$->useOp = NIL;
937+
$$->location = -1; /* no operator */
938+
}
939+
;
940+
878941
CreateGraphStmt:
879942
CREATE GRAPH IDENTIFIER
880943
{
@@ -1394,6 +1457,12 @@ return_item:
13941457
}
13951458
;
13961459

1460+
opt_asc_desc: ASC { $$ = SORTBY_ASC; }
1461+
| DESC { $$ = SORTBY_DESC; }
1462+
| /*EMPTY*/ { $$ = SORTBY_DEFAULT; }
1463+
;
1464+
1465+
13971466
opt_nulls_order: NULLS_LA FIRST_P { $$ = SORTBY_NULLS_FIRST; }
13981467
| NULLS_LA LAST_P { $$ = SORTBY_NULLS_LAST; }
13991468
| /*EMPTY*/ { $$ = SORTBY_NULLS_DEFAULT; }
@@ -1686,7 +1755,7 @@ Iconst: INTEGER { $$ = $1; };
16861755
/* Note: any simple identifier will be returned as a type name! */
16871756
def_arg: func_type { $$ = (Node *)$1; }
16881757
//| reserved_keyword { $$ = (Node *)makeString(pstrdup($1)); }
1689-
//| qual_all_Op { $$ = (Node *)$1; }
1758+
| all_op { $$ = (Node *)$1; }
16901759
| NumericOnly { $$ = (Node *)$1; }
16911760
| Sconst { $$ = (Node *)makeString($1); }
16921761
//| NONE { $$ = (Node *)makeString(pstrdup($1)); }
@@ -4543,3 +4612,87 @@ doNegate(Node *n, int location)
45434612
return (Node *) makeSimpleA_Expr(AEXPR_OP, "-", NULL, n, location);
45444613
}
45454614

4615+
/* insertSelectOptions()
4616+
* Insert ORDER BY, etc into an already-constructed SelectStmt.
4617+
*
4618+
* This routine is just to avoid duplicating code in SelectStmt productions.
4619+
*/
4620+
static void
4621+
insertSelectOptions(SelectStmt *stmt,
4622+
List *sortClause, List *lockingClause,
4623+
SelectLimit *limitClause,
4624+
WithClause *withClause,
4625+
ag_scanner_t yyscanner)
4626+
{
4627+
Assert(IsA(stmt, SelectStmt));
4628+
4629+
/*
4630+
* Tests here are to reject constructs like
4631+
* (SELECT foo ORDER BY bar) ORDER BY baz
4632+
*/
4633+
if (sortClause)
4634+
{
4635+
if (stmt->sortClause)
4636+
ereport(ERROR,
4637+
(errcode(ERRCODE_SYNTAX_ERROR),
4638+
errmsg("multiple ORDER BY clauses not allowed"),
4639+
parser_errposition(exprLocation((Node *) sortClause))));
4640+
stmt->sortClause = sortClause;
4641+
}
4642+
/* We can handle multiple locking clauses, though */
4643+
stmt->lockingClause = list_concat(stmt->lockingClause, lockingClause);
4644+
if (limitClause && limitClause->limitOffset)
4645+
{
4646+
if (stmt->limitOffset)
4647+
ereport(ERROR,
4648+
(errcode(ERRCODE_SYNTAX_ERROR),
4649+
errmsg("multiple OFFSET clauses not allowed"),
4650+
parser_errposition(exprLocation(limitClause->limitOffset))));
4651+
stmt->limitOffset = limitClause->limitOffset;
4652+
}
4653+
if (limitClause && limitClause->limitCount)
4654+
{
4655+
if (stmt->limitCount)
4656+
ereport(ERROR,
4657+
(errcode(ERRCODE_SYNTAX_ERROR),
4658+
errmsg("multiple LIMIT clauses not allowed"),
4659+
parser_errposition(exprLocation(limitClause->limitCount))));
4660+
stmt->limitCount = limitClause->limitCount;
4661+
}
4662+
if (limitClause && limitClause->limitOption != LIMIT_OPTION_DEFAULT)
4663+
{
4664+
if (stmt->limitOption)
4665+
ereport(ERROR,
4666+
(errcode(ERRCODE_SYNTAX_ERROR),
4667+
errmsg("multiple limit options not allowed")));
4668+
if (!stmt->sortClause && limitClause->limitOption == LIMIT_OPTION_WITH_TIES)
4669+
ereport(ERROR,
4670+
(errcode(ERRCODE_SYNTAX_ERROR),
4671+
errmsg("WITH TIES cannot be specified without ORDER BY clause")));
4672+
if (limitClause->limitOption == LIMIT_OPTION_WITH_TIES && stmt->lockingClause)
4673+
{
4674+
ListCell *lc;
4675+
4676+
foreach(lc, stmt->lockingClause)
4677+
{
4678+
LockingClause *lock = lfirst_node(LockingClause, lc);
4679+
4680+
if (lock->waitPolicy == LockWaitSkip)
4681+
ereport(ERROR,
4682+
(errcode(ERRCODE_SYNTAX_ERROR),
4683+
errmsg("%s and %s options cannot be used together",
4684+
"SKIP LOCKED", "WITH TIES")));
4685+
}
4686+
}
4687+
stmt->limitOption = limitClause->limitOption;
4688+
}
4689+
if (withClause)
4690+
{
4691+
if (stmt->withClause)
4692+
ereport(ERROR,
4693+
(errcode(ERRCODE_SYNTAX_ERROR),
4694+
errmsg("multiple WITH clauses not allowed"),
4695+
parser_errposition(exprLocation((Node *) withClause))));
4696+
stmt->withClause = withClause;
4697+
}
4698+
}

0 commit comments

Comments
 (0)