pg_query 2.1.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 (472) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +104 -0
  3. data/README.md +59 -31
  4. data/Rakefile +2 -2
  5. data/ext/pg_query/extconf.rb +8 -2
  6. data/ext/pg_query/include/access/amapi.h +45 -1
  7. data/ext/pg_query/include/access/attmap.h +1 -1
  8. data/ext/pg_query/include/access/attnum.h +2 -2
  9. data/ext/pg_query/include/access/clog.h +4 -2
  10. data/ext/pg_query/include/access/commit_ts.h +6 -9
  11. data/ext/pg_query/include/access/detoast.h +1 -11
  12. data/ext/pg_query/include/access/genam.h +15 -12
  13. data/ext/pg_query/include/access/gin.h +2 -2
  14. data/ext/pg_query/include/access/htup.h +1 -1
  15. data/ext/pg_query/include/access/htup_details.h +75 -87
  16. data/ext/pg_query/include/access/itup.h +7 -1
  17. data/ext/pg_query/include/access/parallel.h +2 -2
  18. data/ext/pg_query/include/access/printtup.h +1 -1
  19. data/ext/pg_query/include/access/relation.h +1 -1
  20. data/ext/pg_query/include/access/relscan.h +17 -2
  21. data/ext/pg_query/include/access/rmgr.h +30 -3
  22. data/ext/pg_query/include/access/rmgrlist.h +23 -23
  23. data/ext/pg_query/include/access/sdir.h +1 -1
  24. data/ext/pg_query/include/access/skey.h +1 -1
  25. data/ext/pg_query/include/access/stratnum.h +4 -2
  26. data/ext/pg_query/include/access/sysattr.h +1 -1
  27. data/ext/pg_query/include/access/table.h +2 -1
  28. data/ext/pg_query/include/access/tableam.h +272 -20
  29. data/ext/pg_query/include/access/toast_compression.h +73 -0
  30. data/ext/pg_query/include/access/transam.h +123 -13
  31. data/ext/pg_query/include/access/tupconvert.h +1 -1
  32. data/ext/pg_query/include/access/tupdesc.h +1 -1
  33. data/ext/pg_query/include/access/tupmacs.h +3 -3
  34. data/ext/pg_query/include/access/twophase.h +5 -1
  35. data/ext/pg_query/include/access/xact.h +79 -19
  36. data/ext/pg_query/include/access/xlog.h +60 -155
  37. data/ext/pg_query/include/access/xlog_internal.h +50 -14
  38. data/ext/pg_query/include/access/xlogdefs.h +8 -16
  39. data/ext/pg_query/include/access/xlogprefetcher.h +55 -0
  40. data/ext/pg_query/include/access/xlogreader.h +148 -32
  41. data/ext/pg_query/include/access/xlogrecord.h +18 -9
  42. data/ext/pg_query/include/access/xlogrecovery.h +157 -0
  43. data/ext/pg_query/include/c.h +101 -44
  44. data/ext/pg_query/include/catalog/catalog.h +3 -1
  45. data/ext/pg_query/include/catalog/catversion.h +2 -2
  46. data/ext/pg_query/include/catalog/dependency.h +10 -16
  47. data/ext/pg_query/include/catalog/genbki.h +83 -5
  48. data/ext/pg_query/include/catalog/index.h +18 -3
  49. data/ext/pg_query/include/catalog/indexing.h +12 -324
  50. data/ext/pg_query/include/catalog/namespace.h +4 -2
  51. data/ext/pg_query/include/catalog/objectaccess.h +70 -2
  52. data/ext/pg_query/include/catalog/objectaddress.h +11 -6
  53. data/ext/pg_query/include/catalog/pg_aggregate.h +14 -10
  54. data/ext/pg_query/include/catalog/pg_aggregate_d.h +2 -1
  55. data/ext/pg_query/include/catalog/pg_am.h +4 -1
  56. data/ext/pg_query/include/catalog/pg_am_d.h +3 -1
  57. data/ext/pg_query/include/catalog/pg_attribute.h +27 -10
  58. data/ext/pg_query/include/catalog/pg_attribute_d.h +21 -18
  59. data/ext/pg_query/include/catalog/pg_authid.h +7 -2
  60. data/ext/pg_query/include/catalog/pg_authid_d.h +17 -9
  61. data/ext/pg_query/include/catalog/pg_class.h +45 -15
  62. data/ext/pg_query/include/catalog/pg_class_d.h +31 -2
  63. data/ext/pg_query/include/catalog/pg_collation.h +33 -8
  64. data/ext/pg_query/include/catalog/pg_collation_d.h +20 -3
  65. data/ext/pg_query/include/catalog/pg_constraint.h +38 -12
  66. data/ext/pg_query/include/catalog/pg_constraint_d.h +10 -4
  67. data/ext/pg_query/include/catalog/pg_control.h +5 -5
  68. data/ext/pg_query/include/catalog/pg_conversion.h +7 -4
  69. data/ext/pg_query/include/catalog/pg_conversion_d.h +4 -1
  70. data/ext/pg_query/include/catalog/pg_depend.h +11 -7
  71. data/ext/pg_query/include/catalog/pg_depend_d.h +3 -1
  72. data/ext/pg_query/include/catalog/pg_event_trigger.h +9 -3
  73. data/ext/pg_query/include/catalog/pg_event_trigger_d.h +3 -1
  74. data/ext/pg_query/include/catalog/pg_index.h +17 -7
  75. data/ext/pg_query/include/catalog/pg_index_d.h +20 -17
  76. data/ext/pg_query/include/catalog/pg_language.h +10 -5
  77. data/ext/pg_query/include/catalog/pg_language_d.h +3 -1
  78. data/ext/pg_query/include/catalog/pg_namespace.h +7 -2
  79. data/ext/pg_query/include/catalog/pg_namespace_d.h +3 -1
  80. data/ext/pg_query/include/catalog/pg_opclass.h +8 -5
  81. data/ext/pg_query/include/catalog/pg_opclass_d.h +3 -1
  82. data/ext/pg_query/include/catalog/pg_operator.h +21 -16
  83. data/ext/pg_query/include/catalog/pg_operator_d.h +37 -1
  84. data/ext/pg_query/include/catalog/pg_opfamily.h +6 -3
  85. data/ext/pg_query/include/catalog/pg_opfamily_d.h +3 -1
  86. data/ext/pg_query/include/catalog/pg_parameter_acl.h +60 -0
  87. data/ext/pg_query/include/catalog/pg_parameter_acl_d.h +34 -0
  88. data/ext/pg_query/include/catalog/pg_partitioned_table.h +20 -9
  89. data/ext/pg_query/include/catalog/pg_partitioned_table_d.h +2 -1
  90. data/ext/pg_query/include/catalog/pg_proc.h +20 -11
  91. data/ext/pg_query/include/catalog/pg_proc_d.h +10 -8
  92. data/ext/pg_query/include/catalog/pg_publication.h +50 -4
  93. data/ext/pg_query/include/catalog/pg_publication_d.h +3 -1
  94. data/ext/pg_query/include/catalog/pg_replication_origin.h +6 -1
  95. data/ext/pg_query/include/catalog/pg_replication_origin_d.h +5 -1
  96. data/ext/pg_query/include/catalog/pg_statistic.h +19 -12
  97. data/ext/pg_query/include/catalog/pg_statistic_d.h +2 -1
  98. data/ext/pg_query/include/catalog/pg_statistic_ext.h +19 -5
  99. data/ext/pg_query/include/catalog/pg_statistic_ext_d.h +7 -2
  100. data/ext/pg_query/include/catalog/pg_transform.h +8 -5
  101. data/ext/pg_query/include/catalog/pg_transform_d.h +3 -1
  102. data/ext/pg_query/include/catalog/pg_trigger.h +24 -8
  103. data/ext/pg_query/include/catalog/pg_trigger_d.h +4 -1
  104. data/ext/pg_query/include/catalog/pg_ts_config.h +6 -3
  105. data/ext/pg_query/include/catalog/pg_ts_config_d.h +3 -1
  106. data/ext/pg_query/include/catalog/pg_ts_dict.h +8 -3
  107. data/ext/pg_query/include/catalog/pg_ts_dict_d.h +3 -1
  108. data/ext/pg_query/include/catalog/pg_ts_parser.h +6 -3
  109. data/ext/pg_query/include/catalog/pg_ts_parser_d.h +3 -1
  110. data/ext/pg_query/include/catalog/pg_ts_template.h +6 -3
  111. data/ext/pg_query/include/catalog/pg_ts_template_d.h +3 -1
  112. data/ext/pg_query/include/catalog/pg_type.h +56 -24
  113. data/ext/pg_query/include/catalog/pg_type_d.h +70 -31
  114. data/ext/pg_query/include/catalog/storage.h +5 -3
  115. data/ext/pg_query/include/commands/async.h +4 -5
  116. data/ext/pg_query/include/commands/dbcommands.h +2 -1
  117. data/ext/pg_query/include/commands/defrem.h +11 -24
  118. data/ext/pg_query/include/commands/event_trigger.h +2 -2
  119. data/ext/pg_query/include/commands/explain.h +1 -1
  120. data/ext/pg_query/include/commands/prepare.h +1 -1
  121. data/ext/pg_query/include/commands/tablespace.h +3 -1
  122. data/ext/pg_query/include/commands/trigger.h +27 -17
  123. data/ext/pg_query/include/commands/user.h +2 -2
  124. data/ext/pg_query/include/commands/vacuum.h +88 -41
  125. data/ext/pg_query/include/commands/variable.h +1 -1
  126. data/ext/pg_query/include/common/file_perm.h +4 -4
  127. data/ext/pg_query/include/common/hashfn.h +1 -1
  128. data/ext/pg_query/include/common/ip.h +1 -7
  129. data/ext/pg_query/include/common/keywords.h +2 -6
  130. data/ext/pg_query/include/common/kwlookup.h +1 -1
  131. data/ext/pg_query/include/common/pg_prng.h +60 -0
  132. data/ext/pg_query/include/common/relpath.h +2 -2
  133. data/ext/pg_query/include/common/string.h +24 -1
  134. data/ext/pg_query/include/common/unicode_combining_table.h +114 -2
  135. data/ext/pg_query/include/common/unicode_east_asian_fw_table.h +125 -0
  136. data/ext/pg_query/include/datatype/timestamp.h +40 -1
  137. data/ext/pg_query/include/executor/execdesc.h +1 -1
  138. data/ext/pg_query/include/executor/executor.h +65 -22
  139. data/ext/pg_query/include/executor/functions.h +17 -3
  140. data/ext/pg_query/include/executor/instrument.h +33 -16
  141. data/ext/pg_query/include/executor/spi.h +41 -3
  142. data/ext/pg_query/include/executor/tablefunc.h +1 -1
  143. data/ext/pg_query/include/executor/tuptable.h +1 -1
  144. data/ext/pg_query/include/fmgr.h +13 -7
  145. data/ext/pg_query/include/funcapi.h +16 -4
  146. data/ext/pg_query/include/getaddrinfo.h +1 -1
  147. data/ext/pg_query/include/jit/jit.h +11 -11
  148. data/ext/pg_query/include/kwlist_d.h +517 -494
  149. data/ext/pg_query/include/lib/dshash.h +112 -0
  150. data/ext/pg_query/include/lib/ilist.h +20 -1
  151. data/ext/pg_query/include/lib/pairingheap.h +1 -1
  152. data/ext/pg_query/include/lib/simplehash.h +150 -25
  153. data/ext/pg_query/include/lib/sort_template.h +432 -0
  154. data/ext/pg_query/include/lib/stringinfo.h +1 -1
  155. data/ext/pg_query/include/libpq/auth.h +6 -4
  156. data/ext/pg_query/include/libpq/crypt.h +5 -4
  157. data/ext/pg_query/include/libpq/hba.h +43 -4
  158. data/ext/pg_query/include/libpq/libpq-be.h +23 -6
  159. data/ext/pg_query/include/libpq/libpq.h +31 -20
  160. data/ext/pg_query/include/libpq/pqcomm.h +17 -31
  161. data/ext/pg_query/include/libpq/pqformat.h +1 -1
  162. data/ext/pg_query/include/libpq/pqsignal.h +4 -4
  163. data/ext/pg_query/include/mb/pg_wchar.h +106 -23
  164. data/ext/pg_query/include/mb/stringinfo_mb.h +1 -1
  165. data/ext/pg_query/include/miscadmin.h +71 -52
  166. data/ext/pg_query/include/nodes/bitmapset.h +1 -1
  167. data/ext/pg_query/include/nodes/execnodes.h +272 -80
  168. data/ext/pg_query/include/nodes/extensible.h +4 -2
  169. data/ext/pg_query/include/nodes/lockoptions.h +1 -1
  170. data/ext/pg_query/include/nodes/makefuncs.h +7 -6
  171. data/ext/pg_query/include/nodes/memnodes.h +5 -3
  172. data/ext/pg_query/include/nodes/nodeFuncs.h +1 -1
  173. data/ext/pg_query/include/nodes/nodes.h +30 -11
  174. data/ext/pg_query/include/nodes/params.h +1 -1
  175. data/ext/pg_query/include/nodes/parsenodes.h +327 -94
  176. data/ext/pg_query/include/nodes/pathnodes.h +245 -67
  177. data/ext/pg_query/include/nodes/pg_list.h +75 -68
  178. data/ext/pg_query/include/nodes/plannodes.h +128 -30
  179. data/ext/pg_query/include/nodes/primnodes.h +99 -47
  180. data/ext/pg_query/include/nodes/print.h +1 -1
  181. data/ext/pg_query/include/nodes/tidbitmap.h +1 -1
  182. data/ext/pg_query/include/nodes/value.h +58 -39
  183. data/ext/pg_query/include/optimizer/cost.h +9 -2
  184. data/ext/pg_query/include/optimizer/geqo.h +9 -7
  185. data/ext/pg_query/include/optimizer/geqo_gene.h +1 -1
  186. data/ext/pg_query/include/optimizer/optimizer.h +25 -22
  187. data/ext/pg_query/include/optimizer/paths.h +6 -6
  188. data/ext/pg_query/include/optimizer/planmain.h +15 -14
  189. data/ext/pg_query/include/parser/analyze.h +19 -5
  190. data/ext/pg_query/include/parser/gram.h +947 -913
  191. data/ext/pg_query/include/parser/gramparse.h +1 -1
  192. data/ext/pg_query/include/parser/kwlist.h +463 -453
  193. data/ext/pg_query/include/parser/parse_agg.h +2 -7
  194. data/ext/pg_query/include/parser/parse_coerce.h +4 -1
  195. data/ext/pg_query/include/parser/parse_expr.h +2 -3
  196. data/ext/pg_query/include/parser/parse_func.h +2 -1
  197. data/ext/pg_query/include/parser/parse_node.h +21 -9
  198. data/ext/pg_query/include/parser/parse_oper.h +1 -3
  199. data/ext/pg_query/include/parser/parse_relation.h +5 -4
  200. data/ext/pg_query/include/parser/parse_type.h +1 -1
  201. data/ext/pg_query/include/parser/parser.h +31 -4
  202. data/ext/pg_query/include/parser/parsetree.h +1 -1
  203. data/ext/pg_query/include/parser/scanner.h +1 -1
  204. data/ext/pg_query/include/parser/scansup.h +2 -5
  205. data/ext/pg_query/include/partitioning/partdefs.h +1 -1
  206. data/ext/pg_query/include/pg_config.h +94 -46
  207. data/ext/pg_query/include/pg_config_manual.h +74 -21
  208. data/ext/pg_query/include/pg_getopt.h +6 -6
  209. data/ext/pg_query/include/pg_query.h +5 -4
  210. data/ext/pg_query/include/pg_query_enum_defs.c +358 -241
  211. data/ext/pg_query/include/pg_query_fingerprint_conds.c +44 -7
  212. data/ext/pg_query/include/pg_query_fingerprint_defs.c +1220 -422
  213. data/ext/pg_query/include/pg_query_outfuncs_conds.c +43 -13
  214. data/ext/pg_query/include/pg_query_outfuncs_defs.c +152 -26
  215. data/ext/pg_query/include/pg_query_readfuncs_conds.c +11 -2
  216. data/ext/pg_query/include/pg_query_readfuncs_defs.c +174 -30
  217. data/ext/pg_query/include/pg_trace.h +1 -1
  218. data/ext/pg_query/include/pgstat.h +449 -1237
  219. data/ext/pg_query/include/pgtime.h +14 -4
  220. data/ext/pg_query/include/pl_gram.h +126 -128
  221. data/ext/pg_query/include/pl_reserved_kwlist.h +1 -1
  222. data/ext/pg_query/include/pl_reserved_kwlist_d.h +10 -10
  223. data/ext/pg_query/include/pl_unreserved_kwlist.h +2 -3
  224. data/ext/pg_query/include/pl_unreserved_kwlist_d.h +54 -56
  225. data/ext/pg_query/include/plerrcodes.h +9 -1
  226. data/ext/pg_query/include/plpgsql.h +52 -54
  227. data/ext/pg_query/include/port/atomics/arch-arm.h +7 -1
  228. data/ext/pg_query/include/port/atomics/arch-ppc.h +1 -1
  229. data/ext/pg_query/include/port/atomics/arch-x86.h +1 -1
  230. data/ext/pg_query/include/port/atomics/fallback.h +1 -1
  231. data/ext/pg_query/include/port/atomics/generic-gcc.h +3 -3
  232. data/ext/pg_query/include/port/atomics/generic.h +1 -1
  233. data/ext/pg_query/include/port/atomics.h +1 -1
  234. data/ext/pg_query/include/port/pg_bitutils.h +88 -12
  235. data/ext/pg_query/include/port/pg_bswap.h +1 -1
  236. data/ext/pg_query/include/port/pg_crc32c.h +1 -1
  237. data/ext/pg_query/include/port.h +72 -43
  238. data/ext/pg_query/include/portability/instr_time.h +1 -1
  239. data/ext/pg_query/include/postgres.h +60 -16
  240. data/ext/pg_query/include/postmaster/autovacuum.h +17 -17
  241. data/ext/pg_query/include/postmaster/auxprocess.h +20 -0
  242. data/ext/pg_query/include/postmaster/bgworker.h +2 -1
  243. data/ext/pg_query/include/postmaster/bgworker_internals.h +2 -2
  244. data/ext/pg_query/include/postmaster/bgwriter.h +5 -5
  245. data/ext/pg_query/include/postmaster/fork_process.h +1 -1
  246. data/ext/pg_query/include/postmaster/interrupt.h +1 -1
  247. data/ext/pg_query/include/postmaster/pgarch.h +42 -8
  248. data/ext/pg_query/include/postmaster/postmaster.h +18 -17
  249. data/ext/pg_query/include/postmaster/startup.h +39 -0
  250. data/ext/pg_query/include/postmaster/syslogger.h +15 -10
  251. data/ext/pg_query/include/postmaster/walwriter.h +3 -3
  252. data/ext/pg_query/include/protobuf/pg_query.pb-c.h +1422 -916
  253. data/ext/pg_query/include/protobuf/pg_query.pb.h +43678 -32769
  254. data/ext/pg_query/include/regex/regex.h +18 -16
  255. data/ext/pg_query/include/replication/logicallauncher.h +3 -5
  256. data/ext/pg_query/include/replication/logicalproto.h +161 -17
  257. data/ext/pg_query/include/replication/logicalworker.h +1 -1
  258. data/ext/pg_query/include/replication/origin.h +7 -7
  259. data/ext/pg_query/include/replication/reorderbuffer.h +262 -44
  260. data/ext/pg_query/include/replication/slot.h +23 -12
  261. data/ext/pg_query/include/replication/syncrep.h +5 -5
  262. data/ext/pg_query/include/replication/walreceiver.h +145 -13
  263. data/ext/pg_query/include/replication/walsender.h +8 -8
  264. data/ext/pg_query/include/rewrite/prs2lock.h +1 -1
  265. data/ext/pg_query/include/rewrite/rewriteHandler.h +1 -3
  266. data/ext/pg_query/include/rewrite/rewriteManip.h +1 -1
  267. data/ext/pg_query/include/rewrite/rewriteSupport.h +1 -1
  268. data/ext/pg_query/include/storage/backendid.h +3 -3
  269. data/ext/pg_query/include/storage/block.h +4 -10
  270. data/ext/pg_query/include/storage/buf.h +1 -1
  271. data/ext/pg_query/include/storage/bufmgr.h +19 -14
  272. data/ext/pg_query/include/storage/bufpage.h +6 -8
  273. data/ext/pg_query/include/storage/condition_variable.h +13 -2
  274. data/ext/pg_query/include/storage/dsm.h +4 -1
  275. data/ext/pg_query/include/storage/dsm_impl.h +3 -2
  276. data/ext/pg_query/include/storage/fd.h +33 -3
  277. data/ext/pg_query/include/storage/fileset.h +40 -0
  278. data/ext/pg_query/include/storage/ipc.h +4 -1
  279. data/ext/pg_query/include/storage/item.h +1 -1
  280. data/ext/pg_query/include/storage/itemid.h +1 -1
  281. data/ext/pg_query/include/storage/itemptr.h +3 -1
  282. data/ext/pg_query/include/storage/large_object.h +2 -2
  283. data/ext/pg_query/include/storage/latch.h +9 -13
  284. data/ext/pg_query/include/storage/lmgr.h +2 -1
  285. data/ext/pg_query/include/storage/lock.h +17 -13
  286. data/ext/pg_query/include/storage/lockdefs.h +2 -2
  287. data/ext/pg_query/include/storage/lwlock.h +6 -32
  288. data/ext/pg_query/include/storage/lwlocknames.h +0 -1
  289. data/ext/pg_query/include/storage/off.h +1 -1
  290. data/ext/pg_query/include/storage/pg_sema.h +1 -1
  291. data/ext/pg_query/include/storage/pg_shmem.h +9 -7
  292. data/ext/pg_query/include/storage/pmsignal.h +15 -4
  293. data/ext/pg_query/include/storage/predicate.h +4 -4
  294. data/ext/pg_query/include/storage/proc.h +183 -55
  295. data/ext/pg_query/include/storage/procarray.h +98 -0
  296. data/ext/pg_query/include/storage/proclist_types.h +1 -1
  297. data/ext/pg_query/include/storage/procsignal.h +3 -7
  298. data/ext/pg_query/include/storage/relfilenode.h +1 -1
  299. data/ext/pg_query/include/storage/s_lock.h +67 -4
  300. data/ext/pg_query/include/storage/sharedfileset.h +3 -11
  301. data/ext/pg_query/include/storage/shm_mq.h +5 -4
  302. data/ext/pg_query/include/storage/shm_toc.h +1 -1
  303. data/ext/pg_query/include/storage/shmem.h +1 -1
  304. data/ext/pg_query/include/storage/sinval.h +3 -3
  305. data/ext/pg_query/include/storage/sinvaladt.h +1 -1
  306. data/ext/pg_query/include/storage/smgr.h +10 -8
  307. data/ext/pg_query/include/storage/spin.h +2 -2
  308. data/ext/pg_query/include/storage/standby.h +13 -6
  309. data/ext/pg_query/include/storage/standbydefs.h +2 -2
  310. data/ext/pg_query/include/storage/sync.h +7 -3
  311. data/ext/pg_query/include/tcop/cmdtag.h +1 -1
  312. data/ext/pg_query/include/tcop/cmdtaglist.h +3 -2
  313. data/ext/pg_query/include/tcop/deparse_utility.h +1 -1
  314. data/ext/pg_query/include/tcop/dest.h +1 -1
  315. data/ext/pg_query/include/tcop/fastpath.h +1 -2
  316. data/ext/pg_query/include/tcop/pquery.h +7 -1
  317. data/ext/pg_query/include/tcop/tcopprot.h +19 -11
  318. data/ext/pg_query/include/tcop/utility.h +7 -3
  319. data/ext/pg_query/include/tsearch/ts_cache.h +2 -2
  320. data/ext/pg_query/include/utils/acl.h +24 -3
  321. data/ext/pg_query/include/utils/aclchk_internal.h +1 -1
  322. data/ext/pg_query/include/utils/array.h +7 -2
  323. data/ext/pg_query/include/utils/backend_progress.h +44 -0
  324. data/ext/pg_query/include/utils/backend_status.h +321 -0
  325. data/ext/pg_query/include/utils/builtins.h +11 -11
  326. data/ext/pg_query/include/utils/bytea.h +3 -2
  327. data/ext/pg_query/include/utils/catcache.h +1 -1
  328. data/ext/pg_query/include/utils/date.h +1 -1
  329. data/ext/pg_query/include/utils/datetime.h +8 -7
  330. data/ext/pg_query/include/utils/datum.h +9 -1
  331. data/ext/pg_query/include/utils/dsa.h +1 -1
  332. data/ext/pg_query/include/utils/dynahash.h +4 -3
  333. data/ext/pg_query/include/utils/elog.h +52 -21
  334. data/ext/pg_query/include/utils/errcodes.h +2 -0
  335. data/ext/pg_query/include/utils/expandeddatum.h +1 -1
  336. data/ext/pg_query/include/utils/expandedrecord.h +1 -1
  337. data/ext/pg_query/include/utils/float.h +7 -7
  338. data/ext/pg_query/include/utils/fmgroids.h +1300 -696
  339. data/ext/pg_query/include/utils/fmgrprotos.h +199 -16
  340. data/ext/pg_query/include/utils/fmgrtab.h +6 -5
  341. data/ext/pg_query/include/utils/guc.h +69 -43
  342. data/ext/pg_query/include/utils/guc_tables.h +23 -19
  343. data/ext/pg_query/include/utils/hsearch.h +15 -11
  344. data/ext/pg_query/include/utils/inval.h +5 -1
  345. data/ext/pg_query/include/utils/lsyscache.h +11 -1
  346. data/ext/pg_query/include/utils/memdebug.h +1 -1
  347. data/ext/pg_query/include/utils/memutils.h +8 -3
  348. data/ext/pg_query/include/utils/numeric.h +19 -5
  349. data/ext/pg_query/include/utils/palloc.h +25 -3
  350. data/ext/pg_query/include/utils/partcache.h +1 -1
  351. data/ext/pg_query/include/utils/pg_locale.h +17 -9
  352. data/ext/pg_query/include/utils/pg_lsn.h +1 -1
  353. data/ext/pg_query/include/utils/pgstat_internal.h +784 -0
  354. data/ext/pg_query/include/utils/pidfile.h +1 -1
  355. data/ext/pg_query/include/utils/plancache.h +6 -5
  356. data/ext/pg_query/include/utils/portal.h +12 -1
  357. data/ext/pg_query/include/utils/ps_status.h +1 -1
  358. data/ext/pg_query/include/utils/queryenvironment.h +1 -1
  359. data/ext/pg_query/include/utils/queryjumble.h +88 -0
  360. data/ext/pg_query/include/utils/regproc.h +14 -3
  361. data/ext/pg_query/include/utils/rel.h +71 -20
  362. data/ext/pg_query/include/utils/relcache.h +9 -7
  363. data/ext/pg_query/include/utils/reltrigger.h +1 -1
  364. data/ext/pg_query/include/utils/resowner.h +1 -1
  365. data/ext/pg_query/include/utils/rls.h +2 -2
  366. data/ext/pg_query/include/utils/ruleutils.h +4 -1
  367. data/ext/pg_query/include/utils/sharedtuplestore.h +1 -1
  368. data/ext/pg_query/include/utils/snapmgr.h +35 -14
  369. data/ext/pg_query/include/utils/snapshot.h +14 -1
  370. data/ext/pg_query/include/utils/sortsupport.h +117 -2
  371. data/ext/pg_query/include/utils/syscache.h +6 -1
  372. data/ext/pg_query/include/utils/timeout.h +11 -4
  373. data/ext/pg_query/include/utils/timestamp.h +6 -5
  374. data/ext/pg_query/include/utils/tuplesort.h +25 -11
  375. data/ext/pg_query/include/utils/tuplestore.h +2 -2
  376. data/ext/pg_query/include/utils/typcache.h +24 -17
  377. data/ext/pg_query/include/utils/tzparser.h +1 -1
  378. data/ext/pg_query/include/utils/varlena.h +5 -3
  379. data/ext/pg_query/include/utils/wait_event.h +289 -0
  380. data/ext/pg_query/include/utils/xml.h +4 -4
  381. data/ext/pg_query/pg_query.pb-c.c +4318 -2307
  382. data/ext/pg_query/pg_query_deparse.c +1114 -381
  383. data/ext/pg_query/pg_query_fingerprint.c +46 -10
  384. data/ext/pg_query/pg_query_fingerprint.h +3 -1
  385. data/ext/pg_query/pg_query_json_plpgsql.c +55 -12
  386. data/ext/pg_query/pg_query_normalize.c +163 -20
  387. data/ext/pg_query/pg_query_outfuncs.h +1 -0
  388. data/ext/pg_query/pg_query_outfuncs_json.c +65 -16
  389. data/ext/pg_query/pg_query_outfuncs_protobuf.c +70 -10
  390. data/ext/pg_query/pg_query_parse.c +1 -1
  391. data/ext/pg_query/pg_query_parse_plpgsql.c +79 -16
  392. data/ext/pg_query/pg_query_readfuncs_protobuf.c +42 -8
  393. data/ext/pg_query/pg_query_ruby.c +1 -1
  394. data/ext/pg_query/pg_query_scan.c +2 -1
  395. data/ext/pg_query/pg_query_split.c +3 -2
  396. data/ext/pg_query/src_backend_catalog_namespace.c +21 -9
  397. data/ext/pg_query/src_backend_catalog_pg_proc.c +4 -1
  398. data/ext/pg_query/src_backend_commands_define.c +11 -1
  399. data/ext/pg_query/src_backend_nodes_bitmapset.c +3 -1
  400. data/ext/pg_query/src_backend_nodes_copyfuncs.c +424 -109
  401. data/ext/pg_query/src_backend_nodes_equalfuncs.c +291 -46
  402. data/ext/pg_query/src_backend_nodes_extensible.c +1 -1
  403. data/ext/pg_query/src_backend_nodes_list.c +86 -11
  404. data/ext/pg_query/src_backend_nodes_makefuncs.c +5 -4
  405. data/ext/pg_query/src_backend_nodes_nodeFuncs.c +55 -12
  406. data/ext/pg_query/src_backend_nodes_value.c +28 -19
  407. data/ext/pg_query/src_backend_parser_gram.c +33890 -31262
  408. data/ext/pg_query/src_backend_parser_parser.c +26 -7
  409. data/ext/pg_query/src_backend_parser_scan.c +644 -441
  410. data/ext/pg_query/src_backend_parser_scansup.c +4 -28
  411. data/ext/pg_query/src_backend_postmaster_postmaster.c +77 -106
  412. data/ext/pg_query/src_backend_storage_ipc_ipc.c +13 -4
  413. data/ext/pg_query/src_backend_storage_lmgr_s_lock.c +5 -4
  414. data/ext/pg_query/src_backend_tcop_postgres.c +73 -24
  415. data/ext/pg_query/src_backend_utils_activity_pgstat_database.c +140 -0
  416. data/ext/pg_query/src_backend_utils_adt_datum.c +13 -1
  417. data/ext/pg_query/src_backend_utils_adt_expandeddatum.c +1 -1
  418. data/ext/pg_query/src_backend_utils_adt_format_type.c +6 -2
  419. data/ext/pg_query/src_backend_utils_adt_ruleutils.c +109 -15
  420. data/ext/pg_query/src_backend_utils_error_assert.c +16 -14
  421. data/ext/pg_query/src_backend_utils_error_elog.c +172 -99
  422. data/ext/pg_query/src_backend_utils_fmgr_fmgr.c +12 -17
  423. data/ext/pg_query/src_backend_utils_hash_dynahash.c +40 -10
  424. data/ext/pg_query/src_backend_utils_init_globals.c +5 -5
  425. data/ext/pg_query/src_backend_utils_mb_mbutils.c +55 -66
  426. data/ext/pg_query/src_backend_utils_misc_guc.c +207 -45
  427. data/ext/pg_query/src_backend_utils_mmgr_aset.c +7 -5
  428. data/ext/pg_query/src_backend_utils_mmgr_mcxt.c +123 -35
  429. data/ext/pg_query/src_common_encnames.c +1 -1
  430. data/ext/pg_query/src_common_hashfn.c +3 -3
  431. data/ext/pg_query/src_common_keywords.c +15 -2
  432. data/ext/pg_query/src_common_kwlist_d.h +517 -494
  433. data/ext/pg_query/src_common_kwlookup.c +1 -1
  434. data/ext/pg_query/src_common_pg_prng.c +152 -0
  435. data/ext/pg_query/src_common_psprintf.c +1 -1
  436. data/ext/pg_query/src_common_string.c +7 -1
  437. data/ext/pg_query/src_common_stringinfo.c +1 -1
  438. data/ext/pg_query/src_common_wchar.c +712 -109
  439. data/ext/pg_query/src_pl_plpgsql_src_pl_comp.c +49 -22
  440. data/ext/pg_query/src_pl_plpgsql_src_pl_funcs.c +1 -18
  441. data/ext/pg_query/src_pl_plpgsql_src_pl_gram.c +1235 -1261
  442. data/ext/pg_query/src_pl_plpgsql_src_pl_handler.c +1 -1
  443. data/ext/pg_query/src_pl_plpgsql_src_pl_reserved_kwlist_d.h +10 -10
  444. data/ext/pg_query/src_pl_plpgsql_src_pl_scanner.c +2 -2
  445. data/ext/pg_query/src_pl_plpgsql_src_pl_unreserved_kwlist_d.h +54 -56
  446. data/ext/pg_query/src_port_pg_bitutils.c +41 -52
  447. data/ext/pg_query/src_port_pgsleep.c +1 -1
  448. data/ext/pg_query/src_port_pgstrcasecmp.c +1 -1
  449. data/ext/pg_query/src_port_qsort.c +12 -224
  450. data/ext/pg_query/src_port_snprintf.c +46 -20
  451. data/ext/pg_query/src_port_strerror.c +9 -19
  452. data/ext/pg_query/src_port_strnlen.c +1 -1
  453. data/lib/pg_query/deparse.rb +7 -1
  454. data/lib/pg_query/filter_columns.rb +6 -4
  455. data/lib/pg_query/fingerprint.rb +18 -3
  456. data/lib/pg_query/node.rb +2 -2
  457. data/lib/pg_query/param_refs.rb +1 -1
  458. data/lib/pg_query/parse.rb +87 -51
  459. data/lib/pg_query/pg_query_pb.rb +1109 -942
  460. data/lib/pg_query/treewalker.rb +6 -0
  461. data/lib/pg_query/truncate.rb +54 -8
  462. data/lib/pg_query/version.rb +1 -1
  463. metadata +29 -18
  464. data/ext/pg_query/include/access/xloginsert.h +0 -64
  465. data/ext/pg_query/include/bootstrap/bootstrap.h +0 -62
  466. data/ext/pg_query/include/parser/parse_clause.h +0 -54
  467. data/ext/pg_query/include/parser/parse_collate.h +0 -27
  468. data/ext/pg_query/include/parser/parse_target.h +0 -46
  469. data/ext/pg_query/src_backend_libpq_pqcomm.c +0 -651
  470. data/ext/pg_query/src_backend_parser_parse_expr.c +0 -313
  471. data/ext/pg_query/src_port_erand48.c +0 -127
  472. 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));
