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.
- checksums.yaml +4 -4
- data/.github/PULL_REQUEST_TEMPLATE.md +15 -15
- data/.github/workflows/benchmark.yml +26 -26
- data/.github/workflows/compatibility.yml +63 -63
- data/.github/workflows/fuzz.yml +33 -33
- data/.github/workflows/lint.yml +21 -21
- data/.github/workflows/operations.yml +24 -24
- data/.github/workflows/production-validation.yml +111 -111
- data/.github/workflows/release.yml +77 -77
- data/.github/workflows/security.yml +39 -37
- data/.github/workflows/test.yml +26 -26
- data/.github/workflows/workload.yml +58 -58
- data/.gitignore +16 -5
- data/.rubocop.yml +50 -44
- data/.standard.yml +9 -14
- data/ARCHITECTURE.md +21 -21
- data/CHANGELOG.md +57 -27
- data/CODE_OF_CONDUCT.md +13 -13
- data/CONTRIBUTING.md +29 -29
- data/GOVERNANCE.md +16 -16
- data/Gemfile +18 -17
- data/Gemfile.lock +125 -71
- data/README.md +168 -12
- data/ROADMAP.md +27 -27
- data/Rakefile +76 -71
- data/SECURITY.md +54 -54
- data/SUPPORT.md +14 -14
- data/accelerator/bin/SHA256SUMS +6 -0
- data/accelerator/bin/rubydb-accelerator-darwin-amd64 +0 -0
- data/accelerator/bin/rubydb-accelerator-darwin-arm64 +0 -0
- data/accelerator/bin/rubydb-accelerator-linux-amd64 +0 -0
- data/accelerator/bin/rubydb-accelerator-linux-arm64 +0 -0
- data/accelerator/bin/rubydb-accelerator-windows-amd64.exe +0 -0
- data/accelerator/bin/rubydb-accelerator-windows-arm64.exe +0 -0
- data/accelerator/cmd/rubydb-accelerator/main.go +11 -0
- data/accelerator/go.mod +3 -0
- data/accelerator/internal/execution/aggregate.go +94 -0
- data/accelerator/internal/execution/distinct.go +22 -0
- data/accelerator/internal/execution/filter.go +73 -0
- data/accelerator/internal/execution/join.go +79 -0
- data/accelerator/internal/execution/operators.go +167 -0
- data/accelerator/internal/execution/scan.go +20 -0
- data/accelerator/internal/execution/sort.go +62 -0
- data/accelerator/internal/execution/types.go +136 -0
- data/accelerator/internal/execution/value.go +67 -0
- data/accelerator/internal/memory/arena.go +47 -0
- data/accelerator/internal/memory/reuse.go +22 -0
- data/accelerator/internal/metrics/registry.go +67 -0
- data/accelerator/internal/parallel/bounded_queue.go +56 -0
- data/accelerator/internal/parallel/scheduler.go +47 -0
- data/accelerator/internal/parallel/worker_pool.go +53 -0
- data/accelerator/internal/protocol/cancellation.go +48 -0
- data/accelerator/internal/protocol/columnar.go +263 -0
- data/accelerator/internal/protocol/frame.go +187 -0
- data/accelerator/internal/runtime/worker.go +521 -0
- data/accelerator/internal/storage/page_reader.go +81 -0
- data/accelerator/internal/storage/snapshot_scan.go +539 -0
- data/accelerator/internal/wal/checksum.go +13 -0
- data/accelerator/internal/wal/compression.go +41 -0
- data/accelerator/internal/wal/group_commit.go +24 -0
- data/accelerator/internal/wal/record_encoder.go +40 -0
- data/adapters/activerecord/Gemfile +11 -11
- data/adapters/activerecord/README.md +8 -3
- data/adapters/activerecord/lib/active_record/connection_adapters/rubydb_adapter.rb +881 -879
- data/adapters/activerecord/rubydb-activerecord.gemspec +21 -21
- data/adapters/activerecord/spec/rubydb_adapter_integration_spec.rb +143 -143
- data/adapters/ruby/README.md +18 -18
- data/adapters/sequel/README.md +11 -11
- data/config/monitoring/prometheus-alerts.yml +39 -39
- data/config/production.yml +36 -36
- data/docs/README.md +77 -71
- data/docs/architecture/concurrency.md +14 -14
- data/docs/architecture/current-state.md +125 -125
- data/docs/architecture/execution-engine.md +25 -25
- data/docs/architecture/go-accelerator.md +179 -0
- data/docs/architecture/indexes.md +19 -19
- data/docs/architecture/mvcc.md +19 -19
- data/docs/architecture/overview.md +13 -13
- data/docs/architecture/pages.md +11 -11
- data/docs/architecture/production-roadmap.md +82 -82
- data/docs/architecture/query-planner.md +20 -20
- data/docs/architecture/recovery.md +18 -18
- data/docs/architecture/sql-engine.md +12 -12
- data/docs/architecture/storage-engine.md +14 -14
- data/docs/architecture/transactions.md +10 -10
- data/docs/architecture/wal.md +28 -28
- data/docs/cli-cheatsheet.md +98 -98
- data/docs/cli.md +299 -275
- data/docs/contributing/architecture.md +9 -9
- data/docs/contributing/benchmarking.md +30 -14
- data/docs/contributing/development.md +16 -16
- data/docs/contributing/release-process.md +49 -49
- data/docs/contributing/testing.md +16 -16
- data/docs/debugging.md +229 -229
- data/docs/developer/branching.md +10 -10
- data/docs/developer/database-diff.md +10 -10
- data/docs/developer/local-development.md +49 -17
- data/docs/developer/snapshots.md +9 -9
- data/docs/developer/temporal-data.md +10 -10
- data/docs/developer-guide.md +297 -297
- data/docs/getting-started/first-database.md +16 -16
- data/docs/getting-started/first-query.md +13 -13
- data/docs/getting-started/installation.md +19 -19
- data/docs/getting-started/local-to-production.md +300 -300
- data/docs/getting-started/quickstart.md +17 -17
- data/docs/getting-started/rails.md +16 -16
- data/docs/hardening_backlog.md +93 -93
- data/docs/lessons-learned.md +112 -112
- data/docs/operations/backups.md +33 -33
- data/docs/operations/disaster-recovery.md +31 -31
- data/docs/operations/failover.md +30 -30
- data/docs/operations/monitoring.md +25 -25
- data/docs/operations/production-guide.md +295 -295
- data/docs/operations/production-runbook.md +45 -45
- data/docs/operations/replication.md +33 -33
- data/docs/operations/restore.md +6 -6
- data/docs/operations/runbook.md +34 -34
- data/docs/operations/upgrades.md +14 -14
- data/docs/operations/workload-testing.md +17 -17
- data/docs/production-readiness.md +118 -118
- data/docs/production_validation.md +150 -150
- data/docs/rails/active-record.md +11 -11
- data/docs/rails/compatibility-guide.md +90 -90
- data/docs/rails/database-yml.md +92 -92
- data/docs/rails/installation.md +17 -17
- data/docs/rails/migrations.md +17 -17
- data/docs/rails/production.md +82 -82
- data/docs/rails/troubleshooting.md +18 -18
- data/docs/release.md +25 -25
- data/docs/server/architecture.md +10 -10
- data/docs/server/authentication.md +10 -10
- data/docs/server/configuration.md +16 -16
- data/docs/server/connection-pooling.md +10 -10
- data/docs/server/deployment.md +10 -10
- data/docs/server/protocol.md +12 -12
- data/docs/sql/compatibility-guide.md +82 -82
- data/docs/sql/compatibility.md +39 -39
- data/docs/sql/data-types.md +10 -10
- data/docs/sql/functions.md +9 -9
- data/docs/sql/joins.md +9 -9
- data/docs/sql/operators.md +9 -9
- data/docs/sql/sqlite-compatibility.md +21 -21
- data/docs/sql/syntax.md +10 -10
- data/docs/sql/transactions.md +10 -10
- data/docs/troubleshooting.md +244 -244
- data/lessons/01-foundations.md +73 -0
- data/lessons/02-local-development.md +121 -0
- data/lessons/03-embedded-rubydb.md +99 -0
- data/lessons/04-rails-complex-apps.md +138 -0
- data/lessons/05-rubydb-production-server.md +237 -0
- data/lessons/06-postgresql-massive-apps.md +96 -0
- data/lessons/07-hybrid-microservices.md +179 -0
- data/lessons/08-migrations-backups-recovery.md +86 -0
- data/lessons/09-observability-security-scale.md +87 -0
- data/lessons/10-release-readiness.md +192 -0
- data/lessons/11-community-adapter.md +323 -0
- data/lessons/12-rails-ecommerce-pressure.md +263 -0
- data/lib/rubydb/accelerator/client.rb +451 -0
- data/lib/rubydb/accelerator/error.rb +22 -0
- data/lib/rubydb/accelerator/manager.rb +606 -0
- data/lib/rubydb/accelerator.rb +13 -0
- data/lib/rubydb/backup/archive.rb +332 -334
- data/lib/rubydb/backup/backup.rb +400 -401
- data/lib/rubydb/backup/incremental.rb +349 -353
- data/lib/rubydb/backup/restore.rb +289 -290
- data/lib/rubydb/backup/snapshot.rb +265 -267
- data/lib/rubydb/backup/verification.rb +276 -279
- data/lib/rubydb/branching/branch.rb +181 -181
- data/lib/rubydb/branching/branch_manager.rb +307 -311
- data/lib/rubydb/branching/branch_metadata.rb +140 -140
- data/lib/rubydb/branching/checkout.rb +165 -166
- data/lib/rubydb/branching/copy_on_write.rb +272 -272
- data/lib/rubydb/branching/diff.rb +137 -138
- data/lib/rubydb/branching/merge.rb +282 -285
- data/lib/rubydb/build_info.rb +15 -15
- data/lib/rubydb/catalog/catalog.rb +391 -391
- data/lib/rubydb/catalog/column.rb +112 -112
- data/lib/rubydb/catalog/constraint.rb +180 -180
- data/lib/rubydb/catalog/database.rb +184 -184
- data/lib/rubydb/catalog/index.rb +97 -97
- data/lib/rubydb/catalog/schema.rb +103 -103
- data/lib/rubydb/catalog/sequence.rb +90 -90
- data/lib/rubydb/catalog/system_catalog.rb +698 -698
- data/lib/rubydb/catalog/table.rb +178 -178
- data/lib/rubydb/catalog/trigger.rb +102 -102
- data/lib/rubydb/catalog/view.rb +66 -66
- data/lib/rubydb/cli/application.rb +168 -163
- data/lib/rubydb/cli/commands/accelerator.rb +72 -0
- data/lib/rubydb/cli/commands/backup.rb +80 -81
- data/lib/rubydb/cli/commands/branch.rb +72 -72
- data/lib/rubydb/cli/commands/checkout.rb +54 -54
- data/lib/rubydb/cli/commands/create.rb +58 -58
- data/lib/rubydb/cli/commands/diff.rb +76 -77
- data/lib/rubydb/cli/commands/doctor.rb +77 -74
- data/lib/rubydb/cli/commands/drop.rb +57 -57
- data/lib/rubydb/cli/commands/init.rb +101 -102
- data/lib/rubydb/cli/commands/inspect.rb +95 -95
- data/lib/rubydb/cli/commands/merge.rb +63 -63
- data/lib/rubydb/cli/commands/migrate.rb +62 -62
- data/lib/rubydb/cli/commands/restart.rb +42 -39
- data/lib/rubydb/cli/commands/restore.rb +121 -121
- data/lib/rubydb/cli/commands/shell.rb +365 -365
- data/lib/rubydb/cli/commands/snapshot.rb +79 -79
- data/lib/rubydb/cli/commands/start.rb +88 -82
- data/lib/rubydb/cli/commands/status.rb +96 -92
- data/lib/rubydb/cli/commands/stop.rb +47 -47
- data/lib/rubydb/cli/commands/vacuum.rb +58 -58
- data/lib/rubydb/cli/formatter.rb +221 -221
- data/lib/rubydb/cli/output.rb +168 -168
- data/lib/rubydb/client/client.rb +309 -304
- data/lib/rubydb/client/connection.rb +429 -415
- data/lib/rubydb/client/connection_pool.rb +168 -168
- data/lib/rubydb/client/connection_url.rb +96 -96
- data/lib/rubydb/client/prepared_statement.rb +60 -60
- data/lib/rubydb/client/result.rb +127 -123
- data/lib/rubydb/client/statement.rb +52 -52
- data/lib/rubydb/client/transaction.rb +130 -130
- data/lib/rubydb/concurrency/concurrency.rb +19 -19
- data/lib/rubydb/concurrency/deadlock_detector.rb +148 -150
- data/lib/rubydb/concurrency/latch.rb +101 -101
- data/lib/rubydb/concurrency/lock_graph.rb +163 -165
- data/lib/rubydb/concurrency/mutex.rb +181 -183
- data/lib/rubydb/concurrency/rw_lock.rb +180 -180
- data/lib/rubydb/concurrency/scheduler.rb +248 -250
- data/lib/rubydb/concurrency/worker_pool.rb +145 -143
- data/lib/rubydb/configuration/config.rb +170 -170
- data/lib/rubydb/configuration/defaults.rb +191 -179
- data/lib/rubydb/configuration/environment.rb +152 -152
- data/lib/rubydb/configuration/parser.rb +185 -185
- data/lib/rubydb/configuration/validation.rb +228 -221
- data/lib/rubydb/constants.rb +74 -74
- data/lib/rubydb/constraints/check.rb +181 -181
- data/lib/rubydb/constraints/constraint.rb +101 -101
- data/lib/rubydb/constraints/foreign_key.rb +130 -130
- data/lib/rubydb/constraints/not_null.rb +64 -64
- data/lib/rubydb/constraints/primary_key.rb +99 -99
- data/lib/rubydb/constraints/unique.rb +106 -108
- data/lib/rubydb/constraints/validator.rb +349 -350
- data/lib/rubydb/errors/authentication_error.rb +10 -10
- data/lib/rubydb/errors/authorization_error.rb +23 -23
- data/lib/rubydb/errors/client_error.rb +10 -10
- data/lib/rubydb/errors/configuration_error.rb +10 -10
- data/lib/rubydb/errors/connection_error.rb +10 -10
- data/lib/rubydb/errors/constraint_error.rb +23 -23
- data/lib/rubydb/errors/corruption_error.rb +10 -10
- data/lib/rubydb/errors/database_error.rb +10 -10
- data/lib/rubydb/errors/error.rb +20 -20
- data/lib/rubydb/errors/execution_error.rb +10 -10
- data/lib/rubydb/errors/parser_error.rb +10 -10
- data/lib/rubydb/errors/recovery_error.rb +10 -10
- data/lib/rubydb/errors/replication_error.rb +10 -10
- data/lib/rubydb/errors/server_error.rb +6 -6
- data/lib/rubydb/errors/storage_error.rb +10 -10
- data/lib/rubydb/errors/transaction_error.rb +10 -10
- data/lib/rubydb/execution/accelerator_dispatch.rb +30 -0
- data/lib/rubydb/execution/aggregate_executor.rb +134 -138
- data/lib/rubydb/execution/cost_model.rb +72 -0
- data/lib/rubydb/execution/delete_executor.rb +110 -112
- data/lib/rubydb/execution/distinct_executor.rb +131 -135
- data/lib/rubydb/execution/executor.rb +1544 -1188
- data/lib/rubydb/execution/expression.rb +191 -193
- data/lib/rubydb/execution/index_scan.rb +142 -142
- data/lib/rubydb/execution/insert_executor.rb +215 -217
- data/lib/rubydb/execution/join_executor.rb +243 -249
- data/lib/rubydb/execution/limit_executor.rb +83 -85
- data/lib/rubydb/execution/operator_selection.rb +57 -0
- data/lib/rubydb/execution/optimizer.rb +227 -215
- data/lib/rubydb/execution/physical_plan.rb +47 -0
- data/lib/rubydb/execution/plan.rb +355 -353
- data/lib/rubydb/execution/planner.rb +508 -536
- data/lib/rubydb/execution/predicate.rb +235 -235
- data/lib/rubydb/execution/scan.rb +49 -49
- data/lib/rubydb/execution/sequential_scan.rb +63 -63
- data/lib/rubydb/execution/sort_executor.rb +194 -185
- data/lib/rubydb/execution/update_executor.rb +160 -162
- data/lib/rubydb/functions/aggregate.rb +70 -70
- data/lib/rubydb/functions/date_functions.rb +274 -278
- data/lib/rubydb/functions/function.rb +85 -85
- data/lib/rubydb/functions/json_functions.rb +231 -215
- data/lib/rubydb/functions/numeric_functions.rb +346 -346
- data/lib/rubydb/functions/scalar.rb +52 -52
- data/lib/rubydb/functions/string_functions.rb +383 -383
- data/lib/rubydb/functions/system_functions.rb +258 -246
- data/lib/rubydb/history/as_of.rb +238 -238
- data/lib/rubydb/history/change.rb +105 -105
- data/lib/rubydb/history/history.rb +131 -131
- data/lib/rubydb/history/history_manager.rb +228 -229
- data/lib/rubydb/history/temporal_query.rb +202 -202
- data/lib/rubydb/history/timeline.rb +144 -144
- data/lib/rubydb/indexes/btree.rb +215 -186
- data/lib/rubydb/indexes/btree_cursor.rb +258 -258
- data/lib/rubydb/indexes/btree_node.rb +384 -385
- data/lib/rubydb/indexes/hash_index.rb +150 -150
- data/lib/rubydb/indexes/index.rb +71 -71
- data/lib/rubydb/indexes/index_manager.rb +408 -406
- data/lib/rubydb/indexes/index_scan.rb +466 -470
- data/lib/rubydb/migrations/migration.rb +253 -254
- data/lib/rubydb/migrations/migration_lock.rb +146 -146
- data/lib/rubydb/migrations/migration_manager.rb +187 -176
- data/lib/rubydb/migrations/migration_version.rb +71 -71
- data/lib/rubydb/migrations/schema_diff.rb +211 -211
- data/lib/rubydb/migrations/schema_version.rb +64 -64
- data/lib/rubydb/monitoring/events.rb +155 -160
- data/lib/rubydb/monitoring/health.rb +216 -222
- data/lib/rubydb/monitoring/logger.rb +188 -193
- data/lib/rubydb/monitoring/metrics.rb +363 -359
- data/lib/rubydb/monitoring/performance.rb +176 -176
- data/lib/rubydb/monitoring/statistics.rb +168 -170
- data/lib/rubydb/mvcc/garbage_collector.rb +199 -199
- data/lib/rubydb/mvcc/mvcc.rb +16 -16
- data/lib/rubydb/mvcc/snapshot.rb +146 -147
- data/lib/rubydb/mvcc/vacuum.rb +180 -180
- data/lib/rubydb/mvcc/version.rb +106 -106
- data/lib/rubydb/mvcc/version_store.rb +396 -398
- data/lib/rubydb/mvcc/visibility.rb +107 -109
- data/lib/rubydb/protocol/capabilities.rb +125 -125
- data/lib/rubydb/protocol/decoder.rb +142 -145
- data/lib/rubydb/protocol/encoder.rb +131 -136
- data/lib/rubydb/protocol/handshake.rb +306 -305
- data/lib/rubydb/protocol/message.rb +121 -121
- data/lib/rubydb/protocol/parameter_binder.rb +101 -0
- data/lib/rubydb/protocol/protocol.rb +276 -277
- data/lib/rubydb/protocol/version.rb +54 -54
- data/lib/rubydb/rails/adapter.rb +245 -239
- data/lib/rubydb/rails/connection.rb +312 -314
- data/lib/rubydb/rails/database_statements.rb +122 -122
- data/lib/rubydb/rails/migration.rb +131 -131
- data/lib/rubydb/rails/quoting.rb +109 -109
- data/lib/rubydb/rails/result.rb +117 -117
- data/lib/rubydb/rails/schema_statements.rb +339 -339
- data/lib/rubydb/rails/transaction.rb +105 -105
- data/lib/rubydb/rails/type.rb +126 -126
- data/lib/rubydb/recovery/checkpoint.rb +261 -257
- data/lib/rubydb/recovery/consistency.rb +457 -467
- data/lib/rubydb/recovery/corruption_detector.rb +5 -5
- data/lib/rubydb/recovery/crash_recovery.rb +381 -387
- data/lib/rubydb/recovery/recovery_manager.rb +204 -206
- data/lib/rubydb/recovery/redo.rb +235 -237
- data/lib/rubydb/recovery/undo.rb +204 -206
- data/lib/rubydb/replication/failover.rb +5 -5
- data/lib/rubydb/replication/fencing.rb +63 -63
- data/lib/rubydb/replication/primary.rb +461 -450
- data/lib/rubydb/replication/replica.rb +382 -384
- data/lib/rubydb/replication/replication_log.rb +194 -200
- data/lib/rubydb/replication/replication_manager.rb +307 -308
- data/lib/rubydb/replication/replication_slot.rb +293 -295
- data/lib/rubydb/replication/replication_stream.rb +198 -201
- data/lib/rubydb/rubydb.rb +570 -560
- data/lib/rubydb/security/access_control.rb +252 -254
- data/lib/rubydb/security/audit_log.rb +209 -213
- data/lib/rubydb/security/authentication.rb +302 -302
- data/lib/rubydb/security/authorization.rb +282 -282
- data/lib/rubydb/security/credentials.rb +192 -196
- data/lib/rubydb/security/password.rb +205 -215
- data/lib/rubydb/security/permissions.rb +74 -74
- data/lib/rubydb/security/role.rb +99 -101
- data/lib/rubydb/security/user.rb +86 -86
- data/lib/rubydb/server/connection.rb +383 -366
- data/lib/rubydb/server/connection_pool.rb +193 -193
- data/lib/rubydb/server/lifecycle.rb +227 -228
- data/lib/rubydb/server/listener.rb +139 -136
- data/lib/rubydb/server/request_handler.rb +277 -276
- data/lib/rubydb/server/server.rb +363 -364
- data/lib/rubydb/server/session.rb +416 -369
- data/lib/rubydb/server/worker.rb +206 -210
- data/lib/rubydb/server/worker_pool.rb +168 -168
- data/lib/rubydb/sql/ast/alter_table.rb +169 -169
- data/lib/rubydb/sql/ast/begin_transaction.rb +47 -47
- data/lib/rubydb/sql/ast/commit.rb +37 -37
- data/lib/rubydb/sql/ast/constraint.rb +92 -83
- data/lib/rubydb/sql/ast/create_database.rb +41 -41
- data/lib/rubydb/sql/ast/create_index.rb +61 -61
- data/lib/rubydb/sql/ast/create_schema.rb +52 -52
- data/lib/rubydb/sql/ast/create_table.rb +187 -187
- data/lib/rubydb/sql/ast/delete.rb +54 -54
- data/lib/rubydb/sql/ast/drop_database.rb +41 -41
- data/lib/rubydb/sql/ast/drop_index.rb +41 -41
- data/lib/rubydb/sql/ast/drop_schema.rb +49 -49
- data/lib/rubydb/sql/ast/drop_table.rb +49 -49
- data/lib/rubydb/sql/ast/explain.rb +64 -64
- data/lib/rubydb/sql/ast/expression.rb +617 -604
- data/lib/rubydb/sql/ast/insert.rb +66 -66
- data/lib/rubydb/sql/ast/node.rb +42 -42
- data/lib/rubydb/sql/ast/rollback.rb +63 -63
- data/lib/rubydb/sql/ast/savepoint.rb +59 -59
- data/lib/rubydb/sql/ast/select.rb +88 -88
- data/lib/rubydb/sql/ast/set_operation.rb +22 -20
- data/lib/rubydb/sql/ast/trigger.rb +35 -29
- data/lib/rubydb/sql/ast/update.rb +88 -88
- data/lib/rubydb/sql/ast/vacuum.rb +19 -19
- data/lib/rubydb/sql/ast/view.rb +38 -32
- data/lib/rubydb/sql/ast/with.rb +32 -32
- data/lib/rubydb/sql/grammar.rb +86 -86
- data/lib/rubydb/sql/keywords.rb +156 -156
- data/lib/rubydb/sql/lexer.rb +209 -214
- data/lib/rubydb/sql/operators.rb +100 -100
- data/lib/rubydb/sql/parser.rb +1167 -1170
- data/lib/rubydb/sql/planner/analyzer.rb +283 -302
- data/lib/rubydb/sql/planner/binder.rb +537 -550
- data/lib/rubydb/sql/planner/type_checker.rb +427 -431
- data/lib/rubydb/sql/token.rb +210 -210
- data/lib/rubydb/storage/buffer_frame.rb +44 -44
- data/lib/rubydb/storage/buffer_pool.rb +155 -155
- data/lib/rubydb/storage/database_lock.rb +74 -74
- data/lib/rubydb/storage/deserializer.rb +332 -342
- data/lib/rubydb/storage/engine.rb +2409 -2330
- data/lib/rubydb/storage/file_manager.rb +191 -187
- data/lib/rubydb/storage/free_space_map.rb +79 -81
- data/lib/rubydb/storage/page.rb +92 -94
- data/lib/rubydb/storage/page_allocator.rb +852 -855
- data/lib/rubydb/storage/page_header.rb +63 -67
- data/lib/rubydb/storage/page_manager.rb +127 -131
- data/lib/rubydb/storage/record.rb +58 -58
- data/lib/rubydb/storage/row.rb +78 -78
- data/lib/rubydb/storage/serializer.rb +51 -51
- data/lib/rubydb/storage/snapshot_reader.rb +167 -0
- data/lib/rubydb/storage/storage_layout.rb +151 -151
- data/lib/rubydb/storage/storage_manager.rb +114 -114
- data/lib/rubydb/storage/tuple.rb +458 -461
- data/lib/rubydb/storage/visibility_map.rb +964 -973
- data/lib/rubydb/transactions/commit_manager.rb +219 -220
- data/lib/rubydb/transactions/isolation.rb +98 -98
- data/lib/rubydb/transactions/lock.rb +76 -76
- data/lib/rubydb/transactions/lock_manager.rb +359 -362
- data/lib/rubydb/transactions/savepoint.rb +142 -143
- data/lib/rubydb/transactions/transaction.rb +214 -215
- data/lib/rubydb/transactions/transaction_id.rb +84 -84
- data/lib/rubydb/transactions/transaction_log.rb +256 -257
- data/lib/rubydb/transactions/transaction_manager.rb +434 -435
- data/lib/rubydb/types/bigint.rb +36 -36
- data/lib/rubydb/types/blob.rb +37 -37
- data/lib/rubydb/types/boolean.rb +34 -34
- data/lib/rubydb/types/date.rb +39 -39
- data/lib/rubydb/types/decimal.rb +48 -48
- data/lib/rubydb/types/float.rb +34 -34
- data/lib/rubydb/types/integer.rb +36 -36
- data/lib/rubydb/types/json.rb +41 -41
- data/lib/rubydb/types/null.rb +34 -34
- data/lib/rubydb/types/smallint.rb +36 -36
- data/lib/rubydb/types/text.rb +37 -37
- data/lib/rubydb/types/time.rb +46 -46
- data/lib/rubydb/types/timestamp.rb +39 -39
- data/lib/rubydb/types/type.rb +119 -119
- data/lib/rubydb/types/uuid.rb +47 -47
- data/lib/rubydb/types/varchar.rb +37 -37
- data/lib/rubydb/version.rb +32 -32
- data/lib/rubydb/wal/archive.rb +207 -193
- data/lib/rubydb/wal/checkpoint.rb +181 -183
- data/lib/rubydb/wal/lsn.rb +94 -94
- data/lib/rubydb/wal/reader.rb +259 -260
- data/lib/rubydb/wal/record.rb +105 -105
- data/lib/rubydb/wal/segment.rb +193 -193
- data/lib/rubydb/wal/wal.rb +481 -452
- data/lib/rubydb/wal/writer.rb +236 -236
- data/lib/rubydb.rb +7 -7
- data/packaging/docker/docker-compose.failover.yml +43 -43
- data/packaging/homebrew/rubydb.rb +19 -19
- data/rubydb.gemspec +70 -57
- data/scripts/benchmark +7 -7
- data/scripts/build_accelerator +49 -0
- data/scripts/durability_drill +37 -37
- data/scripts/fuzz +63 -63
- data/scripts/release +77 -42
- data/scripts/release_check +43 -43
- data/scripts/replication_failover_drill +268 -250
- data/scripts/replication_network_failover_drill +287 -255
- data/scripts/restore_drill +45 -45
- data/scripts/security +45 -0
- metadata +102 -1
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
# Ruby + Go accelerator
|
|
2
|
+
|
|
3
|
+
RubyDB installs as one Ruby package. Release gems include CGO-free Go
|
|
4
|
+
executables for Windows amd64/arm64, Linux amd64/arm64, and macOS amd64/arm64. A
|
|
5
|
+
developer needs Go only when building RubyDB itself or publishing a release;
|
|
6
|
+
an application developer or production operator does not need Go installed.
|
|
7
|
+
|
|
8
|
+
Ruby remains the database authority. It owns SQL meaning, physical-plan
|
|
9
|
+
selection, transactions, MVCC visibility, locks, schema and constraints,
|
|
10
|
+
permissions, WAL, recovery, and every commit decision. Go receives immutable
|
|
11
|
+
read batches and returns data; it never writes database pages or decides what
|
|
12
|
+
is committed.
|
|
13
|
+
|
|
14
|
+
## Runtime boundary
|
|
15
|
+
|
|
16
|
+
The Ruby process starts one long-lived private worker over stdin/stdout. The
|
|
17
|
+
worker does not listen on a TCP port and is not reachable by application
|
|
18
|
+
clients.
|
|
19
|
+
|
|
20
|
+
```text
|
|
21
|
+
application -> RubyDB parser/planner -> Ruby transaction and visibility checks
|
|
22
|
+
\-> Go binary read worker
|
|
23
|
+
Ruby storage/WAL/MVCC/commit <--------- Ruby remains authoritative
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
The Go source is deliberately split by responsibility:
|
|
27
|
+
|
|
28
|
+
```text
|
|
29
|
+
accelerator/cmd/rubydb-accelerator/main.go process entrypoint only
|
|
30
|
+
accelerator/internal/runtime/ request loop and dispatch
|
|
31
|
+
accelerator/internal/protocol/ bounded frames and columnar batches
|
|
32
|
+
accelerator/internal/execution/ filters, sorting, aggregates, joins
|
|
33
|
+
accelerator/internal/storage/ immutable snapshot page reads
|
|
34
|
+
accelerator/internal/wal/ checksums, compression, record batches
|
|
35
|
+
accelerator/internal/parallel/ bounded queues and worker scheduling
|
|
36
|
+
accelerator/internal/memory/ reusable arena and byte buffers
|
|
37
|
+
accelerator/internal/metrics/ operation counts and p95 timings
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Each package has focused tests. The storage reader accepts only a page size,
|
|
41
|
+
page list, and an immutable snapshot contract supplied by RubyDB; it does not
|
|
42
|
+
open the catalog, WAL, or mutable page state by itself. This boundary is
|
|
43
|
+
intentional: adding more Go code must not silently create a second transaction
|
|
44
|
+
or recovery authority.
|
|
45
|
+
|
|
46
|
+
Control messages use bounded JSON-lines. Large row operations use a versioned
|
|
47
|
+
`RDBB` binary frame with a columnar batch: column names are sent once and
|
|
48
|
+
values use typed, length-prefixed fields for NULL, booleans, integers, floats,
|
|
49
|
+
strings, bytes, and JSON fallback values. Responses contain bounded metadata
|
|
50
|
+
and one or more columnar result batches. This removes the old JSON/base64 row
|
|
51
|
+
copy from the hot path while retaining a simple control protocol.
|
|
52
|
+
|
|
53
|
+
Every frame has a request ID, protocol/version fields, a maximum size, and a
|
|
54
|
+
structured error status. Startup verifies the binary against `SHA256SUMS`.
|
|
55
|
+
Timeout, EOF, protocol mismatch, checksum failure, malformed data, or worker
|
|
56
|
+
exit stops that worker. In `auto`, Ruby retries the operation on the Ruby
|
|
57
|
+
executor; in `required`, the error is surfaced to the caller.
|
|
58
|
+
|
|
59
|
+
## Accelerated work
|
|
60
|
+
|
|
61
|
+
The current safe physical operators are:
|
|
62
|
+
|
|
63
|
+
- immutable snapshot page and record decoding for eligible read-only scans;
|
|
64
|
+
- immutable B-tree entry filtering for eligible indexed scans;
|
|
65
|
+
- columnar serialization and deserialization;
|
|
66
|
+
- deterministic parallel filtering for large batches;
|
|
67
|
+
- filtering, projection, ordering, DISTINCT, and NULL-aware comparisons;
|
|
68
|
+
- grouped `COUNT`, `SUM`, `AVG`, `MIN`, and `MAX`;
|
|
69
|
+
- validated inner hash and merge joins;
|
|
70
|
+
- portable `ROW_NUMBER`, `RANK`, `DENSE_RANK`, `LAG`, `LEAD`, and aggregate window operations;
|
|
71
|
+
- SHA-256 checksums; and
|
|
72
|
+
- gzip archive compression/decompression;
|
|
73
|
+
- versioned WAL batch encoding, checksums, and optional compression; and
|
|
74
|
+
- request-scoped cancellation, multiplexed requests, and bounded JSON result batches.
|
|
75
|
+
|
|
76
|
+
WAL acceleration is deliberately a preparation boundary: Ruby assigns the
|
|
77
|
+
transaction ID, LSN, commit order, and commit decision. Go returns an encoded
|
|
78
|
+
and checksummed batch; Ruby is still responsible for writing the approved
|
|
79
|
+
bytes, calling `fsync`, and publishing the durable acknowledgement. A failed
|
|
80
|
+
or uncertain acknowledgement must remain a Ruby recovery error.
|
|
81
|
+
|
|
82
|
+
The SQL executor delegates only plans it can describe with simple identifiers,
|
|
83
|
+
literal predicates, and an eligible immutable read snapshot. Outer joins,
|
|
84
|
+
complex expressions, writes, active transactions, and visibility-sensitive
|
|
85
|
+
work stay in Ruby. The general row pipeline can also receive explicit
|
|
86
|
+
projection, DISTINCT, HAVING, window, and merge-join specifications when the
|
|
87
|
+
Ruby planner has already validated their semantics. Ruby applies every stage
|
|
88
|
+
that was not delegated and remains the result authority through differential
|
|
89
|
+
validation.
|
|
90
|
+
|
|
91
|
+
### Immutable snapshot contract
|
|
92
|
+
|
|
93
|
+
Before a snapshot scan Ruby flushes dirty pages, visibility metadata, and the
|
|
94
|
+
table catalog while holding the engine lock. The default direct path records
|
|
95
|
+
the page size/count, table page lists, schema, B-tree entries, and visibility
|
|
96
|
+
exclusions in a manifest, then lets Go read the already-flushed database file
|
|
97
|
+
while that lock remains held. This avoids copying and hashing the complete
|
|
98
|
+
database for every read. `RUBYDB_ACCELERATOR_DIRECT_SNAPSHOT=off` (or
|
|
99
|
+
`accelerator.direct_snapshot: false`) selects the detached fallback: Ruby
|
|
100
|
+
copies the database to a short-lived private snapshot, records a SHA-256
|
|
101
|
+
digest, and removes the copy after the request. Go verifies the file size,
|
|
102
|
+
optional digest, page headers, record bounds, record flags, column count, and
|
|
103
|
+
type lengths before returning rows.
|
|
104
|
+
|
|
105
|
+
This path is intentionally conservative. Ruby declines it while the current
|
|
106
|
+
thread has a transaction or any transaction is active. Go does not read WAL,
|
|
107
|
+
catalog files, live indexes, or MVCC state and cannot publish writes. If a
|
|
108
|
+
manifest, page, index entry, type, or result is invalid, `auto` falls back to
|
|
109
|
+
the Ruby executor and `required` reports the error. The B-tree data is a
|
|
110
|
+
consistent in-memory index snapshot because RubyDB rebuilds its indexes from
|
|
111
|
+
metadata on open; it is not a new persisted index format.
|
|
112
|
+
|
|
113
|
+
## Automatic selection
|
|
114
|
+
|
|
115
|
+
The default is:
|
|
116
|
+
|
|
117
|
+
```yaml
|
|
118
|
+
accelerator:
|
|
119
|
+
mode: auto
|
|
120
|
+
read_pipeline: on
|
|
121
|
+
direct_snapshot: true
|
|
122
|
+
min_rows: 256
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
For each eligible snapshot scan, the first automatic operation is differentially
|
|
126
|
+
checked against the Ruby implementation and timed. The result is recorded for
|
|
127
|
+
both the physical snapshot scan and the row-batch scan family. Aggregate and
|
|
128
|
+
join operations retain their own differential checks and timing. Utility
|
|
129
|
+
operations record checksum, compression, and WAL-batch samples as well.
|
|
130
|
+
`auto` keeps the Go operator only when it is faster and equivalent; otherwise
|
|
131
|
+
that family falls back to Ruby for the lifetime of the worker. This avoids
|
|
132
|
+
turning IPC overhead into a regression for small or already-optimized queries.
|
|
133
|
+
The decision is process-local and is reset on restart, so it must be validated
|
|
134
|
+
again after a deployment change.
|
|
135
|
+
|
|
136
|
+
`mode: required` bypasses the speed decision and is intended for accelerator
|
|
137
|
+
CI, release smoke tests, and deployments whose workload benchmark has already
|
|
138
|
+
established a win. `mode: off` disables the worker entirely.
|
|
139
|
+
|
|
140
|
+
```sh
|
|
141
|
+
RUBYDB_ACCELERATOR=off rubydb doctor
|
|
142
|
+
RUBYDB_ACCELERATOR=required rubydb accelerator --ping --json
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
The runtime reports capabilities, selected mode, checksum-verified binary,
|
|
146
|
+
calibration decisions, and the last worker error in `rubydb accelerator
|
|
147
|
+
--ping --json` and database statistics.
|
|
148
|
+
|
|
149
|
+
## Building and packaging
|
|
150
|
+
|
|
151
|
+
Release builds are cross-compiled with CGO disabled:
|
|
152
|
+
|
|
153
|
+
```sh
|
|
154
|
+
ruby scripts/build_accelerator
|
|
155
|
+
RUBYDB_ACCELERATOR_TARGETS=current ruby scripts/build_accelerator
|
|
156
|
+
bundle exec rake build:checksum
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
The gemspec packages the Ruby bridge, source module, six supported binaries,
|
|
160
|
+
and the checksum manifest. A release preflight must run Go tests, Ruby
|
|
161
|
+
accelerator tests, checksum verification, the extracted-gem handshake, and a
|
|
162
|
+
representative workload benchmark before publishing.
|
|
163
|
+
|
|
164
|
+
## Performance policy
|
|
165
|
+
|
|
166
|
+
Go is intended to improve workloads dominated by scans, joins, aggregation,
|
|
167
|
+
serialization, compression, or checksum work. It cannot promise that every
|
|
168
|
+
query becomes seconds instead of minutes: indexes, disk latency, query shape,
|
|
169
|
+
lock contention, and result size may dominate. The benchmark harness should
|
|
170
|
+
report p50/p95/p99 latency, throughput, rows/sec, an RSS snapshot where the
|
|
171
|
+
platform exposes it, worker/fallback metrics, and WAL-batch timing. CPU,
|
|
172
|
+
process restarts, and host-level memory should be collected by the deployment
|
|
173
|
+
monitor because those metrics are platform-specific. A speed claim is valid
|
|
174
|
+
only for the measured workload and platform.
|
|
175
|
+
|
|
176
|
+
Future shared immutable page snapshots and broader index/parallel operators
|
|
177
|
+
must preserve the same contract: Go may read a versioned snapshot, but it may
|
|
178
|
+
never mutate pages, indexes, catalog files, WAL, transaction state, or
|
|
179
|
+
visibility state.
|
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
# Indexes
|
|
2
|
-
|
|
3
|
-
RubyDB provides B-tree indexes for supported table columns, including unique
|
|
4
|
-
indexes. The executor can use indexes for eligible lookups while preserving
|
|
5
|
-
correctness through table visibility and transaction rules.
|
|
6
|
-
|
|
7
|
-
Index metadata is persisted with the catalog. Index creation, DML maintenance,
|
|
8
|
-
rollback, deep splits, reopen, and failure handling must remain consistent. If
|
|
9
|
-
index recovery fails, startup must fail visibly; never silently rebuild or claim
|
|
10
|
-
an index is healthy without verification.
|
|
11
|
-
|
|
12
|
-
## Change checklist
|
|
13
|
-
|
|
14
|
-
Index changes require coverage for empty and populated tables, duplicate and
|
|
15
|
-
null keys, deep splits, deletes, rollback, crash/replay, compaction, and
|
|
16
|
-
concurrent readers. Compare an index lookup with a table scan before and after
|
|
17
|
-
reopen. A required-index persistence error must abort the owning operation and
|
|
18
|
-
be observable by the caller. See [troubleshooting](../troubleshooting.md) for
|
|
19
|
-
the safe response to suspected index corruption.
|
|
1
|
+
# Indexes
|
|
2
|
+
|
|
3
|
+
RubyDB provides B-tree indexes for supported table columns, including unique
|
|
4
|
+
indexes. The executor can use indexes for eligible lookups while preserving
|
|
5
|
+
correctness through table visibility and transaction rules.
|
|
6
|
+
|
|
7
|
+
Index metadata is persisted with the catalog. Index creation, DML maintenance,
|
|
8
|
+
rollback, deep splits, reopen, and failure handling must remain consistent. If
|
|
9
|
+
index recovery fails, startup must fail visibly; never silently rebuild or claim
|
|
10
|
+
an index is healthy without verification.
|
|
11
|
+
|
|
12
|
+
## Change checklist
|
|
13
|
+
|
|
14
|
+
Index changes require coverage for empty and populated tables, duplicate and
|
|
15
|
+
null keys, deep splits, deletes, rollback, crash/replay, compaction, and
|
|
16
|
+
concurrent readers. Compare an index lookup with a table scan before and after
|
|
17
|
+
reopen. A required-index persistence error must abort the owning operation and
|
|
18
|
+
be observable by the caller. See [troubleshooting](../troubleshooting.md) for
|
|
19
|
+
the safe response to suspected index corruption.
|
data/docs/architecture/mvcc.md
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
# MVCC support status
|
|
2
|
-
|
|
3
|
-
RubyDB currently provides safe READ COMMITTED behavior for the storage engine.
|
|
4
|
-
Uncommitted row versions are visible to their owning transaction and hidden
|
|
5
|
-
from other transactions. Committed versions become visible after the durable
|
|
6
|
-
COMMIT WAL record is written. Deleted physical records remain on pages until
|
|
7
|
-
vacuum/compaction and are excluded from ordinary scans.
|
|
8
|
-
|
|
9
|
-
REPEATABLE READ uses persisted historical row versions and transaction
|
|
10
|
-
snapshots. SERIALIZABLE uses snapshot validation over tracked row read/write
|
|
11
|
-
keys and conservative table predicates. A newer committed version intersecting
|
|
12
|
-
the dependency set aborts commit with a serialization failure. Table-level
|
|
13
|
-
predicate tracking prevents phantoms at the cost of false-positive conflicts;
|
|
14
|
-
exact index-range predicate locking is a future optimization.
|
|
15
|
-
|
|
16
|
-
The version store is persisted atomically and supports safe-point vacuuming.
|
|
17
|
-
Vacuum never removes active versions and retains the newest committed base
|
|
18
|
-
version needed by an active reader; older committed history is removable only
|
|
19
|
-
when its commit ID precedes the oldest active transaction.
|
|
1
|
+
# MVCC support status
|
|
2
|
+
|
|
3
|
+
RubyDB currently provides safe READ COMMITTED behavior for the storage engine.
|
|
4
|
+
Uncommitted row versions are visible to their owning transaction and hidden
|
|
5
|
+
from other transactions. Committed versions become visible after the durable
|
|
6
|
+
COMMIT WAL record is written. Deleted physical records remain on pages until
|
|
7
|
+
vacuum/compaction and are excluded from ordinary scans.
|
|
8
|
+
|
|
9
|
+
REPEATABLE READ uses persisted historical row versions and transaction
|
|
10
|
+
snapshots. SERIALIZABLE uses snapshot validation over tracked row read/write
|
|
11
|
+
keys and conservative table predicates. A newer committed version intersecting
|
|
12
|
+
the dependency set aborts commit with a serialization failure. Table-level
|
|
13
|
+
predicate tracking prevents phantoms at the cost of false-positive conflicts;
|
|
14
|
+
exact index-range predicate locking is a future optimization.
|
|
15
|
+
|
|
16
|
+
The version store is persisted atomically and supports safe-point vacuuming.
|
|
17
|
+
Vacuum never removes active versions and retains the newest committed base
|
|
18
|
+
version needed by an active reader; older committed history is removable only
|
|
19
|
+
when its commit ID precedes the oldest active transaction.
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
# Architecture overview
|
|
2
|
-
|
|
3
|
-
RubyDB separates logical query processing from durable state changes. SQL is
|
|
4
|
-
lexed into tokens, parsed into an AST, bound against catalog metadata, planned,
|
|
5
|
-
and executed against the storage engine. DML is coordinated with transactions
|
|
6
|
-
and WAL before durable acknowledgement.
|
|
7
|
-
|
|
8
|
-
The catalog defines tables, columns, constraints, views, and indexes. The page
|
|
9
|
-
manager and buffer pool provide durable storage. Recovery replays valid WAL and
|
|
10
|
-
rejects malformed or uncertain state. Server/client mode isolates application
|
|
11
|
-
processes from the exclusive embedded owner.
|
|
12
|
-
|
|
13
|
-
Read the [current-state audit](current-state.md) before relying on any feature.
|
|
1
|
+
# Architecture overview
|
|
2
|
+
|
|
3
|
+
RubyDB separates logical query processing from durable state changes. SQL is
|
|
4
|
+
lexed into tokens, parsed into an AST, bound against catalog metadata, planned,
|
|
5
|
+
and executed against the storage engine. DML is coordinated with transactions
|
|
6
|
+
and WAL before durable acknowledgement.
|
|
7
|
+
|
|
8
|
+
The catalog defines tables, columns, constraints, views, and indexes. The page
|
|
9
|
+
manager and buffer pool provide durable storage. Recovery replays valid WAL and
|
|
10
|
+
rejects malformed or uncertain state. Server/client mode isolates application
|
|
11
|
+
processes from the exclusive embedded owner.
|
|
12
|
+
|
|
13
|
+
Read the [current-state audit](current-state.md) before relying on any feature.
|
data/docs/architecture/pages.md
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
# Pages and file layout
|
|
2
|
-
|
|
3
|
-
RubyDB stores fixed-size pages containing validated headers, checksums, and
|
|
4
|
-
typed records. Page allocation, metadata, table data, and index pages are
|
|
5
|
-
managed by the storage layer; callers must not edit database files directly.
|
|
6
|
-
|
|
7
|
-
The page format is versioned. Unknown formats, invalid page sizes, malformed
|
|
8
|
-
headers, and checksum failures fail closed during open or recovery. Keep the
|
|
9
|
-
database, WAL, catalog metadata, and lock files together when copying or
|
|
10
|
-
restoring a database. See [storage format](../../spec/storage/format.md) and
|
|
11
|
-
[upgrade guidance](../operations/upgrades.md).
|
|
1
|
+
# Pages and file layout
|
|
2
|
+
|
|
3
|
+
RubyDB stores fixed-size pages containing validated headers, checksums, and
|
|
4
|
+
typed records. Page allocation, metadata, table data, and index pages are
|
|
5
|
+
managed by the storage layer; callers must not edit database files directly.
|
|
6
|
+
|
|
7
|
+
The page format is versioned. Unknown formats, invalid page sizes, malformed
|
|
8
|
+
headers, and checksum failures fail closed during open or recovery. Keep the
|
|
9
|
+
database, WAL, catalog metadata, and lock files together when copying or
|
|
10
|
+
restoring a database. See [storage format](../../spec/storage/format.md) and
|
|
11
|
+
[upgrade guidance](../operations/upgrades.md).
|
|
@@ -1,82 +1,82 @@
|
|
|
1
|
-
# RubyDB production roadmap
|
|
2
|
-
|
|
3
|
-
## Current baseline
|
|
4
|
-
|
|
5
|
-
The project has a meaningful repository skeleton and substantial design intent. It already includes modules for storage, indexing, transactions, MVCC, SQL parts, server, replication, and backup flows. However, the implementation still lacks enough end-to-end proof for durable, crash-safe operation.
|
|
6
|
-
|
|
7
|
-
## Prioritized roadmap
|
|
8
|
-
|
|
9
|
-
### Phase 0 — Repository stabilization
|
|
10
|
-
|
|
11
|
-
- fix library loading and Ruby compatibility metadata
|
|
12
|
-
- verify the project loads via `require "rubydb"`
|
|
13
|
-
- establish a truthful project health baseline
|
|
14
|
-
- add characterization tests for current public behavior
|
|
15
|
-
|
|
16
|
-
### Phase 1 — Storage durability
|
|
17
|
-
|
|
18
|
-
- define a stable on-disk page format and file format
|
|
19
|
-
- add checksums, header validation, and corruption detection
|
|
20
|
-
- ensure WAL durability precedes page flush semantics
|
|
21
|
-
- add real restart tests and crash tests
|
|
22
|
-
|
|
23
|
-
### Phase 2 — Transaction correctness
|
|
24
|
-
|
|
25
|
-
- complete transaction lifecycle handling
|
|
26
|
-
- prove commit/rollback semantics under restart
|
|
27
|
-
- validate isolation semantics and visibility rules
|
|
28
|
-
- add deadlock and lock manager tests
|
|
29
|
-
|
|
30
|
-
### Phase 3 — Catalog and indexes
|
|
31
|
-
|
|
32
|
-
- persist catalog metadata consistently
|
|
33
|
-
- maintain indexes correctly during DML
|
|
34
|
-
- verify index consistency after crash and rollback
|
|
35
|
-
- document supported SQL compatibility targets honestly
|
|
36
|
-
|
|
37
|
-
### Phase 4 — SQL execution and optimizer
|
|
38
|
-
|
|
39
|
-
- validate end-to-end SQL execution
|
|
40
|
-
- ensure binder, planner, and executor are integrated
|
|
41
|
-
- add integration tests for basic DML and queries
|
|
42
|
-
- implement `EXPLAIN` only with real, honest plan output
|
|
43
|
-
|
|
44
|
-
### Phase 5 — Server and security
|
|
45
|
-
|
|
46
|
-
- harden server lifecycle and malformed-client handling
|
|
47
|
-
- enforce connection limits and timeouts
|
|
48
|
-
- check authorization before execution
|
|
49
|
-
- validate auth flows and access controls
|
|
50
|
-
|
|
51
|
-
### Phase 6 — Backup, recovery, and replication
|
|
52
|
-
|
|
53
|
-
- prove full backup + restore works from a clean environment
|
|
54
|
-
- validate point-in-time or incremental recovery only when implemented correctly
|
|
55
|
-
- only add replication once WAL recovery is demonstrably correct
|
|
56
|
-
|
|
57
|
-
### Phase 7 — Monitoring and production readiness
|
|
58
|
-
|
|
59
|
-
- add structured logging and health/readiness checks
|
|
60
|
-
- expose operational metrics
|
|
61
|
-
- create a final production-readiness audit with limitations and unsupported features
|
|
62
|
-
|
|
63
|
-
## Hard gates before declaring production readiness
|
|
64
|
-
|
|
65
|
-
RubyDB should not claim production readiness until it demonstrates all of the following:
|
|
66
|
-
|
|
67
|
-
- updated data survives restart
|
|
68
|
-
- crash recovery is validated with subprocess termination tests
|
|
69
|
-
- transactions preserve isolation semantics
|
|
70
|
-
- WAL ordering is durable and replayed correctly
|
|
71
|
-
- index and table data stay consistent
|
|
72
|
-
- authZ/authN is enforced over real operations
|
|
73
|
-
- backup and restore work in a clean environment
|
|
74
|
-
- server operations handle failures safely without whole-process crashes
|
|
75
|
-
|
|
76
|
-
## Decision rule
|
|
77
|
-
|
|
78
|
-
The repository must prefer correctness over feature breadth. A smaller well-tested engine is more valuable than a broad but unsafe one.
|
|
79
|
-
|
|
80
|
-
## Long-term target
|
|
81
|
-
|
|
82
|
-
The final target is not a fake "PostgreSQL clone" or a marketing demo. The target is a Ruby-first, SQLite-like development experience paired with durable, crash-safe relational database semantics that can be validated under real workloads.
|
|
1
|
+
# RubyDB production roadmap
|
|
2
|
+
|
|
3
|
+
## Current baseline
|
|
4
|
+
|
|
5
|
+
The project has a meaningful repository skeleton and substantial design intent. It already includes modules for storage, indexing, transactions, MVCC, SQL parts, server, replication, and backup flows. However, the implementation still lacks enough end-to-end proof for durable, crash-safe operation.
|
|
6
|
+
|
|
7
|
+
## Prioritized roadmap
|
|
8
|
+
|
|
9
|
+
### Phase 0 — Repository stabilization
|
|
10
|
+
|
|
11
|
+
- fix library loading and Ruby compatibility metadata
|
|
12
|
+
- verify the project loads via `require "rubydb"`
|
|
13
|
+
- establish a truthful project health baseline
|
|
14
|
+
- add characterization tests for current public behavior
|
|
15
|
+
|
|
16
|
+
### Phase 1 — Storage durability
|
|
17
|
+
|
|
18
|
+
- define a stable on-disk page format and file format
|
|
19
|
+
- add checksums, header validation, and corruption detection
|
|
20
|
+
- ensure WAL durability precedes page flush semantics
|
|
21
|
+
- add real restart tests and crash tests
|
|
22
|
+
|
|
23
|
+
### Phase 2 — Transaction correctness
|
|
24
|
+
|
|
25
|
+
- complete transaction lifecycle handling
|
|
26
|
+
- prove commit/rollback semantics under restart
|
|
27
|
+
- validate isolation semantics and visibility rules
|
|
28
|
+
- add deadlock and lock manager tests
|
|
29
|
+
|
|
30
|
+
### Phase 3 — Catalog and indexes
|
|
31
|
+
|
|
32
|
+
- persist catalog metadata consistently
|
|
33
|
+
- maintain indexes correctly during DML
|
|
34
|
+
- verify index consistency after crash and rollback
|
|
35
|
+
- document supported SQL compatibility targets honestly
|
|
36
|
+
|
|
37
|
+
### Phase 4 — SQL execution and optimizer
|
|
38
|
+
|
|
39
|
+
- validate end-to-end SQL execution
|
|
40
|
+
- ensure binder, planner, and executor are integrated
|
|
41
|
+
- add integration tests for basic DML and queries
|
|
42
|
+
- implement `EXPLAIN` only with real, honest plan output
|
|
43
|
+
|
|
44
|
+
### Phase 5 — Server and security
|
|
45
|
+
|
|
46
|
+
- harden server lifecycle and malformed-client handling
|
|
47
|
+
- enforce connection limits and timeouts
|
|
48
|
+
- check authorization before execution
|
|
49
|
+
- validate auth flows and access controls
|
|
50
|
+
|
|
51
|
+
### Phase 6 — Backup, recovery, and replication
|
|
52
|
+
|
|
53
|
+
- prove full backup + restore works from a clean environment
|
|
54
|
+
- validate point-in-time or incremental recovery only when implemented correctly
|
|
55
|
+
- only add replication once WAL recovery is demonstrably correct
|
|
56
|
+
|
|
57
|
+
### Phase 7 — Monitoring and production readiness
|
|
58
|
+
|
|
59
|
+
- add structured logging and health/readiness checks
|
|
60
|
+
- expose operational metrics
|
|
61
|
+
- create a final production-readiness audit with limitations and unsupported features
|
|
62
|
+
|
|
63
|
+
## Hard gates before declaring production readiness
|
|
64
|
+
|
|
65
|
+
RubyDB should not claim production readiness until it demonstrates all of the following:
|
|
66
|
+
|
|
67
|
+
- updated data survives restart
|
|
68
|
+
- crash recovery is validated with subprocess termination tests
|
|
69
|
+
- transactions preserve isolation semantics
|
|
70
|
+
- WAL ordering is durable and replayed correctly
|
|
71
|
+
- index and table data stay consistent
|
|
72
|
+
- authZ/authN is enforced over real operations
|
|
73
|
+
- backup and restore work in a clean environment
|
|
74
|
+
- server operations handle failures safely without whole-process crashes
|
|
75
|
+
|
|
76
|
+
## Decision rule
|
|
77
|
+
|
|
78
|
+
The repository must prefer correctness over feature breadth. A smaller well-tested engine is more valuable than a broad but unsafe one.
|
|
79
|
+
|
|
80
|
+
## Long-term target
|
|
81
|
+
|
|
82
|
+
The final target is not a fake "PostgreSQL clone" or a marketing demo. The target is a Ruby-first, SQLite-like development experience paired with durable, crash-safe relational database semantics that can be validated under real workloads.
|
|
@@ -1,20 +1,20 @@
|
|
|
1
|
-
# Query planner
|
|
2
|
-
|
|
3
|
-
The planner binds identifiers to catalog columns, validates expressions, and
|
|
4
|
-
builds executable plans. It supports sequential/index scans, safe inner-join
|
|
5
|
-
reordering, outer joins, filters, grouping, sorting, limits, set operations,
|
|
6
|
-
subqueries, CTEs, and window operations in the documented SQL surface.
|
|
7
|
-
|
|
8
|
-
Plans must preserve SQL null, ordering, grouping, and transaction visibility
|
|
9
|
-
semantics. `EXPLAIN` reports the actual selected plan; it is not a performance
|
|
10
|
-
promise. Use the benchmark and workload harnesses to establish capacity on the
|
|
11
|
-
target hardware.
|
|
12
|
-
|
|
13
|
-
## Plan review
|
|
14
|
-
|
|
15
|
-
For every rewrite, compare the optimized and baseline results on empty,
|
|
16
|
-
duplicate, null, and concurrent data. Include joins with unmatched rows,
|
|
17
|
-
grouping, limits, and repeated execution with bound parameters. Measure plan
|
|
18
|
-
selection, execution, lock wait, and I/O separately. A plan that is faster but
|
|
19
|
-
changes cardinality or ordering is incorrect; add the minimized query as a
|
|
20
|
-
regression spec before merging.
|
|
1
|
+
# Query planner
|
|
2
|
+
|
|
3
|
+
The planner binds identifiers to catalog columns, validates expressions, and
|
|
4
|
+
builds executable plans. It supports sequential/index scans, safe inner-join
|
|
5
|
+
reordering, outer joins, filters, grouping, sorting, limits, set operations,
|
|
6
|
+
subqueries, CTEs, and window operations in the documented SQL surface.
|
|
7
|
+
|
|
8
|
+
Plans must preserve SQL null, ordering, grouping, and transaction visibility
|
|
9
|
+
semantics. `EXPLAIN` reports the actual selected plan; it is not a performance
|
|
10
|
+
promise. Use the benchmark and workload harnesses to establish capacity on the
|
|
11
|
+
target hardware.
|
|
12
|
+
|
|
13
|
+
## Plan review
|
|
14
|
+
|
|
15
|
+
For every rewrite, compare the optimized and baseline results on empty,
|
|
16
|
+
duplicate, null, and concurrent data. Include joins with unmatched rows,
|
|
17
|
+
grouping, limits, and repeated execution with bound parameters. Measure plan
|
|
18
|
+
selection, execution, lock wait, and I/O separately. A plan that is faster but
|
|
19
|
+
changes cardinality or ordering is incorrect; add the minimized query as a
|
|
20
|
+
regression spec before merging.
|
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
# Recovery architecture
|
|
2
|
-
|
|
3
|
-
Recovery validates the database format, page headers, checksums, metadata, and
|
|
4
|
-
WAL before making state available. Valid committed WAL records may be replayed;
|
|
5
|
-
malformed or ambiguous records fail closed and require operator investigation.
|
|
6
|
-
|
|
7
|
-
Recovery procedures work from a preserved source or verified backup. Restore to
|
|
8
|
-
a new directory, run dry-run and checksum checks, reopen the restored engine,
|
|
9
|
-
compare schema/row evidence, and only then switch application traffic. See the
|
|
10
|
-
[disaster recovery](../operations/disaster-recovery.md) procedure.
|
|
11
|
-
|
|
12
|
-
## Failure handling
|
|
13
|
-
|
|
14
|
-
Recovery is allowed to replay only validated, committed records. Truncated
|
|
15
|
-
frames, invalid checksums, impossible LSNs, and incomplete metadata must stop
|
|
16
|
-
startup with an actionable error. Preserve the original directory and WAL;
|
|
17
|
-
repair or compaction experiments belong on a copy. The [debugging playbook](../debugging.md)
|
|
18
|
-
lists the evidence to collect.
|
|
1
|
+
# Recovery architecture
|
|
2
|
+
|
|
3
|
+
Recovery validates the database format, page headers, checksums, metadata, and
|
|
4
|
+
WAL before making state available. Valid committed WAL records may be replayed;
|
|
5
|
+
malformed or ambiguous records fail closed and require operator investigation.
|
|
6
|
+
|
|
7
|
+
Recovery procedures work from a preserved source or verified backup. Restore to
|
|
8
|
+
a new directory, run dry-run and checksum checks, reopen the restored engine,
|
|
9
|
+
compare schema/row evidence, and only then switch application traffic. See the
|
|
10
|
+
[disaster recovery](../operations/disaster-recovery.md) procedure.
|
|
11
|
+
|
|
12
|
+
## Failure handling
|
|
13
|
+
|
|
14
|
+
Recovery is allowed to replay only validated, committed records. Truncated
|
|
15
|
+
frames, invalid checksums, impossible LSNs, and incomplete metadata must stop
|
|
16
|
+
startup with an actionable error. Preserve the original directory and WAL;
|
|
17
|
+
repair or compaction experiments belong on a copy. The [debugging playbook](../debugging.md)
|
|
18
|
+
lists the evidence to collect.
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
# SQL engine
|
|
2
|
-
|
|
3
|
-
RubyDB implements a documented RubyDB SQL subset with a tested common
|
|
4
|
-
SQLite-style application profile. Covered features include CRUD, constraints,
|
|
5
|
-
joins, grouping/aggregates, transactions/savepoints, CTEs, subqueries, set
|
|
6
|
-
operations, upserts, windows, indexes, views, and maintenance statements listed
|
|
7
|
-
in [SQL compatibility](../sql/compatibility.md).
|
|
8
|
-
|
|
9
|
-
This is not complete PostgreSQL, MySQL, or SQLite dialect/file-format
|
|
10
|
-
compatibility. Unsupported syntax must fail explicitly. Applications migrating
|
|
11
|
-
from another engine must run their own schema, query, migration, and error
|
|
12
|
-
behavior suite.
|
|
1
|
+
# SQL engine
|
|
2
|
+
|
|
3
|
+
RubyDB implements a documented RubyDB SQL subset with a tested common
|
|
4
|
+
SQLite-style application profile. Covered features include CRUD, constraints,
|
|
5
|
+
joins, grouping/aggregates, transactions/savepoints, CTEs, subqueries, set
|
|
6
|
+
operations, upserts, windows, indexes, views, and maintenance statements listed
|
|
7
|
+
in [SQL compatibility](../sql/compatibility.md).
|
|
8
|
+
|
|
9
|
+
This is not complete PostgreSQL, MySQL, or SQLite dialect/file-format
|
|
10
|
+
compatibility. Unsupported syntax must fail explicitly. Applications migrating
|
|
11
|
+
from another engine must run their own schema, query, migration, and error
|
|
12
|
+
behavior suite.
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
# Storage engine
|
|
2
|
-
|
|
3
|
-
The storage engine owns the database path, page manager, buffer pool, catalog,
|
|
4
|
-
indexes, WAL, and recovery lifecycle. It serializes durable changes and exposes
|
|
5
|
-
Ruby-native operations used by the SQL executor and adapters.
|
|
6
|
-
|
|
7
|
-
Embedded ownership is exclusive and enforced with an operating-system lock.
|
|
8
|
-
Multiple processes must use the server. On failure, callers should preserve the
|
|
9
|
-
original directory and recover into a new destination; do not delete WAL or
|
|
10
|
-
overwrite the source during investigation.
|
|
11
|
-
|
|
12
|
-
Storage changes require reopen, crash, fault-injection, corruption, compaction,
|
|
13
|
-
and backup/restore coverage. The [lessons learned](../lessons-learned.md) page
|
|
14
|
-
explains why these are separate guarantees.
|
|
1
|
+
# Storage engine
|
|
2
|
+
|
|
3
|
+
The storage engine owns the database path, page manager, buffer pool, catalog,
|
|
4
|
+
indexes, WAL, and recovery lifecycle. It serializes durable changes and exposes
|
|
5
|
+
Ruby-native operations used by the SQL executor and adapters.
|
|
6
|
+
|
|
7
|
+
Embedded ownership is exclusive and enforced with an operating-system lock.
|
|
8
|
+
Multiple processes must use the server. On failure, callers should preserve the
|
|
9
|
+
original directory and recover into a new destination; do not delete WAL or
|
|
10
|
+
overwrite the source during investigation.
|
|
11
|
+
|
|
12
|
+
Storage changes require reopen, crash, fault-injection, corruption, compaction,
|
|
13
|
+
and backup/restore coverage. The [lessons learned](../lessons-learned.md) page
|
|
14
|
+
explains why these are separate guarantees.
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
# Transactions
|
|
2
|
-
|
|
3
|
-
Transactions group mutations into a commit or rollback boundary. WAL commit and
|
|
4
|
-
flush ordering precede durable acknowledgement. MVCC determines visibility,
|
|
5
|
-
while lock management protects conflicting writes and resolves wait-for cycles.
|
|
6
|
-
|
|
7
|
-
Supported controls include `BEGIN`, `COMMIT`, `ROLLBACK`, savepoints, and
|
|
8
|
-
rollback to savepoint. A deadlock victim is rolled back and must retry the whole
|
|
9
|
-
application unit as appropriate. Test isolation and recovery together; a green
|
|
10
|
-
single-thread transaction test does not prove concurrent correctness.
|
|
1
|
+
# Transactions
|
|
2
|
+
|
|
3
|
+
Transactions group mutations into a commit or rollback boundary. WAL commit and
|
|
4
|
+
flush ordering precede durable acknowledgement. MVCC determines visibility,
|
|
5
|
+
while lock management protects conflicting writes and resolves wait-for cycles.
|
|
6
|
+
|
|
7
|
+
Supported controls include `BEGIN`, `COMMIT`, `ROLLBACK`, savepoints, and
|
|
8
|
+
rollback to savepoint. A deadlock victim is rolled back and must retry the whole
|
|
9
|
+
application unit as appropriate. Test isolation and recovery together; a green
|
|
10
|
+
single-thread transaction test does not prove concurrent correctness.
|