Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions ballerina/Ballerina.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
org = "ballerina"
name = "persist"
version = "1.6.1"
version = "1.7.0"
authors = ["Ballerina"]
keywords = ["persist"]
repository = "https://github.com/ballerina-platform/module-ballerina-persist"
Expand All @@ -15,5 +15,5 @@ graalvmCompatible = true
[[platform.java21.dependency]]
groupId = "io.ballerina.stdlib"
artifactId = "persist-native"
version = "1.6.1"
path = "../native/build/libs/persist-native-1.6.1-SNAPSHOT.jar"
version = "1.7.0"
path = "../native/build/libs/persist-native-1.7.0-SNAPSHOT.jar"
2 changes: 1 addition & 1 deletion ballerina/CompilerPlugin.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ id = "persist-compiler-plugin"
class = "io.ballerina.stdlib.persist.compiler.PersistCompilerPlugin"

[[dependency]]
path = "../compiler-plugin/build/libs/persist-compiler-plugin-1.6.1-SNAPSHOT.jar"
path = "../compiler-plugin/build/libs/persist-compiler-plugin-1.7.0-SNAPSHOT.jar"
2 changes: 1 addition & 1 deletion ballerina/Dependencies.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ modules = [
[[package]]
org = "ballerina"
name = "persist"
version = "1.6.1"
version = "1.7.0"
dependencies = [
{org = "ballerina", name = "jballerina.java"}
]
Expand Down
6 changes: 6 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Added

- [Enable persist compiler plugin validations for the new persist multi-model support](https://github.com/ballerina-platform/ballerina-library/issues/8503)

## [1.4.0] - 2024-08-20

### Added
- [Added compiler plugin validations for H2 as a datasource](https://github.com/ballerina-platform/ballerina-library/issues/5715)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -790,6 +790,236 @@ public void validateFieldTypesForRedisDB() {
);
}

// --- Multi-model support tests ---

private Package loadMultiModelPersistFile(String directory, String modelName, String name) {
Path projectDirPath = Paths.get("src", "test", "resources", directory, "persist", modelName)
.toAbsolutePath().resolve(name);
SingleFileProject project = SingleFileProject.load(getEnvironmentBuilder(), projectDirPath);
return project.currentPackage();
}

@Test
public void identifyMultiModelFileSuccess() {
List<Diagnostic> diagnostics = getMultiModelErrorDiagnostics("project_12", "medical",
"valid-persist-model-path.bal", 1);
testDiagnostic(
diagnostics,
new String[]{
PERSIST_101.getCode()
},
new String[]{
"persist model definition only supports record and enum definitions"
},
new String[]{
"(18:0,19:1)"
});
}

@Test
public void identifyMultiModelFileFailure() {
// A file in a non-persist subdirectory should not be identified as a model file
Path projectDirPath = Paths.get("src", "test", "resources", "project_1", "resources").toAbsolutePath()
.resolve("single-bal.bal");
SingleFileProject project = SingleFileProject.load(getEnvironmentBuilder(), projectDirPath);
DiagnosticResult diagnosticResult = project.currentPackage().getCompilation().diagnosticResult();
Assert.assertEquals(diagnosticResult.diagnosticCount(), 0);
}

@Test
public void validateEntityFieldTypeForMysqlMultiModel() {
List<Diagnostic> diagnostics = getMultiModelErrorDiagnostics("project_12", "medical",
"field-types.bal", 10);
testDiagnostic(
diagnostics,
new String[]{
PERSIST_306.getCode(),
PERSIST_305.getCode(),
PERSIST_306.getCode(),
PERSIST_306.getCode(),
PERSIST_305.getCode(),
PERSIST_305.getCode(),
PERSIST_306.getCode(),
PERSIST_305.getCode(),
PERSIST_306.getCode(),
PERSIST_306.getCode(),
},
new String[]{
"an entity does not support boolean array field type",
"an entity does not support json-typed field",
"an entity does not support json array field type",
"an entity does not support time:Civil array field type",
"an entity does not support union-typed field",
"an entity does not support error-typed field",
"an entity does not support error array field type",
"an entity does not support mysql:Client-typed field",
"an entity does not support mysql:Client array field type",
"an entity does not support enum array field type"
},
new String[]{
"(34:4,34:13)",
"(36:4,36:8)",
"(37:4,37:10)",
"(40:4,40:16)",
"(41:4,41:21)",
"(43:4,43:9)",
"(44:4,44:11)",
"(46:4,46:16)",
"(47:4,47:18)",
"(50:4,50:12)"
});
}

@Test
public void validateEntityRecordPropertiesMultiModel() {
List<Diagnostic> diagnostics = getMultiModelErrorDiagnostics("project_12", "medical",
"record-properties.bal", 1);
testDiagnostic(
diagnostics,
new String[]{
PERSIST_201.getCode()
},
new String[]{
"an entity should be a closed record"
},
new String[]{
"(33:25,39:1)"
});
}

@Test
public void validateEntityFieldTypeForPostgresqlMultiModelByFilePath() {
List<Diagnostic> diagnostics = getMultiModelErrorDiagnostics("project_13", "inventory",
"field-types.bal", 10);
testDiagnostic(
diagnostics,
new String[]{
PERSIST_306.getCode(),
PERSIST_305.getCode(),
PERSIST_306.getCode(),
PERSIST_306.getCode(),
PERSIST_305.getCode(),
PERSIST_305.getCode(),
PERSIST_306.getCode(),
PERSIST_305.getCode(),
PERSIST_306.getCode(),
PERSIST_306.getCode(),
},
new String[]{
"an entity does not support boolean array field type",
"an entity does not support json-typed field",
"an entity does not support json array field type",
"an entity does not support time:Civil array field type",
"an entity does not support union-typed field",
"an entity does not support error-typed field",
"an entity does not support error array field type",
"an entity does not support mysql:Client-typed field",
"an entity does not support mysql:Client array field type",
"an entity does not support enum array field type"
},
new String[]{
"(34:4,34:13)",
"(36:4,36:8)",
"(37:4,37:10)",
"(40:4,40:16)",
"(41:4,41:21)",
"(43:4,43:9)",
"(44:4,44:11)",
"(46:4,46:16)",
"(47:4,47:18)",
"(50:4,50:12)"
});
}

@Test
public void validateMultiModelIsolationDefaultModel() {
List<Diagnostic> diagnostics = getErrorDiagnostics("project_14", "field-types.bal", 10);
testDiagnostic(
diagnostics,
new String[]{
PERSIST_306.getCode(),
PERSIST_305.getCode(),
PERSIST_306.getCode(),
PERSIST_306.getCode(),
PERSIST_305.getCode(),
PERSIST_305.getCode(),
PERSIST_306.getCode(),
PERSIST_305.getCode(),
PERSIST_306.getCode(),
PERSIST_306.getCode(),
},
new String[]{
"an entity does not support boolean array field type",
"an entity does not support json-typed field",
"an entity does not support json array field type",
"an entity does not support time:Civil array field type",
"an entity does not support union-typed field",
"an entity does not support error-typed field",
"an entity does not support error array field type",
"an entity does not support mysql:Client-typed field",
"an entity does not support mysql:Client array field type",
"an entity does not support enum array field type"
},
new String[]{
"(34:4,34:13)",
"(36:4,36:8)",
"(37:4,37:10)",
"(40:4,40:16)",
"(41:4,41:21)",
"(43:4,43:9)",
"(44:4,44:11)",
"(46:4,46:16)",
"(47:4,47:18)",
"(50:4,50:12)"
});
}

@Test
public void validateMultiModelIsolationNamedModel() {
List<Diagnostic> diagnostics = getMultiModelErrorDiagnostics("project_14", "secondary",
"field-types.bal", 10);
testDiagnostic(
diagnostics,
new String[]{
PERSIST_306.getCode(),
PERSIST_305.getCode(),
PERSIST_306.getCode(),
PERSIST_306.getCode(),
PERSIST_305.getCode(),
PERSIST_305.getCode(),
PERSIST_306.getCode(),
PERSIST_305.getCode(),
PERSIST_306.getCode(),
PERSIST_306.getCode(),
},
new String[]{
"an entity does not support boolean array field type",
"an entity does not support json-typed field",
"an entity does not support json array field type",
"an entity does not support time:Civil array field type",
"an entity does not support union-typed field",
"an entity does not support error-typed field",
"an entity does not support error array field type",
"an entity does not support mysql:Client-typed field",
"an entity does not support mysql:Client array field type",
"an entity does not support enum array field type"
},
new String[]{
"(34:4,34:13)",
"(36:4,36:8)",
"(37:4,37:10)",
"(40:4,40:16)",
"(41:4,41:21)",
"(43:4,43:9)",
"(44:4,44:11)",
"(46:4,46:16)",
"(47:4,47:18)",
"(50:4,50:12)"
});
}

// --- Helper methods ---

private List<Diagnostic> getErrorDiagnostics(String modelDirectory, String modelFileName, int count) {
DiagnosticResult diagnosticResult = loadPersistModelFile(modelDirectory, modelFileName).getCompilation()
.diagnosticResult();
Expand All @@ -799,6 +1029,18 @@ private List<Diagnostic> getErrorDiagnostics(String modelDirectory, String model
return errorDiagnosticsList;
}

private List<Diagnostic> getMultiModelErrorDiagnostics(String projectDirectory, String modelName,
String modelFileName, int count) {
DiagnosticResult diagnosticResult = loadMultiModelPersistFile(projectDirectory, modelName,
modelFileName)
.getCompilation().diagnosticResult();
List<Diagnostic> errorDiagnosticsList = diagnosticResult.diagnostics().stream()
.filter(r -> r.diagnosticInfo().severity().equals(DiagnosticSeverity.ERROR))
.collect(Collectors.toList());
Assert.assertEquals(errorDiagnosticsList.size(), count);
return errorDiagnosticsList;
}


private void testDiagnostic(List<Diagnostic> errorDiagnosticsList, String[] codes, String[] messages,
String[] locations) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[package]
org = "root"
name = "project_12"
version = "0.1.0"

[[tool.persist]]
model = "medical"
options.datastore = "mysql"
filePath = "persist/medical/model.bal"
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// Copyright (c) 2026 WSO2 LLC. (http://www.wso2.org)
//
// WSO2 LLC. licenses this file to you under the Apache License,
// Version 2.0 (the "License"); you may not use this file except
// in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.

import ballerina/persist as _;
import ballerina/time;
import ballerinax/mysql;

public enum Gender {
M,
F
}

public type MedicalNeed record {|
readonly int needId;
boolean booleanTest;
int itemId;
float floatTest;
decimal decimalTest;
string beneficiaryId;
byte[] beneficiaryIdByteArray;

boolean[] booleanArray;

json jsonTest;
json[] jsonArray;

time:Civil period;
time:Civil[] periodArray;
time:Civil|string unionType;

error errorType;
error[] errorArrayType;

mysql:Client clientType;
mysql:Client[] clientArrayType;

Gender gender;
Gender[] genderArray;
|};
Loading