pg_query 2.1.4 → 2.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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)