pg_query 2.1.4 → 2.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (85) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +29 -0
  3. data/README.md +32 -0
  4. data/Rakefile +2 -2
  5. data/ext/pg_query/include/access/twophase.h +2 -0
  6. data/ext/pg_query/include/access/xact.h +6 -0
  7. data/ext/pg_query/include/access/xlog_internal.h +10 -1
  8. data/ext/pg_query/include/access/xlogreader.h +10 -0
  9. data/ext/pg_query/include/catalog/dependency.h +2 -0
  10. data/ext/pg_query/include/catalog/pg_class.h +1 -1
  11. data/ext/pg_query/include/catalog/pg_class_d.h +1 -1
  12. data/ext/pg_query/include/catalog/pg_control.h +2 -0
  13. data/ext/pg_query/include/catalog/pg_operator.h +3 -1
  14. data/ext/pg_query/include/catalog/pg_publication.h +3 -0
  15. data/ext/pg_query/include/catalog/pg_type.h +1 -0
  16. data/ext/pg_query/include/commands/async.h +1 -1
  17. data/ext/pg_query/include/commands/tablespace.h +2 -0
  18. data/ext/pg_query/include/commands/trigger.h +8 -0
  19. data/ext/pg_query/include/lib/simplehash.h +13 -13
  20. data/ext/pg_query/include/libpq/libpq.h +1 -0
  21. data/ext/pg_query/include/mb/pg_wchar.h +1 -0
  22. data/ext/pg_query/include/miscadmin.h +24 -11
  23. data/ext/pg_query/include/nodes/execnodes.h +2 -2
  24. data/ext/pg_query/include/nodes/parsenodes.h +5 -4
  25. data/ext/pg_query/include/nodes/pathnodes.h +2 -1
  26. data/ext/pg_query/include/nodes/pg_list.h +1 -0
  27. data/ext/pg_query/include/nodes/plannodes.h +18 -3
  28. data/ext/pg_query/include/optimizer/optimizer.h +0 -5
  29. data/ext/pg_query/include/parser/gram.h +2 -2
  30. data/ext/pg_query/include/parser/kwlist.h +1 -1
  31. data/ext/pg_query/include/parser/parse_coerce.h +1 -0
  32. data/ext/pg_query/include/pg_config.h +16 -13
  33. data/ext/pg_query/include/pg_query.h +2 -2
  34. data/ext/pg_query/include/pg_query_fingerprint_defs.c +286 -314
  35. data/ext/pg_query/include/pg_query_outfuncs_defs.c +1 -0
  36. data/ext/pg_query/include/pg_query_readfuncs_defs.c +1 -0
  37. data/ext/pg_query/include/pgstat.h +2 -1
  38. data/ext/pg_query/include/plpgsql.h +2 -2
  39. data/ext/pg_query/include/port/pg_bitutils.h +48 -2
  40. data/ext/pg_query/include/port.h +4 -0
  41. data/ext/pg_query/include/protobuf/pg_query.pb-c.h +4 -3
  42. data/ext/pg_query/include/replication/reorderbuffer.h +6 -5
  43. data/ext/pg_query/include/replication/slot.h +1 -1
  44. data/ext/pg_query/include/storage/block.h +1 -1
  45. data/ext/pg_query/include/storage/lock.h +6 -5
  46. data/ext/pg_query/include/storage/lwlock.h +1 -0
  47. data/ext/pg_query/include/storage/proc.h +14 -0
  48. data/ext/pg_query/include/storage/s_lock.h +24 -0
  49. data/ext/pg_query/include/tcop/pquery.h +6 -0
  50. data/ext/pg_query/include/utils/builtins.h +1 -0
  51. data/ext/pg_query/include/utils/inval.h +1 -0
  52. data/ext/pg_query/include/utils/portal.h +13 -0
  53. data/ext/pg_query/include/utils/rel.h +0 -1
  54. data/ext/pg_query/include/utils/relcache.h +1 -2
  55. data/ext/pg_query/include/utils/snapmgr.h +1 -0
  56. data/ext/pg_query/pg_query.pb-c.c +18 -5
  57. data/ext/pg_query/pg_query_deparse.c +8 -8
  58. data/ext/pg_query/pg_query_fingerprint.c +1 -0
  59. data/ext/pg_query/pg_query_json_plpgsql.c +68 -0
  60. data/ext/pg_query/pg_query_normalize.c +43 -7
  61. data/ext/pg_query/pg_query_outfuncs.h +1 -0
  62. data/ext/pg_query/pg_query_outfuncs_json.c +11 -0
  63. data/ext/pg_query/pg_query_parse_plpgsql.c +58 -15
  64. data/ext/pg_query/src_backend_catalog_namespace.c +1 -0
  65. data/ext/pg_query/src_backend_libpq_pqcomm.c +8 -0
  66. data/ext/pg_query/src_backend_nodes_copyfuncs.c +23 -33
  67. data/ext/pg_query/src_backend_nodes_equalfuncs.c +1 -0
  68. data/ext/pg_query/src_backend_nodes_list.c +12 -0
  69. data/ext/pg_query/src_backend_parser_gram.c +18 -3
  70. data/ext/pg_query/src_backend_parser_scan.c +493 -253
  71. data/ext/pg_query/src_backend_tcop_postgres.c +11 -1
  72. data/ext/pg_query/src_backend_utils_adt_ruleutils.c +38 -10
  73. data/ext/pg_query/src_backend_utils_misc_guc.c +1 -0
  74. data/ext/pg_query/src_common_wchar.c +11 -0
  75. data/ext/pg_query/src_pl_plpgsql_src_pl_comp.c +4 -2
  76. data/ext/pg_query/src_pl_plpgsql_src_pl_gram.c +1 -1
  77. data/ext/pg_query/src_port_pg_bitutils.c +1 -22
  78. data/ext/pg_query/src_port_snprintf.c +9 -7
  79. data/lib/pg_query/deparse.rb +7 -1
  80. data/lib/pg_query/fingerprint.rb +13 -2
  81. data/lib/pg_query/parse.rb +5 -3
  82. data/lib/pg_query/pg_query_pb.rb +2 -1
  83. data/lib/pg_query/treewalker.rb +6 -0
  84. data/lib/pg_query/version.rb +1 -1
  85. metadata +2 -2
