Skip to content

Dev#52

Merged
OGR-67 merged 2 commits into
mainfrom
dev
Apr 3, 2026
Merged

Dev#52
OGR-67 merged 2 commits into
mainfrom
dev

Conversation

@OGR-67

@OGR-67 OGR-67 commented Apr 3, 2026

Copy link
Copy Markdown
Owner

Description

Closes

closes #49
closes #50

OGR-67 and others added 2 commits April 3, 2026 10:10
- Added support for parsing TableRelation syntax in AlParser.
- Updated DBMLColumn to include References for foreign key lookups.
- Enhanced schema post-processing to handle missing referenced tables and fields.
- Created documentation for schema post-processing steps and conventions.
- Added tests for TableRelation parsing and handling in various scenarios.
Copilot AI review requested due to automatic review settings April 3, 2026 08:15
@OGR-67 OGR-67 merged commit 402afc6 into main Apr 3, 2026
4 checks passed

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR adds end-to-end support for AL TableRelation parsing and DBML relationship emission, including schema post-processing to handle missing/partial referenced tables and to keep output consistent when base tables are absent (common with tableextension-only inputs).

Changes:

  • Parse TableRelation from AL fields into DBMLColumn.References (with UnknownField sentinel when the referenced field isn’t explicit).
  • Extend schema post-processing to remove empty tables, create stub tables for missing referenced targets, and add missing referenced fields to existing partial tables.
  • Add/extend tests and fixtures to cover relationship parsing + post-processing behavior; add documentation for parsing and post-processing.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/DBMLWriter/SchemaPostProcessor.cs Adds new post-processing steps for empty tables, stub table creation, and filling missing referenced fields.
src/AL2DBML.Parser/AlParser.cs Extracts TableRelation into DBMLColumn.References and wires it through table parsing.
src/AL2DBML.Tests/Writer/WriterTests.cs Adds writer-level tests validating stub creation, empty table removal, and unknown-field resolution.
src/AL2DBML.Tests/Parser/TableParserTests.cs Adds parser tests for supported/unsupported TableRelation syntaxes (quoted/unquoted/where/conditional).
src/AL2DBML.Tests/Fixtures/Tables/PurchaseHeader.al Updates fixture to include TableRelation examples used by parser tests.
src/AL2DBML.Tests/Fixtures/Tables/Customer.al Updates fixture to include TableRelation example used by parser tests.
docs/SCHEMA_POST_PROCESSING.md New doc describing schema post-processing pipeline and relationship-resolution rules.
docs/AL_PARSING.md Documents TableRelation parsing and the UnknownField sentinel behavior.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +84 to +89
var explicitFields = group
.Where(f => !string.IsNullOrEmpty(f.References![1]) && !string.Equals(f.References![1], Unknown, StringComparison.OrdinalIgnoreCase))
.DistinctBy(f => f.References![1], StringComparer.OrdinalIgnoreCase)
.Select(f => new DBMLColumn { Name = f.References![1], Type = f.Type, IsPrimaryKey = true })
.ToList();

Copilot AI Apr 3, 2026

Copy link

Choose a reason for hiding this comment

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

CreateStubsForMissingReferencedTables marks every distinct explicitly referenced field as IsPrimaryKey = true. If multiple explicit field names reference the same missing table, this produces a composite-PK stub and also prevents ResolveUnknownFieldReferences from resolving UnknownField references to that table (since singlePkByTable only tracks tables with exactly one PK). Consider only marking the stub field as PK when there is exactly one explicit referenced field (otherwise add fields without pk, or choose a single best candidate).

Suggested change
var explicitFields = group
.Where(f => !string.IsNullOrEmpty(f.References![1]) && !string.Equals(f.References![1], Unknown, StringComparison.OrdinalIgnoreCase))
.DistinctBy(f => f.References![1], StringComparer.OrdinalIgnoreCase)
.Select(f => new DBMLColumn { Name = f.References![1], Type = f.Type, IsPrimaryKey = true })
.ToList();
var explicitReferencedFields = group
.Where(f => !string.IsNullOrEmpty(f.References![1]) && !string.Equals(f.References![1], Unknown, StringComparison.OrdinalIgnoreCase))
.DistinctBy(f => f.References![1], StringComparer.OrdinalIgnoreCase)
.ToList();
var hasSingleExplicitReferencedField = explicitReferencedFields.Count == 1;
var explicitFields = explicitReferencedFields
.Select(f => new DBMLColumn
{
Name = f.References![1],
Type = f.Type,
IsPrimaryKey = hasSingleExplicitReferencedField
})
.ToList();

Copilot uses AI. Check for mistakes.
Comment thread docs/AL_PARSING.md
| `TableRelation = "Salesperson/Purchaser"."Code";` | `["Salesperson/Purchaser", "Code"]` |
| `TableRelation = "Salesperson/Purchaser".Code;` | `["Salesperson/Purchaser", "Code"]` |

When no field is specified, the sentinel value `"UnknownField"` is used. This is resolved at post-processing time (see ARCHITECTURE.md — Schema post-processing).

Copilot AI Apr 3, 2026

Copy link

Choose a reason for hiding this comment

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

This link reference appears to be incorrect: ARCHITECTURE.md does not contain a “Schema post-processing” section. Consider updating the reference to SCHEMA_POST_PROCESSING.md (or adding an explicit section/link target in ARCHITECTURE.md).

Suggested change
When no field is specified, the sentinel value `"UnknownField"` is used. This is resolved at post-processing time (see ARCHITECTURE.md — Schema post-processing).
When no field is specified, the sentinel value `"UnknownField"` is used. This is resolved at post-processing time (see `SCHEMA_POST_PROCESSING.md`).

Copilot uses AI. Check for mistakes.
Comment on lines +31 to +35
**3. CreateStubsForMissingReferencedTables**
For each `TableRelation` reference pointing to a table absent from the schema, a stub table is created:
- If the reference includes an explicit field name: the stub contains that field as PK.
- If only `UnknownField` references exist: the stub contains an `UnknownField` column as PK (typed from the referencing field). The relation is kept as-is in the output — the schema is technically incomplete but the reference is not broken.

Copilot AI Apr 3, 2026

Copy link

Choose a reason for hiding this comment

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

The doc says the stub table contains “that field” as PK, but the current implementation can add multiple distinct explicitly referenced fields for the same missing table (and marks them all as PK). Consider clarifying the behavior for multiple explicit references (single vs multiple stub columns, and PK marking rules) so the documentation matches the code.

Copilot uses AI. Check for mistakes.
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.

Feat: Parse tables with relationship test: parse tables with relationship

2 participants