rubydb 0.1.4 → 0.1.6

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 (469) hide show
  1. checksums.yaml +4 -4
  2. data/.github/PULL_REQUEST_TEMPLATE.md +15 -15
  3. data/.github/workflows/benchmark.yml +26 -26
  4. data/.github/workflows/compatibility.yml +63 -63
  5. data/.github/workflows/fuzz.yml +33 -33
  6. data/.github/workflows/lint.yml +21 -21
  7. data/.github/workflows/operations.yml +24 -24
  8. data/.github/workflows/production-validation.yml +111 -111
  9. data/.github/workflows/release.yml +77 -77
  10. data/.github/workflows/security.yml +39 -37
  11. data/.github/workflows/test.yml +26 -26
  12. data/.github/workflows/workload.yml +58 -58
  13. data/.gitignore +16 -5
  14. data/.rubocop.yml +50 -44
  15. data/.standard.yml +9 -14
  16. data/ARCHITECTURE.md +21 -21
  17. data/CHANGELOG.md +57 -27
  18. data/CODE_OF_CONDUCT.md +13 -13
  19. data/CONTRIBUTING.md +29 -29
  20. data/GOVERNANCE.md +16 -16
  21. data/Gemfile +18 -17
  22. data/Gemfile.lock +125 -71
  23. data/README.md +168 -12
  24. data/ROADMAP.md +27 -27
  25. data/Rakefile +76 -71
  26. data/SECURITY.md +54 -54
  27. data/SUPPORT.md +14 -14
  28. data/accelerator/bin/SHA256SUMS +6 -0
  29. data/accelerator/bin/rubydb-accelerator-darwin-amd64 +0 -0
  30. data/accelerator/bin/rubydb-accelerator-darwin-arm64 +0 -0
  31. data/accelerator/bin/rubydb-accelerator-linux-amd64 +0 -0
  32. data/accelerator/bin/rubydb-accelerator-linux-arm64 +0 -0
  33. data/accelerator/bin/rubydb-accelerator-windows-amd64.exe +0 -0
  34. data/accelerator/bin/rubydb-accelerator-windows-arm64.exe +0 -0
  35. data/accelerator/cmd/rubydb-accelerator/main.go +11 -0
  36. data/accelerator/go.mod +3 -0
  37. data/accelerator/internal/execution/aggregate.go +94 -0
  38. data/accelerator/internal/execution/distinct.go +22 -0
  39. data/accelerator/internal/execution/filter.go +73 -0
  40. data/accelerator/internal/execution/join.go +79 -0
  41. data/accelerator/internal/execution/operators.go +167 -0
  42. data/accelerator/internal/execution/scan.go +20 -0
  43. data/accelerator/internal/execution/sort.go +62 -0
  44. data/accelerator/internal/execution/types.go +136 -0
  45. data/accelerator/internal/execution/value.go +67 -0
  46. data/accelerator/internal/memory/arena.go +47 -0
  47. data/accelerator/internal/memory/reuse.go +22 -0
  48. data/accelerator/internal/metrics/registry.go +67 -0
  49. data/accelerator/internal/parallel/bounded_queue.go +56 -0
  50. data/accelerator/internal/parallel/scheduler.go +47 -0
  51. data/accelerator/internal/parallel/worker_pool.go +53 -0
  52. data/accelerator/internal/protocol/cancellation.go +48 -0
  53. data/accelerator/internal/protocol/columnar.go +263 -0
  54. data/accelerator/internal/protocol/frame.go +187 -0
  55. data/accelerator/internal/runtime/worker.go +521 -0
  56. data/accelerator/internal/storage/page_reader.go +81 -0
  57. data/accelerator/internal/storage/snapshot_scan.go +539 -0
  58. data/accelerator/internal/wal/checksum.go +13 -0
  59. data/accelerator/internal/wal/compression.go +41 -0
  60. data/accelerator/internal/wal/group_commit.go +24 -0
  61. data/accelerator/internal/wal/record_encoder.go +40 -0
  62. data/adapters/activerecord/Gemfile +11 -11
  63. data/adapters/activerecord/README.md +8 -3
  64. data/adapters/activerecord/lib/active_record/connection_adapters/rubydb_adapter.rb +881 -879
  65. data/adapters/activerecord/rubydb-activerecord.gemspec +21 -21
  66. data/adapters/activerecord/spec/rubydb_adapter_integration_spec.rb +143 -143
  67. data/adapters/ruby/README.md +18 -18
  68. data/adapters/sequel/README.md +11 -11
  69. data/config/monitoring/prometheus-alerts.yml +39 -39
  70. data/config/production.yml +36 -36
  71. data/docs/README.md +77 -71
  72. data/docs/architecture/concurrency.md +14 -14
  73. data/docs/architecture/current-state.md +125 -125
  74. data/docs/architecture/execution-engine.md +25 -25
  75. data/docs/architecture/go-accelerator.md +179 -0
  76. data/docs/architecture/indexes.md +19 -19
  77. data/docs/architecture/mvcc.md +19 -19
  78. data/docs/architecture/overview.md +13 -13
  79. data/docs/architecture/pages.md +11 -11
  80. data/docs/architecture/production-roadmap.md +82 -82
  81. data/docs/architecture/query-planner.md +20 -20
  82. data/docs/architecture/recovery.md +18 -18
  83. data/docs/architecture/sql-engine.md +12 -12
  84. data/docs/architecture/storage-engine.md +14 -14
  85. data/docs/architecture/transactions.md +10 -10
  86. data/docs/architecture/wal.md +28 -28
  87. data/docs/cli-cheatsheet.md +98 -98
  88. data/docs/cli.md +299 -275
  89. data/docs/contributing/architecture.md +9 -9
  90. data/docs/contributing/benchmarking.md +30 -14
  91. data/docs/contributing/development.md +16 -16
  92. data/docs/contributing/release-process.md +49 -49
  93. data/docs/contributing/testing.md +16 -16
  94. data/docs/debugging.md +229 -229
  95. data/docs/developer/branching.md +10 -10
  96. data/docs/developer/database-diff.md +10 -10
  97. data/docs/developer/local-development.md +49 -17
  98. data/docs/developer/snapshots.md +9 -9
  99. data/docs/developer/temporal-data.md +10 -10
  100. data/docs/developer-guide.md +297 -297
  101. data/docs/getting-started/first-database.md +16 -16
  102. data/docs/getting-started/first-query.md +13 -13
  103. data/docs/getting-started/installation.md +19 -19
  104. data/docs/getting-started/local-to-production.md +300 -300
  105. data/docs/getting-started/quickstart.md +17 -17
  106. data/docs/getting-started/rails.md +16 -16
  107. data/docs/hardening_backlog.md +93 -93
  108. data/docs/lessons-learned.md +112 -112
  109. data/docs/operations/backups.md +33 -33
  110. data/docs/operations/disaster-recovery.md +31 -31
  111. data/docs/operations/failover.md +30 -30
  112. data/docs/operations/monitoring.md +25 -25
  113. data/docs/operations/production-guide.md +295 -295
  114. data/docs/operations/production-runbook.md +45 -45
  115. data/docs/operations/replication.md +33 -33
  116. data/docs/operations/restore.md +6 -6
  117. data/docs/operations/runbook.md +34 -34
  118. data/docs/operations/upgrades.md +14 -14
  119. data/docs/operations/workload-testing.md +17 -17
  120. data/docs/production-readiness.md +118 -118
  121. data/docs/production_validation.md +150 -150
  122. data/docs/rails/active-record.md +11 -11
  123. data/docs/rails/compatibility-guide.md +90 -90
  124. data/docs/rails/database-yml.md +92 -92
  125. data/docs/rails/installation.md +17 -17
  126. data/docs/rails/migrations.md +17 -17
  127. data/docs/rails/production.md +82 -82
  128. data/docs/rails/troubleshooting.md +18 -18
  129. data/docs/release.md +25 -25
  130. data/docs/server/architecture.md +10 -10
  131. data/docs/server/authentication.md +10 -10
  132. data/docs/server/configuration.md +16 -16
  133. data/docs/server/connection-pooling.md +10 -10
  134. data/docs/server/deployment.md +10 -10
  135. data/docs/server/protocol.md +12 -12
  136. data/docs/sql/compatibility-guide.md +82 -82
  137. data/docs/sql/compatibility.md +39 -39
  138. data/docs/sql/data-types.md +10 -10
  139. data/docs/sql/functions.md +9 -9
  140. data/docs/sql/joins.md +9 -9
  141. data/docs/sql/operators.md +9 -9
  142. data/docs/sql/sqlite-compatibility.md +21 -21
  143. data/docs/sql/syntax.md +10 -10
  144. data/docs/sql/transactions.md +10 -10
  145. data/docs/troubleshooting.md +244 -244
  146. data/lessons/01-foundations.md +73 -0
  147. data/lessons/02-local-development.md +121 -0
  148. data/lessons/03-embedded-rubydb.md +99 -0
  149. data/lessons/04-rails-complex-apps.md +138 -0
  150. data/lessons/05-rubydb-production-server.md +237 -0
  151. data/lessons/06-postgresql-massive-apps.md +96 -0
  152. data/lessons/07-hybrid-microservices.md +179 -0
  153. data/lessons/08-migrations-backups-recovery.md +86 -0
  154. data/lessons/09-observability-security-scale.md +87 -0
  155. data/lessons/10-release-readiness.md +192 -0
  156. data/lessons/11-community-adapter.md +323 -0
  157. data/lessons/12-rails-ecommerce-pressure.md +263 -0
  158. data/lib/rubydb/accelerator/client.rb +451 -0
  159. data/lib/rubydb/accelerator/error.rb +22 -0
  160. data/lib/rubydb/accelerator/manager.rb +606 -0
  161. data/lib/rubydb/accelerator.rb +13 -0
  162. data/lib/rubydb/backup/archive.rb +332 -334
  163. data/lib/rubydb/backup/backup.rb +400 -401
  164. data/lib/rubydb/backup/incremental.rb +349 -353
  165. data/lib/rubydb/backup/restore.rb +289 -290
  166. data/lib/rubydb/backup/snapshot.rb +265 -267
  167. data/lib/rubydb/backup/verification.rb +276 -279
  168. data/lib/rubydb/branching/branch.rb +181 -181
  169. data/lib/rubydb/branching/branch_manager.rb +307 -311
  170. data/lib/rubydb/branching/branch_metadata.rb +140 -140
  171. data/lib/rubydb/branching/checkout.rb +165 -166
  172. data/lib/rubydb/branching/copy_on_write.rb +272 -272
  173. data/lib/rubydb/branching/diff.rb +137 -138
  174. data/lib/rubydb/branching/merge.rb +282 -285
  175. data/lib/rubydb/build_info.rb +15 -15
  176. data/lib/rubydb/catalog/catalog.rb +391 -391
  177. data/lib/rubydb/catalog/column.rb +112 -112
  178. data/lib/rubydb/catalog/constraint.rb +180 -180
  179. data/lib/rubydb/catalog/database.rb +184 -184
  180. data/lib/rubydb/catalog/index.rb +97 -97
  181. data/lib/rubydb/catalog/schema.rb +103 -103
  182. data/lib/rubydb/catalog/sequence.rb +90 -90
  183. data/lib/rubydb/catalog/system_catalog.rb +698 -698
  184. data/lib/rubydb/catalog/table.rb +178 -178
  185. data/lib/rubydb/catalog/trigger.rb +102 -102
  186. data/lib/rubydb/catalog/view.rb +66 -66
  187. data/lib/rubydb/cli/application.rb +168 -163
  188. data/lib/rubydb/cli/commands/accelerator.rb +72 -0
  189. data/lib/rubydb/cli/commands/backup.rb +80 -81
  190. data/lib/rubydb/cli/commands/branch.rb +72 -72
  191. data/lib/rubydb/cli/commands/checkout.rb +54 -54
  192. data/lib/rubydb/cli/commands/create.rb +58 -58
  193. data/lib/rubydb/cli/commands/diff.rb +76 -77
  194. data/lib/rubydb/cli/commands/doctor.rb +77 -74
  195. data/lib/rubydb/cli/commands/drop.rb +57 -57
  196. data/lib/rubydb/cli/commands/init.rb +101 -102
  197. data/lib/rubydb/cli/commands/inspect.rb +95 -95
  198. data/lib/rubydb/cli/commands/merge.rb +63 -63
  199. data/lib/rubydb/cli/commands/migrate.rb +62 -62
  200. data/lib/rubydb/cli/commands/restart.rb +42 -39
  201. data/lib/rubydb/cli/commands/restore.rb +121 -121
  202. data/lib/rubydb/cli/commands/shell.rb +365 -365
  203. data/lib/rubydb/cli/commands/snapshot.rb +79 -79
  204. data/lib/rubydb/cli/commands/start.rb +88 -82
  205. data/lib/rubydb/cli/commands/status.rb +96 -92
  206. data/lib/rubydb/cli/commands/stop.rb +47 -47
  207. data/lib/rubydb/cli/commands/vacuum.rb +58 -58
  208. data/lib/rubydb/cli/formatter.rb +221 -221
  209. data/lib/rubydb/cli/output.rb +168 -168
  210. data/lib/rubydb/client/client.rb +309 -304
  211. data/lib/rubydb/client/connection.rb +429 -415
  212. data/lib/rubydb/client/connection_pool.rb +168 -168
  213. data/lib/rubydb/client/connection_url.rb +96 -96
  214. data/lib/rubydb/client/prepared_statement.rb +60 -60
  215. data/lib/rubydb/client/result.rb +127 -123
  216. data/lib/rubydb/client/statement.rb +52 -52
  217. data/lib/rubydb/client/transaction.rb +130 -130
  218. data/lib/rubydb/concurrency/concurrency.rb +19 -19
  219. data/lib/rubydb/concurrency/deadlock_detector.rb +148 -150
  220. data/lib/rubydb/concurrency/latch.rb +101 -101
  221. data/lib/rubydb/concurrency/lock_graph.rb +163 -165
  222. data/lib/rubydb/concurrency/mutex.rb +181 -183
  223. data/lib/rubydb/concurrency/rw_lock.rb +180 -180
  224. data/lib/rubydb/concurrency/scheduler.rb +248 -250
  225. data/lib/rubydb/concurrency/worker_pool.rb +145 -143
  226. data/lib/rubydb/configuration/config.rb +170 -170
  227. data/lib/rubydb/configuration/defaults.rb +191 -179
  228. data/lib/rubydb/configuration/environment.rb +152 -152
  229. data/lib/rubydb/configuration/parser.rb +185 -185
  230. data/lib/rubydb/configuration/validation.rb +228 -221
  231. data/lib/rubydb/constants.rb +74 -74
  232. data/lib/rubydb/constraints/check.rb +181 -181
  233. data/lib/rubydb/constraints/constraint.rb +101 -101
  234. data/lib/rubydb/constraints/foreign_key.rb +130 -130
  235. data/lib/rubydb/constraints/not_null.rb +64 -64
  236. data/lib/rubydb/constraints/primary_key.rb +99 -99
  237. data/lib/rubydb/constraints/unique.rb +106 -108
  238. data/lib/rubydb/constraints/validator.rb +349 -350
  239. data/lib/rubydb/errors/authentication_error.rb +10 -10
  240. data/lib/rubydb/errors/authorization_error.rb +23 -23
  241. data/lib/rubydb/errors/client_error.rb +10 -10
  242. data/lib/rubydb/errors/configuration_error.rb +10 -10
  243. data/lib/rubydb/errors/connection_error.rb +10 -10
  244. data/lib/rubydb/errors/constraint_error.rb +23 -23
  245. data/lib/rubydb/errors/corruption_error.rb +10 -10
  246. data/lib/rubydb/errors/database_error.rb +10 -10
  247. data/lib/rubydb/errors/error.rb +20 -20
  248. data/lib/rubydb/errors/execution_error.rb +10 -10
  249. data/lib/rubydb/errors/parser_error.rb +10 -10
  250. data/lib/rubydb/errors/recovery_error.rb +10 -10
  251. data/lib/rubydb/errors/replication_error.rb +10 -10
  252. data/lib/rubydb/errors/server_error.rb +6 -6
  253. data/lib/rubydb/errors/storage_error.rb +10 -10
  254. data/lib/rubydb/errors/transaction_error.rb +10 -10
  255. data/lib/rubydb/execution/accelerator_dispatch.rb +30 -0
  256. data/lib/rubydb/execution/aggregate_executor.rb +134 -138
  257. data/lib/rubydb/execution/cost_model.rb +72 -0
  258. data/lib/rubydb/execution/delete_executor.rb +110 -112
  259. data/lib/rubydb/execution/distinct_executor.rb +131 -135
  260. data/lib/rubydb/execution/executor.rb +1544 -1188
  261. data/lib/rubydb/execution/expression.rb +191 -193
  262. data/lib/rubydb/execution/index_scan.rb +142 -142
  263. data/lib/rubydb/execution/insert_executor.rb +215 -217
  264. data/lib/rubydb/execution/join_executor.rb +243 -249
  265. data/lib/rubydb/execution/limit_executor.rb +83 -85
  266. data/lib/rubydb/execution/operator_selection.rb +57 -0
  267. data/lib/rubydb/execution/optimizer.rb +227 -215
  268. data/lib/rubydb/execution/physical_plan.rb +47 -0
  269. data/lib/rubydb/execution/plan.rb +355 -353
  270. data/lib/rubydb/execution/planner.rb +508 -536
  271. data/lib/rubydb/execution/predicate.rb +235 -235
  272. data/lib/rubydb/execution/scan.rb +49 -49
  273. data/lib/rubydb/execution/sequential_scan.rb +63 -63
  274. data/lib/rubydb/execution/sort_executor.rb +194 -185
  275. data/lib/rubydb/execution/update_executor.rb +160 -162
  276. data/lib/rubydb/functions/aggregate.rb +70 -70
  277. data/lib/rubydb/functions/date_functions.rb +274 -278
  278. data/lib/rubydb/functions/function.rb +85 -85
  279. data/lib/rubydb/functions/json_functions.rb +231 -215
  280. data/lib/rubydb/functions/numeric_functions.rb +346 -346
  281. data/lib/rubydb/functions/scalar.rb +52 -52
  282. data/lib/rubydb/functions/string_functions.rb +383 -383
  283. data/lib/rubydb/functions/system_functions.rb +258 -246
  284. data/lib/rubydb/history/as_of.rb +238 -238
  285. data/lib/rubydb/history/change.rb +105 -105
  286. data/lib/rubydb/history/history.rb +131 -131
  287. data/lib/rubydb/history/history_manager.rb +228 -229
  288. data/lib/rubydb/history/temporal_query.rb +202 -202
  289. data/lib/rubydb/history/timeline.rb +144 -144
  290. data/lib/rubydb/indexes/btree.rb +215 -186
  291. data/lib/rubydb/indexes/btree_cursor.rb +258 -258
  292. data/lib/rubydb/indexes/btree_node.rb +384 -385
  293. data/lib/rubydb/indexes/hash_index.rb +150 -150
  294. data/lib/rubydb/indexes/index.rb +71 -71
  295. data/lib/rubydb/indexes/index_manager.rb +408 -406
  296. data/lib/rubydb/indexes/index_scan.rb +466 -470
  297. data/lib/rubydb/migrations/migration.rb +253 -254
  298. data/lib/rubydb/migrations/migration_lock.rb +146 -146
  299. data/lib/rubydb/migrations/migration_manager.rb +187 -176
  300. data/lib/rubydb/migrations/migration_version.rb +71 -71
  301. data/lib/rubydb/migrations/schema_diff.rb +211 -211
  302. data/lib/rubydb/migrations/schema_version.rb +64 -64
  303. data/lib/rubydb/monitoring/events.rb +155 -160
  304. data/lib/rubydb/monitoring/health.rb +216 -222
  305. data/lib/rubydb/monitoring/logger.rb +188 -193
  306. data/lib/rubydb/monitoring/metrics.rb +363 -359
  307. data/lib/rubydb/monitoring/performance.rb +176 -176
  308. data/lib/rubydb/monitoring/statistics.rb +168 -170
  309. data/lib/rubydb/mvcc/garbage_collector.rb +199 -199
  310. data/lib/rubydb/mvcc/mvcc.rb +16 -16
  311. data/lib/rubydb/mvcc/snapshot.rb +146 -147
  312. data/lib/rubydb/mvcc/vacuum.rb +180 -180
  313. data/lib/rubydb/mvcc/version.rb +106 -106
  314. data/lib/rubydb/mvcc/version_store.rb +396 -398
  315. data/lib/rubydb/mvcc/visibility.rb +107 -109
  316. data/lib/rubydb/protocol/capabilities.rb +125 -125
  317. data/lib/rubydb/protocol/decoder.rb +142 -145
  318. data/lib/rubydb/protocol/encoder.rb +131 -136
  319. data/lib/rubydb/protocol/handshake.rb +306 -305
  320. data/lib/rubydb/protocol/message.rb +121 -121
  321. data/lib/rubydb/protocol/parameter_binder.rb +101 -0
  322. data/lib/rubydb/protocol/protocol.rb +276 -277
  323. data/lib/rubydb/protocol/version.rb +54 -54
  324. data/lib/rubydb/rails/adapter.rb +245 -239
  325. data/lib/rubydb/rails/connection.rb +312 -314
  326. data/lib/rubydb/rails/database_statements.rb +122 -122
  327. data/lib/rubydb/rails/migration.rb +131 -131
  328. data/lib/rubydb/rails/quoting.rb +109 -109
  329. data/lib/rubydb/rails/result.rb +117 -117
  330. data/lib/rubydb/rails/schema_statements.rb +339 -339
  331. data/lib/rubydb/rails/transaction.rb +105 -105
  332. data/lib/rubydb/rails/type.rb +126 -126
  333. data/lib/rubydb/recovery/checkpoint.rb +261 -257
  334. data/lib/rubydb/recovery/consistency.rb +457 -467
  335. data/lib/rubydb/recovery/corruption_detector.rb +5 -5
  336. data/lib/rubydb/recovery/crash_recovery.rb +381 -387
  337. data/lib/rubydb/recovery/recovery_manager.rb +204 -206
  338. data/lib/rubydb/recovery/redo.rb +235 -237
  339. data/lib/rubydb/recovery/undo.rb +204 -206
  340. data/lib/rubydb/replication/failover.rb +5 -5
  341. data/lib/rubydb/replication/fencing.rb +63 -63
  342. data/lib/rubydb/replication/primary.rb +461 -450
  343. data/lib/rubydb/replication/replica.rb +382 -384
  344. data/lib/rubydb/replication/replication_log.rb +194 -200
  345. data/lib/rubydb/replication/replication_manager.rb +307 -308
  346. data/lib/rubydb/replication/replication_slot.rb +293 -295
  347. data/lib/rubydb/replication/replication_stream.rb +198 -201
  348. data/lib/rubydb/rubydb.rb +570 -560
  349. data/lib/rubydb/security/access_control.rb +252 -254
  350. data/lib/rubydb/security/audit_log.rb +209 -213
  351. data/lib/rubydb/security/authentication.rb +302 -302
  352. data/lib/rubydb/security/authorization.rb +282 -282
  353. data/lib/rubydb/security/credentials.rb +192 -196
  354. data/lib/rubydb/security/password.rb +205 -215
  355. data/lib/rubydb/security/permissions.rb +74 -74
  356. data/lib/rubydb/security/role.rb +99 -101
  357. data/lib/rubydb/security/user.rb +86 -86
  358. data/lib/rubydb/server/connection.rb +383 -366
  359. data/lib/rubydb/server/connection_pool.rb +193 -193
  360. data/lib/rubydb/server/lifecycle.rb +227 -228
  361. data/lib/rubydb/server/listener.rb +139 -136
  362. data/lib/rubydb/server/request_handler.rb +277 -276
  363. data/lib/rubydb/server/server.rb +363 -364
  364. data/lib/rubydb/server/session.rb +416 -369
  365. data/lib/rubydb/server/worker.rb +206 -210
  366. data/lib/rubydb/server/worker_pool.rb +168 -168
  367. data/lib/rubydb/sql/ast/alter_table.rb +169 -169
  368. data/lib/rubydb/sql/ast/begin_transaction.rb +47 -47
  369. data/lib/rubydb/sql/ast/commit.rb +37 -37
  370. data/lib/rubydb/sql/ast/constraint.rb +92 -83
  371. data/lib/rubydb/sql/ast/create_database.rb +41 -41
  372. data/lib/rubydb/sql/ast/create_index.rb +61 -61
  373. data/lib/rubydb/sql/ast/create_schema.rb +52 -52
  374. data/lib/rubydb/sql/ast/create_table.rb +187 -187
  375. data/lib/rubydb/sql/ast/delete.rb +54 -54
  376. data/lib/rubydb/sql/ast/drop_database.rb +41 -41
  377. data/lib/rubydb/sql/ast/drop_index.rb +41 -41
  378. data/lib/rubydb/sql/ast/drop_schema.rb +49 -49
  379. data/lib/rubydb/sql/ast/drop_table.rb +49 -49
  380. data/lib/rubydb/sql/ast/explain.rb +64 -64
  381. data/lib/rubydb/sql/ast/expression.rb +617 -604
  382. data/lib/rubydb/sql/ast/insert.rb +66 -66
  383. data/lib/rubydb/sql/ast/node.rb +42 -42
  384. data/lib/rubydb/sql/ast/rollback.rb +63 -63
  385. data/lib/rubydb/sql/ast/savepoint.rb +59 -59
  386. data/lib/rubydb/sql/ast/select.rb +88 -88
  387. data/lib/rubydb/sql/ast/set_operation.rb +22 -20
  388. data/lib/rubydb/sql/ast/trigger.rb +35 -29
  389. data/lib/rubydb/sql/ast/update.rb +88 -88
  390. data/lib/rubydb/sql/ast/vacuum.rb +19 -19
  391. data/lib/rubydb/sql/ast/view.rb +38 -32
  392. data/lib/rubydb/sql/ast/with.rb +32 -32
  393. data/lib/rubydb/sql/grammar.rb +86 -86
  394. data/lib/rubydb/sql/keywords.rb +156 -156
  395. data/lib/rubydb/sql/lexer.rb +209 -214
  396. data/lib/rubydb/sql/operators.rb +100 -100
  397. data/lib/rubydb/sql/parser.rb +1167 -1170
  398. data/lib/rubydb/sql/planner/analyzer.rb +283 -302
  399. data/lib/rubydb/sql/planner/binder.rb +537 -550
  400. data/lib/rubydb/sql/planner/type_checker.rb +427 -431
  401. data/lib/rubydb/sql/token.rb +210 -210
  402. data/lib/rubydb/storage/buffer_frame.rb +44 -44
  403. data/lib/rubydb/storage/buffer_pool.rb +155 -155
  404. data/lib/rubydb/storage/database_lock.rb +74 -74
  405. data/lib/rubydb/storage/deserializer.rb +332 -342
  406. data/lib/rubydb/storage/engine.rb +2409 -2330
  407. data/lib/rubydb/storage/file_manager.rb +191 -187
  408. data/lib/rubydb/storage/free_space_map.rb +79 -81
  409. data/lib/rubydb/storage/page.rb +92 -94
  410. data/lib/rubydb/storage/page_allocator.rb +852 -855
  411. data/lib/rubydb/storage/page_header.rb +63 -67
  412. data/lib/rubydb/storage/page_manager.rb +127 -131
  413. data/lib/rubydb/storage/record.rb +58 -58
  414. data/lib/rubydb/storage/row.rb +78 -78
  415. data/lib/rubydb/storage/serializer.rb +51 -51
  416. data/lib/rubydb/storage/snapshot_reader.rb +167 -0
  417. data/lib/rubydb/storage/storage_layout.rb +151 -151
  418. data/lib/rubydb/storage/storage_manager.rb +114 -114
  419. data/lib/rubydb/storage/tuple.rb +458 -461
  420. data/lib/rubydb/storage/visibility_map.rb +964 -973
  421. data/lib/rubydb/transactions/commit_manager.rb +219 -220
  422. data/lib/rubydb/transactions/isolation.rb +98 -98
  423. data/lib/rubydb/transactions/lock.rb +76 -76
  424. data/lib/rubydb/transactions/lock_manager.rb +359 -362
  425. data/lib/rubydb/transactions/savepoint.rb +142 -143
  426. data/lib/rubydb/transactions/transaction.rb +214 -215
  427. data/lib/rubydb/transactions/transaction_id.rb +84 -84
  428. data/lib/rubydb/transactions/transaction_log.rb +256 -257
  429. data/lib/rubydb/transactions/transaction_manager.rb +434 -435
  430. data/lib/rubydb/types/bigint.rb +36 -36
  431. data/lib/rubydb/types/blob.rb +37 -37
  432. data/lib/rubydb/types/boolean.rb +34 -34
  433. data/lib/rubydb/types/date.rb +39 -39
  434. data/lib/rubydb/types/decimal.rb +48 -48
  435. data/lib/rubydb/types/float.rb +34 -34
  436. data/lib/rubydb/types/integer.rb +36 -36
  437. data/lib/rubydb/types/json.rb +41 -41
  438. data/lib/rubydb/types/null.rb +34 -34
  439. data/lib/rubydb/types/smallint.rb +36 -36
  440. data/lib/rubydb/types/text.rb +37 -37
  441. data/lib/rubydb/types/time.rb +46 -46
  442. data/lib/rubydb/types/timestamp.rb +39 -39
  443. data/lib/rubydb/types/type.rb +119 -119
  444. data/lib/rubydb/types/uuid.rb +47 -47
  445. data/lib/rubydb/types/varchar.rb +37 -37
  446. data/lib/rubydb/version.rb +32 -32
  447. data/lib/rubydb/wal/archive.rb +207 -193
  448. data/lib/rubydb/wal/checkpoint.rb +181 -183
  449. data/lib/rubydb/wal/lsn.rb +94 -94
  450. data/lib/rubydb/wal/reader.rb +259 -260
  451. data/lib/rubydb/wal/record.rb +105 -105
  452. data/lib/rubydb/wal/segment.rb +193 -193
  453. data/lib/rubydb/wal/wal.rb +481 -452
  454. data/lib/rubydb/wal/writer.rb +236 -236
  455. data/lib/rubydb.rb +7 -7
  456. data/packaging/docker/docker-compose.failover.yml +43 -43
  457. data/packaging/homebrew/rubydb.rb +19 -19
  458. data/rubydb.gemspec +70 -57
  459. data/scripts/benchmark +7 -7
  460. data/scripts/build_accelerator +49 -0
  461. data/scripts/durability_drill +37 -37
  462. data/scripts/fuzz +63 -63
  463. data/scripts/release +77 -42
  464. data/scripts/release_check +43 -43
  465. data/scripts/replication_failover_drill +268 -250
  466. data/scripts/replication_network_failover_drill +287 -255
  467. data/scripts/restore_drill +45 -45
  468. data/scripts/security +45 -0
  469. metadata +102 -1
