Fix SQLSchema-To-ALExtension.ps1 so it works on NAV/BC SQL schemas - #362
Conversation
|
Additional validation: this fix has now been verified against a real partner-supplied BC14 CU41 (DK) schema — the
A field-by-field diff of the SQL columns against the generated AL confirms no missing fields, no extra fields, no One extra defect surfaced by the partner's actual output file and fixed here: the original writes the generated 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 |
Problem
SQLSchema-To-ALExtension.ps1was 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: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:
Root causes
$tableidregex[^\s\n\(]+disallows spaces[dbo].[CRONUS Danmark A_S$Vendor]only matches[dbo].[CRONUS, soCREATE TABLEnever matches → Unable to parse schema definitions$colidregex[a-zA-Z\d_\[\]]+disallows spaces[Search Name]splits into column[Search/ typeName]→ the whole Unkown column type cascadeSQLColTypeToALonly maps GP typesnvarchar,decimal,bigint,bit,uniqueidentifier,date,time,datetime2,money,float,real,timestampare all unmapped — these are the BC core types[String](Get-Content ...)without-Rawfield(4; Search Name; Text[100])andtable 50000 MSFTSales Headerare syntax errorsRemove-Item $extensionFolderwithout-Recurse -Forcestats.sqlemitted unbracketed table names$Changes
Parsing
$,.,(,-are parsed correctly, for both table names and column names.Get-Content -Raw, so line structure survives. CRLF, LF and BOM inputs all work.[db].[dbo].[Table]) resolve to the last segment.NAV/BC awareness
<Company>$<Table>is reduced to<Table>, with-CompanyNameand-NoStripCompanyNameas escape hatches. The mapping codeunit still maps to the correct source table name.$<app guid>on extension tables is removed.timestamp/rowversioncolumn and the platform-managed$systemId,$systemCreatedAt,$systemCreatedBy,$systemModifiedAt,$systemModifiedBycolumns 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 toBlob; lengths above 2048 are clamped.Valid AL output
Item Charge Assignment (Purch)+ prefix exceeds the limit and previously producedAL0305). The source table name in the mapping codeunit is unaffected.stats.sqlbrackets database and table names.-OutputFolder/-ExtensionNameare 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/ntext→Text[2048],binary→Text[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 producedUNKNOWN, which never compiled, so nothing working can depend on them.Verified on a GP
RM00101schema: 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.exeagainst BC symbols:Vendor(the reported case)alcerrors via the workaround$system*,image,uniqueidentifier,decimal(38,20)AL0305RM00101CREATE TABLE/ missing input / re-run into same folder / LF / BOM / PK on skipped columnREADME.mddocuments the new parameters, the skipped columns, the object-name shortening, and the type-mapping caveats — in particular that BCCodeandTextfields are bothnvarcharand cannot be told apart from the SQL schema, and thatOption/Enumarrive asIntegerordinals.