Skip to content

fix(db): make db seed work on SQLite - #540

Merged
emoss08 merged 3 commits into
masterfrom
claude/trenova-sqlite-support-4oc8h8
Aug 12, 2026
Merged

fix(db): make db seed work on SQLite#540
emoss08 merged 3 commits into
masterfrom
claude/trenova-sqlite-support-4oc8h8

Conversation

@emoss08

@emoss08 emoss08 commented Aug 12, 2026

Copy link
Copy Markdown
Owner

Description

db seed failed on the first statement under SQLite, because the seed bookkeeping DDL was hardcoded PostgreSQL:

*sqlite.Error: SQL logic error: near "DO": syntax error (1)
Error: seeding failed: failed to initialize tracker: failed to initialize seed tracking table

Fixing that surfaced five more blockers behind it. All six are fixed here and all 25 seeds now apply on SQLite. PostgreSQL behaviour is unchanged throughout.

Related Issue or Discussion

Follow-up to #536. The last blocker is an upstream bun bug, uptrace/bun#1394, with a fix open at uptrace/bun#1412.

Type of Change

  • Bug fix
  • Feature
  • Documentation
  • Refactor
  • Tests
  • Build, CI, or infrastructure

Scope

Seed bookkeeping DDLseeder/schema/{postgres,sqlite}/*.sql, embedded with go:embed and split on --bun:split. The SQL is out of the Go string literals so it stays reviewable and diffable, matching how the migrations are written. Statements run one at a time, which SQLite drivers require and which names the failing statement when one breaks.

Model default tags'{}'::jsonb emitted a :: token SQLite cannot parse. The cast is redundant on PostgreSQL too, since a string literal assignment-casts to jsonb, so it is dropped.

Converter, scripts/dialect-convert/

  • Array columns map to TEXT holding JSON, so the PostgreSQL empty-array literal '{}' has to become '[]'. As an empty JSON object it failed to unmarshal into a Go slice.
  • numeric/decimal map to REAL rather than NUMERIC. NUMERIC affinity demotes integral values to INTEGER, which then refuses to scan into a Go float64. Precision is unchanged either way; SQLite has no exact decimal regardless.
  • DROP COLUMN is emitted again rather than skipped wholesale. Skipping it left columns PostgreSQL had dropped behind as NOT NULL, which broke inserts. SQLite only refuses the drop when an index or constraint still references the column, so the converter tracks emitted indexes and constraint-pinned columns, drops blocking indexes first, and skips only genuinely blocked drops. This raised the translated statement count from 1471 to 1518, all applying cleanly.

Zero-value default tags — bun picks the columns for a bulk insert by looking only at the first element of the slice (uptrace/bun#1394). A notnull column whose first row holds a zero value is dropped from the statement, so every row silently takes the table default instead of its own value. Removing default:0 and default:false from plain scalar fields sidesteps it: bun then writes the actual value. 344 tags across 125 files.

The tag is deliberately kept on the 44 pointer, nullzero and nullable fields such as decimal.NullDecimal. bun writes NULL rather than the zero value there, so the default is load-bearing and removing it violates the notnull constraint — shipments.other_charge_amount is one, and it would have broken PostgreSQL too. Those 44 remain exposed to the upstream bug until #1412 lands.

Validation

  • cd services/tms && task test — passes
  • cd services/tms && task lintnot run. golangci-lint is unavailable in this environment: it is built against Go 1.25 while the module targets Go 1.26 and exits with can't load config. gofmt and go vet are clean over the changed packages.
  • cd client && pnpm build — no client changes
  • cd client && pnpm lint — no client changes
  • Other: python3 scripts/dialect-convert/convert.py sqlite --check — 1518/1518 statements apply, 273 tables
  • Other: go build ./... and go vet ./internal/core/domain/... — clean

Adds TestFullSeedRunOnSQLite, which migrates a throwaway SQLite database and runs the whole seed registry. It is what found every problem above, including a first attempt at the tag sweep that was too broad. Runs in about 7 seconds and needs no Docker.

Deployment Notes

No migrations, config, or env changes for PostgreSQL deployments.

The default-tag removals change generated SQL on PostgreSQL: bun now writes the Go zero value where it previously wrote the column default. For the fields touched those are the same value, which is why the sweep was restricted to plain scalars.

Checklist

  • I kept the change focused and reviewable.
  • I followed AGENTS.md, CLAUDE.md, and existing repository patterns.
  • I added or updated tests for behavior changes, or explained why tests are not applicable.
  • I updated relevant documentation, examples, migrations, or configuration.
  • I did not include secrets, credentials, private customer data, unrelated refactors, or placeholder code.

Generated by Claude Code

claude added 3 commits August 12, 2026 03:09
db seed failed immediately on SQLite because the seed bookkeeping DDL was
hardcoded PostgreSQL. Fixing that surfaced four further blockers, found by
running the whole seed registry against a migrated SQLite database.

Seed bookkeeping DDL now lives in per-dialect .sql files under
seeder/schema/, embedded with go:embed and split on --bun:split, so the SQL
stays reviewable instead of sitting in Go string literals. Statements execute
one at a time, which SQLite drivers require and which names the failing
statement when something breaks.

Model defaults: the jsonb casts in bun default tags ('{}'::jsonb) emitted a
'::' token SQLite cannot parse. The casts are redundant on PostgreSQL too,
since a string literal assignment-casts to jsonb, so they are simply dropped.

Converter fixes:
- Array columns map to TEXT holding JSON, so the PostgreSQL empty-array literal
  '{}' has to become '[]'. As an empty JSON object it failed to unmarshal into
  a Go slice.
- numeric/decimal map to REAL rather than NUMERIC. NUMERIC affinity demotes
  integral values to INTEGER, which then refuses to scan into a Go float64.
  Precision is unchanged; SQLite has no exact decimal either way.
- DROP COLUMN is emitted again instead of being skipped wholesale. Skipping it
  left columns PostgreSQL had dropped behind as NOT NULL, which broke inserts.
  SQLite only refuses the drop when an index or constraint still references the
  column, so the converter now tracks emitted indexes and constraint columns,
  drops blocking indexes first, and skips only genuinely blocked drops.

All 1518 translated statements apply cleanly, up from 1471, and the seed run
reaches 21 of 25 seeds. The remaining blocker is an upstream bun bug, reported
separately.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FXYnxBszfwkNUeeAcVSSNf
bun decides which columns a bulk insert writes by looking only at the first
element of the slice (uptrace/bun#1394). A notnull column whose first row holds
a zero value is dropped from the statement entirely, so every row silently gets
the table default instead of its own value. SQLite hits this on every bulk
insert; Postgres only when the table has an identity column.

Removing default:0 and default:false from plain scalar fields sidesteps it,
because bun then writes the actual value rather than treating zero as "use the
default". The column keeps its database default for inserts that omit it, so
nothing changes on Postgres.

The tag is left alone on pointer, nullzero and nullable fields such as
decimal.NullDecimal. bun writes NULL rather than the zero value there, so the
default is load-bearing and removing it violates the notnull constraint. That
was caught by the seed run, on shipments.other_charge_amount.

Adds a test that migrates a throwaway SQLite database and runs the whole seed
registry, which is what found this and the four dialect problems before it.
All 25 seeds now apply on SQLite.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FXYnxBszfwkNUeeAcVSSNf
@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Too many files!

This PR contains 181 files, which is 81 over the limit of 100.

To get a review, reduce the PR to 100 files or fewer by splitting it into smaller PRs or changing its base branch.

Upgrade to a paid plan to raise the limit.

This review couldn't start because sufficient usage credits or metered capacity aren't available. Add credits or update usage-based reviews in the billing tab, then retry.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 568bdf5f-376d-4caf-9304-5507a5c503bb

📥 Commits

Reviewing files that changed from the base of the PR and between 31f8792 and f0cbb77.

📒 Files selected for processing (181)
  • scripts/dialect-convert/convert.py
  • scripts/dialect-convert/profiles.py
  • services/tms/internal/core/domain/accounttype/accounttype.go
  • services/tms/internal/core/domain/agent/agentexception.go
  • services/tms/internal/core/domain/agent/agentproposal.go
  • services/tms/internal/core/domain/apikey/usage.go
  • services/tms/internal/core/domain/audit/auditentry.go
  • services/tms/internal/core/domain/audit/dlqentry.go
  • services/tms/internal/core/domain/bankreceipt/bankreceipt.go
  • services/tms/internal/core/domain/bankreceiptbatch/bankreceiptbatch.go
  • services/tms/internal/core/domain/bankreceiptworkitem/bankreceiptworkitem.go
  • services/tms/internal/core/domain/billingqueue/billingqueue.go
  • services/tms/internal/core/domain/billingqueuefilterpreset/billingqueuefilterpreset.go
  • services/tms/internal/core/domain/commodity/commodity.go
  • services/tms/internal/core/domain/costingcontrol/category.go
  • services/tms/internal/core/domain/costingcontrol/costingcontrol.go
  • services/tms/internal/core/domain/customer/billingprofile.go
  • services/tms/internal/core/domain/customer/customer.go
  • services/tms/internal/core/domain/customer/emailprofile.go
  • services/tms/internal/core/domain/customerpayment/customerpayment.go
  • services/tms/internal/core/domain/customfield/customfield.go
  • services/tms/internal/core/domain/dedicatedlane/patternconfig.go
  • services/tms/internal/core/domain/detention/evidence.go
  • services/tms/internal/core/domain/detention/notice.go
  • services/tms/internal/core/domain/detention/occurrence.go
  • services/tms/internal/core/domain/detention/policy.go
  • services/tms/internal/core/domain/detention/tier.go
  • services/tms/internal/core/domain/dispatchcontrol/dispatchcontrol.go
  • services/tms/internal/core/domain/distancecalculation/distancecalculationrun.go
  • services/tms/internal/core/domain/distancecontrol/distancecontrol.go
  • services/tms/internal/core/domain/distanceprofile/distanceprofile.go
  • services/tms/internal/core/domain/document/document.go
  • services/tms/internal/core/domain/documentaiextraction/extraction.go
  • services/tms/internal/core/domain/documentcontent/content.go
  • services/tms/internal/core/domain/documentcontent/page.go
  • services/tms/internal/core/domain/documentpacketrule/rule.go
  • services/tms/internal/core/domain/documentparsingrule/model.go
  • services/tms/internal/core/domain/documentshipmentdraft/draft.go
  • services/tms/internal/core/domain/documenttemplate/assignment.go
  • services/tms/internal/core/domain/documenttemplate/generated.go
  • services/tms/internal/core/domain/documenttemplate/template.go
  • services/tms/internal/core/domain/documenttemplate/version.go
  • services/tms/internal/core/domain/documenttype/documenttype.go
  • services/tms/internal/core/domain/documentupload/session.go
  • services/tms/internal/core/domain/driverpay/advance.go
  • services/tms/internal/core/domain/driverpay/assignment.go
  • services/tms/internal/core/domain/driverpay/escrow.go
  • services/tms/internal/core/domain/driverpay/expense.go
  • services/tms/internal/core/domain/driverpay/paycode.go
  • services/tms/internal/core/domain/driverpay/payprofile.go
  • services/tms/internal/core/domain/driverpay/recurringdeduction.go
  • services/tms/internal/core/domain/driverpay/recurringearning.go
  • services/tms/internal/core/domain/driversettlement/batch.go
  • services/tms/internal/core/domain/driversettlement/dispute.go
  • services/tms/internal/core/domain/driversettlement/payevent.go
  • services/tms/internal/core/domain/driversettlement/settlement.go
  • services/tms/internal/core/domain/edi/carrierinvoice.go
  • services/tms/internal/core/domain/edi/communicationprofile.go
  • services/tms/internal/core/domain/edi/connection.go
  • services/tms/internal/core/domain/edi/document.go
  • services/tms/internal/core/domain/edi/documentprofile.go
  • services/tms/internal/core/domain/edi/inbound_file.go
  • services/tms/internal/core/domain/edi/message.go
  • services/tms/internal/core/domain/edi/partner.go
  • services/tms/internal/core/domain/edi/partnersettings.go
  • services/tms/internal/core/domain/edi/sourcecontext.go
  • services/tms/internal/core/domain/edi/sync.go
  • services/tms/internal/core/domain/edi/template.go
  • services/tms/internal/core/domain/edi/tenderchange.go
  • services/tms/internal/core/domain/edi/transactionset.go
  • services/tms/internal/core/domain/edi/transfer.go
  • services/tms/internal/core/domain/email/email.go
  • services/tms/internal/core/domain/email/message.go
  • services/tms/internal/core/domain/exchangerate/exchangerate.go
  • services/tms/internal/core/domain/fiscalperiod/fiscalperiod.go
  • services/tms/internal/core/domain/fiscalyear/fiscalyear.go
  • services/tms/internal/core/domain/fuelsurcharge/price.go
  • services/tms/internal/core/domain/fuelsurcharge/tablerow.go
  • services/tms/internal/core/domain/glaccount/glaccount.go
  • services/tms/internal/core/domain/hazardousmaterial/hazardousmaterial.go
  • services/tms/internal/core/domain/hazmatsegregationrule/hazmatsegregationrule.go
  • services/tms/internal/core/domain/holdreason/holdreason.go
  • services/tms/internal/core/domain/homelayout/preset.go
  • services/tms/internal/core/domain/iam/models.go
  • services/tms/internal/core/domain/integration/integration.go
  • services/tms/internal/core/domain/invoice/invoice.go
  • services/tms/internal/core/domain/invoiceadjustment/batch.go
  • services/tms/internal/core/domain/invoiceadjustment/invoiceadjustment.go
  • services/tms/internal/core/domain/journalreversal/journalreversal.go
  • services/tms/internal/core/domain/location/location.go
  • services/tms/internal/core/domain/locationcategory/locationcategory.go
  • services/tms/internal/core/domain/manualjournal/manualjournal.go
  • services/tms/internal/core/domain/notification/notification.go
  • services/tms/internal/core/domain/permission/role.go
  • services/tms/internal/core/domain/ratetable/entry.go
  • services/tms/internal/core/domain/recurringshipment/recurringshipment.go
  • services/tms/internal/core/domain/report/run.go
  • services/tms/internal/core/domain/report/schedule.go
  • services/tms/internal/core/domain/report/view.go
  • services/tms/internal/core/domain/servicefailure/reason_code.go
  • services/tms/internal/core/domain/servicefailure/service_failure.go
  • services/tms/internal/core/domain/shipment/additionalcharge.go
  • services/tms/internal/core/domain/shipment/comment.go
  • services/tms/internal/core/domain/shipment/hold.go
  • services/tms/internal/core/domain/shipment/shipment.go
  • services/tms/internal/core/domain/shipment/shipmentmove.go
  • services/tms/internal/core/domain/shipment/stop.go
  • services/tms/internal/core/domain/shipmentevent/event.go
  • services/tms/internal/core/domain/shipmentimportchat/chat.go
  • services/tms/internal/core/domain/storedmileage/storedmileage.go
  • services/tms/internal/core/domain/tableconfiguration/tableconfiguration.go
  • services/tms/internal/core/domain/telematics/feedstate.go
  • services/tms/internal/core/domain/telematics/formsubmission.go
  • services/tms/internal/core/domain/telematics/hosstate.go
  • services/tms/internal/core/domain/telematics/hosviolation.go
  • services/tms/internal/core/domain/telematics/vehicleinspection.go
  • services/tms/internal/core/domain/telematics/vehicleposition.go
  • services/tms/internal/core/domain/tenant/accountingcontrol.go
  • services/tms/internal/core/domain/tenant/agentcontrol.go
  • services/tms/internal/core/domain/tenant/billingcontrol.go
  • services/tms/internal/core/domain/tenant/businessunit.go
  • services/tms/internal/core/domain/tenant/dashcontrol.go
  • services/tms/internal/core/domain/tenant/dataretention.go
  • services/tms/internal/core/domain/tenant/documentcontrol.go
  • services/tms/internal/core/domain/tenant/invoiceadjustmentcontrol.go
  • services/tms/internal/core/domain/tenant/settlementcontrol.go
  • services/tms/internal/core/domain/tenant/shipmentcontrol.go
  • services/tms/internal/core/domain/tenant/user.go
  • services/tms/internal/core/domain/weatheralert/weatheralert.go
  • services/tms/internal/core/domain/worker/portalinvitation.go
  • services/tms/internal/core/domain/worker/worker.go
  • services/tms/internal/core/domain/worker/workerprofile.go
  • services/tms/internal/infrastructure/database/seeder/rollback_tracker.go
  • services/tms/internal/infrastructure/database/seeder/schema.go
  • services/tms/internal/infrastructure/database/seeder/schema/postgres/seed_history.sql
  • services/tms/internal/infrastructure/database/seeder/schema/postgres/seed_rollbacks.sql
  • services/tms/internal/infrastructure/database/seeder/schema/sqlite/seed_history.sql
  • services/tms/internal/infrastructure/database/seeder/schema/sqlite/seed_rollbacks.sql
  • services/tms/internal/infrastructure/database/seeder/seedrun_sqlite_test.go
  • services/tms/internal/infrastructure/database/seeder/sqlite_test.go
  • services/tms/internal/infrastructure/database/seeder/tracker.go
  • services/tms/internal/infrastructure/sqlite/migrations/20241211015840_shipment.tx.up.sql
  • services/tms/internal/infrastructure/sqlite/migrations/20241223200800_fleet_code.tx.up.sql
  • services/tms/internal/infrastructure/sqlite/migrations/20250105193652_document_quality.tx.up.sql
  • services/tms/internal/infrastructure/sqlite/migrations/20250118041547_commodity.tx.up.sql
  • services/tms/internal/infrastructure/sqlite/migrations/20250306161153_accessorial_charge.tx.up.sql
  • services/tms/internal/infrastructure/sqlite/migrations/20250323174045_billing_control.tx.up.sql
  • services/tms/internal/infrastructure/sqlite/migrations/20250326012748_additional_charge.tx.up.sql
  • services/tms/internal/infrastructure/sqlite/migrations/20250401131740_customer_billing_profile.tx.up.sql
  • services/tms/internal/infrastructure/sqlite/migrations/20250607200055_dedicated_lane_suggestions.tx.up.sql
  • services/tms/internal/infrastructure/sqlite/migrations/20250608193352_dedicated_lane_config.tx.up.sql
  • services/tms/internal/infrastructure/sqlite/migrations/20250616062950_notification_preferences.tx.up.sql
  • services/tms/internal/infrastructure/sqlite/migrations/20251105034324_add_accounting_control.tx.up.sql
  • services/tms/internal/infrastructure/sqlite/migrations/20260101054529_rbac_v3.tx.up.sql
  • services/tms/internal/infrastructure/sqlite/migrations/20260304190000_drop_sequence_config_static_codes.tx.down.sql
  • services/tms/internal/infrastructure/sqlite/migrations/20260304190000_drop_sequence_config_static_codes.tx.up.sql
  • services/tms/internal/infrastructure/sqlite/migrations/20260326110000_add_document_upload_sessions.tx.up.sql
  • services/tms/internal/infrastructure/sqlite/migrations/20260405120000_add_equipment_type_interior_length.tx.up.sql
  • services/tms/internal/infrastructure/sqlite/migrations/20260407100000_shipment_base_rate.tx.up.sql
  • services/tms/internal/infrastructure/sqlite/migrations/20260407210000_remove_billing_control_prefix_columns.tx.down.sql
  • services/tms/internal/infrastructure/sqlite/migrations/20260407210000_remove_billing_control_prefix_columns.tx.up.sql
  • services/tms/internal/infrastructure/sqlite/migrations/20260408120000_add_invoices.tx.up.sql
  • services/tms/internal/infrastructure/sqlite/migrations/20260408180000_finalize_finance_controls.tx.up.sql
  • services/tms/internal/infrastructure/sqlite/migrations/20260408210000_invoice_adjustment_engine.tx.up.sql
  • services/tms/internal/infrastructure/sqlite/migrations/20260511000000_add_oanda_exchange_rates.tx.up.sql
  • services/tms/internal/infrastructure/sqlite/migrations/20260527130000_replace_legacy_fx_with_oanda.tx.up.sql
  • services/tms/internal/infrastructure/sqlite/migrations/20260531120000_customer_invoice_auto_send_profile.tx.up.sql
  • services/tms/internal/infrastructure/sqlite/migrations/20260709120000_edi_carrier_invoices.tx.up.sql
  • services/tms/internal/infrastructure/sqlite/migrations/20260711120000_drop_edi_partner_validation_profile.tx.down.sql
  • services/tms/internal/infrastructure/sqlite/migrations/20260711120000_drop_edi_partner_validation_profile.tx.up.sql
  • services/tms/internal/infrastructure/sqlite/migrations/20260718010000_formula_rating_features.tx.up.sql
  • services/tms/internal/infrastructure/sqlite/migrations/20260719000000_orders_and_grouped_invoicing.tx.up.sql
  • services/tms/internal/infrastructure/sqlite/migrations/20260720000000_order_charges.tx.up.sql
  • services/tms/internal/infrastructure/sqlite/migrations/20260723000000_fuel_surcharge.tx.up.sql
  • services/tms/internal/infrastructure/sqlite/migrations/20260726000000_costing.tx.up.sql
  • services/tms/internal/infrastructure/sqlite/migrations/20260729000000_driver_settlements.tx.up.sql
  • services/tms/internal/infrastructure/sqlite/migrations/20260802000000_pay_codes.tx.up.sql
  • services/tms/internal/infrastructure/sqlite/migrations/20260808000000_agent_execution.tx.up.sql
  • services/tms/internal/infrastructure/sqlite/migrations/20260830000000_detention_policy.tx.up.sql
  • services/tms/internal/infrastructure/sqlite/migrations/20260831000000_dispatcher_console.tx.up.sql
  • services/tms/internal/infrastructure/sqlite/migrations/20260902000000_document_templates.tx.up.sql

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@cloudflare-workers-and-pages

Copy link
Copy Markdown
Contributor

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Updated (UTC)
❌ Deployment failed
View logs
trenova f0cbb77 Aug 12 2026, 03:39 AM

@emoss08
emoss08 merged commit 85f23dc into master Aug 12, 2026
19 of 21 checks passed
@emoss08
emoss08 deleted the claude/trenova-sqlite-support-4oc8h8 branch August 12, 2026 03:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants