Skip to content

Commit dc0907a

Browse files
akoclaude
andcommitted
feat: add CREATE/DROP CONFIGURATION and DROP constant override
Add three new commands for configuration management: - CREATE CONFIGURATION 'Name' [Key = Value, ...] — new server config - DROP CONFIGURATION 'Name' — remove a server configuration - ALTER SETTINGS DROP CONSTANT 'Name' IN CONFIGURATION 'cfg' — remove a constant override (reset to default value) Full pipeline: grammar → parser → AST → visitor → executor. Updated help topics, quick reference, language reference, site docs, and skills. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent aa93097 commit dc0907a

File tree

16 files changed

+8096
-7434
lines changed

16 files changed

+8096
-7434
lines changed

.claude/skills/mendix/project-settings.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,25 @@ ALTER SETTINGS CONSTANT 'BusinessEvents.ServerUrl' VALUE 'kafka:9092'
6767

6868
-- Without IN CONFIGURATION (uses first configuration)
6969
ALTER SETTINGS CONSTANT 'MyModule.ApiKey' VALUE 'abc123';
70+
71+
-- Remove a constant override (reset to default)
72+
ALTER SETTINGS DROP CONSTANT 'MyModule.ApiKey' IN CONFIGURATION 'Default';
73+
```
74+
75+
### Create / Drop Configurations
76+
77+
```sql
78+
-- Create a new server configuration
79+
CREATE CONFIGURATION 'Staging';
80+
81+
-- Create with properties
82+
CREATE CONFIGURATION 'Production'
83+
DatabaseType = 'POSTGRESQL',
84+
DatabaseUrl = 'prod-db:5432',
85+
HttpPortNumber = 8080;
86+
87+
-- Drop a configuration
88+
DROP CONFIGURATION 'Staging';
7089
```
7190

7291
### Language and Workflow Settings

cmd/mxcli/help_topics/constant.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ Show constant values across configurations:
2424
SHOW CONSTANT VALUES; -- All constants with per-config overrides
2525
SHOW CONSTANT VALUES IN MyModule; -- Filter by module
2626

27+
Remove a constant override from a configuration:
28+
ALTER SETTINGS DROP CONSTANT 'Module.Name' IN CONFIGURATION 'cfg';
29+
2730
Describe a constant:
2831
DESCRIBE CONSTANT Module.Name;
2932

cmd/mxcli/help_topics/settings.txt

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,21 @@ ALTER SETTINGS (Constant Overrides)
3434
ALTER SETTINGS CONSTANT 'BusinessEvents.ServerUrl' VALUE 'kafka:9092'
3535
IN CONFIGURATION 'Default';
3636

37+
ALTER SETTINGS DROP CONSTANT 'BusinessEvents.ServerUrl'
38+
IN CONFIGURATION 'Default'; -- Remove override (reset to default)
39+
40+
CREATE / DROP CONFIGURATION
41+
----------------------------
42+
43+
CREATE CONFIGURATION 'Staging'; -- Create with defaults
44+
45+
CREATE CONFIGURATION 'Production'
46+
DatabaseType = 'POSTGRESQL',
47+
DatabaseUrl = 'prod-db:5432',
48+
HttpPortNumber = 8080; -- Create with properties
49+
50+
DROP CONFIGURATION 'Staging'; -- Remove a configuration
51+
3752
ALTER SETTINGS (Language / Workflows)
3853
-------------------------------------
3954

docs-site/src/reference/settings/alter-settings.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,12 @@
88

99
ALTER SETTINGS CONSTANT 'name' VALUE 'value' IN CONFIGURATION 'config'
1010

11+
ALTER SETTINGS DROP CONSTANT 'name' IN CONFIGURATION 'config'
12+
13+
CREATE CONFIGURATION 'name' [key = value, ...]
14+
15+
DROP CONFIGURATION 'name'
16+
1117
ALTER SETTINGS LANGUAGE key = value
1218

1319
ALTER SETTINGS WORKFLOWS key = value
@@ -84,6 +90,27 @@ ALTER SETTINGS WORKFLOWS UserEntity = 'Administration.Account';
8490
ALTER SETTINGS MODEL JavaVersion = '17';
8591
```
8692