@@ -321,8 +324,7 @@ static void deparseExpr(StringInfo str, Node *node)
321
324
  deparseGroupingFunc(str, castNode(GroupingFunc, node));
322
325
  break;
323
326
  default:
324
- Assert(false);
325
- elog(ERROR, "unpermitted node type in a_expr/b_expr: %d",
327
+ elog(ERROR, "deparse: unpermitted node type in a_expr/b_expr: %d",
326
328
  (int) nodeTag(node));
327
329
  break;
328
330
  }
@@ -340,7 +342,7 @@ static void deparseCExpr(StringInfo str, Node *node)
340
342
  deparseAConst(str, castNode(A_Const, node));
341
343
  break;
342
344
  case T_TypeCast:
343
- deparseTypeCast(str, castNode(TypeCast, node));
345
+ deparseTypeCast(str, castNode(TypeCast, node), DEPARSE_NODE_CONTEXT_NONE);
344
346
  break;
345
347
  case T_A_Expr:
346
348
  appendStringInfoChar(str, '(');
@@ -372,8 +374,7 @@ static void deparseCExpr(StringInfo str, Node *node)
372
374
  deparseGroupingFunc(str, castNode(GroupingFunc, node));
373
375
  break;
374
376
  default:
375
- Assert(false);
376
- elog(ERROR, "unpermitted node type in c_expr: %d",
377
+ elog(ERROR, "deparse: unpermitted node type in c_expr: %d",
377
378
  (int) nodeTag(node));
378
379
  break;
379
380
  }
