pg_query 2.2.0 → 4.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 (467) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +25 -0
  3. data/README.md +59 -31
  4. data/Rakefile +2 -2
  5. data/ext/pg_query/include/access/amapi.h +45 -1
  6. data/ext/pg_query/include/access/attmap.h +1 -1
  7. data/ext/pg_query/include/access/attnum.h +2 -2
  8. data/ext/pg_query/include/access/clog.h +4 -2
  9. data/ext/pg_query/include/access/commit_ts.h +6 -9
  10. data/ext/pg_query/include/access/detoast.h +1 -11
  11. data/ext/pg_query/include/access/genam.h +15 -12
  12. data/ext/pg_query/include/access/gin.h +2 -2
  13. data/ext/pg_query/include/access/htup.h +1 -1
  14. data/ext/pg_query/include/access/htup_details.h +75 -87
  15. data/ext/pg_query/include/access/itup.h +7 -1
  16. data/ext/pg_query/include/access/parallel.h +2 -2
  17. data/ext/pg_query/include/access/printtup.h +1 -1
  18. data/ext/pg_query/include/access/relation.h +1 -1
  19. data/ext/pg_query/include/access/relscan.h +17 -2
  20. data/ext/pg_query/include/access/rmgr.h +30 -3
  21. data/ext/pg_query/include/access/rmgrlist.h +23 -23
  22. data/ext/pg_query/include/access/sdir.h +1 -1
  23. data/ext/pg_query/include/access/skey.h +1 -1
  24. data/ext/pg_query/include/access/stratnum.h +4 -2
  25. data/ext/pg_query/include/access/sysattr.h +1 -1
  26. data/ext/pg_query/include/access/table.h +2 -1
  27. data/ext/pg_query/include/access/tableam.h +272 -20
  28. data/ext/pg_query/include/access/toast_compression.h +73 -0
  29. data/ext/pg_query/include/access/transam.h +123 -13
  30. data/ext/pg_query/include/access/tupconvert.h +1 -1
  31. data/ext/pg_query/include/access/tupdesc.h +1 -1
  32. data/ext/pg_query/include/access/tupmacs.h +3 -3
  33. data/ext/pg_query/include/access/twophase.h +3 -1
  34. data/ext/pg_query/include/access/xact.h +73 -19
  35. data/ext/pg_query/include/access/xlog.h +60 -155
  36. data/ext/pg_query/include/access/xlog_internal.h +40 -13
  37. data/ext/pg_query/include/access/xlogdefs.h +8 -16
  38. data/ext/pg_query/include/access/xlogprefetcher.h +55 -0
  39. data/ext/pg_query/include/access/xlogreader.h +145 -39
  40. data/ext/pg_query/include/access/xlogrecord.h +18 -9
  41. data/ext/pg_query/include/access/xlogrecovery.h +157 -0
  42. data/ext/pg_query/include/c.h +101 -44
  43. data/ext/pg_query/include/catalog/catalog.h +3 -1
  44. data/ext/pg_query/include/catalog/catversion.h +2 -2
  45. data/ext/pg_query/include/catalog/dependency.h +8 -16
  46. data/ext/pg_query/include/catalog/genbki.h +83 -5
  47. data/ext/pg_query/include/catalog/index.h +18 -3
  48. data/ext/pg_query/include/catalog/indexing.h +12 -324
  49. data/ext/pg_query/include/catalog/namespace.h +4 -2
  50. data/ext/pg_query/include/catalog/objectaccess.h +70 -2
  51. data/ext/pg_query/include/catalog/objectaddress.h +11 -6
  52. data/ext/pg_query/include/catalog/pg_aggregate.h +14 -10
  53. data/ext/pg_query/include/catalog/pg_aggregate_d.h +2 -1
  54. data/ext/pg_query/include/catalog/pg_am.h +4 -1
  55. data/ext/pg_query/include/catalog/pg_am_d.h +3 -1
  56. data/ext/pg_query/include/catalog/pg_attribute.h +27 -10
  57. data/ext/pg_query/include/catalog/pg_attribute_d.h +21 -18
  58. data/ext/pg_query/include/catalog/pg_authid.h +7 -2
  59. data/ext/pg_query/include/catalog/pg_authid_d.h +17 -9
  60. data/ext/pg_query/include/catalog/pg_class.h +44 -14
  61. data/ext/pg_query/include/catalog/pg_class_d.h +30 -1
  62. data/ext/pg_query/include/catalog/pg_collation.h +33 -8
  63. data/ext/pg_query/include/catalog/pg_collation_d.h +20 -3
  64. data/ext/pg_query/include/catalog/pg_constraint.h +38 -12
  65. data/ext/pg_query/include/catalog/pg_constraint_d.h +10 -4
  66. data/ext/pg_query/include/catalog/pg_control.h +3 -5
  67. data/ext/pg_query/include/catalog/pg_conversion.h +7 -4
  68. data/ext/pg_query/include/catalog/pg_conversion_d.h +4 -1
  69. data/ext/pg_query/include/catalog/pg_depend.h +11 -7
  70. data/ext/pg_query/include/catalog/pg_depend_d.h +3 -1
  71. data/ext/pg_query/include/catalog/pg_event_trigger.h +9 -3
  72. data/ext/pg_query/include/catalog/pg_event_trigger_d.h +3 -1
  73. data/ext/pg_query/include/catalog/pg_index.h +17 -7
  74. data/ext/pg_query/include/catalog/pg_index_d.h +20 -17
  75. data/ext/pg_query/include/catalog/pg_language.h +10 -5
  76. data/ext/pg_query/include/catalog/pg_language_d.h +3 -1
  77. data/ext/pg_query/include/catalog/pg_namespace.h +7 -2
  78. data/ext/pg_query/include/catalog/pg_namespace_d.h +3 -1
  79. data/ext/pg_query/include/catalog/pg_opclass.h +8 -5
  80. data/ext/pg_query/include/catalog/pg_opclass_d.h +3 -1
  81. data/ext/pg_query/include/catalog/pg_operator.h +18 -15
  82. data/ext/pg_query/include/catalog/pg_operator_d.h +37 -1
  83. data/ext/pg_query/include/catalog/pg_opfamily.h +6 -3
  84. data/ext/pg_query/include/catalog/pg_opfamily_d.h +3 -1
  85. data/ext/pg_query/include/catalog/pg_parameter_acl.h +60 -0
  86. data/ext/pg_query/include/catalog/pg_parameter_acl_d.h +34 -0
  87. data/ext/pg_query/include/catalog/pg_partitioned_table.h +20 -9
  88. data/ext/pg_query/include/catalog/pg_partitioned_table_d.h +2 -1
  89. data/ext/pg_query/include/catalog/pg_proc.h +20 -11
  90. data/ext/pg_query/include/catalog/pg_proc_d.h +10 -8
  91. data/ext/pg_query/include/catalog/pg_publication.h +50 -7
  92. data/ext/pg_query/include/catalog/pg_publication_d.h +3 -1
  93. data/ext/pg_query/include/catalog/pg_replication_origin.h +6 -1
  94. data/ext/pg_query/include/catalog/pg_replication_origin_d.h +5 -1
  95. data/ext/pg_query/include/catalog/pg_statistic.h +19 -12
  96. data/ext/pg_query/include/catalog/pg_statistic_d.h +2 -1
  97. data/ext/pg_query/include/catalog/pg_statistic_ext.h +19 -5
  98. data/ext/pg_query/include/catalog/pg_statistic_ext_d.h +7 -2
  99. data/ext/pg_query/include/catalog/pg_transform.h +8 -5
  100. data/ext/pg_query/include/catalog/pg_transform_d.h +3 -1
  101. data/ext/pg_query/include/catalog/pg_trigger.h +24 -8
  102. data/ext/pg_query/include/catalog/pg_trigger_d.h +4 -1
  103. data/ext/pg_query/include/catalog/pg_ts_config.h +6 -3
  104. data/ext/pg_query/include/catalog/pg_ts_config_d.h +3 -1
  105. data/ext/pg_query/include/catalog/pg_ts_dict.h +8 -3
  106. data/ext/pg_query/include/catalog/pg_ts_dict_d.h +3 -1
  107. data/ext/pg_query/include/catalog/pg_ts_parser.h +6 -3
  108. data/ext/pg_query/include/catalog/pg_ts_parser_d.h +3 -1
  109. data/ext/pg_query/include/catalog/pg_ts_template.h +6 -3
  110. data/ext/pg_query/include/catalog/pg_ts_template_d.h +3 -1
  111. data/ext/pg_query/include/catalog/pg_type.h +55 -24
  112. data/ext/pg_query/include/catalog/pg_type_d.h +70 -31
  113. data/ext/pg_query/include/catalog/storage.h +5 -3
  114. data/ext/pg_query/include/commands/async.h +3 -4
  115. data/ext/pg_query/include/commands/dbcommands.h +2 -1
  116. data/ext/pg_query/include/commands/defrem.h +11 -24
  117. data/ext/pg_query/include/commands/event_trigger.h +2 -2
  118. data/ext/pg_query/include/commands/explain.h +1 -1
  119. data/ext/pg_query/include/commands/prepare.h +1 -1
  120. data/ext/pg_query/include/commands/tablespace.h +2 -2
  121. data/ext/pg_query/include/commands/trigger.h +18 -16
  122. data/ext/pg_query/include/commands/user.h +2 -2
  123. data/ext/pg_query/include/commands/vacuum.h +88 -41
  124. data/ext/pg_query/include/commands/variable.h +1 -1
  125. data/ext/pg_query/include/common/file_perm.h +4 -4
  126. data/ext/pg_query/include/common/hashfn.h +1 -1
  127. data/ext/pg_query/include/common/ip.h +1 -7
  128. data/ext/pg_query/include/common/keywords.h +2 -6
  129. data/ext/pg_query/include/common/kwlookup.h +1 -1
  130. data/ext/pg_query/include/common/pg_prng.h +60 -0
  131. data/ext/pg_query/include/common/relpath.h +2 -2
  132. data/ext/pg_query/include/common/string.h +24 -1
  133. data/ext/pg_query/include/common/unicode_combining_table.h +114 -2
  134. data/ext/pg_query/include/common/unicode_east_asian_fw_table.h +125 -0
  135. data/ext/pg_query/include/datatype/timestamp.h +40 -1
  136. data/ext/pg_query/include/executor/execdesc.h +1 -1
  137. data/ext/pg_query/include/executor/executor.h +65 -22
  138. data/ext/pg_query/include/executor/functions.h +17 -3
  139. data/ext/pg_query/include/executor/instrument.h +33 -16
  140. data/ext/pg_query/include/executor/spi.h +41 -3
  141. data/ext/pg_query/include/executor/tablefunc.h +1 -1
  142. data/ext/pg_query/include/executor/tuptable.h +1 -1
  143. data/ext/pg_query/include/fmgr.h +13 -7
  144. data/ext/pg_query/include/funcapi.h +16 -4
  145. data/ext/pg_query/include/getaddrinfo.h +1 -1
  146. data/ext/pg_query/include/jit/jit.h +11 -11
  147. data/ext/pg_query/include/kwlist_d.h +517 -494
  148. data/ext/pg_query/include/lib/dshash.h +112 -0
  149. data/ext/pg_query/include/lib/ilist.h +20 -1
  150. data/ext/pg_query/include/lib/pairingheap.h +1 -1
  151. data/ext/pg_query/include/lib/simplehash.h +140 -15
  152. data/ext/pg_query/include/lib/sort_template.h +432 -0
  153. data/ext/pg_query/include/lib/stringinfo.h +1 -1
  154. data/ext/pg_query/include/libpq/auth.h +6 -4
  155. data/ext/pg_query/include/libpq/crypt.h +5 -4
  156. data/ext/pg_query/include/libpq/hba.h +43 -4
  157. data/ext/pg_query/include/libpq/libpq-be.h +23 -6
  158. data/ext/pg_query/include/libpq/libpq.h +30 -20
  159. data/ext/pg_query/include/libpq/pqcomm.h +17 -31
  160. data/ext/pg_query/include/libpq/pqformat.h +1 -1
  161. data/ext/pg_query/include/libpq/pqsignal.h +4 -4
  162. data/ext/pg_query/include/mb/pg_wchar.h +105 -23
  163. data/ext/pg_query/include/mb/stringinfo_mb.h +1 -1
  164. data/ext/pg_query/include/miscadmin.h +47 -41
  165. data/ext/pg_query/include/nodes/bitmapset.h +1 -1
  166. data/ext/pg_query/include/nodes/execnodes.h +270 -78
  167. data/ext/pg_query/include/nodes/extensible.h +4 -2
  168. data/ext/pg_query/include/nodes/lockoptions.h +1 -1
  169. data/ext/pg_query/include/nodes/makefuncs.h +7 -6
  170. data/ext/pg_query/include/nodes/memnodes.h +5 -3
  171. data/ext/pg_query/include/nodes/nodeFuncs.h +1 -1
  172. data/ext/pg_query/include/nodes/nodes.h +30 -11
  173. data/ext/pg_query/include/nodes/params.h +1 -1
  174. data/ext/pg_query/include/nodes/parsenodes.h +322 -90
  175. data/ext/pg_query/include/nodes/pathnodes.h +243 -66
  176. data/ext/pg_query/include/nodes/pg_list.h +75 -69
  177. data/ext/pg_query/include/nodes/plannodes.h +111 -28
  178. data/ext/pg_query/include/nodes/primnodes.h +99 -47
  179. data/ext/pg_query/include/nodes/print.h +1 -1
  180. data/ext/pg_query/include/nodes/tidbitmap.h +1 -1
  181. data/ext/pg_query/include/nodes/value.h +58 -39
  182. data/ext/pg_query/include/optimizer/cost.h +9 -2
  183. data/ext/pg_query/include/optimizer/geqo.h +9 -7
  184. data/ext/pg_query/include/optimizer/geqo_gene.h +1 -1
  185. data/ext/pg_query/include/optimizer/optimizer.h +25 -17
  186. data/ext/pg_query/include/optimizer/paths.h +6 -6
  187. data/ext/pg_query/include/optimizer/planmain.h +15 -14
  188. data/ext/pg_query/include/parser/analyze.h +19 -5
  189. data/ext/pg_query/include/parser/gram.h +947 -913
  190. data/ext/pg_query/include/parser/gramparse.h +1 -1
  191. data/ext/pg_query/include/parser/kwlist.h +463 -453
  192. data/ext/pg_query/include/parser/parse_agg.h +2 -7
  193. data/ext/pg_query/include/parser/parse_coerce.h +3 -1
  194. data/ext/pg_query/include/parser/parse_expr.h +2 -3
  195. data/ext/pg_query/include/parser/parse_func.h +2 -1
  196. data/ext/pg_query/include/parser/parse_node.h +21 -9
  197. data/ext/pg_query/include/parser/parse_oper.h +1 -3
  198. data/ext/pg_query/include/parser/parse_relation.h +5 -4
  199. data/ext/pg_query/include/parser/parse_type.h +1 -1
  200. data/ext/pg_query/include/parser/parser.h +31 -4
  201. data/ext/pg_query/include/parser/parsetree.h +1 -1
  202. data/ext/pg_query/include/parser/scanner.h +1 -1
  203. data/ext/pg_query/include/parser/scansup.h +2 -5
  204. data/ext/pg_query/include/partitioning/partdefs.h +1 -1
  205. data/ext/pg_query/include/pg_config.h +83 -41
  206. data/ext/pg_query/include/pg_config_manual.h +74 -21
  207. data/ext/pg_query/include/pg_getopt.h +6 -6
  208. data/ext/pg_query/include/pg_query.h +5 -4
  209. data/ext/pg_query/include/pg_query_enum_defs.c +358 -241
  210. data/ext/pg_query/include/pg_query_fingerprint_conds.c +44 -7
  211. data/ext/pg_query/include/pg_query_fingerprint_defs.c +939 -113
  212. data/ext/pg_query/include/pg_query_outfuncs_conds.c +43 -13
  213. data/ext/pg_query/include/pg_query_outfuncs_defs.c +151 -26
  214. data/ext/pg_query/include/pg_query_readfuncs_conds.c +11 -2
  215. data/ext/pg_query/include/pg_query_readfuncs_defs.c +173 -30
  216. data/ext/pg_query/include/pg_trace.h +1 -1
  217. data/ext/pg_query/include/pgstat.h +449 -1238
  218. data/ext/pg_query/include/pgtime.h +14 -4
  219. data/ext/pg_query/include/pl_gram.h +126 -128
  220. data/ext/pg_query/include/pl_reserved_kwlist.h +1 -1
  221. data/ext/pg_query/include/pl_reserved_kwlist_d.h +10 -10
  222. data/ext/pg_query/include/pl_unreserved_kwlist.h +2 -3
  223. data/ext/pg_query/include/pl_unreserved_kwlist_d.h +54 -56
  224. data/ext/pg_query/include/plerrcodes.h +9 -1
  225. data/ext/pg_query/include/plpgsql.h +52 -54
  226. data/ext/pg_query/include/port/atomics/arch-arm.h +7 -1
  227. data/ext/pg_query/include/port/atomics/arch-ppc.h +1 -1
  228. data/ext/pg_query/include/port/atomics/arch-x86.h +1 -1
  229. data/ext/pg_query/include/port/atomics/fallback.h +1 -1
  230. data/ext/pg_query/include/port/atomics/generic-gcc.h +3 -3
  231. data/ext/pg_query/include/port/atomics/generic.h +1 -1
  232. data/ext/pg_query/include/port/atomics.h +1 -1
  233. data/ext/pg_query/include/port/pg_bitutils.h +40 -10
  234. data/ext/pg_query/include/port/pg_bswap.h +1 -1
  235. data/ext/pg_query/include/port/pg_crc32c.h +1 -1
  236. data/ext/pg_query/include/port.h +71 -46
  237. data/ext/pg_query/include/portability/instr_time.h +1 -1
  238. data/ext/pg_query/include/postgres.h +60 -16
  239. data/ext/pg_query/include/postmaster/autovacuum.h +17 -17
  240. data/ext/pg_query/include/postmaster/auxprocess.h +20 -0
  241. data/ext/pg_query/include/postmaster/bgworker.h +2 -1
  242. data/ext/pg_query/include/postmaster/bgworker_internals.h +2 -2
  243. data/ext/pg_query/include/postmaster/bgwriter.h +5 -5
  244. data/ext/pg_query/include/postmaster/fork_process.h +1 -1
  245. data/ext/pg_query/include/postmaster/interrupt.h +1 -1
  246. data/ext/pg_query/include/postmaster/pgarch.h +42 -8
  247. data/ext/pg_query/include/postmaster/postmaster.h +18 -17
  248. data/ext/pg_query/include/postmaster/startup.h +39 -0
  249. data/ext/pg_query/include/postmaster/syslogger.h +15 -10
  250. data/ext/pg_query/include/postmaster/walwriter.h +3 -3
  251. data/ext/pg_query/include/protobuf/pg_query.pb-c.h +1419 -914
  252. data/ext/pg_query/include/protobuf/pg_query.pb.h +43678 -32769
  253. data/ext/pg_query/include/regex/regex.h +18 -16
  254. data/ext/pg_query/include/replication/logicallauncher.h +3 -5
  255. data/ext/pg_query/include/replication/logicalproto.h +161 -17
  256. data/ext/pg_query/include/replication/logicalworker.h +1 -1
  257. data/ext/pg_query/include/replication/origin.h +7 -7
  258. data/ext/pg_query/include/replication/reorderbuffer.h +259 -42
  259. data/ext/pg_query/include/replication/slot.h +22 -11
  260. data/ext/pg_query/include/replication/syncrep.h +5 -5
  261. data/ext/pg_query/include/replication/walreceiver.h +145 -13
  262. data/ext/pg_query/include/replication/walsender.h +8 -8
  263. data/ext/pg_query/include/rewrite/prs2lock.h +1 -1
  264. data/ext/pg_query/include/rewrite/rewriteHandler.h +1 -3
  265. data/ext/pg_query/include/rewrite/rewriteManip.h +1 -1
  266. data/ext/pg_query/include/rewrite/rewriteSupport.h +1 -1
  267. data/ext/pg_query/include/storage/backendid.h +3 -3
  268. data/ext/pg_query/include/storage/block.h +4 -10
  269. data/ext/pg_query/include/storage/buf.h +1 -1
  270. data/ext/pg_query/include/storage/bufmgr.h +19 -14
  271. data/ext/pg_query/include/storage/bufpage.h +6 -8
  272. data/ext/pg_query/include/storage/condition_variable.h +13 -2
  273. data/ext/pg_query/include/storage/dsm.h +4 -1
  274. data/ext/pg_query/include/storage/dsm_impl.h +3 -2
  275. data/ext/pg_query/include/storage/fd.h +33 -3
  276. data/ext/pg_query/include/storage/fileset.h +40 -0
  277. data/ext/pg_query/include/storage/ipc.h +4 -1
  278. data/ext/pg_query/include/storage/item.h +1 -1
  279. data/ext/pg_query/include/storage/itemid.h +1 -1
  280. data/ext/pg_query/include/storage/itemptr.h +3 -1
  281. data/ext/pg_query/include/storage/large_object.h +2 -2
  282. data/ext/pg_query/include/storage/latch.h +9 -13
  283. data/ext/pg_query/include/storage/lmgr.h +2 -1
  284. data/ext/pg_query/include/storage/lock.h +11 -8
  285. data/ext/pg_query/include/storage/lockdefs.h +2 -2
  286. data/ext/pg_query/include/storage/lwlock.h +5 -32
  287. data/ext/pg_query/include/storage/lwlocknames.h +0 -1
  288. data/ext/pg_query/include/storage/off.h +1 -1
  289. data/ext/pg_query/include/storage/pg_sema.h +1 -1
  290. data/ext/pg_query/include/storage/pg_shmem.h +9 -7
  291. data/ext/pg_query/include/storage/pmsignal.h +15 -4
  292. data/ext/pg_query/include/storage/predicate.h +4 -4
  293. data/ext/pg_query/include/storage/proc.h +173 -59
  294. data/ext/pg_query/include/storage/procarray.h +98 -0
  295. data/ext/pg_query/include/storage/proclist_types.h +1 -1
  296. data/ext/pg_query/include/storage/procsignal.h +3 -7
  297. data/ext/pg_query/include/storage/relfilenode.h +1 -1
  298. data/ext/pg_query/include/storage/s_lock.h +60 -21
  299. data/ext/pg_query/include/storage/sharedfileset.h +3 -11
  300. data/ext/pg_query/include/storage/shm_mq.h +5 -4
  301. data/ext/pg_query/include/storage/shm_toc.h +1 -1
  302. data/ext/pg_query/include/storage/shmem.h +1 -1
  303. data/ext/pg_query/include/storage/sinval.h +3 -3
  304. data/ext/pg_query/include/storage/sinvaladt.h +1 -1
  305. data/ext/pg_query/include/storage/smgr.h +10 -8
  306. data/ext/pg_query/include/storage/spin.h +2 -2
  307. data/ext/pg_query/include/storage/standby.h +13 -6
  308. data/ext/pg_query/include/storage/standbydefs.h +2 -2
  309. data/ext/pg_query/include/storage/sync.h +7 -3
  310. data/ext/pg_query/include/tcop/cmdtag.h +1 -1
  311. data/ext/pg_query/include/tcop/cmdtaglist.h +3 -2
  312. data/ext/pg_query/include/tcop/deparse_utility.h +1 -1
  313. data/ext/pg_query/include/tcop/dest.h +1 -1
  314. data/ext/pg_query/include/tcop/fastpath.h +1 -2
  315. data/ext/pg_query/include/tcop/pquery.h +1 -1
  316. data/ext/pg_query/include/tcop/tcopprot.h +19 -11
  317. data/ext/pg_query/include/tcop/utility.h +7 -3
  318. data/ext/pg_query/include/tsearch/ts_cache.h +2 -2
  319. data/ext/pg_query/include/utils/acl.h +24 -3
  320. data/ext/pg_query/include/utils/aclchk_internal.h +1 -1
  321. data/ext/pg_query/include/utils/array.h +7 -2
  322. data/ext/pg_query/include/utils/backend_progress.h +44 -0
  323. data/ext/pg_query/include/utils/backend_status.h +321 -0
  324. data/ext/pg_query/include/utils/builtins.h +10 -11
  325. data/ext/pg_query/include/utils/bytea.h +3 -2
  326. data/ext/pg_query/include/utils/catcache.h +1 -1
  327. data/ext/pg_query/include/utils/date.h +1 -1
  328. data/ext/pg_query/include/utils/datetime.h +8 -7
  329. data/ext/pg_query/include/utils/datum.h +9 -1
  330. data/ext/pg_query/include/utils/dsa.h +1 -1
  331. data/ext/pg_query/include/utils/dynahash.h +4 -3
  332. data/ext/pg_query/include/utils/elog.h +52 -21
  333. data/ext/pg_query/include/utils/errcodes.h +2 -0
  334. data/ext/pg_query/include/utils/expandeddatum.h +1 -1
  335. data/ext/pg_query/include/utils/expandedrecord.h +1 -1
  336. data/ext/pg_query/include/utils/float.h +7 -7
  337. data/ext/pg_query/include/utils/fmgroids.h +1300 -696
  338. data/ext/pg_query/include/utils/fmgrprotos.h +199 -16
  339. data/ext/pg_query/include/utils/fmgrtab.h +6 -5
  340. data/ext/pg_query/include/utils/guc.h +69 -43
  341. data/ext/pg_query/include/utils/guc_tables.h +23 -19
  342. data/ext/pg_query/include/utils/hsearch.h +15 -11
  343. data/ext/pg_query/include/utils/inval.h +4 -1
  344. data/ext/pg_query/include/utils/lsyscache.h +11 -1
  345. data/ext/pg_query/include/utils/memdebug.h +1 -1
  346. data/ext/pg_query/include/utils/memutils.h +8 -3
  347. data/ext/pg_query/include/utils/numeric.h +19 -5
  348. data/ext/pg_query/include/utils/palloc.h +25 -3
  349. data/ext/pg_query/include/utils/partcache.h +1 -1
  350. data/ext/pg_query/include/utils/pg_locale.h +17 -9
  351. data/ext/pg_query/include/utils/pg_lsn.h +1 -1
  352. data/ext/pg_query/include/utils/pgstat_internal.h +784 -0
  353. data/ext/pg_query/include/utils/pidfile.h +1 -1
  354. data/ext/pg_query/include/utils/plancache.h +6 -5
  355. data/ext/pg_query/include/utils/portal.h +10 -12
  356. data/ext/pg_query/include/utils/ps_status.h +1 -1
  357. data/ext/pg_query/include/utils/queryenvironment.h +1 -1
  358. data/ext/pg_query/include/utils/queryjumble.h +88 -0
  359. data/ext/pg_query/include/utils/regproc.h +14 -3
  360. data/ext/pg_query/include/utils/rel.h +71 -19
  361. data/ext/pg_query/include/utils/relcache.h +8 -5
  362. data/ext/pg_query/include/utils/reltrigger.h +1 -1
  363. data/ext/pg_query/include/utils/resowner.h +1 -1
  364. data/ext/pg_query/include/utils/rls.h +2 -2
  365. data/ext/pg_query/include/utils/ruleutils.h +4 -1
  366. data/ext/pg_query/include/utils/sharedtuplestore.h +1 -1
  367. data/ext/pg_query/include/utils/snapmgr.h +34 -14
  368. data/ext/pg_query/include/utils/snapshot.h +14 -1
  369. data/ext/pg_query/include/utils/sortsupport.h +117 -2
  370. data/ext/pg_query/include/utils/syscache.h +6 -1
  371. data/ext/pg_query/include/utils/timeout.h +11 -4
  372. data/ext/pg_query/include/utils/timestamp.h +6 -5
  373. data/ext/pg_query/include/utils/tuplesort.h +25 -11
  374. data/ext/pg_query/include/utils/tuplestore.h +2 -2
  375. data/ext/pg_query/include/utils/typcache.h +24 -17
  376. data/ext/pg_query/include/utils/tzparser.h +1 -1
  377. data/ext/pg_query/include/utils/varlena.h +5 -3
  378. data/ext/pg_query/include/utils/wait_event.h +289 -0
  379. data/ext/pg_query/include/utils/xml.h +4 -4
  380. data/ext/pg_query/pg_query.pb-c.c +4302 -2304
  381. data/ext/pg_query/pg_query_deparse.c +1106 -373
  382. data/ext/pg_query/pg_query_fingerprint.c +30 -10
  383. data/ext/pg_query/pg_query_json_plpgsql.c +0 -25
  384. data/ext/pg_query/pg_query_normalize.c +1 -1
  385. data/ext/pg_query/pg_query_outfuncs_json.c +54 -16
  386. data/ext/pg_query/pg_query_outfuncs_protobuf.c +70 -10
  387. data/ext/pg_query/pg_query_parse.c +1 -1
  388. data/ext/pg_query/pg_query_readfuncs_protobuf.c +42 -8
  389. data/ext/pg_query/pg_query_scan.c +2 -1
  390. data/ext/pg_query/pg_query_split.c +3 -2
  391. data/ext/pg_query/src_backend_catalog_namespace.c +20 -9
  392. data/ext/pg_query/src_backend_catalog_pg_proc.c +4 -1
  393. data/ext/pg_query/src_backend_commands_define.c +11 -1
  394. data/ext/pg_query/src_backend_nodes_bitmapset.c +3 -1
  395. data/ext/pg_query/src_backend_nodes_copyfuncs.c +401 -76
  396. data/ext/pg_query/src_backend_nodes_equalfuncs.c +290 -46
  397. data/ext/pg_query/src_backend_nodes_extensible.c +1 -1
  398. data/ext/pg_query/src_backend_nodes_list.c +74 -11
  399. data/ext/pg_query/src_backend_nodes_makefuncs.c +5 -4
  400. data/ext/pg_query/src_backend_nodes_nodeFuncs.c +55 -12
  401. data/ext/pg_query/src_backend_nodes_value.c +28 -19
  402. data/ext/pg_query/src_backend_parser_gram.c +33874 -31261
  403. data/ext/pg_query/src_backend_parser_parser.c +26 -7
  404. data/ext/pg_query/src_backend_parser_scan.c +172 -209
  405. data/ext/pg_query/src_backend_parser_scansup.c +4 -28
  406. data/ext/pg_query/src_backend_postmaster_postmaster.c +77 -106
  407. data/ext/pg_query/src_backend_storage_ipc_ipc.c +13 -4
  408. data/ext/pg_query/src_backend_storage_lmgr_s_lock.c +5 -4
  409. data/ext/pg_query/src_backend_tcop_postgres.c +62 -23
  410. data/ext/pg_query/src_backend_utils_activity_pgstat_database.c +140 -0
  411. data/ext/pg_query/src_backend_utils_adt_datum.c +13 -1
  412. data/ext/pg_query/src_backend_utils_adt_expandeddatum.c +1 -1
  413. data/ext/pg_query/src_backend_utils_adt_format_type.c +6 -2
  414. data/ext/pg_query/src_backend_utils_adt_ruleutils.c +71 -5
  415. data/ext/pg_query/src_backend_utils_error_assert.c +16 -14
  416. data/ext/pg_query/src_backend_utils_error_elog.c +172 -99
  417. data/ext/pg_query/src_backend_utils_fmgr_fmgr.c +12 -17
  418. data/ext/pg_query/src_backend_utils_hash_dynahash.c +40 -10
  419. data/ext/pg_query/src_backend_utils_init_globals.c +5 -5
  420. data/ext/pg_query/src_backend_utils_mb_mbutils.c +55 -66
  421. data/ext/pg_query/src_backend_utils_misc_guc.c +206 -45
  422. data/ext/pg_query/src_backend_utils_mmgr_aset.c +7 -5
  423. data/ext/pg_query/src_backend_utils_mmgr_mcxt.c +123 -35
  424. data/ext/pg_query/src_common_encnames.c +1 -1
  425. data/ext/pg_query/src_common_hashfn.c +3 -3
  426. data/ext/pg_query/src_common_keywords.c +15 -2
  427. data/ext/pg_query/src_common_kwlist_d.h +517 -494
  428. data/ext/pg_query/src_common_kwlookup.c +1 -1
  429. data/ext/pg_query/src_common_pg_prng.c +152 -0
  430. data/ext/pg_query/src_common_psprintf.c +1 -1
  431. data/ext/pg_query/src_common_string.c +7 -1
  432. data/ext/pg_query/src_common_stringinfo.c +1 -1
  433. data/ext/pg_query/src_common_wchar.c +701 -109
  434. data/ext/pg_query/src_pl_plpgsql_src_pl_comp.c +45 -20
  435. data/ext/pg_query/src_pl_plpgsql_src_pl_funcs.c +1 -18
  436. data/ext/pg_query/src_pl_plpgsql_src_pl_gram.c +1233 -1259
  437. data/ext/pg_query/src_pl_plpgsql_src_pl_handler.c +1 -1
  438. data/ext/pg_query/src_pl_plpgsql_src_pl_reserved_kwlist_d.h +10 -10
  439. data/ext/pg_query/src_pl_plpgsql_src_pl_scanner.c +2 -2
  440. data/ext/pg_query/src_pl_plpgsql_src_pl_unreserved_kwlist_d.h +54 -56
  441. data/ext/pg_query/src_port_pg_bitutils.c +41 -31
  442. data/ext/pg_query/src_port_pgsleep.c +1 -1
  443. data/ext/pg_query/src_port_pgstrcasecmp.c +1 -1
  444. data/ext/pg_query/src_port_qsort.c +12 -224
  445. data/ext/pg_query/src_port_snprintf.c +37 -13
  446. data/ext/pg_query/src_port_strerror.c +9 -19
  447. data/ext/pg_query/src_port_strnlen.c +1 -1
  448. data/lib/pg_query/filter_columns.rb +1 -1
  449. data/lib/pg_query/fingerprint.rb +5 -1
  450. data/lib/pg_query/node.rb +2 -2
  451. data/lib/pg_query/param_refs.rb +1 -1
  452. data/lib/pg_query/parse.rb +20 -8
  453. data/lib/pg_query/pg_query_pb.rb +1108 -942
  454. data/lib/pg_query/treewalker.rb +6 -0
  455. data/lib/pg_query/truncate.rb +1 -1
  456. data/lib/pg_query/version.rb +1 -1
  457. metadata +27 -17
  458. data/ext/pg_query/include/access/xloginsert.h +0 -64
  459. data/ext/pg_query/include/bootstrap/bootstrap.h +0 -62
  460. data/ext/pg_query/include/parser/parse_clause.h +0 -54
  461. data/ext/pg_query/include/parser/parse_collate.h +0 -27
  462. data/ext/pg_query/include/parser/parse_target.h +0 -46
  463. data/ext/pg_query/pg_query_ruby_freebsd.sym +0 -2
  464. data/ext/pg_query/src_backend_libpq_pqcomm.c +0 -659
  465. data/ext/pg_query/src_backend_parser_parse_expr.c +0 -313
  466. data/ext/pg_query/src_port_erand48.c +0 -127
  467. data/ext/pg_query/src_port_random.c +0 -31
