pg_query 4.2.1 → 5.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (531) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +31 -0
  3. data/README.md +6 -8
  4. data/Rakefile +5 -6
  5. data/ext/pg_query/extconf.rb +14 -4
  6. data/ext/pg_query/include/pg_query.h +27 -3
  7. data/ext/pg_query/include/pg_query_enum_defs.c +311 -149
  8. data/ext/pg_query/include/pg_query_fingerprint_conds.c +545 -489
  9. data/ext/pg_query/include/pg_query_fingerprint_defs.c +5092 -4432
  10. data/ext/pg_query/include/pg_query_outfuncs_conds.c +385 -343
  11. data/ext/pg_query/include/pg_query_outfuncs_defs.c +1294 -1161
  12. data/ext/pg_query/include/pg_query_readfuncs_conds.c +137 -123
  13. data/ext/pg_query/include/pg_query_readfuncs_defs.c +1657 -1496
  14. data/ext/pg_query/include/{access → postgres/access}/amapi.h +3 -1
  15. data/ext/pg_query/include/{access → postgres/access}/attmap.h +5 -3
  16. data/ext/pg_query/include/{access → postgres/access}/attnum.h +1 -1
  17. data/ext/pg_query/include/{access → postgres/access}/clog.h +1 -1
  18. data/ext/pg_query/include/{access → postgres/access}/commit_ts.h +1 -1
  19. data/ext/pg_query/include/{access → postgres/access}/detoast.h +1 -1
  20. data/ext/pg_query/include/{access → postgres/access}/genam.h +7 -5
  21. data/ext/pg_query/include/{access → postgres/access}/gin.h +16 -3
  22. data/ext/pg_query/include/{access → postgres/access}/htup.h +1 -1
  23. data/ext/pg_query/include/{access → postgres/access}/htup_details.h +6 -2
  24. data/ext/pg_query/include/{access → postgres/access}/itup.h +61 -58
  25. data/ext/pg_query/include/{access → postgres/access}/parallel.h +2 -2
  26. data/ext/pg_query/include/{access → postgres/access}/printtup.h +1 -1
  27. data/ext/pg_query/include/{access → postgres/access}/relation.h +1 -1
  28. data/ext/pg_query/include/{access → postgres/access}/relscan.h +1 -1
  29. data/ext/pg_query/include/{access → postgres/access}/rmgrlist.h +2 -2
  30. data/ext/pg_query/include/{access → postgres/access}/sdir.h +12 -3
  31. data/ext/pg_query/include/{access → postgres/access}/skey.h +1 -1
  32. data/ext/pg_query/include/{access → postgres/access}/stratnum.h +1 -1
  33. data/ext/pg_query/include/{access → postgres/access}/sysattr.h +1 -1
  34. data/ext/pg_query/include/{access → postgres/access}/table.h +1 -1
  35. data/ext/pg_query/include/{access → postgres/access}/tableam.h +68 -45
  36. data/ext/pg_query/include/{access → postgres/access}/toast_compression.h +1 -1
  37. data/ext/pg_query/include/{access → postgres/access}/transam.h +1 -1
  38. data/ext/pg_query/include/postgres/access/tsmapi.h +82 -0
  39. data/ext/pg_query/include/{access → postgres/access}/tupconvert.h +5 -2
  40. data/ext/pg_query/include/{access → postgres/access}/tupdesc.h +2 -2
  41. data/ext/pg_query/include/{access → postgres/access}/tupmacs.h +58 -98
  42. data/ext/pg_query/include/{access → postgres/access}/twophase.h +2 -2
  43. data/ext/pg_query/include/{access → postgres/access}/xact.h +25 -18
  44. data/ext/pg_query/include/{access → postgres/access}/xlog.h +15 -16
  45. data/ext/pg_query/include/{access → postgres/access}/xlog_internal.h +100 -62
  46. data/ext/pg_query/include/postgres/access/xlogbackup.h +41 -0
  47. data/ext/pg_query/include/{access → postgres/access}/xlogdefs.h +6 -25
  48. data/ext/pg_query/include/{access → postgres/access}/xlogprefetcher.h +1 -1
  49. data/ext/pg_query/include/{access → postgres/access}/xlogreader.h +7 -6
  50. data/ext/pg_query/include/{access → postgres/access}/xlogrecord.h +17 -5
  51. data/ext/pg_query/include/{access → postgres/access}/xlogrecovery.h +4 -3
  52. data/ext/pg_query/include/postgres/archive/archive_module.h +59 -0
  53. data/ext/pg_query/include/{c.h → postgres/c.h} +144 -156
  54. data/ext/pg_query/include/{catalog → postgres/catalog}/catalog.h +4 -3
  55. data/ext/pg_query/include/{catalog → postgres/catalog}/catversion.h +6 -2
  56. data/ext/pg_query/include/{catalog → postgres/catalog}/dependency.h +5 -4
  57. data/ext/pg_query/include/{catalog → postgres/catalog}/genbki.h +7 -6
  58. data/ext/pg_query/include/{catalog → postgres/catalog}/index.h +4 -4
  59. data/ext/pg_query/include/{catalog → postgres/catalog}/indexing.h +1 -1
  60. data/ext/pg_query/include/{catalog → postgres/catalog}/namespace.h +2 -2
  61. data/ext/pg_query/include/{catalog → postgres/catalog}/objectaccess.h +10 -8
  62. data/ext/pg_query/include/{catalog → postgres/catalog}/objectaddress.h +3 -3
  63. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_aggregate.h +1 -1
  64. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_aggregate_d.h +1 -1
  65. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_am.h +1 -1
  66. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_am_d.h +1 -1
  67. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_attribute.h +19 -17
  68. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_attribute_d.h +19 -19
  69. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_authid.h +1 -1
  70. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_authid_d.h +3 -1
  71. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_class.h +1 -1
  72. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_class_d.h +1 -1
  73. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_collation.h +3 -1
  74. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_collation_d.h +4 -3
  75. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_constraint.h +2 -2
  76. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_constraint_d.h +1 -1
  77. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_control.h +9 -1
  78. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_conversion.h +2 -2
  79. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_conversion_d.h +1 -1
  80. data/ext/pg_query/include/postgres/catalog/pg_database.h +124 -0
  81. data/ext/pg_query/include/postgres/catalog/pg_database_d.h +52 -0
  82. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_depend.h +1 -1
  83. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_depend_d.h +1 -1
  84. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_event_trigger.h +1 -1
  85. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_event_trigger_d.h +1 -1
  86. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_index.h +1 -1
  87. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_index_d.h +1 -1
  88. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_language.h +1 -1
  89. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_language_d.h +1 -1
  90. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_namespace.h +1 -1
  91. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_namespace_d.h +1 -1
  92. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_opclass.h +1 -1
  93. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_opclass_d.h +1 -1
  94. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_operator.h +1 -1
  95. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_operator_d.h +1 -1
  96. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_opfamily.h +3 -2
  97. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_opfamily_d.h +4 -2
  98. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_partitioned_table.h +1 -1
  99. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_partitioned_table_d.h +1 -1
  100. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_proc.h +1 -1
  101. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_proc_d.h +1 -1
  102. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_publication.h +2 -5
  103. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_publication_d.h +1 -1
  104. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_replication_origin.h +1 -1
  105. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_replication_origin_d.h +1 -1
  106. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_statistic.h +1 -1
  107. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_statistic_d.h +1 -1
  108. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_statistic_ext.h +1 -1
  109. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_statistic_ext_d.h +1 -1
  110. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_transform.h +1 -1
  111. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_transform_d.h +1 -1
  112. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_trigger.h +1 -1
  113. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_trigger_d.h +1 -1
  114. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_ts_config.h +1 -1
  115. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_ts_config_d.h +1 -1
  116. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_ts_dict.h +1 -1
  117. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_ts_dict_d.h +1 -1
  118. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_ts_parser.h +1 -1
  119. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_ts_parser_d.h +1 -1
  120. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_ts_template.h +1 -1
  121. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_ts_template_d.h +1 -1
  122. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_type.h +1 -1
  123. data/ext/pg_query/include/{catalog → postgres/catalog}/pg_type_d.h +1 -1
  124. data/ext/pg_query/include/{catalog → postgres/catalog}/storage.h +6 -6
  125. data/ext/pg_query/include/{commands → postgres/commands}/async.h +1 -1
  126. data/ext/pg_query/include/{commands → postgres/commands}/dbcommands.h +2 -1
  127. data/ext/pg_query/include/{commands → postgres/commands}/defrem.h +2 -1
  128. data/ext/pg_query/include/{commands → postgres/commands}/event_trigger.h +1 -1
  129. data/ext/pg_query/include/{commands → postgres/commands}/explain.h +3 -1
  130. data/ext/pg_query/include/{commands → postgres/commands}/prepare.h +1 -1
  131. data/ext/pg_query/include/{commands → postgres/commands}/tablespace.h +4 -4
  132. data/ext/pg_query/include/{commands → postgres/commands}/trigger.h +15 -14
  133. data/ext/pg_query/include/{commands → postgres/commands}/user.h +9 -3
  134. data/ext/pg_query/include/{commands → postgres/commands}/vacuum.h +60 -14
  135. data/ext/pg_query/include/postgres/common/cryptohash.h +39 -0
  136. data/ext/pg_query/include/{common → postgres/common}/file_perm.h +1 -1
  137. data/ext/pg_query/include/{common → postgres/common}/hashfn.h +1 -1
  138. data/ext/pg_query/include/postgres/common/int.h +437 -0
  139. data/ext/pg_query/include/{common → postgres/common}/keywords.h +1 -1
  140. data/ext/pg_query/include/{common → postgres/common}/kwlookup.h +2 -2
  141. data/ext/pg_query/include/{common → postgres/common}/pg_prng.h +3 -2
  142. data/ext/pg_query/include/{common → postgres/common}/relpath.h +20 -13
  143. data/ext/pg_query/include/postgres/common/scram-common.h +70 -0
  144. data/ext/pg_query/include/postgres/common/sha2.h +32 -0
  145. data/ext/pg_query/include/{common → postgres/common}/string.h +5 -3
  146. data/ext/pg_query/include/{common → postgres/common}/unicode_east_asian_fw_table.h +10 -10
  147. data/ext/pg_query/include/{common/unicode_combining_table.h → postgres/common/unicode_nonspacing_table.h} +31 -13
  148. data/ext/pg_query/include/postgres/copyfuncs.funcs.c +5013 -0
  149. data/ext/pg_query/include/postgres/copyfuncs.switch.c +938 -0
  150. data/ext/pg_query/include/{datatype → postgres/datatype}/timestamp.h +11 -4
  151. data/ext/pg_query/include/postgres/equalfuncs.funcs.c +3097 -0
  152. data/ext/pg_query/include/postgres/equalfuncs.switch.c +785 -0
  153. data/ext/pg_query/include/{executor → postgres/executor}/execdesc.h +1 -1
  154. data/ext/pg_query/include/{executor → postgres/executor}/executor.h +34 -17
  155. data/ext/pg_query/include/{executor → postgres/executor}/functions.h +1 -1
  156. data/ext/pg_query/include/{executor → postgres/executor}/instrument.h +1 -1
  157. data/ext/pg_query/include/{executor → postgres/executor}/spi.h +2 -2
  158. data/ext/pg_query/include/{executor → postgres/executor}/tablefunc.h +1 -1
  159. data/ext/pg_query/include/{executor → postgres/executor}/tuptable.h +18 -11
  160. data/ext/pg_query/include/{fmgr.h → postgres/fmgr.h} +21 -2
  161. data/ext/pg_query/include/postgres/foreign/fdwapi.h +294 -0
  162. data/ext/pg_query/include/{funcapi.h → postgres/funcapi.h} +12 -12
  163. data/ext/pg_query/include/postgres/gram.h +1127 -0
  164. data/ext/pg_query/include/{parser → postgres}/gramparse.h +4 -4
  165. data/ext/pg_query/include/{jit → postgres/jit}/jit.h +2 -2
  166. data/ext/pg_query/include/postgres/kwlist_d.h +1119 -0
  167. data/ext/pg_query/include/{lib → postgres/lib}/dshash.h +4 -1
  168. data/ext/pg_query/include/{lib → postgres/lib}/ilist.h +435 -22
  169. data/ext/pg_query/include/{lib → postgres/lib}/pairingheap.h +1 -1
  170. data/ext/pg_query/include/{lib → postgres/lib}/simplehash.h +9 -9
  171. data/ext/pg_query/include/{lib → postgres/lib}/sort_template.h +1 -1
  172. data/ext/pg_query/include/{lib → postgres/lib}/stringinfo.h +3 -3
  173. data/ext/pg_query/include/{libpq → postgres/libpq}/auth.h +8 -2
  174. data/ext/pg_query/include/{libpq → postgres/libpq}/crypt.h +1 -1
  175. data/ext/pg_query/include/{libpq → postgres/libpq}/hba.h +24 -17
  176. data/ext/pg_query/include/{libpq → postgres/libpq}/libpq-be.h +36 -25
  177. data/ext/pg_query/include/{libpq → postgres/libpq}/libpq.h +1 -1
  178. data/ext/pg_query/include/{libpq → postgres/libpq}/pqcomm.h +10 -41
  179. data/ext/pg_query/include/{libpq → postgres/libpq}/pqformat.h +2 -2
  180. data/ext/pg_query/include/{libpq → postgres/libpq}/pqsignal.h +22 -10
  181. data/ext/pg_query/include/postgres/libpq/sasl.h +136 -0
  182. data/ext/pg_query/include/postgres/libpq/scram.h +37 -0
  183. data/ext/pg_query/include/{mb → postgres/mb}/pg_wchar.h +35 -18
  184. data/ext/pg_query/include/{mb → postgres/mb}/stringinfo_mb.h +1 -1
  185. data/ext/pg_query/include/{miscadmin.h → postgres/miscadmin.h} +27 -15
  186. data/ext/pg_query/include/{nodes → postgres/nodes}/bitmapset.h +11 -7
  187. data/ext/pg_query/include/{nodes → postgres/nodes}/execnodes.h +83 -30
  188. data/ext/pg_query/include/{nodes → postgres/nodes}/extensible.h +5 -3
  189. data/ext/pg_query/include/{nodes → postgres/nodes}/lockoptions.h +1 -1
  190. data/ext/pg_query/include/{nodes → postgres/nodes}/makefuncs.h +14 -2
  191. data/ext/pg_query/include/{nodes → postgres/nodes}/memnodes.h +7 -4
  192. data/ext/pg_query/include/postgres/nodes/miscnodes.h +56 -0
  193. data/ext/pg_query/include/{nodes → postgres/nodes}/nodeFuncs.h +89 -29
  194. data/ext/pg_query/include/{nodes → postgres/nodes}/nodes.h +96 -511
  195. data/ext/pg_query/include/postgres/nodes/nodetags.h +471 -0
  196. data/ext/pg_query/include/{nodes → postgres/nodes}/params.h +3 -3
  197. data/ext/pg_query/include/{nodes → postgres/nodes}/parsenodes.h +377 -139
  198. data/ext/pg_query/include/{nodes → postgres/nodes}/pathnodes.h +1090 -440
  199. data/ext/pg_query/include/{nodes → postgres/nodes}/pg_list.h +30 -7
  200. data/ext/pg_query/include/{nodes → postgres/nodes}/plannodes.h +367 -124
  201. data/ext/pg_query/include/{nodes → postgres/nodes}/primnodes.h +670 -222
  202. data/ext/pg_query/include/{nodes → postgres/nodes}/print.h +1 -1
  203. data/ext/pg_query/include/{utils → postgres/nodes}/queryjumble.h +5 -7
  204. data/ext/pg_query/include/postgres/nodes/replnodes.h +111 -0
  205. data/ext/pg_query/include/postgres/nodes/supportnodes.h +346 -0
  206. data/ext/pg_query/include/{nodes → postgres/nodes}/tidbitmap.h +1 -1
  207. data/ext/pg_query/include/{nodes → postgres/nodes}/value.h +12 -2
  208. data/ext/pg_query/include/{optimizer → postgres/optimizer}/cost.h +6 -4
  209. data/ext/pg_query/include/{optimizer → postgres/optimizer}/geqo.h +1 -1
  210. data/ext/pg_query/include/{optimizer → postgres/optimizer}/geqo_gene.h +1 -1
  211. data/ext/pg_query/include/{optimizer → postgres/optimizer}/optimizer.h +8 -8
  212. data/ext/pg_query/include/{optimizer → postgres/optimizer}/paths.h +16 -7
  213. data/ext/pg_query/include/{optimizer → postgres/optimizer}/planmain.h +3 -6
  214. data/ext/pg_query/include/{parser → postgres/parser}/analyze.h +4 -3
  215. data/ext/pg_query/include/{parser → postgres/parser}/kwlist.h +12 -1
  216. data/ext/pg_query/include/{parser → postgres/parser}/parse_agg.h +4 -2
  217. data/ext/pg_query/include/{parser → postgres/parser}/parse_coerce.h +3 -1
  218. data/ext/pg_query/include/{parser → postgres/parser}/parse_expr.h +1 -1
  219. data/ext/pg_query/include/{parser → postgres/parser}/parse_func.h +1 -1
  220. data/ext/pg_query/include/{parser → postgres/parser}/parse_node.h +22 -4
  221. data/ext/pg_query/include/{parser → postgres/parser}/parse_oper.h +3 -3
  222. data/ext/pg_query/include/{parser → postgres/parser}/parse_relation.h +8 -3
  223. data/ext/pg_query/include/{parser → postgres/parser}/parse_type.h +4 -3
  224. data/ext/pg_query/include/{parser → postgres/parser}/parser.h +4 -4
  225. data/ext/pg_query/include/{parser → postgres/parser}/parsetree.h +1 -1
  226. data/ext/pg_query/include/{parser → postgres/parser}/scanner.h +2 -2
  227. data/ext/pg_query/include/{parser → postgres/parser}/scansup.h +1 -1
  228. data/ext/pg_query/include/{partitioning → postgres/partitioning}/partdefs.h +1 -1
  229. data/ext/pg_query/include/{pg_config.h → postgres/pg_config.h} +158 -218
  230. data/ext/pg_query/include/{pg_config_manual.h → postgres/pg_config_manual.h} +8 -46
  231. data/ext/pg_query/include/postgres/pg_config_os.h +8 -0
  232. data/ext/pg_query/include/{pg_getopt.h → postgres/pg_getopt.h} +1 -1
  233. data/ext/pg_query/include/{pg_trace.h → postgres/pg_trace.h} +1 -1
  234. data/ext/pg_query/include/{pgstat.h → postgres/pgstat.h} +173 -94
  235. data/ext/pg_query/include/{pgtime.h → postgres/pgtime.h} +3 -3
  236. data/ext/pg_query/include/{pl_gram.h → postgres/pl_gram.h} +66 -64
  237. data/ext/pg_query/include/{pl_reserved_kwlist.h → postgres/pl_reserved_kwlist.h} +1 -1
  238. data/ext/pg_query/include/{pl_reserved_kwlist_d.h → postgres/pl_reserved_kwlist_d.h} +1 -1
  239. data/ext/pg_query/include/{pl_unreserved_kwlist.h → postgres/pl_unreserved_kwlist.h} +2 -1
  240. data/ext/pg_query/include/{pl_unreserved_kwlist_d.h → postgres/pl_unreserved_kwlist_d.h} +48 -46
  241. data/ext/pg_query/include/{plpgsql.h → postgres/plpgsql.h} +28 -33
  242. data/ext/pg_query/include/{port → postgres/port}/atomics/arch-arm.h +3 -3
  243. data/ext/pg_query/include/postgres/port/atomics/arch-hppa.h +17 -0
  244. data/ext/pg_query/include/{port → postgres/port}/atomics/arch-ppc.h +21 -21
  245. data/ext/pg_query/include/{port → postgres/port}/atomics/arch-x86.h +2 -2
  246. data/ext/pg_query/include/{port → postgres/port}/atomics/fallback.h +3 -3
  247. data/ext/pg_query/include/{port → postgres/port}/atomics/generic-gcc.h +1 -1
  248. data/ext/pg_query/include/postgres/port/atomics/generic-msvc.h +101 -0
  249. data/ext/pg_query/include/postgres/port/atomics/generic-sunpro.h +106 -0
  250. data/ext/pg_query/include/{port → postgres/port}/atomics/generic.h +1 -1
  251. data/ext/pg_query/include/{port → postgres/port}/atomics.h +2 -7
  252. data/ext/pg_query/include/{port → postgres/port}/pg_bitutils.h +62 -25
  253. data/ext/pg_query/include/{port → postgres/port}/pg_bswap.h +1 -1
  254. data/ext/pg_query/include/{port → postgres/port}/pg_crc32c.h +1 -1
  255. data/ext/pg_query/include/postgres/port/simd.h +375 -0
  256. data/ext/pg_query/include/postgres/port/win32/arpa/inet.h +3 -0
  257. data/ext/pg_query/include/postgres/port/win32/dlfcn.h +1 -0
  258. data/ext/pg_query/include/postgres/port/win32/grp.h +1 -0
  259. data/ext/pg_query/include/postgres/port/win32/netdb.h +7 -0
  260. data/ext/pg_query/include/postgres/port/win32/netinet/in.h +3 -0
  261. data/ext/pg_query/include/postgres/port/win32/netinet/tcp.h +7 -0
  262. data/ext/pg_query/include/postgres/port/win32/pwd.h +3 -0
  263. data/ext/pg_query/include/postgres/port/win32/sys/resource.h +20 -0
  264. data/ext/pg_query/include/postgres/port/win32/sys/select.h +3 -0
  265. data/ext/pg_query/include/postgres/port/win32/sys/socket.h +26 -0
  266. data/ext/pg_query/include/postgres/port/win32/sys/un.h +17 -0
  267. data/ext/pg_query/include/postgres/port/win32/sys/wait.h +3 -0
  268. data/ext/pg_query/include/postgres/port/win32.h +59 -0
  269. data/ext/pg_query/include/postgres/port/win32_msvc/dirent.h +34 -0
  270. data/ext/pg_query/include/postgres/port/win32_msvc/sys/file.h +1 -0
  271. data/ext/pg_query/include/postgres/port/win32_msvc/sys/param.h +1 -0
  272. data/ext/pg_query/include/postgres/port/win32_msvc/sys/time.h +1 -0
  273. data/ext/pg_query/include/postgres/port/win32_msvc/unistd.h +9 -0
  274. data/ext/pg_query/include/postgres/port/win32_msvc/utime.h +3 -0
  275. data/ext/pg_query/include/postgres/port/win32_port.h +594 -0
  276. data/ext/pg_query/include/{port.h → postgres/port.h} +42 -75
  277. data/ext/pg_query/include/postgres/portability/instr_time.h +197 -0
  278. data/ext/pg_query/include/postgres/postgres.h +579 -0
  279. data/ext/pg_query/include/{postgres_ext.h → postgres/postgres_ext.h} +0 -1
  280. data/ext/pg_query/include/{postmaster → postgres/postmaster}/autovacuum.h +1 -4
  281. data/ext/pg_query/include/{postmaster → postgres/postmaster}/bgworker.h +2 -2
  282. data/ext/pg_query/include/{postmaster → postgres/postmaster}/bgworker_internals.h +1 -1
  283. data/ext/pg_query/include/{postmaster → postgres/postmaster}/bgwriter.h +2 -2
  284. data/ext/pg_query/include/{postmaster → postgres/postmaster}/interrupt.h +1 -1
  285. data/ext/pg_query/include/postgres/postmaster/pgarch.h +36 -0
  286. data/ext/pg_query/include/{postmaster → postgres/postmaster}/postmaster.h +6 -3
  287. data/ext/pg_query/include/{postmaster → postgres/postmaster}/startup.h +3 -1
  288. data/ext/pg_query/include/{postmaster → postgres/postmaster}/syslogger.h +2 -2
  289. data/ext/pg_query/include/{postmaster → postgres/postmaster}/walwriter.h +3 -1
  290. data/ext/pg_query/include/{regex → postgres/regex}/regex.h +9 -6
  291. data/ext/pg_query/include/{replication → postgres/replication}/logicallauncher.h +6 -1
  292. data/ext/pg_query/include/{replication → postgres/replication}/logicalproto.h +30 -10
  293. data/ext/pg_query/include/postgres/replication/logicalworker.h +32 -0
  294. data/ext/pg_query/include/{replication → postgres/replication}/origin.h +4 -4
  295. data/ext/pg_query/include/{replication → postgres/replication}/reorderbuffer.h +113 -45
  296. data/ext/pg_query/include/{replication → postgres/replication}/slot.h +25 -6
  297. data/ext/pg_query/include/{replication → postgres/replication}/syncrep.h +2 -8
  298. data/ext/pg_query/include/{replication → postgres/replication}/walreceiver.h +15 -9
  299. data/ext/pg_query/include/{replication → postgres/replication}/walsender.h +13 -13
  300. data/ext/pg_query/include/{rewrite → postgres/rewrite}/prs2lock.h +1 -1
  301. data/ext/pg_query/include/{rewrite → postgres/rewrite}/rewriteHandler.h +1 -4
  302. data/ext/pg_query/include/{rewrite → postgres/rewrite}/rewriteManip.h +11 -2
  303. data/ext/pg_query/include/{rewrite → postgres/rewrite}/rewriteSupport.h +1 -1
  304. data/ext/pg_query/include/{storage → postgres/storage}/backendid.h +1 -1
  305. data/ext/pg_query/include/{storage → postgres/storage}/block.h +24 -31
  306. data/ext/pg_query/include/{storage → postgres/storage}/buf.h +1 -1
  307. data/ext/pg_query/include/{storage → postgres/storage}/bufmgr.h +183 -87
  308. data/ext/pg_query/include/{storage → postgres/storage}/bufpage.h +146 -93
  309. data/ext/pg_query/include/{storage → postgres/storage}/condition_variable.h +2 -2
  310. data/ext/pg_query/include/{storage → postgres/storage}/dsm.h +3 -6
  311. data/ext/pg_query/include/{storage → postgres/storage}/dsm_impl.h +4 -1
  312. data/ext/pg_query/include/{storage → postgres/storage}/fd.h +24 -20
  313. data/ext/pg_query/include/{storage → postgres/storage}/fileset.h +1 -1
  314. data/ext/pg_query/include/{storage → postgres/storage}/ipc.h +2 -2
  315. data/ext/pg_query/include/{storage → postgres/storage}/item.h +1 -1
  316. data/ext/pg_query/include/{storage → postgres/storage}/itemid.h +1 -1
  317. data/ext/pg_query/include/{storage → postgres/storage}/itemptr.h +94 -57
  318. data/ext/pg_query/include/{storage → postgres/storage}/large_object.h +1 -1
  319. data/ext/pg_query/include/{storage → postgres/storage}/latch.h +9 -1
  320. data/ext/pg_query/include/{storage → postgres/storage}/lmgr.h +6 -1
  321. data/ext/pg_query/include/{storage → postgres/storage}/lock.h +21 -13
  322. data/ext/pg_query/include/{storage → postgres/storage}/lockdefs.h +3 -3
  323. data/ext/pg_query/include/{storage → postgres/storage}/lwlock.h +16 -2
  324. data/ext/pg_query/include/{storage → postgres/storage}/off.h +1 -1
  325. data/ext/pg_query/include/{storage → postgres/storage}/pg_sema.h +1 -1
  326. data/ext/pg_query/include/{storage → postgres/storage}/pg_shmem.h +1 -1
  327. data/ext/pg_query/include/{storage → postgres/storage}/pmsignal.h +1 -1
  328. data/ext/pg_query/include/{storage → postgres/storage}/predicate.h +2 -2
  329. data/ext/pg_query/include/{storage → postgres/storage}/proc.h +22 -17
  330. data/ext/pg_query/include/{storage → postgres/storage}/procarray.h +3 -2
  331. data/ext/pg_query/include/{storage → postgres/storage}/proclist_types.h +1 -1
  332. data/ext/pg_query/include/{storage → postgres/storage}/procsignal.h +3 -1
  333. data/ext/pg_query/include/postgres/storage/relfilelocator.h +99 -0
  334. data/ext/pg_query/include/{storage → postgres/storage}/s_lock.h +66 -309
  335. data/ext/pg_query/include/{storage → postgres/storage}/sharedfileset.h +1 -1
  336. data/ext/pg_query/include/{storage → postgres/storage}/shm_mq.h +1 -1
  337. data/ext/pg_query/include/{storage → postgres/storage}/shm_toc.h +1 -1
  338. data/ext/pg_query/include/{storage → postgres/storage}/shmem.h +1 -23
  339. data/ext/pg_query/include/{storage → postgres/storage}/sinval.h +3 -3
  340. data/ext/pg_query/include/{storage → postgres/storage}/sinvaladt.h +4 -2
  341. data/ext/pg_query/include/{storage → postgres/storage}/smgr.h +12 -10
  342. data/ext/pg_query/include/{storage → postgres/storage}/spin.h +1 -1
  343. data/ext/pg_query/include/{storage → postgres/storage}/standby.h +9 -8
  344. data/ext/pg_query/include/{storage → postgres/storage}/standbydefs.h +1 -1
  345. data/ext/pg_query/include/{storage → postgres/storage}/sync.h +3 -3
  346. data/ext/pg_query/include/{tcop → postgres/tcop}/cmdtag.h +7 -2
  347. data/ext/pg_query/include/{tcop → postgres/tcop}/cmdtaglist.h +1 -1
  348. data/ext/pg_query/include/{tcop → postgres/tcop}/deparse_utility.h +1 -1
  349. data/ext/pg_query/include/{tcop → postgres/tcop}/dest.h +1 -3
  350. data/ext/pg_query/include/{tcop → postgres/tcop}/fastpath.h +1 -1
  351. data/ext/pg_query/include/{tcop → postgres/tcop}/pquery.h +1 -1
  352. data/ext/pg_query/include/{tcop → postgres/tcop}/tcopprot.h +3 -6
  353. data/ext/pg_query/include/{tcop → postgres/tcop}/utility.h +1 -1
  354. data/ext/pg_query/include/{tsearch → postgres/tsearch}/ts_cache.h +2 -4
  355. data/ext/pg_query/include/{utils → postgres/utils}/acl.h +26 -81
  356. data/ext/pg_query/include/{utils → postgres/utils}/aclchk_internal.h +1 -1
  357. data/ext/pg_query/include/{utils → postgres/utils}/array.h +19 -1
  358. data/ext/pg_query/include/{utils → postgres/utils}/backend_progress.h +2 -1
  359. data/ext/pg_query/include/{utils → postgres/utils}/backend_status.h +24 -3
  360. data/ext/pg_query/include/{utils → postgres/utils}/builtins.h +15 -6
  361. data/ext/pg_query/include/{utils → postgres/utils}/bytea.h +1 -1
  362. data/ext/pg_query/include/{utils → postgres/utils}/catcache.h +1 -1
  363. data/ext/pg_query/include/{utils → postgres/utils}/date.h +37 -9
  364. data/ext/pg_query/include/{utils → postgres/utils}/datetime.h +41 -21
  365. data/ext/pg_query/include/{utils → postgres/utils}/datum.h +1 -1
  366. data/ext/pg_query/include/{utils → postgres/utils}/dsa.h +5 -1
  367. data/ext/pg_query/include/{utils → postgres/utils}/elog.h +104 -29
  368. data/ext/pg_query/include/{utils → postgres/utils}/expandeddatum.h +14 -3
  369. data/ext/pg_query/include/{utils → postgres/utils}/expandedrecord.h +14 -4
  370. data/ext/pg_query/include/{utils → postgres/utils}/float.h +7 -6
  371. data/ext/pg_query/include/{utils → postgres/utils}/fmgroids.h +54 -1
  372. data/ext/pg_query/include/{utils → postgres/utils}/fmgrprotos.h +45 -3
  373. data/ext/pg_query/include/{utils → postgres/utils}/fmgrtab.h +1 -1
  374. data/ext/pg_query/include/{utils → postgres/utils}/guc.h +59 -86
  375. data/ext/pg_query/include/postgres/utils/guc_hooks.h +163 -0
  376. data/ext/pg_query/include/{utils → postgres/utils}/guc_tables.h +49 -3
  377. data/ext/pg_query/include/{utils → postgres/utils}/hsearch.h +1 -1
  378. data/ext/pg_query/include/{utils → postgres/utils}/inval.h +3 -3
  379. data/ext/pg_query/include/postgres/utils/logtape.h +77 -0
  380. data/ext/pg_query/include/{utils → postgres/utils}/lsyscache.h +5 -1
  381. data/ext/pg_query/include/{utils → postgres/utils}/memdebug.h +1 -1
  382. data/ext/pg_query/include/{utils → postgres/utils}/memutils.h +7 -51
  383. data/ext/pg_query/include/postgres/utils/memutils_internal.h +136 -0
  384. data/ext/pg_query/include/postgres/utils/memutils_memorychunk.h +237 -0
  385. data/ext/pg_query/include/{utils → postgres/utils}/numeric.h +20 -5
  386. data/ext/pg_query/include/{utils → postgres/utils}/palloc.h +9 -2
  387. data/ext/pg_query/include/{utils → postgres/utils}/partcache.h +3 -2
  388. data/ext/pg_query/include/{utils → postgres/utils}/pg_locale.h +22 -14
  389. data/ext/pg_query/include/{utils → postgres/utils}/pgstat_internal.h +37 -7
  390. data/ext/pg_query/include/{utils → postgres/utils}/plancache.h +1 -1
  391. data/ext/pg_query/include/{utils → postgres/utils}/portal.h +1 -1
  392. data/ext/pg_query/include/{utils → postgres/utils}/probes.h +6 -6
  393. data/ext/pg_query/include/postgres/utils/ps_status.h +47 -0
  394. data/ext/pg_query/include/{utils → postgres/utils}/queryenvironment.h +1 -1
  395. data/ext/pg_query/include/{utils → postgres/utils}/regproc.h +3 -3
  396. data/ext/pg_query/include/{utils → postgres/utils}/rel.h +60 -43
  397. data/ext/pg_query/include/{utils → postgres/utils}/relcache.h +13 -8
  398. data/ext/pg_query/include/{utils → postgres/utils}/reltrigger.h +1 -1
  399. data/ext/pg_query/include/{utils → postgres/utils}/resowner.h +1 -1
  400. data/ext/pg_query/include/{utils → postgres/utils}/ruleutils.h +6 -1
  401. data/ext/pg_query/include/{utils → postgres/utils}/sharedtuplestore.h +1 -1
  402. data/ext/pg_query/include/{utils → postgres/utils}/snapmgr.h +4 -2
  403. data/ext/pg_query/include/{utils → postgres/utils}/snapshot.h +1 -1
  404. data/ext/pg_query/include/{utils → postgres/utils}/sortsupport.h +2 -2
  405. data/ext/pg_query/include/{utils → postgres/utils}/syscache.h +4 -1
  406. data/ext/pg_query/include/{utils → postgres/utils}/timeout.h +1 -1
  407. data/ext/pg_query/include/{utils → postgres/utils}/timestamp.h +41 -11
  408. data/ext/pg_query/include/{utils → postgres/utils}/tuplesort.h +189 -35
  409. data/ext/pg_query/include/{utils → postgres/utils}/tuplestore.h +1 -1
  410. data/ext/pg_query/include/{utils → postgres/utils}/typcache.h +1 -1
  411. data/ext/pg_query/include/{utils → postgres/utils}/varlena.h +13 -1
  412. data/ext/pg_query/include/{utils → postgres/utils}/wait_event.h +9 -4
  413. data/ext/pg_query/include/{utils → postgres/utils}/xml.h +15 -5
  414. data/ext/pg_query/include/{postgres.h → postgres/varatt.h} +7 -457
  415. data/ext/pg_query/include/protobuf/pg_query.pb-c.h +6186 -5585
  416. data/ext/pg_query/include/protobuf/pg_query.pb.h +112443 -91222
  417. data/ext/pg_query/pg_query.c +10 -1
  418. data/ext/pg_query/pg_query.pb-c.c +19755 -17757
  419. data/ext/pg_query/pg_query_deparse.c +1 -10635
  420. data/ext/pg_query/pg_query_fingerprint.c +12 -8
  421. data/ext/pg_query/pg_query_fingerprint.h +1 -1
  422. data/ext/pg_query/pg_query_internal.h +1 -1
  423. data/ext/pg_query/pg_query_json_plpgsql.c +1 -0
  424. data/ext/pg_query/pg_query_normalize.c +1 -1
  425. data/ext/pg_query/pg_query_outfuncs_json.c +6 -0
  426. data/ext/pg_query/pg_query_outfuncs_protobuf.c +3 -2
  427. data/ext/pg_query/pg_query_parse.c +47 -5
  428. data/ext/pg_query/pg_query_parse_plpgsql.c +7 -5
  429. data/ext/pg_query/pg_query_readfuncs_protobuf.c +1 -0
  430. data/ext/pg_query/pg_query_ruby.c +5 -0
  431. data/ext/pg_query/pg_query_ruby_freebsd.sym +2 -0
  432. data/ext/pg_query/pg_query_scan.c +1 -1
  433. data/ext/pg_query/pg_query_split.c +3 -3
  434. data/ext/pg_query/postgres_deparse.c +11067 -0
  435. data/ext/pg_query/postgres_deparse.h +9 -0
  436. data/ext/pg_query/src_backend_catalog_namespace.c +7 -2
  437. data/ext/pg_query/src_backend_catalog_pg_proc.c +1 -1
  438. data/ext/pg_query/src_backend_commands_define.c +1 -1
  439. data/ext/pg_query/src_backend_nodes_bitmapset.c +11 -70
  440. data/ext/pg_query/src_backend_nodes_copyfuncs.c +96 -6202
  441. data/ext/pg_query/src_backend_nodes_equalfuncs.c +95 -4068
  442. data/ext/pg_query/src_backend_nodes_extensible.c +6 -29
  443. data/ext/pg_query/src_backend_nodes_list.c +14 -2
  444. data/ext/pg_query/src_backend_nodes_makefuncs.c +95 -1
  445. data/ext/pg_query/src_backend_nodes_nodeFuncs.c +283 -132
  446. data/ext/pg_query/src_backend_nodes_nodes.c +38 -0
  447. data/ext/pg_query/src_backend_nodes_value.c +1 -1
  448. data/ext/pg_query/src_backend_parser_gram.c +33208 -31806
  449. data/ext/pg_query/src_backend_parser_parser.c +28 -2
  450. data/ext/pg_query/src_backend_parser_scan.c +4318 -3329
  451. data/ext/pg_query/src_backend_parser_scansup.c +1 -1
  452. data/ext/pg_query/src_backend_storage_ipc_ipc.c +1 -1
  453. data/ext/pg_query/src_backend_tcop_postgres.c +66 -87
  454. data/ext/pg_query/src_backend_utils_activity_pgstat_database.c +1 -1
  455. data/ext/pg_query/src_backend_utils_adt_datum.c +5 -7
  456. data/ext/pg_query/src_backend_utils_adt_expandeddatum.c +1 -1
  457. data/ext/pg_query/src_backend_utils_adt_format_type.c +1 -1
  458. data/ext/pg_query/src_backend_utils_adt_numutils.c +489 -0
  459. data/ext/pg_query/src_backend_utils_adt_ruleutils.c +79 -5
  460. data/ext/pg_query/src_backend_utils_error_assert.c +4 -7
  461. data/ext/pg_query/src_backend_utils_error_elog.c +371 -249
  462. data/ext/pg_query/src_backend_utils_fmgr_fmgr.c +33 -1
  463. data/ext/pg_query/src_backend_utils_init_globals.c +6 -3
  464. data/ext/pg_query/src_backend_utils_mb_mbutils.c +21 -67
  465. data/ext/pg_query/src_backend_utils_misc_guc_tables.c +492 -0
  466. data/ext/pg_query/src_backend_utils_mmgr_alignedalloc.c +163 -0
  467. data/ext/pg_query/src_backend_utils_mmgr_aset.c +449 -312
  468. data/ext/pg_query/src_backend_utils_mmgr_generation.c +1039 -0
  469. data/ext/pg_query/src_backend_utils_mmgr_mcxt.c +398 -49
  470. data/ext/pg_query/src_backend_utils_mmgr_slab.c +1021 -0
  471. data/ext/pg_query/src_common_encnames.c +4 -1
  472. data/ext/pg_query/src_common_hashfn.c +1 -1
  473. data/ext/pg_query/src_common_keywords.c +1 -1
  474. data/ext/pg_query/src_common_kwlist_d.h +534 -510
  475. data/ext/pg_query/src_common_kwlookup.c +1 -1
  476. data/ext/pg_query/src_common_psprintf.c +1 -1
  477. data/ext/pg_query/src_common_stringinfo.c +4 -4
  478. data/ext/pg_query/src_common_wchar.c +9 -8
  479. data/ext/pg_query/src_pl_plpgsql_src_pl_comp.c +1 -1
  480. data/ext/pg_query/src_pl_plpgsql_src_pl_funcs.c +3 -1
  481. data/ext/pg_query/src_pl_plpgsql_src_pl_gram.c +661 -694
  482. data/ext/pg_query/src_pl_plpgsql_src_pl_handler.c +1 -1
  483. data/ext/pg_query/src_pl_plpgsql_src_pl_reserved_kwlist_d.h +1 -1
  484. data/ext/pg_query/src_pl_plpgsql_src_pl_scanner.c +1 -1
  485. data/ext/pg_query/src_pl_plpgsql_src_pl_unreserved_kwlist_d.h +48 -46
  486. data/ext/pg_query/src_port_pg_bitutils.c +79 -5
  487. data/ext/pg_query/src_port_pgstrcasecmp.c +29 -1
  488. data/ext/pg_query/src_port_snprintf.c +6 -10
  489. data/ext/pg_query/src_port_strerror.c +1 -1
  490. data/ext/pg_query/src_port_strlcpy.c +79 -0
  491. data/lib/pg_query/fingerprint.rb +2 -3
  492. data/lib/pg_query/node.rb +16 -11
  493. data/lib/pg_query/parse.rb +1 -1
  494. data/lib/pg_query/pg_query_pb.rb +166 -3191
  495. data/lib/pg_query/treewalker.rb +23 -5
  496. data/lib/pg_query/version.rb +1 -1
  497. metadata +432 -380
  498. data/ext/pg_query/guc-file.c +0 -0
  499. data/ext/pg_query/include/catalog/pg_parameter_acl.h +0 -60
  500. data/ext/pg_query/include/catalog/pg_parameter_acl_d.h +0 -34
  501. data/ext/pg_query/include/commands/variable.h +0 -38
  502. data/ext/pg_query/include/common/ip.h +0 -31
  503. data/ext/pg_query/include/getaddrinfo.h +0 -162
  504. data/ext/pg_query/include/kwlist_d.h +0 -1095
  505. data/ext/pg_query/include/parser/gram.h +0 -1101
  506. data/ext/pg_query/include/pg_config_os.h +0 -8
  507. data/ext/pg_query/include/portability/instr_time.h +0 -256
  508. data/ext/pg_query/include/postmaster/auxprocess.h +0 -20
  509. data/ext/pg_query/include/postmaster/fork_process.h +0 -17
  510. data/ext/pg_query/include/postmaster/pgarch.h +0 -73
  511. data/ext/pg_query/include/replication/logicalworker.h +0 -19
  512. data/ext/pg_query/include/storage/relfilenode.h +0 -99
  513. data/ext/pg_query/include/utils/dynahash.h +0 -20
  514. data/ext/pg_query/include/utils/pg_lsn.h +0 -29
  515. data/ext/pg_query/include/utils/pidfile.h +0 -56
  516. data/ext/pg_query/include/utils/ps_status.h +0 -25
  517. data/ext/pg_query/include/utils/rls.h +0 -50
  518. data/ext/pg_query/include/utils/tzparser.h +0 -39
  519. data/ext/pg_query/src_backend_postmaster_postmaster.c +0 -2201
  520. data/ext/pg_query/src_backend_storage_lmgr_s_lock.c +0 -371
  521. data/ext/pg_query/src_backend_utils_hash_dynahash.c +0 -1116
  522. data/ext/pg_query/src_backend_utils_misc_guc.c +0 -1993
  523. data/ext/pg_query/src_common_pg_prng.c +0 -152
  524. data/ext/pg_query/src_common_string.c +0 -92
  525. data/ext/pg_query/src_port_pgsleep.c +0 -69
  526. data/ext/pg_query/src_port_strnlen.c +0 -39
  527. /data/ext/pg_query/include/{access → postgres/access}/rmgr.h +0 -0
  528. /data/ext/pg_query/include/{pg_config_ext.h → postgres/pg_config_ext.h} +0 -0
  529. /data/ext/pg_query/include/{plerrcodes.h → postgres/plerrcodes.h} +0 -0
  530. /data/ext/pg_query/include/{storage → postgres/storage}/lwlocknames.h +0 -0
  531. /data/ext/pg_query/include/{utils → postgres/utils}/errcodes.h +0 -0