@@ -383,7 +384,6 @@ static void deparseCExpr(StringInfo str, Node *node)
383
384
  static void deparseExprList(StringInfo str, List *exprs)
384
385
  {
385
386
  ListCell *lc;
386
-
387
387
  foreach(lc, exprs)
388
388
  {
389
389
  deparseExpr(str, lfirst(lc));
@@ -462,15 +462,15 @@ static void deparseSimpleTypename(StringInfo str, Node *node)
462
462
  }
463
463
 
464
464
  // "NumericOnly" in gram.y
465
- static void deparseNumericOnly(StringInfo str, Value *value)
465
+ static void deparseNumericOnly(StringInfo str, union ValUnion *value)
466
466
  {
467
467
  switch (nodeTag(value))
468
468
  {
469
469
  case T_Integer:
470
- appendStringInfo(str, "%d", value->val.ival);
470
+ appendStringInfo(str, "%d", value->ival.ival);
471
471
  break;
472
472
  case T_Float:
473
- appendStringInfoString(str, value->val.str);
473
+ appendStringInfoString(str, value->sval.sval);
474
474
  break;
475
475
  default:
476
476
  Assert(false);
@@ -484,7 +484,7 @@ static void deparseNumericOnlyList(StringInfo str, List *l)
484
484
 
485
485
  foreach(lc, l)
486
486
  {
487
- deparseNumericOnly(str, (Value *) lfirst(lc));
487
+ deparseNumericOnly(str, (union ValUnion *) lfirst(lc));
488
488
  if (lnext(l, lc))
489
489
  appendStringInfoString(str, ", ");
490
490
  }
@@ -503,25 +503,25 @@ static void deparseSeqOptElem(StringInfo str, DefElem *def_elem)
503
503
  else if (strcmp(def_elem->defname, "cache") == 0)
504
504
  {
505
505
  appendStringInfoString(str, "CACHE ");
506
- deparseNumericOnly(str, (Value *) def_elem->arg);
506
+ deparseNumericOnly(str, (union ValUnion *) def_elem->arg);
507
507
  }
508
- 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))
509
509
  {
510
510
  appendStringInfoString(str, "CYCLE");
511
511
  }
512
- 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))
513
513
  {
514
514
  appendStringInfoString(str, "NO CYCLE");
515
515
  }
516
516
  else if (strcmp(def_elem->defname, "increment") == 0)
517
517
  {
518
518
  appendStringInfoString(str, "INCREMENT ");
519
- deparseNumericOnly(str, (Value *) def_elem->arg);
519
+ deparseNumericOnly(str, (union ValUnion *) def_elem->arg);
520
520
  }
521
521
  else if (strcmp(def_elem->defname, "maxvalue") == 0 && def_elem->arg != NULL)
522
522
  {
523
523
  appendStringInfoString(str, "MAXVALUE ");
524
- deparseNumericOnly(str, (Value *) def_elem->arg);
524
+ deparseNumericOnly(str, (union ValUnion *) def_elem->arg);
525
525
  }
526
526
  else if (strcmp(def_elem->defname, "maxvalue") == 0 && def_elem->arg == NULL)
527
527
  {
@@ -530,7 +530,7 @@ static void deparseSeqOptElem(StringInfo str, DefElem *def_elem)
530
530
  else if (strcmp(def_elem->defname, "minvalue") == 0 && def_elem->arg != NULL)
531
531
  {
532
532
  appendStringInfoString(str, "MINVALUE ");
533
- deparseNumericOnly(str, (Value *) def_elem->arg);
533
+ deparseNumericOnly(str, (union ValUnion *) def_elem->arg);
534
534
  }
535
535
  else if (strcmp(def_elem->defname, "minvalue") == 0 && def_elem->arg == NULL)
536
536
  {
@@ -549,7 +549,7 @@ static void deparseSeqOptElem(StringInfo str, DefElem *def_elem)
549
549
  else if (strcmp(def_elem->defname, "start") == 0)
550
550
  {
551
551
  appendStringInfoString(str, "START ");
552
- deparseNumericOnly(str, (Value *) def_elem->arg);
552
+ deparseNumericOnly(str, (union ValUnion *) def_elem->arg);
553
553
  }
554
554
  else if (strcmp(def_elem->defname, "restart") == 0 && def_elem->arg == NULL)
555
555
  {
@@ -558,7 +558,7 @@ static void deparseSeqOptElem(StringInfo str, DefElem *def_elem)
558
558
  else if (strcmp(def_elem->defname, "restart") == 0 && def_elem->arg != NULL)
559
559
  {
560
560
  appendStringInfoString(str, "RESTART ");
561
- deparseNumericOnly(str, (Value *) def_elem->arg);
561
+ deparseNumericOnly(str, (union ValUnion *) def_elem->arg);
562
562
  }
563
563
  else
564
564
  {
@@ -713,7 +713,7 @@ static void deparseDefArg(StringInfo str, Node *arg, bool is_operator_def_arg)
713
713
  }
714
714
  else if (IsA(arg, Float) || IsA(arg, Integer)) // NumericOnly
715
715
  {
716
- deparseValue(str, (Value *) arg, DEPARSE_NODE_CONTEXT_NONE);
716
+ deparseValue(str, (union ValUnion *) arg, DEPARSE_NODE_CONTEXT_NONE);
717
717
  }
718
718
  else if (IsA(arg, String))
719
719
  {
@@ -794,11 +794,11 @@ static void deparseCreateGenericOptions(StringInfo str, List *options)
794
794
  // "common_func_opt_item" in gram.y
795
795
  static void deparseCommonFuncOptItem(StringInfo str, DefElem *def_elem)
796
796
  {
797
- if (strcmp(def_elem->defname, "strict") == 0 && intVal(def_elem->arg) == 1)
797
+ if (strcmp(def_elem->defname, "strict") == 0 && boolVal(def_elem->arg))
798
798
  {
799
799
  appendStringInfoString(str, "RETURNS NULL ON NULL INPUT");
800
800
  }
801
- 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))
802
802
  {
803
803
  appendStringInfoString(str, "CALLED ON NULL INPUT");
804
804
  }
@@ -814,31 +814,31 @@ static void deparseCommonFuncOptItem(StringInfo str, DefElem *def_elem)
814
814
  {
815
815
  appendStringInfoString(str, "VOLATILE");
816
816
  }
817
- 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))
818
818
  {
819
819
  appendStringInfoString(str, "SECURITY DEFINER");
820
820
  }
821
- 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))
822
822
  {
823
823
  appendStringInfoString(str, "SECURITY INVOKER");
824
824
  }
