Skip to content

DBX-5320 Optional ref#937

Open
huydo862003 wants to merge 80 commits into
masterfrom
optional-ref-2
Open

DBX-5320 Optional ref#937
huydo862003 wants to merge 80 commits into
masterfrom
optional-ref-2

Conversation

@huydo862003

@huydo862003 huydo862003 commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Summary

BREAKING CHANGE

All "many" endpoints are now "some" (min=1):

  • >: many-to-one -> some-to-one ([1..*]-[1..1])
  • <: one-to-many -> one-to-some ([1..1]-[1..*])
  • <>: many-to-many -> some-to-some ([1..*]-[1..*])
  • -: one-to-one (unchanged)

SQL importers/db connectors will default to optional ref cardinalities & the model_structure layer in @dbml/core will adjust the cardinalities to required if it makes sense

New features

  • Introduces ? modifier for optional (min=0) endpoints:
    • ?>: many-to-one ([0..*]-[1..1])
    • ?-?: maybe-to-maybe ([0..1]-[0..1])
    • etc.

Changes

  • 16 relationship operators (4 base x 4 optionality combinations)
    • RefEndpoint.relation extended from '1' | '*' to
      '1', '*', '0..1', '0..*', etc.
    • Lexer tokenizes ?>?, ?<>? etc. as single OP tokens
  • SQL exporters/importers now respect nullability to generate correct relationship operators.

Issue

(issue link here)

Lasting Changes (Technical)