@@ -8,6 +8,8 @@
8
8
  #include "mb/pg_wchar.h"
9
9
  #include "nodes/nodeFuncs.h"
10
10
 
11
+ #include "pg_query_outfuncs.h"
12
+
11
13
  /*
12
14
  * Struct for tracking locations/lengths of constants during normalization
13
15
  */
@@ -331,6 +333,27 @@ static void RecordConstLocation(pgssConstLocations *jstate, int location)
331
333
  }
332
334
  }
333
335
 
336
+ static void record_defelem_arg_location(pgssConstLocations *jstate, int location)
337
+ {
338
+ for (int i = location; i < jstate->query_len; i++) {
339
+ if (jstate->query[i] == '\'' || jstate->query[i] == '$') {
340
+ RecordConstLocation(jstate, i);
341
+ break;
342
+ }
343
+ }
344
+ }
345
+
346
+ static void record_matching_string(pgssConstLocations *jstate, const char *str)
347
+ {
348
+ char *loc = NULL;
349
+ if (str == NULL)
350
+ return;
351
+
352
+ loc = strstr(jstate->query, str);
353
+ if (loc != NULL)
354
+ RecordConstLocation(jstate, loc - jstate->query - 1);
355
+ }
356
+
334
357
  static bool const_record_walker(Node *node, pgssConstLocations *jstate)