825
- 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))
826
826
  {
827
827
  appendStringInfoString(str, "LEAKPROOF");
828
828
  }
829
- 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))
830
830
  {
831
831
  appendStringInfoString(str, "NOT LEAKPROOF");
832
832
  }
833
833
  else if (strcmp(def_elem->defname, "cost") == 0)
834
834
  {
835
835
  appendStringInfoString(str, "COST ");
836
- deparseValue(str, (Value *) def_elem->arg, DEPARSE_NODE_CONTEXT_NONE);
836
+ deparseValue(str, (union ValUnion *) def_elem->arg, DEPARSE_NODE_CONTEXT_NONE);
837
837
  }
838
838
  else if (strcmp(def_elem->defname, "rows") == 0)
839
839
  {
840
840
  appendStringInfoString(str, "ROWS ");
841
- deparseValue(str, (Value *) def_elem->arg, DEPARSE_NODE_CONTEXT_NONE);
841
+ deparseValue(str, (union ValUnion *) def_elem->arg, DEPARSE_NODE_CONTEXT_NONE);
842
842
  }
843
843
  else if (strcmp(def_elem->defname, "support") == 0)
844
844
  {
@@ -995,19 +995,22 @@ static void deparseFuncName(StringInfo str, List *func_name)
995
995
  static void deparseFunctionWithArgtypes(StringInfo str, ObjectWithArgs *object_with_args)
996
996
  {
997
997
  ListCell *lc;
998
-
999
998
  deparseFuncName(str, object_with_args->objname);
1000
999
 
1001
1000
  if (!object_with_args->args_unspecified)
1002
1001
  {
1003
1002
  appendStringInfoChar(str, '(');
1004
- 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)
1005
1008
  {
1006
- if (IsA(lfirst(lc), TypeName))
1007
- deparseTypeName(str, castNode(TypeName, lfirst(lc)));
1008
- else
1009
+ if (IsA(lfirst(lc), FunctionParameter))
1009
1010
  deparseFunctionParameter(str, castNode(FunctionParameter, lfirst(lc)));
1010
- if (lnext(object_with_args->objargs, lc))
1011
+ else
1012
+ deparseTypeName(str, castNode(TypeName, lfirst(lc)));
1013
+ if (lnext(objargs, lc))
1011
1014
  appendStringInfoString(str, ", ");
1012
1015
  }
1013
1016
  appendStringInfoChar(str, ')');
@@ -1097,16 +1100,23 @@ static void deparseAggregateWithArgtypes(StringInfo str, ObjectWithArgs *object_
1097
1100
  deparseFuncName(str, object_with_args->objname);
1098
1101
 
1099
1102
  appendStringInfoChar(str, '(');
1100
- if (object_with_args->objargs == NULL)
1103
+ if (object_with_args->objargs == NULL && object_with_args->objfuncargs == NULL)
1101
1104
  {
1102
1105
  appendStringInfoChar(str, '*');
1103
1106
  }
1104
1107
  else
1105
1108
  {
1106
- 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)
1107
1114
  {
1108
- deparseTypeName(str, castNode(TypeName, lfirst(lc)));
1109
- 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))
1110
1120
  appendStringInfoString(str, ", ");
1111
1121
  }
1112
1122
  }
@@ -1237,6 +1247,64 @@ static void deparseOptBooleanOrString(StringInfo str, char *s)
1237
1247
  deparseNonReservedWordOrSconst(str, s);
1238
1248
  }
1239
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
+
1240
1308
  // "var_name"
1241
1309
  //
1242
1310
  // Note this is kept separate from ColId in case we want to improve the
@@ -1261,12 +1329,16 @@ static void deparseVarList(StringInfo str, List *l)
1261
1329
  {
1262
1330
  A_Const *a_const = castNode(A_Const, lfirst(lc));
1263
1331
  if (IsA(&a_const->val, Integer) || IsA(&a_const->val, Float))
1264
- deparseNumericOnly(str, (Value *) &a_const->val);
1332
+ deparseNumericOnly(str, (union ValUnion *) &a_const->val);
1265
1333
  else if (IsA(&a_const->val, String))
1266
1334
  deparseOptBooleanOrString(str, strVal(&a_const->val));
1267
1335
  else
1268
1336
  Assert(false);
1269
1337
  }
1338
+ else if (IsA(lfirst(lc), TypeCast))
1339
+ {
1340
+ deparseTypeCast(str, castNode(TypeCast, lfirst(lc)), DEPARSE_NODE_CONTEXT_SET_STATEMENT);
1341
+ }
1270
1342
  else
1271
1343
  {
1272
1344
  Assert(false);
@@ -1342,7 +1414,7 @@ static void deparseAlterIdentityColumnOptionList(StringInfo str, List *l)
1342
1414
  else if (strcmp(def_elem->defname, "restart") == 0 && def_elem->arg != NULL)
1343
1415
  {
1344
1416
  appendStringInfoString(str, "RESTART ");
1345
- deparseNumericOnly(str, (Value *) def_elem->arg);
1417
+ deparseNumericOnly(str, (union ValUnion *) def_elem->arg);
1346
1418
  }
1347
1419
  else if (strcmp(def_elem->defname, "generated") == 0)
1348
1420
  {
@@ -1416,7 +1488,7 @@ static void deparseTargetList(StringInfo str, List *l)
1416
1488
  ResTarget *res_target = castNode(ResTarget, lfirst(lc));
1417
1489
 
1418
1490
  if (res_target->val == NULL)
1419
- elog(ERROR, "deparse error in deparseTargetList: ResTarget without val");
1491
+ elog(ERROR, "deparse: error in deparseTargetList: ResTarget without val");
1420
1492
  else if (IsA(res_target->val, ColumnRef))
1421
1493
  deparseColumnRef(str, castNode(ColumnRef, res_target->val));
1422
1494
  else
@@ -1712,7 +1784,7 @@ static void deparseFuncExprWindowless(StringInfo str, Node* node)
1712
1784
  deparseSQLValueFunction(str, castNode(SQLValueFunction, node));
1713
1785
  break;
1714
1786
  case T_TypeCast:
1715
- deparseTypeCast(str, castNode(TypeCast, node));
1787
+ deparseTypeCast(str, castNode(TypeCast, node), DEPARSE_NODE_CONTEXT_NONE);
1716
1788
  break;
1717
1789
  case T_CoalesceExpr:
1718
1790
  deparseCoalesceExpr(str, castNode(CoalesceExpr, node));
@@ -2012,6 +2084,38 @@ static void deparseCreatedbOptList(StringInfo str, List *l)
2012
2084
  }
2013
2085
  }
2014
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
+
2015
2119
  static void deparseSelectStmt(StringInfo str, SelectStmt *stmt)
2016
2120
  {
2017
2121
  const ListCell *lc = NULL;
@@ -2076,6 +2180,8 @@ static void deparseSelectStmt(StringInfo str, SelectStmt *stmt)
2076
2180
  if (list_length(stmt->groupClause) > 0)
2077
2181
  {
2078
2182
  appendStringInfoString(str, "GROUP BY ");
2183
+ if (stmt->groupDistinct)
2184
+ appendStringInfoString(str, "DISTINCT ");
2079
2185
  deparseGroupByList(str, stmt->groupClause);
2080
2186
  appendStringInfoChar(str, ' ');
2081
2187
  }
@@ -2161,7 +2267,7 @@ static void deparseSelectStmt(StringInfo str, SelectStmt *stmt)
2161
2267
  else if (stmt->limitOption == LIMIT_OPTION_WITH_TIES)
2162
2268
  appendStringInfoString(str, "FETCH FIRST ");
2163
2269
 
2164
- 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)
2165
2271
  appendStringInfoString(str, "ALL");
2166
2272
  else
2167
2273
  deparseCExpr(str, stmt->limitCount);
@@ -2276,6 +2382,9 @@ static void deparseRangeVar(StringInfo str, RangeVar *range_var, DeparseNodeCont
2276
2382
 
2277
2383
  static void deparseRawStmt(StringInfo str, RawStmt *raw_stmt)
2278
2384
  {
2385
+ if (raw_stmt->stmt == NULL)
2386
+ elog(ERROR, "deparse error in deparseRawStmt: RawStmt with empty Stmt");
2387
+
2279
2388
  deparseStmt(str, raw_stmt->stmt);
2280
2389
  }
2281
2390
 
@@ -2294,7 +2403,8 @@ static void deparseAlias(StringInfo str, Alias *alias)
2294
2403
 
2295
2404
  static void deparseAConst(StringInfo str, A_Const *a_const)
2296
2405
  {
2297
- 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);
2298
2408
  }
2299
2409
 
2300
2410
  static void deparseFuncCall(StringInfo str, FuncCall *func_call)
@@ -2322,8 +2432,217 @@ static void deparseFuncCall(StringInfo str, FuncCall *func_call)
2322
2432
  deparseExpr(str, lfourth(func_call->args));
2323
2433
  appendStringInfoChar(str, ')');
2324
2434
  return;
2325
- }
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, ") ");
2326
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);
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
+
2327
2646
  deparseFuncName(str, func_call->funcname);
2328
2647
  appendStringInfoChar(str, '(');
2329
2648
 
@@ -2647,31 +2966,13 @@ static void deparseAExpr(StringInfo str, A_Expr* a_expr, DeparseNodeContext cont
2647
2966
  deparseExpr(str, a_expr->rexpr);
2648
2967
  appendStringInfoChar(str, ')');
2649
2968
  return;
2650
- case AEXPR_OF: /* IS [NOT] OF - name must be "=" or "<>" */
2651
- Assert(list_length(a_expr->name) == 1);
2652
- Assert(IsA(linitial(a_expr->name), String));
2653
- Assert(IsA(a_expr->rexpr, List));
2654
- deparseExpr(str, a_expr->lexpr);
2655
- appendStringInfoChar(str, ' ');
2656
- name = ((Value *) linitial(a_expr->name))->val.str;
2657
- if (strcmp(name, "=") == 0) {
2658
- appendStringInfoString(str, "IS OF ");
2659
- } else if (strcmp(name, "<>") == 0) {
2660
- appendStringInfoString(str, "IS NOT OF ");
2661
- } else {
2662
- Assert(false);
2663
- }
2664
- appendStringInfoChar(str, '(');
2665
- deparseTypeList(str, castNode(List, a_expr->rexpr));
2666
- appendStringInfoChar(str, ')');
2667
- return;
2668
2969
  case AEXPR_IN: /* [NOT] IN - name must be "=" or "<>" */
2669
2970
  Assert(list_length(a_expr->name) == 1);
2670
2971
  Assert(IsA(linitial(a_expr->name), String));
2671
2972
  Assert(IsA(a_expr->rexpr, List));
2672
2973
  deparseExpr(str, a_expr->lexpr);
2673
2974
  appendStringInfoChar(str, ' ');
2674
- name = ((Value *) linitial(a_expr->name))->val.str;
2975
+ name = ((union ValUnion *) linitial(a_expr->name))->sval.sval;
2675
2976
  if (strcmp(name, "=") == 0) {
2676
2977
  appendStringInfoString(str, "IN ");
2677
2978
  } else if (strcmp(name, "<>") == 0) {
@@ -2692,7 +2993,7 @@ static void deparseAExpr(StringInfo str, A_Expr* a_expr, DeparseNodeContext cont
2692
2993
  deparseExpr(str, a_expr->lexpr);
2693
2994
  appendStringInfoChar(str, ' ');
2694
2995
 
2695
- name = ((Value *) linitial(a_expr->name))->val.str;
2996
+ name = ((union ValUnion *) linitial(a_expr->name))->sval.sval;
2696
2997
  if (strcmp(name, "~~") == 0) {
2697
2998
  appendStringInfoString(str, "LIKE ");
2698
2999
  } else if (strcmp(name, "!~~") == 0) {
@@ -2709,7 +3010,7 @@ static void deparseAExpr(StringInfo str, A_Expr* a_expr, DeparseNodeContext cont
2709
3010
  deparseExpr(str, a_expr->lexpr);
2710
3011
  appendStringInfoChar(str, ' ');
2711
3012
 
2712
- name = ((Value *) linitial(a_expr->name))->val.str;
3013
+ name = ((union ValUnion *) linitial(a_expr->name))->sval.sval;
2713
3014
  if (strcmp(name, "~~*") == 0) {
2714
3015
  appendStringInfoString(str, "ILIKE ");
2715
3016
  } else if (strcmp(name, "!~~*") == 0) {
@@ -2726,7 +3027,7 @@ static void deparseAExpr(StringInfo str, A_Expr* a_expr, DeparseNodeContext cont
2726
3027
  deparseExpr(str, a_expr->lexpr);
2727
3028
  appendStringInfoChar(str, ' ');
2728
3029
 
2729
- name = ((Value *) linitial(a_expr->name))->val.str;
3030
+ name = ((union ValUnion *) linitial(a_expr->name))->sval.sval;
2730
3031
  if (strcmp(name, "~") == 0) {
2731
3032
  appendStringInfoString(str, "SIMILAR TO ");
2732
3033
  } else if (strcmp(name, "!~") == 0) {
@@ -2768,10 +3069,6 @@ static void deparseAExpr(StringInfo str, A_Expr* a_expr, DeparseNodeContext cont
2768
3069
  appendStringInfoString(str, " AND ");
2769
3070
  }
2770
3071
  return;
2771
- case AEXPR_PAREN: /* nameless dummy node for parentheses */
2772
- // Not present in parse trees when operator_precedence_warning is turned off
2773
- Assert(false);
2774
- return;
2775
3072
  }
2776
3073
  }
2777
3074
 
@@ -3031,6 +3328,12 @@ static void deparseJoinExpr(StringInfo str, JoinExpr *join_expr)
3031
3328
  appendStringInfoString(str, "USING (");
3032
3329
  deparseNameList(str, join_expr->usingClause);
3033
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
+ }
3034
3337
  }
3035
3338
 
3036
3339
  if (need_alias_parens)
@@ -3042,6 +3345,49 @@ static void deparseJoinExpr(StringInfo str, JoinExpr *join_expr)
3042
3345
  removeTrailingSpace(str);
3043
3346
  }
3044
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
+
3045
3391
  static void deparseCommonTableExpr(StringInfo str, CommonTableExpr *cte)
3046
3392
  {
3047
3393
  deparseColId(str, cte->ctename);
@@ -3069,6 +3415,11 @@ static void deparseCommonTableExpr(StringInfo str, CommonTableExpr *cte)
3069
3415
  appendStringInfoChar(str, '(');
3070
3416
  deparsePreparableStmt(str, cte->ctequery);
3071
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);
3072
3423
  }
3073
3424
 
3074
3425
  static void deparseRangeSubselect(StringInfo str, RangeSubselect *range_subselect)
@@ -3173,6 +3524,7 @@ static void deparseRowExpr(StringInfo str, RowExpr *row_expr)
3173
3524
  case COERCE_EXPLICIT_CALL:
3174
3525
  appendStringInfoString(str, "ROW");
3175
3526
  break;
3527
+ case COERCE_SQL_SYNTAX:
3176
3528
  case COERCE_EXPLICIT_CAST:
3177
3529
  // Not present in raw parser output
3178
3530
  Assert(false);
@@ -3187,7 +3539,7 @@ static void deparseRowExpr(StringInfo str, RowExpr *row_expr)
3187
3539
  appendStringInfoChar(str, ')');
3188
3540
  }
3189
3541
 
3190
- static void deparseTypeCast(StringInfo str, TypeCast *type_cast)
3542
+ static void deparseTypeCast(StringInfo str, TypeCast *type_cast, DeparseNodeContext context)
3191
3543
  {
3192
3544
  bool need_parens = false;
3193
3545
 
@@ -3235,6 +3587,13 @@ static void deparseTypeCast(StringInfo str, TypeCast *type_cast)
3235
3587
  return;
3236
3588
  }
3237
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
+ }
3238
3597
  }
