pg_query 1.3.0 → 2.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (480) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +207 -117
  3. data/README.md +72 -65
  4. data/Rakefile +85 -5
  5. data/ext/pg_query/extconf.rb +3 -39
  6. data/ext/pg_query/guc-file.c +0 -0
  7. data/ext/pg_query/include/access/amapi.h +246 -0
  8. data/ext/pg_query/include/access/attmap.h +52 -0
  9. data/ext/pg_query/include/access/attnum.h +64 -0
  10. data/ext/pg_query/include/access/clog.h +61 -0
  11. data/ext/pg_query/include/access/commit_ts.h +77 -0
  12. data/ext/pg_query/include/access/detoast.h +92 -0
  13. data/ext/pg_query/include/access/genam.h +228 -0
  14. data/ext/pg_query/include/access/gin.h +78 -0
  15. data/ext/pg_query/include/access/htup.h +89 -0
  16. data/ext/pg_query/include/access/htup_details.h +819 -0
  17. data/ext/pg_query/include/access/itup.h +161 -0
  18. data/ext/pg_query/include/access/parallel.h +82 -0
  19. data/ext/pg_query/include/access/printtup.h +35 -0
  20. data/ext/pg_query/include/access/relation.h +28 -0
  21. data/ext/pg_query/include/access/relscan.h +176 -0
  22. data/ext/pg_query/include/access/rmgr.h +35 -0
  23. data/ext/pg_query/include/access/rmgrlist.h +49 -0
  24. data/ext/pg_query/include/access/sdir.h +58 -0
  25. data/ext/pg_query/include/access/skey.h +151 -0
  26. data/ext/pg_query/include/access/stratnum.h +83 -0
  27. data/ext/pg_query/include/access/sysattr.h +29 -0
  28. data/ext/pg_query/include/access/table.h +27 -0
  29. data/ext/pg_query/include/access/tableam.h +1825 -0
  30. data/ext/pg_query/include/access/transam.h +265 -0
  31. data/ext/pg_query/include/access/tupconvert.h +51 -0
  32. data/ext/pg_query/include/access/tupdesc.h +154 -0
  33. data/ext/pg_query/include/access/tupmacs.h +247 -0
  34. data/ext/pg_query/include/access/twophase.h +61 -0
  35. data/ext/pg_query/include/access/xact.h +463 -0
  36. data/ext/pg_query/include/access/xlog.h +398 -0
  37. data/ext/pg_query/include/access/xlog_internal.h +330 -0
  38. data/ext/pg_query/include/access/xlogdefs.h +109 -0
  39. data/ext/pg_query/include/access/xloginsert.h +64 -0
  40. data/ext/pg_query/include/access/xlogreader.h +327 -0
  41. data/ext/pg_query/include/access/xlogrecord.h +227 -0
  42. data/ext/pg_query/include/bootstrap/bootstrap.h +62 -0
  43. data/ext/pg_query/include/c.h +1322 -0
  44. data/ext/pg_query/include/catalog/catalog.h +42 -0
  45. data/ext/pg_query/include/catalog/catversion.h +58 -0
  46. data/ext/pg_query/include/catalog/dependency.h +275 -0
  47. data/ext/pg_query/include/catalog/genbki.h +64 -0
  48. data/ext/pg_query/include/catalog/index.h +199 -0
  49. data/ext/pg_query/include/catalog/indexing.h +366 -0
  50. data/ext/pg_query/include/catalog/namespace.h +188 -0
  51. data/ext/pg_query/include/catalog/objectaccess.h +197 -0
  52. data/ext/pg_query/include/catalog/objectaddress.h +84 -0
  53. data/ext/pg_query/include/catalog/pg_aggregate.h +176 -0
  54. data/ext/pg_query/include/catalog/pg_aggregate_d.h +77 -0
  55. data/ext/pg_query/include/catalog/pg_am.h +60 -0
  56. data/ext/pg_query/include/catalog/pg_am_d.h +45 -0
  57. data/ext/pg_query/include/catalog/pg_attribute.h +204 -0
  58. data/ext/pg_query/include/catalog/pg_attribute_d.h +59 -0
  59. data/ext/pg_query/include/catalog/pg_authid.h +58 -0
  60. data/ext/pg_query/include/catalog/pg_authid_d.h +49 -0
  61. data/ext/pg_query/include/catalog/pg_class.h +200 -0
  62. data/ext/pg_query/include/catalog/pg_class_d.h +103 -0
  63. data/ext/pg_query/include/catalog/pg_collation.h +73 -0
  64. data/ext/pg_query/include/catalog/pg_collation_d.h +45 -0
  65. data/ext/pg_query/include/catalog/pg_constraint.h +247 -0
  66. data/ext/pg_query/include/catalog/pg_constraint_d.h +67 -0
  67. data/ext/pg_query/include/catalog/pg_control.h +250 -0
  68. data/ext/pg_query/include/catalog/pg_conversion.h +72 -0
  69. data/ext/pg_query/include/catalog/pg_conversion_d.h +35 -0
  70. data/ext/pg_query/include/catalog/pg_depend.h +73 -0
  71. data/ext/pg_query/include/catalog/pg_depend_d.h +34 -0
  72. data/ext/pg_query/include/catalog/pg_event_trigger.h +51 -0
  73. data/ext/pg_query/include/catalog/pg_event_trigger_d.h +34 -0
  74. data/ext/pg_query/include/catalog/pg_index.h +80 -0
  75. data/ext/pg_query/include/catalog/pg_index_d.h +56 -0
  76. data/ext/pg_query/include/catalog/pg_language.h +67 -0
  77. data/ext/pg_query/include/catalog/pg_language_d.h +39 -0
  78. data/ext/pg_query/include/catalog/pg_namespace.h +59 -0
  79. data/ext/pg_query/include/catalog/pg_namespace_d.h +34 -0
  80. data/ext/pg_query/include/catalog/pg_opclass.h +85 -0
  81. data/ext/pg_query/include/catalog/pg_opclass_d.h +49 -0
  82. data/ext/pg_query/include/catalog/pg_operator.h +102 -0
  83. data/ext/pg_query/include/catalog/pg_operator_d.h +106 -0
  84. data/ext/pg_query/include/catalog/pg_opfamily.h +60 -0
  85. data/ext/pg_query/include/catalog/pg_opfamily_d.h +47 -0
  86. data/ext/pg_query/include/catalog/pg_partitioned_table.h +63 -0
  87. data/ext/pg_query/include/catalog/pg_partitioned_table_d.h +35 -0
  88. data/ext/pg_query/include/catalog/pg_proc.h +211 -0
  89. data/ext/pg_query/include/catalog/pg_proc_d.h +99 -0
  90. data/ext/pg_query/include/catalog/pg_publication.h +115 -0
  91. data/ext/pg_query/include/catalog/pg_publication_d.h +36 -0
  92. data/ext/pg_query/include/catalog/pg_replication_origin.h +57 -0
  93. data/ext/pg_query/include/catalog/pg_replication_origin_d.h +29 -0
  94. data/ext/pg_query/include/catalog/pg_statistic.h +275 -0
  95. data/ext/pg_query/include/catalog/pg_statistic_d.h +194 -0
  96. data/ext/pg_query/include/catalog/pg_statistic_ext.h +74 -0
  97. data/ext/pg_query/include/catalog/pg_statistic_ext_d.h +40 -0
  98. data/ext/pg_query/include/catalog/pg_transform.h +45 -0
  99. data/ext/pg_query/include/catalog/pg_transform_d.h +32 -0
  100. data/ext/pg_query/include/catalog/pg_trigger.h +137 -0
  101. data/ext/pg_query/include/catalog/pg_trigger_d.h +106 -0
  102. data/ext/pg_query/include/catalog/pg_ts_config.h +50 -0
  103. data/ext/pg_query/include/catalog/pg_ts_config_d.h +32 -0
  104. data/ext/pg_query/include/catalog/pg_ts_dict.h +54 -0
  105. data/ext/pg_query/include/catalog/pg_ts_dict_d.h +33 -0
  106. data/ext/pg_query/include/catalog/pg_ts_parser.h +57 -0
  107. data/ext/pg_query/include/catalog/pg_ts_parser_d.h +35 -0
  108. data/ext/pg_query/include/catalog/pg_ts_template.h +48 -0
  109. data/ext/pg_query/include/catalog/pg_ts_template_d.h +32 -0
  110. data/ext/pg_query/include/catalog/pg_type.h +372 -0
  111. data/ext/pg_query/include/catalog/pg_type_d.h +285 -0
  112. data/ext/pg_query/include/catalog/storage.h +48 -0
  113. data/ext/pg_query/include/commands/async.h +54 -0
  114. data/ext/pg_query/include/commands/dbcommands.h +35 -0
  115. data/ext/pg_query/include/commands/defrem.h +173 -0
  116. data/ext/pg_query/include/commands/event_trigger.h +88 -0
  117. data/ext/pg_query/include/commands/explain.h +127 -0
  118. data/ext/pg_query/include/commands/prepare.h +61 -0
  119. data/ext/pg_query/include/commands/tablespace.h +67 -0
  120. data/ext/pg_query/include/commands/trigger.h +277 -0
  121. data/ext/pg_query/include/commands/user.h +37 -0
  122. data/ext/pg_query/include/commands/vacuum.h +293 -0
  123. data/ext/pg_query/include/commands/variable.h +38 -0
  124. data/ext/pg_query/include/common/file_perm.h +56 -0
  125. data/ext/pg_query/include/common/hashfn.h +104 -0
  126. data/ext/pg_query/include/common/ip.h +37 -0
  127. data/ext/pg_query/include/common/keywords.h +33 -0
  128. data/ext/pg_query/include/common/kwlookup.h +44 -0
  129. data/ext/pg_query/include/common/relpath.h +90 -0
  130. data/ext/pg_query/include/common/string.h +19 -0
  131. data/ext/pg_query/include/common/unicode_combining_table.h +196 -0
  132. data/ext/pg_query/include/datatype/timestamp.h +197 -0
  133. data/ext/pg_query/include/executor/execdesc.h +70 -0
  134. data/ext/pg_query/include/executor/executor.h +614 -0
  135. data/ext/pg_query/include/executor/functions.h +41 -0
  136. data/ext/pg_query/include/executor/instrument.h +101 -0
  137. data/ext/pg_query/include/executor/spi.h +175 -0
  138. data/ext/pg_query/include/executor/tablefunc.h +67 -0
  139. data/ext/pg_query/include/executor/tuptable.h +487 -0
  140. data/ext/pg_query/include/fmgr.h +775 -0
  141. data/ext/pg_query/include/funcapi.h +348 -0
  142. data/ext/pg_query/include/getaddrinfo.h +162 -0
  143. data/ext/pg_query/include/jit/jit.h +105 -0
  144. data/ext/pg_query/include/kwlist_d.h +1072 -0
  145. data/ext/pg_query/include/lib/ilist.h +727 -0
  146. data/ext/pg_query/include/lib/pairingheap.h +102 -0
  147. data/ext/pg_query/include/lib/simplehash.h +1059 -0
  148. data/ext/pg_query/include/lib/stringinfo.h +161 -0
  149. data/ext/pg_query/include/libpq/auth.h +29 -0
  150. data/ext/pg_query/include/libpq/crypt.h +46 -0
  151. data/ext/pg_query/include/libpq/hba.h +140 -0
  152. data/ext/pg_query/include/libpq/libpq-be.h +326 -0
  153. data/ext/pg_query/include/libpq/libpq.h +133 -0
  154. data/ext/pg_query/include/libpq/pqcomm.h +208 -0
  155. data/ext/pg_query/include/libpq/pqformat.h +210 -0
  156. data/ext/pg_query/include/libpq/pqsignal.h +42 -0
  157. data/ext/pg_query/include/mb/pg_wchar.h +672 -0
  158. data/ext/pg_query/include/mb/stringinfo_mb.h +24 -0
  159. data/ext/pg_query/include/miscadmin.h +476 -0
  160. data/ext/pg_query/include/nodes/bitmapset.h +122 -0
  161. data/ext/pg_query/include/nodes/execnodes.h +2520 -0
  162. data/ext/pg_query/include/nodes/extensible.h +160 -0
  163. data/ext/pg_query/include/nodes/lockoptions.h +61 -0
  164. data/ext/pg_query/include/nodes/makefuncs.h +108 -0
  165. data/ext/pg_query/include/nodes/memnodes.h +108 -0
  166. data/ext/pg_query/include/nodes/nodeFuncs.h +162 -0
  167. data/ext/pg_query/include/nodes/nodes.h +842 -0
  168. data/ext/pg_query/include/nodes/params.h +170 -0
  169. data/ext/pg_query/include/nodes/parsenodes.h +3579 -0
  170. data/ext/pg_query/include/nodes/pathnodes.h +2556 -0
  171. data/ext/pg_query/include/nodes/pg_list.h +605 -0
  172. data/ext/pg_query/include/nodes/plannodes.h +1251 -0
  173. data/ext/pg_query/include/nodes/primnodes.h +1541 -0
  174. data/ext/pg_query/include/nodes/print.h +34 -0
  175. data/ext/pg_query/include/nodes/tidbitmap.h +75 -0
  176. data/ext/pg_query/include/nodes/value.h +61 -0
  177. data/ext/pg_query/include/optimizer/cost.h +206 -0
  178. data/ext/pg_query/include/optimizer/geqo.h +88 -0
  179. data/ext/pg_query/include/optimizer/geqo_gene.h +45 -0
  180. data/ext/pg_query/include/optimizer/optimizer.h +199 -0
  181. data/ext/pg_query/include/optimizer/paths.h +249 -0
  182. data/ext/pg_query/include/optimizer/planmain.h +119 -0
  183. data/ext/pg_query/include/parser/analyze.h +49 -0
  184. data/ext/pg_query/include/parser/gram.h +1067 -0
  185. data/ext/pg_query/include/parser/gramparse.h +75 -0
  186. data/ext/pg_query/include/parser/kwlist.h +477 -0
  187. data/ext/pg_query/include/parser/parse_agg.h +68 -0
  188. data/ext/pg_query/include/parser/parse_clause.h +54 -0
  189. data/ext/pg_query/include/parser/parse_coerce.h +97 -0
  190. data/ext/pg_query/include/parser/parse_collate.h +27 -0
  191. data/ext/pg_query/include/parser/parse_expr.h +26 -0
  192. data/ext/pg_query/include/parser/parse_func.h +73 -0
  193. data/ext/pg_query/include/parser/parse_node.h +327 -0
  194. data/ext/pg_query/include/parser/parse_oper.h +67 -0
  195. data/ext/pg_query/include/parser/parse_relation.h +123 -0
  196. data/ext/pg_query/include/parser/parse_target.h +46 -0
  197. data/ext/pg_query/include/parser/parse_type.h +60 -0
  198. data/ext/pg_query/include/parser/parser.h +41 -0
  199. data/ext/pg_query/include/parser/parsetree.h +61 -0
  200. data/ext/pg_query/include/parser/scanner.h +152 -0
  201. data/ext/pg_query/include/parser/scansup.h +30 -0
  202. data/ext/pg_query/include/partitioning/partdefs.h +26 -0
  203. data/ext/pg_query/include/pg_config.h +989 -0
  204. data/ext/pg_query/include/pg_config_ext.h +8 -0
  205. data/ext/pg_query/include/pg_config_manual.h +350 -0
  206. data/ext/pg_query/include/pg_config_os.h +8 -0
  207. data/ext/pg_query/include/pg_getopt.h +56 -0
  208. data/ext/pg_query/include/pg_query.h +121 -0
  209. data/ext/pg_query/include/pg_query_enum_defs.c +2454 -0
  210. data/ext/pg_query/include/pg_query_fingerprint_conds.c +875 -0
  211. data/ext/pg_query/include/pg_query_fingerprint_defs.c +12413 -0
  212. data/ext/pg_query/include/pg_query_json_helper.c +61 -0
  213. data/ext/pg_query/include/pg_query_outfuncs_conds.c +686 -0
  214. data/ext/pg_query/include/pg_query_outfuncs_defs.c +2437 -0
  215. data/ext/pg_query/include/pg_query_readfuncs_conds.c +222 -0
  216. data/ext/pg_query/include/pg_query_readfuncs_defs.c +2878 -0
  217. data/ext/pg_query/include/pg_trace.h +17 -0
  218. data/ext/pg_query/include/pgstat.h +1487 -0
  219. data/ext/pg_query/include/pgtime.h +84 -0
  220. data/ext/pg_query/include/pl_gram.h +385 -0
  221. data/ext/pg_query/include/pl_reserved_kwlist.h +52 -0
  222. data/ext/pg_query/include/pl_reserved_kwlist_d.h +114 -0
  223. data/ext/pg_query/include/pl_unreserved_kwlist.h +112 -0
  224. data/ext/pg_query/include/pl_unreserved_kwlist_d.h +246 -0
  225. data/ext/pg_query/include/plerrcodes.h +990 -0
  226. data/ext/pg_query/include/plpgsql.h +1347 -0
  227. data/ext/pg_query/include/port.h +524 -0
  228. data/ext/pg_query/include/port/atomics.h +524 -0
  229. data/ext/pg_query/include/port/atomics/arch-arm.h +26 -0
  230. data/ext/pg_query/include/port/atomics/arch-ppc.h +254 -0
  231. data/ext/pg_query/include/port/atomics/arch-x86.h +252 -0
  232. data/ext/pg_query/include/port/atomics/fallback.h +170 -0
  233. data/ext/pg_query/include/port/atomics/generic-gcc.h +286 -0
  234. data/ext/pg_query/include/port/atomics/generic.h +401 -0
  235. data/ext/pg_query/include/port/pg_bitutils.h +226 -0
  236. data/ext/pg_query/include/port/pg_bswap.h +161 -0
  237. data/ext/pg_query/include/port/pg_crc32c.h +101 -0
  238. data/ext/pg_query/include/portability/instr_time.h +256 -0
  239. data/ext/pg_query/include/postgres.h +764 -0
  240. data/ext/pg_query/include/postgres_ext.h +74 -0
  241. data/ext/pg_query/include/postmaster/autovacuum.h +83 -0
  242. data/ext/pg_query/include/postmaster/bgworker.h +161 -0
  243. data/ext/pg_query/include/postmaster/bgworker_internals.h +64 -0
  244. data/ext/pg_query/include/postmaster/bgwriter.h +45 -0
  245. data/ext/pg_query/include/postmaster/fork_process.h +17 -0
  246. data/ext/pg_query/include/postmaster/interrupt.h +32 -0
  247. data/ext/pg_query/include/postmaster/pgarch.h +39 -0
  248. data/ext/pg_query/include/postmaster/postmaster.h +77 -0
  249. data/ext/pg_query/include/postmaster/syslogger.h +98 -0
  250. data/ext/pg_query/include/postmaster/walwriter.h +21 -0
  251. data/ext/pg_query/include/protobuf-c.h +1106 -0
  252. data/ext/pg_query/include/protobuf-c/protobuf-c.h +1106 -0
  253. data/ext/pg_query/include/protobuf/pg_query.pb-c.h +10846 -0
  254. data/ext/pg_query/include/protobuf/pg_query.pb.h +124718 -0
  255. data/ext/pg_query/include/regex/regex.h +184 -0
  256. data/ext/pg_query/include/replication/logicallauncher.h +31 -0
  257. data/ext/pg_query/include/replication/logicalproto.h +110 -0
  258. data/ext/pg_query/include/replication/logicalworker.h +19 -0
  259. data/ext/pg_query/include/replication/origin.h +73 -0
  260. data/ext/pg_query/include/replication/reorderbuffer.h +467 -0
  261. data/ext/pg_query/include/replication/slot.h +219 -0
  262. data/ext/pg_query/include/replication/syncrep.h +115 -0
  263. data/ext/pg_query/include/replication/walreceiver.h +340 -0
  264. data/ext/pg_query/include/replication/walsender.h +74 -0
  265. data/ext/pg_query/include/rewrite/prs2lock.h +46 -0
  266. data/ext/pg_query/include/rewrite/rewriteHandler.h +40 -0
  267. data/ext/pg_query/include/rewrite/rewriteManip.h +87 -0
  268. data/ext/pg_query/include/rewrite/rewriteSupport.h +26 -0
  269. data/ext/pg_query/include/storage/backendid.h +37 -0
  270. data/ext/pg_query/include/storage/block.h +121 -0
  271. data/ext/pg_query/include/storage/buf.h +46 -0
  272. data/ext/pg_query/include/storage/bufmgr.h +292 -0
  273. data/ext/pg_query/include/storage/bufpage.h +459 -0
  274. data/ext/pg_query/include/storage/condition_variable.h +62 -0
  275. data/ext/pg_query/include/storage/dsm.h +61 -0
  276. data/ext/pg_query/include/storage/dsm_impl.h +75 -0
  277. data/ext/pg_query/include/storage/fd.h +168 -0
  278. data/ext/pg_query/include/storage/ipc.h +81 -0
  279. data/ext/pg_query/include/storage/item.h +19 -0
  280. data/ext/pg_query/include/storage/itemid.h +184 -0
  281. data/ext/pg_query/include/storage/itemptr.h +206 -0
  282. data/ext/pg_query/include/storage/large_object.h +100 -0
  283. data/ext/pg_query/include/storage/latch.h +190 -0
  284. data/ext/pg_query/include/storage/lmgr.h +114 -0
  285. data/ext/pg_query/include/storage/lock.h +612 -0
  286. data/ext/pg_query/include/storage/lockdefs.h +59 -0
  287. data/ext/pg_query/include/storage/lwlock.h +232 -0
  288. data/ext/pg_query/include/storage/lwlocknames.h +51 -0
  289. data/ext/pg_query/include/storage/off.h +57 -0
  290. data/ext/pg_query/include/storage/pg_sema.h +61 -0
  291. data/ext/pg_query/include/storage/pg_shmem.h +90 -0
  292. data/ext/pg_query/include/storage/pmsignal.h +94 -0
  293. data/ext/pg_query/include/storage/predicate.h +87 -0
  294. data/ext/pg_query/include/storage/proc.h +333 -0
  295. data/ext/pg_query/include/storage/proclist_types.h +51 -0
  296. data/ext/pg_query/include/storage/procsignal.h +75 -0
  297. data/ext/pg_query/include/storage/relfilenode.h +99 -0
  298. data/ext/pg_query/include/storage/s_lock.h +1047 -0
  299. data/ext/pg_query/include/storage/sharedfileset.h +45 -0
  300. data/ext/pg_query/include/storage/shm_mq.h +85 -0
  301. data/ext/pg_query/include/storage/shm_toc.h +58 -0
  302. data/ext/pg_query/include/storage/shmem.h +81 -0
  303. data/ext/pg_query/include/storage/sinval.h +153 -0
  304. data/ext/pg_query/include/storage/sinvaladt.h +43 -0
  305. data/ext/pg_query/include/storage/smgr.h +109 -0
  306. data/ext/pg_query/include/storage/spin.h +77 -0
  307. data/ext/pg_query/include/storage/standby.h +91 -0
  308. data/ext/pg_query/include/storage/standbydefs.h +74 -0
  309. data/ext/pg_query/include/storage/sync.h +62 -0
  310. data/ext/pg_query/include/tcop/cmdtag.h +58 -0
  311. data/ext/pg_query/include/tcop/cmdtaglist.h +217 -0
  312. data/ext/pg_query/include/tcop/deparse_utility.h +108 -0
  313. data/ext/pg_query/include/tcop/dest.h +149 -0
  314. data/ext/pg_query/include/tcop/fastpath.h +21 -0
  315. data/ext/pg_query/include/tcop/pquery.h +45 -0
  316. data/ext/pg_query/include/tcop/tcopprot.h +89 -0
  317. data/ext/pg_query/include/tcop/utility.h +108 -0
  318. data/ext/pg_query/include/tsearch/ts_cache.h +98 -0
  319. data/ext/pg_query/include/utils/acl.h +312 -0
  320. data/ext/pg_query/include/utils/aclchk_internal.h +45 -0
  321. data/ext/pg_query/include/utils/array.h +458 -0
  322. data/ext/pg_query/include/utils/builtins.h +127 -0
  323. data/ext/pg_query/include/utils/bytea.h +27 -0
  324. data/ext/pg_query/include/utils/catcache.h +231 -0
  325. data/ext/pg_query/include/utils/date.h +90 -0
  326. data/ext/pg_query/include/utils/datetime.h +343 -0
  327. data/ext/pg_query/include/utils/datum.h +68 -0
  328. data/ext/pg_query/include/utils/dsa.h +123 -0
  329. data/ext/pg_query/include/utils/dynahash.h +19 -0
  330. data/ext/pg_query/include/utils/elog.h +439 -0
  331. data/ext/pg_query/include/utils/errcodes.h +352 -0
  332. data/ext/pg_query/include/utils/expandeddatum.h +159 -0
  333. data/ext/pg_query/include/utils/expandedrecord.h +231 -0
  334. data/ext/pg_query/include/utils/float.h +356 -0
  335. data/ext/pg_query/include/utils/fmgroids.h +2657 -0
  336. data/ext/pg_query/include/utils/fmgrprotos.h +2646 -0
  337. data/ext/pg_query/include/utils/fmgrtab.h +48 -0
  338. data/ext/pg_query/include/utils/guc.h +443 -0
  339. data/ext/pg_query/include/utils/guc_tables.h +272 -0
  340. data/ext/pg_query/include/utils/hsearch.h +149 -0
  341. data/ext/pg_query/include/utils/inval.h +64 -0
  342. data/ext/pg_query/include/utils/lsyscache.h +197 -0
  343. data/ext/pg_query/include/utils/memdebug.h +82 -0
  344. data/ext/pg_query/include/utils/memutils.h +225 -0
  345. data/ext/pg_query/include/utils/numeric.h +76 -0
  346. data/ext/pg_query/include/utils/palloc.h +136 -0
  347. data/ext/pg_query/include/utils/partcache.h +102 -0
  348. data/ext/pg_query/include/utils/pg_locale.h +119 -0
  349. data/ext/pg_query/include/utils/pg_lsn.h +29 -0
  350. data/ext/pg_query/include/utils/pidfile.h +56 -0
  351. data/ext/pg_query/include/utils/plancache.h +235 -0
  352. data/ext/pg_query/include/utils/portal.h +241 -0
  353. data/ext/pg_query/include/utils/probes.h +114 -0
  354. data/ext/pg_query/include/utils/ps_status.h +25 -0
  355. data/ext/pg_query/include/utils/queryenvironment.h +74 -0
  356. data/ext/pg_query/include/utils/regproc.h +28 -0
  357. data/ext/pg_query/include/utils/rel.h +644 -0
  358. data/ext/pg_query/include/utils/relcache.h +151 -0
  359. data/ext/pg_query/include/utils/reltrigger.h +81 -0
  360. data/ext/pg_query/include/utils/resowner.h +86 -0
  361. data/ext/pg_query/include/utils/rls.h +50 -0
  362. data/ext/pg_query/include/utils/ruleutils.h +44 -0
  363. data/ext/pg_query/include/utils/sharedtuplestore.h +61 -0
  364. data/ext/pg_query/include/utils/snapmgr.h +158 -0
  365. data/ext/pg_query/include/utils/snapshot.h +206 -0
  366. data/ext/pg_query/include/utils/sortsupport.h +276 -0
  367. data/ext/pg_query/include/utils/syscache.h +219 -0
  368. data/ext/pg_query/include/utils/timeout.h +88 -0
  369. data/ext/pg_query/include/utils/timestamp.h +116 -0
  370. data/ext/pg_query/include/utils/tuplesort.h +277 -0
  371. data/ext/pg_query/include/utils/tuplestore.h +91 -0
  372. data/ext/pg_query/include/utils/typcache.h +202 -0
  373. data/ext/pg_query/include/utils/tzparser.h +39 -0
  374. data/ext/pg_query/include/utils/varlena.h +39 -0
  375. data/ext/pg_query/include/utils/xml.h +84 -0
  376. data/ext/pg_query/include/xxhash.h +5445 -0
  377. data/ext/pg_query/include/xxhash/xxhash.h +5445 -0
  378. data/ext/pg_query/pg_query.c +104 -0
  379. data/ext/pg_query/pg_query.pb-c.c +37628 -0
  380. data/ext/pg_query/pg_query_deparse.c +9959 -0
  381. data/ext/pg_query/pg_query_fingerprint.c +295 -0
  382. data/ext/pg_query/pg_query_fingerprint.h +8 -0
  383. data/ext/pg_query/pg_query_internal.h +24 -0
  384. data/ext/pg_query/pg_query_json_plpgsql.c +738 -0
  385. data/ext/pg_query/pg_query_json_plpgsql.h +9 -0
  386. data/ext/pg_query/pg_query_normalize.c +439 -0
  387. data/ext/pg_query/pg_query_outfuncs.h +10 -0
  388. data/ext/pg_query/pg_query_outfuncs_json.c +297 -0
  389. data/ext/pg_query/pg_query_outfuncs_protobuf.c +237 -0
  390. data/ext/pg_query/pg_query_parse.c +148 -0
  391. data/ext/pg_query/pg_query_parse_plpgsql.c +460 -0
  392. data/ext/pg_query/pg_query_readfuncs.h +11 -0
  393. data/ext/pg_query/pg_query_readfuncs_protobuf.c +142 -0
  394. data/ext/pg_query/pg_query_ruby.c +108 -12
  395. data/ext/pg_query/pg_query_scan.c +173 -0
  396. data/ext/pg_query/pg_query_split.c +221 -0
  397. data/ext/pg_query/protobuf-c.c +3660 -0
  398. data/ext/pg_query/src_backend_catalog_namespace.c +1051 -0
  399. data/ext/pg_query/src_backend_catalog_pg_proc.c +142 -0
  400. data/ext/pg_query/src_backend_commands_define.c +117 -0
  401. data/ext/pg_query/src_backend_libpq_pqcomm.c +651 -0
  402. data/ext/pg_query/src_backend_nodes_bitmapset.c +513 -0
  403. data/ext/pg_query/src_backend_nodes_copyfuncs.c +6013 -0
  404. data/ext/pg_query/src_backend_nodes_equalfuncs.c +4003 -0
  405. data/ext/pg_query/src_backend_nodes_extensible.c +99 -0
  406. data/ext/pg_query/src_backend_nodes_list.c +922 -0
  407. data/ext/pg_query/src_backend_nodes_makefuncs.c +417 -0
  408. data/ext/pg_query/src_backend_nodes_nodeFuncs.c +1363 -0
  409. data/ext/pg_query/src_backend_nodes_value.c +84 -0
  410. data/ext/pg_query/src_backend_parser_gram.c +47456 -0
  411. data/ext/pg_query/src_backend_parser_parse_expr.c +313 -0
  412. data/ext/pg_query/src_backend_parser_parser.c +497 -0
  413. data/ext/pg_query/src_backend_parser_scan.c +7091 -0
  414. data/ext/pg_query/src_backend_parser_scansup.c +160 -0
  415. data/ext/pg_query/src_backend_postmaster_postmaster.c +2230 -0
  416. data/ext/pg_query/src_backend_storage_ipc_ipc.c +192 -0
  417. data/ext/pg_query/src_backend_storage_lmgr_s_lock.c +370 -0
  418. data/ext/pg_query/src_backend_tcop_postgres.c +776 -0
  419. data/ext/pg_query/src_backend_utils_adt_datum.c +326 -0
  420. data/ext/pg_query/src_backend_utils_adt_expandeddatum.c +98 -0
  421. data/ext/pg_query/src_backend_utils_adt_format_type.c +136 -0
  422. data/ext/pg_query/src_backend_utils_adt_ruleutils.c +1683 -0
  423. data/ext/pg_query/src_backend_utils_error_assert.c +74 -0
  424. data/ext/pg_query/src_backend_utils_error_elog.c +1748 -0
  425. data/ext/pg_query/src_backend_utils_fmgr_fmgr.c +570 -0
  426. data/ext/pg_query/src_backend_utils_hash_dynahash.c +1086 -0
  427. data/ext/pg_query/src_backend_utils_init_globals.c +168 -0
  428. data/ext/pg_query/src_backend_utils_mb_mbutils.c +839 -0
  429. data/ext/pg_query/src_backend_utils_misc_guc.c +1831 -0
  430. data/ext/pg_query/src_backend_utils_mmgr_aset.c +1560 -0
  431. data/ext/pg_query/src_backend_utils_mmgr_mcxt.c +1006 -0
  432. data/ext/pg_query/src_common_encnames.c +158 -0
  433. data/ext/pg_query/src_common_keywords.c +39 -0
  434. data/ext/pg_query/src_common_kwlist_d.h +1081 -0
  435. data/ext/pg_query/src_common_kwlookup.c +91 -0
  436. data/ext/pg_query/src_common_psprintf.c +158 -0
  437. data/ext/pg_query/src_common_string.c +86 -0
  438. data/ext/pg_query/src_common_stringinfo.c +336 -0
  439. data/ext/pg_query/src_common_wchar.c +1651 -0
  440. data/ext/pg_query/src_pl_plpgsql_src_pl_comp.c +1133 -0
  441. data/ext/pg_query/src_pl_plpgsql_src_pl_funcs.c +877 -0
  442. data/ext/pg_query/src_pl_plpgsql_src_pl_gram.c +6533 -0
  443. data/ext/pg_query/src_pl_plpgsql_src_pl_handler.c +107 -0
  444. data/ext/pg_query/src_pl_plpgsql_src_pl_reserved_kwlist_d.h +123 -0
  445. data/ext/pg_query/src_pl_plpgsql_src_pl_scanner.c +671 -0
  446. data/ext/pg_query/src_pl_plpgsql_src_pl_unreserved_kwlist_d.h +255 -0
  447. data/ext/pg_query/src_port_erand48.c +127 -0
  448. data/ext/pg_query/src_port_pg_bitutils.c +246 -0
  449. data/ext/pg_query/src_port_pgsleep.c +69 -0
  450. data/ext/pg_query/src_port_pgstrcasecmp.c +83 -0
  451. data/ext/pg_query/src_port_qsort.c +240 -0
  452. data/ext/pg_query/src_port_random.c +31 -0
  453. data/ext/pg_query/src_port_snprintf.c +1449 -0
  454. data/ext/pg_query/src_port_strerror.c +324 -0
  455. data/ext/pg_query/src_port_strnlen.c +39 -0
  456. data/ext/pg_query/xxhash.c +43 -0
  457. data/lib/pg_query.rb +7 -4
  458. data/lib/pg_query/constants.rb +21 -0
  459. data/lib/pg_query/deparse.rb +15 -1673
  460. data/lib/pg_query/filter_columns.rb +88 -85
  461. data/lib/pg_query/fingerprint.rb +122 -87
  462. data/lib/pg_query/json_field_names.rb +1402 -0
  463. data/lib/pg_query/node.rb +31 -0
  464. data/lib/pg_query/param_refs.rb +42 -37
  465. data/lib/pg_query/parse.rb +220 -203
  466. data/lib/pg_query/parse_error.rb +1 -1
  467. data/lib/pg_query/pg_query_pb.rb +3211 -0
  468. data/lib/pg_query/scan.rb +23 -0
  469. data/lib/pg_query/treewalker.rb +24 -40
  470. data/lib/pg_query/truncate.rb +71 -42
  471. data/lib/pg_query/version.rb +2 -2
  472. metadata +472 -11
  473. data/ext/pg_query/pg_query_ruby.h +0 -10
  474. data/lib/pg_query/deep_dup.rb +0 -16
  475. data/lib/pg_query/deparse/alter_table.rb +0 -42
  476. data/lib/pg_query/deparse/interval.rb +0 -105
  477. data/lib/pg_query/deparse/keywords.rb +0 -159
  478. data/lib/pg_query/deparse/rename.rb +0 -41
  479. data/lib/pg_query/legacy_parsetree.rb +0 -109
  480. data/lib/pg_query/node_types.rb +0 -297