335
358
  {
336
359
  bool result;
@@ -362,13 +385,12 @@ static bool const_record_walker(Node *node, pgssConstLocations *jstate)
362
385
  case T_DefElem:
363
386
  {
364
387
  DefElem * defElem = (DefElem *) node;
365
- if (defElem->arg != NULL && IsA(defElem->arg, String)) {
366
- for (int i = defElem->location; i < jstate->query_len; i++) {
367
- if (jstate->query[i] == '\'') {
368
- RecordConstLocation(jstate, i);
369
- break;
370
- }
371
- }
388
+ if (defElem->arg == NULL) {
389
+ // No argument
390
+ } else if (IsA(defElem->arg, String)) {
391
+ record_defelem_arg_location(jstate, defElem->location);
392
+ } else if (IsA(defElem->arg, List) && list_length((List *) defElem->arg) == 1 && IsA(linitial((List *) defElem->arg), String)) {
393
+ record_defelem_arg_location(jstate, defElem->location);
372
394
  }
373
395
  return const_record_walker((Node *) ((DefElem *) node)->arg, jstate);
374
396
  }
@@ -387,6 +409,20 @@ static bool const_record_walker(Node *node, pgssConstLocations *jstate)
387
409
  return const_record_walker((Node *) ((AlterRoleStmt *) node)->options, jstate);
388
410
  case T_DeclareCursorStmt:
389
411
  return const_record_walker((Node *) ((DeclareCursorStmt *) node)->query, jstate);
412
+ case T_CreateFunctionStmt:
413
+ return const_record_walker((Node *) ((CreateFunctionStmt *) node)->options, jstate);
414
+ case T_DoStmt:
415
+ return const_record_walker((Node *) ((DoStmt *) node)->args, jstate);
416
+ case T_CreateSubscriptionStmt:
417
+ record_matching_string(jstate, ((CreateSubscriptionStmt *) node)->conninfo);
418
+ break;
419
+ case T_AlterSubscriptionStmt:
420
+ record_matching_string(jstate, ((CreateSubscriptionStmt *) node)->conninfo);
421
+ break;
422
+ case T_CreateUserMappingStmt:
423
+ return const_record_walker((Node *) ((CreateUserMappingStmt *) node)->options, jstate);
424
+ case T_AlterUserMappingStmt:
425
+ return const_record_walker((Node *) ((AlterUserMappingStmt *) node)->options, jstate);
390
426
  case T_TypeName:
391
427
  /* Don't normalize constants in typmods or arrayBounds */
392
428
  return false;
@@ -5,6 +5,7 @@
5
5
 
6
6
  PgQueryProtobuf pg_query_nodes_to_protobuf(const void *obj);
7
7
 
8
+ char *pg_query_node_to_json(const void *obj);
8
9
  char *pg_query_nodes_to_json(const void *obj);
9
10
 
10
11
  #endif
@@ -259,6 +259,17 @@ _outNode(StringInfo out, const void *obj)
259
259
  }
260
260
  }
261
261
 
262
+ char *
263
+ pg_query_node_to_json(const void *obj)
264
+ {
265
+ StringInfoData out;
266
+
267
+ initStringInfo(&out);
268
+ _outNode(&out, obj);
269
+
270
+ return out.data;
271
+ }
272
+
262
273
  char *
263
274
  pg_query_nodes_to_json(const void *obj)
264
275
  {
@@ -18,7 +18,7 @@ typedef struct {
18
18
  PgQueryError* error;
19
19
  } PgQueryInternalPlpgsqlFuncAndError;
20
20
 
21
- static PgQueryInternalPlpgsqlFuncAndError pg_query_raw_parse_plpgsql(CreateFunctionStmt* stmt);
21
+ static PgQueryInternalPlpgsqlFuncAndError pg_query_raw_parse_plpgsql(Node* stmt);
22
22
 
23
23
  static void add_dummy_return(PLpgSQL_function *function)
24
24
  {
@@ -73,6 +73,36 @@ static void plpgsql_compile_error_callback(void *arg)
73
73
  plpgsql_error_funcname, plpgsql_latest_lineno());
74
74
  }