3239
3598
 
3240
3599
  // Ensure negative values have wrapping parentheses
@@ -3242,8 +3601,18 @@ static void deparseTypeCast(StringInfo str, TypeCast *type_cast)
3242
3601
  {
3243
3602
  need_parens = true;
3244
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
+ }
3245
3613
  }
3246
3614
 
3615
+
3247
3616
  if (need_parens)
3248
3617
  appendStringInfoChar(str, '(');
3249
3618
  deparseExpr(str, type_cast->arg);
@@ -3349,70 +3718,9 @@ static void deparseTypeName(StringInfo str, TypeName *type_name)
3349
3718
  }
3350
3719
  else if (strcmp(name, "interval") == 0 && list_length(type_name->typmods) >= 1)
3351
3720
  {
3352
- Assert(IsA(linitial(type_name->typmods), A_Const));
3353
- Assert(IsA(&castNode(A_Const, linitial(type_name->typmods))->val, Integer));
3354
-
3355
- int fields = intVal(&castNode(A_Const, linitial(type_name->typmods))->val);
3356
-
3357
3721
  appendStringInfoString(str, "interval");
3722
+ deparseIntervalTypmods(str, type_name);
3358
3723
 
3359
- // This logic is based on intervaltypmodout in timestamp.c
3360
- switch (fields)
3361
- {
3362
- case INTERVAL_MASK(YEAR):
3363
- appendStringInfoString(str, " year");
3364
- break;
3365
- case INTERVAL_MASK(MONTH):
3366
- appendStringInfoString(str, " month");
3367
- break;
3368
- case INTERVAL_MASK(DAY):
3369
- appendStringInfoString(str, " day");
3370
- break;
3371
- case INTERVAL_MASK(HOUR):
3372
- appendStringInfoString(str, " hour");
3373
- break;
3374
- case INTERVAL_MASK(MINUTE):
3375
- appendStringInfoString(str, " minute");
3376
- break;
3377
- case INTERVAL_MASK(SECOND):
3378
- appendStringInfoString(str, " second");
3379
- break;
3380
- case INTERVAL_MASK(YEAR) | INTERVAL_MASK(MONTH):
3381
- appendStringInfoString(str, " year to month");
3382
- break;
3383
- case INTERVAL_MASK(DAY) | INTERVAL_MASK(HOUR):
3384
- appendStringInfoString(str, " day to hour");
3385
- break;
3386
- case INTERVAL_MASK(DAY) | INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE):
3387
- appendStringInfoString(str, " day to minute");
3388
- break;
3389
- case INTERVAL_MASK(DAY) | INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE) | INTERVAL_MASK(SECOND):
3390
- appendStringInfoString(str, " day to second");
3391
- break;
3392
- case INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE):
3393
- appendStringInfoString(str, " hour to minute");
3394
- break;
3395
- case INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE) | INTERVAL_MASK(SECOND):
3396
- appendStringInfoString(str, " hour to second");
3397
- break;
3398
- case INTERVAL_MASK(MINUTE) | INTERVAL_MASK(SECOND):
3399
- appendStringInfoString(str, " minute to second");
3400
- break;
3401
- case INTERVAL_FULL_RANGE:
3402
- // Nothing
3403
- break;
3404
- default:
3405
- Assert(false);
3406
- break;
3407
- }
3408
-
3409
- if (list_length(type_name->typmods) == 2)
3410
- {
3411
- int precision = intVal(&castNode(A_Const, lsecond(type_name->typmods))->val);
3412
- if (precision != INTERVAL_FULL_PRECISION)
3413
- appendStringInfo(str, "(%d)", precision);
3414
- }
3415
-
3416
3724
  skip_typmods = true;
3417
3725
  }
3418
3726
  else
@@ -3458,6 +3766,79 @@ static void deparseTypeName(StringInfo str, TypeName *type_name)
3458
3766
  appendStringInfoString(str, "%type");
3459
3767
  }
3460
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
+
3461
3842
  static void deparseNullTest(StringInfo str, NullTest *null_test)
3462
3843
  {
3463
3844
  // argisrow is always false in raw parser output
@@ -3601,7 +3982,7 @@ static void deparseColumnDef(StringInfo str, ColumnDef *column_def)
3601
3982
 
3602
3983
  if (column_def->colname != NULL)
3603
3984
  {
3604
- appendStringInfoString(str, column_def->colname);
3985
+ appendStringInfoString(str, quote_identifier(column_def->colname));
3605
3986
  appendStringInfoChar(str, ' ');
3606
3987
  }
3607
3988
 
@@ -3638,6 +4019,22 @@ static void deparseColumnDef(StringInfo str, ColumnDef *column_def)
3638
4019
  removeTrailingSpace(str);
3639
4020
  }
3640
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
+
3641
4038
  static void deparseInsertStmt(StringInfo str, InsertStmt *insert_stmt)
3642
4039
  {
3643
4040
  ListCell *lc;
@@ -3660,18 +4057,7 @@ static void deparseInsertStmt(StringInfo str, InsertStmt *insert_stmt)
3660
4057
  appendStringInfoString(str, ") ");
3661
4058
  }
3662
4059
 
3663
- switch (insert_stmt->override)
3664
- {
3665
- case OVERRIDING_NOT_SET:
3666
- // Do nothing
3667
- break;
3668
- case OVERRIDING_USER_VALUE:
3669
- appendStringInfoString(str, "OVERRIDING USER VALUE ");
3670
- break;
3671
- case OVERRIDING_SYSTEM_VALUE:
3672
- appendStringInfoString(str, "OVERRIDING SYSTEM VALUE ");
3673
- break;
3674
- }
4060
+ deparseInsertOverride(str, insert_stmt->override);
3675
4061
 
3676
4062
  if (insert_stmt->selectStmt != NULL)
3677
4063
  {
@@ -3798,6 +4184,90 @@ static void deparseUpdateStmt(StringInfo str, UpdateStmt *update_stmt)
3798
4184
  removeTrailingSpace(str);
3799
4185
  }
3800
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
+
3801
4271
  static void deparseDeleteStmt(StringInfo str, DeleteStmt *delete_stmt)
3802
4272
  {
3803
4273
  if (delete_stmt->withClause != NULL)
@@ -3913,6 +4383,10 @@ static void deparseCreateCastStmt(StringInfo str, CreateCastStmt *create_cast_st
3913
4383
  case COERCION_ASSIGNMENT:
3914
4384
  appendStringInfoString(str, "AS ASSIGNMENT");
3915
4385
  break;
4386
+ case COERCION_PLPGSQL:
4387
+ // Not present in raw parser output
4388
+ Assert(false);
4389
+ break;
3916
4390
  case COERCION_EXPLICIT:
3917
4391
  // Default
3918
4392
  break;
@@ -4293,10 +4767,24 @@ static void deparseConstraint(StringInfo str, Constraint *constraint)
4293
4767
  appendStringInfoString(str, "ON DELETE CASCADE ");
4294
4768
  break;
4295
4769
  case FKCONSTR_ACTION_SETNULL:
4296
- appendStringInfoString(str, "ON DELETE SET NULL ");
4297
- break;
4298
4770
  case FKCONSTR_ACTION_SETDEFAULT:
4299
- 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
+ }
4300
4788
  break;
4301
4789
  default:
4302
4790
  // Not specified
@@ -4331,6 +4819,12 @@ static void deparseConstraint(StringInfo str, Constraint *constraint)
4331
4819
  removeTrailingSpace(str);
4332
4820
  }
4333
4821
 
4822
+ static void deparseReturnStmt(StringInfo str, ReturnStmt *return_stmt)
4823
+ {
4824
+ appendStringInfoString(str, "RETURN ");
4825
+ deparseExpr(str, return_stmt->returnval);
4826
+ }
4827
+
4334
4828
  static void deparseCreateFunctionStmt(StringInfo str, CreateFunctionStmt *create_function_stmt)
4335
4829
  {
4336
4830
  ListCell *lc;
@@ -4391,6 +4885,20 @@ static void deparseCreateFunctionStmt(StringInfo str, CreateFunctionStmt *create
4391
4885
  appendStringInfoChar(str, ' ');
4392
4886
  }
4393
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
+
4394
4902
  removeTrailingSpace(str);
4395
4903
  }
4396
4904
 
