diff --git a/.claude/skills/mendix/bootstrap-app/SKILL.md b/.claude/skills/mendix/bootstrap-app/SKILL.md index 683b8e0e81..a2a4fca33e 100644 --- a/.claude/skills/mendix/bootstrap-app/SKILL.md +++ b/.claude/skills/mendix/bootstrap-app/SKILL.md @@ -253,8 +253,9 @@ with these deltas: against the host name rather than the listen address: ```sql - alter settings configuration 'Default' - ApplicationRootUrl = 'http://backend.local:8080/'; + alter settings configuration 'Default' ( + ApplicationRootUrl: 'http://backend.local:8080/' + ); ``` `run --local` picks that up at boot and prints which configuration it came from. diff --git a/.claude/skills/mendix/create-page/SKILL.md b/.claude/skills/mendix/create-page/SKILL.md index 3f944f0807..65dd872670 100644 --- a/.claude/skills/mendix/create-page/SKILL.md +++ b/.claude/skills/mendix/create-page/SKILL.md @@ -47,11 +47,11 @@ create [or replace] page Module.PageName page is opened in a pop-up. They are optional — omitting them uses the Mendix defaults (600 × 600, not resizable). Unlike the other header keywords, these property names are **case-sensitive** and must be written exactly as shown. They can also be changed later -with `alter page … { set PopupWidth = …; }` (see the alter-page skill). +with `alter page … { set (PopupWidth: …); }` (see the alter-page skill). **Page CSS class / style** (`Class` / `Style`) set the page's Appearance — a CSS class and inline style applied to the whole page (e.g. `Class: 'container-fluid bg-light'`). -Both are optional and can be changed later with `alter page … { set Class = '…'; }`. +Both are optional and can be changed later with `alter page … { set (Class: '…'); }`. **Page Variables**: Local variables at the page level for use in expressions (e.g., column visibility). - DataType: `boolean`, `string`, `integer`, `decimal`, `datetime` @@ -243,7 +243,7 @@ To make targeted changes to an existing page (change a label, add a field, remov ```sql -- Change a button caption and add a field alter page Module.Customer_Edit { - set caption = 'Save & Close' on btnSave; + set (caption: 'Save & Close') on btnSave; insert after txtEmail { textbox txtPhone (label: 'Phone', attribute: Phone) } diff --git a/.claude/skills/mendix/demo-data/SKILL.md b/.claude/skills/mendix/demo-data/SKILL.md index faead4d4bf..74975483ba 100644 --- a/.claude/skills/mendix/demo-data/SKILL.md +++ b/.claude/skills/mendix/demo-data/SKILL.md @@ -41,13 +41,14 @@ For full credentials (username, password): Example output: ```sql -alter settings configuration 'Default' - DatabaseType = 'PostgreSql', - DatabaseUrl = 'localhost:5434', - DatabaseName = 'mxcli2-dev', - DatabaseUserName = 'mendix', - DatabasePassword = 'mendix', - HttpPortNumber = 8080; +alter settings configuration 'Default' ( + DatabaseType: 'PostgreSql', + DatabaseUrl: 'localhost:5434', + DatabaseName: 'mxcli2-dev', + DatabaseUserName: 'mendix', + DatabasePassword: 'mendix', + HttpPortNumber: 8080 +); ``` --- diff --git a/.claude/skills/mendix/migrate-design-prototype/SKILL.md b/.claude/skills/mendix/migrate-design-prototype/SKILL.md index 423769afbd..d270f7a2ed 100644 --- a/.claude/skills/mendix/migrate-design-prototype/SKILL.md +++ b/.claude/skills/mendix/migrate-design-prototype/SKILL.md @@ -538,7 +538,7 @@ Use `alter page` to attach a class without rewriting the page (see `alter-page`) ```sql alter page ResourceScheduling.Approvals { - set Class = 'ss-appr-card ss-appr-card--conflict' on queueCard; + set (Class: 'ss-appr-card ss-appr-card--conflict') on queueCard; } ``` diff --git a/.claude/skills/mendix/odata-data-sharing/SKILL.md b/.claude/skills/mendix/odata-data-sharing/SKILL.md index b38a891e72..938115b155 100644 --- a/.claude/skills/mendix/odata-data-sharing/SKILL.md +++ b/.claude/skills/mendix/odata-data-sharing/SKILL.md @@ -81,7 +81,7 @@ Then re-import: `CREATE OR MODIFY EXTERNAL ENTITIES FROM F1Now.NowApi` maps the new entity sets. Do **not** `DROP CONSUMED ODATA SERVICE` and recreate it to force a refresh — that invalidates the client ID the existing external entities point at. -Note that `ALTER CONSUMED ODATA SERVICE SET MetadataUrl = …` does *not* re-fetch. Use +Note that `ALTER CONSUMED ODATA SERVICE … SET ( MetadataUrl: … )` does *not* re-fetch. Use `CREATE OR MODIFY` when the contract is what changed. **Use Cases for Local Metadata:** diff --git a/.claude/skills/mendix/odata-data-sharing/reference/walkthroughs.md b/.claude/skills/mendix/odata-data-sharing/reference/walkthroughs.md index 54b37a4edd..661a110a20 100644 --- a/.claude/skills/mendix/odata-data-sharing/reference/walkthroughs.md +++ b/.claude/skills/mendix/odata-data-sharing/reference/walkthroughs.md @@ -309,8 +309,8 @@ from consumed odata service ShopClient.ShopApiClient ); -- Toggle the flag without recreating the entity. -alter entity ShopClient.Product set allow_create_change_locally = true; -alter entity ShopClient.Product set allow_create_change_locally = false; +alter entity ShopClient.Product set ( AllowCreateChangeLocally: true ); +alter entity ShopClient.Product set ( AllowCreateChangeLocally: false ); ``` ## Publishing a Non-Persistable Entity (no copy of the data) diff --git a/.claude/skills/mendix/project-settings/SKILL.md b/.claude/skills/mendix/project-settings/SKILL.md index bcf305d913..529d8486ab 100644 --- a/.claude/skills/mendix/project-settings/SKILL.md +++ b/.claude/skills/mendix/project-settings/SKILL.md @@ -30,22 +30,22 @@ describe settings; ### Modify Model Settings ```sql -alter settings runtime AfterStartupMicroflow = 'Module.MF_Startup'; -- must return Boolean (CE0142) -alter settings runtime BeforeShutdownMicroflow = 'Module.MF_Shutdown'; -alter settings runtime HealthCheckMicroflow = 'Module.MF_HealthCheck'; -alter settings runtime HashAlgorithm = 'BCrypt'; -alter settings runtime BcryptCost = 12; -alter settings runtime JavaVersion = 'Java21'; -- or '21'; see note below -alter settings runtime RoundingMode = 'HalfUp'; -alter settings runtime AllowUserMultipleSessions = true; -alter settings runtime ScheduledEventTimeZoneCode = 'Etc/UTC'; -alter settings runtime DefaultTimeZoneCode = 'Europe/Amsterdam'; -alter settings runtime FirstDayOfWeek = 'Monday'; -- Default, Monday..Sunday -alter settings runtime DecimalScale = 8; -alter settings runtime EnableDataStorageOptimisticLocking = true; -alter settings runtime UseDatabaseForeignKeyConstraints = true; -alter settings runtime UseOQLVersion2 = true; -alter settings runtime SslCertificateAlgorithm = 'PKIX'; -- PKIX or SunX509 +alter settings runtime ( AfterStartupMicroflow: 'Module.MF_Startup' ); -- must return Boolean (CE0142) +alter settings runtime ( BeforeShutdownMicroflow: 'Module.MF_Shutdown' ); +alter settings runtime ( HealthCheckMicroflow: 'Module.MF_HealthCheck' ); +alter settings runtime ( HashAlgorithm: 'BCrypt' ); +alter settings runtime ( BcryptCost: 12 ); +alter settings runtime ( JavaVersion: 'Java21' ); -- or '21'; see note below +alter settings runtime ( RoundingMode: 'HalfUp' ); +alter settings runtime ( AllowUserMultipleSessions: true ); +alter settings runtime ( ScheduledEventTimeZoneCode: 'Etc/UTC' ); +alter settings runtime ( DefaultTimeZoneCode: 'Europe/Amsterdam' ); +alter settings runtime ( FirstDayOfWeek: 'Monday' ); -- Default, Monday..Sunday +alter settings runtime ( DecimalScale: 8 ); +alter settings runtime ( EnableDataStorageOptimisticLocking: true ); +alter settings runtime ( UseDatabaseForeignKeyConstraints: true ); +alter settings runtime ( UseOQLVersion2: true ); +alter settings runtime ( SslCertificateAlgorithm: 'PKIX' ); -- PKIX or SunX509 ``` **Not every project stores every setting.** Mendix adds model settings over time — @@ -97,18 +97,20 @@ configuration, add `DatabasePassword = '…'` yourself. ```sql -- Full database configuration -alter settings configuration 'Default' - DatabaseType = 'PostgreSql', - DatabaseUrl = 'localhost:5432', - DatabaseName = 'mydb', - DatabaseUserName = 'mendix', - DatabasePassword = 'mendix', - HttpPortNumber = 8080, - ServerPortNumber = 8090; +alter settings configuration 'Default' ( + DatabaseType: 'PostgreSql', + DatabaseUrl: 'localhost:5432', + DatabaseName: 'mydb', + DatabaseUserName: 'mendix', + DatabasePassword: 'mendix', + HttpPortNumber: 8080, + ServerPortNumber: 8090 +); -- Update a single field -alter settings configuration 'Default' - DatabaseUrl = 'newhost:5432'; +alter settings configuration 'Default' ( + DatabaseUrl: 'newhost:5432' +); ``` `HttpPortNumber`, `ServerPortNumber`, `BcryptCost`, `DefaultTaskParallelism` and @@ -169,10 +171,11 @@ on shared values only: create configuration 'Staging'; -- Create with properties -create configuration 'Production' - DatabaseType = 'PostgreSql', - DatabaseUrl = 'prod-db:5432', - HttpPortNumber = 8080; +create configuration 'Production' ( + DatabaseType: 'PostgreSql', + DatabaseUrl: 'prod-db:5432', + HttpPortNumber: 8080 +); -- Drop a configuration drop configuration 'Staging'; @@ -197,7 +200,7 @@ alter settings LANGUAGE modify 'de_DE' (CheckCompleteness: true); alter settings LANGUAGE remove 'de_DE'; -- the default must already be enabled -alter settings LANGUAGE DefaultLanguageCode = 'en_US'; +alter settings LANGUAGE ( DefaultLanguageCode: 'en_US' ); ``` A language is identified by its **code** — "Arabic, Sudan" is derived from @@ -213,7 +216,7 @@ A language is identified by its **code** — "Arabic, Sudan" is derived from **Set the default language BEFORE authoring content.** The default is not only a fallback — it is the language a new caption is stored under, because Mendix has no -language-neutral text. `alter settings LANGUAGE DefaultLanguageCode = 'nl_NL'` +language-neutral text. `alter settings LANGUAGE (DefaultLanguageCode: 'nl_NL')` *after* creating a page leaves that page's texts in the old language, and nothing reports it: `mx check` is 0 errors either way and the symptom shows up only in Studio Pro, as the empty-caption placeholder plus a "no translation" warning. @@ -231,9 +234,10 @@ list. ```sql -alter settings workflows - UserEntity = 'System.User', - DefaultTaskParallelism = 3; +alter settings workflows ( + UserEntity: 'System.User', + DefaultTaskParallelism: 3 +); ``` ### Workflow Groups (Mendix 11.2+) @@ -281,24 +285,26 @@ Four things worth knowing: ### PostgreSQL Configuration ```sql -alter settings configuration 'Default' - DatabaseType = 'PostgreSql', - DatabaseUrl = 'localhost:5432', - DatabaseName = 'myapp', - DatabaseUserName = 'mendix', - DatabasePassword = 'mendix', - HttpPortNumber = 8080; +alter settings configuration 'Default' ( + DatabaseType: 'PostgreSql', + DatabaseUrl: 'localhost:5432', + DatabaseName: 'myapp', + DatabaseUserName: 'mendix', + DatabasePassword: 'mendix', + HttpPortNumber: 8080 +); ``` ### SQL Server Configuration ```sql -alter settings configuration 'Default' - DatabaseType = 'SqlServer', - DatabaseUrl = 'localhost:1433', - DatabaseName = 'myapp', - DatabaseUserName = 'sa', - DatabasePassword = 'MyPassword', - HttpPortNumber = 8080; +alter settings configuration 'Default' ( + DatabaseType: 'SqlServer', + DatabaseUrl: 'localhost:1433', + DatabaseName: 'myapp', + DatabaseUserName: 'sa', + DatabasePassword: 'MyPassword', + HttpPortNumber: 8080 +); ``` ## Checklist diff --git a/.claude/skills/mendix/regular-expressions/SKILL.md b/.claude/skills/mendix/regular-expressions/SKILL.md index 0f70dd8847..9ce048de96 100644 --- a/.claude/skills/mendix/regular-expressions/SKILL.md +++ b/.claude/skills/mendix/regular-expressions/SKILL.md @@ -102,7 +102,7 @@ create entity Val.Person ( Code: String(20) unique error message 'Code must be unique' ); -alter entity Val.Person modify attribute Email String(200) +alter entity Val.Person modify attribute Email: String(200) not null error message 'Email is required'; ``` diff --git a/.claude/skills/mendix/write-layouts/SKILL.md b/.claude/skills/mendix/write-layouts/SKILL.md index 8a9055d5f1..2e17bccd5a 100644 --- a/.claude/skills/mendix/write-layouts/SKILL.md +++ b/.claude/skills/mendix/write-layouts/SKILL.md @@ -96,8 +96,8 @@ survive. Same operations as `ALTER PAGE`: ```sql alter layout MyModule.App_Default { insert into layoutContainer.top { snippetcall bar (snippet: MyModule.SNIPPET_ThemeBar) }; - set Content = 'My App' on brandText; - drop widget oldBanner; + set (Content: 'My App') on brandText; + drop oldBanner; }; ``` diff --git a/cmd/mxcli/cmd_new.go b/cmd/mxcli/cmd_new.go index 0304d1bb37..62b88cf40a 100644 --- a/cmd/mxcli/cmd_new.go +++ b/cmd/mxcli/cmd_new.go @@ -266,7 +266,7 @@ Examples: if lowered, err := alignJavaVersion(mprPath, os.Stdout); err != nil { fmt.Fprintf(os.Stderr, " Warning: could not align the project's Java version: %v\n", err) fmt.Fprintln(os.Stderr, " If the first build fails with 'release version NN not supported',") - fmt.Fprintln(os.Stderr, " run: mxcli -p .mpr -c \"alter settings runtime JavaVersion = '21'\"") + fmt.Fprintln(os.Stderr, " run: mxcli -p .mpr -c \"alter settings runtime ( JavaVersion: '21' )\"") } else if lowered { fmt.Println() } diff --git a/cmd/mxcli/cmd_new_java.go b/cmd/mxcli/cmd_new_java.go index 608ac3efad..19ad99fce9 100644 --- a/cmd/mxcli/cmd_new_java.go +++ b/cmd/mxcli/cmd_new_java.go @@ -56,13 +56,13 @@ func alignJavaVersion(projectPath string, out io.Writer) (bool, error) { return false, nil } - script := fmt.Sprintf("alter settings runtime JavaVersion = '%d';\n", fallback) + script := fmt.Sprintf("alter settings runtime ( JavaVersion: '%d' );\n", fallback) if err := runMDL(projectPath, script, io.Discard); err != nil { return false, fmt.Errorf("lowering JavaVersion from %d to %d: %w", major, fallback, err) } fmt.Fprintf(out, " Java %d → %d: no JDK %d on this machine, and the project would not build.\n", major, fallback, major) fmt.Fprintf(out, " Install a JDK %d and set JavaVersion back to %d to build for it:\n", major, major) - fmt.Fprintf(out, " mxcli -p .mpr -c \"alter settings runtime JavaVersion = '%d'\"\n", major) + fmt.Fprintf(out, " mxcli -p .mpr -c \"alter settings runtime ( JavaVersion: '%d' )\"\n", major) return true, nil } diff --git a/cmd/mxcli/docker/detect.go b/cmd/mxcli/docker/detect.go index 723be44742..9bba775481 100644 --- a/cmd/mxcli/docker/detect.go +++ b/cmd/mxcli/docker/detect.go @@ -350,7 +350,7 @@ func resolveJDK(major int) (string, error) { // be noise. if major != DefaultJavaMajor { msg += fmt.Sprintf("\n This is the project's own Settings > Model > JavaVersion. To build for a"+ - "\n release you already have instead: mxcli -p .mpr -c \"alter settings runtime JavaVersion = '%d'\"", DefaultJavaMajor) + "\n release you already have instead: mxcli -p .mpr -c \"alter settings runtime ( JavaVersion: '%d' )\"", DefaultJavaMajor) } return "", fmt.Errorf("%s", msg) } diff --git a/cmd/mxcli/syntax/features_domain_model.go b/cmd/mxcli/syntax/features_domain_model.go index 8f094e8420..aac434a206 100644 --- a/cmd/mxcli/syntax/features_domain_model.go +++ b/cmd/mxcli/syntax/features_domain_model.go @@ -96,8 +96,8 @@ func init() { "if not exists", "if exists", "idempotent", "alter entities", "bulk", "every entity", "all entities", "where persistent", }, - Syntax: "ALTER ENTITY Module.Name ADD ATTRIBUTE [IF NOT EXISTS] AttrName: Type [constraints];\nALTER ENTITY Module.Name DROP ATTRIBUTE [IF EXISTS] AttrName;\nALTER ENTITY Module.Name RENAME ATTRIBUTE OldName TO NewName;\nALTER ENTITY Module.Name MODIFY ATTRIBUTE AttrName Type [DEFAULT val];\nALTER ENTITY Module.Name DROP DEFAULT ON ATTRIBUTE AttrName;\nALTER ENTITY Module.Name ADD INDEX [name] [ON] (attr1, attr2);\nALTER ENTITY Module.Name SET DOCUMENTATION 'text';\nALTER ENTITY Module.Name SET POSITION (x, y);\nALTER ENTITY Module.Name ADD EVENT HANDLER ON BEFORE COMMIT CALL Module.MF RAISE ERROR;\nALTER ENTITIES [IN Module] ADD ATTRIBUTE [IF NOT EXISTS] AttrName: Type [, ...]\n [WHERE PERSISTENT | WHERE NON-PERSISTENT];\n\nALTER ENTITIES is the bulk form: one statement applied to every entity in a\nmodule instead of one statement per entity. Only ADD ATTRIBUTE is offered --\nDROP and RENAME aimed at a set are destructive by a typo, and SET POSITION on\nevery entity is meaningless. Pair it with IF NOT EXISTS so the script re-runs.\n\nWHERE filters by persistence, using the same words CREATE ENTITY uses. A VIEW\nentity matches NEITHER: its rows come from an OQL query, so it is not the\npersistent/non-persistent distinction this filter means.\n\nWITHOUT IN, the sweep covers the whole project but SKIPS System and every\nMarketplace module, reporting which -- an upgrade replaces those modules and\nwould take the attribute with it. Naming a module with IN is taken as meaning\nit, so a deliberate edit there is still possible.\n\nSET POSITION places the entity in the domain-model editor, and CREATE ENTITY\ntakes the same thing as an @Position(x, y) annotation. Both are the box's\nCENTRE, not its top-left corner. An entity created without one takes the next\nslot in a wrapping grid, which is a default rather than a layout: to arrange a\nwhole module from its association graph, run 'mxcli layout -p app.mpr'\n(--dry-run first; it replaces positions you set by hand).\n\nMODIFY ATTRIBUTE always takes a type — restate it even when you are only\nchanging the default. There is no 'MODIFY ATTRIBUTE X SET DEFAULT v' form:\nSET would be read as the type name. Use DROP DEFAULT to clear one.\n\nIF NOT EXISTS / IF EXISTS make the add/drop a no-op (skipped, not an error)\nwhen the attribute is already present / already gone — so a domain script\nre-runs cleanly. For a whole script, 'mxcli exec --continue-on-error' reports\neach failed statement and keeps going instead of halting at the first.\n\nRENAME ATTRIBUTE also rewrites every reference to the attribute: the stored\nqualified names (microflow create/change members, page widgets, the entity's own\nvalidation and access rules) AND the bare steps inside XPath constraints, which\nare resolved to their owning entity first so another entity's identically-named\nattribute is left alone. A constraint that cannot be resolved is reported and\nleft unchanged, never guessed at. Uses inside microflow expressions ($obj/Attr)\nare free text and are NOT rewritten; mxbuild reports those as CE0117.", - Example: "ALTER ENTITY Shop.Customer ADD ATTRIBUTE Phone: String(20);\nALTER ENTITY Shop.Customer ADD ATTRIBUTE IF NOT EXISTS Phone: String(20); -- re-runnable\nALTER ENTITY Shop.Customer DROP ATTRIBUTE IF EXISTS OldField; -- re-runnable\nALTER ENTITY Shop.Customer RENAME ATTRIBUTE Email TO EmailAddress;\nALTER ENTITY Shop.Customer MODIFY ATTRIBUTE Phone String(30) DEFAULT ''; -- type restated\nALTER ENTITY Shop.Customer DROP DEFAULT ON ATTRIBUTE Phone; -- clear a default\nALTER ENTITY Shop.Customer ADD INDEX ON (EmailAddress);\nALTER ENTITY Shop.Customer\n ADD EVENT HANDLER ON BEFORE COMMIT CALL Shop.Validate($currentObject) RAISE ERROR;\n\n-- give every persistent entity in a module an audit trail, in one statement\nALTER ENTITIES IN Shop\n ADD ATTRIBUTE IF NOT EXISTS CreatedDate: AutoCreatedDate,\n ADD ATTRIBUTE IF NOT EXISTS ChangedDate: AutoChangedDate\n WHERE PERSISTENT;", + Syntax: "ALTER ENTITY Module.Name ADD ATTRIBUTE [IF NOT EXISTS] AttrName: Type [constraints];\nALTER ENTITY Module.Name DROP ATTRIBUTE [IF EXISTS] AttrName;\nALTER ENTITY Module.Name RENAME ATTRIBUTE OldName TO NewName;\nALTER ENTITY Module.Name MODIFY ATTRIBUTE AttrName: Type [DEFAULT val];\nALTER ENTITY Module.Name DROP DEFAULT ON ATTRIBUTE AttrName;\nALTER ENTITY Module.Name ADD INDEX [name] [ON] (attr1, attr2);\nALTER ENTITY Module.Name SET DOCUMENTATION 'text';\nALTER ENTITY Module.Name SET POSITION (x, y);\nALTER ENTITY Module.Name SET (AllowCreateChangeLocally: true|false); -- external entity\nALTER ENTITY Module.Name ADD EVENT HANDLER ON BEFORE COMMIT CALL Module.MF RAISE ERROR;\nALTER ENTITIES [IN Module] ADD ATTRIBUTE [IF NOT EXISTS] AttrName: Type [, ...]\n [WHERE PERSISTENT | WHERE NON-PERSISTENT];\n\nALTER ENTITIES is the bulk form: one statement applied to every entity in a\nmodule instead of one statement per entity. Only ADD ATTRIBUTE is offered --\nDROP and RENAME aimed at a set are destructive by a typo, and SET POSITION on\nevery entity is meaningless. Pair it with IF NOT EXISTS so the script re-runs.\n\nWHERE filters by persistence, using the same words CREATE ENTITY uses. A VIEW\nentity matches NEITHER: its rows come from an OQL query, so it is not the\npersistent/non-persistent distinction this filter means.\n\nWITHOUT IN, the sweep covers the whole project but SKIPS System and every\nMarketplace module, reporting which -- an upgrade replaces those modules and\nwould take the attribute with it. Naming a module with IN is taken as meaning\nit, so a deliberate edit there is still possible.\n\nSET POSITION places the entity in the domain-model editor, and CREATE ENTITY\ntakes the same thing as an @Position(x, y) annotation. Both are the box's\nCENTRE, not its top-left corner. An entity created without one takes the next\nslot in a wrapping grid, which is a default rather than a layout: to arrange a\nwhole module from its association graph, run 'mxcli layout -p app.mpr'\n(--dry-run first; it replaces positions you set by hand).\n\nMODIFY ATTRIBUTE always takes a type — restate it even when you are only\nchanging the default. There is no 'MODIFY ATTRIBUTE X SET DEFAULT v' form:\nSET would be read as the type name. Use DROP DEFAULT to clear one.\n\nIF NOT EXISTS / IF EXISTS make the add/drop a no-op (skipped, not an error)\nwhen the attribute is already present / already gone — so a domain script\nre-runs cleanly. For a whole script, 'mxcli exec --continue-on-error' reports\neach failed statement and keeps going instead of halting at the first.\n\nRENAME ATTRIBUTE also rewrites every reference to the attribute: the stored\nqualified names (microflow create/change members, page widgets, the entity's own\nvalidation and access rules) AND the bare steps inside XPath constraints, which\nare resolved to their owning entity first so another entity's identically-named\nattribute is left alone. A constraint that cannot be resolved is reported and\nleft unchanged, never guessed at. Uses inside microflow expressions ($obj/Attr)\nare free text and are NOT rewritten; mxbuild reports those as CE0117.", + Example: "ALTER ENTITY Shop.Customer ADD ATTRIBUTE Phone: String(20);\nALTER ENTITY Shop.Customer ADD ATTRIBUTE IF NOT EXISTS Phone: String(20); -- re-runnable\nALTER ENTITY Shop.Customer DROP ATTRIBUTE IF EXISTS OldField; -- re-runnable\nALTER ENTITY Shop.Customer RENAME ATTRIBUTE Email TO EmailAddress;\nALTER ENTITY Shop.Customer MODIFY ATTRIBUTE Phone: String(30) DEFAULT ''; -- type restated\nALTER ENTITY Shop.Customer DROP DEFAULT ON ATTRIBUTE Phone; -- clear a default\nALTER ENTITY Shop.Customer ADD INDEX ON (EmailAddress);\nALTER ENTITY Shop.Customer\n ADD EVENT HANDLER ON BEFORE COMMIT CALL Shop.Validate($currentObject) RAISE ERROR;\n\n-- give every persistent entity in a module an audit trail, in one statement\nALTER ENTITIES IN Shop\n ADD ATTRIBUTE IF NOT EXISTS CreatedDate: AutoCreatedDate,\n ADD ATTRIBUTE IF NOT EXISTS ChangedDate: AutoChangedDate\n WHERE PERSISTENT;", SeeAlso: []string{"domain-model.entity.create", "domain-model.entity.attributes"}, }) diff --git a/cmd/mxcli/syntax/features_integration.go b/cmd/mxcli/syntax/features_integration.go index e1a662c6ec..7830d1ff95 100644 --- a/cmd/mxcli/syntax/features_integration.go +++ b/cmd/mxcli/syntax/features_integration.go @@ -55,12 +55,17 @@ func init() { " ErrorHandlingMicroflow: microflow Module.HandleError\n" + ")\n" + "[HEADERS ('Key': 'Value')];\n\n" + + "ALTER CONSUMED ODATA SERVICE Module.Name SET (Key: value, ...); -- CREATE's keys\n" + + "ALTER PUBLISHED ODATA SERVICE Module.Name SET (Key: value, ...);\n\n" + "CREATE EXTERNAL ENTITY Module.Name\n" + " FROM CONSUMED ODATA SERVICE Module.Client\n" + " (EntitySet: 'Name', RemoteName: 'Name')\n" + " (Attr: Type, ...);\n\n" + "CREATE EXTERNAL ENTITIES FROM Module.Client\n" + - " [INTO Module] [ENTITIES (Name1, Name2)];", + " [INTO Module] [ENTITIES (Name1, Name2)];\n\n" + + "ALTER ENTITY Module.Name SET (AllowCreateChangeLocally: true);\n\n" + + "-- `SET Key = value, ...` (no parentheses) still runs and warns MDL-DEPR061;\n" + + "-- `SET allow_create_change_locally = true` warns MDL-DEPR063.", Example: "CREATE CONSTANT MyModule.SvcUrl TYPE String DEFAULT 'https://api.example.com/odata/v4/';\n\nCREATE CONSUMED ODATA SERVICE MyModule.SalesforceAPI (\n Version: '1.0',\n ODataVersion: OData4,\n MetadataUrl: 'https://api.example.com/odata/$metadata',\n Timeout: 300,\n ServiceUrl: MyModule.SvcUrl\n);\n\nCREATE EXTERNAL ENTITIES FROM MyModule.SalesforceAPI INTO Integration;", SeeAlso: []string{"odata", "odata.publish", "odata.show"}, }) diff --git a/cmd/mxcli/syntax/features_misc.go b/cmd/mxcli/syntax/features_misc.go index 50f6410ae4..aae68a05a2 100644 --- a/cmd/mxcli/syntax/features_misc.go +++ b/cmd/mxcli/syntax/features_misc.go @@ -369,8 +369,8 @@ CREATE OR REPLACE NAVIGATION TabletOffline "settings", "project settings", "configuration", "startup", "shutdown", "hash algorithm", "java version", }, - Syntax: "SHOW SETTINGS;\nDESCRIBE SETTINGS;\nDESCRIBE SETTINGS CONFIGURATION ''; -- just one configuration\nALTER SETTINGS RUNTIME = ; -- MODEL is a deprecated alias\nALTER SETTINGS CONFIGURATION '' = ;", - Example: "SHOW SETTINGS;\nALTER SETTINGS RUNTIME AfterStartupMicroflow = 'Module.MF_Startup';", + Syntax: "SHOW SETTINGS;\nDESCRIBE SETTINGS;\nDESCRIBE SETTINGS CONFIGURATION ''; -- just one configuration\nALTER SETTINGS RUNTIME (: , ...); -- MODEL is a deprecated alias\nALTER SETTINGS CONFIGURATION '' (: , ...);", + Example: "SHOW SETTINGS;\nALTER SETTINGS RUNTIME (AfterStartupMicroflow: 'Module.MF_Startup');", SeeAlso: []string{"settings.show", "settings.alter"}, }) @@ -460,33 +460,37 @@ create or modify translations in Administration for nl_NL ( "optimistic locking", "concurrency", "lost update", "workflow group", "workflow groups", "add group", "task assignment", }, - Syntax: `ALTER SETTINGS RUNTIME = ; -ALTER SETTINGS CONFIGURATION '' = , ...; + Syntax: `ALTER SETTINGS RUNTIME (: , ...); +ALTER SETTINGS CONFIGURATION '' (: , ...); ALTER SETTINGS CONSTANT '' VALUE '' IN CONFIGURATION ''; ALTER SETTINGS DROP CONSTANT '' IN CONFIGURATION ''; -ALTER SETTINGS LANGUAGE DefaultLanguageCode = ''; +ALTER SETTINGS LANGUAGE (DefaultLanguageCode: ''); ALTER SETTINGS LANGUAGE ADD '' [(CheckCompleteness: true, CustomDateFormat: '')]; ALTER SETTINGS LANGUAGE ADD OR MODIFY '' [(...)]; ALTER SETTINGS LANGUAGE MODIFY '' (CheckCompleteness: true, ...); ALTER SETTINGS LANGUAGE REMOVE ''; -ALTER SETTINGS WORKFLOWS UserEntity = ''; +ALTER SETTINGS WORKFLOWS (UserEntity: ''); ALTER SETTINGS WORKFLOWS ADD [OR MODIFY] GROUP '' [(Description: '')]; ALTER SETTINGS WORKFLOWS MODIFY GROUP '' (Description: ''); ALTER SETTINGS WORKFLOWS REMOVE GROUP ''; -CREATE [OR MODIFY] CONFIGURATION '' [ = , ...]; -DROP CONFIGURATION '';`, - Example: `ALTER SETTINGS RUNTIME AfterStartupMicroflow = 'Module.MF_Startup'; -ALTER SETTINGS RUNTIME HashAlgorithm = 'BCrypt'; -ALTER SETTINGS RUNTIME EnableDataStorageOptimisticLocking = true; -ALTER SETTINGS CONFIGURATION 'Default' - DatabaseType = 'PostgreSql', - DatabaseUrl = 'localhost:5432', - DatabaseName = 'mydb'; +CREATE [OR MODIFY] CONFIGURATION '' [(: , ...)]; +DROP CONFIGURATION ''; + +-- A property is Key: value in a ( … ) list, as everywhere else in MDL (R3). +-- Key = value, … without the parentheses still runs and warns MDL-DEPR060.`, + Example: `ALTER SETTINGS RUNTIME (AfterStartupMicroflow: 'Module.MF_Startup'); +ALTER SETTINGS RUNTIME (HashAlgorithm: 'BCrypt', EnableDataStorageOptimisticLocking: true); +ALTER SETTINGS CONFIGURATION 'Default' ( + DatabaseType: 'PostgreSql', + DatabaseUrl: 'localhost:5432', + DatabaseName: 'mydb' +); ALTER SETTINGS CONSTANT 'BusinessEvents.ServerUrl' VALUE 'kafka:9092' IN CONFIGURATION 'Default'; -CREATE CONFIGURATION 'Production' - DatabaseType = 'PostgreSql', - HttpPortNumber = 8080; +CREATE CONFIGURATION 'Production' ( + DatabaseType: 'PostgreSql', + HttpPortNumber: 8080 +); -- LANGUAGE ADD/REMOVE change the ENABLED languages — the list under App -- Settings > Languages, and the only languages a build emits anything for. A @@ -719,9 +723,9 @@ CE0135 "No regular expression specified" at build time. REQUIRED and UNIQUE rules are written as attribute constraints instead, on CREATE ENTITY or ALTER ENTITY: - ALTER ENTITY Shop.Product MODIFY ATTRIBUTE Email string(200) + ALTER ENTITY Shop.Product MODIFY ATTRIBUTE Email: string(200) NOT NULL ERROR MESSAGE 'Email is required'; - ALTER ENTITY Shop.Product MODIFY ATTRIBUTE Code string(20) + ALTER ENTITY Shop.Product MODIFY ATTRIBUTE Code: string(20) UNIQUE ERROR MESSAGE 'Code must be unique';`, Example: `CREATE REGULAR EXPRESSION Shop.EmailPattern ( Expression: '^[^@\s]+@[^@\s]+\.[^@\s]+$' diff --git a/cmd/mxcli/syntax/features_page.go b/cmd/mxcli/syntax/features_page.go index 81e6b357bd..d19944a8c7 100644 --- a/cmd/mxcli/syntax/features_page.go +++ b/cmd/mxcli/syntax/features_page.go @@ -306,21 +306,23 @@ CREATE PAGE Sales.Detail (Title: 'Detail', Layout: Atlas_Core.Atlas_Default) { " DesignProperties: ['Full width': ON]\n\n" + "ON A PAGE THAT ALREADY EXISTS, without rewriting it:\n\n" + " ALTER STYLING ON PAGE|SNIPPET Module.Name WIDGET \n" + - " SET Class = 'css-class', Style = 'css', 'Design property' = 'Value'|ON|OFF;\n\n" + + " SET (Class: 'css-class', Style: 'css', 'Design property': 'Value'|ON|OFF);\n\n" + " ALTER STYLING ON PAGE|SNIPPET Module.Name WIDGET \n" + " CLEAR DESIGN PROPERTIES;\n\n" + "The widget is named by its MDL NAME — the identifier after the widget\n" + "keyword (`ACTIONBUTTON btnSave`), not its caption. `DESCRIBE PAGE` prints\n" + "the names.\n\n" + - "A bare `Class =` REPLACES the widget's classes rather than adding to them.\n" + + "A bare `Class:` REPLACES the widget's classes rather than adding to them.\n" + "Read the current value first if you meant to append.\n\n" + "Reach for ALTER STYLING rather than CREATE OR REPLACE PAGE whenever only\n" + "the look changes: replacing the page rewrites every widget in it, so the\n" + - "diff is the whole document and anything MDL cannot yet spell is lost.", + "diff is the whole document and anything MDL cannot yet spell is lost.\n\n" + + "`SET Class = 'x', 'P' = ON` (no parentheses, `=`) still runs and warns\n" + + "MDL-DEPR062.", Example: "CONTAINER ctn (\n Class: 'my-card',\n DynamicClasses: if $currentObject/Priority = 'High' then 'card-danger' else 'card-normal'\n) {\n DYNAMICTEXT txt (Content: 'Styled text')\n}\n\n" + "-- Restyle one widget on a page that already exists\n" + "alter styling on page Sales.OrderOverview widget btnSave\n" + - " set Class = 'btn-primary', 'Spacing top' = 'Large';\n\n" + + " set (Class: 'btn-primary', 'Spacing top': 'Large');\n\n" + "-- Back to Atlas defaults\n" + "alter styling on snippet Sales.OrderRow widget ctnMain\n" + " clear design properties;", diff --git a/cmd/mxcli/testrunner/generator_endpoint_test.go b/cmd/mxcli/testrunner/generator_endpoint_test.go index 976513c798..1b695d3cf5 100644 --- a/cmd/mxcli/testrunner/generator_endpoint_test.go +++ b/cmd/mxcli/testrunner/generator_endpoint_test.go @@ -171,7 +171,7 @@ func TestEndpointCleanupCommands(t *testing.T) { state: projectState{afterStartup: "Mod.ASU", createdMxTest: true}, present: true, want: []string{ - "ALTER SETTINGS RUNTIME AfterStartupMicroflow = 'Mod.ASU'", + "ALTER SETTINGS RUNTIME (AfterStartupMicroflow: 'Mod.ASU')", "DROP MODULE MxTest", }, }, @@ -180,7 +180,7 @@ func TestEndpointCleanupCommands(t *testing.T) { state: projectState{createdMxTest: false}, present: true, want: []string{ - "ALTER SETTINGS RUNTIME AfterStartupMicroflow = ''", + "ALTER SETTINGS RUNTIME (AfterStartupMicroflow: '')", "DROP MICROFLOW MxTest.Test_test_1", "DROP MICROFLOW MxTest.Test_test_2", "DROP MICROFLOW " + endpointStartupFlow, @@ -191,7 +191,7 @@ func TestEndpointCleanupCommands(t *testing.T) { name: "drops nothing when the module never landed", state: projectState{afterStartup: "Mod.ASU", createdMxTest: true}, present: false, - want: []string{"ALTER SETTINGS RUNTIME AfterStartupMicroflow = 'Mod.ASU'"}, + want: []string{"ALTER SETTINGS RUNTIME (AfterStartupMicroflow: 'Mod.ASU')"}, }, } @@ -220,7 +220,7 @@ func TestEndpointCleanupRestoreIsAlwaysFirst(t *testing.T) { {afterStartup: "Mod.ASU", createdMxTest: true}, } { cmds := endpointCleanupCommands(st, suiteTestFlowNames(suite), true) - if !strings.HasPrefix(cmds[0], "ALTER SETTINGS RUNTIME AfterStartupMicroflow") { + if !strings.HasPrefix(cmds[0], "ALTER SETTINGS RUNTIME (AfterStartupMicroflow") { t.Errorf("state %+v: first command is %q, want the after-startup restore", st, cmds[0]) } } diff --git a/cmd/mxcli/testrunner/host.go b/cmd/mxcli/testrunner/host.go index 20b02bf531..e6ba9c5629 100644 --- a/cmd/mxcli/testrunner/host.go +++ b/cmd/mxcli/testrunner/host.go @@ -61,7 +61,7 @@ func InstallHostedEndpoint(projectPath string, w io.Writer) (*HostedEndpoint, er h.Remove() return nil, fmt.Errorf("injecting the test endpoint: %w", err) } - if err := execMxcliCmd(projectPath, "ALTER SETTINGS RUNTIME AfterStartupMicroflow = "+quoteMDLString(endpointStartupFlow)); err != nil { + if err := execMxcliCmd(projectPath, "ALTER SETTINGS RUNTIME (AfterStartupMicroflow: "+quoteMDLString(endpointStartupFlow)+")"); err != nil { h.Remove() return nil, fmt.Errorf("pointing after-startup at the endpoint: %w", err) } diff --git a/cmd/mxcli/testrunner/runner.go b/cmd/mxcli/testrunner/runner.go index b14a996f9b..fae3d0ea33 100644 --- a/cmd/mxcli/testrunner/runner.go +++ b/cmd/mxcli/testrunner/runner.go @@ -667,7 +667,7 @@ func moduleExists(projectPath, name string) (bool, error) { // changing projects that run at another level (mendixlabs/mxcli#802). func setupCommands(startupFlow string) []string { return []string{ - "ALTER SETTINGS RUNTIME AfterStartupMicroflow = " + quoteMDLString(startupFlow), + "ALTER SETTINGS RUNTIME (AfterStartupMicroflow: " + quoteMDLString(startupFlow) + ")", } } @@ -714,9 +714,9 @@ func execMDLScript(projectPath, mdl, namePattern string) error { // injection landed does not report a spurious cleanup failure. func cleanupCommands(st projectState, mxTestPresent bool) []string { // Restore the original after-startup microflow, or clear it if there was none. - restore := "ALTER SETTINGS RUNTIME AfterStartupMicroflow = ''" + restore := "ALTER SETTINGS RUNTIME (AfterStartupMicroflow: '')" if st.afterStartup != "" { - restore = "ALTER SETTINGS RUNTIME AfterStartupMicroflow = " + quoteMDLString(st.afterStartup) + restore = "ALTER SETTINGS RUNTIME (AfterStartupMicroflow: " + quoteMDLString(st.afterStartup) + ")" } cmds := []string{restore} if !mxTestPresent { diff --git a/cmd/mxcli/testrunner/runner_cleanup_test.go b/cmd/mxcli/testrunner/runner_cleanup_test.go index d5f0f5e460..03f5642fa1 100644 --- a/cmd/mxcli/testrunner/runner_cleanup_test.go +++ b/cmd/mxcli/testrunner/runner_cleanup_test.go @@ -134,7 +134,7 @@ func TestCleanupCommands(t *testing.T) { state: projectState{afterStartup: "MyFirstModule.ASU_Startup", createdMxTest: true}, present: true, want: []string{ - "ALTER SETTINGS RUNTIME AfterStartupMicroflow = 'MyFirstModule.ASU_Startup'", + "ALTER SETTINGS RUNTIME (AfterStartupMicroflow: 'MyFirstModule.ASU_Startup')", "DROP MODULE MxTest", }, }, @@ -143,7 +143,7 @@ func TestCleanupCommands(t *testing.T) { state: projectState{createdMxTest: true}, present: true, want: []string{ - "ALTER SETTINGS RUNTIME AfterStartupMicroflow = ''", + "ALTER SETTINGS RUNTIME (AfterStartupMicroflow: '')", "DROP MODULE MxTest", }, }, @@ -154,7 +154,7 @@ func TestCleanupCommands(t *testing.T) { state: projectState{afterStartup: "Mod.Flow"}, present: true, want: []string{ - "ALTER SETTINGS RUNTIME AfterStartupMicroflow = 'Mod.Flow'", + "ALTER SETTINGS RUNTIME (AfterStartupMicroflow: 'Mod.Flow')", "DROP MICROFLOW MxTest.TestRunner", }, }, @@ -165,7 +165,7 @@ func TestCleanupCommands(t *testing.T) { state: projectState{afterStartup: "Mod.Flow", createdMxTest: true}, present: false, want: []string{ - "ALTER SETTINGS RUNTIME AfterStartupMicroflow = 'Mod.Flow'", + "ALTER SETTINGS RUNTIME (AfterStartupMicroflow: 'Mod.Flow')", }, }, } @@ -189,7 +189,7 @@ func TestCleanupCommands(t *testing.T) { func TestCleanupCommands_RestoreIsWellFormed(t *testing.T) { parsed := parseSettingValue(" AfterStartupMicroflow = 'MyFirstModule.ASU_Startup',") restore := cleanupCommands(projectState{afterStartup: parsed}, true)[0] - want := "ALTER SETTINGS RUNTIME AfterStartupMicroflow = 'MyFirstModule.ASU_Startup'" + want := "ALTER SETTINGS RUNTIME (AfterStartupMicroflow: 'MyFirstModule.ASU_Startup')" if restore != want { t.Errorf("restore command = %q, want %q", restore, want) } diff --git a/cmd/mxcli/testrunner/runner_endpoint.go b/cmd/mxcli/testrunner/runner_endpoint.go index 74eb3883a6..e80204045d 100644 --- a/cmd/mxcli/testrunner/runner_endpoint.go +++ b/cmd/mxcli/testrunner/runner_endpoint.go @@ -211,9 +211,9 @@ func endpointReadyTimeout(suiteTimeout time.Duration) time.Duration { // when the module was already the user's, each generated document is named // explicitly so nothing of theirs is touched. func endpointCleanupCommands(st projectState, flows []string, mxTestPresent bool) []string { - restore := "ALTER SETTINGS RUNTIME AfterStartupMicroflow = ''" + restore := "ALTER SETTINGS RUNTIME (AfterStartupMicroflow: '')" if st.afterStartup != "" { - restore = "ALTER SETTINGS RUNTIME AfterStartupMicroflow = " + quoteMDLString(st.afterStartup) + restore = "ALTER SETTINGS RUNTIME (AfterStartupMicroflow: " + quoteMDLString(st.afterStartup) + ")" } cmds := []string{restore} if !mxTestPresent { diff --git a/docs-site/src/appendixes/quick-reference.md b/docs-site/src/appendixes/quick-reference.md index 9ced9a4d4a..7be500653b 100644 --- a/docs-site/src/appendixes/quick-reference.md +++ b/docs-site/src/appendixes/quick-reference.md @@ -83,12 +83,12 @@ CREATE CONSTANT MyModule.EnableLogging TYPE Boolean DEFAULT true; | List consumed odata services | `LIST CONSUMED ODATA SERVICES [IN Module];` | Consumed OData services | | Describe consumed odata service | `DESCRIBE CONSUMED ODATA SERVICE Module.Name;` | Full MDL output | | Create consumed odata service | `CREATE [OR MODIFY] CONSUMED ODATA SERVICE Module.Name (...);` | Version, MetadataUrl, Timeout, etc. | -| Alter consumed odata service | `ALTER CONSUMED ODATA SERVICE Module.Name SET Key = Value;` | | +| Alter consumed odata service | `ALTER CONSUMED ODATA SERVICE Module.Name SET (Key: Value, ...);` | | | Drop consumed odata service | `DROP CONSUMED ODATA SERVICE Module.Name;` | | | List published odata services | `LIST PUBLISHED ODATA SERVICES [IN Module];` | Published OData services | | Describe published odata service | `DESCRIBE PUBLISHED ODATA SERVICE Module.Name;` | Full MDL output | | Create published odata service | `CREATE [OR MODIFY] PUBLISHED ODATA SERVICE Module.Name (...) AUTHENTICATION ... { PUBLISH ENTITY ... };` | | -| Alter published odata service | `ALTER PUBLISHED ODATA SERVICE Module.Name SET Key = Value;` | | +| Alter published odata service | `ALTER PUBLISHED ODATA SERVICE Module.Name SET (Key: Value, ...);` | | | Drop published odata service | `DROP PUBLISHED ODATA SERVICE Module.Name;` | | | List external entities | `LIST EXTERNAL ENTITIES [IN Module];` | OData-backed entities | | List external actions | `LIST EXTERNAL ACTIONS [IN Module];` | Actions used in microflows | @@ -300,11 +300,11 @@ CREATE OR REPLACE NAVIGATION Responsive |-----------|--------|-------| | List settings | `LIST SETTINGS;` | Overview of all settings parts | | Describe settings | `DESCRIBE SETTINGS;` | Full MDL output (round-trippable) | -| Alter model settings | `ALTER SETTINGS RUNTIME Key = Value;` | AfterStartupMicroflow, HashAlgorithm, JavaVersion, etc. | -| Alter configuration | `ALTER SETTINGS CONFIGURATION 'Name' Key = Value;` | DatabaseType, DatabaseUrl, HttpPortNumber, etc. | +| Alter model settings | `ALTER SETTINGS RUNTIME (Key: Value, ...);` | AfterStartupMicroflow, HashAlgorithm, JavaVersion, etc. | +| Alter configuration | `ALTER SETTINGS CONFIGURATION 'Name' (Key: Value, ...);` | DatabaseType, DatabaseUrl, HttpPortNumber, etc. | | Alter constant | `ALTER SETTINGS CONSTANT 'Name' VALUE 'val' IN CONFIGURATION 'cfg';` | Override constant per configuration | -| Alter language | `ALTER SETTINGS LANGUAGE Key = Value;` | DefaultLanguageCode | -| Alter workflows | `ALTER SETTINGS WORKFLOWS Key = Value;` | UserEntity, DefaultTaskParallelism | +| Alter language | `ALTER SETTINGS LANGUAGE (Key: Value);` | DefaultLanguageCode | +| Alter workflows | `ALTER SETTINGS WORKFLOWS (Key: Value, ...);` | UserEntity, DefaultTaskParallelism | ## Business Events @@ -421,15 +421,15 @@ Modify an existing page or snippet's widget tree in-place without full `CREATE O | Operation | Syntax | Notes | |-----------|--------|-------| -| Set property | `SET Caption = 'New' ON widgetName` | Single property on a widget | +| Set property | `SET (Caption: 'New') ON widgetName` | Single property on a widget | | Set multiple | `SET (Caption = 'Save', ButtonStyle = Success) ON btn` | Multiple properties at once | -| Page-level set | `SET Title = 'New Title'` | No ON clause for page properties | +| Page-level set | `SET (Title: 'New Title')` | No ON clause for page properties | | Insert after | `INSERT AFTER widgetName { widgets }` | Add widgets after target | | Insert before | `INSERT BEFORE widgetName { widgets }` | Add widgets before target | | Insert into | `INSERT INTO containerName { widgets }` | Append as the container's last child (fills an empty container) | -| Drop widgets | `DROP WIDGET name1, name2` | Remove widgets by name | +| Drop widgets | `DROP name1, name2` | Remove widgets by name | | Replace widget | `REPLACE widgetName WITH { widgets }` | Replace widget subtree | -| Pluggable prop | `SET 'showLabel' = false ON cbStatus` | Quoted name for pluggable widgets | +| Pluggable prop | `SET ('showLabel': false) ON cbStatus` | Quoted name for pluggable widgets | | Add variable | `ADD Variables $name: Type = 'expr'` | Add a page variable | | Drop variable | `DROP Variables $name` | Remove a page variable | @@ -438,15 +438,15 @@ Modify an existing page or snippet's widget tree in-place without full `CREATE O **Example:** ```sql ALTER PAGE Module.EditPage { - SET (Caption = 'Save & Close', ButtonStyle = Success) ON btnSave; - DROP WIDGET txtUnused; + SET (Caption: 'Save & Close', ButtonStyle: Success) ON btnSave; + DROP txtUnused; INSERT AFTER txtEmail { TEXTBOX txtPhone (Label: 'Phone', Attribute: Phone) } }; ALTER SNIPPET Module.NavMenu { - SET Caption = 'Dashboard' ON btnHome + SET (Caption: 'Dashboard') ON btnHome }; ``` diff --git a/docs-site/src/examples/alter-page.md b/docs-site/src/examples/alter-page.md index 2afd6c931d..4cb0f50b67 100644 --- a/docs-site/src/examples/alter-page.md +++ b/docs-site/src/examples/alter-page.md @@ -6,7 +6,7 @@ ```sql ALTER PAGE CRM.Customer_Edit { - SET (Caption = 'Save & Close', ButtonStyle = Success) ON btnSave + SET (Caption: 'Save & Close', ButtonStyle: Success) ON btnSave }; ``` @@ -36,7 +36,7 @@ ALTER PAGE CRM.Customer_Overview { ```sql ALTER PAGE CRM.Customer_Edit { - DROP WIDGET txtLegacyField, lblOldNote + DROP txtLegacyField, lblOldNote }; ``` @@ -58,12 +58,12 @@ ALTER PAGE CRM.Customer_Edit { ```sql ALTER PAGE CRM.Customer_Edit { - SET Title = 'Edit Customer Details'; - SET Label = 'Email Address' ON txtEmail; + SET (Title: 'Edit Customer Details'); + SET (Label: 'Email Address') ON txtEmail; INSERT AFTER txtPhone { TEXTBOX txtWebsite (Label: 'Website', Attribute: Website) }; - DROP WIDGET lblInternalRef + DROP lblInternalRef }; ``` @@ -108,12 +108,12 @@ ALTER PAGE CRM.Customer_List { -- Remove a column ALTER PAGE CRM.Customer_List { - DROP WIDGET dgCustomers.OldNotes + DROP dgCustomers.OldNotes }; -- Rename a column header ALTER PAGE CRM.Customer_List { - SET Caption = 'E-mail Address' ON dgCustomers.Email + SET (Caption: 'E-mail Address') ON dgCustomers.Email }; ``` @@ -123,7 +123,7 @@ Use `DESCRIBE PAGE CRM.Customer_List` to discover column names. ```sql ALTER SNIPPET CRM.NavigationMenu { - SET Caption = 'Dashboard' ON btnHome; + SET (Caption: 'Dashboard') ON btnHome; INSERT AFTER btnHome { ACTIONBUTTON btnReports ( Caption: 'Reports', diff --git a/docs-site/src/language/alter-entity.md b/docs-site/src/language/alter-entity.md index e554339c0b..f436111636 100644 --- a/docs-site/src/language/alter-entity.md +++ b/docs-site/src/language/alter-entity.md @@ -49,10 +49,10 @@ a clause written where the type belongs is read *as* the type: ```mdl -- WRONG: `SET` is read as the type name, not as a keyword -ALTER ENTITY Sales.Customer MODIFY ATTRIBUTE Discount SET DEFAULT 0; +ALTER ENTITY Sales.Customer MODIFY ATTRIBUTE Discount: SET DEFAULT 0; -- Right: restate the type -ALTER ENTITY Sales.Customer MODIFY ATTRIBUTE Discount Decimal DEFAULT 0; +ALTER ENTITY Sales.Customer MODIFY ATTRIBUTE Discount: Decimal DEFAULT 0; ``` mxcli refuses the first form and names the alternatives. Before it did, that diff --git a/docs-site/src/language/project-settings.md b/docs-site/src/language/project-settings.md index 661230d847..da6068d8a7 100644 --- a/docs-site/src/language/project-settings.md +++ b/docs-site/src/language/project-settings.md @@ -21,15 +21,15 @@ Settings are organized into categories. Each `ALTER SETTINGS` command targets on Runtime-level settings such as the after-startup microflow, hashing algorithm, and Java version: ```sql -ALTER SETTINGS RUNTIME = ; +ALTER SETTINGS RUNTIME ( : , ... ); ``` Examples: ```sql -ALTER SETTINGS RUNTIME AfterStartupMicroflow = 'MyModule.ACT_Startup'; -ALTER SETTINGS RUNTIME HashAlgorithm = 'BCrypt'; -ALTER SETTINGS RUNTIME JavaVersion = '17'; +ALTER SETTINGS RUNTIME ( AfterStartupMicroflow: 'MyModule.ACT_Startup' ); +ALTER SETTINGS RUNTIME ( HashAlgorithm: 'BCrypt' ); +ALTER SETTINGS RUNTIME ( JavaVersion: '17' ); ``` Mendix renamed the Java version property between versions — up to 11.6 it is stored @@ -42,15 +42,15 @@ project already uses. Server configuration settings like database type, URL, and HTTP port. Each configuration is identified by name (commonly `'default'`): ```sql -ALTER SETTINGS CONFIGURATION '' = ; +ALTER SETTINGS CONFIGURATION '' ( : , ... ); ``` Examples: ```sql -ALTER SETTINGS CONFIGURATION 'default' DatabaseType = 'POSTGRESQL'; -ALTER SETTINGS CONFIGURATION 'default' DatabaseUrl = 'jdbc:postgresql://localhost:5432/myapp'; -ALTER SETTINGS CONFIGURATION 'default' HttpPortNumber = '8080'; +ALTER SETTINGS CONFIGURATION 'default' ( DatabaseType: 'POSTGRESQL' ); +ALTER SETTINGS CONFIGURATION 'default' ( DatabaseUrl: 'jdbc:postgresql://localhost:5432/myapp' ); +ALTER SETTINGS CONFIGURATION 'default' ( HttpPortNumber: '8080' ); ``` ### Constant Overrides @@ -75,7 +75,7 @@ for. A translation written for any other language is stored in the model, passes the step that makes translating an app do anything. ```sql -ALTER SETTINGS LANGUAGE = ; +ALTER SETTINGS LANGUAGE ( : , ... ); ALTER SETTINGS LANGUAGE ADD [OR MODIFY] '' [(