@@ -1,129 +1,129 @@
1
- # frozen_string_literal: true
2
-
3
- module RubyDB
4
- module Execution
5
- # Plan - Query execution plan
6
- class Plan
7
- attr_reader :type, :table_name, :columns, :projections, :predicate,
8
- :order_by, :group_by, :aggregates, :limit, :offset,
9
- :distinct, :having, :scan_type, :index, :estimated_cost,
10
- :estimated_rows, :joins, :source_reference
11
-
12
- def initialize(type, table_name = nil, columns = [])
13
- @type = type
14
- @table_name = table_name
15
- @columns = columns
16
- @projections = nil
17
- @predicate = nil
18
- @order_by = []
19
- @group_by = []
20
- @aggregates = []
21
- @limit = nil
22
- @offset = nil
23
- @distinct = false
24
- @having = nil
25
- @scan_type = :sequential
26
- @index = nil
27
- @estimated_cost = 0
28
- @estimated_rows = 0
29
- @joins = []
30
- @source_reference = nil
31
- end
32
-
33
- def set_projections(projections)
34
- @projections = projections
35
- self
36
- end
37
-
38
- def set_predicate(predicate)
39
- @predicate = predicate
40
- self
41
- end
42
-
43
- def set_order_by(order_by)
44
- @order_by = order_by
45
- self
46
- end
47
-
48
- def set_group_by(group_by, aggregates = [])
49
- @group_by = group_by
50
- @aggregates = aggregates
51
- self
52
- end
53
-
54
- def set_having(having)
55
- @having = having
56
- self
57
- end
58
-
59
- def set_limit(limit, offset = nil)
60
- @limit = limit
61
- @offset = offset if offset
62
- self
63
- end
64
-
65
- def set_distinct(distinct = true)
66
- @distinct = distinct
67
- self
68
- end
69
-
70
- def set_joins(joins)
71
- @joins = joins
72
- self
73
- end
74
-
75
- def set_source_reference(reference)
76
- @source_reference = reference
77
- self
78
- end
79
-
80
- def set_scan_type(scan_type, index = nil)
81
- @scan_type = scan_type
82
- @index = index
83
- self
84
- end
85
-
86
- def set_cost(estimated_cost, estimated_rows = nil)
87
- @estimated_cost = estimated_cost
88
- @estimated_rows = estimated_rows if estimated_rows
89
- self
90
- end
91
-
92
- def to_s
93
- "Plan(#{@type}) on #{@table_name}"
94
- end
95
-
96
- def inspect
97
- to_s
98
- end
99
-
100
- # Plan types
101
- class Select < Plan
102
- def initialize(table_name, columns = [])
103
- super(:select, table_name, columns)
104
- end
105
- end
106
-
107
- class SetOperation < Plan
108
- attr_reader :left_plan, :right_plan, :operator, :all
109
- def initialize(left_plan, right_plan, operator, all: false)
110
- super(:set_operation)
111
- @left_plan, @right_plan, @operator, @all = left_plan, right_plan, operator, all
112
- end
113
- end
114
-
115
- class With < Plan
116
- attr_reader :ctes, :query_plan, :recursive
117
-
118
- def initialize(ctes, query_plan, recursive: false)
119
- super(:with)
120
- @ctes = ctes
121
- @query_plan = query_plan
122
- @recursive = recursive
123
- end
124
- end
125
-
126
- class Insert < Plan
1
+ # frozen_string_literal: true
2
+
3
+ module RubyDB
4
+ module Execution
5
+ # Plan - Query execution plan
6
+ class Plan
7
+ attr_reader :type, :table_name, :columns, :projections, :predicate,
8
+ :order_by, :group_by, :aggregates, :limit, :offset,
9
+ :distinct, :having, :scan_type, :index, :estimated_cost,
10
+ :estimated_rows, :joins, :source_reference
11
+
12
+ def initialize(type, table_name = nil, columns = [])
13
+ @type = type
14
+ @table_name = table_name
15
+ @columns = columns
16
+ @projections = nil
17
+ @predicate = nil
18
+ @order_by = []
19
+ @group_by = []
20
+ @aggregates = []
21
+ @limit = nil
22
+ @offset = nil
23
+ @distinct = false
24
+ @having = nil
25
+ @scan_type = :sequential
26
+ @index = nil
27
+ @estimated_cost = 0
28
+ @estimated_rows = 0
29
+ @joins = []
30
+ @source_reference = nil
31
+ end
32
+
33
+ def set_projections(projections)
34
+ @projections = projections
35
+ self
36
+ end
37
+
38
+ def set_predicate(predicate)
39
+ @predicate = predicate
40
+ self
41
+ end
42
+
43
+ def set_order_by(order_by)
44
+ @order_by = order_by
45
+ self
46
+ end
47
+
48
+ def set_group_by(group_by, aggregates = [])
49
+ @group_by = group_by
50
+ @aggregates = aggregates
51
+ self
52
+ end
53
+
54
+ def set_having(having)
55
+ @having = having
56
+ self
57
+ end
58
+
59
+ def set_limit(limit, offset = nil)
60
+ @limit = limit
61
+ @offset = offset if offset
62
+ self
63
+ end
64
+
65
+ def set_distinct(distinct = true)
66
+ @distinct = distinct
67
+ self
68
+ end
69
+
70
+ def set_joins(joins)
71
+ @joins = joins
72
+ self
73
+ end
74
+
75
+ def set_source_reference(reference)
76
+ @source_reference = reference
77
+ self
78
+ end
79
+
80
+ def set_scan_type(scan_type, index = nil)
81
+ @scan_type = scan_type
82
+ @index = index
83
+ self
84
+ end
85
+
86
+ def set_cost(estimated_cost, estimated_rows = nil)
87
+ @estimated_cost = estimated_cost
88
+ @estimated_rows = estimated_rows if estimated_rows
89
+ self
90
+ end
91
+
92
+ def to_s
93
+ "Plan(#{@type}) on #{@table_name}"
94
+ end
95
+
96
+ def inspect
97
+ to_s
98
+ end
99
+
100
+ # Plan types
101
+ class Select < Plan
102
+ def initialize(table_name, columns = [])
103
+ super(:select, table_name, columns)
104
+ end
105
+ end
106
+
107
+ class SetOperation < Plan
108
+ attr_reader :left_plan, :right_plan, :operator, :all
109
+ def initialize(left_plan, right_plan, operator, all: false)
110
+ super(:set_operation)
111
+ @left_plan, @right_plan, @operator, @all = left_plan, right_plan, operator, all
112
+ end
113
+ end
114
+
115
+ class With < Plan
116
+ attr_reader :ctes, :query_plan, :recursive
117
+
118
+ def initialize(ctes, query_plan, recursive: false)
119
+ super(:with)
120
+ @ctes = ctes
121
+ @query_plan = query_plan
122
+ @recursive = recursive
123
+ end
124
+ end
125
+
126
+ class Insert < Plan
127
127
  attr_reader :values, :rows, :on_conflict, :default_values