@@ -1,1680 +1,22 @@
1
- require_relative 'deparse/alter_table'
2
- require_relative 'deparse/rename'
3
- require_relative 'deparse/interval'
4
- require_relative 'deparse/keywords'
1
+ module PgQuery
2
+ class ParserResult
3
+ def deparse
4
+ PgQuery.deparse(@tree)
5
+ end
6
+ end
5
7
 
6
- class PgQuery
7
8
  # Reconstruct all of the parsed queries into their original form
8
- def deparse(tree = @tree)
9
- tree.map do |item|
10
- Deparse.from(item)
11
- end.join('; ')
9
+ def self.deparse(tree)
10
+ PgQuery.deparse_protobuf(PgQuery::ParseResult.encode(tree)).force_encoding('UTF-8')
12
11
  end
13
12
 
14
- # rubocop:disable Metrics/ModuleLength
15
- module Deparse
16
- extend self
17
-
18
- # Given one element of the PgQuery#parsetree reconstruct it back into the
19
- # original query.
20
- def from(item)
21
- deparse_item(item)
22
- end
23
-
24
- private
25
-
26
- def deparse_item(item, context = nil) # rubocop:disable Metrics/CyclomaticComplexity
27
- return if item.nil?
28
- return item if item.is_a?(Integer)
29
-
30
- type = item.keys[0]
31
- node = item.values[0]
32
-
33
- case type
34
- when A_EXPR
35
- case node['kind']
36
- when AEXPR_OP
37
- deparse_aexpr(node, context)
38
- when AEXPR_OP_ALL
39
- deparse_aexpr_all(node)
40
- when AEXPR_OP_ANY
41
- deparse_aexpr_any(node)
42
- when AEXPR_IN
43
- deparse_aexpr_in(node)
44
- when AEXPR_ILIKE
45
- deparse_aexpr_ilike(node)
46
- when CONSTR_TYPE_FOREIGN
47
- deparse_aexpr_like(node)
48
- when AEXPR_BETWEEN, AEXPR_NOT_BETWEEN, AEXPR_BETWEEN_SYM, AEXPR_NOT_BETWEEN_SYM
49
- deparse_aexpr_between(node)
50
- when AEXPR_NULLIF
51
- deparse_aexpr_nullif(node)
52
- else
53
- raise format("Can't deparse: %s: %s", type, node.inspect)
54
- end
55
- when ACCESS_PRIV
56
- deparse_access_priv(node)
57
- when ALIAS
58
- deparse_alias(node)
59
- when ALTER_TABLE_STMT
60
- deparse_alter_table(node)
61
- when ALTER_TABLE_CMD
62
- deparse_alter_table_cmd(node)
63
- when A_ARRAY_EXPR
64
- deparse_a_arrayexp(node)
65
- when A_CONST
66
- deparse_a_const(node)
67
- when A_INDICES
68
- deparse_a_indices(node)
69
- when A_INDIRECTION
70
- deparse_a_indirection(node)
71
- when A_STAR
72
- deparse_a_star(node)
73
- when A_TRUNCATED
74
- '...' # pg_query internal
75
- when BOOL_EXPR
76
- case node['boolop']
77
- when BOOL_EXPR_AND
78
- deparse_bool_expr_and(node)
79
- when BOOL_EXPR_OR
80
- deparse_bool_expr_or(node)
81
- when BOOL_EXPR_NOT
82
- deparse_bool_expr_not(node)
83
- end
84
- when BOOLEAN_TEST
85
- deparse_boolean_test(node)
86
- when CASE_EXPR
87
- deparse_case(node)
88
- when COALESCE_EXPR
89
- deparse_coalesce(node)
90
- when COLLATE_CLAUSE
91
- deparse_collate(node)
92
- when COLUMN_DEF
93
- deparse_columndef(node)
94
- when COLUMN_REF
95
- deparse_columnref(node, context)
96
- when COMMON_TABLE_EXPR
97
- deparse_cte(node)
98
- when COMPOSITE_TYPE_STMT
99
- deparse_composite_type(node)
100
- when CONSTRAINT
101
- deparse_constraint(node)
102
- when COPY_STMT
103
- deparse_copy(node)
104
- when CREATE_CAST_STMT
105
- deparse_create_cast(node)
106
- when CREATE_DOMAIN_STMT
107
- deparse_create_domain(node)
108
- when CREATE_ENUM_STMT
109
- deparse_create_enum(node)
110
- when CREATE_FUNCTION_STMT
111
- deparse_create_function(node)
112
- when CREATE_RANGE_STMT
113
- deparse_create_range(node)
114
- when CREATE_SCHEMA_STMT
115
- deparse_create_schema(node)
116
- when CREATE_STMT
117
- deparse_create_table(node)
118
- when CREATE_TABLE_AS_STMT
119
- deparse_create_table_as(node)
120
- when INTO_CLAUSE
121
- deparse_into_clause(node)
122
- when DEF_ELEM
123
- deparse_defelem(node)
124
- when DEFINE_STMT
125
- deparse_define_stmt(node)
126
- when DELETE_STMT
127
- deparse_delete_from(node)
128
- when DISCARD_STMT
129
- deparse_discard(node)
130
- when DROP_ROLE
131
- deparse_drop_role(node)
132
- when DROP_STMT
133
- deparse_drop(node)
134
- when DROP_SUBSCRIPTION
135
- deparse_drop_subscription(node)
136
- when DROP_TABLESPACE
137
- deparse_drop_tablespace(node)
138
- when EXPLAIN_STMT
139
- deparse_explain(node)
140
- when EXECUTE_STMT
141
- deparse_execute(node)
142
- when FUNC_CALL
143
- deparse_funccall(node)
144
- when FUNCTION_PARAMETER
145
- deparse_functionparameter(node)
146
- when GRANT_ROLE_STMT
147
- deparse_grant_role(node)
148
- when GRANT_STMT
149
- deparse_grant(node)
150
- when INSERT_STMT
151
- deparse_insert_into(node)
152
- when JOIN_EXPR
153
- deparse_joinexpr(node)
154
- when LOCK_STMT
155
- deparse_lock(node)
156
- when LOCKING_CLAUSE
157
- deparse_lockingclause(node)
158
- when NULL_TEST
159
- deparse_nulltest(node)
160
- when OBJECT_WITH_ARGS
161
- deparse_object_with_args(node)
162
- when PARAM_REF
163
- deparse_paramref(node)
164
- when PREPARE_STMT
165
- deparse_prepare(node)
166
- when RANGE_FUNCTION
167
- deparse_range_function(node)
168
- when RANGE_SUBSELECT
169
- deparse_rangesubselect(node)
170
- when RANGE_VAR
171
- deparse_rangevar(node)
172
- when RAW_STMT
173
- deparse_raw_stmt(node)
174
- when RENAME_STMT
175
- deparse_renamestmt(node)
176
- when RES_TARGET
177
- deparse_restarget(node, context)
178
- when ROLE_SPEC
179
- deparse_role_spec(node)
180
- when ROW_EXPR
181
- deparse_row(node)
182
- when SELECT_STMT
183
- deparse_select(node)
184
- when SQL_VALUE_FUNCTION
185
- deparse_sql_value_function(node)
186
- when SORT_BY
187
- deparse_sortby(node)
188
- when SUB_LINK
189
- deparse_sublink(node)
190
- when TRANSACTION_STMT
191
- deparse_transaction(node)
192
- when TYPE_CAST
193
- deparse_typecast(node)
194
- when TYPE_NAME
195
- deparse_typename(node)
196
- when UPDATE_STMT
197
- deparse_update(node)
198
- when CASE_WHEN
199
- deparse_when(node)
200
- when WINDOW_DEF
201
- deparse_windowdef(node)
202
- when WITH_CLAUSE
203
- deparse_with_clause(node)
204
- when VIEW_STMT
205
- deparse_viewstmt(node)
206
- when VARIABLE_SET_STMT
207
- deparse_variable_set_stmt(node)
208
- when VACUUM_STMT
209
- deparse_vacuum_stmt(node)
210
- when DO_STMT
211
- deparse_do_stmt(node)
212
- when SET_TO_DEFAULT
213
- 'DEFAULT'
214
- when STRING
215
- if context == A_CONST
216
- format("'%s'", node['str'].gsub("'", "''"))
217
- elsif [FUNC_CALL, TYPE_NAME, :operator, :defname_as].include?(context)
218
- node['str']
219
- elsif context == :excluded
220
- node['str'].casecmp('EXCLUDED').zero? ? node['str'].upcase : deparse_identifier(node['str'], escape_always: true)
221
- else
222
- deparse_identifier(node['str'], escape_always: true)
223
- end
224
- when INTEGER
225
- node['ival'].to_s
226
- when FLOAT
227
- node['str']
228
- when NULL
229
- 'NULL'
230
- else
231
- raise format("Can't deparse: %s: %s", type, node.inspect)
232
- end
233
- end
234
-
235
- def deparse_item_list(nodes, context = nil)
236
- nodes.map { |n| deparse_item(n, context) }
237
- end
238
-
239
- def deparse_identifier(ident, escape_always: false)
240
- return if ident.nil?
241
- if escape_always || !ident[/^\w+$/] || KEYWORDS.include?(ident.upcase)
242
- format('"%s"', ident.gsub('"', '""'))
243
- else
244
- ident
245
- end
246
- end
247
-
248
- def deparse_rangevar(node)
249
- output = []
250
- output << 'ONLY' unless node['inh']
251
- schema = node['schemaname'] ? '"' + node['schemaname'] + '".' : ''
252
- output << schema + '"' + node['relname'] + '"'
253
- output << deparse_item(node['alias']) if node['alias']
254
- output.join(' ')
255
- end
256
-
257
- def deparse_raw_stmt(node)
258
- deparse_item(node[STMT_FIELD])
259
- end
260
-
261
- def deparse_renamestmt_decision(node, type)
262
- if node[type]
263
- if node[type].is_a?(String)
264
- deparse_identifier(node[type])
265
- elsif node[type].is_a?(Array)
266
- deparse_item_list(node[type])
267
- elsif node[type].is_a?(Object)
268
- deparse_item(node[type])
269
- end
270
- else
271
- type
272
- end
273
- end
274
-
275
- def deparse_renamestmt(node)
276
- output = []
277
- output << 'ALTER'
278
- command, type, options, type2, options2 = Rename.commands(node)
279
-
280
- output << command if command
281
- output << deparse_renamestmt_decision(node, type)
282
- output << options if options
283
- output << deparse_renamestmt_decision(node, type2) if type2
284
- output << deparse_renamestmt_decision(node, options2) if options2
285
- output << 'TO'
286
- output << deparse_identifier(node['newname'], escape_always: true)
287
- output.join(' ')
288
- end
289
-
290
- def deparse_columnref(node, context = false)
291
- node['fields'].map do |field|
292
- field.is_a?(String) ? '"' + field + '"' : deparse_item(field, context)
293
- end.join('.')
294
- end
295
-
296
- def deparse_a_arrayexp(node)
297
- 'ARRAY[' + (node['elements'] || []).map do |element|
298
- deparse_item(element)
299
- end.join(', ') + ']'
300
- end
301
-
302
- def deparse_a_const(node)
303
- deparse_item(node['val'], A_CONST)
304
- end
305
-
306
- def deparse_a_star(_node)
307
- '*'
308
- end
309
-
310
- def deparse_a_indirection(node)
311
- output = []
312
- arg = deparse_item(node['arg'])
313
- array_indirection = []
314
- if node['indirection']
315
- array_indirection = node['indirection'].select { |a| a.key?(A_INDICES) }
316
- end
317
- output << if node['arg'].key?(FUNC_CALL) || node['arg'].key?(A_EXPR) || (node['arg'].key?(SUB_LINK) && array_indirection.count.zero?)
318
- "(#{arg})."
319
- else
320
- arg
321
- end
322
- node['indirection'].each do |subnode|
323
- output << deparse_item(subnode)
324
- end
325
- output.join
326
- end
327
-
328
- def deparse_a_indices(node)
329
- format('[%s]', deparse_item(node['uidx']))
330
- end
331
-
332
- def deparse_alias(node)
333
- name = node['aliasname']
334
- if node['colnames']
335
- name + '(' + deparse_item_list(node['colnames']).join(', ') + ')'
336
- else
337
- deparse_identifier(name)
338
- end
339
- end
340
-
341
- def deparse_alter_table(node)
342
- output = []
343
- output << 'ALTER'
344
-
345
- output << 'TABLE' if node['relkind'] == OBJECT_TYPE_TABLE
346
- output << 'VIEW' if node['relkind'] == OBJECT_TYPE_VIEW
347
-
348
- output << deparse_item(node['relation'])
349
-
350
- output << node['cmds'].map do |item|
351
- deparse_item(item)
352
- end.join(', ')
353
-
354
- output.join(' ')
355
- end
356
-
357
- def deparse_alter_table_cmd(node)
358
- command, options = AlterTable.commands(node)
359
-
360
- output = []
361
- output << command if command
362
- output << 'IF EXISTS' if node['missing_ok']
363
- output << node['name']
364
- output << options if options
365
- output << deparse_item(node['def']) if node['def']
366
- output << 'CASCADE' if node['behavior'] == 1
367
-
368
- output.compact.join(' ')
369
- end
370
-
371
- def deparse_object_with_args(node)
372
- output = []
373
- output << deparse_item_list(node['objname']).join('.')
374
- unless node['args_unspecified']
375
- args = node.fetch('objargs', []).map(&method(:deparse_item)).join(', ')
376
- output << "(#{args})"
377
- end
378
- output.join('')
379
- end
380
-
381
- def deparse_paramref(node)
382
- if node['number'].nil?
383
- '?'
384
- else
385
- format('$%d', node['number'])
386
- end
387
- end
388
-
389
- def deparse_prepare(node)
390
- output = ['PREPARE']
391
- output << deparse_identifier(node['name'])
392
- output << "(#{deparse_item_list(node['argtypes']).join(', ')})" if node['argtypes']
393
- output << 'AS'
394
- output << deparse_item(node['query'])
395
- output.join(' ')
396
- end
397
-
398
- def deparse_restarget(node, context)
399
- if context == :select
400
- [deparse_item(node['val']), deparse_identifier(node['name'])].compact.join(' AS ')
401
- elsif context == :update
402
- [deparse_identifier(node['name']), deparse_item(node['val'])].compact.join(' = ')
403
- elsif context == :excluded
404
- [deparse_identifier(node['name'], escape_always: true), deparse_item(node['val'], context)].compact.join(' = ')
405
- elsif node['val'].nil?
406
- node['name']
407
- else
408
- raise format("Can't deparse %s in context %s", node.inspect, context)
409
- end
410
- end
411
-
412
- def deparse_funccall(node)
413
- output = []
414
-
415
- # SUM(a, b)
416
- args = Array(node['args']).map { |arg| deparse_item(arg) }
417
- # COUNT(*)
418
- args << '*' if node['agg_star']
419
-
420
- name = (node['funcname'].map { |n| deparse_item(n, FUNC_CALL) }).join('.')
421
- if name == 'pg_catalog.overlay'
422
- # Note that this is a bit odd, but "OVERLAY" is a keyword on its own merit, and only accepts the
423
- # keyword parameter style when its called as a keyword, not as a regular function (i.e. pg_catalog.overlay)
424
- output << format('OVERLAY(%s PLACING %s FROM %s FOR %s)', args[0], args[1], args[2], args[3])
425
- else
426
- distinct = node['agg_distinct'] ? 'DISTINCT ' : ''
427
- output << format('%s(%s%s)', name, distinct, args.join(', '))
428
- output << format('FILTER (WHERE %s)', deparse_item(node['agg_filter'])) if node['agg_filter']
429
- output << format('OVER %s', deparse_item(node['over'])) if node['over']
430
- end
431
-
432
- output.join(' ')
433
- end
434
-
435
- def deparse_windowdef(node)
436
- return deparse_identifier(node['name']) if node['name']
437
-
438
- output = []
439
-
440
- if node['partitionClause']
441
- output << 'PARTITION BY'
442
- output << node['partitionClause'].map do |item|
443
- deparse_item(item)
444
- end.join(', ')
445
- end
446
-
447
- if node['orderClause']
448
- output << 'ORDER BY'
449
- output << node['orderClause'].map do |item|
450
- deparse_item(item)
451
- end.join(', ')
452
- end
453
-
454
- format('(%s)', output.join(' '))
455
- end
456
-
457
- def deparse_functionparameter(node)
458
- deparse_item(node['argType'])
459
- end
460
-
461
- def deparse_grant_role(node)
462
- output = []
463
- output << ['GRANT'] if node['is_grant']
464
- output << ['REVOKE'] unless node['is_grant']
465
- output << node['granted_roles'].map(&method(:deparse_item)).join(', ')
466
- output << ['TO'] if node['is_grant']
467
- output << ['FROM'] unless node['is_grant']
468
- output << node['grantee_roles'].map(&method(:deparse_item)).join(', ')
469
- output << 'WITH ADMIN OPTION' if node['admin_opt']
470
- output.join(' ')
471
- end
472
-
473
- def deparse_grant(node) # rubocop:disable Metrics/CyclomaticComplexity
474
- objtype, allow_all = deparse_grant_objtype(node)
475
- output = []
476
- output << ['GRANT'] if node['is_grant']
477
- output << ['REVOKE'] unless node['is_grant']
478
- output << if node.key?('privileges')
479
- node['privileges'].map(&method(:deparse_item)).join(', ')
480
- else
481
- 'ALL'
482
- end
483
- output << 'ON'
484
- objects = node['objects']
485
- objects = objects[0] if %w[DOMAIN TYPE].include?(objtype)
486
- objects = objects.map do |object|
487
- deparsed = deparse_item(object)
488
- if object.key?(RANGE_VAR) || object.key?(OBJECT_WITH_ARGS) || !allow_all
489
- objtype == 'TABLE' ? deparsed : "#{objtype} #{deparsed}"
490
- else
491
- "ALL #{objtype}S IN SCHEMA #{deparsed}"
492
- end
493
- end
494
- output << objects.join(', ')
495
- output << ['TO'] if node['is_grant']
496
- output << ['FROM'] unless node['is_grant']
497
- output << node['grantees'].map(&method(:deparse_item)).join(', ')
498
- output << 'WITH GRANT OPTION' if node['grant_option']
499
- output.join(' ')
500
- end
501
-
502
- def deparse_grant_objtype(node)
503
- {
504
- 1 => ['TABLE', true],
505
- 2 => ['SEQUENCE', true],
506
- 3 => ['DATABASE', false],
507
- 4 => ['DOMAIN', false],
508
- 5 => ['FOREIGN DATA WRAPPER', false],
509
- 6 => ['FOREIGN SERVER', false],
510
- 7 => ['FUNCTION', true],
511
- 8 => ['LANGUAGE', false],
512
- 9 => ['LARGE OBJECT', false],
513
- 10 => ['SCHEMA', false],
514
- 11 => ['TABLESPACE', false],
515
- 12 => ['TYPE', false]
516
- }.fetch(node['objtype'])
517
- end
518
-
519
- def deparse_access_priv(node)
520
- output = [node['priv_name']]
521
- output << "(#{node['cols'].map(&method(:deparse_item)).join(', ')})" if node.key?('cols')
522
- output.join(' ')
523
- end
524
-
525
- def deparse_role_spec(node)
526
- return 'CURRENT_USER' if node['roletype'] == 1
527
- return 'SESSION_USER' if node['roletype'] == 2
528
- return 'PUBLIC' if node['roletype'] == 3
529
- deparse_identifier(node['rolename'], escape_always: true)
530
- end
531
-
532
- def deparse_aexpr_in(node)
533
- rexpr = Array(node['rexpr']).map { |arg| deparse_item(arg) }
534
- operator = node['name'].map { |n| deparse_item(n, :operator) } == ['='] ? 'IN' : 'NOT IN'
535
- format('%s %s (%s)', deparse_item(node['lexpr']), operator, rexpr.join(', '))
536
- end
537
-
538
- def deparse_aexpr_like(node)
539
- value = deparse_item(node['rexpr'])
540
- operator = node['name'].map { |n| deparse_item(n, :operator) } == ['~~'] ? 'LIKE' : 'NOT LIKE'
541
- format('%s %s %s', deparse_item(node['lexpr']), operator, value)
542
- end
543
-
544
- def deparse_aexpr_ilike(node)
545
- value = deparse_item(node['rexpr'])
546
- operator = node['name'][0]['String']['str'] == '~~*' ? 'ILIKE' : 'NOT ILIKE'
547
- format('%s %s %s', deparse_item(node['lexpr']), operator, value)
548
- end
549
-
550
- def deparse_bool_expr_not(node)
551
- format('NOT %s', deparse_item(node['args'][0]))
552
- end
553
-
554
- BOOLEAN_TEST_TYPE_TO_STRING = {
555
- BOOLEAN_TEST_TRUE => ' IS TRUE',
556
- BOOLEAN_TEST_NOT_TRUE => ' IS NOT TRUE',
557
- BOOLEAN_TEST_FALSE => ' IS FALSE',
558
- BOOLEAN_TEST_NOT_FALSE => ' IS NOT FALSE',
559
- BOOLEAN_TEST_UNKNOWN => ' IS UNKNOWN',
560
- BOOLEAN_TEST_NOT_UNKNOWN => ' IS NOT UNKNOWN'
561
- }.freeze
562
- def deparse_boolean_test(node)
563
- deparse_item(node['arg']) + BOOLEAN_TEST_TYPE_TO_STRING[node['booltesttype']]
564
- end
565
-
566
- def deparse_range_function(node)
567
- output = []
568
- output << 'LATERAL' if node['lateral']
569
- output << deparse_item(node['functions'][0][0]) # FIXME: Needs more test cases
570
- output << deparse_item(node['alias']) if node['alias']
571
- output << "#{node['alias'] ? '' : 'AS '}(#{deparse_item_list(node['coldeflist']).join(', ')})" if node['coldeflist']
572
- output.join(' ')
573
- end
574
-
575
- def deparse_aexpr(node, context = false)
576
- output = []
577
- output << deparse_item(node['lexpr'], context || true)
578
- output << deparse_item(node['rexpr'], context || true)
579
- output = output.join(' ' + deparse_item(node['name'][0], :operator) + ' ')
580
- if context
581
- # This is a nested expression, add parentheses.
582
- output = '(' + output + ')'
583
- end
584
- output
585
- end
586
-
587
- def deparse_bool_expr_and(node)
588
- # Only put parantheses around OR nodes that are inside this one
589
- node['args'].map do |arg|
590
- if [BOOL_EXPR_OR].include?(arg.values[0]['boolop'])
591
- format('(%s)', deparse_item(arg))
592
- else
593
- deparse_item(arg)
594
- end
595
- end.join(' AND ')
596
- end
597
-
598
- def deparse_bool_expr_or(node)
599
- # Put parantheses around AND + OR nodes that are inside
600
- node['args'].map do |arg|
601
- if [BOOL_EXPR_AND, BOOL_EXPR_OR].include?(arg.values[0]['boolop'])
602
- format('(%s)', deparse_item(arg))
603
- else
604
- deparse_item(arg)
605
- end
606
- end.join(' OR ')
607
- end
608
-
609
- def deparse_aexpr_any(node)
610
- output = []
611
- output << deparse_item(node['lexpr'])
612
- output << format('ANY(%s)', deparse_item(node['rexpr']))
613
- output.join(' ' + deparse_item(node['name'][0], :operator) + ' ')
614
- end
615
-
616
- def deparse_aexpr_all(node)
617
- output = []
618
- output << deparse_item(node['lexpr'])
619
- output << format('ALL(%s)', deparse_item(node['rexpr']))
620
- output.join(' ' + deparse_item(node['name'][0], :operator) + ' ')
621
- end
622
-
623
- def deparse_aexpr_between(node)
624
- between = case node['kind']
625
- when AEXPR_BETWEEN
626
- ' BETWEEN '
627
- when AEXPR_NOT_BETWEEN
628
- ' NOT BETWEEN '
629
- when AEXPR_BETWEEN_SYM
630
- ' BETWEEN SYMMETRIC '
631
- when AEXPR_NOT_BETWEEN_SYM
632
- ' NOT BETWEEN SYMMETRIC '
633
- end
634
- name = deparse_item(node['lexpr'])
635
- output = node['rexpr'].map { |n| deparse_item(n) }
636
- name << between << output.join(' AND ')
637
- end
638
-
639
- def deparse_aexpr_nullif(node)
640
- lexpr = deparse_item(node['lexpr'])
641
- rexpr = deparse_item(node['rexpr'])
642
- format('NULLIF(%s, %s)', lexpr, rexpr)
643
- end
644
-
645
- def deparse_joinexpr(node) # rubocop:disable Metrics/CyclomaticComplexity
646
- output = []
647
- output << deparse_item(node['larg'])
648
- case node['jointype']
649
- when 0
650
- if node['isNatural']
651
- output << 'NATURAL'
652
- elsif node['quals'].nil? && node['usingClause'].nil?
653
- output << 'CROSS'
654
- end
655
- when 1
656
- output << 'LEFT'
657
- when 2
658
- output << 'FULL'
659
- when 3
660
- output << 'RIGHT'
661
- end
662
- output << 'JOIN'
663
- output << deparse_item(node['rarg'])
664
-
665
- if node['quals']
666
- output << 'ON'
667
- output << deparse_item(node['quals'])
668
- end
669
-
670
- output << format('USING (%s)', node['usingClause'].map { |n| deparse_item(n) }.join(', ')) if node['usingClause']
671
-
672
- output.join(' ')
673
- end
674
-
675
- def deparse_lock(node)
676
- output = []
677
- output << 'LOCK TABLE'
678
- tables = node['relations'].map { |table| deparse_item(table) }
679
- output << tables.join(', ')
680
- output.join(' ')
681
- end
682
-
683
- LOCK_CLAUSE_STRENGTH = {
684
- LCS_FORKEYSHARE => 'FOR KEY SHARE',
685
- LCS_FORSHARE => 'FOR SHARE',
686
- LCS_FORNOKEYUPDATE => 'FOR NO KEY UPDATE',
687
- LCS_FORUPDATE => 'FOR UPDATE'
688
- }.freeze
689
- def deparse_lockingclause(node)
690
- output = []
691
- output << LOCK_CLAUSE_STRENGTH[node['strength']]
692
- if node['lockedRels']
693
- output << 'OF'
694
- output << node['lockedRels'].map do |item|
695
- deparse_item(item)
696
- end.join(', ')
697
- end
698
- output.join(' ')
699
- end
700
-
701
- def deparse_sortby(node)
702
- output = []
703
- output << deparse_item(node['node'])
704
- output << 'ASC' if node['sortby_dir'] == 1
705
- output << 'DESC' if node['sortby_dir'] == 2
706
- output << 'NULLS FIRST' if node['sortby_nulls'] == 1
707
- output << 'NULLS LAST' if node['sortby_nulls'] == 2
708
- output.join(' ')
709
- end
710
-
711
- def deparse_collate(node)
712
- output = []
713
- output << deparse_item(node['arg'])
714
- output << 'COLLATE'
715
- output << deparse_item_list(node['collname'])
716
- output.join(' ')
717
- end
718
-
719
- def deparse_with_clause(node)
720
- output = ['WITH']
721
- output << 'RECURSIVE' if node['recursive']
722
- output << node['ctes'].map do |cte|
723
- deparse_item(cte)
724
- end.join(', ')
725
- output.join(' ')
726
- end
727
-
728
- def deparse_viewstmt(node)
729
- output = []
730
- output << 'CREATE'
731
- output << 'OR REPLACE' if node['replace']
732
-
733
- persistence = relpersistence(node['view'])
734
- output << persistence if persistence
735
-
736
- output << 'VIEW'
737
- output << node['view'][RANGE_VAR]['relname']
738
- output << format('(%s)', deparse_item_list(node['aliases']).join(', ')) if node['aliases']
739
-
740
- output << 'AS'
741
- output << deparse_item(node['query'])
742
-
743
- case node['withCheckOption']
744
- when 1
745
- output << 'WITH CHECK OPTION'
746
- when 2
747
- output << 'WITH CASCADED CHECK OPTION'
748
- end
749
- output.join(' ')
750
- end
751
-
752
- def deparse_variable_set_stmt(node)
753
- output = []
754
- output << 'SET'
755
- output << 'LOCAL' if node['is_local']
756
- output << node['name']
757
- output << 'TO'
758
- output << node['args'].map { |arg| deparse_item(arg) }.join(', ')
759
- output.join(' ')
760
- end
761
-
762
- def deparse_vacuum_stmt(node)
763
- output = []
764
- output << 'VACUUM'
765
- output.concat(deparse_vacuum_options(node))
766
- output << deparse_item(node['relation']) if node.key?('relation')
767
- if node.key?('va_cols')
768
- output << "(#{node['va_cols'].map(&method(:deparse_item)).join(', ')})"
769
- end
770
- output.join(' ')
771
- end
772
-
773
- def deparse_vacuum_options(node)
774
- output = []
775
- output << 'FULL' if node['options'][4] == 1
776
- output << 'FREEZE' if node['options'][3] == 1
777
- output << 'VERBOSE' if node['options'][2] == 1
778
- output << 'ANALYZE' if node['options'][1] == 1
779
- output
780
- end
781
-
782
- def deparse_do_stmt(node)
783
- output = []
784
- output << 'DO'
785
- statement, *rest = node['args']
786
- output << "$$#{statement['DefElem']['arg']['String']['str']}$$"
787
- output += rest.map { |item| deparse_item(item) }
788
- output.join(' ')
789
- end
790
-
791
- def deparse_cte(node)
792
- output = []
793
- output << node['ctename']
794
- output << format('(%s)', node['aliascolnames'].map { |n| deparse_item(n) }.join(', ')) if node['aliascolnames']
795
- output << format('AS (%s)', deparse_item(node['ctequery']))
796
- output.join(' ')
797
- end
798
-
799
- def deparse_case(node)
800
- output = ['CASE']
801
- output << deparse_item(node['arg']) if node['arg']
802
- output += node['args'].map { |arg| deparse_item(arg) }
803
- if node['defresult']
804
- output << 'ELSE'
805
- output << deparse_item(node['defresult'])
806
- end
807
- output << 'END'
808
- output.join(' ')
809
- end
810
-
811
- def deparse_columndef(node)
812
- output = [node['colname']]
813
- output << deparse_item(node['typeName'])
814
- if node['raw_default']
815
- output << 'USING'
816
- output << deparse_item(node['raw_default'])
817
- end
818
- if node['constraints']
819
- output += node['constraints'].map do |item|
820
- deparse_item(item)
821
- end
822
- end
823
- if node['collClause']
824
- output << 'COLLATE'
825
- output += node['collClause']['CollateClause']['collname'].map(&method(:deparse_item))
826
- end
827
- output.compact.join(' ')
828
- end
829
-
830
- def deparse_composite_type(node)
831
- output = ['CREATE TYPE']
832
- output << deparse_rangevar(node['typevar'][RANGE_VAR].merge('inh' => true))
833
- output << 'AS'
834
- coldeflist = node['coldeflist'].map(&method(:deparse_item))
835
- output << "(#{coldeflist.join(', ')})"
836
- output.join(' ')
837
- end
838
-
839
- def deparse_constraint(node) # rubocop:disable Metrics/CyclomaticComplexity
840
- output = []
841
- if node['conname']
842
- output << 'CONSTRAINT'
843
- output << node['conname']
844
- end
845
- case node['contype']
846
- when CONSTR_TYPE_NULL
847
- output << 'NULL'
848
- when CONSTR_TYPE_NOTNULL
849
- output << 'NOT NULL'
850
- when CONSTR_TYPE_DEFAULT
851
- output << 'DEFAULT'
852
- when CONSTR_TYPE_CHECK
853
- output << 'CHECK'
854
- when CONSTR_TYPE_PRIMARY
855
- output << 'PRIMARY KEY'
856
- when CONSTR_TYPE_UNIQUE
857
- output << 'UNIQUE'
858
- when CONSTR_TYPE_EXCLUSION
859
- output << 'EXCLUSION'
860
- when CONSTR_TYPE_FOREIGN
861
- output << 'FOREIGN KEY'
862
- end
863
-
864
- if node['raw_expr']
865
- expression = deparse_item(node['raw_expr'])
866
- # Unless it's simple, put parentheses around it
867
- expression = '(' + expression + ')' if node['raw_expr'][BOOL_EXPR]
868
- expression = '(' + expression + ')' if node['raw_expr'][A_EXPR] && node['raw_expr'][A_EXPR]['kind'] == AEXPR_OP
869
- output << expression
870
- end
871
- output << '(' + deparse_item_list(node['keys']).join(', ') + ')' if node['keys']
872
- output << '(' + deparse_item_list(node['fk_attrs']).join(', ') + ')' if node['fk_attrs']
873
- output << 'REFERENCES ' + deparse_item(node['pktable']) + ' (' + deparse_item_list(node['pk_attrs']).join(', ') + ')' if node['pktable']
874
- output << 'NOT VALID' if node['skip_validation']
875
- output << "USING INDEX #{node['indexname']}" if node['indexname']
876
- output.join(' ')
877
- end
878
-
879
- def deparse_copy(node)
880
- output = ['COPY']
881
- if node.key?('relation')
882
- output << deparse_item(node['relation'])
883
- elsif node.key?('query')
884
- output << "(#{deparse_item(node['query'])})"
885
- end
886
- columns = node.fetch('attlist', []).map { |column| deparse_item(column) }
887
- output << "(#{columns.join(', ')})" unless columns.empty?
888
- output << (node['is_from'] ? 'FROM' : 'TO')
889
- output << 'PROGRAM' if node['is_program']
890
- output << deparse_copy_output(node)
891
- output.join(' ')
892
- end
893
-
894
- def deparse_copy_output(node)
895
- return "'#{node['filename']}'" if node.key?('filename')
896
- return 'STDIN' if node['is_from']
897
- 'STDOUT'
898
- end
899
-
900
- def deparse_create_enum(node)
901
- output = ['CREATE TYPE']
902
- output << deparse_item(node['typeName'][0])
903
- output << 'AS ENUM'
904
- vals = node['vals'].map { |val| deparse_item(val, A_CONST) }
905
- output << "(#{vals.join(', ')})"
906
- output.join(' ')
907
- end
908
-
909
- def deparse_create_cast(node)
910
- output = []
911
- output << 'CREATE'
912
- output << 'CAST'
913
- output << format('(%s AS %s)', deparse_item(node['sourcetype']), deparse_item(node['targettype']))
914
- output << if node['func']
915
- function = node['func']['ObjectWithArgs']
916
- name = deparse_item_list(function['objname']).join('.')
917
- arguments = deparse_item_list(function['objargs']).join(', ')
918
- format('WITH FUNCTION %s(%s)', name, arguments)
919
- elsif node['inout']
920
- 'WITH INOUT'
921
- else
922
- 'WITHOUT FUNCTION'
923
- end
924
- output << 'AS IMPLICIT' if (node['context']).zero?
925
- output << 'AS ASSIGNMENT' if node['context'] == 1
926
- output.join(' ')
927
- end
928
-
929
- def deparse_create_domain(node)
930
- output = []
931
- output << 'CREATE'
932
- output << 'DOMAIN'
933
- output << deparse_item_list(node['domainname']).join('.')
934
- output << 'AS'
935
- output << deparse_item(node['typeName']) if node['typeName']
936
- output << deparse_item(node['collClause']) if node['collClause']
937
- output << deparse_item_list(node['constraints'])
938
- output.join(' ')
939
- end
940
-
941
- def deparse_create_function(node)
942
- output = []
943
- output << 'CREATE'
944
- output << 'OR REPLACE' if node['replace']
945
- output << 'FUNCTION'
946
-
947
- arguments = deparse_item_list(node.fetch('parameters', [])).join(', ')
948
-
949
- output << deparse_item_list(node['funcname']).join('.') + '(' + arguments + ')'
950
-
951
- output << 'RETURNS'
952
- output << deparse_item(node['returnType'])
953
- output += node['options'].map { |item| deparse_item(item) }
954
-
955
- output.join(' ')
956
- end
957
-
958
- def deparse_create_range(node)
959
- output = ['CREATE TYPE']
960
- output << deparse_item(node['typeName'][0])
961
- output << 'AS RANGE'
962
- params = node['params'].map do |param|
963
- param_out = [param['DefElem']['defname']]
964
- if param['DefElem'].key?('arg')
965
- param_out << deparse_item(param['DefElem']['arg'])
966
- end
967
- param_out.join('=')
968
- end
969
- output << "(#{params.join(', ')})"
970
- output.join(' ')
971
- end
972
-
973
- def deparse_create_schema(node)
974
- output = ['CREATE SCHEMA']
975
- output << 'IF NOT EXISTS' if node['if_not_exists']
976
- output << deparse_identifier(node['schemaname']) if node.key?('schemaname')
977
- output << format('AUTHORIZATION %s', deparse_item(node['authrole'])) if node.key?('authrole')
978
- output << deparse_item_list(node['schemaElts']) if node.key?('schemaElts')
979
- output.join(' ')
980
- end
981
-
982
- def deparse_create_table(node)
983
- output = []
984
- output << 'CREATE'
985
-
986
- persistence = relpersistence(node['relation'])
987
- output << persistence if persistence
988
-
989
- output << 'TABLE'
990
-
991
- output << 'IF NOT EXISTS' if node['if_not_exists']
992
-
993
- output << deparse_item(node['relation'])
994
-
995
- output << '(' + node['tableElts'].map do |item|
996
- deparse_item(item)
997
- end.join(', ') + ')'
998
-
999
- if node['inhRelations']
1000
- output << 'INHERITS'
1001
- output << '(' + node['inhRelations'].map do |relation|
1002
- deparse_item(relation)
1003
- end.join(', ') + ')'
1004
- end
1005
-
1006
- output.join(' ')
1007
- end
1008
-
1009
- def deparse_create_table_as(node)
1010
- output = []
1011
- output << 'CREATE'
1012
-
1013
- into = node['into']['IntoClause']
1014
- persistence = relpersistence(into['rel'])
1015
- output << persistence if persistence
1016
-
1017
- output << 'TABLE'
1018
-
1019
- output << deparse_item(node['into'])
1020
-
1021
- if into['onCommit'] > 0
1022
- output << 'ON COMMIT'
1023
- output << 'DELETE ROWS' if into['onCommit'] == 2
1024
- output << 'DROP' if into['onCommit'] == 3
1025
- end
1026
-
1027
- output << 'AS'
1028
- output << deparse_item(node['query'])
1029
- output.join(' ')
1030
- end
1031
-
1032
- def deparse_execute(node)
1033
- output = ['EXECUTE']
1034
- output << deparse_identifier(node['name'])
1035
- output << "(#{deparse_item_list(node['params']).join(', ')})" if node['params']
1036
- output.join(' ')
1037
- end
1038
-
1039
- def deparse_into_clause(node)
1040
- deparse_item(node['rel'])
1041
- end
1042
-
1043
- def deparse_when(node)
1044
- output = ['WHEN']
1045
- output << deparse_item(node['expr'])
1046
- output << 'THEN'
1047
- output << deparse_item(node['result'])
1048
- output.join(' ')
1049
- end
1050
-
1051
- def deparse_sublink(node)
1052
- if node['subLinkType'] == SUBLINK_TYPE_ANY
1053
- format('%s IN (%s)', deparse_item(node['testexpr']), deparse_item(node['subselect']))
1054
- elsif node['subLinkType'] == SUBLINK_TYPE_ALL
1055
- format('%s %s ALL (%s)', deparse_item(node['testexpr']), deparse_item(node['operName'][0], :operator), deparse_item(node['subselect']))
1056
- elsif node['subLinkType'] == SUBLINK_TYPE_EXISTS
1057
- format('EXISTS(%s)', deparse_item(node['subselect']))
1058
- elsif node['subLinkType'] == SUBLINK_TYPE_ARRAY
1059
- format('ARRAY(%s)', deparse_item(node['subselect']))
1060
- else
1061
- format('(%s)', deparse_item(node['subselect']))
1062
- end
1063
- end
1064
-
1065
- def deparse_rangesubselect(node)
1066
- output = ''
1067
- output = 'LATERAL ' if node['lateral']
1068
- output = output + '(' + deparse_item(node['subquery']) + ')'
1069
- if node['alias']
1070
- output + ' ' + deparse_item(node['alias'])
1071
- else
1072
- output
1073
- end
1074
- end
1075
-
1076
- def deparse_row(node)
1077
- 'ROW(' + node['args'].map { |arg| deparse_item(arg) }.join(', ') + ')'
1078
- end
1079
-
1080
- def deparse_select(node) # rubocop:disable Metrics/CyclomaticComplexity
1081
- output = []
1082
-
1083
- output << deparse_item(node['withClause']) if node['withClause']
1084
-
1085
- if node['op'] == 1
1086
- output << '(' if node['larg']['SelectStmt']['sortClause']
1087
- output << deparse_item(node['larg'])
1088
- output << ')' if node['larg']['SelectStmt']['sortClause']
1089
- output << 'UNION'
1090
- output << 'ALL' if node['all']
1091
- output << '(' if node['rarg']['SelectStmt']['sortClause']
1092
- output << deparse_item(node['rarg'])
1093
- output << ')' if node['rarg']['SelectStmt']['sortClause']
1094
- output.join(' ')
1095
- end
1096
-
1097
- if node['op'] == 3
1098
- output << deparse_item(node['larg'])
1099
- output << 'EXCEPT'
1100
- output << deparse_item(node['rarg'])
1101
- output.join(' ')
1102
- end
1103
-
1104
- if node['op'] == 2
1105
- output << deparse_item(node['larg'])
1106
- output << 'INTERSECT'
1107
- output << deparse_item(node['rarg'])
1108
- output.join(' ')
1109
- end
1110
-
1111
- output << 'SELECT' if node[FROM_CLAUSE_FIELD] || node[TARGET_LIST_FIELD]
1112
-
1113
- if node[TARGET_LIST_FIELD]
1114
- if node['distinctClause']
1115
- output << 'DISTINCT'
1116
- unless node['distinctClause'].compact.empty?
1117
- columns = node['distinctClause'].map { |item| deparse_item(item, :select) }
1118
- output << "ON (#{columns.join(', ')})"
1119
- end
1120
- end
1121
- output << node[TARGET_LIST_FIELD].map do |item|
1122
- deparse_item(item, :select)
1123
- end.join(', ')
1124
-
1125
- if node['intoClause']
1126
- output << 'INTO'
1127
- output << deparse_item(node['intoClause'])
1128
- end
1129
- end
1130
-
1131
- if node[FROM_CLAUSE_FIELD]
1132
- output << 'FROM'
1133
- output << node[FROM_CLAUSE_FIELD].map do |item|
1134
- deparse_item(item)
1135
- end.join(', ')
1136
- end
1137
-
1138
- if node['whereClause']
1139
- output << 'WHERE'
1140
- output << deparse_item(node['whereClause'])
1141
- end
1142
-
1143
- if node['valuesLists']
1144
- output << 'VALUES'
1145
- output << node['valuesLists'].map do |value_list|
1146
- '(' + value_list.map { |v| deparse_item(v) }.join(', ') + ')'
1147
- end.join(', ')
1148
- end
1149
-
1150
- if node['groupClause']
1151
- output << 'GROUP BY'
1152
- output << node['groupClause'].map do |item|
1153
- deparse_item(item)
1154
- end.join(', ')
1155
- end
1156
-
1157
- if node['havingClause']
1158
- output << 'HAVING'
1159
- output << deparse_item(node['havingClause'])
1160
- end
1161
-
1162
- if node['sortClause']
1163
- output << 'ORDER BY'
1164
- output << node['sortClause'].map do |item|
1165
- deparse_item(item)
1166
- end.join(', ')
1167
- end
1168
-
1169
- if node['limitCount']
1170
- output << 'LIMIT'
1171
- output << deparse_item(node['limitCount'])
1172
- end
1173
-
1174
- if node['limitOffset']
1175
- output << 'OFFSET'
1176
- output << deparse_item(node['limitOffset'])
1177
- end
1178
-
1179
- if node['lockingClause']
1180
- node['lockingClause'].map do |item|
1181
- output << deparse_item(item)
1182
- end
1183
- end
1184
-
1185
- output.join(' ')
1186
- end
1187
-
1188
- def deparse_sql_value_function(node)
1189
- output = []
1190
- lookup = [
1191
- 'current_date',
1192
- 'current_time',
1193
- 'current_time', # with precision
1194
- 'current_timestamp',
1195
- 'current_timestamp', # with precision
1196
- 'localtime',
1197
- 'localtime', # with precision
1198
- 'localtimestamp',
1199
- 'localtimestamp', # with precision
1200
- 'current_role',
1201
- 'current_user',
1202
- 'session_user',
1203
- 'user',
1204
- 'current_catalog',
1205
- 'current_schema'
1206
- ]
1207
- output << lookup[node['op']]
1208
- output << "(#{node['typmod']})" unless node.fetch('typmod', -1) == -1
1209
- output.join('')
1210
- end
1211
-
1212
- def deparse_insert_into(node)
1213
- output = []
1214
- output << deparse_item(node['withClause']) if node['withClause']
1215
-
1216
- output << 'INSERT INTO'
1217
- output << deparse_item(node['relation'])
1218
-
1219
- if node['cols']
1220
- output << '(' + node['cols'].map do |column|
1221
- deparse_item(column, :select)
1222
- end.join(', ') + ')'
1223
- end
1224
-
1225
- output << deparse_item(node['selectStmt'])
1226
-
1227
- if node['onConflictClause']
1228
- output << deparse_insert_onconflict(node['onConflictClause'][ON_CONFLICT_CLAUSE])
1229
- end
1230
-
1231
- if node['returningList']
1232
- output << 'RETURNING'
1233
- output << node['returningList'].map do |column|
1234
- deparse_item(column, :select)
1235
- end.join(', ')
1236
- end
1237
-
1238
- output.join(' ')
1239
- end
1240
-
1241
- def deparse_insert_onconflict(node) # rubocop:disable Metrics/CyclomaticComplexity
1242
- output = []
1243
- output << 'ON CONFLICT'
1244
-
1245
- infer = node['infer']['InferClause']
1246
- if infer['indexElems']
1247
- output << '(' + infer['indexElems'].map do |column|
1248
- '"' + column['IndexElem']['name'] + '"'
1249
- end.join(', ') + ')'
1250
- end
1251
-
1252
- if infer['conname']
1253
- output << 'ON CONSTRAINT'
1254
- output << deparse_identifier(infer['conname'], escape_always: true)
1255
- end
1256
-
1257
- output << 'DO UPDATE' if node['action'] == 2
1258
-
1259
- if node[TARGET_LIST_FIELD]
1260
- output << 'SET ' + node[TARGET_LIST_FIELD].map do |column|
1261
- deparse_item(column, :excluded)
1262
- end.join(', ')
1263
- end
1264
-
1265
- if infer['whereClause']
1266
- output << 'WHERE'
1267
- output << deparse_item(infer['whereClause'])
1268
- end
1269
-
1270
- output << 'DO NOTHING' if node['action'] == 1
1271
-
1272
- output.join(' ')
1273
- end
1274
-
1275
- def deparse_update(node)
1276
- output = []
1277
- output << deparse_item(node['withClause']) if node['withClause']
1278
-
1279
- output << 'UPDATE'
1280
- output << deparse_item(node['relation'])
1281
-
1282
- if node[TARGET_LIST_FIELD]
1283
- output << 'SET'
1284
- columns = node[TARGET_LIST_FIELD].map do |item|
1285
- deparse_item(item, :update)
1286
- end
1287
- output << columns.join(', ')
1288
- end
1289
-
1290
- if node[FROM_CLAUSE_FIELD]
1291
- output << 'FROM'
1292
- output << node[FROM_CLAUSE_FIELD].map do |item|
1293
- deparse_item(item)
1294
- end.join(', ')
1295
- end
1296
-
1297
- if node['whereClause']
1298
- output << 'WHERE'
1299
- output << deparse_item(node['whereClause'])
1300
- end
1301
-
1302
- if node['returningList']
1303
- output << 'RETURNING'
1304
- output << node['returningList'].map do |item|
1305
- # RETURNING is formatted like a SELECT
1306
- deparse_item(item, :select)
1307
- end.join(', ')
1308
- end
1309
-
1310
- output.join(' ')
1311
- end
1312
-
1313
- # Builds a properly-qualified reference to a built-in Postgres type.
1314
- #
1315
- # Inspired by SystemTypeName in Postgres' gram.y, but without node name
1316
- # and locations, to simplify comparison.
1317
- def make_system_type_name(name)
1318
- {
1319
- 'names' => [
1320
- { 'String' => { 'str' => 'pg_catalog' } },
1321
- { 'String' => { 'str' => name } }
1322
- ],
1323
- 'typemod' => -1
1324
- }
1325
- end
1326
-
1327
- def make_string(str)
1328
- { 'String' => { 'str' => str } }
1329
- end
1330
-
1331
- def deparse_typecast(node)
1332
- # Handle "bool" or "false" in the statement, which is represented as a typecast
1333
- # (other boolean casts should be represented as a cast, i.e. don't need special handling)
1334
- if node['arg'][A_CONST] && node['typeName'][TYPE_NAME].slice('names', 'typemod') == make_system_type_name('bool')
1335
- return 'true' if node['arg'][A_CONST]['val'] == make_string('t')
1336
- return 'false' if node['arg'][A_CONST]['val'] == make_string('f')
1337
- end
1338
-
1339
- context = true if node['arg']['A_Expr']
1340
- deparse_item(node['arg'], context) + '::' + deparse_typename(node['typeName'][TYPE_NAME])
1341
- end
1342
-
1343
- def deparse_typename(node)
1344
- names = node['names'].map { |n| deparse_item(n, TYPE_NAME) }
1345
-
1346
- # Intervals are tricky and should be handled in a separate method because
1347
- # they require performing some bitmask operations.
1348
- return deparse_interval_type(node) if names == %w[pg_catalog interval]
1349
-
1350
- output = []
1351
- output << 'SETOF' if node['setof']
1352
-
1353
- if node['typmods']
1354
- arguments = node['typmods'].map do |item|
1355
- deparse_item(item)
1356
- end.join(', ')
1357
- end
1358
- output << deparse_typename_cast(names, arguments)
1359
- output.last << '[]' if node['arrayBounds']
1360
-
1361
- output.join(' ')
1362
- end
1363
-
1364
- def deparse_typename_cast(names, arguments) # rubocop:disable Metrics/CyclomaticComplexity
1365
- catalog, type = names
1366
- # Just pass along any custom types.
1367
- # (The pg_catalog types are built-in Postgres system types and are
1368
- # handled in the case statement below)
1369
- return names.join('.') + (arguments.nil? ? '' : "(#{arguments})") if catalog != 'pg_catalog'
1370
-
1371
- case type
1372
- when 'bpchar'
1373
- # char(2) or char(9)
1374
- "char(#{arguments})"
1375
- when 'varchar'
1376
- arguments.nil? ? 'varchar' : "varchar(#{arguments})"
1377
- when 'numeric'
1378
- # numeric(3, 5)
1379
- arguments.nil? ? 'numeric' : "numeric(#{arguments})"
1380
- when 'bool'
1381
- 'boolean'
1382
- when 'int2'
1383
- 'smallint'
1384
- when 'int4'
1385
- 'int'
1386
- when 'int8'
1387
- 'bigint'
1388
- when 'real', 'float4'
1389
- 'real'
1390
- when 'float8'
1391
- 'double precision'
1392
- when 'time'
1393
- 'time'
1394
- when 'timetz'
1395
- 'time with time zone'
1396
- when 'timestamp'
1397
- 'timestamp'
1398
- when 'timestamptz'
1399
- 'timestamp with time zone'
1400
- else
1401
- raise format("Can't deparse type: %s", type)
1402
- end
1403
- end
1404
-
1405
- # Deparses interval type expressions like `interval year to month` or
1406
- # `interval hour to second(5)`
1407
- def deparse_interval_type(node)
1408
- type = ['interval']
1409
-
1410
- if node['typmods']
1411
- typmods = node['typmods'].map { |typmod| deparse_item(typmod) }
1412
- type << Interval.from_int(typmods.first.to_i).map do |part|
1413
- # only the `second` type can take an argument.
1414
- if part == 'second' && typmods.size == 2
1415
- "second(#{typmods.last})"
1416
- else
1417
- part
1418
- end.downcase
1419
- end.join(' to ')
1420
- end
1421
-
1422
- type.join(' ')
1423
- end
1424
-
1425
- def deparse_nulltest(node)
1426
- output = [deparse_item(node['arg'])]
1427
- case node['nulltesttype']
1428
- when 0
1429
- output << 'IS NULL'
1430
- when 1
1431
- output << 'IS NOT NULL'
1432
- end
1433
- output.join(' ')
1434
- end
1435
-
1436
- TRANSACTION_CMDS = {
1437
- TRANS_STMT_BEGIN => 'BEGIN',
1438
- TRANS_STMT_COMMIT => 'COMMIT',
1439
- TRANS_STMT_ROLLBACK => 'ROLLBACK',
1440
- TRANS_STMT_SAVEPOINT => 'SAVEPOINT',
1441
- TRANS_STMT_RELEASE => 'RELEASE',
1442
- TRANS_STMT_ROLLBACK_TO => 'ROLLBACK TO SAVEPOINT'
1443
- }.freeze
1444
- def deparse_transaction(node)
1445
- output = []
1446
- output << TRANSACTION_CMDS[node['kind']] || raise(format("Can't deparse TRANSACTION %s", node.inspect))
1447
-
1448
- if node['options']
1449
- output += node['options'].map { |item| deparse_item(item) }
1450
- end
1451
-
1452
- output.join(' ')
1453
- end
1454
-
1455
- def deparse_coalesce(node)
1456
- format('COALESCE(%s)', node['args'].map { |a| deparse_item(a) }.join(', '))
1457
- end
1458
-
1459
- def deparse_defelem(node)
1460
- case node['defname']
1461
- when 'as'
1462
- "AS $$#{deparse_item_list(node['arg'], :defname_as).join("\n")}$$"
1463
- when 'language'
1464
- "language #{deparse_item(node['arg'])}"
1465
- when 'volatility'
1466
- node['arg']['String']['str'].upcase # volatility does not need to be quoted
1467
- when 'strict'
1468
- deparse_item(node['arg']) == '1' ? 'RETURNS NULL ON NULL INPUT' : 'CALLED ON NULL INPUT'
1469
- else
1470
- deparse_item(node['arg'])
1471
- end
1472
- end
1473
-
1474
- def deparse_define_stmt(node)
1475
- dispatch = {
1476
- 1 => :deparse_create_aggregate,
1477
- 25 => :deparse_create_operator,
1478
- 45 => :deparse_create_type
1479
- }
1480
- method(dispatch.fetch(node['kind'])).call(node)
1481
- end
1482
-
1483
- def deparse_create_aggregate(node)
1484
- output = ['CREATE AGGREGATE']
1485
- output << node['defnames'].map(&method(:deparse_item))
1486
- args = node['args'][0] || [{ A_STAR => nil }]
1487
- output << "(#{args.map(&method(:deparse_item)).join(', ')})"
1488
- definitions = node['definition'].map do |definition|
1489
- definition_output = [definition['DefElem']['defname']]
1490
- definition_output << definition['DefElem']['arg']['TypeName']['names'].map(&method(:deparse_item)).join(', ') if definition['DefElem'].key?('arg')
1491
- definition_output.join('=')
1492
- end
1493
- output << "(#{definitions.join(', ')})"
1494
- output.join(' ')
1495
- end
1496
-
1497
- def deparse_create_operator(node)
1498
- output = ['CREATE OPERATOR']
1499
- output << node['defnames'][0]['String']['str']
1500
- definitions = node['definition'].map do |definition|
1501
- definition_output = [definition['DefElem']['defname']]
1502
- definition_output << definition['DefElem']['arg']['TypeName']['names'].map(&method(:deparse_item)).join(', ') if definition['DefElem'].key?('arg')
1503
- definition_output.join('=')
1504
- end
1505
- output << "(#{definitions.join(', ')})"
1506
- output.join(' ')
1507
- end
1508
-
1509
- def deparse_create_type(node)
1510
- output = ['CREATE TYPE']
1511
- output << node['defnames'].map(&method(:deparse_item))
1512
- if node.key?('definition')
1513
- definitions = node['definition'].map do |definition|
1514
- definition_output = [definition['DefElem']['defname']]
1515
- if definition['DefElem'].key?('arg')
1516
- definition_output += definition['DefElem']['arg']['TypeName']['names'].map(&method(:deparse_item))
1517
- end
1518
- definition_output.join('=')
1519
- end
1520
- output << "(#{definitions.join(', ')})"
1521
- end
1522
- output.join(' ')
1523
- end
1524
-
1525
- def deparse_delete_from(node)
1526
- output = []
1527
- output << deparse_item(node['withClause']) if node['withClause']
1528
-
1529
- output << 'DELETE FROM'
1530
- output << deparse_item(node['relation'])
1531
-
1532
- if node['usingClause']
1533
- output << 'USING'
1534
- output << node['usingClause'].map do |item|
1535
- deparse_item(item)
1536
- end.join(', ')
1537
- end
1538
-
1539
- if node['whereClause']
1540
- output << 'WHERE'
1541
- output << deparse_item(node['whereClause'])
1542
- end
1543
-
1544
- if node['returningList']
1545
- output << 'RETURNING'
1546
- output << node['returningList'].map do |item|
1547
- # RETURNING is formatted like a SELECT
1548
- deparse_item(item, :select)
1549
- end.join(', ')
1550
- end
1551
-
1552
- output.join(' ')
1553
- end
1554
-
1555
- def deparse_discard(node)
1556
- output = ['DISCARD']
1557
- output << 'ALL' if (node['target']).zero?
1558
- output << 'PLANS' if node['target'] == 1
1559
- output << 'SEQUENCES' if node['target'] == 2
1560
- output << 'TEMP' if node['target'] == 3
1561
- output.join(' ')
1562
- end
1563
-
1564
- def deparse_drop(node) # rubocop:disable Metrics/CyclomaticComplexity
1565
- output = ['DROP']
1566
-
1567
- output << 'ACCESS METHOD' if node['removeType'] == OBJECT_TYPE_ACCESS_METHOD
1568
- output << 'AGGREGATE' if node['removeType'] == OBJECT_TYPE_AGGREGATE
1569
- output << 'CAST' if node['removeType'] == OBJECT_TYPE_CAST
1570
- output << 'COLLATION' if node['removeType'] == OBJECT_TYPE_COLLATION
1571
- output << 'DOMAIN' if node['removeType'] == OBJECT_TYPE_DOMAIN
1572
- output << 'CONVERSION' if node['removeType'] == OBJECT_TYPE_CONVERSION
1573
- output << 'EVENT TRIGGER' if node['removeType'] == OBJECT_TYPE_EVENT_TRIGGER
1574
- output << 'EXTENSION' if node['removeType'] == OBJECT_TYPE_EXTENSION
1575
- output << 'FOREIGN DATA WRAPPER' if node['removeType'] == OBJECT_TYPE_FDW
1576
- output << 'FOREIGN TABLE' if node['removeType'] == OBJECT_TYPE_FOREIGN_TABLE
1577
- output << 'FUNCTION' if node['removeType'] == OBJECT_TYPE_FUNCTION
1578
- output << 'INDEX' if node['removeType'] == OBJECT_TYPE_INDEX
1579
- output << 'MATERIALIZED VIEW' if node['removeType'] == OBJECT_TYPE_MATVIEW
1580
- output << 'OPERATOR CLASS' if node['removeType'] == OBJECT_TYPE_OPCLASS
1581
- output << 'OPERATOR FAMILY' if node['removeType'] == OBJECT_TYPE_OPFAMILY
1582
- output << 'POLICY' if node['removeType'] == OBJECT_TYPE_POLICY
1583
- output << 'PUBLICATION' if node['removeType'] == OBJECT_TYPE_PUBLICATION
1584
- output << 'RULE' if node['removeType'] == OBJECT_TYPE_RULE
1585
- output << 'SCHEMA' if node['removeType'] == OBJECT_TYPE_SCHEMA
1586
- output << 'SERVER' if node['removeType'] == OBJECT_TYPE_FOREIGN_SERVER
1587
- output << 'SEQUENCE' if node['removeType'] == OBJECT_TYPE_SEQUENCE
1588
- output << 'STATISTICS' if node['removeType'] == OBJECT_TYPE_STATISTIC_EXT
1589
- output << 'TABLE' if node['removeType'] == OBJECT_TYPE_TABLE
1590
- output << 'TRANSFORM' if node['removeType'] == OBJECT_TYPE_TRANSFORM
1591
- output << 'TRIGGER' if node['removeType'] == OBJECT_TYPE_TRIGGER
1592
- output << 'TEXT SEARCH CONFIGURATION' if node['removeType'] == OBJECT_TYPE_TSCONFIGURATION
1593
- output << 'TEXT SEARCH DICTIONARY' if node['removeType'] == OBJECT_TYPE_TSDICTIONARY
1594
- output << 'TEXT SEARCH PARSER' if node['removeType'] == OBJECT_TYPE_TSPARSER
1595
- output << 'TEXT SEARCH TEMPLATE' if node['removeType'] == OBJECT_TYPE_TSTEMPLATE
1596
- output << 'TYPE' if node['removeType'] == OBJECT_TYPE_TYPE
1597
- output << 'VIEW' if node['removeType'] == OBJECT_TYPE_VIEW
1598
-
1599
- output << 'CONCURRENTLY' if node['concurrent']
1600
- output << 'IF EXISTS' if node['missing_ok']
1601
-
1602
- objects = node['objects']
1603
- objects = [objects] unless objects[0].is_a?(Array)
1604
- case node['removeType']
1605
- when OBJECT_TYPE_CAST
1606
- object = objects[0]
1607
- output << format('(%s)', deparse_item_list(object).join(' AS '))
1608
- when OBJECT_TYPE_FUNCTION, OBJECT_TYPE_AGGREGATE, OBJECT_TYPE_SCHEMA, OBJECT_TYPE_EXTENSION
1609
- output << objects.map { |list| list.map { |object_line| deparse_item(object_line) } }.join(', ')
1610
- when OBJECT_TYPE_OPFAMILY, OBJECT_TYPE_OPCLASS
1611
- object = objects[0]
1612
- output << deparse_item(object[1]) if object.length == 2
1613
- output << deparse_item_list(object[1..-1]).join('.') if object.length == 3
1614
- output << 'USING'
1615
- output << deparse_item(object[0])
1616
- when OBJECT_TYPE_TRIGGER, OBJECT_TYPE_RULE, OBJECT_TYPE_POLICY
1617
- object = objects[0]
1618
- output << deparse_item(object[-1])
1619
- output << 'ON'
1620
- output << deparse_item(object[0]) if object.length == 2
1621
- output << deparse_item_list(object[0..1]).join('.') if object.length == 3
1622
- when OBJECT_TYPE_TRANSFORM
1623
- object = objects[0]
1624
- output << 'FOR'
1625
- output << deparse_item(object[0])
1626
- output << 'LANGUAGE'
1627
- output << deparse_item(object[1])
1628
- else
1629
- output << objects.map { |list| list.map { |object_line| deparse_item(object_line) }.join('.') }.join(', ')
1630
- end
1631
-
1632
- output << 'CASCADE' if node['behavior'] == 1
1633
-
1634
- output.join(' ')
1635
- end
1636
-
1637
- def deparse_drop_role(node)
1638
- output = ['DROP ROLE']
1639
- output << 'IF EXISTS' if node['missing_ok']
1640
- output << node['roles'].map { |role| deparse_identifier(role['RoleSpec']['rolename']) }.join(', ')
1641
- output.join(' ')
1642
- end
1643
-
1644
- def deparse_drop_subscription(node)
1645
- output = ['DROP SUBSCRIPTION']
1646
- output << 'IF EXISTS' if node['missing_ok']
1647
- output << deparse_identifier(node['subname'])
1648
- output.join(' ')
1649
- end
1650
-
1651
- def deparse_drop_tablespace(node)
1652
- output = ['DROP TABLESPACE']
1653
- output << 'IF EXISTS' if node['missing_ok']
1654
- output << node['tablespacename']
1655
- output.join(' ')
1656
- end
1657
-
1658
- def deparse_explain(node)
1659
- output = ['EXPLAIN']
1660
- options = node.fetch('options', []).map { |option| option['DefElem']['defname'].upcase }
1661
- if options.size == 1
1662
- output.concat(options)
1663
- elsif options.size > 1
1664
- output << "(#{options.join(', ')})"
1665
- end
1666
- output << deparse_item(node['query'])
1667
- output.join(' ')
1668
- end
13
+ # Convenience method for deparsing a statement of a specific type
14
+ def self.deparse_stmt(stmt)
15
+ deparse(PgQuery::ParseResult.new(version: PG_VERSION_NUM, stmts: [PgQuery::RawStmt.new(stmt: PgQuery::Node.from(stmt))]))
16
+ end
1669
17
 
1670
- # The PG parser adds several pieces of view data onto the RANGEVAR
1671
- # that need to be printed before deparse_rangevar is called.
1672
- def relpersistence(rangevar)
1673
- if rangevar[RANGE_VAR]['relpersistence'] == 't'
1674
- 'TEMPORARY'
1675
- elsif rangevar[RANGE_VAR]['relpersistence'] == 'u'
1676
- 'UNLOGGED'
1677
- end
1678
- end
18
+ # Convenience method for deparsing an expression
19
+ def self.deparse_expr(expr)
20
+ deparse_stmt(PgQuery::SelectStmt.new(where_clause: expr, op: :SETOP_NONE)).gsub('SELECT WHERE ', '')
1679
21
  end
1680
22
  end