93+
### Remove a constant override from a configuration
94+
95+
```sql
96+
ALTER SETTINGS DROP CONSTANT 'MyModule.ApiBaseUrl' IN CONFIGURATION 'staging';
97+
```
98+
99+
### Create a new configuration
100+
101+
```sql
102+
CREATE CONFIGURATION 'Staging'
103+
DatabaseType = 'POSTGRESQL',
104+
DatabaseUrl = 'staging-db:5432',
105+
HttpPortNumber = 8080;
106+
```
107+
108+
### Drop a configuration
109+
110+
```sql
111+
DROP CONFIGURATION 'Staging';
112+
```
113+
87114
## See Also
88115

89116
[SHOW / DESCRIBE SETTINGS](show-settings.md)

docs/01-project/MDL_QUICK_REFERENCE.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,9 @@ CREATE OR REPLACE NAVIGATION Responsive
293293
| Alter model settings | `ALTER SETTINGS MODEL Key = Value;` | AfterStartupMicroflow, HashAlgorithm, JavaVersion, etc. |
294294
| Alter configuration | `ALTER SETTINGS CONFIGURATION 'Name' Key = Value;` | DatabaseType, DatabaseUrl, HttpPortNumber, etc. |
295295
| Alter constant | `ALTER SETTINGS CONSTANT 'Name' VALUE 'val' IN CONFIGURATION 'cfg';` | Override constant per configuration |
296+
| Drop constant override | `ALTER SETTINGS DROP CONSTANT 'Name' IN CONFIGURATION 'cfg';` | Reset to default value |
297+
| Create configuration | `CREATE CONFIGURATION 'Name' [Key = Value, ...];` | New server configuration |
298+
| Drop configuration | `DROP CONFIGURATION 'Name';` | Remove a configuration |
296299
| Alter language | `ALTER SETTINGS LANGUAGE Key = Value;` | DefaultLanguageCode |
297300
| Alter workflows | `ALTER SETTINGS WORKFLOWS Key = Value;` | UserEntity, DefaultTaskParallelism |
298301

docs/05-mdl-specification/01-language-reference.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1177,10 +1177,18 @@ Displays one row per constant per configuration. Shows the default value followe
11771177
ALTER SETTINGS MODEL Key = Value;
11781178
ALTER SETTINGS CONFIGURATION 'Name' Key = Value;
11791179
ALTER SETTINGS CONSTANT 'Name' VALUE 'val' IN CONFIGURATION 'cfg';
1180+
ALTER SETTINGS DROP CONSTANT 'Name' IN CONFIGURATION 'cfg';
11801181
ALTER SETTINGS LANGUAGE Key = Value;
11811182
ALTER SETTINGS WORKFLOWS Key = Value;
11821183
```
11831184

1185+
### CREATE / DROP CONFIGURATION
1186+
1187+
```sql
1188+
CREATE CONFIGURATION 'Name' [Key = Value, ...];
1189+
DROP CONFIGURATION 'Name';
1190+
```
1191+
11841192
**Example:**
11851193
```sql
11861194
ALTER SETTINGS MODEL AfterStartupMicroflow = 'MyModule.ACT_Startup';
@@ -1189,6 +1197,15 @@ ALTER SETTINGS LANGUAGE DefaultLanguageCode = 'en_US';
11891197