(please list down: code changes/things that have wide-effect; new libraries/functions added that can be used by others; examples below)

  • (Added class EmailValidator to validate email address' validity)
  • (Added Tenant#is_trial? check)

Checklist

Please check directly on the box once each of these are done

  • Documentation (if necessary)
  • Lint Checks Passed
  • Unit Tests Passed
  • Coverage Tests Passed
  • Integration Tests Passed
  • Code Review

@github-actions

github-actions Bot commented Jul 1, 2026

Copy link
Copy Markdown

Benchmark Result

dbml-parse

suite 🏠 master 🔀 this branch change
18k 1126.166ms ±4.9% 1185.356ms ±3.42% 🔴 +5.3%
25k 1720.88ms ±4.3% 1812.225ms ±6.41% 🔴 +5.3%

@github-actions

github-actions Bot commented Jul 1, 2026

Copy link
Copy Markdown

Coverage Report

Commit: 4a6baf7

Overall Coverage

Metric Coverage
Lines ✅ 84.86% (8870/10452)
Statements ✅ 82.09% (9617/11715)
Functions ✅ 86.98% (1850/2127)
Branches ⚠️ 73.29% (5835/7962)

Package Coverage

Package Lines Statements Functions Branches
dbml-cli ✅ 100.00% ✅ 100.00% ✅ 100.00% ✅ 100.00%
dbml-connector ⚠️ 64.62% ⚠️ 64.36% ⚠️ 59.53% ⚠️ 59.09%
dbml-core N/A N/A N/A N/A
dbml-parse ✅ 86.87% ✅ 83.76% ✅ 89.40% ⚠️ 74.30%

⚠️ Coverage Warnings

The following packages have coverage below 80%:

  • dbml-connector: 64.62% line coverage

Files with Coverage Below 80%

dbml-connector

9 file(s) below 80% coverage
File Lines Statements Functions Branches
src/connectors/bigquery/index.ts 0.00% 0.00% 0.00% 0.00%
src/utils/credential-loader.ts 0.00% 0.00% 0.00% 0.00%
src/utils/helpers.ts 0.00% 0.00% 0.00% 0.00%
src/connectors/snowflake/index.ts 10.56% 10.31% 0.00% 0.00%
src/utils/parseSchema.ts 46.15% 42.85% 28.57% 27.27%
src/connectors/connector.ts 66.66% 66.66% 100.00% 57.14%
src/connectors/oracle/tables.ts 71.25% 67.39% 100.00% 56.96%
src/connectors/oracle/index.ts 80.00% 80.76% 100.00% 25.00%
src/connectors/oracle/utils.ts 85.71% 85.71% 100.00% 71.42%

dbml-parse

83 file(s) below 80% coverage
File Lines Statements Functions Branches
src/compiler/queries/container/scope.ts 0.00% 0.00% 0.00% 0.00%
src/services/code_actions/provider.ts 0.00% 0.00% 0.00% 0.00%
src/services/diagnostics/provider.ts 0.00% 0.00% 0.00% 0.00%
src/compiler/queries/pipeline/interpret.ts 10.52% 12.19% 66.66% 41.66%
src/services/suggestions/crossFile.ts 19.35% 19.44% 33.33% 10.00%
src/core/local_modules/enum/index.ts 48.00% 46.29% 57.14% 52.63%
src/core/global_modules/project/interpret.ts 52.50% 46.66% 83.33% 23.07%
src/compiler/queries/legacy/parse.ts 53.84% 46.66% 50.00% 25.00%
src/compiler/projectLayout/layout.ts 54.16% 53.84% 75.00% 52.63%
src/core/local_modules/ref/index.ts 62.50% 61.76% 100.00% 57.14%
src/core/types/report.ts 62.96% 56.66% 76.92% 57.14%
src/core/global_modules/records/utils/data/values.ts 63.30% 55.71% 72.72% 49.28%
src/core/types/symbol/symbols.ts 64.41% 56.50% 60.80% 48.48%
src/core/local_modules/tableGroup/validate.ts 64.55% 64.44% 71.42% 58.00%
src/compiler/queries/legacy/token.ts 66.66% 66.66% 66.66% 100.00%
src/core/global_modules/enum/bind.ts 66.66% 68.75% 83.33% 50.00%
src/core/local_modules/program/index.ts 66.66% 69.23% 75.00% 62.50%
src/core/global_modules/note/bind.ts 69.23% 71.42% 83.33% 50.00%
src/core/local_modules/checks/index.ts 69.23% 75.00% 100.00% 64.28%
src/core/local_modules/project/index.ts 69.23% 69.23% 100.00% 63.63%
src/core/local_modules/custom/index.ts 70.58% 71.42% 80.00% 68.75%
src/compiler/queries/utils.ts 73.10% 73.38% 90.90% 51.11%
src/core/local_modules/tablePartial/validate.ts 73.12% 71.83% 79.22% 57.67%
src/core/global_modules/project/bind.ts 73.33% 75.00% 100.00% 50.00%
src/core/local_modules/indexes/index.ts 73.68% 69.35% 63.63% 64.28%
src/core/local_modules/use/index.ts 73.91% 75.00% 75.00% 81.25%
src/core/local_modules/indexes/validate.ts 74.28% 74.66% 90.90% 56.00%
src/core/local_modules/note/index.ts 75.00% 75.86% 75.00% 72.72%
src/services/suggestions/utils/index.ts 75.00% 75.00% 100.00% 60.71%
src/core/local_modules/records/index.ts 75.60% 76.19% 100.00% 68.08%
src/core/global_modules/utils.ts 75.75% 72.22% 57.14% 53.84%
src/core/local_modules/project/validate.ts 75.86% 75.86% 100.00% 56.25%
src/core/global_modules/indexes/bind.ts 76.31% 74.35% 90.90% 68.96%
src/core/global_modules/records/utils/data/sqlTypes.ts 76.59% 80.64% 82.35% 72.22%
src/core/global_modules/tablePartial/interpret.ts 77.65% 70.37% 78.94% 53.84%
src/core/types/relation.ts 78.12% 73.56% 85.71% 73.55%
src/core/types/filepath.ts 79.48% 78.57% 77.77% 70.37%
src/core/global_modules/program/utils.ts 80.00% 80.00% 100.00% 70.00%
src/core/global_modules/tableGroup/bind.ts 80.00% 80.00% 100.00% 57.14%
src/core/local_modules/note/validate.ts 80.00% 78.18% 83.33% 73.68%
src/core/local_modules/records/validate.ts 80.28% 80.55% 93.75% 72.30%
src/core/global_modules/ref/bind.ts 80.64% 80.64% 90.00% 70.00%
src/core/global_modules/indexes/interpret.ts 81.39% 72.00% 100.00% 56.66%
src/core/local_modules/tablePartial/index.ts 81.48% 81.48% 100.00% 77.27%
src/core/local_modules/diagramView/validate.ts 81.57% 78.04% 84.21% 72.72%
src/core/local_modules/checks/validate.ts 81.63% 82.69% 93.75% 70.00%
src/core/global_modules/records/bind.ts 82.92% 83.72% 93.75% 67.30%
src/compiler/queries/container/token.ts 83.33% 85.71% 100.00% 75.00%
__tests__/utils/compiler.ts 84.28% 82.25% 100.00% 58.97%
src/core/parser/parser.ts 84.52% 84.75% 100.00% 76.09%
src/core/utils/setting.ts 84.84% 80.95% 85.71% 68.75%
src/core/local_modules/table/validate.ts 84.92% 85.47% 90.24% 73.40%
src/core/local_modules/enum/validate.ts 85.48% 81.81% 81.25% 76.31%
__tests__/utils/mocks.ts 85.71% 86.20% 75.00% 100.00%
src/core/global_modules/use/index.ts 86.59% 83.20% 100.00% 78.22%
src/services/suggestions/utils/useMerger.ts 86.95% 81.13% 100.00% 46.34%
src/core/global_modules/tablePartial/bind.ts 87.03% 87.27% 100.00% 71.42%
src/core/global_modules/tableGroup/interpret.ts 88.37% 88.37% 100.00% 77.27%
src/services/suggestions/provider.ts 88.43% 84.41% 98.41% 76.75%
src/services/suggestions/recordRowSnippet.ts 88.46% 87.09% 100.00% 73.80%
src/core/types/symbol/metadata.ts 88.72% 75.60% 90.00% 59.66%
src/compiler/queries/nodeAtPosition.ts 88.88% 90.00% 100.00% 75.00%
src/core/global_modules/diagramView/index.ts 89.16% 86.23% 83.33% 78.18%
src/compiler/index.ts 90.00% 90.07% 70.00% 76.92%
src/core/global_modules/table/interpret.ts 90.62% 84.61% 95.45% 67.02%
src/core/global_modules/records/index.ts 90.90% 87.15% 100.00% 79.16%
src/core/global_modules/records/utils/constraints/pk.ts 91.66% 88.88% 93.75% 63.15%
src/core/global_modules/schema/index.ts 92.26% 82.46% 91.66% 70.07%
src/core/utils/interpret.ts 93.33% 90.00% 100.00% 73.23%
src/core/global_modules/diagramView/interpret.ts 94.59% 90.40% 92.85% 75.75%
src/services/suggestions/use.ts 94.68% 87.61% 100.00% 77.45%
src/core/global_modules/note/interpret.ts 95.65% 95.65% 100.00% 75.00%
src/core/global_modules/ref/interpret.ts 95.83% 94.11% 100.00% 78.84%
src/core/global_modules/records/interpret.ts 95.97% 92.59% 100.00% 79.54%
__tests__/examples/interpreter/multifile/utils.ts 96.00% 89.65% 100.00% 62.50%
src/compiler/queries/canonicalName.ts 96.96% 92.10% 100.00% 76.66%
src/core/global_modules/program/interpret.ts 97.22% 91.82% 100.00% 70.31%
src/core/types/errors.ts 98.59% 98.59% 75.00% 100.00%
src/compiler/queries/transform/renameTable.ts 99.05% 90.47% 100.00% 78.82%
src/core/global_modules/checks/interpret.ts 100.00% 88.88% 100.00% 60.00%
src/core/global_modules/program/index.ts 100.00% 85.71% 100.00% 75.00%
src/core/global_modules/records/utils/constraints/unique.ts 100.00% 94.28% 100.00% 58.33%
src/services/definition/provider.ts 100.00% 95.23% 100.00% 71.42%

@huydo862003
huydo862003 force-pushed the optional-ref-2 branch 2 times, most recently from c2c5723 to 162bcf5 Compare July 1, 2026 04:50
@huydo862003
huydo862003 changed the base branch from master to fix/pk-null-validation July 9, 2026 02:40
@huydo862003
huydo862003 changed the base branch from fix/pk-null-validation to master July 13, 2026 07:20
if (s instanceof CompileError) return 6;
if (s instanceof CompileInfo) return 5;
if (s instanceof CompileWarning) return 6;
if (s instanceof CompileError) return 7;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should the values below be increased?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's internal to the tests for consistent ordering only, wherever is fine, as long as the partial ordering among the old objects do not change :*

const c = this.cardinalities(compiler);
return c ? parseCardinality(c[1]) : undefined;
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These 2 seem to not be used anywhere 🤔

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah but just kept it though, it can be useful :pepe-cuoi-guong:

Comment on lines +312 to +319
leftCardinality (compiler: Compiler): { min: number; max: number | '*' } | undefined {
const c = this.cardinalities(compiler);
return c ? parseCardinality(c[0]) : undefined;
}

rightCardinality (compiler: Compiler): { min: number; max: number | '*' } | undefined {
const c = this.cardinalities(compiler);
return c ? parseCardinality(c[1]) : undefined;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These 2 seem to not be used anywhere 🤔

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah but just kept it though, it can be useful :pepe-cuoi-guong:

Comment on lines +32 to +42
export function updateSettingEdit (
declaration: SyntaxNode,
settingName: string,
newValue: string,
source: string,
): TextEdit | undefined {
const found = findSetting(source, declaration, settingName);
if (!found) return undefined;

return { start: found.settingNode.start, end: found.settingNode.end, newText: newValue };
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems to not be used anywhere 🤔

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's used in #933 nhó, we're about to update fragile regexes in dbdiagram-frontend to these.

Comment on lines +111 to +112
"onDelete": null,
"onUpdate": null

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we have a way to ensure either:

  • Empty/null/undefined values don't appear on the output json
  • They do appear
    so the test output won't necessarily change in future works?

The output at packages/dbml-core/__tests__/examples/parser/mssql-parse/output/table_constraints_indexes.out.json at line 316 does not have onUpdate but I assume it'll be onUpdate: null.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

may need to either normalize the output before outputting like in @dbml/parse :3 but maybe another pr would do

@huydo862003 huydo862003 changed the title Optional ref DBX-5320 Optional ref Jul 17, 2026
@linear-code

linear-code Bot commented Jul 17, 2026

Copy link
Copy Markdown

DBX-5320

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