@@ -11,7 +11,6 @@
11
11
  #include "common/keywords.h"
12
12
  #include "common/kwlookup.h"
13
13
  #include "lib/stringinfo.h"
14
- #include "limits.h"
15
14
  #include "nodes/nodes.h"
16
15
  #include "nodes/parsenodes.h"
17
16
  #include "nodes/pg_list.h"
@@ -32,6 +31,7 @@ typedef enum DeparseNodeContext {
32
31
  DEPARSE_NODE_CONTEXT_XMLNAMESPACES,
33
32
  DEPARSE_NODE_CONTEXT_CREATE_TYPE,
34
33
  DEPARSE_NODE_CONTEXT_ALTER_TYPE,
34
+ DEPARSE_NODE_CONTEXT_SET_STATEMENT,
35
35
  // Identifier vs constant context
36
36
  DEPARSE_NODE_CONTEXT_IDENTIFIER,
37
37
  DEPARSE_NODE_CONTEXT_CONSTANT
@@ -160,8 +160,9 @@ static void deparseRangeSubselect(StringInfo str, RangeSubselect *range_subselec
160
160
  static void deparseRangeFunction(StringInfo str, RangeFunction *range_func);
161
161
  static void deparseAArrayExpr(StringInfo str, A_ArrayExpr * array_expr);
162
162
  static void deparseRowExpr(StringInfo str, RowExpr *row_expr);
163
- static void deparseTypeCast(StringInfo str, TypeCast *type_cast);
163
+ static void deparseTypeCast(StringInfo str, TypeCast *type_cast, DeparseNodeContext context);
164
164
  static void deparseTypeName(StringInfo str, TypeName *type_name);
165
+ static void deparseIntervalTypmods(StringInfo str, TypeName *type_name);
165
166
  static void deparseNullTest(StringInfo str, NullTest *null_test);
166
167
  static void deparseCaseExpr(StringInfo str, CaseExpr *case_expr);
167
168
  static void deparseCaseWhen(StringInfo str, CaseWhen *case_when);
@@ -204,7 +205,7 @@ static void deparsePreparableStmt(StringInfo str, Node *node);
204
205
  static void deparseRuleActionStmt(StringInfo str, Node *node);
205
206
  static void deparseExplainableStmt(StringInfo str, Node *node);
206
207
  static void deparseStmt(StringInfo str, Node *node);
207
- static void deparseValue(StringInfo str, Value *value, DeparseNodeContext context);
208
+ static void deparseValue(StringInfo str, union ValUnion *value, DeparseNodeContext context);
208
209
 
209
210
  // "any_name" in gram.y
210
211
  static void deparseAnyName(StringInfo str, List *parts)
@@ -249,6 +250,8 @@ static void deparseAnyNameSkipLast(StringInfo str, List *parts)
249
250
  // "a_expr" / "b_expr" in gram.y
250
251
  static void deparseExpr(StringInfo str, Node *node)
251
252
  {
253
+ if (node == NULL)
254
+ return;
252
255
  switch (nodeTag(node))
253
256
  {
254
257
  case T_FuncCall:
@@ -258,7 +261,7 @@ static void deparseExpr(StringInfo str, Node *node)
258
261
  deparseXmlExpr(str, castNode(XmlExpr, node));
259
262
  break;
260
263
  case T_TypeCast:
261
- deparseTypeCast(str, castNode(TypeCast, node));
264
+ deparseTypeCast(str, castNode(TypeCast, node), DEPARSE_NODE_CONTEXT_NONE);
262
265
  break;
263
266
  case T_A_Const:
264
267
  deparseAConst(str, castNode(A_Const, node));
@@ -339,7 +342,7 @@ static void deparseCExpr(StringInfo str, Node *node)
339
342
  deparseAConst(str, castNode(A_Const, node));
340
343
  break;
341
344
  case T_TypeCast:
342
- deparseTypeCast(str, castNode(TypeCast, node));
345
+ deparseTypeCast(str, castNode(TypeCast, node), DEPARSE_NODE_CONTEXT_NONE);
343
346
  break;
344
347
  case T_A_Expr:
345
348
  appendStringInfoChar(str, '(');
@@ -381,7 +384,6 @@ static void deparseCExpr(StringInfo str, Node *node)
381
384
  static void deparseExprList(StringInfo str, List *exprs)
382
385
  {
383
386
  ListCell *lc;
384
-
385
387
  foreach(lc, exprs)
386
388
  {
387
389
  deparseExpr(str, lfirst(lc));
@@ -460,15 +462,15 @@ static void deparseSimpleTypename(StringInfo str, Node *node)
460
462
  }
461
463
 
462
464
  // "NumericOnly" in gram.y
463
- static void deparseNumericOnly(StringInfo str, Value *value)
465
+ static void deparseNumericOnly(StringInfo str, union ValUnion *value)
464
466
  {
465
467
  switch (nodeTag(value))
466
468
  {
467
469
  case T_Integer:
468
- appendStringInfo(str, "%d", value->val.ival);
470
+ appendStringInfo(str, "%d", value->ival.ival);
469
471
  break;
470
472
  case T_Float:
471
- appendStringInfoString(str, value->val.str);
473
+ appendStringInfoString(str, value->sval.sval);
472
474
  break;
473
475
  default:
474
476
  Assert(false);
@@ -482,7 +484,7 @@ static void deparseNumericOnlyList(StringInfo str, List *l)
482
484
 
483
485
  foreach(lc, l)
484
486
  {
485
- deparseNumericOnly(str, (Value *) lfirst(lc));
487
+ deparseNumericOnly(str, (union ValUnion *) lfirst(lc));
486
488
  if (lnext(l, lc))
487
489
  appendStringInfoString(str, ", ");
488
490
  }
@@ -501,25 +503,25 @@ static void deparseSeqOptElem(StringInfo str, DefElem *def_elem)
501
503
  else if (strcmp(def_elem->defname, "cache") == 0)
502
504
  {
503
505
  appendStringInfoString(str, "CACHE ");
504
- deparseNumericOnly(str, (Value *) def_elem->arg);
506
+ deparseNumericOnly(str, (union ValUnion *) def_elem->arg);
505
507
  }
506
- else if (strcmp(def_elem->defname, "cycle") == 0 && intVal(def_elem->arg) == 1)
508
+ else if (strcmp(def_elem->defname, "cycle") == 0 && boolVal(def_elem->arg))
507
509
  {
508
510
  appendStringInfoString(str, "CYCLE");
509
511
  }
510
- else if (strcmp(def_elem->defname, "cycle") == 0 && intVal(def_elem->arg) == 0)
512
+ else if (strcmp(def_elem->defname, "cycle") == 0 && !boolVal(def_elem->arg))
511
513
  {
512
514
  appendStringInfoString(str, "NO CYCLE");
513
515
  }
514
516
  else if (strcmp(def_elem->defname, "increment") == 0)
515
517
  {
516
518
  appendStringInfoString(str, "INCREMENT ");
517
- deparseNumericOnly(str, (Value *) def_elem->arg);
519
+ deparseNumericOnly(str, (union ValUnion *) def_elem->arg);
518
520
  }
519
521
  else if (strcmp(def_elem->defname, "maxvalue") == 0 && def_elem->arg != NULL)
520
522
  {
521
523
  appendStringInfoString(str, "MAXVALUE ");
522
- deparseNumericOnly(str, (Value *) def_elem->arg);
524
+ deparseNumericOnly(str, (union ValUnion *) def_elem->arg);
523
525
  }
524
526
  else if (strcmp(def_elem->defname, "maxvalue") == 0 && def_elem->arg == NULL)
525
527
  {
@@ -528,7 +530,7 @@ static void deparseSeqOptElem(StringInfo str, DefElem *def_elem)
528
530
  else if (strcmp(def_elem->defname, "minvalue") == 0 && def_elem->arg != NULL)
529
531
  {
530
532
  appendStringInfoString(str, "MINVALUE ");
531
- deparseNumericOnly(str, (Value *) def_elem->arg);
533
+ deparseNumericOnly(str, (union ValUnion *) def_elem->arg);
532
534
  }
533
535
  else if (strcmp(def_elem->defname, "minvalue") == 0 && def_elem->arg == NULL)
534
536
  {
@@ -547,7 +549,7 @@ static void deparseSeqOptElem(StringInfo str, DefElem *def_elem)
547
549
  else if (strcmp(def_elem->defname, "start") == 0)
548
550
  {
549
551
  appendStringInfoString(str, "START ");
550
- deparseNumericOnly(str, (Value *) def_elem->arg);
552
+ deparseNumericOnly(str, (union ValUnion *) def_elem->arg);
551
553
  }
552
554
  else if (strcmp(def_elem->defname, "restart") == 0 && def_elem->arg == NULL)
553
555
  {
@@ -556,7 +558,7 @@ static void deparseSeqOptElem(StringInfo str, DefElem *def_elem)
556
558
  else if (strcmp(def_elem->defname, "restart") == 0 && def_elem->arg != NULL)
557
559
  {
558
560
  appendStringInfoString(str, "RESTART ");
559
- deparseNumericOnly(str, (Value *) def_elem->arg);
561
+ deparseNumericOnly(str, (union ValUnion *) def_elem->arg);
560
562
  }
561
563
  else
562
564
  {
@@ -711,7 +713,7 @@ static void deparseDefArg(StringInfo str, Node *arg, bool is_operator_def_arg)
711
713
  }
712
714
  else if (IsA(arg, Float) || IsA(arg, Integer)) // NumericOnly
713
715
  {
714
- deparseValue(str, (Value *) arg, DEPARSE_NODE_CONTEXT_NONE);
716
+ deparseValue(str, (union ValUnion *) arg, DEPARSE_NODE_CONTEXT_NONE);
715
717
  }
716
718
  else if (IsA(arg, String))
717
719
  {
@@ -792,11 +794,11 @@ static void deparseCreateGenericOptions(StringInfo str, List *options)
792
794
  // "common_func_opt_item" in gram.y
793
795
  static void deparseCommonFuncOptItem(StringInfo str, DefElem *def_elem)
794
796
  {
795
- if (strcmp(def_elem->defname, "strict") == 0 && intVal(def_elem->arg) == 1)
797
+ if (strcmp(def_elem->defname, "strict") == 0 && boolVal(def_elem->arg))
796
798
  {
797
799
  appendStringInfoString(str, "RETURNS NULL ON NULL INPUT");
798
800
  }
799
- else if (strcmp(def_elem->defname, "strict") == 0 && intVal(def_elem->arg) == 0)
801
+ else if (strcmp(def_elem->defname, "strict") == 0 && !boolVal(def_elem->arg))
800
802
  {
801
803
  appendStringInfoString(str, "CALLED ON NULL INPUT");
802
804
  }
@@ -812,31 +814,31 @@ static void deparseCommonFuncOptItem(StringInfo str, DefElem *def_elem)
812
814
  {
813
815
  appendStringInfoString(str, "VOLATILE");
814
816
  }
815
- else if (strcmp(def_elem->defname, "security") == 0 && intVal(def_elem->arg) == 1)
817
+ else if (strcmp(def_elem->defname, "security") == 0 && boolVal(def_elem->arg))
816
818
  {
817
819
  appendStringInfoString(str, "SECURITY DEFINER");
818
820
  }
819
- else if (strcmp(def_elem->defname, "security") == 0 && intVal(def_elem->arg) == 0)
821
+ else if (strcmp(def_elem->defname, "security") == 0 && !boolVal(def_elem->arg))
820
822
  {
821
823
  appendStringInfoString(str, "SECURITY INVOKER");
822
824
  }
823
- else if (strcmp(def_elem->defname, "leakproof") == 0 && intVal(def_elem->arg) == 1)
825
+ else if (strcmp(def_elem->defname, "leakproof") == 0 && boolVal(def_elem->arg))
824
826
  {
825
827
  appendStringInfoString(str, "LEAKPROOF");
826
828
  }
827
- else if (strcmp(def_elem->defname, "leakproof") == 0 && intVal(def_elem->arg) == 0)
829
+ else if (strcmp(def_elem->defname, "leakproof") == 0 && !boolVal(def_elem->arg))
828
830
  {
829
831
  appendStringInfoString(str, "NOT LEAKPROOF");
830
832
  }
831
833
  else if (strcmp(def_elem->defname, "cost") == 0)
832
834
  {
833
835
  appendStringInfoString(str, "COST ");
834
- deparseValue(str, (Value *) def_elem->arg, DEPARSE_NODE_CONTEXT_NONE);
836
+ deparseValue(str, (union ValUnion *) def_elem->arg, DEPARSE_NODE_CONTEXT_NONE);
835
837
  }
836
838
  else if (strcmp(def_elem->defname, "rows") == 0)
837
839
  {
838
840
  appendStringInfoString(str, "ROWS ");
839
- deparseValue(str, (Value *) def_elem->arg, DEPARSE_NODE_CONTEXT_NONE);
841
+ deparseValue(str, (union ValUnion *) def_elem->arg, DEPARSE_NODE_CONTEXT_NONE);
840
842
  }
841
843
  else if (strcmp(def_elem->defname, "support") == 0)
842
844
  {
@@ -993,19 +995,22 @@ static void deparseFuncName(StringInfo str, List *func_name)
993
995
  static void deparseFunctionWithArgtypes(StringInfo str, ObjectWithArgs *object_with_args)
994
996
  {
995
997
  ListCell *lc;
996
-
997
998
  deparseFuncName(str, object_with_args->objname);
998
999
 
999
1000
  if (!object_with_args->args_unspecified)
1000
1001
  {
1001
1002
  appendStringInfoChar(str, '(');
1002
- foreach(lc, object_with_args->objargs)
1003
+ List *objargs = object_with_args->objargs;
1004
+ if (object_with_args->objfuncargs)
1005
+ objargs = object_with_args->objfuncargs;
1006
+
1007
+ foreach(lc, objargs)
1003
1008
  {
1004
- if (IsA(lfirst(lc), TypeName))
1005
- deparseTypeName(str, castNode(TypeName, lfirst(lc)));
1006
- else
1009
+ if (IsA(lfirst(lc), FunctionParameter))
1007
1010
  deparseFunctionParameter(str, castNode(FunctionParameter, lfirst(lc)));
1008
- if (lnext(object_with_args->objargs, lc))
1011
+ else
1012
+ deparseTypeName(str, castNode(TypeName, lfirst(lc)));
1013
+ if (lnext(objargs, lc))
1009
1014
  appendStringInfoString(str, ", ");
1010
1015
  }
1011
1016
  appendStringInfoChar(str, ')');
@@ -1095,16 +1100,23 @@ static void deparseAggregateWithArgtypes(StringInfo str, ObjectWithArgs *object_
1095
1100
  deparseFuncName(str, object_with_args->objname);
1096
1101
 
1097
1102
  appendStringInfoChar(str, '(');
1098
- if (object_with_args->objargs == NULL)
1103
+ if (object_with_args->objargs == NULL && object_with_args->objfuncargs == NULL)
1099
1104
  {
1100
1105
  appendStringInfoChar(str, '*');
1101
1106
  }
1102
1107
  else
1103
1108
  {
1104
- foreach(lc, object_with_args->objargs)
1109
+ List *objargs = object_with_args->objargs;
1110
+ if (object_with_args->objfuncargs)
1111
+ objargs = object_with_args->objfuncargs;
1112
+
1113
+ foreach(lc, objargs)
1105
1114
  {
1106
- deparseTypeName(str, castNode(TypeName, lfirst(lc)));
1107
- if (lnext(object_with_args->objargs, lc))
1115
+ if (IsA(lfirst(lc), FunctionParameter))
1116
+ deparseFunctionParameter(str, castNode(FunctionParameter, lfirst(lc)));
1117
+ else
1118
+ deparseTypeName(str, castNode(TypeName, lfirst(lc)));
1119
+ if (lnext(objargs, lc))
1108
1120
  appendStringInfoString(str, ", ");
1109
1121
  }
1110
1122
  }
@@ -1235,6 +1247,64 @@ static void deparseOptBooleanOrString(StringInfo str, char *s)
1235
1247
  deparseNonReservedWordOrSconst(str, s);
1236
1248
  }
1237
1249
 
1250
+ static void deparseOptBoolean(StringInfo str, Node *node)
1251
+ {
1252
+ if (node == NULL)
1253
+ {
1254
+ return;
1255
+ }
1256
+
1257
+ switch (nodeTag(node))
1258
+ {
1259
+ case T_String:
1260
+ appendStringInfo(str, " %s", strVal(node));
1261
+ break;
1262
+ case T_Integer:
1263
+ appendStringInfo(str, " %d", intVal(node));
1264
+ break;
1265
+ case T_Boolean:
1266
+ appendStringInfo(str, " %s", boolVal(node) ? "TRUE" : "FALSE");
1267
+ break;
1268
+ default:
1269
+ Assert(false);
1270
+ break;
1271
+ }
1272
+ }
1273
+
1274
+ bool optBooleanValue(Node *node)
1275
+ {
1276
+ if (node == NULL)
1277
+ {
1278
+ return true;
1279
+ }
1280
+
1281
+ switch (nodeTag(node))
1282
+ {
1283
+ case T_String: {
1284
+ // Longest valid string is "off\0"
1285
+ char lower[4];
1286
+ strncpy(lower, strVal(node), 4);
1287
+ lower[3] = 0;
1288
+
1289
+ if (strcmp(lower, "on") == 0) {
1290
+ return true;
1291
+ } else if (strcmp(lower, "off") == 0) {
1292
+ return false;
1293
+ }
1294
+
1295
+ // No sane way to handle this.
1296
+ return false;
1297
+ }
1298
+ case T_Integer:
1299
+ return intVal(node) != 0;
1300
+ case T_Boolean:
1301
+ return boolVal(node);
1302
+ default:
1303
+ Assert(false);
1304
+ return false;
1305
+ }
1306
+ }
1307
+
1238
1308
  // "var_name"
1239
1309
  //
1240
1310
  // Note this is kept separate from ColId in case we want to improve the
@@ -1259,12 +1329,16 @@ static void deparseVarList(StringInfo str, List *l)
1259
1329
  {
1260
1330
  A_Const *a_const = castNode(A_Const, lfirst(lc));
1261
1331
  if (IsA(&a_const->val, Integer) || IsA(&a_const->val, Float))
1262
- deparseNumericOnly(str, (Value *) &a_const->val);
1332
+ deparseNumericOnly(str, (union ValUnion *) &a_const->val);
1263
1333
  else if (IsA(&a_const->val, String))
1264
1334
  deparseOptBooleanOrString(str, strVal(&a_const->val));
1265
1335
  else
1266
1336
  Assert(false);
1267
1337
  }
1338
+ else if (IsA(lfirst(lc), TypeCast))
1339
+ {
1340
+ deparseTypeCast(str, castNode(TypeCast, lfirst(lc)), DEPARSE_NODE_CONTEXT_SET_STATEMENT);
1341
+ }
1268
1342
  else
1269
1343
  {
1270
1344
  Assert(false);
@@ -1340,7 +1414,7 @@ static void deparseAlterIdentityColumnOptionList(StringInfo str, List *l)
1340
1414
  else if (strcmp(def_elem->defname, "restart") == 0 && def_elem->arg != NULL)
1341
1415
  {
1342
1416
  appendStringInfoString(str, "RESTART ");
1343
- deparseNumericOnly(str, (Value *) def_elem->arg);
1417
+ deparseNumericOnly(str, (union ValUnion *) def_elem->arg);
1344
1418
  }
1345
1419
  else if (strcmp(def_elem->defname, "generated") == 0)
1346
1420
  {
@@ -1710,7 +1784,7 @@ static void deparseFuncExprWindowless(StringInfo str, Node* node)
1710
1784
  deparseSQLValueFunction(str, castNode(SQLValueFunction, node));
1711
1785
  break;
1712
1786
  case T_TypeCast:
1713
- deparseTypeCast(str, castNode(TypeCast, node));
1787
+ deparseTypeCast(str, castNode(TypeCast, node), DEPARSE_NODE_CONTEXT_NONE);
1714
1788
  break;
1715
1789
  case T_CoalesceExpr:
1716
1790
  deparseCoalesceExpr(str, castNode(CoalesceExpr, node));
@@ -2010,6 +2084,38 @@ static void deparseCreatedbOptList(StringInfo str, List *l)
2010
2084
  }
2011
2085
  }
2012
2086
 
2087
+ // "utility_option_list" in gram.y
2088
+ static void deparseUtilityOptionList(StringInfo str, List *options)
2089
+ {
2090
+ ListCell *lc = NULL;
2091
+ char *defname = NULL;
2092
+
2093
+ if (list_length(options) > 0)
2094
+ {
2095
+ appendStringInfoChar(str, '(');
2096
+ foreach(lc, options)
2097
+ {
2098
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
2099
+ deparseGenericDefElemName(str, def_elem->defname);
2100
+
2101
+ if (def_elem->arg != NULL)
2102
+ {
2103
+ appendStringInfoChar(str, ' ');
2104
+ if (IsA(def_elem->arg, Integer) || IsA(def_elem->arg, Float))
2105
+ deparseNumericOnly(str, (union ValUnion *) def_elem->arg);
2106
+ else if (IsA(def_elem->arg, String))
2107
+ deparseOptBooleanOrString(str, strVal(def_elem->arg));
2108
+ else
2109
+ Assert(false);
2110
+ }
2111
+
2112
+ if (lnext(options, lc))
2113
+ appendStringInfoString(str, ", ");
2114
+ }
2115
+ appendStringInfoString(str, ") ");
2116
+ }
2117
+ }
2118
+
2013
2119
  static void deparseSelectStmt(StringInfo str, SelectStmt *stmt)
2014
2120
  {
2015
2121
  const ListCell *lc = NULL;
@@ -2074,6 +2180,8 @@ static void deparseSelectStmt(StringInfo str, SelectStmt *stmt)
2074
2180
  if (list_length(stmt->groupClause) > 0)
2075
2181
  {
2076
2182
  appendStringInfoString(str, "GROUP BY ");
2183
+ if (stmt->groupDistinct)
2184
+ appendStringInfoString(str, "DISTINCT ");
2077
2185
  deparseGroupByList(str, stmt->groupClause);
2078
2186
  appendStringInfoChar(str, ' ');
2079
2187
  }
@@ -2159,7 +2267,7 @@ static void deparseSelectStmt(StringInfo str, SelectStmt *stmt)
2159
2267
  else if (stmt->limitOption == LIMIT_OPTION_WITH_TIES)
2160
2268
  appendStringInfoString(str, "FETCH FIRST ");
2161
2269
 
2162
- if (IsA(stmt->limitCount, A_Const) && IsA(&castNode(A_Const, stmt->limitCount)->val, Null))
2270
+ if (IsA(stmt->limitCount, A_Const) && castNode(A_Const, stmt->limitCount)->isnull)
2163
2271
  appendStringInfoString(str, "ALL");
2164
2272
  else
2165
2273
  deparseCExpr(str, stmt->limitCount);
@@ -2295,7 +2403,8 @@ static void deparseAlias(StringInfo str, Alias *alias)
2295
2403
 
2296
2404
  static void deparseAConst(StringInfo str, A_Const *a_const)
2297
2405
  {
2298
- deparseValue(str, &a_const->val, DEPARSE_NODE_CONTEXT_CONSTANT);
2406
+ union ValUnion *val = a_const->isnull ? NULL : &a_const->val;
2407
+ deparseValue(str, val, DEPARSE_NODE_CONTEXT_CONSTANT);
2299
2408
  }
2300
2409
 
2301
2410
  static void deparseFuncCall(StringInfo str, FuncCall *func_call)
@@ -2323,8 +2432,217 @@ static void deparseFuncCall(StringInfo str, FuncCall *func_call)
2323
2432
  deparseExpr(str, lfourth(func_call->args));
2324
2433
  appendStringInfoChar(str, ')');
2325
2434
  return;
2326
- }
2435
+ } else if (func_call->funcformat == COERCE_SQL_SYNTAX &&
2436
+ list_length(func_call->funcname) == 2 &&
2437
+ strcmp(strVal(linitial(func_call->funcname)), "pg_catalog") == 0 &&
2438
+ strcmp(strVal(lsecond(func_call->funcname)), "substring") == 0)
2439
+ {
2440
+ /*
2441
+ * "SUBSTRING" is a keyword on its own merit, and only accepts the
2442
+ * keyword parameter style when its called as a keyword, not as a regular function (i.e. pg_catalog.substring)
2443
+ */
2444
+ Assert(list_length(func_call->args) == 2 || list_length(func_call->args) == 3);
2445
+ appendStringInfoString(str, "SUBSTRING(");
2446
+ deparseExpr(str, linitial(func_call->args));
2447
+ appendStringInfoString(str, " FROM ");
2448
+ deparseExpr(str, lsecond(func_call->args));
2449
+ if (list_length(func_call->args) == 3)
2450
+ {
2451
+ appendStringInfoString(str, " FOR ");
2452
+ deparseExpr(str, lthird(func_call->args));
2453
+ }
2454
+ appendStringInfoChar(str, ')');
2455
+ return;
2456
+ } else if (func_call->funcformat == COERCE_SQL_SYNTAX &&
2457
+ list_length(func_call->funcname) == 2 &&
2458
+ strcmp(strVal(linitial(func_call->funcname)), "pg_catalog") == 0 &&
2459
+ strcmp(strVal(lsecond(func_call->funcname)), "position") == 0 &&
2460
+ list_length(func_call->args) == 2)
2461
+ {
2462
+ /*
2463
+ * "POSITION" is a keyword on its own merit, and only accepts the
2464
+ * keyword parameter style when its called as a keyword, not as a regular function (i.e. pg_catalog.position)
2465
+ * Note that the first and second arguments are switched in this format
2466
+ */
2467
+ appendStringInfoString(str, "POSITION(");
2468
+ deparseExpr(str, lsecond(func_call->args));
2469
+ appendStringInfoString(str, " IN ");
2470
+ deparseExpr(str, linitial(func_call->args));
2471
+ appendStringInfoChar(str, ')');
2472
+ return;
2473
+ } else if (func_call->funcformat == COERCE_SQL_SYNTAX &&
2474
+ list_length(func_call->funcname) == 2 &&
2475
+ strcmp(strVal(linitial(func_call->funcname)), "pg_catalog") == 0 &&
2476
+ strcmp(strVal(lsecond(func_call->funcname)), "overlay") == 0 &&
2477
+ list_length(func_call->args) == 3)
2478
+ {
2479
+ /*
2480
+ * "OVERLAY" is a keyword on its own merit, and only accepts the
2481
+ * keyword parameter style when its called as a keyword, not as a regular function (i.e. pg_catalog.overlay)
2482
+ */
2483
+ appendStringInfoString(str, "overlay(");
2484
+ deparseExpr(str, linitial(func_call->args));
2485
+ appendStringInfoString(str, " placing ");
2486
+ deparseExpr(str, lsecond(func_call->args));
2487
+ appendStringInfoString(str, " from ");
2488
+ deparseExpr(str, lthird(func_call->args));
2489
+ appendStringInfoChar(str, ')');
2490
+ return;
2491
+ } else if (func_call->funcformat == COERCE_SQL_SYNTAX &&
2492
+ list_length(func_call->funcname) == 2 &&
2493
+ strcmp(strVal(linitial(func_call->funcname)), "pg_catalog") == 0 &&
2494
+ strcmp(strVal(lsecond(func_call->funcname)), "pg_collation_for") == 0 &&
2495
+ list_length(func_call->args) == 1)
2496
+ {
2497
+ /*
2498
+ * "collation for" is a keyword on its own merit, and only accepts the
2499
+ * keyword parameter style when its called as a keyword, not as a regular function (i.e. pg_catalog.overlay)
2500
+ */
2501
+ appendStringInfoString(str, "collation for (");
2502
+ deparseExpr(str, linitial(func_call->args));
2503
+ appendStringInfoChar(str, ')');
2504
+ return;
2505
+ } else if (func_call->funcformat == COERCE_SQL_SYNTAX &&
2506
+ list_length(func_call->funcname) == 2 &&
2507
+ strcmp(strVal(linitial(func_call->funcname)), "pg_catalog") == 0 &&
2508
+ strcmp(strVal(lsecond(func_call->funcname)), "extract") == 0 &&
2509
+ list_length(func_call->args) == 2)
2510
+ {
2511
+ /*
2512
+ * "EXTRACT" is a keyword on its own merit, and only accepts the
2513
+ * keyword parameter style when its called as a keyword, not as a regular function (i.e. pg_catalog.extract)
2514
+ */
2515
+ appendStringInfoString(str, "extract (");
2516
+ deparseExpr(str, linitial(func_call->args));
2517
+ appendStringInfoString(str, " FROM ");
2518
+ deparseExpr(str, lsecond(func_call->args));
2519
+ appendStringInfoChar(str, ')');
2520
+ return;
2521
+ } else if (func_call->funcformat == COERCE_SQL_SYNTAX &&
2522
+ list_length(func_call->funcname) == 2 &&
2523
+ strcmp(strVal(linitial(func_call->funcname)), "pg_catalog") == 0 &&
2524
+ strcmp(strVal(lsecond(func_call->funcname)), "overlaps") == 0 &&
2525
+ list_length(func_call->args) == 4)
2526
+ {
2527
+ /*
2528
+ * "OVERLAPS" is a keyword on its own merit, and only accepts the
2529
+ * keyword parameter style when its called as a keyword, not as a regular function (i.e. pg_catalog.overlaps)
2530
+ * format: (start_1, end_1) overlaps (start_2, end_2)
2531
+ */
2532
+ appendStringInfoChar(str, '(');
2533
+ deparseExpr(str, linitial(func_call->args));
2534
+ appendStringInfoString(str, ", ");
2535
+ deparseExpr(str, lsecond(func_call->args));
2536
+ appendStringInfoString(str, ") ");
2537
+
2538
+ appendStringInfoString(str, "overlaps ");
2539
+ appendStringInfoChar(str, '(');
2540
+ deparseExpr(str, lthird(func_call->args));
2541
+ appendStringInfoString(str, ", ");
2542
+ deparseExpr(str, lfourth(func_call->args));
2543
+ appendStringInfoString(str, ") ");
2544
+ return;
2545
+ } else if (func_call->funcformat == COERCE_SQL_SYNTAX &&
2546
+ list_length(func_call->funcname) == 2 &&
2547
+ strcmp(strVal(linitial(func_call->funcname)), "pg_catalog") == 0 &&
2548
+ (
2549
+ strcmp(strVal(lsecond(func_call->funcname)), "ltrim") == 0 ||
2550
+ strcmp(strVal(lsecond(func_call->funcname)), "btrim") == 0 ||
2551
+ strcmp(strVal(lsecond(func_call->funcname)), "rtrim") == 0
2552
+ ))
2553
+ {
2554
+ /*
2555
+ * "TRIM " is a keyword on its own merit, and only accepts the
2556
+ * keyword parameter style when its called as a keyword, not as a regular function (i.e. pg_catalog.ltrim)
2557
+ * Note that the first and second arguments are switched in this format
2558
+ */
2559
+ Assert(list_length(func_call->args) == 1 || list_length(func_call->args) == 2);
2560
+ appendStringInfoString(str, "TRIM (");
2561
+ if (strcmp(strVal(lsecond(func_call->funcname)), "ltrim") == 0)
2562
+ appendStringInfoString(str, "LEADING ");
2563
+ else if (strcmp(strVal(lsecond(func_call->funcname)), "btrim") == 0)
2564
+ appendStringInfoString(str, "BOTH ");
2565
+ else if (strcmp(strVal(lsecond(func_call->funcname)), "rtrim") == 0)
2566
+ appendStringInfoString(str, "TRAILING ");
2567
+
2568
+ if (list_length(func_call->args) == 2)
2569
+ deparseExpr(str, lsecond(func_call->args));
2570
+ appendStringInfoString(str, " FROM ");
2571
+ deparseExpr(str, linitial(func_call->args));
2572
+ appendStringInfoChar(str, ')');
2573
+ return;
2574
+ } else if (func_call->funcformat == COERCE_SQL_SYNTAX &&
2575
+ list_length(func_call->funcname) == 2 &&
2576
+ strcmp(strVal(linitial(func_call->funcname)), "pg_catalog") == 0 &&
2577
+ strcmp(strVal(lsecond(func_call->funcname)), "timezone") == 0 &&
2578
+ list_length(func_call->args) == 2)
2579
+ {
2580
+ /*
2581
+ * "AT TIME ZONE" is a keyword on its own merit, and only accepts the
2582
+ * keyword parameter style when its called as a keyword, not as a regular function (i.e. pg_catalog.timezone)
2583
+ * Note that the arguments are swapped in this case
2584
+ */
2585
+ deparseExpr(str, lsecond(func_call->args));
2586
+ appendStringInfoString(str, " AT TIME ZONE ");
2587
+ deparseExpr(str, linitial(func_call->args));
2588
+ return;
2589
+ } else if (func_call->funcformat == COERCE_SQL_SYNTAX &&
2590
+ list_length(func_call->funcname) == 2 &&
2591
+ strcmp(strVal(linitial(func_call->funcname)), "pg_catalog") == 0 &&
2592
+ strcmp(strVal(lsecond(func_call->funcname)), "normalize") == 0)
2593
+ {
2594
+ /*
2595
+ * "NORMALIZE" is a keyword on its own merit, and only accepts the
2596
+ * keyword parameter style when its called as a keyword, not as a regular function (i.e. pg_catalog.normalize)
2597
+ */
2598
+ Assert(list_length(func_call->args) == 1 || list_length(func_call->args) == 2);
2599
+ appendStringInfoString(str, "normalize (");
2600
+
2601
+ deparseExpr(str, linitial(func_call->args));
2602
+ if (list_length(func_call->args) == 2)
2603
+ {
2604
+ appendStringInfoString(str, ", ");
2605
+ Assert(IsA(lsecond(func_call->args), A_Const));
2606
+ A_Const *aconst = lsecond(func_call->args);
2607
+ deparseValue(str, &aconst->val, DEPARSE_NODE_CONTEXT_NONE);
2608
+ }
2609
+ appendStringInfoChar(str, ')');
2610
+ return;
2611
+ } else if (func_call->funcformat == COERCE_SQL_SYNTAX &&
2612
+ list_length(func_call->funcname) == 2 &&
2613
+ strcmp(strVal(linitial(func_call->funcname)), "pg_catalog") == 0 &&
2614
+ strcmp(strVal(lsecond(func_call->funcname)), "is_normalized") == 0)
2615
+ {
2616
+ /*
2617
+ * "IS NORMALIZED" is a keyword on its own merit, and only accepts the
2618
+ * keyword parameter style when its called as a keyword, not as a regular function (i.e. pg_catalog.is_normalized)
2619
+ */
2620
+ Assert(list_length(func_call->args) == 1 || list_length(func_call->args) == 2);
2327
2621
 
2622
+ deparseExpr(str, linitial(func_call->args));
2623
+ appendStringInfoString(str, " IS ");
2624
+ if (list_length(func_call->args) == 2)
2625
+ {
2626
+ Assert(IsA(lsecond(func_call->args), A_Const));
2627
+ A_Const *aconst = lsecond(func_call->args);
2628
+ deparseValue(str, &aconst->val, DEPARSE_NODE_CONTEXT_NONE);
2629
+ }
2630
+ appendStringInfoString(str, " NORMALIZED ");
2631
+ return;
2632
+ } else if (func_call->funcformat == COERCE_SQL_SYNTAX &&
2633
+ list_length(func_call->funcname) == 2 &&
2634
+ strcmp(strVal(linitial(func_call->funcname)), "pg_catalog") == 0 &&
2635
+ strcmp(strVal(lsecond(func_call->funcname)), "xmlexists") == 0 &&
2636
+ list_length(func_call->args) == 2)
2637
+ {
2638
+ appendStringInfoString(str, "xmlexists (");
2639
+ deparseExpr(str, linitial(func_call->args));
2640
+ appendStringInfoString(str, " PASSING ");
2641
+ deparseExpr(str, lsecond(func_call->args));
2642
+ appendStringInfoChar(str, ')');
2643
+ return;
2644
+ }
2645
+
2328
2646
  deparseFuncName(str, func_call->funcname);
2329
2647
  appendStringInfoChar(str, '(');
2330
2648
 
@@ -2648,31 +2966,13 @@ static void deparseAExpr(StringInfo str, A_Expr* a_expr, DeparseNodeContext cont
2648
2966
  deparseExpr(str, a_expr->rexpr);
2649
2967
  appendStringInfoChar(str, ')');
2650
2968
  return;
2651
- case AEXPR_OF: /* IS [NOT] OF - name must be "=" or "<>" */
2652
- Assert(list_length(a_expr->name) == 1);
2653
- Assert(IsA(linitial(a_expr->name), String));
2654
- Assert(IsA(a_expr->rexpr, List));
2655
- deparseExpr(str, a_expr->lexpr);
2656
- appendStringInfoChar(str, ' ');
2657
- name = ((Value *) linitial(a_expr->name))->val.str;
2658
- if (strcmp(name, "=") == 0) {
2659
- appendStringInfoString(str, "IS OF ");
2660
- } else if (strcmp(name, "<>") == 0) {
2661
- appendStringInfoString(str, "IS NOT OF ");
2662
- } else {
2663
- Assert(false);
2664
- }
2665
- appendStringInfoChar(str, '(');
2666
- deparseTypeList(str, castNode(List, a_expr->rexpr));
2667
- appendStringInfoChar(str, ')');
2668
- return;
2669
2969
  case AEXPR_IN: /* [NOT] IN - name must be "=" or "<>" */
2670
2970
  Assert(list_length(a_expr->name) == 1);
2671
2971
  Assert(IsA(linitial(a_expr->name), String));
2672
2972
  Assert(IsA(a_expr->rexpr, List));
2673
2973
  deparseExpr(str, a_expr->lexpr);
2674
2974
  appendStringInfoChar(str, ' ');
2675
- name = ((Value *) linitial(a_expr->name))->val.str;
2975
+ name = ((union ValUnion *) linitial(a_expr->name))->sval.sval;
2676
2976
  if (strcmp(name, "=") == 0) {
2677
2977
  appendStringInfoString(str, "IN ");
2678
2978
  } else if (strcmp(name, "<>") == 0) {
@@ -2693,7 +2993,7 @@ static void deparseAExpr(StringInfo str, A_Expr* a_expr, DeparseNodeContext cont
2693
2993
  deparseExpr(str, a_expr->lexpr);
2694
2994
  appendStringInfoChar(str, ' ');
2695
2995
 
2696
- name = ((Value *) linitial(a_expr->name))->val.str;
2996
+ name = ((union ValUnion *) linitial(a_expr->name))->sval.sval;
2697
2997
  if (strcmp(name, "~~") == 0) {
2698
2998
  appendStringInfoString(str, "LIKE ");
2699
2999
  } else if (strcmp(name, "!~~") == 0) {
@@ -2710,7 +3010,7 @@ static void deparseAExpr(StringInfo str, A_Expr* a_expr, DeparseNodeContext cont
2710
3010
  deparseExpr(str, a_expr->lexpr);
2711
3011
  appendStringInfoChar(str, ' ');
2712
3012
 
2713
- name = ((Value *) linitial(a_expr->name))->val.str;
3013
+ name = ((union ValUnion *) linitial(a_expr->name))->sval.sval;
2714
3014
  if (strcmp(name, "~~*") == 0) {
2715
3015
  appendStringInfoString(str, "ILIKE ");
2716
3016
  } else if (strcmp(name, "!~~*") == 0) {
@@ -2727,7 +3027,7 @@ static void deparseAExpr(StringInfo str, A_Expr* a_expr, DeparseNodeContext cont
2727
3027
  deparseExpr(str, a_expr->lexpr);
2728
3028
  appendStringInfoChar(str, ' ');
2729
3029
 
2730
- name = ((Value *) linitial(a_expr->name))->val.str;
3030
+ name = ((union ValUnion *) linitial(a_expr->name))->sval.sval;
2731
3031
  if (strcmp(name, "~") == 0) {
2732
3032
  appendStringInfoString(str, "SIMILAR TO ");
2733
3033
  } else if (strcmp(name, "!~") == 0) {
@@ -2769,10 +3069,6 @@ static void deparseAExpr(StringInfo str, A_Expr* a_expr, DeparseNodeContext cont
2769
3069
  appendStringInfoString(str, " AND ");
2770
3070
  }
2771
3071
  return;
2772
- case AEXPR_PAREN: /* nameless dummy node for parentheses */
2773
- // Not present in parse trees when operator_precedence_warning is turned off
2774
- Assert(false);
2775
- return;
2776
3072
  }
2777
3073
  }
2778
3074
 
@@ -3032,6 +3328,12 @@ static void deparseJoinExpr(StringInfo str, JoinExpr *join_expr)
3032
3328
  appendStringInfoString(str, "USING (");
3033
3329
  deparseNameList(str, join_expr->usingClause);
3034
3330
  appendStringInfoString(str, ") ");
3331
+
3332
+ if (join_expr->join_using_alias)
3333
+ {
3334
+ appendStringInfoString(str, "AS ");
3335
+ appendStringInfoString(str, join_expr->join_using_alias->aliasname);
3336
+ }
3035
3337
  }
3036
3338
 
3037
3339
  if (need_alias_parens)
@@ -3043,6 +3345,49 @@ static void deparseJoinExpr(StringInfo str, JoinExpr *join_expr)
3043
3345
  removeTrailingSpace(str);
3044
3346
  }
3045
3347
 
3348
+ static void deparseCTESearchClause(StringInfo str, CTESearchClause *search_clause)
3349
+ {
3350
+ appendStringInfoString(str, " SEARCH ");
3351
+ if (search_clause->search_breadth_first)
3352
+ appendStringInfoString(str, "BREADTH ");
3353
+ else
3354
+ appendStringInfoString(str, "DEPTH ");
3355
+
3356
+ appendStringInfoString(str, "FIRST BY ");
3357
+
3358
+ if (search_clause->search_col_list)
3359
+ deparseColumnList(str, search_clause->search_col_list);
3360
+
3361
+ appendStringInfoString(str, " SET ");
3362
+ appendStringInfoString(str, quote_identifier(search_clause->search_seq_column));
3363
+ }
3364
+
3365
+ static void deparseCTECycleClause(StringInfo str, CTECycleClause *cycle_clause)
3366
+ {
3367
+ appendStringInfoString(str, " CYCLE ");
3368
+
3369
+ if (cycle_clause->cycle_col_list)
3370
+ deparseColumnList(str, cycle_clause->cycle_col_list);
3371
+
3372
+ appendStringInfoString(str, " SET ");
3373
+ appendStringInfoString(str, quote_identifier(cycle_clause->cycle_mark_column));
3374
+
3375
+ if (cycle_clause->cycle_mark_value)
3376
+ {
3377
+ appendStringInfoString(str, " TO ");
3378
+ deparseExpr(str, cycle_clause->cycle_mark_value);
3379
+ }
3380
+
3381
+ if (cycle_clause->cycle_mark_default)
3382
+ {
3383
+ appendStringInfoString(str, " DEFAULT ");
3384
+ deparseExpr(str, cycle_clause->cycle_mark_default);
3385
+ }
3386
+
3387
+ appendStringInfoString(str, " USING ");
3388
+ appendStringInfoString(str, quote_identifier(cycle_clause->cycle_path_column));
3389
+ }
3390
+
3046
3391
  static void deparseCommonTableExpr(StringInfo str, CommonTableExpr *cte)
3047
3392
  {
3048
3393
  deparseColId(str, cte->ctename);
@@ -3070,6 +3415,11 @@ static void deparseCommonTableExpr(StringInfo str, CommonTableExpr *cte)
3070
3415
  appendStringInfoChar(str, '(');
3071
3416
  deparsePreparableStmt(str, cte->ctequery);
3072
3417
  appendStringInfoChar(str, ')');
3418
+
3419
+ if (cte->search_clause)
3420
+ deparseCTESearchClause(str, cte->search_clause);
3421
+ if (cte->cycle_clause)
3422
+ deparseCTECycleClause(str, cte->cycle_clause);
3073
3423
  }
3074
3424
 
3075
3425
  static void deparseRangeSubselect(StringInfo str, RangeSubselect *range_subselect)
@@ -3174,6 +3524,7 @@ static void deparseRowExpr(StringInfo str, RowExpr *row_expr)
3174
3524
  case COERCE_EXPLICIT_CALL:
3175
3525
  appendStringInfoString(str, "ROW");
3176
3526
  break;
3527
+ case COERCE_SQL_SYNTAX:
3177
3528
  case COERCE_EXPLICIT_CAST:
3178
3529
  // Not present in raw parser output
3179
3530
  Assert(false);
@@ -3188,7 +3539,7 @@ static void deparseRowExpr(StringInfo str, RowExpr *row_expr)
3188
3539
  appendStringInfoChar(str, ')');
3189
3540
  }
3190
3541
 
3191
- static void deparseTypeCast(StringInfo str, TypeCast *type_cast)
3542
+ static void deparseTypeCast(StringInfo str, TypeCast *type_cast, DeparseNodeContext context)
3192
3543
  {
3193
3544
  bool need_parens = false;
3194
3545
 
@@ -3236,6 +3587,13 @@ static void deparseTypeCast(StringInfo str, TypeCast *type_cast)
3236
3587
  return;
3237
3588
  }
3238
3589
  }
3590
+ else if (strcmp(typename, "interval") == 0 && context == DEPARSE_NODE_CONTEXT_SET_STATEMENT && IsA(&a_const->val, String))
3591
+ {
3592
+ appendStringInfoString(str, "interval ");
3593
+ deparseAConst(str, a_const);
3594
+ deparseIntervalTypmods(str, type_cast->typeName);
3595
+ return;
3596
+ }
3239
3597
  }
3240
3598
 
3241
3599
  // Ensure negative values have wrapping parentheses
@@ -3243,8 +3601,18 @@ static void deparseTypeCast(StringInfo str, TypeCast *type_cast)
3243
3601
  {
3244
3602
  need_parens = true;
3245
3603
  }
3604
+
3605
+ if (list_length(type_cast->typeName->names) == 1 &&
3606
+ strcmp(strVal(linitial(type_cast->typeName->names)), "point") == 0 &&
3607
+ a_const->location > type_cast->typeName->location)
3608
+ {
3609
+ appendStringInfoString(str, " point ");
3610
+ deparseAConst(str, a_const);
3611
+ return;
3612
+ }
3246
3613
  }
3247
3614
 
3615
+
3248
3616
  if (need_parens)
3249
3617
  appendStringInfoChar(str, '(');
3250
3618
  deparseExpr(str, type_cast->arg);
@@ -3350,70 +3718,9 @@ static void deparseTypeName(StringInfo str, TypeName *type_name)
3350
3718
  }
3351
3719
  else if (strcmp(name, "interval") == 0 && list_length(type_name->typmods) >= 1)
3352
3720
  {
3353
- Assert(IsA(linitial(type_name->typmods), A_Const));
3354
- Assert(IsA(&castNode(A_Const, linitial(type_name->typmods))->val, Integer));
3355
-
3356
- int fields = intVal(&castNode(A_Const, linitial(type_name->typmods))->val);
3357
-
3358
3721
  appendStringInfoString(str, "interval");
3722
+ deparseIntervalTypmods(str, type_name);
3359
3723
 
3360
- // This logic is based on intervaltypmodout in timestamp.c
3361
- switch (fields)
3362
- {
3363
- case INTERVAL_MASK(YEAR):
3364
- appendStringInfoString(str, " year");
3365
- break;
3366
- case INTERVAL_MASK(MONTH):
3367
- appendStringInfoString(str, " month");
3368
- break;
3369
- case INTERVAL_MASK(DAY):
3370
- appendStringInfoString(str, " day");
3371
- break;
3372
- case INTERVAL_MASK(HOUR):
3373
- appendStringInfoString(str, " hour");
3374
- break;
3375
- case INTERVAL_MASK(MINUTE):
3376
- appendStringInfoString(str, " minute");
3377
- break;
3378
- case INTERVAL_MASK(SECOND):
3379
- appendStringInfoString(str, " second");
3380
- break;
3381
- case INTERVAL_MASK(YEAR) | INTERVAL_MASK(MONTH):
3382
- appendStringInfoString(str, " year to month");
3383
- break;
3384
- case INTERVAL_MASK(DAY) | INTERVAL_MASK(HOUR):
3385
- appendStringInfoString(str, " day to hour");
3386
- break;
3387
- case INTERVAL_MASK(DAY) | INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE):
3388
- appendStringInfoString(str, " day to minute");
3389
- break;
3390
- case INTERVAL_MASK(DAY) | INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE) | INTERVAL_MASK(SECOND):
3391
- appendStringInfoString(str, " day to second");
3392
- break;
3393
- case INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE):
3394
- appendStringInfoString(str, " hour to minute");
3395
- break;
3396
- case INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE) | INTERVAL_MASK(SECOND):
3397
- appendStringInfoString(str, " hour to second");
3398
- break;
3399
- case INTERVAL_MASK(MINUTE) | INTERVAL_MASK(SECOND):
3400
- appendStringInfoString(str, " minute to second");
3401
- break;
3402
- case INTERVAL_FULL_RANGE:
3403
- // Nothing
3404
- break;
3405
- default:
3406
- Assert(false);
3407
- break;
3408
- }
3409
-
3410
- if (list_length(type_name->typmods) == 2)
3411
- {
3412
- int precision = intVal(&castNode(A_Const, lsecond(type_name->typmods))->val);
3413
- if (precision != INTERVAL_FULL_PRECISION)
3414
- appendStringInfo(str, "(%d)", precision);
3415
- }
3416
-
3417
3724
  skip_typmods = true;
3418
3725
  }
3419
3726
  else
@@ -3459,6 +3766,79 @@ static void deparseTypeName(StringInfo str, TypeName *type_name)
3459
3766
  appendStringInfoString(str, "%type");
3460
3767
  }
3461
3768
 
3769
+ // Handle typemods for Interval types separately
3770
+ // so that they can be applied appropriately for different contexts.
3771
+ // For example, when using `SET` a query like `INTERVAL 'x' hour TO minute`
3772
+ // the `INTERVAL` keyword is specified first.
3773
+ // In all other contexts, intervals use the `'x'::interval` style.
3774
+ static void deparseIntervalTypmods(StringInfo str, TypeName *type_name)
3775
+ {
3776
+ const char *name = strVal(lsecond(type_name->names));
3777
+ Assert(strcmp(name, "interval") == 0);
3778
+ Assert(list_length(type_name->typmods) >= 1);
3779
+ Assert(IsA(linitial(type_name->typmods), A_Const));
3780
+ Assert(IsA(&castNode(A_Const, linitial(type_name->typmods))->val, Integer));
3781
+
3782
+ int fields = intVal(&castNode(A_Const, linitial(type_name->typmods))->val);
3783
+
3784
+ // This logic is based on intervaltypmodout in timestamp.c
3785
+ switch (fields)
3786
+ {
3787
+ case INTERVAL_MASK(YEAR):
3788
+ appendStringInfoString(str, " year");
3789
+ break;
3790
+ case INTERVAL_MASK(MONTH):
3791
+ appendStringInfoString(str, " month");
3792
+ break;
3793
+ case INTERVAL_MASK(DAY):
3794
+ appendStringInfoString(str, " day");
3795
+ break;
3796
+ case INTERVAL_MASK(HOUR):
3797
+ appendStringInfoString(str, " hour");
3798
+ break;
3799
+ case INTERVAL_MASK(MINUTE):
3800
+ appendStringInfoString(str, " minute");
3801
+ break;
3802
+ case INTERVAL_MASK(SECOND):
3803
+ appendStringInfoString(str, " second");
3804
+ break;
3805
+ case INTERVAL_MASK(YEAR) | INTERVAL_MASK(MONTH):
3806
+ appendStringInfoString(str, " year to month");
3807
+ break;
3808
+ case INTERVAL_MASK(DAY) | INTERVAL_MASK(HOUR):
3809
+ appendStringInfoString(str, " day to hour");
3810
+ break;
3811
+ case INTERVAL_MASK(DAY) | INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE):
3812
+ appendStringInfoString(str, " day to minute");
3813
+ break;
3814
+ case INTERVAL_MASK(DAY) | INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE) | INTERVAL_MASK(SECOND):
3815
+ appendStringInfoString(str, " day to second");
3816
+ break;
3817
+ case INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE):
3818
+ appendStringInfoString(str, " hour to minute");
3819
+ break;
3820
+ case INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE) | INTERVAL_MASK(SECOND):
3821
+ appendStringInfoString(str, " hour to second");
3822
+ break;
3823
+ case INTERVAL_MASK(MINUTE) | INTERVAL_MASK(SECOND):
3824
+ appendStringInfoString(str, " minute to second");
3825
+ break;
3826
+ case INTERVAL_FULL_RANGE:
3827
+ // Nothing
3828
+ break;
3829
+ default:
3830
+ Assert(false);
3831
+ break;
3832
+ }
3833
+
3834
+ if (list_length(type_name->typmods) == 2)
3835
+ {
3836
+ int precision = intVal(&castNode(A_Const, lsecond(type_name->typmods))->val);
3837
+ if (precision != INTERVAL_FULL_PRECISION)
3838
+ appendStringInfo(str, "(%d)", precision);
3839
+ }
3840
+ }
3841
+
3462
3842
  static void deparseNullTest(StringInfo str, NullTest *null_test)
3463
3843
  {
3464
3844
  // argisrow is always false in raw parser output
@@ -3602,7 +3982,7 @@ static void deparseColumnDef(StringInfo str, ColumnDef *column_def)
3602
3982
 
3603
3983
  if (column_def->colname != NULL)
3604
3984
  {
3605
- appendStringInfoString(str, column_def->colname);
3985
+ appendStringInfoString(str, quote_identifier(column_def->colname));
3606
3986
  appendStringInfoChar(str, ' ');
3607
3987
  }
3608
3988
 
@@ -3639,6 +4019,22 @@ static void deparseColumnDef(StringInfo str, ColumnDef *column_def)
3639
4019
  removeTrailingSpace(str);
3640
4020
  }
3641
4021
 
4022
+ static void deparseInsertOverride(StringInfo str, OverridingKind override)
4023
+ {
4024
+ switch (override)
4025
+ {
4026
+ case OVERRIDING_NOT_SET:
4027
+ // Do nothing
4028
+ break;
4029
+ case OVERRIDING_USER_VALUE:
4030
+ appendStringInfoString(str, "OVERRIDING USER VALUE ");
4031
+ break;
4032
+ case OVERRIDING_SYSTEM_VALUE:
4033
+ appendStringInfoString(str, "OVERRIDING SYSTEM VALUE ");
4034
+ break;
4035
+ }
4036
+ }
4037
+
3642
4038
  static void deparseInsertStmt(StringInfo str, InsertStmt *insert_stmt)
3643
4039
  {
3644
4040
  ListCell *lc;
@@ -3661,18 +4057,7 @@ static void deparseInsertStmt(StringInfo str, InsertStmt *insert_stmt)
3661
4057
  appendStringInfoString(str, ") ");
3662
4058
  }
3663
4059
 
3664
- switch (insert_stmt->override)
3665
- {
3666
- case OVERRIDING_NOT_SET:
3667
- // Do nothing
3668
- break;
3669
- case OVERRIDING_USER_VALUE:
3670
- appendStringInfoString(str, "OVERRIDING USER VALUE ");
3671
- break;
3672
- case OVERRIDING_SYSTEM_VALUE:
3673
- appendStringInfoString(str, "OVERRIDING SYSTEM VALUE ");
3674
- break;
3675
- }
4060
+ deparseInsertOverride(str, insert_stmt->override);
3676
4061
 
3677
4062
  if (insert_stmt->selectStmt != NULL)
3678
4063
  {
@@ -3799,6 +4184,90 @@ static void deparseUpdateStmt(StringInfo str, UpdateStmt *update_stmt)
3799
4184
  removeTrailingSpace(str);
3800
4185
  }
3801
4186
 
4187
+ static void deparseMergeStmt(StringInfo str, MergeStmt *merge_stmt)
4188
+ {
4189
+ if (merge_stmt->withClause != NULL)
4190
+ {
4191
+ deparseWithClause(str, merge_stmt->withClause);
4192
+ appendStringInfoChar(str, ' ');
4193
+ }
4194
+
4195
+ appendStringInfoString(str, "MERGE INTO ");
4196
+ deparseRangeVar(str, merge_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
4197
+ appendStringInfoChar(str, ' ');
4198
+
4199
+ appendStringInfoString(str, "USING ");
4200
+ deparseTableRef(str, merge_stmt->sourceRelation);
4201
+ appendStringInfoChar(str, ' ');
4202
+
4203
+ appendStringInfoString(str, "ON ");
4204
+ deparseExpr(str, merge_stmt->joinCondition);
4205
+ appendStringInfoChar(str, ' ');
4206
+
4207
+ ListCell *lc, *lc2;
4208
+ foreach (lc, merge_stmt->mergeWhenClauses)
4209
+ {
4210
+ MergeWhenClause *clause = castNode(MergeWhenClause, lfirst(lc));
4211
+
4212
+ appendStringInfoString(str, "WHEN ");
4213
+
4214
+ if (!clause->matched)
4215
+ {
4216
+ appendStringInfoString(str, "NOT ");
4217
+ }
4218
+
4219
+ appendStringInfoString(str, "MATCHED ");
4220
+
4221
+ if (clause->condition)
4222
+ {
4223
+ appendStringInfoString(str, "AND ");
4224
+ deparseExpr(str, clause->condition);
4225
+ appendStringInfoChar(str, ' ');
4226
+ }
4227
+
4228
+ appendStringInfoString(str, "THEN ");
4229
+
4230
+ switch (clause->commandType) {
4231
+ case CMD_INSERT:
4232
+ appendStringInfoString(str, "INSERT ");
4233
+
4234
+ if (clause->targetList) {
4235
+ appendStringInfoChar(str, '(');
4236
+ deparseInsertColumnList(str, clause->targetList);
4237
+ appendStringInfoString(str, ") ");
4238
+ }
4239
+
4240
+ deparseInsertOverride(str, clause->override);
4241
+
4242
+ if (clause->values) {
4243
+ appendStringInfoString(str, "VALUES (");
4244
+ deparseExprList(str, clause->values);
4245
+ appendStringInfoString(str, ")");
4246
+ } else {
4247
+ appendStringInfoString(str, "DEFAULT VALUES ");
4248
+ }
4249
+
4250
+ break;
4251
+ case CMD_UPDATE:
4252
+ appendStringInfoString(str, "UPDATE SET ");
4253
+ deparseSetClauseList(str, clause->targetList);
4254
+ break;
4255
+ case CMD_DELETE:
4256
+ appendStringInfoString(str, "DELETE");
4257
+ break;
4258
+ case CMD_NOTHING:
4259
+ appendStringInfoString(str, "DO NOTHING");
4260
+ break;
4261
+ default:
4262
+ elog(ERROR, "deparse: unpermitted command type in merge statement: %d", clause->commandType);
4263
+ break;
4264
+ }
4265
+
4266
+ if (lfirst(lc) != llast(merge_stmt->mergeWhenClauses))
4267
+ appendStringInfoChar(str, ' ');
4268
+ }
4269
+ }
4270
+
3802
4271
  static void deparseDeleteStmt(StringInfo str, DeleteStmt *delete_stmt)
3803
4272
  {
3804
4273
  if (delete_stmt->withClause != NULL)
@@ -3914,6 +4383,10 @@ static void deparseCreateCastStmt(StringInfo str, CreateCastStmt *create_cast_st
3914
4383
  case COERCION_ASSIGNMENT:
3915
4384
  appendStringInfoString(str, "AS ASSIGNMENT");
3916
4385
  break;
4386
+ case COERCION_PLPGSQL:
4387
+ // Not present in raw parser output
4388
+ Assert(false);
4389
+ break;
3917
4390
  case COERCION_EXPLICIT:
3918
4391
  // Default
3919
4392
  break;
@@ -4294,10 +4767,24 @@ static void deparseConstraint(StringInfo str, Constraint *constraint)
4294
4767
  appendStringInfoString(str, "ON DELETE CASCADE ");
4295
4768
  break;
4296
4769
  case FKCONSTR_ACTION_SETNULL:
4297
- appendStringInfoString(str, "ON DELETE SET NULL ");
4298
- break;
4299
4770
  case FKCONSTR_ACTION_SETDEFAULT:
4300
- appendStringInfoString(str, "ON DELETE SET DEFAULT ");
4771
+ appendStringInfoString(str, "ON DELETE SET ");
4772
+
4773
+ switch (constraint->fk_del_action) {
4774
+ case FKCONSTR_ACTION_SETDEFAULT: appendStringInfoString(str, "DEFAULT "); break;
4775
+ case FKCONSTR_ACTION_SETNULL: appendStringInfoString(str, "NULL "); break;
4776
+ }
4777
+
4778
+ if (constraint->fk_del_set_cols) {
4779
+ appendStringInfoString(str, "(");
4780
+ ListCell *lc;
4781
+ foreach (lc, constraint->fk_del_set_cols) {
4782
+ appendStringInfoString(str, strVal(lfirst(lc)));
4783
+ if (lfirst(lc) != llast(constraint->fk_del_set_cols))
4784
+ appendStringInfoString(str, ", ");
4785
+ }
4786
+ appendStringInfoString(str, ")");
4787
+ }
4301
4788
  break;
4302
4789
  default:
4303
4790
  // Not specified
@@ -4332,6 +4819,12 @@ static void deparseConstraint(StringInfo str, Constraint *constraint)
4332
4819
  removeTrailingSpace(str);
4333
4820
  }
4334
4821
 
4822
+ static void deparseReturnStmt(StringInfo str, ReturnStmt *return_stmt)
4823
+ {
4824
+ appendStringInfoString(str, "RETURN ");
4825
+ deparseExpr(str, return_stmt->returnval);
4826
+ }
4827
+
4335
4828
  static void deparseCreateFunctionStmt(StringInfo str, CreateFunctionStmt *create_function_stmt)
4336
4829
  {
4337
4830
  ListCell *lc;
@@ -4392,6 +4885,20 @@ static void deparseCreateFunctionStmt(StringInfo str, CreateFunctionStmt *create
4392
4885
  appendStringInfoChar(str, ' ');
4393
4886
  }
4394
4887
 
4888
+ if (create_function_stmt->sql_body)
4889
+ {
4890
+ /* RETURN or BEGIN ... END
4891
+ */
4892
+ if (IsA(create_function_stmt->sql_body, ReturnStmt))
4893
+ deparseReturnStmt(str, castNode(ReturnStmt, create_function_stmt->sql_body));
4894
+ else
4895
+ {
4896
+ appendStringInfoString(str, "BEGIN ATOMIC ");
4897
+ deparseExprList(str, castNode(List, create_function_stmt->sql_body));
4898
+ appendStringInfoString(str, "END ");
4899
+ }
4900
+ }
4901
+
4395
4902
  removeTrailingSpace(str);
4396
4903
  }
4397
4904
 
@@ -4400,7 +4907,7 @@ static void deparseFunctionParameter(StringInfo str, FunctionParameter *function
4400
4907
  switch (function_parameter->mode)
4401
4908
  {
4402
4909
  case FUNC_PARAM_IN: /* input only */
4403
- // Default
4910
+ appendStringInfoString(str, "IN ");
4404
4911
  break;
4405
4912
  case FUNC_PARAM_OUT: /* output only */
4406
4913
  appendStringInfoString(str, "OUT ");
@@ -4415,6 +4922,9 @@ static void deparseFunctionParameter(StringInfo str, FunctionParameter *function
4415
4922
  // No special annotation, the caller is expected to correctly put
4416
4923
  // this into the RETURNS part of the CREATE FUNCTION statement
4417
4924
  break;
4925
+ case FUNC_PARAM_DEFAULT:
4926
+ // Default
4927
+ break;
4418
4928
  default:
4419
4929
  Assert(false);
4420
4930
  break;
@@ -4446,7 +4956,6 @@ static void deparseCheckPointStmt(StringInfo str, CheckPointStmt *check_point_st
4446
4956
  static void deparseCreateSchemaStmt(StringInfo str, CreateSchemaStmt *create_schema_stmt)
4447
4957
  {
4448
4958
  ListCell *lc;
4449
-
4450
4959
  appendStringInfoString(str, "CREATE SCHEMA ");
4451
4960
 
4452
4961
  if (create_schema_stmt->if_not_exists)
@@ -4465,11 +4974,14 @@ static void deparseCreateSchemaStmt(StringInfo str, CreateSchemaStmt *create_sch
4465
4974
  appendStringInfoChar(str, ' ');
4466
4975
  }
4467
4976
 
4468
- foreach(lc, create_schema_stmt->schemaElts)
4977
+ if (create_schema_stmt->schemaElts)
4469
4978
  {
4470
- deparseSchemaStmt(str, lfirst(lc));
4471
- if (lnext(create_schema_stmt->schemaElts, lc))
4472
- appendStringInfoChar(str, ' ');
4979
+ foreach(lc, create_schema_stmt->schemaElts)
4980
+ {
4981
+ deparseSchemaStmt(str, lfirst(lc));
4982
+ if (lnext(create_schema_stmt->schemaElts, lc))
4983
+ appendStringInfoChar(str, ' ');
4984
+ }
4473
4985
  }
4474
4986
 
4475
4987
  removeTrailingSpace(str);
@@ -4523,6 +5035,9 @@ static void deparseRoleSpec(StringInfo str, RoleSpec *role_spec)
4523
5035
  Assert(role_spec->rolename != NULL);
4524
5036
  appendStringInfoString(str, quote_identifier(role_spec->rolename));
4525
5037
  break;
5038
+ case ROLESPEC_CURRENT_ROLE:
5039
+ appendStringInfoString(str, "CURRENT_ROLE");
5040
+ break;
4526
5041
  case ROLESPEC_CURRENT_USER:
4527
5042
  appendStringInfoString(str, "CURRENT_USER");
4528
5043
  break;
@@ -4619,6 +5134,8 @@ static void deparsePartitionCmd(StringInfo str, PartitionCmd *partition_cmd)
4619
5134
  appendStringInfoChar(str, ' ');
4620
5135
  deparsePartitionBoundSpec(str, partition_cmd->bound);
4621
5136
  }
5137
+ if (partition_cmd->concurrent)
5138
+ appendStringInfoString(str, " CONCURRENTLY ");
4622
5139
  }
4623
5140
 
4624
5141
  // "TableElement" in gram.y
@@ -4983,7 +5500,7 @@ static void deparseSecLabelStmt(StringInfo str, SecLabelStmt *sec_label_stmt)
4983
5500
  break;
4984
5501
  case OBJECT_LARGEOBJECT:
4985
5502
  appendStringInfoString(str, "LARGE OBJECT ");
4986
- deparseValue(str, (Value *) sec_label_stmt->object, DEPARSE_NODE_CONTEXT_CONSTANT);
5503
+ deparseValue(str, (union ValUnion *) sec_label_stmt->object, DEPARSE_NODE_CONTEXT_CONSTANT);
4987
5504
  break;
4988
5505
  case OBJECT_PROCEDURE:
4989
5506
  appendStringInfoString(str, "PROCEDURE ");
@@ -5067,7 +5584,7 @@ static void deparseCreateTableAsStmt(StringInfo str, CreateTableAsStmt *create_t
5067
5584
 
5068
5585
  deparseOptTemp(str, create_table_as_stmt->into->rel->relpersistence);
5069
5586
 
5070
- switch (create_table_as_stmt->relkind)
5587
+ switch (create_table_as_stmt->objtype)
5071
5588
  {
5072
5589
  case OBJECT_TABLE:
5073
5590
  appendStringInfoString(str, "TABLE ");
@@ -5340,7 +5857,7 @@ static void deparseDropStmt(StringInfo str, DropStmt *drop_stmt)
5340
5857
  appendStringInfoChar(str, ' ');
5341
5858
  break;
5342
5859
  case OBJECT_LANGUAGE:
5343
- deparseStringLiteral(str, strVal(linitial(drop_stmt->objects)));
5860
+ deparseNameList(str, drop_stmt->objects);
5344
5861
  appendStringInfoChar(str, ' ');
5345
5862
  break;
5346
5863
  case OBJECT_TYPE:
@@ -5471,8 +5988,7 @@ static void deparseAlterObjectDependsStmt(StringInfo str, AlterObjectDependsStmt
5471
5988
  if (alter_object_depends_stmt->remove)
5472
5989
  appendStringInfoString(str, "NO ");
5473
5990
 
5474
- appendStringInfoString(str, "DEPENDS ON EXTENSION ");
5475
- deparseColId(str, strVal(alter_object_depends_stmt->extname));
5991
+ appendStringInfo(str, "DEPENDS ON EXTENSION %s", alter_object_depends_stmt->extname->sval);
5476
5992
  }
5477
5993
 
5478
5994
  static void deparseAlterObjectSchemaStmt(StringInfo str, AlterObjectSchemaStmt *alter_object_schema_stmt)
@@ -5662,6 +6178,10 @@ static void deparseAlterTableCmd(StringInfo str, AlterTableCmd *alter_table_cmd,
5662
6178
  appendStringInfoString(str, "ALTER COLUMN ");
5663
6179
  options = "SET STORAGE";
5664
6180
  break;
6181
+ case AT_SetCompression: /* alter column set compression */
6182
+ appendStringInfoString(str, "ALTER COLUMN ");
6183
+ options = "SET COMPRESSION";
6184
+ break;
5665
6185
  case AT_DropColumn: /* drop column */
5666
6186
  if (context == DEPARSE_NODE_CONTEXT_ALTER_TYPE)
5667
6187
  appendStringInfoString(str, "DROP ATTRIBUTE ");
@@ -5709,6 +6229,7 @@ static void deparseAlterTableCmd(StringInfo str, AlterTableCmd *alter_table_cmd,
5709
6229
  Assert(false);
5710
6230
  break;
5711
6231
  case AT_ReAddComment: /* internal to commands/tablecmds.c */
6232
+ case AT_ReAddStatistics: /* internal to commands/tablecmds.c */
5712
6233
  Assert(false);
5713
6234
  break;
5714
6235
  case AT_AlterColumnType: /* alter column type */
@@ -5747,6 +6268,9 @@ static void deparseAlterTableCmd(StringInfo str, AlterTableCmd *alter_table_cmd,
5747
6268
  case AT_SetRelOptions: /* SET (...) -- AM specific parameters */
5748
6269
  appendStringInfoString(str, "SET ");
5749
6270
  break;
6271
+ case AT_SetAccessMethod:
6272
+ appendStringInfo(str, "SET ACCESS METHOD ");
6273
+ break;
5750
6274
  case AT_ResetRelOptions: /* RESET (...) -- AM specific parameters */
5751
6275
  appendStringInfoString(str, "RESET ");
5752
6276
  break;
@@ -5826,6 +6350,9 @@ static void deparseAlterTableCmd(StringInfo str, AlterTableCmd *alter_table_cmd,
5826
6350
  case AT_DetachPartition: /* DETACH PARTITION */
5827
6351
  appendStringInfoString(str, "DETACH PARTITION ");
5828
6352
  break;
6353
+ case AT_DetachPartitionFinalize: /* DETACH PARTITION FINALIZE */
6354
+ appendStringInfoString(str, "DETACH PARTITION ");
6355
+ break;
5829
6356
  case AT_AddIdentity: /* ADD IDENTITY */
5830
6357
  appendStringInfoString(str, "ALTER ");
5831
6358
  options = "ADD";
@@ -5874,6 +6401,10 @@ static void deparseAlterTableCmd(StringInfo str, AlterTableCmd *alter_table_cmd,
5874
6401
  deparsePartitionCmd(str, castNode(PartitionCmd, alter_table_cmd->def));
5875
6402
  appendStringInfoChar(str, ' ');
5876
6403
  break;
6404
+ case AT_DetachPartitionFinalize:
6405
+ deparsePartitionCmd(str, castNode(PartitionCmd, alter_table_cmd->def));
6406
+ appendStringInfoString(str, "FINALIZE ");
6407
+ break;
5877
6408
  case AT_AddColumn:
5878
6409
  case AT_AlterColumnType:
5879
6410
  deparseColumnDef(str, castNode(ColumnDef, alter_table_cmd->def));
@@ -5901,6 +6432,13 @@ static void deparseAlterTableCmd(StringInfo str, AlterTableCmd *alter_table_cmd,
5901
6432
  deparseColId(str, strVal(alter_table_cmd->def));
5902
6433
  appendStringInfoChar(str, ' ');
5903
6434
  break;
6435
+ case AT_SetCompression:
6436
+ if (strcmp(strVal(alter_table_cmd->def), "default") == 0)
6437
+ appendStringInfoString(str, "DEFAULT");
6438
+ else
6439
+ deparseColId(str, strVal(alter_table_cmd->def));
6440
+ appendStringInfoChar(str, ' ');
6441
+ break;
5904
6442
  case AT_AddIdentity:
5905
6443
  case AT_AddConstraint:
5906
6444
  case AT_AlterConstraint:
@@ -5939,14 +6477,9 @@ static void deparseAlterTableCmd(StringInfo str, AlterTableCmd *alter_table_cmd,
5939
6477
  removeTrailingSpace(str);
5940
6478
  }
5941
6479
 
5942
- static void deparseAlterTableStmt(StringInfo str, AlterTableStmt *alter_table_stmt)
6480
+ static DeparseNodeContext deparseAlterTableObjType(StringInfo str, ObjectType type)
5943
6481
  {
5944
- ListCell *lc;
5945
- DeparseNodeContext context = DEPARSE_NODE_CONTEXT_NONE;
5946
-
5947
- appendStringInfoString(str, "ALTER ");
5948
-
5949
- switch (alter_table_stmt->relkind)
6482
+ switch (type)
5950
6483
  {
5951
6484
  case OBJECT_TABLE:
5952
6485
  appendStringInfoString(str, "TABLE ");
@@ -5968,13 +6501,49 @@ static void deparseAlterTableStmt(StringInfo str, AlterTableStmt *alter_table_st
5968
6501
  break;
5969
6502
  case OBJECT_TYPE:
5970
6503
  appendStringInfoString(str, "TYPE ");
5971
- context = DEPARSE_NODE_CONTEXT_ALTER_TYPE;
6504
+ return DEPARSE_NODE_CONTEXT_ALTER_TYPE;
5972
6505
  break;
5973
6506
  default:
5974
6507
  Assert(false);
5975
6508
  break;
5976
6509
  }
5977
6510
 
6511
+ return DEPARSE_NODE_CONTEXT_NONE;
6512
+ }
6513
+
6514
+ static void deparseAlterTableMoveAllStmt(StringInfo str, AlterTableMoveAllStmt *move_all_stmt)
6515
+ {
6516
+ appendStringInfoString(str, "ALTER ");
6517
+ deparseAlterTableObjType(str, move_all_stmt->objtype);
6518
+
6519
+ appendStringInfoString(str, "ALL IN TABLESPACE ");
6520
+ appendStringInfoString(str, move_all_stmt->orig_tablespacename);
6521
+ appendStringInfoChar(str, ' ');
6522
+
6523
+ if (move_all_stmt->roles)
6524
+ {
6525
+ appendStringInfoString(str, "OWNED BY ");
6526
+ deparseRoleList(str, move_all_stmt->roles);
6527
+ appendStringInfoChar(str, ' ');
6528
+ }
6529
+
6530
+ appendStringInfoString(str, "SET TABLESPACE ");
6531
+ appendStringInfoString(str, move_all_stmt->new_tablespacename);
6532
+ appendStringInfoChar(str, ' ');
6533
+
6534
+ if (move_all_stmt->nowait)
6535
+ {
6536
+ appendStringInfoString(str, "NOWAIT");
6537
+ }
6538
+ }
6539
+
6540
+ static void deparseAlterTableStmt(StringInfo str, AlterTableStmt *alter_table_stmt)
6541
+ {
6542
+ ListCell *lc;
6543
+
6544
+ appendStringInfoString(str, "ALTER ");
6545
+ DeparseNodeContext context = deparseAlterTableObjType(str, alter_table_stmt->objtype);
6546
+
5978
6547
  if (alter_table_stmt->missing_ok)
5979
6548
  appendStringInfoString(str, "IF EXISTS ");
5980
6549
 
@@ -6354,6 +6923,22 @@ static void deparseTransactionStmt(StringInfo str, TransactionStmt *transaction_
6354
6923
  removeTrailingSpace(str);
6355
6924
  }
6356
6925
 
6926
+ // Determine if we hit SET TIME ZONE INTERVAL, that has special syntax not
6927
+ // supported for other SET statements
6928
+ static bool isSetTimeZoneInterval(VariableSetStmt* stmt)
6929
+ {
6930
+ if (!(strcmp(stmt->name, "timezone") == 0 &&
6931
+ list_length(stmt->args) == 1 &&
6932
+ IsA(linitial(stmt->args), TypeCast)))
6933
+ return false;
6934
+
6935
+ TypeName* typeName = castNode(TypeCast, linitial(stmt->args))->typeName;
6936
+
6937
+ return (list_length(typeName->names) == 2 &&
6938
+ strcmp(strVal(linitial(typeName->names)), "pg_catalog") == 0 &&
6939
+ strcmp(strVal(llast(typeName->names)), "interval") == 0);
6940
+ }
6941
+
6357
6942
  static void deparseVariableSetStmt(StringInfo str, VariableSetStmt* variable_set_stmt)
6358
6943
  {
6359
6944
  ListCell *lc;
@@ -6364,9 +6949,17 @@ static void deparseVariableSetStmt(StringInfo str, VariableSetStmt* variable_set
6364
6949
  appendStringInfoString(str, "SET ");
6365
6950
  if (variable_set_stmt->is_local)
6366
6951
  appendStringInfoString(str, "LOCAL ");
6367
- deparseVarName(str, variable_set_stmt->name);
6368
- appendStringInfoString(str, " TO ");
6369
- deparseVarList(str, variable_set_stmt->args);
6952
+ if (isSetTimeZoneInterval(variable_set_stmt))
6953
+ {
6954
+ appendStringInfoString(str, "TIME ZONE ");
6955
+ deparseVarList(str, variable_set_stmt->args);
6956
+ }
6957
+ else
6958
+ {
6959
+ deparseVarName(str, variable_set_stmt->name);
6960
+ appendStringInfoString(str, " TO ");
6961
+ deparseVarList(str, variable_set_stmt->args);
6962
+ }
6370
6963
  break;
6371
6964
  case VAR_SET_DEFAULT: /* SET var TO DEFAULT */
6372
6965
  appendStringInfoString(str, "SET ");
@@ -6458,28 +7051,7 @@ static void deparseVacuumStmt(StringInfo str, VacuumStmt *vacuum_stmt)
6458
7051
  else
6459
7052
  appendStringInfoString(str, "ANALYZE ");
6460
7053
 
6461
- if (list_length(vacuum_stmt->options) > 0)
6462
- {
6463
- appendStringInfoChar(str, '(');
6464
- foreach(lc, vacuum_stmt->options)
6465
- {
6466
- DefElem *def_elem = castNode(DefElem, lfirst(lc));
6467
- deparseGenericDefElemName(str, def_elem->defname);
6468
- if (def_elem->arg != NULL)
6469
- {
6470
- appendStringInfoChar(str, ' ');
6471
- if (IsA(def_elem->arg, Integer) || IsA(def_elem->arg, Float))
6472
- deparseNumericOnly(str, (Value *) def_elem->arg);
6473
- else if (IsA(def_elem->arg, String))
6474
- deparseOptBooleanOrString(str, strVal(def_elem->arg));
6475
- else
6476
- Assert(false);
6477
- }
6478
- if (lnext(vacuum_stmt->options, lc))
6479
- appendStringInfoString(str, ", ");
6480
- }
6481
- appendStringInfoString(str, ") ");
6482
- }
7054
+ deparseUtilityOptionList(str, vacuum_stmt->options);
6483
7055
 
6484
7056
  foreach(lc, vacuum_stmt->rels)
6485
7057
  {
@@ -6590,31 +7162,7 @@ static void deparseExplainStmt(StringInfo str, ExplainStmt *explain_stmt)
6590
7162
 
6591
7163
  appendStringInfoString(str, "EXPLAIN ");
6592
7164
 
6593
- if (list_length(explain_stmt->options) > 0)
6594
- {
6595
- appendStringInfoChar(str, '(');
6596
-
6597
- foreach(lc, explain_stmt->options)
6598
- {
6599
- DefElem *def_elem = castNode(DefElem, lfirst(lc));
6600
- deparseGenericDefElemName(str, def_elem->defname);
6601
-
6602
- if (def_elem->arg != NULL && IsA(def_elem->arg, String))
6603
- {
6604
- appendStringInfoChar(str, ' ');
6605
- deparseOptBooleanOrString(str, strVal(def_elem->arg));
6606
- }
6607
- else if (def_elem->arg != NULL && (IsA(def_elem->arg, Integer) || IsA(def_elem->arg, Float)))
6608
- {
6609
- appendStringInfoChar(str, ' ');
6610
- deparseNumericOnly(str, (Value *) def_elem->arg);
6611
- }
6612
-
6613
- if (lnext(explain_stmt->options, lc))
6614
- appendStringInfoString(str, ", ");
6615
- }
6616
- appendStringInfoString(str, ") ");
6617
- }
7165
+ deparseUtilityOptionList(str, explain_stmt->options);
6618
7166
 
6619
7167
  deparseExplainableStmt(str, explain_stmt->query);
6620
7168
  }
@@ -6668,130 +7216,194 @@ static void deparseCopyStmt(StringInfo str, CopyStmt *copy_stmt)
6668
7216
 
6669
7217
  if (list_length(copy_stmt->options) > 0)
6670
7218
  {
6671
- appendStringInfoString(str, "WITH (");
7219
+ // In some cases, equivalent expressions may have slightly different parse trees for `COPY`
7220
+ // statements. For example the following two statements result in different (but equivalent) parse
7221
+ // trees:
7222
+ //
7223
+ // - COPY foo FROM STDIN CSV FREEZE
7224
+ // - COPY foo FROM STDIN WITH (FORMAT CSV, FREEZE)
7225
+ //
7226
+ // In order to make sure we deparse to the "correct" version, we always try to deparse to the older
7227
+ // compact syntax first.
7228
+ //
7229
+ // The old syntax can be seen here in the Postgres 8.4 Reference:
7230
+ // https://www.postgresql.org/docs/8.4/sql-copy.html
7231
+
7232
+ bool old_fmt = true;
7233
+
7234
+ // Loop over the options to see if any require the new `WITH (...)` syntax.
6672
7235
  foreach(lc, copy_stmt->options)
6673
7236
  {
6674
7237
  DefElem *def_elem = castNode(DefElem, lfirst(lc));
6675
7238
 
6676
- if (strcmp(def_elem->defname, "format") == 0)
6677
- {
6678
- appendStringInfoString(str, "FORMAT ");
6679
-
6680
- char *format = strVal(def_elem->arg);
6681
- if (strcmp(format, "binary") == 0)
6682
- appendStringInfoString(str, "BINARY");
6683
- else if (strcmp(format, "csv") == 0)
6684
- appendStringInfoString(str, "CSV");
6685
- else
6686
- Assert(false);
6687
- }
6688
- else if (strcmp(def_elem->defname, "freeze") == 0 && (def_elem->arg == NULL || intVal(def_elem->arg) == 1))
6689
- {
6690
- appendStringInfoString(str, "FREEZE");
6691
- if (def_elem->arg != NULL && intVal(def_elem->arg) == 1)
6692
- appendStringInfoString(str, " 1");
6693
- }
6694
- else if (strcmp(def_elem->defname, "delimiter") == 0)
6695
- {
6696
- appendStringInfoString(str, "DELIMITER ");
6697
- deparseStringLiteral(str, strVal(def_elem->arg));
6698
- }
6699
- else if (strcmp(def_elem->defname, "null") == 0)
6700
- {
6701
- appendStringInfoString(str, "NULL ");
6702
- deparseStringLiteral(str, strVal(def_elem->arg));
6703
- }
6704
- else if (strcmp(def_elem->defname, "header") == 0 && (def_elem->arg == NULL || intVal(def_elem->arg) == 1))
6705
- {
6706
- appendStringInfoString(str, "HEADER");
6707
- if (def_elem->arg != NULL && intVal(def_elem->arg) == 1)
6708
- appendStringInfoString(str, " 1");
6709
- }
6710
- else if (strcmp(def_elem->defname, "quote") == 0)
6711
- {
6712
- appendStringInfoString(str, "QUOTE ");
6713
- deparseStringLiteral(str, strVal(def_elem->arg));
6714
- }
6715
- else if (strcmp(def_elem->defname, "escape") == 0)
7239
+ if (strcmp(def_elem->defname, "freeze") == 0 && optBooleanValue(def_elem->arg))
7240
+ {}
7241
+ else if (strcmp(def_elem->defname, "header") == 0 && def_elem->arg && optBooleanValue(def_elem->arg))
7242
+ {}
7243
+ else if (strcmp(def_elem->defname, "format") == 0 && strcmp(strVal(def_elem->arg), "csv") == 0)
7244
+ {}
7245
+ else if (strcmp(def_elem->defname, "force_quote") == 0 && def_elem->arg && nodeTag(def_elem->arg) == T_List)
7246
+ {}
7247
+ else
6716
7248
  {
6717
- appendStringInfoString(str, "ESCAPE ");
6718
- deparseStringLiteral(str, strVal(def_elem->arg));
7249
+ old_fmt = false;
7250
+ break;
6719
7251
  }
6720
- else if (strcmp(def_elem->defname, "force_quote") == 0)
7252
+ }
7253
+
7254
+ // Branch to differing output modes, depending on if we can use the old syntax.
7255
+ if (old_fmt) {
7256
+ foreach(lc, copy_stmt->options)
6721
7257
  {
6722
- appendStringInfoString(str, "FORCE_QUOTE ");
6723
- if (IsA(def_elem->arg, A_Star))
7258
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
7259
+
7260
+ if (strcmp(def_elem->defname, "freeze") == 0 && optBooleanValue(def_elem->arg))
6724
7261
  {
6725
- appendStringInfoChar(str, '*');
7262
+ appendStringInfoString(str, "FREEZE ");
6726
7263
  }
6727
- else if (IsA(def_elem->arg, List))
7264
+ else if (strcmp(def_elem->defname, "header") == 0 && def_elem->arg && optBooleanValue(def_elem->arg))
6728
7265
  {
6729
- appendStringInfoChar(str, '(');
7266
+ appendStringInfoString(str, "HEADER ");
7267
+ }
7268
+ else if (strcmp(def_elem->defname, "format") == 0 && strcmp(strVal(def_elem->arg), "csv") == 0)
7269
+ {
7270
+ appendStringInfoString(str, "CSV ");
7271
+ }
7272
+ else if (strcmp(def_elem->defname, "force_quote") == 0 && def_elem->arg && nodeTag(def_elem->arg) == T_List)
7273
+ {
7274
+ appendStringInfoString(str, "FORCE QUOTE ");
6730
7275
  deparseColumnList(str, castNode(List, def_elem->arg));
6731
- appendStringInfoChar(str, ')');
6732
7276
  }
6733
7277
  else
6734
7278
  {
7279
+ // This isn't reachable, the conditions here are exactly the same as the first loop above.
6735
7280
  Assert(false);
6736
7281
  }
6737
7282
  }
6738
- else if (strcmp(def_elem->defname, "force_not_null") == 0)
6739
- {
6740
- appendStringInfoString(str, "FORCE_NOT_NULL (");
6741
- deparseColumnList(str, castNode(List, def_elem->arg));
6742
- appendStringInfoChar(str, ')');
6743
- }
6744
- else if (strcmp(def_elem->defname, "force_null") == 0)
6745
- {
6746
- appendStringInfoString(str, "FORCE_NULL (");
6747
- deparseColumnList(str, castNode(List, def_elem->arg));
6748
- appendStringInfoChar(str, ')');
6749
- }
6750
- else if (strcmp(def_elem->defname, "encoding") == 0)
6751
- {
6752
- appendStringInfoString(str, "ENCODING ");
6753
- deparseStringLiteral(str, strVal(def_elem->arg));
6754
- }
6755
- else
7283
+ } else {
7284
+ appendStringInfoString(str, "WITH (");
7285
+ foreach(lc, copy_stmt->options)
6756
7286
  {
6757
- appendStringInfoString(str, quote_identifier(def_elem->defname));
6758
- if (def_elem->arg != NULL)
6759
- appendStringInfoChar(str, ' ');
6760
-
6761
- if (def_elem->arg == NULL)
7287
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
7288
+
7289
+ if (strcmp(def_elem->defname, "format") == 0)
7290
+ {
7291
+ appendStringInfoString(str, "FORMAT ");
7292
+
7293
+ char *format = strVal(def_elem->arg);
7294
+ if (strcmp(format, "binary") == 0)
7295
+ appendStringInfoString(str, "BINARY");
7296
+ else if (strcmp(format, "csv") == 0)
7297
+ appendStringInfoString(str, "CSV");
7298
+ else
7299
+ Assert(false);
7300
+ }
7301
+ else if (strcmp(def_elem->defname, "freeze") == 0)
6762
7302
  {
6763
- // Nothing
7303
+ appendStringInfoString(str, "FREEZE");
7304
+ deparseOptBoolean(str, def_elem->arg);
6764
7305
  }
6765
- else if (IsA(def_elem->arg, String))
7306
+ else if (strcmp(def_elem->defname, "delimiter") == 0)
6766
7307
  {
6767
- deparseOptBooleanOrString(str, strVal(def_elem->arg));
7308
+ appendStringInfoString(str, "DELIMITER ");
7309
+ deparseStringLiteral(str, strVal(def_elem->arg));
6768
7310
  }
6769
- else if (IsA(def_elem->arg, Integer) || IsA(def_elem->arg, Float))
7311
+ else if (strcmp(def_elem->defname, "null") == 0)
6770
7312
  {
6771
- deparseNumericOnly(str, (Value *) def_elem->arg);
7313
+ appendStringInfoString(str, "NULL ");
7314
+ deparseStringLiteral(str, strVal(def_elem->arg));
6772
7315
  }
6773
- else if (IsA(def_elem->arg, A_Star))
7316
+ else if (strcmp(def_elem->defname, "header") == 0)
6774
7317
  {
6775
- deparseAStar(str, castNode(A_Star, def_elem->arg));
7318
+ appendStringInfoString(str, "HEADER");
7319
+ deparseOptBoolean(str, def_elem->arg);
6776
7320
  }
6777
- else if (IsA(def_elem->arg, List))
7321
+ else if (strcmp(def_elem->defname, "quote") == 0)
6778
7322
  {
6779
- List *l = castNode(List, def_elem->arg);
6780
- appendStringInfoChar(str, '(');
6781
- foreach(lc2, l)
7323
+ appendStringInfoString(str, "QUOTE ");
7324
+ deparseStringLiteral(str, strVal(def_elem->arg));
7325
+ }
7326
+ else if (strcmp(def_elem->defname, "escape") == 0)
7327
+ {
7328
+ appendStringInfoString(str, "ESCAPE ");
7329
+ deparseStringLiteral(str, strVal(def_elem->arg));
7330
+ }
7331
+ else if (strcmp(def_elem->defname, "force_quote") == 0)
7332
+ {
7333
+ appendStringInfoString(str, "FORCE_QUOTE ");
7334
+ if (IsA(def_elem->arg, A_Star))
7335
+ {
7336
+ appendStringInfoChar(str, '*');
7337
+ }
7338
+ else if (IsA(def_elem->arg, List))
7339
+ {
7340
+ appendStringInfoChar(str, '(');
7341
+ deparseColumnList(str, castNode(List, def_elem->arg));
7342
+ appendStringInfoChar(str, ')');
7343
+ }
7344
+ else
6782
7345
  {
6783
- deparseOptBooleanOrString(str, strVal(lfirst(lc2)));
6784
- if (lnext(l, lc2))
6785
- appendStringInfoString(str, ", ");
7346
+ Assert(false);
6786
7347
  }
7348
+ }
7349
+ else if (strcmp(def_elem->defname, "force_not_null") == 0)
7350
+ {
7351
+ appendStringInfoString(str, "FORCE_NOT_NULL (");
7352
+ deparseColumnList(str, castNode(List, def_elem->arg));
6787
7353
  appendStringInfoChar(str, ')');
6788
7354
  }
6789
- }
7355
+ else if (strcmp(def_elem->defname, "force_null") == 0)
7356
+ {
7357
+ appendStringInfoString(str, "FORCE_NULL (");
7358
+ deparseColumnList(str, castNode(List, def_elem->arg));
7359
+ appendStringInfoChar(str, ')');
7360
+ }
7361
+ else if (strcmp(def_elem->defname, "encoding") == 0)
7362
+ {
7363
+ appendStringInfoString(str, "ENCODING ");
7364
+ deparseStringLiteral(str, strVal(def_elem->arg));
7365
+ }
7366
+ else
7367
+ {
7368
+ appendStringInfoString(str, quote_identifier(def_elem->defname));
7369
+ if (def_elem->arg != NULL)
7370
+ appendStringInfoChar(str, ' ');
7371
+
7372
+ if (def_elem->arg == NULL)
7373
+ {
7374
+ // Nothing
7375
+ }
7376
+ else if (IsA(def_elem->arg, String))
7377
+ {
7378
+ deparseOptBooleanOrString(str, strVal(def_elem->arg));
7379
+ }
7380
+ else if (IsA(def_elem->arg, Integer) || IsA(def_elem->arg, Float))
7381
+ {
7382
+ deparseNumericOnly(str, (union ValUnion *) def_elem->arg);
7383
+ }
7384
+ else if (IsA(def_elem->arg, A_Star))
7385
+ {
7386
+ deparseAStar(str, castNode(A_Star, def_elem->arg));
7387
+ }
7388
+ else if (IsA(def_elem->arg, List))
7389
+ {
7390
+ List *l = castNode(List, def_elem->arg);
7391
+ appendStringInfoChar(str, '(');
7392
+ foreach(lc2, l)
7393
+ {
7394
+ deparseOptBooleanOrString(str, strVal(lfirst(lc2)));
7395
+ if (lnext(l, lc2))
7396
+ appendStringInfoString(str, ", ");
7397
+ }
7398
+ appendStringInfoChar(str, ')');
7399
+ }
7400
+ }
6790
7401
 
6791
- if (lnext(copy_stmt->options, lc))
6792
- appendStringInfoString(str, ", ");
7402
+ if (lnext(copy_stmt->options, lc))
7403
+ appendStringInfoString(str, ", ");
7404
+ }
7405
+ appendStringInfoString(str, ") ");
6793
7406
  }
6794
- appendStringInfoString(str, ") ");
6795
7407
  }
6796
7408
 
6797
7409
  deparseWhereClause(str, copy_stmt->whereClause);
@@ -7248,7 +7860,6 @@ static void deparseAccessPriv(StringInfo str, AccessPriv *access_priv)
7248
7860
  static void deparseGrantStmt(StringInfo str, GrantStmt *grant_stmt)
7249
7861
  {
7250
7862
  ListCell *lc;
7251
-
7252
7863
  if (grant_stmt->is_grant)
7253
7864
  appendStringInfoString(str, "GRANT ");
7254
7865
  else
@@ -7295,6 +7906,12 @@ static void deparseGrantStmt(StringInfo str, GrantStmt *grant_stmt)
7295
7906
 
7296
7907
  deparseOptDropBehavior(str, grant_stmt->behavior);
7297
7908
 
7909
+ if (grant_stmt->grantor)
7910
+ {
7911
+ appendStringInfoString(str, "GRANTED BY ");
7912
+ deparseRoleSpec(str, castNode(RoleSpec, grant_stmt->grantor));
7913
+ }
7914
+
7298
7915
  removeTrailingSpace(str);
7299
7916
  }
7300
7917
 
@@ -7307,6 +7924,9 @@ static void deparseGrantRoleStmt(StringInfo str, GrantRoleStmt *grant_role_stmt)
7307
7924
  else
7308
7925
  appendStringInfoString(str, "REVOKE ");
7309
7926
 
7927
+ if (!grant_role_stmt->is_grant && grant_role_stmt->admin_opt)
7928
+ appendStringInfoString(str, "ADMIN OPTION FOR ");
7929
+
7310
7930
  foreach(lc, grant_role_stmt->granted_roles)
7311
7931
  {
7312
7932
  deparseAccessPriv(str, castNode(AccessPriv, lfirst(lc)));
@@ -7323,9 +7943,15 @@ static void deparseGrantRoleStmt(StringInfo str, GrantRoleStmt *grant_role_stmt)
7323
7943
  deparseRoleList(str, grant_role_stmt->grantee_roles);
7324
7944
  appendStringInfoChar(str, ' ');
7325
7945
 
7326
- if (grant_role_stmt->admin_opt)
7946
+ if (grant_role_stmt->is_grant && grant_role_stmt->admin_opt)
7327
7947
  appendStringInfoString(str, "WITH ADMIN OPTION ");
7328
7948
 
7949
+ if (grant_role_stmt->grantor)
7950
+ {
7951
+ appendStringInfoString(str, "GRANTED BY ");
7952
+ deparseRoleSpec(str, castNode(RoleSpec, grant_role_stmt->grantor));
7953
+ }
7954
+
7329
7955
  removeTrailingSpace(str);
7330
7956
  }
7331
7957
 
@@ -7360,7 +7986,7 @@ static void deparseIndexStmt(StringInfo str, IndexStmt *index_stmt)
7360
7986
 
7361
7987
  if (index_stmt->idxname != NULL)
7362
7988
  {
7363
- appendStringInfoString(str, index_stmt->idxname);
7989
+ appendStringInfoString(str, quote_identifier(index_stmt->idxname));
7364
7990
  appendStringInfoChar(str, ' ');
7365
7991
  }
7366
7992
 
@@ -7396,6 +8022,11 @@ static void deparseIndexStmt(StringInfo str, IndexStmt *index_stmt)
7396
8022
  appendStringInfoString(str, ") ");
7397
8023
  }
7398
8024
 
8025
+ if (index_stmt->nulls_not_distinct)
8026
+ {
8027
+ appendStringInfoString(str, "NULLS NOT DISTINCT ");
8028
+ }
8029
+
7399
8030
  deparseOptWith(str, index_stmt->options);
7400
8031
 
7401
8032
  if (index_stmt->tableSpace != NULL)
@@ -7499,59 +8130,59 @@ static void deparseAlterRoleElem(StringInfo str, DefElem *def_elem)
7499
8130
  appendStringInfoString(str, "VALID UNTIL ");
7500
8131
  deparseStringLiteral(str, strVal(def_elem->arg));
7501
8132
  }
7502
- else if (strcmp(def_elem->defname, "superuser") == 0 && intVal(def_elem->arg) == 1)
8133
+ else if (strcmp(def_elem->defname, "superuser") == 0 && boolVal(def_elem->arg))
7503
8134
  {
7504
8135
  appendStringInfoString(str, "SUPERUSER");
7505
8136
  }
7506
- else if (strcmp(def_elem->defname, "superuser") == 0 && intVal(def_elem->arg) == 0)
8137
+ else if (strcmp(def_elem->defname, "superuser") == 0 && !boolVal(def_elem->arg))
7507
8138
  {
7508
8139
  appendStringInfoString(str, "NOSUPERUSER");
7509
8140
  }
7510
- else if (strcmp(def_elem->defname, "createrole") == 0 && intVal(def_elem->arg) == 1)
8141
+ else if (strcmp(def_elem->defname, "createrole") == 0 && boolVal(def_elem->arg))
7511
8142
  {
7512
8143
  appendStringInfoString(str, "CREATEROLE");
7513
8144
  }
7514
- else if (strcmp(def_elem->defname, "createrole") == 0 && intVal(def_elem->arg) == 0)
8145
+ else if (strcmp(def_elem->defname, "createrole") == 0 && !boolVal(def_elem->arg))
7515
8146
  {
7516
8147
  appendStringInfoString(str, "NOCREATEROLE");
7517
8148
  }
7518
- else if (strcmp(def_elem->defname, "isreplication") == 0 && intVal(def_elem->arg) == 1)
8149
+ else if (strcmp(def_elem->defname, "isreplication") == 0 && boolVal(def_elem->arg))
7519
8150
  {
7520
8151
  appendStringInfoString(str, "REPLICATION");
7521
8152
  }
7522
- else if (strcmp(def_elem->defname, "isreplication") == 0 && intVal(def_elem->arg) == 0)
8153
+ else if (strcmp(def_elem->defname, "isreplication") == 0 && !boolVal(def_elem->arg))
7523
8154
  {
7524
8155
  appendStringInfoString(str, "NOREPLICATION");
7525
8156
  }
7526
- else if (strcmp(def_elem->defname, "createdb") == 0 && intVal(def_elem->arg) == 1)
8157
+ else if (strcmp(def_elem->defname, "createdb") == 0 && boolVal(def_elem->arg))
7527
8158
  {
7528
8159
  appendStringInfoString(str, "CREATEDB");
7529
8160
  }
7530
- else if (strcmp(def_elem->defname, "createdb") == 0 && intVal(def_elem->arg) == 0)
8161
+ else if (strcmp(def_elem->defname, "createdb") == 0 && !boolVal(def_elem->arg))
7531
8162
  {
7532
8163
  appendStringInfoString(str, "NOCREATEDB");
7533
8164
  }
7534
- else if (strcmp(def_elem->defname, "canlogin") == 0 && intVal(def_elem->arg) == 1)
8165
+ else if (strcmp(def_elem->defname, "canlogin") == 0 && boolVal(def_elem->arg))
7535
8166
  {
7536
8167
  appendStringInfoString(str, "LOGIN");
7537
8168
  }
7538
- else if (strcmp(def_elem->defname, "canlogin") == 0 && intVal(def_elem->arg) == 0)
8169
+ else if (strcmp(def_elem->defname, "canlogin") == 0 && !boolVal(def_elem->arg))
7539
8170
  {
7540
8171
  appendStringInfoString(str, "NOLOGIN");
7541
8172
  }
7542
- else if (strcmp(def_elem->defname, "bypassrls") == 0 && intVal(def_elem->arg) == 1)
8173
+ else if (strcmp(def_elem->defname, "bypassrls") == 0 && boolVal(def_elem->arg))
7543
8174
  {
7544
8175
  appendStringInfoString(str, "BYPASSRLS");
7545
8176
  }
7546
- else if (strcmp(def_elem->defname, "bypassrls") == 0 && intVal(def_elem->arg) == 0)
8177
+ else if (strcmp(def_elem->defname, "bypassrls") == 0 && !boolVal(def_elem->arg))
7547
8178
  {
7548
8179
  appendStringInfoString(str, "NOBYPASSRLS");
7549
8180
  }
7550
- else if (strcmp(def_elem->defname, "inherit") == 0 && intVal(def_elem->arg) == 1)
8181
+ else if (strcmp(def_elem->defname, "inherit") == 0 && boolVal(def_elem->arg))
7551
8182
  {
7552
8183
  appendStringInfoString(str, "INHERIT");
7553
8184
  }
7554
- else if (strcmp(def_elem->defname, "inherit") == 0 && intVal(def_elem->arg) == 0)
8185
+ else if (strcmp(def_elem->defname, "inherit") == 0 && !boolVal(def_elem->arg))
7555
8186
  {
7556
8187
  appendStringInfoString(str, "NOINHERIT");
7557
8188
  }
@@ -7824,8 +8455,7 @@ static void deparseReindexStmt(StringInfo str, ReindexStmt *reindex_stmt)
7824
8455
  {
7825
8456
  appendStringInfoString(str, "REINDEX ");
7826
8457
 
7827
- if (reindex_stmt->options & REINDEXOPT_VERBOSE)
7828
- appendStringInfoString(str, "(VERBOSE) ");
8458
+ deparseUtilityOptionList(str, reindex_stmt->params);
7829
8459
 
7830
8460
  switch (reindex_stmt->kind)
7831
8461
  {
@@ -7846,9 +8476,6 @@ static void deparseReindexStmt(StringInfo str, ReindexStmt *reindex_stmt)
7846
8476
  break;
7847
8477
  }
7848
8478
 
7849
- if (reindex_stmt->concurrent)
7850
- appendStringInfoString(str, "CONCURRENTLY ");
7851
-
7852
8479
  if (reindex_stmt->relation != NULL)
7853
8480
  {
7854
8481
  deparseRangeVar(str, reindex_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
@@ -7892,6 +8519,9 @@ static void deparseRuleStmt(StringInfo str, RuleStmt* rule_stmt)
7892
8519
  case CMD_DELETE:
7893
8520
  appendStringInfoString(str, "DELETE ");
7894
8521
  break;
8522
+ case CMD_MERGE:
8523
+ appendStringInfoString(str, "MERGE ");
8524
+ break;
7895
8525
  }
7896
8526
 
7897
8527
  appendStringInfoString(str, "TO ");
@@ -8214,7 +8844,12 @@ static void deparseCreateTableSpaceStmt(StringInfo str, CreateTableSpaceStmt *cr
8214
8844
  }
8215
8845
 
8216
8846
  appendStringInfoString(str, "LOCATION ");
8217
- deparseStringLiteral(str, create_table_space_stmt->location);
8847
+
8848
+ if (create_table_space_stmt->location != NULL)
8849
+ deparseStringLiteral(str, create_table_space_stmt->location);
8850
+ else
8851
+ appendStringInfoString(str, "''");
8852
+
8218
8853
  appendStringInfoChar(str, ' ');
8219
8854
 
8220
8855
  deparseOptWith(str, create_table_space_stmt->options);
@@ -8277,6 +8912,50 @@ static void deparseCreateAmStmt(StringInfo str, CreateAmStmt *create_am_stmt)
8277
8912
  deparseHandlerName(str, create_am_stmt->handler_name);
8278
8913
  }
8279
8914
 
8915
+ static void deparsePublicationObjectList(StringInfo str, List *pubobjects) {
8916
+ const ListCell *lc;
8917
+ foreach(lc, pubobjects) {
8918
+ PublicationObjSpec *obj = lfirst(lc);
8919
+
8920
+ switch (obj->pubobjtype) {
8921
+ case PUBLICATIONOBJ_TABLE:
8922
+ appendStringInfoString(str, "TABLE ");
8923
+ deparseRangeVar(str, obj->pubtable->relation, DEPARSE_NODE_CONTEXT_NONE);
8924
+
8925
+ if (obj->pubtable->columns)
8926
+ {
8927
+ appendStringInfoChar(str, '(');
8928
+ deparseColumnList(str, obj->pubtable->columns);
8929
+ appendStringInfoChar(str, ')');
8930
+ }
8931
+
8932
+ if (obj->pubtable->whereClause)
8933
+ {
8934
+ appendStringInfoString(str, " WHERE (");
8935
+ deparseExpr(str, obj->pubtable->whereClause);
8936
+ appendStringInfoString(str, ")");
8937
+ }
8938
+
8939
+ break;
8940
+ case PUBLICATIONOBJ_TABLES_IN_SCHEMA:
8941
+ appendStringInfoString(str, "TABLES IN SCHEMA ");
8942
+ appendStringInfoString(str, quote_identifier(obj->name));
8943
+ break;
8944
+ case PUBLICATIONOBJ_TABLES_IN_CUR_SCHEMA:
8945
+ appendStringInfoString(str, "TABLES IN SCHEMA CURRENT_SCHEMA");
8946
+ break;
8947
+ case PUBLICATIONOBJ_CONTINUATION:
8948
+ // This should be unreachable, the parser merges these before we can even get here.
8949
+ Assert(false);
8950
+ break;
8951
+ }
8952
+
8953
+ if (lnext(pubobjects, lc)) {
8954
+ appendStringInfoString(str, ", ");
8955
+ }
8956
+ }
8957
+ }
8958
+
8280
8959
  static void deparseCreatePublicationStmt(StringInfo str, CreatePublicationStmt *create_publication_stmt)
8281
8960
  {
8282
8961
  ListCell *lc = NULL;
@@ -8285,10 +8964,10 @@ static void deparseCreatePublicationStmt(StringInfo str, CreatePublicationStmt *
8285
8964
  appendStringInfoString(str, quote_identifier(create_publication_stmt->pubname));
8286
8965
  appendStringInfoChar(str, ' ');
8287
8966
 
8288
- if (list_length(create_publication_stmt->tables) > 0)
8967
+ if (list_length(create_publication_stmt->pubobjects) > 0)
8289
8968
  {
8290
- appendStringInfoString(str, "FOR TABLE ");
8291
- deparseRelationExprList(str, create_publication_stmt->tables);
8969
+ appendStringInfoString(str, "FOR ");
8970
+ deparsePublicationObjectList(str, create_publication_stmt->pubobjects);
8292
8971
  appendStringInfoChar(str, ' ');
8293
8972
  }
8294
8973
  else if (create_publication_stmt->for_all_tables)
@@ -8306,25 +8985,22 @@ static void deparseAlterPublicationStmt(StringInfo str, AlterPublicationStmt *al
8306
8985
  deparseColId(str, alter_publication_stmt->pubname);
8307
8986
  appendStringInfoChar(str, ' ');
8308
8987
 
8309
- if (list_length(alter_publication_stmt->tables) > 0)
8988
+ if (list_length(alter_publication_stmt->pubobjects) > 0)
8310
8989
  {
8311
- switch (alter_publication_stmt->tableAction)
8990
+ switch (alter_publication_stmt->action)
8312
8991
  {
8313
- case DEFELEM_SET:
8314
- appendStringInfoString(str, "SET TABLE ");
8315
- break;
8316
- case DEFELEM_ADD:
8317
- appendStringInfoString(str, "ADD TABLE ");
8992
+ case AP_SetObjects:
8993
+ appendStringInfoString(str, "SET ");
8318
8994
  break;
8319
- case DEFELEM_DROP:
8320
- appendStringInfoString(str, "DROP TABLE ");
8995
+ case AP_AddObjects:
8996
+ appendStringInfoString(str, "ADD ");
8321
8997
  break;
8322
- case DEFELEM_UNSPEC:
8323
- Assert(false);
8998
+ case AP_DropObjects:
8999
+ appendStringInfoString(str, "DROP ");
8324
9000
  break;
8325
9001
  }
8326
9002
 
8327
- deparseRelationExprList(str, alter_publication_stmt->tables);
9003
+ deparsePublicationObjectList(str, alter_publication_stmt->pubobjects);
8328
9004
  }
8329
9005
  else if (list_length(alter_publication_stmt->options) > 0)
8330
9006
  {
@@ -8581,7 +9257,7 @@ static void deparseCommentStmt(StringInfo str, CommentStmt *comment_stmt)
8581
9257
  appendStringInfoString(str, quote_identifier(strVal(linitial(l))));
8582
9258
  break;
8583
9259
  case OBJECT_LARGEOBJECT:
8584
- deparseValue(str, (Value *) comment_stmt->object, DEPARSE_NODE_CONTEXT_NONE);
9260
+ deparseValue(str, (union ValUnion *) comment_stmt->object, DEPARSE_NODE_CONTEXT_NONE);
8585
9261
  break;
8586
9262
  case OBJECT_CAST:
8587
9263
  l = castNode(List, comment_stmt->object);
@@ -8605,6 +9281,19 @@ static void deparseCommentStmt(StringInfo str, CommentStmt *comment_stmt)
8605
9281
  appendStringInfoString(str, "NULL");
8606
9282
  }
8607
9283
 
9284
+ static void deparseStatsElem(StringInfo str, StatsElem *stats_elem)
9285
+ {
9286
+ // only one of stats_elem->name or stats_elem->expr can be non-null
9287
+ if (stats_elem->name)
9288
+ appendStringInfoString(str, stats_elem->name);
9289
+ else if (stats_elem->expr)
9290
+ {
9291
+ appendStringInfoChar(str, '(');
9292
+ deparseExpr(str, stats_elem->expr);
9293
+ appendStringInfoChar(str, ')');
9294
+ }
9295
+ }
9296
+
8608
9297
  static void deparseCreateStatsStmt(StringInfo str, CreateStatsStmt *create_stats_stmt)
8609
9298
  {
8610
9299
  ListCell *lc;
@@ -8625,7 +9314,12 @@ static void deparseCreateStatsStmt(StringInfo str, CreateStatsStmt *create_stats
8625
9314
  }
8626
9315
 
8627
9316
  appendStringInfoString(str, "ON ");
8628
- deparseExprList(str, create_stats_stmt->exprs);
9317
+ foreach (lc, create_stats_stmt->exprs)
9318
+ {
9319
+ deparseStatsElem(str, lfirst(lc));
9320
+ if (lnext(create_stats_stmt->exprs, lc))
9321
+ appendStringInfoString(str, ", ");
9322
+ }
8629
9323
 
8630
9324
  appendStringInfoString(str, " FROM ");
8631
9325
  deparseFromList(str, create_stats_stmt->relations);
@@ -8737,7 +9431,7 @@ static void deparseVariableShowStmt(StringInfo str, VariableShowStmt *variable_s
8737
9431
  else if (strcmp(variable_show_stmt->name, "all") == 0)
8738
9432
  appendStringInfoString(str, "SESSION ALL");
8739
9433
  else
8740
- appendStringInfoString(str, variable_show_stmt->name);
9434
+ appendStringInfoString(str, quote_identifier(variable_show_stmt->name));
8741
9435
  }
8742
9436
 
8743
9437
  static void deparseRangeTableSample(StringInfo str, RangeTableSample *range_table_sample)
@@ -8802,6 +9496,10 @@ static void deparseAlterSubscriptionStmt(StringInfo str, AlterSubscriptionStmt *
8802
9496
  appendStringInfoString(str, "SET ");
8803
9497
  deparseDefinition(str, alter_subscription_stmt->options);
8804
9498
  break;
9499
+ case ALTER_SUBSCRIPTION_SKIP:
9500
+ appendStringInfoString(str, "SKIP ");
9501
+ deparseDefinition(str, alter_subscription_stmt->options);
9502
+ break;
8805
9503
  case ALTER_SUBSCRIPTION_CONNECTION:
8806
9504
  appendStringInfoString(str, "CONNECTION ");
8807
9505
  deparseStringLiteral(str, alter_subscription_stmt->conninfo);
@@ -8811,7 +9509,29 @@ static void deparseAlterSubscriptionStmt(StringInfo str, AlterSubscriptionStmt *
8811
9509
  appendStringInfoString(str, "REFRESH PUBLICATION ");
8812
9510
  deparseOptDefinition(str, alter_subscription_stmt->options);
8813
9511
  break;
8814
- case ALTER_SUBSCRIPTION_PUBLICATION:
9512
+ case ALTER_SUBSCRIPTION_ADD_PUBLICATION:
9513
+ appendStringInfoString(str, "ADD PUBLICATION ");
9514
+ foreach(lc, alter_subscription_stmt->publication)
9515
+ {
9516
+ deparseColLabel(str, strVal(lfirst(lc)));
9517
+ if (lnext(alter_subscription_stmt->publication, lc))
9518
+ appendStringInfoString(str, ", ");
9519
+ }
9520
+ appendStringInfoChar(str, ' ');
9521
+ deparseOptDefinition(str, alter_subscription_stmt->options);
9522
+ break;
9523
+ case ALTER_SUBSCRIPTION_DROP_PUBLICATION:
9524
+ appendStringInfoString(str, "DROP PUBLICATION ");
9525
+ foreach(lc, alter_subscription_stmt->publication)
9526
+ {
9527
+ deparseColLabel(str, strVal(lfirst(lc)));
9528
+ if (lnext(alter_subscription_stmt->publication, lc))
9529
+ appendStringInfoString(str, ", ");
9530
+ }
9531
+ appendStringInfoChar(str, ' ');
9532
+ deparseOptDefinition(str, alter_subscription_stmt->options);
9533
+ break;
9534
+ case ALTER_SUBSCRIPTION_SET_PUBLICATION:
8815
9535
  appendStringInfoString(str, "SET PUBLICATION ");
8816
9536
  foreach(lc, alter_subscription_stmt->publication)
8817
9537
  {
@@ -8826,17 +9546,13 @@ static void deparseAlterSubscriptionStmt(StringInfo str, AlterSubscriptionStmt *
8826
9546
  Assert(list_length(alter_subscription_stmt->options) == 1);
8827
9547
  DefElem *defelem = castNode(DefElem, linitial(alter_subscription_stmt->options));
8828
9548
  Assert(strcmp(defelem->defname, "enabled") == 0);
8829
- if (intVal(defelem->arg) == 1)
9549
+ if (optBooleanValue(defelem->arg))
8830
9550
  {
8831
9551
  appendStringInfoString(str, " ENABLE ");
8832
9552
  }
8833
- else if (intVal(defelem->arg) == 0)
8834
- {
8835
- appendStringInfoString(str, " DISABLE ");
8836
- }
8837
9553
  else
8838
9554
  {
8839
- Assert(false);
9555
+ appendStringInfoString(str, " DISABLE ");
8840
9556
  }
8841
9557
  break;
8842
9558
  }
@@ -8898,7 +9614,7 @@ static void deparseAlterOwnerStmt(StringInfo str, AlterOwnerStmt *alter_owner_st
8898
9614
  break;
8899
9615
  case OBJECT_LARGEOBJECT:
8900
9616
  appendStringInfoString(str, "LARGE OBJECT ");
8901
- deparseNumericOnly(str, (Value *) alter_owner_stmt->object);
9617
+ deparseNumericOnly(str, (union ValUnion *) alter_owner_stmt->object);
8902
9618
  break;
8903
9619
  case OBJECT_OPERATOR:
8904
9620
  appendStringInfoString(str, "OPERATOR ");
@@ -9061,6 +9777,8 @@ static void deparseCreateTrigStmt(StringInfo str, CreateTrigStmt *create_trig_st
9061
9777
  bool skip_events_or = true;
9062
9778
 
9063
9779
  appendStringInfoString(str, "CREATE ");
9780
+ if (create_trig_stmt->replace)
9781
+ appendStringInfoString(str, "OR REPLACE ");
9064
9782
  if (create_trig_stmt->isconstraint)
9065
9783
  appendStringInfoString(str, "CONSTRAINT ");
9066
9784
  appendStringInfoString(str, "TRIGGER ");
@@ -9224,8 +9942,6 @@ static void deparseXmlExpr(StringInfo str, XmlExpr* xml_expr)
9224
9942
  Assert(false);
9225
9943
  }
9226
9944
  deparseExpr(str, linitial(xml_expr->args));
9227
- if (strcmp(strVal(&castNode(A_Const, castNode(TypeCast, lsecond(xml_expr->args))->arg)->val), "t") == 0)
9228
- appendStringInfoString(str, " PRESERVE WHITESPACE");
9229
9945
  appendStringInfoChar(str, ')');
9230
9946
  break;
9231
9947
  case IS_XMLPI: /* XMLPI(name [, args]) */
@@ -9242,7 +9958,7 @@ static void deparseXmlExpr(StringInfo str, XmlExpr* xml_expr)
9242
9958
  appendStringInfoString(str, "xmlroot(");
9243
9959
  deparseExpr(str, linitial(xml_expr->args));
9244
9960
  appendStringInfoString(str, ", version ");
9245
- if (nodeTag(&castNode(A_Const, lsecond(xml_expr->args))->val) == T_Null)
9961
+ if (castNode(A_Const, lsecond(xml_expr->args))->isnull)
9246
9962
  appendStringInfoString(str, "NO VALUE");
9247
9963
  else
9248
9964
  deparseExpr(str, lsecond(xml_expr->args));
@@ -9372,8 +10088,8 @@ static void deparseGroupingFunc(StringInfo str, GroupingFunc *grouping_func)
9372
10088
  static void deparseClusterStmt(StringInfo str, ClusterStmt *cluster_stmt)
9373
10089
  {
9374
10090
  appendStringInfoString(str, "CLUSTER ");
9375
- if (cluster_stmt->options & CLUOPT_VERBOSE)
9376
- appendStringInfoString(str, "VERBOSE ");
10091
+
10092
+ deparseUtilityOptionList(str, cluster_stmt->params);
9377
10093
 
9378
10094
  if (cluster_stmt->relation != NULL)
9379
10095
  {
@@ -9391,42 +10107,47 @@ static void deparseClusterStmt(StringInfo str, ClusterStmt *cluster_stmt)
9391
10107
  removeTrailingSpace(str);
9392
10108
  }
9393
10109
 
9394
- static void deparseValue(StringInfo str, Value *value, DeparseNodeContext context)
10110
+ static void deparseValue(StringInfo str, union ValUnion *value, DeparseNodeContext context)
9395
10111
  {
10112
+ if (!value) {
10113
+ appendStringInfoString(str, "NULL");
10114
+ return;
10115
+ }
10116
+
9396
10117
  switch (nodeTag(value))
9397
10118
  {
9398
10119
  case T_Integer:
9399
10120
  case T_Float:
9400
10121
  deparseNumericOnly(str, value);
9401
10122
  break;
10123
+ case T_Boolean:
10124
+ appendStringInfoString(str, value->boolval.boolval ? "true" : "false");
10125
+ break;
9402
10126
  case T_String:
9403
10127
  if (context == DEPARSE_NODE_CONTEXT_IDENTIFIER) {
9404
- appendStringInfoString(str, quote_identifier(value->val.str));
10128
+ appendStringInfoString(str, quote_identifier(value->sval.sval));
9405
10129
  } else if (context == DEPARSE_NODE_CONTEXT_CONSTANT) {
9406
- deparseStringLiteral(str, value->val.str);
10130
+ deparseStringLiteral(str, value->sval.sval);
9407
10131
  } else {
9408
- appendStringInfoString(str, value->val.str);
10132
+ appendStringInfoString(str, value->sval.sval);
9409
10133
  }
9410
10134
  break;
9411
10135
  case T_BitString:
9412
- if (strlen(value->val.str) >= 1 && value->val.str[0] == 'x')
10136
+ if (strlen(value->sval.sval) >= 1 && value->sval.sval[0] == 'x')
9413
10137
  {
9414
10138
  appendStringInfoChar(str, 'x');
9415
- deparseStringLiteral(str, value->val.str + 1);
10139
+ deparseStringLiteral(str, value->sval.sval + 1);
9416
10140
  }
9417
- else if (strlen(value->val.str) >= 1 && value->val.str[0] == 'b')
10141
+ else if (strlen(value->sval.sval) >= 1 && value->sval.sval[0] == 'b')
9418
10142
  {
9419
10143
  appendStringInfoChar(str, 'b');
9420
- deparseStringLiteral(str, value->val.str + 1);
10144
+ deparseStringLiteral(str, value->sval.sval + 1);
9421
10145
  }
9422
10146
  else
9423
10147
  {
9424
10148
  Assert(false);
9425
10149
  }
9426
10150
  break;
9427
- case T_Null:
9428
- appendStringInfoString(str, "NULL");
9429
- break;
9430
10151
  default:
9431
10152
  elog(ERROR, "deparse: unrecognized value node type: %d",
9432
10153
  (int) nodeTag(value));
@@ -9451,6 +10172,9 @@ static void deparsePreparableStmt(StringInfo str, Node *node)
9451
10172
  case T_DeleteStmt:
9452
10173
  deparseDeleteStmt(str, castNode(DeleteStmt, node));
9453
10174
  break;
10175
+ case T_MergeStmt:
10176
+ deparseMergeStmt(str, castNode(MergeStmt, node));
10177
+ break;
9454
10178
  default:
9455
10179
  Assert(false);
9456
10180
  }
@@ -9510,6 +10234,9 @@ static void deparseExplainableStmt(StringInfo str, Node *node)
9510
10234
  case T_ExecuteStmt:
9511
10235
  deparseExecuteStmt(str, castNode(ExecuteStmt, node));
9512
10236
  break;
10237
+ case T_MergeStmt:
10238
+ deparseMergeStmt(str, castNode(MergeStmt, node));
10239
+ break;
9513
10240
  default:
9514
10241
  Assert(false);
9515
10242
  }
@@ -9632,6 +10359,9 @@ static void deparseStmt(StringInfo str, Node *node)
9632
10359
  case T_AlterSystemStmt:
9633
10360
  deparseAlterSystemStmt(str, castNode(AlterSystemStmt, node));
9634
10361
  break;
10362
+ case T_AlterTableMoveAllStmt:
10363
+ deparseAlterTableMoveAllStmt(str, castNode(AlterTableMoveAllStmt, node));
10364
+ break;
9635
10365
  case T_AlterTableStmt:
9636
10366
  deparseAlterTableStmt(str, castNode(AlterTableStmt, node));
9637
10367
  break;
@@ -9842,6 +10572,9 @@ static void deparseStmt(StringInfo str, Node *node)
9842
10572
  case T_LockStmt:
9843
10573
  deparseLockStmt(str, castNode(LockStmt, node));
9844
10574
  break;
10575
+ case T_MergeStmt:
10576
+ deparseMergeStmt(str, castNode(MergeStmt, node));
10577
+ break;
9845
10578
  case T_NotifyStmt:
9846
10579
  deparseNotifyStmt(str, castNode(NotifyStmt, node));
9847
10580
  break;