75
75
 
76
+ static PLpgSQL_function *compile_do_stmt(DoStmt* stmt)
77
+ {
78
+ char *proc_source = NULL;
79
+ const ListCell *lc;
80
+ char *language = "plpgsql";
81
+
82
+ assert(IsA(stmt, DoStmt));
83
+
84
+ foreach(lc, stmt->args)
85
+ {
86
+ DefElem* elem = (DefElem*) lfirst(lc);
87
+
88
+ if (strcmp(elem->defname, "as") == 0) {
89
+
90
+ assert(IsA(elem->arg, String));
91
+ proc_source = strVal(elem->arg);
92
+ } else if (strcmp(elem->defname, "language") == 0) {
93
+ language = strVal(elem->arg);
94
+ }
95
+ }
96
+
97
+ assert(proc_source != NULL);
98
+
99
+ if(strcmp(language, "plpgsql") != 0) {
100
+ return (PLpgSQL_function *) palloc0(sizeof(PLpgSQL_function));
101
+ }
102
+ return plpgsql_compile_inline(proc_source);
103
+
104
+ }
105
+
76
106
  static PLpgSQL_function *compile_create_function_stmt(CreateFunctionStmt* stmt)
77
107
  {
78
108
  char *func_name;
@@ -87,6 +117,7 @@ static PLpgSQL_function *compile_create_function_stmt(CreateFunctionStmt* stmt)
87
117
  const ListCell *lc, *lc2, *lc3;
88
118
  bool is_trigger = false;
89
119
  bool is_setof = false;
120
+ char *language = "plpgsql";
90
121
 
91
122
  assert(IsA(stmt, CreateFunctionStmt));
92
123
 
@@ -105,11 +136,17 @@ static PLpgSQL_function *compile_create_function_stmt(CreateFunctionStmt* stmt)
105
136
  {
106
137
  proc_source = strVal(lfirst(lc2));
107
138
  }
139
+ } else if (strcmp(elem->defname, "language") == 0) {
140
+ language = strVal(elem->arg);
108
141
  }
109
142
  }
110
143
 
111
144
  assert(proc_source != NULL);
112
145
 