128
128
 
129
129
  def initialize(table_name, columns = [], values = [], rows: nil, on_conflict: nil, default_values: false)
@@ -133,230 +133,232 @@ module RubyDB
133
133
  @on_conflict = on_conflict
134
134
  @default_values = default_values
135
135
  end
136
- end
137
-
138
- class Update < Plan
139
- attr_reader :assignments
140
-
141
- def initialize(table_name, assignments = [])
142
- super(:update, table_name)
143
- @assignments = assignments
144
- end
145
- end
146
-
147
- class Delete < Plan
148
- def initialize(table_name)
149
- super(:delete, table_name)
150
- end
151
- end
152
-
153
- class CreateTable < Plan
154
- attr_reader :options
155
-
156
- def initialize(table_name, columns = [], options = {})
157
- super(:create_table, table_name, columns)
158
- @options = options
159
- end
160
- end
161
-
162
- class DropTable < Plan
163
- attr_reader :options
164
-
165
- def initialize(table_name, options = {})
166
- super(:drop_table, table_name)
167
- @options = options
168
- end
169
- end
170
-
171
- class CreateDatabase < Plan
172
- attr_reader :options
173
- def initialize(name, options = {})
174
- super(:create_database)
175
- @database_name = name
176
- @options = options
177
- end
178
- def database_name = @database_name
179
- end
180
-
181
- class DropDatabase < Plan
182
- attr_reader :options
183
- def initialize(name, options = {})
184
- super(:drop_database)
185
- @database_name = name
186
- @options = options
187
- end
188
- def database_name = @database_name
189
- end
190
-
191
- class CreateSchema < Plan
192
- attr_reader :schema_name, :options
193
- def initialize(name, options = {})
194
- super(:create_schema)
195
- @schema_name = name
196
- @options = options
197
- end
198
- end
199
-
200
- class DropSchema < Plan
201
- attr_reader :schema_name, :options
202
- def initialize(name, options = {})
203
- super(:drop_schema)
204
- @schema_name = name
205
- @options = options
206
- end
207
- end
208
-
209
- class CreateView < Plan
210
- attr_reader :view_name, :query, :options
211
- def initialize(name, query, options = {})
212
- super(:create_view)
213
- @view_name = name
214
- @query = query
215
- @options = options
216
- end
217
- end
218
-
219
- class DropView < Plan
220
- attr_reader :view_name, :options
221
- def initialize(name, options = {})
222
- super(:drop_view)
223
- @view_name = name
224
- @options = options
225
- end
226
- end
227
-
228
- class CreateTrigger < Plan
229
- attr_reader :trigger_name, :timing, :event, :target_table, :function_name
230
- def initialize(name, timing, event, table, function_name)
231
- super(:create_trigger)
232
- @trigger_name, @timing, @event, @target_table, @function_name = name, timing, event, table, function_name
233
- end
234
- end
235
-
236
- class DropTrigger < Plan
237
- attr_reader :trigger_name, :options
238
- def initialize(name, options = {})
239
- super(:drop_trigger)
240
- @trigger_name, @options = name, options
241
- end
242
- end
243
-
244
- class Vacuum < Plan
245
- def initialize
246
- super(:vacuum)
247
- end
248
- end
249
-
250
- class AlterTableAddColumn < Plan
251
- attr_reader :column_name, :column_type, :options
252
-
253
- def initialize(table_name, column_name, column_type, options = {})
254
- super(:alter_table_add_column, table_name)
255
- @column_name = column_name
256
- @column_type = column_type
257
- @options = options
258
- end
259
- end
260
-
261
- class AlterTableDropColumn < Plan
262
- attr_reader :column_name
263
-
264
- def initialize(table_name, column_name)
265
- super(:alter_table_drop_column, table_name)
266
- @column_name = column_name
267
- end
268
- end
269
-
270
- class AlterTableAddConstraint < Plan
271
- attr_reader :constraint
272
- def initialize(table_name, constraint)
273
- super(:alter_table_add_constraint, table_name)
274
- @constraint = constraint
275
- end
276
- end
277
-
278
- class AlterTableDropConstraint < Plan
279
- attr_reader :constraint_name
280
- def initialize(table_name, constraint_name)
281
- super(:alter_table_drop_constraint, table_name)
282
- @constraint_name = constraint_name
283
- end
284
- end
285
-
286
- class CreateIndex < Plan
287
- attr_reader :index_name, :options
288
-
289
- def initialize(index_name, table_name, columns = [], options = {})
290
- super(:create_index, table_name, columns)
291
- @index_name = index_name
292
- @options = options
293
- end
294
- end
295
-
296
- class DropIndex < Plan
297
- attr_reader :index_name, :options
298
-
299
- def initialize(index_name, options = {})
300
- super(:drop_index)
301
- @index_name = index_name
302
- @options = options
303
- end
304
- end
305
-
306
- class BeginTransaction < Plan
307
- attr_reader :isolation_level
308
-
309
- def initialize(isolation_level = :read_committed)
310
- super(:begin_transaction)
311
- @isolation_level = isolation_level
312
- end
313
- end
314
-
315
- class Commit < Plan
316
- def initialize
317
- super(:commit)
318
- end
319
- end
320
-
321
- class Rollback < Plan
322
- def initialize
323
- super(:rollback)
324
- end
325
- end
326
-
327
- class Savepoint < Plan
328
- attr_reader :name
329
- def initialize(name)
330
- super(:savepoint)
331
- @name = name
332
- end
333
- end
334
-
335
- class RollbackToSavepoint < Plan
336
- attr_reader :name
337
- def initialize(name)
338
- super(:rollback_to_savepoint)
339
- @name = name
340
- end
341
- end
342
-
343
- class ReleaseSavepoint < Plan
344
- attr_reader :name
345
- def initialize(name)
346
- super(:release_savepoint)
347
- @name = name
348
- end
349
- end
350
-
351
- class Explain < Plan
352
- attr_reader :statement, :analyze
353
-
354
- def initialize(statement, analyze = false)
355
- super(:explain)
356
- @statement = statement
357
- @analyze = analyze
358
- end
359
- end
360
- end
361
- end
362
- end
136
+ end
137
+
138
+ class Update < Plan
139
+ attr_reader :assignments
140
+
141
+ def initialize(table_name, assignments = [])
142
+ super(:update, table_name)
143
+ @assignments = assignments
144
+ end
145
+ end
146
+
147
+ class Delete < Plan
148
+ def initialize(table_name)
149
+ super(:delete, table_name)
150
+ end
151
+ end
152
+
153
+ class CreateTable < Plan
154
+ attr_reader :options
155
+
156
+ def initialize(table_name, columns = [], options = {})
157
+ super(:create_table, table_name, columns)
158
+ @options = options
159
+ end
160
+ end
161
+
162
+ class DropTable < Plan
163
+ attr_reader :options
164
+
165
+ def initialize(table_name, options = {})
166
+ super(:drop_table, table_name)
167
+ @options = options
168
+ end
169
+ end
170
+
171
+ class CreateDatabase < Plan
172
+ attr_reader :options
173
+ def initialize(name, options = {})
174
+ super(:create_database)
175
+ @database_name = name
176
+ @options = options
177
+ end
178
+
179
+ attr_reader :database_name
180
+ end
181
+
182
+ class DropDatabase < Plan
183
+ attr_reader :options
184
+ def initialize(name, options = {})
185
+ super(:drop_database)
186
+ @database_name = name
187
+ @options = options
188
+ end
189
+
190
+ attr_reader :database_name
191
+ end
192
+
193
+ class CreateSchema < Plan
194
+ attr_reader :schema_name, :options
195
+ def initialize(name, options = {})
196
+ super(:create_schema)
197
+ @schema_name = name
198
+ @options = options
199
+ end
200
+ end
201
+
202
+ class DropSchema < Plan
203
+ attr_reader :schema_name, :options
204
+ def initialize(name, options = {})
205
+ super(:drop_schema)
206
+ @schema_name = name
207
+ @options = options
208
+ end
209
+ end
210
+
211
+ class CreateView < Plan
212
+ attr_reader :view_name, :query, :options
213
+ def initialize(name, query, options = {})
214
+ super(:create_view)
215
+ @view_name = name
216
+ @query = query
217
+ @options = options
218
+ end
219
+ end
220
+
221
+ class DropView < Plan
222
+ attr_reader :view_name, :options
223
+ def initialize(name, options = {})
224
+ super(:drop_view)
225
+ @view_name = name
226
+ @options = options
227
+ end
228
+ end
229
+
230
+ class CreateTrigger < Plan
231
+ attr_reader :trigger_name, :timing, :event, :target_table, :function_name
232
+ def initialize(name, timing, event, table, function_name)
233
+ super(:create_trigger)
234
+ @trigger_name, @timing, @event, @target_table, @function_name = name, timing, event, table, function_name
235
+ end
236
+ end
237
+
238
+ class DropTrigger < Plan
239
+ attr_reader :trigger_name, :options
240
+ def initialize(name, options = {})
241
+ super(:drop_trigger)
242
+ @trigger_name, @options = name, options
243
+ end
244
+ end
245
+
246
+ class Vacuum < Plan
247
+ def initialize
248
+ super(:vacuum)
249
+ end
250
+ end
251
+
252
+ class AlterTableAddColumn < Plan
253
+ attr_reader :column_name, :column_type, :options
254
+
255
+ def initialize(table_name, column_name, column_type, options = {})
256
+ super(:alter_table_add_column, table_name)
257
+ @column_name = column_name
258
+ @column_type = column_type
259
+ @options = options
260
+ end
261
+ end
262
+
263
+ class AlterTableDropColumn < Plan
264
+ attr_reader :column_name
265
+
266
+ def initialize(table_name, column_name)
267
+ super(:alter_table_drop_column, table_name)
268
+ @column_name = column_name
269
+ end
270
+ end
271
+
272
+ class AlterTableAddConstraint < Plan
273
+ attr_reader :constraint
274
+ def initialize(table_name, constraint)
275
+ super(:alter_table_add_constraint, table_name)
276
+ @constraint = constraint
277
+ end
278
+ end
279
+
280
+ class AlterTableDropConstraint < Plan
281
+ attr_reader :constraint_name
282
+ def initialize(table_name, constraint_name)
283
+ super(:alter_table_drop_constraint, table_name)
284
+ @constraint_name = constraint_name
285
+ end
286
+ end
287
+
288
+ class CreateIndex < Plan
289
+ attr_reader :index_name, :options
290
+
291
+ def initialize(index_name, table_name, columns = [], options = {})
292
+ super(:create_index, table_name, columns)
293
+ @index_name = index_name
294
+ @options = options
295
+ end
296
+ end
297
+
298
+ class DropIndex < Plan
299
+ attr_reader :index_name, :options
300
+
301
+ def initialize(index_name, options = {})
302
+ super(:drop_index)
303
+ @index_name = index_name
304
+ @options = options
305
+ end
306
+ end
307
+
308
+ class BeginTransaction < Plan
309
+ attr_reader :isolation_level
310
+
311
+ def initialize(isolation_level = :read_committed)
312
+ super(:begin_transaction)
313
+ @isolation_level = isolation_level
314
+ end
315
+ end
316
+
317
+ class Commit < Plan
318
+ def initialize
319
+ super(:commit)
320
+ end
321
+ end
322
+
323
+ class Rollback < Plan
324
+ def initialize
325
+ super(:rollback)
326
+ end
327
+ end
328
+
329
+ class Savepoint < Plan
330
+ attr_reader :name
331
+ def initialize(name)
332
+ super(:savepoint)
333
+ @name = name
334
+ end
335
+ end
336
+
337
+ class RollbackToSavepoint < Plan
338
+ attr_reader :name
339
+ def initialize(name)
340
+ super(:rollback_to_savepoint)
341
+ @name = name
342
+ end
343
+ end
344
+
345
+ class ReleaseSavepoint < Plan
346
+ attr_reader :name
347
+ def initialize(name)
348
+ super(:release_savepoint)
349
+ @name = name
350
+ end
351
+ end
352
+
353
+ class Explain < Plan
354
+ attr_reader :statement, :analyze
355
+
356
+ def initialize(statement, analyze = false)
357
+ super(:explain)
358
+ @statement = statement
359
+ @analyze = analyze
360
+ end
361
+ end
362
+ end
363
+ end
364
+ end