pg_query 2.1.0 → 4.2.1

Sign up to get free protection for your applications and to get access to all the features.
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