146
+ if(strcmp(language, "plpgsql") != 0) {
147
+ return (PLpgSQL_function *) palloc0(sizeof(PLpgSQL_function));
148
+ }
149
+
113
150
  if (stmt->returnType != NULL) {
114
151
  foreach(lc3, stmt->returnType->names)
115
152
  {
@@ -273,7 +310,7 @@ static PLpgSQL_function *compile_create_function_stmt(CreateFunctionStmt* stmt)
273
310
  return function;
274
311
  }
275
312
 
276
- PgQueryInternalPlpgsqlFuncAndError pg_query_raw_parse_plpgsql(CreateFunctionStmt* stmt)
313
+ PgQueryInternalPlpgsqlFuncAndError pg_query_raw_parse_plpgsql(Node* stmt)
277
314
  {
278
315
  PgQueryInternalPlpgsqlFuncAndError result = {0};
279
316
  MemoryContext cctx = CurrentMemoryContext;
@@ -306,7 +343,13 @@ PgQueryInternalPlpgsqlFuncAndError pg_query_raw_parse_plpgsql(CreateFunctionStmt
306
343
 
307
344
  PG_TRY();
308
345
  {
309
- result.func = compile_create_function_stmt(stmt);
346
+ if (IsA(stmt, CreateFunctionStmt)) {
347
+ result.func = compile_create_function_stmt((CreateFunctionStmt *) stmt);
348
+ } else if (IsA(stmt, DoStmt)){
349
+ result.func = compile_do_stmt((DoStmt *) stmt);
350
+ } else {
351
+ elog(ERROR, "Unexpected node type for PL/pgSQL parsing: %d", nodeTag(stmt));
352
+ }
310
353
 
311
354
  #ifndef DEBUG
312
355
  // Save stderr for result
@@ -354,36 +397,36 @@ PgQueryInternalPlpgsqlFuncAndError pg_query_raw_parse_plpgsql(CreateFunctionStmt
354
397
  return result;
355
398
  }
356
399
 
357
- typedef struct createFunctionStmts
400
+ typedef struct plStmts
358
401
  {
359
- CreateFunctionStmt **stmts;
402
+ Node **stmts;
360
403
  int stmts_buf_size;
361
404
  int stmts_count;
362
- } createFunctionStmts;
405
+ } plStmts;
363
406
 
364
- static bool create_function_stmts_walker(Node *node, createFunctionStmts *state)
407
+ static bool stmts_walker(Node *node, plStmts *state)
365
408
  {
366
409
  bool result;
367
410
  MemoryContext ccxt = CurrentMemoryContext;
368
411
 
369
412
  if (node == NULL) return false;
370
413
 
371
- if (IsA(node, CreateFunctionStmt))
414
+ if (IsA(node, CreateFunctionStmt) || IsA(node, DoStmt))
372
415
  {
373
416
  if (state->stmts_count >= state->stmts_buf_size)
374
417
  {
375
418
  state->stmts_buf_size *= 2;
376
- state->stmts = (CreateFunctionStmt**) repalloc(state->stmts, state->stmts_buf_size * sizeof(CreateFunctionStmt*));
419
+ state->stmts = (Node**) repalloc(state->stmts, state->stmts_buf_size * sizeof(Node*));
377
420
  }
378
- state->stmts[state->stmts_count] = (CreateFunctionStmt *) node;
421
+ state->stmts[state->stmts_count] = (Node *) node;
379
422
  state->stmts_count++;
380
423
  } else if (IsA(node, RawStmt)) {
381
- return create_function_stmts_walker((Node *) ((RawStmt *) node)->stmt, state);
424
+ return stmts_walker((Node *) ((RawStmt *) node)->stmt, state);
382
425
  }
383
426
 
384
427
  PG_TRY();
385
428
  {
386
- result = raw_expression_tree_walker(node, create_function_stmts_walker, (void*) state);
429
+ result = raw_expression_tree_walker(node, stmts_walker, (void*) state);
387
430
  }
388
431
  PG_CATCH();
389
432
  {
@@ -401,7 +444,7 @@ PgQueryPlpgsqlParseResult pg_query_parse_plpgsql(const char* input)
401
444
  MemoryContext ctx = NULL;
402
445
  PgQueryPlpgsqlParseResult result = {0};
403
446
  PgQueryInternalParsetreeAndError parse_result;
404
- createFunctionStmts statements;
447
+ plStmts statements;
405
448
  size_t i;
406
449
 
407
450
  ctx = pg_query_enter_memory_context();
@@ -414,10 +457,10 @@ PgQueryPlpgsqlParseResult pg_query_parse_plpgsql(const char* input)
414
457
  }
415
458
 
416
459
  statements.stmts_buf_size = 100;
417
- statements.stmts = (CreateFunctionStmt**) palloc(statements.stmts_buf_size * sizeof(CreateFunctionStmt*));
460
+ statements.stmts = (Node**) palloc(statements.stmts_buf_size * sizeof(Node*));
418
461
  statements.stmts_count = 0;
419
462
 
420
- create_function_stmts_walker((Node*) parse_result.tree, &statements);
463
+ stmts_walker((Node*) parse_result.tree, &statements);
421
464
 
422
465
  if (statements.stmts_count == 0) {
423
466
  result.plpgsql_funcs = strdup("[]");
@@ -62,6 +62,7 @@
62
62
  #include "utils/inval.h"
63
63
  #include "utils/lsyscache.h"
64
64
  #include "utils/memutils.h"
65
+ #include "utils/snapmgr.h"
65
66
  #include "utils/syscache.h"
66
67
  #include "utils/varlena.h"
67
68
 
@@ -404,6 +404,14 @@ const PQcommMethods *PqCommMethods = NULL;
404
404
  */
405
405
 
406
406
 
407
+ /* --------------------------------
408
+ * pq_buffer_has_data - is any buffered data available to read?
409
+ *
410
+ * This will *not* attempt to read more data.
411
+ * --------------------------------
412
+ */
413
+
414
+
407
415
 
408
416
  /* --------------------------------
409
417
  * pq_startmsgread - begin reading a message from the client.
@@ -345,8 +345,11 @@
345
345
  #define COPY_POINTER_FIELD(fldname, sz) \
346
346
  do { \
347
347
  Size _size = (sz); \
348
- newnode->fldname = palloc(_size); \
349
- memcpy(newnode->fldname, from->fldname, _size); \
348
+ if (_size > 0) \
349
+ { \
350
+ newnode->fldname = palloc(_size); \
351
+ memcpy(newnode->fldname, from->fldname, _size); \
352
+ } \
350
353
  } while (0)
351
354
 
352
355
  /* Copy a parse location field (for Copy, this is same as scalar case) */
@@ -584,12 +587,9 @@ _copyRecursiveUnion(const RecursiveUnion *from)
584
587
  */
585
588
  COPY_SCALAR_FIELD(wtParam);
586
589
  COPY_SCALAR_FIELD(numCols);
587
- if (from->numCols > 0)
588
- {
589
- COPY_POINTER_FIELD(dupColIdx, from->numCols * sizeof(AttrNumber));
590
- COPY_POINTER_FIELD(dupOperators, from->numCols * sizeof(Oid));
591
- COPY_POINTER_FIELD(dupCollations, from->numCols * sizeof(Oid));
592
- }
590
+ COPY_POINTER_FIELD(dupColIdx, from->numCols * sizeof(AttrNumber));
591
+ COPY_POINTER_FIELD(dupOperators, from->numCols * sizeof(Oid));
592
+ COPY_POINTER_FIELD(dupCollations, from->numCols * sizeof(Oid));
593
593
  COPY_SCALAR_FIELD(numGroups);
594
594
 
595
595
  return newnode;
@@ -803,6 +803,7 @@ _copyIndexOnlyScan(const IndexOnlyScan *from)
803
803
  */
804
804
  COPY_SCALAR_FIELD(indexid);
805
805
  COPY_NODE_FIELD(indexqual);
806
+ COPY_NODE_FIELD(recheckqual);
806
807
  COPY_NODE_FIELD(indexorderby);
807
808
  COPY_NODE_FIELD(indextlist);
808
809
  COPY_SCALAR_FIELD(indexorderdir);
@@ -1162,13 +1163,10 @@ _copyMergeJoin(const MergeJoin *from)
1162
1163
  COPY_SCALAR_FIELD(skip_mark_restore);
1163
1164
  COPY_NODE_FIELD(mergeclauses);
1164
1165
  numCols = list_length(from->mergeclauses);
1165
- if (numCols > 0)
1166
- {
1167
- COPY_POINTER_FIELD(mergeFamilies, numCols * sizeof(Oid));
1168
- COPY_POINTER_FIELD(mergeCollations, numCols * sizeof(Oid));
1169
- COPY_POINTER_FIELD(mergeStrategies, numCols * sizeof(int));
1170
- COPY_POINTER_FIELD(mergeNullsFirst, numCols * sizeof(bool));
1171
- }
1166
+ COPY_POINTER_FIELD(mergeFamilies, numCols * sizeof(Oid));
1167
+ COPY_POINTER_FIELD(mergeCollations, numCols * sizeof(Oid));
1168
+ COPY_POINTER_FIELD(mergeStrategies, numCols * sizeof(int));
1169
+ COPY_POINTER_FIELD(mergeNullsFirst, numCols * sizeof(bool));
1172
1170
 
1173
1171
  return newnode;
1174
1172
  }
@@ -1303,12 +1301,9 @@ _copyAgg(const Agg *from)
1303
1301
  COPY_SCALAR_FIELD(aggstrategy);
1304
1302
  COPY_SCALAR_FIELD(aggsplit);
1305
1303
  COPY_SCALAR_FIELD(numCols);
1306
- if (from->numCols > 0)
1307
- {
1308
- COPY_POINTER_FIELD(grpColIdx, from->numCols * sizeof(AttrNumber));
1309
- COPY_POINTER_FIELD(grpOperators, from->numCols * sizeof(Oid));
1310
- COPY_POINTER_FIELD(grpCollations, from->numCols * sizeof(Oid));
1311
- }
1304
+ COPY_POINTER_FIELD(grpColIdx, from->numCols * sizeof(AttrNumber));
1305
+ COPY_POINTER_FIELD(grpOperators, from->numCols * sizeof(Oid));
1306
+ COPY_POINTER_FIELD(grpCollations, from->numCols * sizeof(Oid));
1312
1307
  COPY_SCALAR_FIELD(numGroups);
1313
1308
  COPY_SCALAR_FIELD(transitionSpace);
1314
1309
  COPY_BITMAPSET_FIELD(aggParams);
@@ -1330,19 +1325,13 @@ _copyWindowAgg(const WindowAgg *from)
1330
1325
 
1331
1326
  COPY_SCALAR_FIELD(winref);
1332
1327
  COPY_SCALAR_FIELD(partNumCols);
1333
- if (from->partNumCols > 0)
1334
- {
1335
- COPY_POINTER_FIELD(partColIdx, from->partNumCols * sizeof(AttrNumber));
1336
- COPY_POINTER_FIELD(partOperators, from->partNumCols * sizeof(Oid));
1337
- COPY_POINTER_FIELD(partCollations, from->partNumCols * sizeof(Oid));
1338
- }
1328
+ COPY_POINTER_FIELD(partColIdx, from->partNumCols * sizeof(AttrNumber));
1329
+ COPY_POINTER_FIELD(partOperators, from->partNumCols * sizeof(Oid));
1330
+ COPY_POINTER_FIELD(partCollations, from->partNumCols * sizeof(Oid));
1339
1331
  COPY_SCALAR_FIELD(ordNumCols);
1340
- if (from->ordNumCols > 0)
1341
- {
1342
- COPY_POINTER_FIELD(ordColIdx, from->ordNumCols * sizeof(AttrNumber));
1343
- COPY_POINTER_FIELD(ordOperators, from->ordNumCols * sizeof(Oid));
1344
- COPY_POINTER_FIELD(ordCollations, from->ordNumCols * sizeof(Oid));
1345
- }
1332
+ COPY_POINTER_FIELD(ordColIdx, from->ordNumCols * sizeof(AttrNumber));
1333
+ COPY_POINTER_FIELD(ordOperators, from->ordNumCols * sizeof(Oid));
1334
+ COPY_POINTER_FIELD(ordCollations, from->ordNumCols * sizeof(Oid));
1346
1335
  COPY_SCALAR_FIELD(frameOptions);
1347
1336
  COPY_NODE_FIELD(startOffset);
1348
1337
  COPY_NODE_FIELD(endOffset);
@@ -3510,6 +3499,7 @@ _copyAlterTableCmd(const AlterTableCmd *from)
3510
3499
  COPY_NODE_FIELD(def);
3511
3500
  COPY_SCALAR_FIELD(behavior);
3512
3501
  COPY_SCALAR_FIELD(missing_ok);
3502
+ COPY_SCALAR_FIELD(recurse);
3513
3503
 
3514
3504
  return newnode;
3515
3505
  }
@@ -1335,6 +1335,7 @@ _equalAlterTableCmd(const AlterTableCmd *a, const AlterTableCmd *b)
1335
1335
  COMPARE_NODE_FIELD(def);
1336
1336
  COMPARE_SCALAR_FIELD(behavior);
1337
1337
  COMPARE_SCALAR_FIELD(missing_ok);
1338
+ COMPARE_SCALAR_FIELD(recurse);
1338
1339
 
1339
1340
  return true;
1340
1341
  }
@@ -642,6 +642,18 @@ list_delete_cell(List *list, ListCell *cell)
642
642
  */
643
643
 
644
644
 
645
+ /*
646
+ * Delete the first N cells of the list.
647
+ *
648
+ * The List is pfree'd if the request causes all cells to be deleted.
649
+ */
650
+ #ifndef DEBUG_LIST_MEMORY_USAGE
651
+ #else
652
+ #ifdef CLOBBER_FREED_MEMORY
653
+ #else
654
+ #endif
655
+ #endif
656
+
645
657
  /*
646
658
  * Generate the union of two lists. This is calculated by copying
647
659
  * list1 via list_copy(), then adding to it all the members of list2
@@ -457,7 +457,7 @@
457
457
  REASSIGN = 579,
458
458
  RECHECK = 580,
459
459
  RECURSIVE = 581,
460
- REF = 582,
460
+ REF_P = 582,
461
461
  REFERENCES = 583,
462
462
  REFERENCING = 584,
463
463
  REFRESH = 585,
@@ -934,7 +934,7 @@
934
934
  #define REASSIGN 579
935
935
  #define RECHECK 580
936
936
  #define RECURSIVE 581
937
- #define REF 582
937
+ #define REF_P 582
938
938
  #define REFERENCES 583
939
939
  #define REFERENCING 584
940
940
  #define REFRESH 585
@@ -3354,7 +3354,7 @@ static const char *const yytname[] =
3354
3354
  "PRESERVE", "PREPARE", "PREPARED", "PRIMARY", "PRIOR", "PRIVILEGES",
3355
3355
  "PROCEDURAL", "PROCEDURE", "PROCEDURES", "PROGRAM", "PUBLICATION",
3356
3356
  "QUOTE", "RANGE", "READ", "REAL", "REASSIGN", "RECHECK", "RECURSIVE",
3357
- "REF", "REFERENCES", "REFERENCING", "REFRESH", "REINDEX", "RELATIVE_P",
3357
+ "REF_P", "REFERENCES", "REFERENCING", "REFRESH", "REINDEX", "RELATIVE_P",
3358
3358
  "RELEASE", "RENAME", "REPEATABLE", "REPLACE", "REPLICA", "RESET",
3359
3359
  "RESTART", "RESTRICT", "RETURNING", "RETURNS", "REVOKE", "RIGHT", "ROLE",
3360
3360
  "ROLLBACK", "ROLLUP", "ROUTINE", "ROUTINES", "ROW", "ROWS", "RULE",
@@ -46994,6 +46994,21 @@ insertSelectOptions(SelectStmt *stmt,
46994
46994
  ereport(ERROR,
46995
46995
  (errcode(ERRCODE_SYNTAX_ERROR),
46996
46996
  errmsg("WITH TIES cannot be specified without ORDER BY clause")));
46997
+ if (limitClause->limitOption == LIMIT_OPTION_WITH_TIES && stmt->lockingClause)
46998
+ {
46999
+ ListCell *lc;
47000
+
47001
+ foreach(lc, stmt->lockingClause)
47002
+ {
47003
+ LockingClause *lock = lfirst_node(LockingClause, lc);
47004
+
47005
+ if (lock->waitPolicy == LockWaitSkip)
47006
+ ereport(ERROR,
47007
+ (errcode(ERRCODE_SYNTAX_ERROR),
47008
+ errmsg("%s and %s options cannot be used together",
47009
+ "SKIP LOCKED", "WITH TIES")));
47010
+ }
47011
+ }
46997
47012
  stmt->limitOption = limitClause->limitOption;
46998
47013
  }
46999
47014
  if (withClause)