@@ -4399,7 +4907,7 @@ static void deparseFunctionParameter(StringInfo str, FunctionParameter *function
4399
4907
  switch (function_parameter->mode)
4400
4908
  {
4401
4909
  case FUNC_PARAM_IN: /* input only */
4402
- // Default
4910
+ appendStringInfoString(str, "IN ");
4403
4911
  break;
4404
4912
  case FUNC_PARAM_OUT: /* output only */
4405
4913
  appendStringInfoString(str, "OUT ");
@@ -4414,6 +4922,9 @@ static void deparseFunctionParameter(StringInfo str, FunctionParameter *function
4414
4922
  // No special annotation, the caller is expected to correctly put
4415
4923
  // this into the RETURNS part of the CREATE FUNCTION statement
4416
4924
  break;
4925
+ case FUNC_PARAM_DEFAULT:
4926
+ // Default
4927
+ break;
4417
4928
  default:
4418
4929
  Assert(false);
4419
4930
  break;
@@ -4445,7 +4956,6 @@ static void deparseCheckPointStmt(StringInfo str, CheckPointStmt *check_point_st
4445
4956
  static void deparseCreateSchemaStmt(StringInfo str, CreateSchemaStmt *create_schema_stmt)
4446
4957
  {
4447
4958
  ListCell *lc;
4448
-
4449
4959
  appendStringInfoString(str, "CREATE SCHEMA ");
4450
4960
 
4451
4961
  if (create_schema_stmt->if_not_exists)
@@ -4464,11 +4974,14 @@ static void deparseCreateSchemaStmt(StringInfo str, CreateSchemaStmt *create_sch
4464
4974
  appendStringInfoChar(str, ' ');
4465
4975
  }
4466
4976
 
4467
- foreach(lc, create_schema_stmt->schemaElts)
4977
+ if (create_schema_stmt->schemaElts)
4468
4978
  {
4469
- deparseSchemaStmt(str, lfirst(lc));
4470
- if (lnext(create_schema_stmt->schemaElts, lc))
4471
- 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
+ }
4472
4985
  }
4473
4986
 
4474
4987
  removeTrailingSpace(str);
@@ -4522,6 +5035,9 @@ static void deparseRoleSpec(StringInfo str, RoleSpec *role_spec)
4522
5035
  Assert(role_spec->rolename != NULL);
4523
5036
  appendStringInfoString(str, quote_identifier(role_spec->rolename));
4524
5037
  break;
5038
+ case ROLESPEC_CURRENT_ROLE:
5039
+ appendStringInfoString(str, "CURRENT_ROLE");
5040
+ break;
4525
5041
  case ROLESPEC_CURRENT_USER:
4526
5042
  appendStringInfoString(str, "CURRENT_USER");
4527
5043
  break;
@@ -4618,6 +5134,8 @@ static void deparsePartitionCmd(StringInfo str, PartitionCmd *partition_cmd)
4618
5134
  appendStringInfoChar(str, ' ');
4619
5135
  deparsePartitionBoundSpec(str, partition_cmd->bound);
4620
5136
  }
5137
+ if (partition_cmd->concurrent)
5138
+ appendStringInfoString(str, " CONCURRENTLY ");
4621
5139
  }
4622
5140
 
4623
5141
  // "TableElement" in gram.y
@@ -4982,7 +5500,7 @@ static void deparseSecLabelStmt(StringInfo str, SecLabelStmt *sec_label_stmt)
4982
5500
  break;
4983
5501
  case OBJECT_LARGEOBJECT:
4984
5502
  appendStringInfoString(str, "LARGE OBJECT ");
4985
- deparseValue(str, (Value *) sec_label_stmt->object, DEPARSE_NODE_CONTEXT_CONSTANT);
5503
+ deparseValue(str, (union ValUnion *) sec_label_stmt->object, DEPARSE_NODE_CONTEXT_CONSTANT);
4986
5504
  break;
4987
5505
  case OBJECT_PROCEDURE:
4988
5506
  appendStringInfoString(str, "PROCEDURE ");
@@ -5066,7 +5584,7 @@ static void deparseCreateTableAsStmt(StringInfo str, CreateTableAsStmt *create_t
5066
5584
 
5067
5585
  deparseOptTemp(str, create_table_as_stmt->into->rel->relpersistence);
5068
5586
 
5069
- switch (create_table_as_stmt->relkind)
5587
+ switch (create_table_as_stmt->objtype)
5070
5588
  {
5071
5589
  case OBJECT_TABLE:
5072
5590
  appendStringInfoString(str, "TABLE ");
@@ -5339,7 +5857,7 @@ static void deparseDropStmt(StringInfo str, DropStmt *drop_stmt)
5339
5857
  appendStringInfoChar(str, ' ');
5340
5858
  break;
5341
5859
  case OBJECT_LANGUAGE:
5342
- deparseStringLiteral(str, strVal(linitial(drop_stmt->objects)));
5860
+ deparseNameList(str, drop_stmt->objects);
5343
5861
  appendStringInfoChar(str, ' ');
5344
5862
  break;
5345
5863
  case OBJECT_TYPE:
@@ -5470,8 +5988,7 @@ static void deparseAlterObjectDependsStmt(StringInfo str, AlterObjectDependsStmt
5470
5988
  if (alter_object_depends_stmt->remove)
5471
5989
  appendStringInfoString(str, "NO ");
5472
5990
 
5473
- appendStringInfoString(str, "DEPENDS ON EXTENSION ");
5474
- deparseColId(str, strVal(alter_object_depends_stmt->extname));
5991
+ appendStringInfo(str, "DEPENDS ON EXTENSION %s", alter_object_depends_stmt->extname->sval);
5475
5992
  }
5476
5993
 
5477
5994
  static void deparseAlterObjectSchemaStmt(StringInfo str, AlterObjectSchemaStmt *alter_object_schema_stmt)
@@ -5661,6 +6178,10 @@ static void deparseAlterTableCmd(StringInfo str, AlterTableCmd *alter_table_cmd,
5661
6178
  appendStringInfoString(str, "ALTER COLUMN ");
5662
6179
  options = "SET STORAGE";
5663
6180
  break;
6181
+ case AT_SetCompression: /* alter column set compression */
6182
+ appendStringInfoString(str, "ALTER COLUMN ");
6183
+ options = "SET COMPRESSION";
6184
+ break;
5664
6185
  case AT_DropColumn: /* drop column */
5665
6186
  if (context == DEPARSE_NODE_CONTEXT_ALTER_TYPE)
5666
6187
  appendStringInfoString(str, "DROP ATTRIBUTE ");
@@ -5708,6 +6229,7 @@ static void deparseAlterTableCmd(StringInfo str, AlterTableCmd *alter_table_cmd,
5708
6229
  Assert(false);
5709
6230
  break;
5710
6231
  case AT_ReAddComment: /* internal to commands/tablecmds.c */
6232
+ case AT_ReAddStatistics: /* internal to commands/tablecmds.c */
5711
6233
  Assert(false);
5712
6234
  break;
5713
6235
  case AT_AlterColumnType: /* alter column type */
@@ -5746,6 +6268,9 @@ static void deparseAlterTableCmd(StringInfo str, AlterTableCmd *alter_table_cmd,
5746
6268
  case AT_SetRelOptions: /* SET (...) -- AM specific parameters */
5747
6269
  appendStringInfoString(str, "SET ");
5748
6270
  break;
6271
+ case AT_SetAccessMethod:
6272
+ appendStringInfo(str, "SET ACCESS METHOD ");
6273
+ break;
5749
6274
  case AT_ResetRelOptions: /* RESET (...) -- AM specific parameters */
5750
6275
  appendStringInfoString(str, "RESET ");
5751
6276
  break;
@@ -5825,6 +6350,9 @@ static void deparseAlterTableCmd(StringInfo str, AlterTableCmd *alter_table_cmd,
5825
6350
  case AT_DetachPartition: /* DETACH PARTITION */
5826
6351
  appendStringInfoString(str, "DETACH PARTITION ");
5827
6352
  break;
6353
+ case AT_DetachPartitionFinalize: /* DETACH PARTITION FINALIZE */
6354
+ appendStringInfoString(str, "DETACH PARTITION ");
6355
+ break;
5828
6356
  case AT_AddIdentity: /* ADD IDENTITY */
5829
6357
  appendStringInfoString(str, "ALTER ");
5830
6358
  options = "ADD";
@@ -5873,6 +6401,10 @@ static void deparseAlterTableCmd(StringInfo str, AlterTableCmd *alter_table_cmd,
5873
6401
  deparsePartitionCmd(str, castNode(PartitionCmd, alter_table_cmd->def));
5874
6402
  appendStringInfoChar(str, ' ');
5875
6403
  break;
6404
+ case AT_DetachPartitionFinalize:
6405
+ deparsePartitionCmd(str, castNode(PartitionCmd, alter_table_cmd->def));
6406
+ appendStringInfoString(str, "FINALIZE ");
6407
+ break;
5876
6408
  case AT_AddColumn:
5877
6409
  case AT_AlterColumnType:
5878
6410
  deparseColumnDef(str, castNode(ColumnDef, alter_table_cmd->def));
@@ -5900,6 +6432,13 @@ static void deparseAlterTableCmd(StringInfo str, AlterTableCmd *alter_table_cmd,
5900
6432
  deparseColId(str, strVal(alter_table_cmd->def));
5901
6433
  appendStringInfoChar(str, ' ');
5902
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;
5903
6442
  case AT_AddIdentity:
5904
6443
  case AT_AddConstraint:
5905
6444
  case AT_AlterConstraint:
@@ -5938,14 +6477,9 @@ static void deparseAlterTableCmd(StringInfo str, AlterTableCmd *alter_table_cmd,
5938
6477
  removeTrailingSpace(str);
5939
6478
  }
5940
6479
 
5941
- static void deparseAlterTableStmt(StringInfo str, AlterTableStmt *alter_table_stmt)
6480
+ static DeparseNodeContext deparseAlterTableObjType(StringInfo str, ObjectType type)
5942
6481
  {
5943
- ListCell *lc;
5944
- DeparseNodeContext context = DEPARSE_NODE_CONTEXT_NONE;
5945
-
5946
- appendStringInfoString(str, "ALTER ");
5947
-
5948
- switch (alter_table_stmt->relkind)
6482
+ switch (type)
5949
6483
  {
5950
6484
  case OBJECT_TABLE:
5951
6485
  appendStringInfoString(str, "TABLE ");
@@ -5967,13 +6501,49 @@ static void deparseAlterTableStmt(StringInfo str, AlterTableStmt *alter_table_st
5967
6501
  break;
5968
6502
  case OBJECT_TYPE:
5969
6503
  appendStringInfoString(str, "TYPE ");
5970
- context = DEPARSE_NODE_CONTEXT_ALTER_TYPE;
6504
+ return DEPARSE_NODE_CONTEXT_ALTER_TYPE;
5971
6505
  break;
5972
6506
  default:
5973
6507
  Assert(false);
5974
6508
  break;
5975
6509
  }
5976
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
+
5977
6547
  if (alter_table_stmt->missing_ok)
5978
6548
  appendStringInfoString(str, "IF EXISTS ");
5979
6549
 
@@ -6353,6 +6923,22 @@ static void deparseTransactionStmt(StringInfo str, TransactionStmt *transaction_
6353
6923
  removeTrailingSpace(str);
6354
6924
  }
6355
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
+
6356
6942
  static void deparseVariableSetStmt(StringInfo str, VariableSetStmt* variable_set_stmt)
6357
6943
  {
6358
6944
  ListCell *lc;
@@ -6363,9 +6949,17 @@ static void deparseVariableSetStmt(StringInfo str, VariableSetStmt* variable_set
6363
6949
  appendStringInfoString(str, "SET ");
6364
6950
  if (variable_set_stmt->is_local)
6365
6951
  appendStringInfoString(str, "LOCAL ");
6366
- deparseVarName(str, variable_set_stmt->name);
6367
- appendStringInfoString(str, " TO ");
6368
- 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
+ }
6369
6963
  break;
6370
6964
  case VAR_SET_DEFAULT: /* SET var TO DEFAULT */
6371
6965
  appendStringInfoString(str, "SET ");
@@ -6457,28 +7051,7 @@ static void deparseVacuumStmt(StringInfo str, VacuumStmt *vacuum_stmt)
6457
7051
  else
6458
7052
  appendStringInfoString(str, "ANALYZE ");
6459
7053
 
6460
- if (list_length(vacuum_stmt->options) > 0)
6461
- {
6462
- appendStringInfoChar(str, '(');
6463
- foreach(lc, vacuum_stmt->options)
6464
- {
6465
- DefElem *def_elem = castNode(DefElem, lfirst(lc));
6466
- deparseGenericDefElemName(str, def_elem->defname);
6467
- if (def_elem->arg != NULL)
6468
- {
6469
- appendStringInfoChar(str, ' ');
6470
- if (IsA(def_elem->arg, Integer) || IsA(def_elem->arg, Float))
6471
- deparseNumericOnly(str, (Value *) def_elem->arg);
6472
- else if (IsA(def_elem->arg, String))
6473
- deparseOptBooleanOrString(str, strVal(def_elem->arg));
6474
- else
6475
- Assert(false);
6476
- }
6477
- if (lnext(vacuum_stmt->options, lc))
6478
- appendStringInfoString(str, ", ");
6479
- }
6480
- appendStringInfoString(str, ") ");
6481
- }
7054
+ deparseUtilityOptionList(str, vacuum_stmt->options);
6482
7055
 
6483
7056
  foreach(lc, vacuum_stmt->rels)
6484
7057
  {
@@ -6589,31 +7162,7 @@ static void deparseExplainStmt(StringInfo str, ExplainStmt *explain_stmt)
6589
7162
 
6590
7163
  appendStringInfoString(str, "EXPLAIN ");
6591
7164
 
6592
- if (list_length(explain_stmt->options) > 0)
6593
- {
6594
- appendStringInfoChar(str, '(');
6595
-
6596
- foreach(lc, explain_stmt->options)
6597
- {
6598
- DefElem *def_elem = castNode(DefElem, lfirst(lc));
6599
- deparseGenericDefElemName(str, def_elem->defname);
6600
-
6601
- if (def_elem->arg != NULL && IsA(def_elem->arg, String))
6602
- {
6603
- appendStringInfoChar(str, ' ');
6604
- deparseOptBooleanOrString(str, strVal(def_elem->arg));
6605
- }
6606
- else if (def_elem->arg != NULL && (IsA(def_elem->arg, Integer) || IsA(def_elem->arg, Float)))
6607
- {
6608
- appendStringInfoChar(str, ' ');
6609
- deparseNumericOnly(str, (Value *) def_elem->arg);
6610
- }
6611
-
6612
- if (lnext(explain_stmt->options, lc))
6613
- appendStringInfoString(str, ", ");
6614
- }
6615
- appendStringInfoString(str, ") ");
6616
- }
7165
+ deparseUtilityOptionList(str, explain_stmt->options);
6617
7166
 
6618
7167
  deparseExplainableStmt(str, explain_stmt->query);
6619
7168
  }
@@ -6667,130 +7216,194 @@ static void deparseCopyStmt(StringInfo str, CopyStmt *copy_stmt)
6667
7216
 
6668
7217
  if (list_length(copy_stmt->options) > 0)
6669
7218
  {
6670
- 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.
6671
7235
  foreach(lc, copy_stmt->options)
6672
7236
  {
6673
7237
  DefElem *def_elem = castNode(DefElem, lfirst(lc));
6674
7238
 
6675
- if (strcmp(def_elem->defname, "format") == 0)
6676
- {
6677
- appendStringInfoString(str, "FORMAT ");
6678
-
6679
- char *format = strVal(def_elem->arg);
6680
- if (strcmp(format, "binary") == 0)
6681
- appendStringInfoString(str, "BINARY");
6682
- else if (strcmp(format, "csv") == 0)
6683
- appendStringInfoString(str, "CSV");
6684
- else
6685
- Assert(false);
6686
- }
6687
- else if (strcmp(def_elem->defname, "freeze") == 0 && (def_elem->arg == NULL || intVal(def_elem->arg) == 1))
6688
- {
6689
- appendStringInfoString(str, "FREEZE");
6690
- if (def_elem->arg != NULL && intVal(def_elem->arg) == 1)
6691
- appendStringInfoString(str, " 1");
6692
- }
6693
- else if (strcmp(def_elem->defname, "delimiter") == 0)
6694
- {
6695
- appendStringInfoString(str, "DELIMITER ");
6696
- deparseStringLiteral(str, strVal(def_elem->arg));
6697
- }
6698
- else if (strcmp(def_elem->defname, "null") == 0)
6699
- {
6700
- appendStringInfoString(str, "NULL ");
6701
- deparseStringLiteral(str, strVal(def_elem->arg));
6702
- }
6703
- else if (strcmp(def_elem->defname, "header") == 0 && (def_elem->arg == NULL || intVal(def_elem->arg) == 1))
6704
- {
6705
- appendStringInfoString(str, "HEADER");
6706
- if (def_elem->arg != NULL && intVal(def_elem->arg) == 1)
6707
- appendStringInfoString(str, " 1");
6708
- }
6709
- else if (strcmp(def_elem->defname, "quote") == 0)
6710
- {
6711
- appendStringInfoString(str, "QUOTE ");
6712
- deparseStringLiteral(str, strVal(def_elem->arg));
6713
- }
6714
- 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
6715
7248
  {
6716
- appendStringInfoString(str, "ESCAPE ");
6717
- deparseStringLiteral(str, strVal(def_elem->arg));
7249
+ old_fmt = false;
7250
+ break;
6718
7251
  }
6719
- 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)
6720
7257
  {
6721
- appendStringInfoString(str, "FORCE_QUOTE ");
6722
- 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))
6723
7261
  {
6724
- appendStringInfoChar(str, '*');
7262
+ appendStringInfoString(str, "FREEZE ");
6725
7263
  }
6726
- else if (IsA(def_elem->arg, List))
7264
+ else if (strcmp(def_elem->defname, "header") == 0 && def_elem->arg && optBooleanValue(def_elem->arg))
6727
7265
  {
6728
- 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 ");
6729
7275
  deparseColumnList(str, castNode(List, def_elem->arg));
6730
- appendStringInfoChar(str, ')');
6731
7276
  }
6732
7277
  else
6733
7278
  {
7279
+ // This isn't reachable, the conditions here are exactly the same as the first loop above.
6734
7280
  Assert(false);
6735
7281
  }
6736
7282
  }
6737
- else if (strcmp(def_elem->defname, "force_not_null") == 0)
7283
+ } else {
7284
+ appendStringInfoString(str, "WITH (");
7285
+ foreach(lc, copy_stmt->options)
6738
7286
  {
6739
- appendStringInfoString(str, "FORCE_NOT_NULL (");
6740
- deparseColumnList(str, castNode(List, def_elem->arg));
6741
- appendStringInfoChar(str, ')');
6742
- }
6743
- else if (strcmp(def_elem->defname, "force_null") == 0)
6744
- {
6745
- appendStringInfoString(str, "FORCE_NULL (");
6746
- deparseColumnList(str, castNode(List, def_elem->arg));
6747
- appendStringInfoChar(str, ')');
6748
- }
6749
- else if (strcmp(def_elem->defname, "encoding") == 0)
6750
- {
6751
- appendStringInfoString(str, "ENCODING ");
6752
- deparseStringLiteral(str, strVal(def_elem->arg));
6753
- }
6754
- else
6755
- {
6756
- appendStringInfoString(str, quote_identifier(def_elem->defname));
6757
- if (def_elem->arg != NULL)
6758
- appendStringInfoChar(str, ' ');
6759
-
6760
- if (def_elem->arg == NULL)
7287
+ DefElem *def_elem = castNode(DefElem, lfirst(lc));
7288
+
7289
+ if (strcmp(def_elem->defname, "format") == 0)
6761
7290
  {
6762
- // Nothing
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);
6763
7300
  }
6764
- else if (IsA(def_elem->arg, String))
7301
+ else if (strcmp(def_elem->defname, "freeze") == 0)
6765
7302
  {
6766
- deparseOptBooleanOrString(str, strVal(def_elem->arg));
7303
+ appendStringInfoString(str, "FREEZE");
7304
+ deparseOptBoolean(str, def_elem->arg);
6767
7305
  }
6768
- else if (IsA(def_elem->arg, Integer) || IsA(def_elem->arg, Float))
7306
+ else if (strcmp(def_elem->defname, "delimiter") == 0)
6769
7307
  {
6770
- deparseNumericOnly(str, (Value *) def_elem->arg);
7308
+ appendStringInfoString(str, "DELIMITER ");
7309
+ deparseStringLiteral(str, strVal(def_elem->arg));
6771
7310
  }
6772
- else if (IsA(def_elem->arg, A_Star))
7311
+ else if (strcmp(def_elem->defname, "null") == 0)
6773
7312
  {
6774
- deparseAStar(str, castNode(A_Star, def_elem->arg));
7313
+ appendStringInfoString(str, "NULL ");
7314
+ deparseStringLiteral(str, strVal(def_elem->arg));
6775
7315
  }
6776
- else if (IsA(def_elem->arg, List))
7316
+ else if (strcmp(def_elem->defname, "header") == 0)
6777
7317
  {
6778
- List *l = castNode(List, def_elem->arg);
6779
- appendStringInfoChar(str, '(');
6780
- foreach(lc2, l)
7318
+ appendStringInfoString(str, "HEADER");
7319
+ deparseOptBoolean(str, def_elem->arg);
7320
+ }
7321
+ else if (strcmp(def_elem->defname, "quote") == 0)
7322
+ {
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))
6781
7335
  {
6782
- deparseOptBooleanOrString(str, strVal(lfirst(lc2)));
6783
- if (lnext(l, lc2))
6784
- appendStringInfoString(str, ", ");
7336
+ appendStringInfoChar(str, '*');
6785
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
7345
+ {
7346
+ Assert(false);
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));
6786
7353
  appendStringInfoChar(str, ')');
6787
7354
  }
6788
- }
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
+ }
6789
7401
 
6790
- if (lnext(copy_stmt->options, lc))
6791
- appendStringInfoString(str, ", ");
7402
+ if (lnext(copy_stmt->options, lc))
7403
+ appendStringInfoString(str, ", ");
7404
+ }
7405
+ appendStringInfoString(str, ") ");
6792
7406
  }
6793
- appendStringInfoString(str, ") ");
6794
7407
  }
6795
7408
 
6796
7409
  deparseWhereClause(str, copy_stmt->whereClause);
@@ -7247,7 +7860,6 @@ static void deparseAccessPriv(StringInfo str, AccessPriv *access_priv)
7247
7860
  static void deparseGrantStmt(StringInfo str, GrantStmt *grant_stmt)
7248
7861
  {
7249
7862
  ListCell *lc;
7250
-
7251
7863
  if (grant_stmt->is_grant)
7252
7864
  appendStringInfoString(str, "GRANT ");
7253
7865
  else
@@ -7294,6 +7906,12 @@ static void deparseGrantStmt(StringInfo str, GrantStmt *grant_stmt)
7294
7906
 
7295
7907
  deparseOptDropBehavior(str, grant_stmt->behavior);
7296
7908
 
7909
+ if (grant_stmt->grantor)
7910
+ {
7911
+ appendStringInfoString(str, "GRANTED BY ");
7912
+ deparseRoleSpec(str, castNode(RoleSpec, grant_stmt->grantor));
7913
+ }
7914
+
7297
7915
  removeTrailingSpace(str);
7298
7916
  }
7299
7917
 
@@ -7306,6 +7924,9 @@ static void deparseGrantRoleStmt(StringInfo str, GrantRoleStmt *grant_role_stmt)
7306
7924
  else
7307
7925
  appendStringInfoString(str, "REVOKE ");
7308
7926
 
7927
+ if (!grant_role_stmt->is_grant && grant_role_stmt->admin_opt)
7928
+ appendStringInfoString(str, "ADMIN OPTION FOR ");
7929
+
7309
7930
  foreach(lc, grant_role_stmt->granted_roles)
7310
7931
  {
7311
7932
  deparseAccessPriv(str, castNode(AccessPriv, lfirst(lc)));
@@ -7322,9 +7943,15 @@ static void deparseGrantRoleStmt(StringInfo str, GrantRoleStmt *grant_role_stmt)
7322
7943
  deparseRoleList(str, grant_role_stmt->grantee_roles);
7323
7944
  appendStringInfoChar(str, ' ');
7324
7945
 
7325
- if (grant_role_stmt->admin_opt)
7946
+ if (grant_role_stmt->is_grant && grant_role_stmt->admin_opt)
7326
7947
  appendStringInfoString(str, "WITH ADMIN OPTION ");
7327
7948
 
7949
+ if (grant_role_stmt->grantor)
7950
+ {
7951
+ appendStringInfoString(str, "GRANTED BY ");
7952
+ deparseRoleSpec(str, castNode(RoleSpec, grant_role_stmt->grantor));
7953
+ }
7954
+
7328
7955
  removeTrailingSpace(str);
7329
7956
  }
7330
7957
 
@@ -7359,7 +7986,7 @@ static void deparseIndexStmt(StringInfo str, IndexStmt *index_stmt)
7359
7986
 
7360
7987
  if (index_stmt->idxname != NULL)
7361
7988
  {
7362
- appendStringInfoString(str, index_stmt->idxname);
7989
+ appendStringInfoString(str, quote_identifier(index_stmt->idxname));
7363
7990
  appendStringInfoChar(str, ' ');
7364
7991
  }
7365
7992
 
@@ -7395,6 +8022,11 @@ static void deparseIndexStmt(StringInfo str, IndexStmt *index_stmt)
7395
8022
  appendStringInfoString(str, ") ");
7396
8023
  }
7397
8024
 
8025
+ if (index_stmt->nulls_not_distinct)
8026
+ {
8027
+ appendStringInfoString(str, "NULLS NOT DISTINCT ");
8028
+ }
8029
+
7398
8030
  deparseOptWith(str, index_stmt->options);
7399
8031
 
7400
8032
  if (index_stmt->tableSpace != NULL)
@@ -7498,59 +8130,59 @@ static void deparseAlterRoleElem(StringInfo str, DefElem *def_elem)
7498
8130
  appendStringInfoString(str, "VALID UNTIL ");
7499
8131
  deparseStringLiteral(str, strVal(def_elem->arg));
7500
8132
  }
7501
- 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))
7502
8134
  {
7503
8135
  appendStringInfoString(str, "SUPERUSER");
7504
8136
  }
7505
- 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))
7506
8138
  {
7507
8139
  appendStringInfoString(str, "NOSUPERUSER");
7508
8140
  }
