Skip to content

Fix SQLSchema-To-ALExtension.ps1 so it works on NAV/BC SQL schemas - #362

Merged
Wenjie Fan (gggdttt) merged 3 commits into
masterfrom
fix/sqlschema-to-al-nav-bc-schemas
Sep 3, 2026
Merged

Wenjie Fan (gggdttt) merged 3 commits into
masterfrom
fix/sqlschema-to-al-nav-bc-schemas

Conversation

@gggdttt

Copy link
Copy Markdown
Contributor

Problem

SQLSchema-To-ALExtension.ps1 was written for Dynamics GP schemas and does not work on NAV / Business Central on-premises schemas, which is the scenario the BC14 Reimplementation extending sample points partners at.

Running it on a stock BC14 table scripted from SSMS (Script Table as > CREATE To) fails outright:

Unable to parse schema definitions

Removing the company name from the table name gets past the parser, but then every column is rejected and the generated AL does not compile:

Unkown column type [nvarchar](20)  on table Vendor.
Unkown column type Name]  on table Vendor.
Unkown column type No_]  on table Vendor.
Unkown column type Dimension  on table Vendor.
...

Root causes

# Cause Effect
1 $tableid regex [^\s\n\(]+ disallows spaces [dbo].[CRONUS Danmark A_S$Vendor] only matches [dbo].[CRONUS, so CREATE TABLE never matches → Unable to parse schema definitions
2 $colid regex [a-zA-Z\d_\[\]]+ disallows spaces [Search Name] splits into column [Search / type Name] → the whole Unkown column type cascade
3 SQLColTypeToAL only maps GP types nvarchar, decimal, bigint, bit, uniqueidentifier, date, time, datetime2, money, float, real, timestamp are all unmapped — these are the BC core types
4 [String](Get-Content ...) without -Raw the string array is joined with spaces, destroying line structure
5 AL identifiers were never quoted field(4; Search Name; Text[100]) and table 50000 MSFTSales Header are syntax errors
6 Remove-Item $extensionFolder without -Recurse -Force fails on a non-empty folder
7 stats.sql emitted unbracketed table names breaks for names containing spaces or $

Changes

Parsing

  • Bracketed SQL identifiers containing spaces, $, ., (, - are parsed correctly, for both table names and column names.
  • Get-Content -Raw, so line structure survives. CRLF, LF and BOM inputs all work.
  • Primary key columns are extracted with a regex rather than by splitting on whitespace, so composite keys and bracketed names with spaces work.
  • N-part table names ([db].[dbo].[Table]) resolve to the last segment.

NAV/BC awareness

  • <Company>$<Table> is reduced to <Table>, with -CompanyName and -NoStripCompanyName as escape hatches. The mapping codeunit still maps to the correct source table name.
  • A trailing $<app guid> on extension tables is removed.
  • The timestamp/rowversion column and the platform-managed $systemId, $systemCreatedAt, $systemCreatedBy, $systemModifiedAt, $systemModifiedBy columns are skipped instead of being emitted as invalid AL fields.

Type mapping — added nvarchar, varchar, nchar, bigint, bit, decimal, money, smallmoney, float, real, date, time, datetime2, smalldatetime, datetimeoffset, uniqueidentifier, xml, sql_variant. nvarchar(max) maps to Blob; lengths above 2048 are clamped.

Valid AL output

  • Object and field names are quoted.
  • Object names are shortened to the 30-character AL limit and uniquified when needed (Item Charge Assignment (Purch) + prefix exceeds the limit and previously produced AL0305). The source table name in the mapping codeunit is unaffected.
  • Tables whose primary key references a column that cannot be generated are skipped, and no permission entry is emitted for a skipped table.
  • stats.sql brackets database and table names.
  • The script no longer resolves its output folder to the drive root when -OutputFolder/-ExtensionName are omitted, and no longer deletes a folder it did not create.

Backwards compatibility with Dynamics GP

This was treated as a hard requirement — the type mappings that GP relies on are unchanged, including the two that are arguably wrong (text/ntextText[2048], binaryText[50]); they are left alone so that already-published GP extensions keep their schema. Company-name stripping only triggers on a $ in the table name, which GP names never contain. The new type mappings are purely additive: they previously produced UNKNOWN, which never compiled, so nothing working can depend on them.

Verified on a GP RM00101 schema: field IDs and types are byte-for-byte identical to the current script's output apart from the added quotes.

Validation

A regression suite of 36 assertions across 11 scenarios, with the generated AL compiled by alc.exe against BC symbols:

Scenario Before After
Verbatim SSMS output, BC14 Vendor (the reported case) parse failure; 6 alc errors via the workaround 0 errors
BC14 schema, 5 tables — composite keys, $system*, image, uniqueidentifier, decimal(38,20) many Unkown column type 0 errors
Long/colliding table names AL0305 0 errors, names unique, mapping intact
Dynamics GP RM00101 baseline identical output, 0 errors
No CREATE TABLE / missing input / re-run into same folder / LF / BOM / PK on skipped column handled cleanly

README.md documents the new parameters, the skipped columns, the object-name shortening, and the type-mapping caveats — in particular that BC Code and Text fields are both nvarchar and cannot be told apart from the SQL schema, and that Option/Enum arrive as Integer ordinals.

@gggdttt

Copy link
Copy Markdown
Contributor Author

Additional validation: this fix has now been verified against a real partner-supplied BC14 CU41 (DK) schema — the [dbo].[CRONUS Danmark$Vendor] table scripted out of SSMS, provided by the partner who reported the issue.

Result
Original script Unable to parse schema definitions, then 70+ Unkown column type warnings; the resulting .al fails to compile with 9 errors (AL0104 / AL0107 / AL0124)
This PR 0 warnings, 0 errors; all 72 fields generated (the timestamp rowversion is correctly skipped), key(Key1; "No_"), and the extension compiles cleanly with alc.exe

A field-by-field diff of the SQL columns against the generated AL confirms no missing fields, no extra fields, no UNKNOWN types, and contiguous field IDs 1..72.

One extra defect surfaced by the partner's actual output file and fixed here: the original writes the generated .al files as UTF-16LE (the PowerShell 5.1 Out-File default). This PR writes UTF-8.

The partner's real schema has also been added to the local regression matrix; the suite is now 46 assertions across 12 scenarios, all passing, with every generated extension compiled by alc.exe.

@gggdttt
Wenjie Fan (gggdttt) merged commit ccb6c3d into master Sep 3, 2026
1 check passed
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