11901198
-- View constant values across all configurations
11911199
SHOW CONSTANT VALUES;
1200+
1201+
-- Create a new configuration
1202+
CREATE CONFIGURATION 'Staging' DatabaseType = 'POSTGRESQL', DatabaseUrl = 'staging-db:5432';
1203+
1204+
-- Remove a constant override
1205+
ALTER SETTINGS DROP CONSTANT 'MyModule.ApiKey' IN CONFIGURATION 'Default';
1206+
1207+
-- Drop a configuration
1208+
DROP CONFIGURATION 'Staging';
11921209
```
11931210

11941211
---

mdl/ast/ast_settings.go

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,24 @@ type AlterSettingsStmt struct {
88
ConfigName string // For CONFIGURATION section: the configuration name (e.g., "Default")
99
Properties map[string]any // Key-value pairs to set
1010
// For CONSTANT section:
11-
ConstantId string // Qualified constant name
12-
Value string // Constant value
11+
ConstantId string // Qualified constant name
12+
Value string // Constant value
13+
DropConstant bool // If true, remove the constant override instead of setting it
1314
}
1415

1516
func (s *AlterSettingsStmt) isStatement() {}
17+
18+
// CreateConfigurationStmt represents CREATE CONFIGURATION 'name' [properties...].
19+
type CreateConfigurationStmt struct {
20+
Name string
21+
Properties map[string]any
22+
}
23+
24+
func (s *CreateConfigurationStmt) isStatement() {}
25+
26+
// DropConfigurationStmt represents DROP CONFIGURATION 'name'.
27+
type DropConfigurationStmt struct {
28+
Name string
29+
}
30+
31+
func (s *DropConfigurationStmt) isStatement() {}

mdl/executor/cmd_settings.go

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,22 @@ func (e *Executor) alterSettingsConstant(ps *model.ProjectSettings, stmt *ast.Al
348348
return fmt.Errorf("configuration not found: %s", targetConfig)
349349
}
350350

351+
if stmt.DropConstant {
352+
// Remove the constant override
353+
for i, cv := range cfg.ConstantValues {
354+
if cv.ConstantId == stmt.ConstantId {
355+
cfg.ConstantValues = append(cfg.ConstantValues[:i], cfg.ConstantValues[i+1:]...)
356+
if err := e.writer.UpdateProjectSettings(ps); err != nil {
357+
return fmt.Errorf("failed to update project settings: %w", err)
358+
}
359+
fmt.Fprintf(e.output, "Dropped constant '%s' from configuration '%s'\n",
360+
stmt.ConstantId, targetConfig)
361+
return nil
362+
}
363+
}
364+
return fmt.Errorf("constant '%s' not found in configuration '%s'", stmt.ConstantId, targetConfig)
365+
}
366+
351367
// Find or create the constant value
352368
found := false
353369
for _, cv := range cfg.ConstantValues {
@@ -375,6 +391,107 @@ func (e *Executor) alterSettingsConstant(ps *model.ProjectSettings, stmt *ast.Al
375391
return nil
376392
}
377393

394+
// createConfiguration handles CREATE CONFIGURATION 'name' [properties...].
395+
func (e *Executor) createConfiguration(stmt *ast.CreateConfigurationStmt) error {
396+
if e.writer == nil {
397+
return fmt.Errorf("not connected in write mode")
398+
}
399+
400+
ps, err := e.reader.GetProjectSettings()
401+
if err != nil {
402+
return fmt.Errorf("failed to read project settings: %w", err)
403+
}
404+
405+
if ps.Configuration == nil {
406+
return fmt.Errorf("configuration settings not found in project")
407+
}
408+
409+
// Check if configuration already exists
410+
for _, cfg := range ps.Configuration.Configurations {
411+
if strings.EqualFold(cfg.Name, stmt.Name) {
412+
return fmt.Errorf("configuration already exists: %s", stmt.Name)
413+
}
414+
}
415+
416+
newCfg := &model.ServerConfiguration{
417+
Name: stmt.Name,
418+
DatabaseType: "HSQLDB",
419+
HttpPortNumber: 8080,
420+
ConstantValues: []*model.ConstantValue{},
421+
}
422+
newCfg.TypeName = "Settings$ServerConfiguration"
423+
424+
// Apply optional properties
425+
for key, val := range stmt.Properties {
426+
valStr := settingsValueToString(val)
427+
switch key {
428+
case "DatabaseType":
429+
newCfg.DatabaseType = valStr
430+
case "DatabaseUrl":
431+
newCfg.DatabaseUrl = valStr
432+
case "DatabaseName":
433+
newCfg.DatabaseName = valStr
434+
case "DatabaseUserName":
435+
newCfg.DatabaseUserName = valStr
436+
case "DatabasePassword":
437+
newCfg.DatabasePassword = valStr
438+
case "HttpPortNumber":
439+
if v, err := strconv.Atoi(valStr); err == nil {
440+
newCfg.HttpPortNumber = v
441+
}
442+
case "ServerPortNumber":
443+
if v, err := strconv.Atoi(valStr); err == nil {
444+
newCfg.ServerPortNumber = v
445+
}
446+
case "ApplicationRootUrl":
447+
newCfg.ApplicationRootUrl = valStr
448+
default:
449+
return fmt.Errorf("unknown configuration property: %s", key)
450+
}
451+
}
452+
453+
ps.Configuration.Configurations = append(ps.Configuration.Configurations, newCfg)
454+
455+
if err := e.writer.UpdateProjectSettings(ps); err != nil {
456+
return fmt.Errorf("failed to update project settings: %w", err)
457+
}
458+
459+
fmt.Fprintf(e.output, "Created configuration: %s\n", stmt.Name)
460+
return nil
461+
}
462+
463+
// dropConfiguration handles DROP CONFIGURATION 'name'.
464+
func (e *Executor) dropConfiguration(stmt *ast.DropConfigurationStmt) error {
465+
if e.writer == nil {
466+
return fmt.Errorf("not connected in write mode")
467+
}
468+
469+
ps, err := e.reader.GetProjectSettings()
470+
if err != nil {
471+
return fmt.Errorf("failed to read project settings: %w", err)
472+
}
473+
474+
if ps.Configuration == nil {
475+
return fmt.Errorf("configuration settings not found in project")
476+
}
477+
478+
for i, cfg := range ps.Configuration.Configurations {
479+
if strings.EqualFold(cfg.Name, stmt.Name) {
480+
ps.Configuration.Configurations = append(
481+
ps.Configuration.Configurations[:i],
482+
ps.Configuration.Configurations[i+1:]...,
483+
)
484+
if err := e.writer.UpdateProjectSettings(ps); err != nil {
485+
return fmt.Errorf("failed to update project settings: %w", err)
486+
}
487+
fmt.Fprintf(e.output, "Dropped configuration: %s\n", stmt.Name)
488+
return nil
489+
}
490+
}
491+
492+
return fmt.Errorf("configuration not found: %s", stmt.Name)
493+
}
494+
378495
// settingsValueToString converts an AST settings value to string.
379496
func settingsValueToString(val any) string {
380497
switch v := val.(type) {

mdl/executor/executor.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,10 @@ func (e *Executor) executeInner(stmt ast.Statement) error {
295295
// Settings statements
296296
case *ast.AlterSettingsStmt:
297297
return e.alterSettings(s)
298+
case *ast.CreateConfigurationStmt:
299+
return e.createConfiguration(s)
300+
case *ast.DropConfigurationStmt:
301+
return e.dropConfiguration(s)
298302

299303
// OData statements
300304
case *ast.CreateODataClientStmt:

mdl/grammar/MDLParser.g4

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ createStatement
9898
| createUserRoleStatement
9999
| createDemoUserStatement
100100
| createImageCollectionStatement
101+
| createConfigurationStatement
101102
)
102103
;
103104

@@ -251,6 +252,7 @@ dropStatement
251252
| DROP WORKFLOW qualifiedName
252253
| DROP IMAGE COLLECTION qualifiedName
253254
| DROP REST CLIENT qualifiedName
255+
| DROP CONFIGURATION STRING_LITERAL
254256
| DROP FOLDER STRING_LITERAL IN (qualifiedName | IDENTIFIER)
255257
;
256258

@@ -2014,6 +2016,11 @@ constantOption
20142016
| EXPOSED TO CLIENT
20152017
;
20162018

2019+
createConfigurationStatement
2020+
: CONFIGURATION STRING_LITERAL
2021+
(settingsAssignment (COMMA settingsAssignment)*)?
2022+
;
2023+
20172024
/**
20182025
* CREATE REST CLIENT Module.Name
20192026
* BASE URL 'https://api.example.com/v1'
@@ -2397,7 +2404,8 @@ workflowAnnotationStmt
23972404
*/
23982405
alterSettingsClause
23992406
: settingsSection settingsAssignment (COMMA settingsAssignment)*
2400-
| CONSTANT STRING_LITERAL VALUE settingsValue (IN CONFIGURATION STRING_LITERAL)?
2407+
| CONSTANT STRING_LITERAL (VALUE settingsValue | DROP) (IN CONFIGURATION STRING_LITERAL)?
2408+
| DROP CONSTANT STRING_LITERAL (IN CONFIGURATION STRING_LITERAL)?
24012409
| CONFIGURATION STRING_LITERAL settingsAssignment (COMMA settingsAssignment)*
24022410
;
24032411

0 commit comments

Comments
 (0)