7509
- 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))
7510
8142
  {
7511
8143
  appendStringInfoString(str, "CREATEROLE");
7512
8144
  }
7513
- 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))
7514
8146
  {
7515
8147
  appendStringInfoString(str, "NOCREATEROLE");
7516
8148
  }
7517
- 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))
7518
8150
  {
7519
8151
  appendStringInfoString(str, "REPLICATION");
7520
8152
  }
7521
- 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))
7522
8154
  {
7523
8155
  appendStringInfoString(str, "NOREPLICATION");
7524
8156
  }
7525
- 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))
7526
8158
  {
7527
8159
  appendStringInfoString(str, "CREATEDB");
7528
8160
  }
7529
- 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))
7530
8162
  {
7531
8163
  appendStringInfoString(str, "NOCREATEDB");
7532
8164
  }
7533
- 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))
7534
8166
  {
7535
8167
  appendStringInfoString(str, "LOGIN");
7536
8168
  }
7537
- 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))
7538
8170
  {
7539
8171
  appendStringInfoString(str, "NOLOGIN");
7540
8172
  }
7541
- 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))
7542
8174
  {
7543
8175
  appendStringInfoString(str, "BYPASSRLS");
7544
8176
  }
7545
- 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))
7546
8178
  {
7547
8179
  appendStringInfoString(str, "NOBYPASSRLS");
7548
8180
  }
7549
- 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))
7550
8182
  {
7551
8183
  appendStringInfoString(str, "INHERIT");
7552
8184
  }
7553
- 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))
7554
8186
  {
7555
8187
  appendStringInfoString(str, "NOINHERIT");
7556
8188
  }
@@ -7823,8 +8455,7 @@ static void deparseReindexStmt(StringInfo str, ReindexStmt *reindex_stmt)
7823
8455
  {
7824
8456
  appendStringInfoString(str, "REINDEX ");
7825
8457
 
7826
- if (reindex_stmt->options & REINDEXOPT_VERBOSE)
7827
- appendStringInfoString(str, "(VERBOSE) ");
8458
+ deparseUtilityOptionList(str, reindex_stmt->params);
7828
8459
 
7829
8460
  switch (reindex_stmt->kind)
7830
8461
  {
@@ -7845,9 +8476,6 @@ static void deparseReindexStmt(StringInfo str, ReindexStmt *reindex_stmt)
7845
8476
  break;
7846
8477
  }
7847
8478
 
7848
- if (reindex_stmt->concurrent)
7849
- appendStringInfoString(str, "CONCURRENTLY ");
7850
-
7851
8479
  if (reindex_stmt->relation != NULL)
7852
8480
  {
7853
8481
  deparseRangeVar(str, reindex_stmt->relation, DEPARSE_NODE_CONTEXT_NONE);
@@ -7891,6 +8519,9 @@ static void deparseRuleStmt(StringInfo str, RuleStmt* rule_stmt)
7891
8519
  case CMD_DELETE:
7892
8520
  appendStringInfoString(str, "DELETE ");
7893
8521
  break;
8522
+ case CMD_MERGE:
8523
+ appendStringInfoString(str, "MERGE ");
8524
+ break;
7894
8525
  }
7895
8526
 
7896
8527
  appendStringInfoString(str, "TO ");
@@ -8213,7 +8844,12 @@ static void deparseCreateTableSpaceStmt(StringInfo str, CreateTableSpaceStmt *cr
8213
8844
  }
8214
8845
 
8215
8846
  appendStringInfoString(str, "LOCATION ");
8216
- 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
+
8217
8853
  appendStringInfoChar(str, ' ');
8218
8854
 
8219
8855
  deparseOptWith(str, create_table_space_stmt->options);
@@ -8276,6 +8912,50 @@ static void deparseCreateAmStmt(StringInfo str, CreateAmStmt *create_am_stmt)
8276
8912
  deparseHandlerName(str, create_am_stmt->handler_name);
8277
8913
  }
8278
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
+
8279
8959
  static void deparseCreatePublicationStmt(StringInfo str, CreatePublicationStmt *create_publication_stmt)