@@ -0,0 +1,1021 @@
1
+ /*--------------------------------------------------------------------
2
+ * Symbols referenced in this file:
3
+ * - SlabAlloc
4
+ * - SlabBlocklistIndex
5
+ * - SlabGetNextFreeChunk
6
+ * - SlabFindNextBlockListIndex
7
+ * - SlabFree
8
+ * - SlabRealloc
9
+ * - SlabReset
10
+ * - SlabDelete
11
+ * - SlabGetChunkContext
12
+ * - SlabGetChunkSpace
13
+ * - SlabIsEmpty
14
+ * - SlabStats
15
+ * - SlabCheck
16
+ *--------------------------------------------------------------------
17
+ */
18
+
19
+ /*-------------------------------------------------------------------------
20
+ *
21
+ * slab.c
22
+ * SLAB allocator definitions.
23
+ *
24
+ * SLAB is a MemoryContext implementation designed for cases where large
25
+ * numbers of equally-sized objects can be allocated and freed efficiently
26
+ * with minimal memory wastage and fragmentation.
27
+ *
28
+ *
29
+ * Portions Copyright (c) 2017-2023, PostgreSQL Global Development Group
30
+ *
31
+ * IDENTIFICATION
32
+ * src/backend/utils/mmgr/slab.c
33
+ *
34
+ *
35
+ * NOTE:
36
+ * The constant allocation size allows significant simplification and various
37
+ * optimizations over more general purpose allocators. The blocks are carved
38
+ * into chunks of exactly the right size, wasting only the space required to
39
+ * MAXALIGN the allocated chunks.
40
+ *
41
+ * Slab can also help reduce memory fragmentation in cases where longer-lived
42
+ * chunks remain stored on blocks while most of the other chunks have already
43
+ * been pfree'd. We give priority to putting new allocations into the
44
+ * "fullest" block. This help avoid having too many sparsely used blocks
45
+ * around and allows blocks to more easily become completely unused which
46
+ * allows them to be eventually free'd.
47
+ *
48
+ * We identify the "fullest" block to put new allocations on by using a block
49
+ * from the lowest populated element of the context's "blocklist" array.
50
+ * This is an array of dlists containing blocks which we partition by the
51
+ * number of free chunks which block has. Blocks with fewer free chunks are
52
+ * stored in a lower indexed dlist array slot. Full blocks go on the 0th
53
+ * element of the blocklist array. So that we don't have to have too many
54
+ * elements in the array, each dlist in the array is responsible for a range
55
+ * of free chunks. When a chunk is palloc'd or pfree'd we may need to move
56
+ * the block onto another dlist if the number of free chunks crosses the
57
+ * range boundary that the current list is responsible for. Having just a
58
+ * few blocklist elements reduces the number of times we must move the block
59
+ * onto another dlist element.
60
+ *
61
+ * We keep track of free chunks within each block by using a block-level free
62
+ * list. We consult this list when we allocate a new chunk in the block.
63
+ * The free list is a linked list, the head of which is pointed to with
64
+ * SlabBlock's freehead field. Each subsequent list item is stored in the
65
+ * free chunk's memory. We ensure chunks are large enough to store this
66
+ * address.
67
+ *
68
+ * When we allocate a new block, technically all chunks are free, however, to
69
+ * avoid having to write out the entire block to set the linked list for the
70
+ * free chunks for every chunk in the block, we instead store a pointer to
71
+ * the next "unused" chunk on the block and keep track of how many of these
72
+ * unused chunks there are. When a new block is malloc'd, all chunks are
73
+ * unused. The unused pointer starts with the first chunk on the block and
74
+ * as chunks are allocated, the unused pointer is incremented. As chunks are
75
+ * pfree'd, the unused pointer never goes backwards. The unused pointer can
76
+ * be thought of as a high watermark for the maximum number of chunks in the
77
+ * block which have been in use concurrently. When a chunk is pfree'd the
78
+ * chunk is put onto the head of the free list and the unused pointer is not
79
+ * changed. We only consume more unused chunks if we run out of free chunks
80
+ * on the free list. This method effectively gives priority to using
81
+ * previously used chunks over previously unused chunks, which should perform
82
+ * better due to CPU caching effects.
83
+ *
84
+ *-------------------------------------------------------------------------
85
+ */
86
+
87
+ #include "postgres.h"
88
+
89
+ #include "lib/ilist.h"
90
+ #include "utils/memdebug.h"
91
+ #include "utils/memutils.h"
92
+ #include "utils/memutils_memorychunk.h"
93
+ #include "utils/memutils_internal.h"
94
+
95
+ #define Slab_BLOCKHDRSZ MAXALIGN(sizeof(SlabBlock))
96
+
97
+ #ifdef MEMORY_CONTEXT_CHECKING
98
+ /*
99
+ * Size of the memory required to store the SlabContext.
100
+ * MEMORY_CONTEXT_CHECKING builds need some extra memory for the isChunkFree
101
+ * array.
102
+ */
103
+ #define Slab_CONTEXT_HDRSZ(chunksPerBlock) \
104
+ (sizeof(SlabContext) + ((chunksPerBlock) * sizeof(bool)))
105
+ #else
106
+ #define Slab_CONTEXT_HDRSZ(chunksPerBlock) sizeof(SlabContext)
107
+ #endif
108
+
109
+ /*
110
+ * The number of partitions to divide the blocklist into based their number of
111
+ * free chunks. There must be at least 2.
112
+ */
113
+ #define SLAB_BLOCKLIST_COUNT 3
114
+
115
+ /* The maximum number of completely empty blocks to keep around for reuse. */
116
+ #define SLAB_MAXIMUM_EMPTY_BLOCKS 10
117
+
118
+ /*
119
+ * SlabContext is a specialized implementation of MemoryContext.
120
+ */
121
+ typedef struct SlabContext
122
+ {
123
+ MemoryContextData header; /* Standard memory-context fields */
124
+ /* Allocation parameters for this context: */
125
+ Size chunkSize; /* the requested (non-aligned) chunk size */
126
+ Size fullChunkSize; /* chunk size with chunk header and alignment */
127
+ Size blockSize; /* the size to make each block of chunks */
128
+ int32 chunksPerBlock; /* number of chunks that fit in 1 block */
129
+ int32 curBlocklistIndex; /* index into the blocklist[] element
130
+ * containing the fullest, blocks */
131
+ #ifdef MEMORY_CONTEXT_CHECKING
132
+ bool *isChunkFree; /* array to mark free chunks in a block during
133
+ * SlabCheck */
134
+ #endif
135
+
136
+ int32 blocklist_shift; /* number of bits to shift the nfree count
137
+ * by to get the index into blocklist[] */
138
+ dclist_head emptyblocks; /* empty blocks to use up first instead of
139
+ * mallocing new blocks */
140
+
141
+ /*
142
+ * Blocks with free space, grouped by the number of free chunks they
143
+ * contain. Completely full blocks are stored in the 0th element.
144
+ * Completely empty blocks are stored in emptyblocks or free'd if we have
145
+ * enough empty blocks already.
146
+ */
147
+ dlist_head blocklist[SLAB_BLOCKLIST_COUNT];
148
+ } SlabContext;
149
+
150
+ /*
151
+ * SlabBlock
152
+ * Structure of a single slab block.
153
+ *
154
+ * slab: pointer back to the owning MemoryContext
155
+ * nfree: number of chunks on the block which are unallocated
156
+ * nunused: number of chunks on the block unallocated and not on the block's
157
+ * freelist.
158
+ * freehead: linked-list header storing a pointer to the first free chunk on
159
+ * the block. Subsequent pointers are stored in the chunk's memory. NULL
160
+ * indicates the end of the list.
161
+ * unused: pointer to the next chunk which has yet to be used.
162
+ * node: doubly-linked list node for the context's blocklist
163
+ */
164
+ typedef struct SlabBlock
165
+ {
166
+ SlabContext *slab; /* owning context */
167
+ int32 nfree; /* number of chunks on free + unused chunks */
168
+ int32 nunused; /* number of unused chunks */
169
+ MemoryChunk *freehead; /* pointer to the first free chunk */
170
+ MemoryChunk *unused; /* pointer to the next unused chunk */
171
+ dlist_node node; /* doubly-linked list for blocklist[] */
172
+ } SlabBlock;
173
+
174
+
175
+ #define Slab_CHUNKHDRSZ sizeof(MemoryChunk)
176
+ #define SlabChunkGetPointer(chk) \
177
+ ((void *) (((char *) (chk)) + sizeof(MemoryChunk)))
178
+
179
+ /*
180
+ * SlabBlockGetChunk
181
+ * Obtain a pointer to the nth (0-based) chunk in the block
182
+ */
183
+ #define SlabBlockGetChunk(slab, block, n) \
184
+ ((MemoryChunk *) ((char *) (block) + Slab_BLOCKHDRSZ \
185
+ + ((n) * (slab)->fullChunkSize)))
186
+
187
+ #if defined(MEMORY_CONTEXT_CHECKING) || defined(USE_ASSERT_CHECKING)
188
+
189
+ /*
190
+ * SlabChunkIndex
191
+ * Get the 0-based index of how many chunks into the block the given
192
+ * chunk is.
193
+ */
194
+ #define SlabChunkIndex(slab, block, chunk) \
195
+ (((char *) (chunk) - (char *) SlabBlockGetChunk(slab, block, 0)) / \
196
+ (slab)->fullChunkSize)
197
+
198
+ /*
199
+ * SlabChunkMod
200
+ * A MemoryChunk should always be at an address which is a multiple of
201
+ * fullChunkSize starting from the 0th chunk position. This will return
202
+ * non-zero if it's not.
203
+ */
204
+ #define SlabChunkMod(slab, block, chunk) \
205
+ (((char *) (chunk) - (char *) SlabBlockGetChunk(slab, block, 0)) % \
206
+ (slab)->fullChunkSize)
207
+
208
+ #endif
209
+
210
+ /*
211
+ * SlabIsValid
212
+ * True iff set is a valid slab allocation set.
213
+ */
214
+ #define SlabIsValid(set) (PointerIsValid(set) && IsA(set, SlabContext))
215
+
216
+ /*
217
+ * SlabBlockIsValid
218
+ * True iff block is a valid block of slab allocation set.
219
+ */
220
+ #define SlabBlockIsValid(block) \
221
+ (PointerIsValid(block) && SlabIsValid((block)->slab))
222
+
223
+ /*
224
+ * SlabBlocklistIndex
225
+ * Determine the blocklist index that a block should be in for the given
226
+ * number of free chunks.
227
+ */
228
+ static inline int32
229
+ SlabBlocklistIndex(SlabContext *slab, int nfree)
230
+ {
231
+ int32 index;
232
+ int32 blocklist_shift = slab->blocklist_shift;
233
+
234
+ Assert(nfree >= 0 && nfree <= slab->chunksPerBlock);
235
+
236
+ /*
237
+ * Determine the blocklist index based on the number of free chunks. We
238
+ * must ensure that 0 free chunks is dedicated to index 0. Everything
239
+ * else must be >= 1 and < SLAB_BLOCKLIST_COUNT.
240
+ *
241
+ * To make this as efficient as possible, we exploit some two's complement
242
+ * arithmetic where we reverse the sign before bit shifting. This results
243
+ * in an nfree of 0 using index 0 and anything non-zero staying non-zero.
244
+ * This is exploiting 0 and -0 being the same in two's complement. When
245
+ * we're done, we just need to flip the sign back over again for a
246
+ * positive index.
247
+ */
248
+ index = -((-nfree) >> blocklist_shift);
249
+
250
+ if (nfree == 0)
251
+ Assert(index == 0);
252
+ else
253
+ Assert(index >= 1 && index < SLAB_BLOCKLIST_COUNT);
254
+
255
+ return index;
256
+ }
257
+
258
+ /*
259
+ * SlabFindNextBlockListIndex
260
+ * Search blocklist for blocks which have free chunks and return the
261
+ * index of the blocklist found containing at least 1 block with free
262
+ * chunks. If no block can be found we return 0.
263
+ *
264
+ * Note: We give priority to fuller blocks so that these are filled before
265
+ * emptier blocks. This is done to increase the chances that mostly-empty
266
+ * blocks will eventually become completely empty so they can be free'd.
267
+ */
268
+ static int32
269
+ SlabFindNextBlockListIndex(SlabContext *slab)
270
+ {
271
+ /* start at 1 as blocklist[0] is for full blocks. */
272
+ for (int i = 1; i < SLAB_BLOCKLIST_COUNT; i++)
273
+ {
274
+ /* return the first found non-empty index */
275
+ if (!dlist_is_empty(&slab->blocklist[i]))
276
+ return i;
277
+ }
278
+
279
+ /* no blocks with free space */
280
+ return 0;
281
+ }
282
+
283
+ /*
284
+ * SlabGetNextFreeChunk
285
+ * Return the next free chunk in block and update the block to account
286
+ * for the returned chunk now being used.
287
+ */
288
+ static inline MemoryChunk *
289
+ SlabGetNextFreeChunk(SlabContext *slab, SlabBlock *block)
290
+ {
291
+ MemoryChunk *chunk;
292
+
293
+ Assert(block->nfree > 0);
294
+
295
+ if (block->freehead != NULL)
296
+ {
297
+ chunk = block->freehead;
298
+
299
+ /*
300
+ * Pop the chunk from the linked list of free chunks. The pointer to
301
+ * the next free chunk is stored in the chunk itself.
302
+ */
303
+ VALGRIND_MAKE_MEM_DEFINED(SlabChunkGetPointer(chunk), sizeof(MemoryChunk *));
304
+ block->freehead = *(MemoryChunk **) SlabChunkGetPointer(chunk);
305
+
306
+ /* check nothing stomped on the free chunk's memory */
307
+ Assert(block->freehead == NULL ||
308
+ (block->freehead >= SlabBlockGetChunk(slab, block, 0) &&
309
+ block->freehead <= SlabBlockGetChunk(slab, block, slab->chunksPerBlock - 1) &&
310
+ SlabChunkMod(slab, block, block->freehead) == 0));
311
+ }
312
+ else
313
+ {
314
+ Assert(block->nunused > 0);
315
+
316
+ chunk = block->unused;
317
+ block->unused = (MemoryChunk *) (((char *) block->unused) + slab->fullChunkSize);
318
+ block->nunused--;
319
+ }
320
+
321
+ block->nfree--;
322
+
323
+ return chunk;
324
+ }
325
+
326
+ /*
327
+ * SlabContextCreate
328
+ * Create a new Slab context.
329
+ *
330
+ * parent: parent context, or NULL if top-level context
331
+ * name: name of context (must be statically allocated)
332
+ * blockSize: allocation block size
333
+ * chunkSize: allocation chunk size
334
+ *
335
+ * The MAXALIGN(chunkSize) may not exceed MEMORYCHUNK_MAX_VALUE
336
+ */
337
+ #ifdef MEMORY_CONTEXT_CHECKING
338
+ #else
339
+ #endif
340
+ #ifdef MEMORY_CONTEXT_CHECKING
341
+ #endif
342
+
343
+ /*
344
+ * SlabReset
345
+ * Frees all memory which is allocated in the given set.
346
+ *
347
+ * The code simply frees all the blocks in the context - we don't keep any
348
+ * keeper blocks or anything like that.
349
+ */
350
+ void
351
+ SlabReset(MemoryContext context)
352
+ {
353
+ SlabContext *slab = (SlabContext *) context;
354
+ dlist_mutable_iter miter;
355
+ int i;
356
+
357
+ Assert(SlabIsValid(slab));
358
+
359
+ #ifdef MEMORY_CONTEXT_CHECKING
360
+ /* Check for corruption and leaks before freeing */
361
+ SlabCheck(context);
362
+ #endif
363
+
364
+ /* release any retained empty blocks */
365
+ dclist_foreach_modify(miter, &slab->emptyblocks)
366
+ {
367
+ SlabBlock *block = dlist_container(SlabBlock, node, miter.cur);
368
+
369
+ dclist_delete_from(&slab->emptyblocks, miter.cur);
370
+
371
+ #ifdef CLOBBER_FREED_MEMORY
372
+ wipe_mem(block, slab->blockSize);
373
+ #endif
374
+ free(block);
375
+ context->mem_allocated -= slab->blockSize;
376
+ }
377
+
378
+ /* walk over blocklist and free the blocks */
379
+ for (i = 0; i < SLAB_BLOCKLIST_COUNT; i++)
380
+ {
381
+ dlist_foreach_modify(miter, &slab->blocklist[i])
382
+ {
383
+ SlabBlock *block = dlist_container(SlabBlock, node, miter.cur);
384
+
385
+ dlist_delete(miter.cur);
386
+
387
+ #ifdef CLOBBER_FREED_MEMORY
388
+ wipe_mem(block, slab->blockSize);
389
+ #endif
390
+ free(block);
391
+ context->mem_allocated -= slab->blockSize;
392
+ }
393
+ }
394
+
395
+ slab->curBlocklistIndex = 0;
396
+
397
+ Assert(context->mem_allocated == 0);
398
+ }
399
+
400
+ /*
401
+ * SlabDelete
402
+ * Free all memory which is allocated in the given context.
403
+ */
404
+ void
405
+ SlabDelete(MemoryContext context)
406
+ {
407
+ /* Reset to release all the SlabBlocks */
408
+ SlabReset(context);
409
+ /* And free the context header */
410
+ free(context);
411
+ }
412
+
413
+ /*
414
+ * SlabAlloc
415
+ * Returns a pointer to allocated memory of given size or NULL if
416
+ * request could not be completed; memory is added to the slab.
417
+ */
418
+ void *
419
+ SlabAlloc(MemoryContext context, Size size)
420
+ {
421
+ SlabContext *slab = (SlabContext *) context;
422
+ SlabBlock *block;
423
+ MemoryChunk *chunk;
424
+
425
+ Assert(SlabIsValid(slab));
426
+
427
+ /* sanity check that this is pointing to a valid blocklist */
428
+ Assert(slab->curBlocklistIndex >= 0);
429
+ Assert(slab->curBlocklistIndex <= SlabBlocklistIndex(slab, slab->chunksPerBlock));
430
+
431
+ /* make sure we only allow correct request size */
432
+ if (unlikely(size != slab->chunkSize))
433
+ elog(ERROR, "unexpected alloc chunk size %zu (expected %zu)",
434
+ size, slab->chunkSize);
435
+
436
+ /*
437
+ * Handle the case when there are no partially filled blocks available.
438
+ * SlabFree() will have updated the curBlocklistIndex setting it to zero
439
+ * to indicate that it has freed the final block. Also later in
440
+ * SlabAlloc() we will set the curBlocklistIndex to zero if we end up
441
+ * filling the final block.
442
+ */
443
+ if (unlikely(slab->curBlocklistIndex == 0))
444
+ {
445
+ dlist_head *blocklist;
446
+ int blocklist_idx;
447
+
448
+ /* to save allocating a new one, first check the empty blocks list */
449
+ if (dclist_count(&slab->emptyblocks) > 0)
450
+ {
451
+ dlist_node *node = dclist_pop_head_node(&slab->emptyblocks);
452
+
453
+ block = dlist_container(SlabBlock, node, node);
454
+
455
+ /*
456
+ * SlabFree() should have left this block in a valid state with
457
+ * all chunks free. Ensure that's the case.
458
+ */
459
+ Assert(block->nfree == slab->chunksPerBlock);
460
+
461
+ /* fetch the next chunk from this block */
462
+ chunk = SlabGetNextFreeChunk(slab, block);
463
+ }
464
+ else
465
+ {
466
+ block = (SlabBlock *) malloc(slab->blockSize);
467
+
468
+ if (unlikely(block == NULL))
469
+ return NULL;
470
+
471
+ block->slab = slab;
472
+ context->mem_allocated += slab->blockSize;
473
+
474
+ /* use the first chunk in the new block */
475
+ chunk = SlabBlockGetChunk(slab, block, 0);
476
+
477
+ block->nfree = slab->chunksPerBlock - 1;
478
+ block->unused = SlabBlockGetChunk(slab, block, 1);
479
+ block->freehead = NULL;
480
+ block->nunused = slab->chunksPerBlock - 1;
481
+ }
482
+
483
+ /* find the blocklist element for storing blocks with 1 used chunk */
484
+ blocklist_idx = SlabBlocklistIndex(slab, block->nfree);
485
+ blocklist = &slab->blocklist[blocklist_idx];
486
+
487
+ /* this better be empty. We just added a block thinking it was */
488
+ Assert(dlist_is_empty(blocklist));
489
+
490
+ dlist_push_head(blocklist, &block->node);
491
+
492
+ slab->curBlocklistIndex = blocklist_idx;
493
+ }
494
+ else
495
+ {
496
+ dlist_head *blocklist = &slab->blocklist[slab->curBlocklistIndex];
497
+ int new_blocklist_idx;
498
+
499
+ Assert(!dlist_is_empty(blocklist));
500
+
501
+ /* grab the block from the blocklist */
502
+ block = dlist_head_element(SlabBlock, node, blocklist);
503
+
504
+ /* make sure we actually got a valid block, with matching nfree */
505
+ Assert(block != NULL);
506
+ Assert(slab->curBlocklistIndex == SlabBlocklistIndex(slab, block->nfree));
507
+ Assert(block->nfree > 0);
508
+
509
+ /* fetch the next chunk from this block */
510
+ chunk = SlabGetNextFreeChunk(slab, block);
511
+
512
+ /* get the new blocklist index based on the new free chunk count */
513
+ new_blocklist_idx = SlabBlocklistIndex(slab, block->nfree);
514
+
515
+ /*
516
+ * Handle the case where the blocklist index changes. This also deals
517
+ * with blocks becoming full as only full blocks go at index 0.
518
+ */
519
+ if (unlikely(slab->curBlocklistIndex != new_blocklist_idx))
520
+ {
521
+ dlist_delete_from(blocklist, &block->node);
522
+ dlist_push_head(&slab->blocklist[new_blocklist_idx], &block->node);
523
+
524
+ if (dlist_is_empty(blocklist))
525
+ slab->curBlocklistIndex = SlabFindNextBlockListIndex(slab);
526
+ }
527
+ }
528
+
529
+ /*
530
+ * Check that the chunk pointer is actually somewhere on the block and is
531
+ * aligned as expected.
532
+ */
533
+ Assert(chunk >= SlabBlockGetChunk(slab, block, 0));
534
+ Assert(chunk <= SlabBlockGetChunk(slab, block, slab->chunksPerBlock - 1));
535
+ Assert(SlabChunkMod(slab, block, chunk) == 0);
536
+
537
+ /* Prepare to initialize the chunk header. */
538
+ VALGRIND_MAKE_MEM_UNDEFINED(chunk, Slab_CHUNKHDRSZ);
539
+
540
+ MemoryChunkSetHdrMask(chunk, block, MAXALIGN(slab->chunkSize),
541
+ MCTX_SLAB_ID);
542
+ #ifdef MEMORY_CONTEXT_CHECKING
543
+ /* slab mark to catch clobber of "unused" space */
544
+ Assert(slab->chunkSize < (slab->fullChunkSize - Slab_CHUNKHDRSZ));
545
+ set_sentinel(MemoryChunkGetPointer(chunk), size);
546
+ VALGRIND_MAKE_MEM_NOACCESS(((char *) chunk) +
547
+ Slab_CHUNKHDRSZ + slab->chunkSize,
548
+ slab->fullChunkSize -
549
+ (slab->chunkSize + Slab_CHUNKHDRSZ));
550
+ #endif
551
+
552
+ #ifdef RANDOMIZE_ALLOCATED_MEMORY
553
+ /* fill the allocated space with junk */
554
+ randomize_mem((char *) MemoryChunkGetPointer(chunk), size);
555
+ #endif
556
+
557
+ /* Disallow access to the chunk header. */
558
+ VALGRIND_MAKE_MEM_NOACCESS(chunk, Slab_CHUNKHDRSZ);
559
+
560
+ return MemoryChunkGetPointer(chunk);
561
+ }
562
+
563
+ /*
564
+ * SlabFree
565
+ * Frees allocated memory; memory is removed from the slab.
566
+ */
567
+ void
568
+ SlabFree(void *pointer)
569
+ {
570
+ MemoryChunk *chunk = PointerGetMemoryChunk(pointer);
571
+ SlabBlock *block;
572
+ SlabContext *slab;
573
+ int curBlocklistIdx;
574
+ int newBlocklistIdx;
575
+
576
+ /* Allow access to the chunk header. */
577
+ VALGRIND_MAKE_MEM_DEFINED(chunk, Slab_CHUNKHDRSZ);
578
+
579
+ block = MemoryChunkGetBlock(chunk);
580
+
581
+ /*
582
+ * For speed reasons we just Assert that the referenced block is good.
583
+ * Future field experience may show that this Assert had better become a
584
+ * regular runtime test-and-elog check.
585
+ */
586
+ Assert(SlabBlockIsValid(block));
587
+ slab = block->slab;
588
+
589
+ #ifdef MEMORY_CONTEXT_CHECKING
590
+ /* Test for someone scribbling on unused space in chunk */
591
+ Assert(slab->chunkSize < (slab->fullChunkSize - Slab_CHUNKHDRSZ));
592
+ if (!sentinel_ok(pointer, slab->chunkSize))
593
+ elog(WARNING, "detected write past chunk end in %s %p",
594
+ slab->header.name, chunk);
595
+ #endif
596
+
597
+ /* push this chunk onto the head of the block's free list */
598
+ *(MemoryChunk **) pointer = block->freehead;
599
+ block->freehead = chunk;
600
+
601
+ block->nfree++;
602
+
603
+ Assert(block->nfree > 0);
604
+ Assert(block->nfree <= slab->chunksPerBlock);
605
+
606
+ #ifdef CLOBBER_FREED_MEMORY
607
+ /* don't wipe the free list MemoryChunk pointer stored in the chunk */
608
+ wipe_mem((char *) pointer + sizeof(MemoryChunk *),
609
+ slab->chunkSize - sizeof(MemoryChunk *));
610
+ #endif
611
+
612
+ curBlocklistIdx = SlabBlocklistIndex(slab, block->nfree - 1);
613
+ newBlocklistIdx = SlabBlocklistIndex(slab, block->nfree);
614
+
615
+ /*
616
+ * Check if the block needs to be moved to another element on the
617
+ * blocklist based on it now having 1 more free chunk.
618
+ */
619
+ if (unlikely(curBlocklistIdx != newBlocklistIdx))
620
+ {
621
+ /* do the move */
622
+ dlist_delete_from(&slab->blocklist[curBlocklistIdx], &block->node);
623
+ dlist_push_head(&slab->blocklist[newBlocklistIdx], &block->node);
624
+
625
+ /*
626
+ * The blocklist[curBlocklistIdx] may now be empty or we may now be
627
+ * able to use a lower-element blocklist. We'll need to redetermine
628
+ * what the slab->curBlocklistIndex is if the current blocklist was
629
+ * changed or if a lower element one was changed. We must ensure we
630
+ * use the list with the fullest block(s).
631
+ */
632
+ if (slab->curBlocklistIndex >= curBlocklistIdx)
633
+ {
634
+ slab->curBlocklistIndex = SlabFindNextBlockListIndex(slab);
635
+
636
+ /*
637
+ * We know there must be a block with at least 1 unused chunk as
638
+ * we just pfree'd one. Ensure curBlocklistIndex reflects this.
639
+ */
640
+ Assert(slab->curBlocklistIndex > 0);
641
+ }
642
+ }
643
+
644
+ /* Handle when a block becomes completely empty */
645
+ if (unlikely(block->nfree == slab->chunksPerBlock))
646
+ {
647
+ /* remove the block */
648
+ dlist_delete_from(&slab->blocklist[newBlocklistIdx], &block->node);
649
+
650
+ /*
651
+ * To avoid thrashing malloc/free, we keep a list of empty blocks that
652
+ * we can reuse again instead of having to malloc a new one.
653
+ */
654
+ if (dclist_count(&slab->emptyblocks) < SLAB_MAXIMUM_EMPTY_BLOCKS)
655
+ dclist_push_head(&slab->emptyblocks, &block->node);
656
+ else
657
+ {
658
+ /*
659
+ * When we have enough empty blocks stored already, we actually
660
+ * free the block.
661
+ */
662
+ #ifdef CLOBBER_FREED_MEMORY
663
+ wipe_mem(block, slab->blockSize);
664
+ #endif
665
+ free(block);
666
+ slab->header.mem_allocated -= slab->blockSize;
667
+ }
668
+
669
+ /*
670
+ * Check if we need to reset the blocklist index. This is required
671
+ * when the blocklist this block is on has become completely empty.
672
+ */
673
+ if (slab->curBlocklistIndex == newBlocklistIdx &&
674
+ dlist_is_empty(&slab->blocklist[newBlocklistIdx]))
675
+ slab->curBlocklistIndex = SlabFindNextBlockListIndex(slab);
676
+ }
677
+ }
678
+
679
+ /*
680
+ * SlabRealloc
681
+ * Change the allocated size of a chunk.
682
+ *
683
+ * As Slab is designed for allocating equally-sized chunks of memory, it can't
684
+ * do an actual chunk size change. We try to be gentle and allow calls with
685
+ * exactly the same size, as in that case we can simply return the same
686
+ * chunk. When the size differs, we throw an error.
687
+ *
688
+ * We could also allow requests with size < chunkSize. That however seems
689
+ * rather pointless - Slab is meant for chunks of constant size, and moreover
690
+ * realloc is usually used to enlarge the chunk.
691
+ */
692
+ void *
693
+ SlabRealloc(void *pointer, Size size)
694
+ {
695
+ MemoryChunk *chunk = PointerGetMemoryChunk(pointer);
696
+ SlabBlock *block;
697
+ SlabContext *slab;
698
+
699
+ /* Allow access to the chunk header. */
700
+ VALGRIND_MAKE_MEM_DEFINED(chunk, Slab_CHUNKHDRSZ);
701
+
702
+ block = MemoryChunkGetBlock(chunk);
703
+
704
+ /* Disallow access to the chunk header. */
705
+ VALGRIND_MAKE_MEM_NOACCESS(chunk, Slab_CHUNKHDRSZ);
706
+
707
+ /*
708
+ * Try to verify that we have a sane block pointer: the block header
709
+ * should reference a slab context. (We use a test-and-elog, not just
710
+ * Assert, because it seems highly likely that we're here in error in the
711
+ * first place.)
712
+ */
713
+ if (!SlabBlockIsValid(block))
714
+ elog(ERROR, "could not find block containing chunk %p", chunk);
715
+ slab = block->slab;
716
+
717
+ /* can't do actual realloc with slab, but let's try to be gentle */
718
+ if (size == slab->chunkSize)
719
+ return pointer;
720
+
721
+ elog(ERROR, "slab allocator does not support realloc()");
722
+ return NULL; /* keep compiler quiet */
723
+ }
724
+
725
+ /*
726
+ * SlabGetChunkContext
727
+ * Return the MemoryContext that 'pointer' belongs to.
728
+ */
729
+ MemoryContext
730
+ SlabGetChunkContext(void *pointer)
731
+ {
732
+ MemoryChunk *chunk = PointerGetMemoryChunk(pointer);
733
+ SlabBlock *block;
734
+
735
+ /* Allow access to the chunk header. */
736
+ VALGRIND_MAKE_MEM_DEFINED(chunk, Slab_CHUNKHDRSZ);
737
+
738
+ block = MemoryChunkGetBlock(chunk);
739
+
740
+ /* Disallow access to the chunk header. */
741
+ VALGRIND_MAKE_MEM_NOACCESS(chunk, Slab_CHUNKHDRSZ);
742
+
743
+ Assert(SlabBlockIsValid(block));
744
+
745
+ return &block->slab->header;
746
+ }
747
+
748
+ /*
749
+ * SlabGetChunkSpace
750
+ * Given a currently-allocated chunk, determine the total space
751
+ * it occupies (including all memory-allocation overhead).
752
+ */
753
+ Size
754
+ SlabGetChunkSpace(void *pointer)
755
+ {
756
+ MemoryChunk *chunk = PointerGetMemoryChunk(pointer);
757
+ SlabBlock *block;
758
+ SlabContext *slab;
759
+
760
+ /* Allow access to the chunk header. */
761
+ VALGRIND_MAKE_MEM_DEFINED(chunk, Slab_CHUNKHDRSZ);
762
+
763
+ block = MemoryChunkGetBlock(chunk);
764
+
765
+ /* Disallow access to the chunk header. */
766
+ VALGRIND_MAKE_MEM_NOACCESS(chunk, Slab_CHUNKHDRSZ);
767
+
768
+ Assert(SlabBlockIsValid(block));
769
+ slab = block->slab;
770
+
771
+ return slab->fullChunkSize;
772
+ }
773
+
774
+ /*
775
+ * SlabIsEmpty
776
+ * Is the slab empty of any allocated space?
777
+ */
778
+ bool
779
+ SlabIsEmpty(MemoryContext context)
780
+ {
781
+ Assert(SlabIsValid((SlabContext *) context));
782
+
783
+ return (context->mem_allocated == 0);
784
+ }
785
+
786
+ /*
787
+ * SlabStats
788
+ * Compute stats about memory consumption of a Slab context.
789
+ *
790
+ * printfunc: if not NULL, pass a human-readable stats string to this.
791
+ * passthru: pass this pointer through to printfunc.
792
+ * totals: if not NULL, add stats about this context into *totals.
793
+ * print_to_stderr: print stats to stderr if true, elog otherwise.
794
+ */
795
+ void
796
+ SlabStats(MemoryContext context,
797
+ MemoryStatsPrintFunc printfunc, void *passthru,
798
+ MemoryContextCounters *totals,
799
+ bool print_to_stderr)
800
+ {
801
+ SlabContext *slab = (SlabContext *) context;
802
+ Size nblocks = 0;
803
+ Size freechunks = 0;
804
+ Size totalspace;
805
+ Size freespace = 0;
806
+ int i;
807
+
808
+ Assert(SlabIsValid(slab));
809
+
810
+ /* Include context header in totalspace */
811
+ totalspace = Slab_CONTEXT_HDRSZ(slab->chunksPerBlock);
812
+
813
+ /* Add the space consumed by blocks in the emptyblocks list */
814
+ totalspace += dclist_count(&slab->emptyblocks) * slab->blockSize;
815
+
816
+ for (i = 0; i < SLAB_BLOCKLIST_COUNT; i++)
817
+ {
818
+ dlist_iter iter;
819
+
820
+ dlist_foreach(iter, &slab->blocklist[i])
821
+ {
822
+ SlabBlock *block = dlist_container(SlabBlock, node, iter.cur);
823
+
824
+ nblocks++;
825
+ totalspace += slab->blockSize;
826
+ freespace += slab->fullChunkSize * block->nfree;
827
+ freechunks += block->nfree;
828
+ }
829
+ }
830
+
831
+ if (printfunc)
832
+ {
833
+ char stats_string[200];
834
+
835
+ /* XXX should we include free chunks on empty blocks? */
836
+ snprintf(stats_string, sizeof(stats_string),
837
+ "%zu total in %zu blocks; %u empty blocks; %zu free (%zu chunks); %zu used",
838
+ totalspace, nblocks, dclist_count(&slab->emptyblocks),
839
+ freespace, freechunks, totalspace - freespace);
840
+ printfunc(context, passthru, stats_string, print_to_stderr);
841
+ }
842
+
843
+ if (totals)
844
+ {
845
+ totals->nblocks += nblocks;
846
+ totals->freechunks += freechunks;
847
+ totals->totalspace += totalspace;
848
+ totals->freespace += freespace;
849
+ }
850
+ }
851
+
852
+
853
+ #ifdef MEMORY_CONTEXT_CHECKING
854
+
855
+ /*
856
+ * SlabCheck
857
+ * Walk through all blocks looking for inconsistencies.
858
+ *
859
+ * NOTE: report errors as WARNING, *not* ERROR or FATAL. Otherwise you'll
860
+ * find yourself in an infinite loop when trouble occurs, because this
861
+ * routine will be entered again when elog cleanup tries to release memory!
862
+ */
863
+ void
864
+ SlabCheck(MemoryContext context)
865
+ {
866
+ SlabContext *slab = (SlabContext *) context;
867
+ int i;
868
+ int nblocks = 0;
869
+ const char *name = slab->header.name;
870
+ dlist_iter iter;
871
+
872
+ Assert(SlabIsValid(slab));
873
+ Assert(slab->chunksPerBlock > 0);
874
+
875
+ /*
876
+ * Have a look at the empty blocks. These should have all their chunks
877
+ * marked as free. Ensure that's the case.
878
+ */
879
+ dclist_foreach(iter, &slab->emptyblocks)
880
+ {
881
+ SlabBlock *block = dlist_container(SlabBlock, node, iter.cur);
882
+
883
+ if (block->nfree != slab->chunksPerBlock)
884
+ elog(WARNING, "problem in slab %s: empty block %p should have %d free chunks but has %d chunks free",
885
+ name, block, slab->chunksPerBlock, block->nfree);
886
+ }
887
+
888
+ /* walk the non-empty block lists */
889
+ for (i = 0; i < SLAB_BLOCKLIST_COUNT; i++)
890
+ {
891
+ int j,
892
+ nfree;
893
+
894
+ /* walk all blocks on this blocklist */
895
+ dlist_foreach(iter, &slab->blocklist[i])
896
+ {
897
+ SlabBlock *block = dlist_container(SlabBlock, node, iter.cur);
898
+ MemoryChunk *cur_chunk;
899
+
900
+ /*
901
+ * Make sure the number of free chunks (in the block header)
902
+ * matches the position in the blocklist.
903
+ */
904
+ if (SlabBlocklistIndex(slab, block->nfree) != i)
905
+ elog(WARNING, "problem in slab %s: block %p is on blocklist %d but should be on blocklist %d",
906
+ name, block, i, SlabBlocklistIndex(slab, block->nfree));
907
+
908
+ /* make sure the block is not empty */
909
+ if (block->nfree >= slab->chunksPerBlock)
910
+ elog(WARNING, "problem in slab %s: empty block %p incorrectly stored on blocklist element %d",
911
+ name, block, i);
912
+
913
+ /* make sure the slab pointer correctly points to this context */
914
+ if (block->slab != slab)
915
+ elog(WARNING, "problem in slab %s: bogus slab link in block %p",
916
+ name, block);
917
+
918
+ /* reset the array of free chunks for this block */
919
+ memset(slab->isChunkFree, 0, (slab->chunksPerBlock * sizeof(bool)));
920
+ nfree = 0;
921
+
922
+ /* walk through the block's free list chunks */
923
+ cur_chunk = block->freehead;
924
+ while (cur_chunk != NULL)
925
+ {
926
+ int chunkidx = SlabChunkIndex(slab, block, cur_chunk);
927
+
928
+ /*
929
+ * Ensure the free list link points to something on the block
930
+ * at an address aligned according to the full chunk size.
931
+ */
932
+ if (cur_chunk < SlabBlockGetChunk(slab, block, 0) ||
933
+ cur_chunk > SlabBlockGetChunk(slab, block, slab->chunksPerBlock - 1) ||
934
+ SlabChunkMod(slab, block, cur_chunk) != 0)
935
+ elog(WARNING, "problem in slab %s: bogus free list link %p in block %p",
936
+ name, cur_chunk, block);
937
+
938
+ /* count the chunk and mark it free on the free chunk array */
939
+ nfree++;
940
+ slab->isChunkFree[chunkidx] = true;
941
+
942
+ /* read pointer of the next free chunk */
943
+ VALGRIND_MAKE_MEM_DEFINED(MemoryChunkGetPointer(cur_chunk), sizeof(MemoryChunk *));
944
+ cur_chunk = *(MemoryChunk **) SlabChunkGetPointer(cur_chunk);
945
+ }
946
+
947
+ /* check that the unused pointer matches what nunused claims */
948
+ if (SlabBlockGetChunk(slab, block, slab->chunksPerBlock - block->nunused) !=
949
+ block->unused)
950
+ elog(WARNING, "problem in slab %s: mismatch detected between nunused chunks and unused pointer in block %p",
951
+ name, block);
952
+
953
+ /*
954
+ * count the remaining free chunks that have yet to make it onto
955
+ * the block's free list.
956
+ */
957
+ cur_chunk = block->unused;
958
+ for (j = 0; j < block->nunused; j++)
959
+ {
960
+ int chunkidx = SlabChunkIndex(slab, block, cur_chunk);
961
+
962
+
963
+ /* count the chunk as free and mark it as so in the array */
964
+ nfree++;
965
+ if (chunkidx < slab->chunksPerBlock)
966
+ slab->isChunkFree[chunkidx] = true;
967
+
968
+ /* move forward 1 chunk */
969
+ cur_chunk = (MemoryChunk *) (((char *) cur_chunk) + slab->fullChunkSize);
970
+ }
971
+
972
+ for (j = 0; j < slab->chunksPerBlock; j++)
973
+ {
974
+ if (!slab->isChunkFree[j])
975
+ {
976
+ MemoryChunk *chunk = SlabBlockGetChunk(slab, block, j);
977
+ SlabBlock *chunkblock;
978
+
979
+ /* Allow access to the chunk header. */
980
+ VALGRIND_MAKE_MEM_DEFINED(chunk, Slab_CHUNKHDRSZ);
981
+
982
+ chunkblock = (SlabBlock *) MemoryChunkGetBlock(chunk);
983
+
984
+ /* Disallow access to the chunk header. */
985
+ VALGRIND_MAKE_MEM_NOACCESS(chunk, Slab_CHUNKHDRSZ);
986
+
987
+ /*
988
+ * check the chunk's blockoffset correctly points back to
989
+ * the block
990
+ */
991
+ if (chunkblock != block)
992
+ elog(WARNING, "problem in slab %s: bogus block link in block %p, chunk %p",
993
+ name, block, chunk);
994
+
995
+ /* check the sentinel byte is intact */
996
+ Assert(slab->chunkSize < (slab->fullChunkSize - Slab_CHUNKHDRSZ));
997
+ if (!sentinel_ok(chunk, Slab_CHUNKHDRSZ + slab->chunkSize))
998
+ elog(WARNING, "problem in slab %s: detected write past chunk end in block %p, chunk %p",
999
+ name, block, chunk);
1000
+ }
1001
+ }
1002
+
1003
+ /*
1004
+ * Make sure we got the expected number of free chunks (as tracked
1005
+ * in the block header).
1006
+ */
1007
+ if (nfree != block->nfree)
1008
+ elog(WARNING, "problem in slab %s: nfree in block %p is %d but %d chunk were found as free",
1009
+ name, block, block->nfree, nfree);
1010
+
1011
+ nblocks++;
1012
+ }
1013
+ }
1014
+
1015
+ /* the stored empty blocks are tracked in mem_allocated too */
1016
+ nblocks += dclist_count(&slab->emptyblocks);
1017
+
1018
+ Assert(nblocks * slab->blockSize == context->mem_allocated);
1019
+ }
1020
+
1021
+ #endif /* MEMORY_CONTEXT_CHECKING */