8280
8960
  {
8281
8961
  ListCell *lc = NULL;
@@ -8284,10 +8964,10 @@ static void deparseCreatePublicationStmt(StringInfo str, CreatePublicationStmt *
8284
8964
  appendStringInfoString(str, quote_identifier(create_publication_stmt->pubname));
8285
8965
  appendStringInfoChar(str, ' ');
8286
8966
 
8287
- if (list_length(create_publication_stmt->tables) > 0)
8967
+ if (list_length(create_publication_stmt->pubobjects) > 0)
8288
8968
  {
8289
- appendStringInfoString(str, "FOR TABLE ");
8290
- deparseRelationExprList(str, create_publication_stmt->tables);
8969
+ appendStringInfoString(str, "FOR ");
8970
+ deparsePublicationObjectList(str, create_publication_stmt->pubobjects);
8291
8971
  appendStringInfoChar(str, ' ');
8292
8972
  }
8293
8973
  else if (create_publication_stmt->for_all_tables)
@@ -8305,25 +8985,22 @@ static void deparseAlterPublicationStmt(StringInfo str, AlterPublicationStmt *al
8305
8985
  deparseColId(str, alter_publication_stmt->pubname);
8306
8986
  appendStringInfoChar(str, ' ');
8307
8987
 
8308
- if (list_length(alter_publication_stmt->tables) > 0)
8988
+ if (list_length(alter_publication_stmt->pubobjects) > 0)
8309
8989
  {
8310
- switch (alter_publication_stmt->tableAction)
8990
+ switch (alter_publication_stmt->action)
8311
8991
  {
8312
- case DEFELEM_SET:
8313
- appendStringInfoString(str, "SET TABLE ");
8314
- break;
8315
- case DEFELEM_ADD:
8316
- appendStringInfoString(str, "ADD TABLE ");
8992
+ case AP_SetObjects:
8993
+ appendStringInfoString(str, "SET ");
8317
8994
  break;
8318
- case DEFELEM_DROP:
8319
- appendStringInfoString(str, "DROP TABLE ");
8995
+ case AP_AddObjects:
8996
+ appendStringInfoString(str, "ADD ");
8320
8997
  break;
8321
- case DEFELEM_UNSPEC:
8322
- Assert(false);
8998
+ case AP_DropObjects:
8999
+ appendStringInfoString(str, "DROP ");
8323
9000
  break;
8324
9001
  }
8325
9002
 
8326
- deparseRelationExprList(str, alter_publication_stmt->tables);
9003
+ deparsePublicationObjectList(str, alter_publication_stmt->pubobjects);
8327
9004
  }
8328
9005
  else if (list_length(alter_publication_stmt->options) > 0)
8329
9006
  {
@@ -8580,7 +9257,7 @@ static void deparseCommentStmt(StringInfo str, CommentStmt *comment_stmt)
8580
9257
  appendStringInfoString(str, quote_identifier(strVal(linitial(l))));
8581
9258
  break;
8582
9259
  case OBJECT_LARGEOBJECT:
8583
- deparseValue(str, (Value *) comment_stmt->object, DEPARSE_NODE_CONTEXT_NONE);
9260
+ deparseValue(str, (union ValUnion *) comment_stmt->object, DEPARSE_NODE_CONTEXT_NONE);
8584
9261
  break;
8585
9262
  case OBJECT_CAST:
8586
9263
  l = castNode(List, comment_stmt->object);
@@ -8604,6 +9281,19 @@ static void deparseCommentStmt(StringInfo str, CommentStmt *comment_stmt)
8604
9281
  appendStringInfoString(str, "NULL");
8605
9282
  }
8606
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
+
8607
9297
  static void deparseCreateStatsStmt(StringInfo str, CreateStatsStmt *create_stats_stmt)
8608
9298
  {
8609
9299
  ListCell *lc;
@@ -8624,7 +9314,12 @@ static void deparseCreateStatsStmt(StringInfo str, CreateStatsStmt *create_stats
8624
9314
  }
8625
9315
 
8626
9316
  appendStringInfoString(str, "ON ");
8627
- 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
+ }
8628
9323
 
8629
9324
  appendStringInfoString(str, " FROM ");
8630
9325
  deparseFromList(str, create_stats_stmt->relations);
@@ -8736,7 +9431,7 @@ static void deparseVariableShowStmt(StringInfo str, VariableShowStmt *variable_s
8736
9431
  else if (strcmp(variable_show_stmt->name, "all") == 0)
8737
9432
  appendStringInfoString(str, "SESSION ALL");
8738
9433
  else
8739
- appendStringInfoString(str, variable_show_stmt->name);
9434
+ appendStringInfoString(str, quote_identifier(variable_show_stmt->name));
8740
9435
  }
8741
9436
 
8742
9437
  static void deparseRangeTableSample(StringInfo str, RangeTableSample *range_table_sample)
@@ -8801,6 +9496,10 @@ static void deparseAlterSubscriptionStmt(StringInfo str, AlterSubscriptionStmt *
8801
9496
  appendStringInfoString(str, "SET ");
8802
9497
  deparseDefinition(str, alter_subscription_stmt->options);
8803
9498
  break;
9499
+ case ALTER_SUBSCRIPTION_SKIP:
9500
+ appendStringInfoString(str, "SKIP ");
9501
+ deparseDefinition(str, alter_subscription_stmt->options);
9502
+ break;
8804
9503
  case ALTER_SUBSCRIPTION_CONNECTION:
8805
9504
  appendStringInfoString(str, "CONNECTION ");
8806
9505
  deparseStringLiteral(str, alter_subscription_stmt->conninfo);
@@ -8810,7 +9509,29 @@ static void deparseAlterSubscriptionStmt(StringInfo str, AlterSubscriptionStmt *
8810
9509
  appendStringInfoString(str, "REFRESH PUBLICATION ");
8811
9510
  deparseOptDefinition(str, alter_subscription_stmt->options);
8812
9511
  break;
8813
- 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:
8814
9535
  appendStringInfoString(str, "SET PUBLICATION ");
8815
9536
  foreach(lc, alter_subscription_stmt->publication)
8816
9537
  {
@@ -8825,17 +9546,13 @@ static void deparseAlterSubscriptionStmt(StringInfo str, AlterSubscriptionStmt *
8825
9546
  Assert(list_length(alter_subscription_stmt->options) == 1);
8826
9547
  DefElem *defelem = castNode(DefElem, linitial(alter_subscription_stmt->options));
8827
9548
  Assert(strcmp(defelem->defname, "enabled") == 0);
8828
- if (intVal(defelem->arg) == 1)
9549
+ if (optBooleanValue(defelem->arg))
8829
9550
  {
8830
9551
  appendStringInfoString(str, " ENABLE ");
8831
9552
  }
8832
- else if (intVal(defelem->arg) == 0)
8833
- {
8834
- appendStringInfoString(str, " DISABLE ");
8835
- }
8836
9553
  else
8837
9554
  {
8838
- Assert(false);
9555
+ appendStringInfoString(str, " DISABLE ");
8839
9556
  }
8840
9557
  break;
8841
9558
  }
@@ -8897,7 +9614,7 @@ static void deparseAlterOwnerStmt(StringInfo str, AlterOwnerStmt *alter_owner_st
8897
9614
  break;
8898
9615
  case OBJECT_LARGEOBJECT:
8899
9616
  appendStringInfoString(str, "LARGE OBJECT ");
8900
- deparseNumericOnly(str, (Value *) alter_owner_stmt->object);
9617
+ deparseNumericOnly(str, (union ValUnion *) alter_owner_stmt->object);
8901
9618
  break;
8902
9619
  case OBJECT_OPERATOR:
8903
9620
  appendStringInfoString(str, "OPERATOR ");
@@ -9060,6 +9777,8 @@ static void deparseCreateTrigStmt(StringInfo str, CreateTrigStmt *create_trig_st
9060
9777
  bool skip_events_or = true;
9061
9778
 
9062
9779
  appendStringInfoString(str, "CREATE ");
9780
+ if (create_trig_stmt->replace)
9781
+ appendStringInfoString(str, "OR REPLACE ");
9063
9782
  if (create_trig_stmt->isconstraint)
9064
9783
  appendStringInfoString(str, "CONSTRAINT ");
9065
9784
  appendStringInfoString(str, "TRIGGER ");
@@ -9223,8 +9942,6 @@ static void deparseXmlExpr(StringInfo str, XmlExpr* xml_expr)
9223
9942
  Assert(false);
9224
9943
  }
9225
9944
  deparseExpr(str, linitial(xml_expr->args));
9226
- if (strcmp(strVal(&castNode(A_Const, castNode(TypeCast, lsecond(xml_expr->args))->arg)->val), "t") == 0)
9227
- appendStringInfoString(str, " PRESERVE WHITESPACE");
9228
9945
  appendStringInfoChar(str, ')');
9229
9946
  break;
9230
9947
  case IS_XMLPI: /* XMLPI(name [, args]) */
@@ -9241,7 +9958,7 @@ static void deparseXmlExpr(StringInfo str, XmlExpr* xml_expr)
9241
9958
  appendStringInfoString(str, "xmlroot(");
9242
9959
  deparseExpr(str, linitial(xml_expr->args));
9243
9960
  appendStringInfoString(str, ", version ");
9244
- if (nodeTag(&castNode(A_Const, lsecond(xml_expr->args))->val) == T_Null)
9961
+ if (castNode(A_Const, lsecond(xml_expr->args))->isnull)
9245
9962
  appendStringInfoString(str, "NO VALUE");
9246
9963
  else
9247
9964
  deparseExpr(str, lsecond(xml_expr->args));
@@ -9371,8 +10088,8 @@ static void deparseGroupingFunc(StringInfo str, GroupingFunc *grouping_func)
9371
10088
  static void deparseClusterStmt(StringInfo str, ClusterStmt *cluster_stmt)
9372
10089
  {
9373
10090
  appendStringInfoString(str, "CLUSTER ");
9374
- if (cluster_stmt->options & CLUOPT_VERBOSE)
9375
- appendStringInfoString(str, "VERBOSE ");
10091
+
10092
+ deparseUtilityOptionList(str, cluster_stmt->params);
9376
10093
 
9377
10094
  if (cluster_stmt->relation != NULL)
9378
10095
  {
@@ -9390,44 +10107,49 @@ static void deparseClusterStmt(StringInfo str, ClusterStmt *cluster_stmt)
9390
10107
  removeTrailingSpace(str);
9391
10108
  }
9392
10109
 
9393
- static void deparseValue(StringInfo str, Value *value, DeparseNodeContext context)
10110
+ static void deparseValue(StringInfo str, union ValUnion *value, DeparseNodeContext context)
9394
10111
  {
10112
+ if (!value) {
10113
+ appendStringInfoString(str, "NULL");
10114
+ return;
10115
+ }
10116
+
9395
10117
  switch (nodeTag(value))
9396
10118
  {
9397
10119
  case T_Integer:
9398
10120
  case T_Float:
9399
10121
  deparseNumericOnly(str, value);
9400
10122
  break;
10123
+ case T_Boolean:
10124
+ appendStringInfoString(str, value->boolval.boolval ? "true" : "false");
10125
+ break;
9401
10126
  case T_String:
9402
10127
  if (context == DEPARSE_NODE_CONTEXT_IDENTIFIER) {
9403
- appendStringInfoString(str, quote_identifier(value->val.str));
10128
+ appendStringInfoString(str, quote_identifier(value->sval.sval));
9404
10129
  } else if (context == DEPARSE_NODE_CONTEXT_CONSTANT) {
9405
- deparseStringLiteral(str, value->val.str);
10130
+ deparseStringLiteral(str, value->sval.sval);
9406
10131
  } else {
9407
- appendStringInfoString(str, value->val.str);
10132
+ appendStringInfoString(str, value->sval.sval);
9408
10133
  }
9409
10134
  break;
9410
10135
  case T_BitString:
9411
- if (strlen(value->val.str) >= 1 && value->val.str[0] == 'x')
10136
+ if (strlen(value->sval.sval) >= 1 && value->sval.sval[0] == 'x')
9412
10137
  {
9413
10138
  appendStringInfoChar(str, 'x');
9414
- deparseStringLiteral(str, value->val.str + 1);
10139
+ deparseStringLiteral(str, value->sval.sval + 1);
9415
10140
  }
9416
- 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')
9417
10142
  {
9418
10143
  appendStringInfoChar(str, 'b');
9419
- deparseStringLiteral(str, value->val.str + 1);
10144
+ deparseStringLiteral(str, value->sval.sval + 1);
9420
10145
  }
9421
10146
  else
9422
10147
  {
9423
10148
  Assert(false);
9424
10149
  }
9425
10150
  break;
9426
- case T_Null:
9427
- appendStringInfoString(str, "NULL");
9428
- break;
9429
10151
  default:
9430
- elog(ERROR, "unrecognized value node type: %d",
10152
+ elog(ERROR, "deparse: unrecognized value node type: %d",
9431
10153
  (int) nodeTag(value));
9432
10154
  break;
9433
10155
  }
@@ -9450,6 +10172,9 @@ static void deparsePreparableStmt(StringInfo str, Node *node)
9450
10172
  case T_DeleteStmt:
9451
10173
  deparseDeleteStmt(str, castNode(DeleteStmt, node));
9452
10174
  break;
10175
+ case T_MergeStmt:
10176
+ deparseMergeStmt(str, castNode(MergeStmt, node));
10177
+ break;
9453
10178
  default:
9454
10179
  Assert(false);
9455
10180
  }
@@ -9509,6 +10234,9 @@ static void deparseExplainableStmt(StringInfo str, Node *node)
9509
10234
  case T_ExecuteStmt:
9510
10235
  deparseExecuteStmt(str, castNode(ExecuteStmt, node));
9511
10236
  break;
10237
+ case T_MergeStmt:
10238
+ deparseMergeStmt(str, castNode(MergeStmt, node));
10239
+ break;
9512
10240
  default:
9513
10241
  Assert(false);
9514
10242
  }
@@ -9631,6 +10359,9 @@ static void deparseStmt(StringInfo str, Node *node)
9631
10359
  case T_AlterSystemStmt:
9632
10360
  deparseAlterSystemStmt(str, castNode(AlterSystemStmt, node));
9633
10361
  break;
10362
+ case T_AlterTableMoveAllStmt:
10363
+ deparseAlterTableMoveAllStmt(str, castNode(AlterTableMoveAllStmt, node));
10364
+ break;
9634
10365
  case T_AlterTableStmt:
9635
10366
  deparseAlterTableStmt(str, castNode(AlterTableStmt, node));
9636
10367
  break;
@@ -9841,6 +10572,9 @@ static void deparseStmt(StringInfo str, Node *node)
9841
10572
  case T_LockStmt:
9842
10573
  deparseLockStmt(str, castNode(LockStmt, node));
9843
10574
  break;
10575
+ case T_MergeStmt:
10576
+ deparseMergeStmt(str, castNode(MergeStmt, node));
10577
+ break;
9844
10578
  case T_NotifyStmt:
9845
10579
  deparseNotifyStmt(str, castNode(NotifyStmt, node));
9846
10580
  break;
@@ -9900,8 +10634,7 @@ static void deparseStmt(StringInfo str, Node *node)
9900
10634
  deparseCreateRangeStmt(str, castNode(CreateRangeStmt, node));
9901
10635
  break;
9902
10636
  default:
9903
- // No other node types are supported at the top-level
9904
- Assert(false);
10637
+ elog(ERROR, "deparse: unsupported top-level node type: %u", nodeTag(node));
9905
10638
  }
9906
10639
  }
9907
10640