Skip to content

Commit

Permalink
Merge pull request #61 from hasathcharu/main
Browse files Browse the repository at this point in the history
Fix issues in annotations with MSSQL and PostgreSQL databases
  • Loading branch information
daneshk committed Mar 20, 2024
2 parents 4b8c6cc + 2baa56b commit 4d37e2f
Show file tree
Hide file tree
Showing 16 changed files with 2,376 additions and 58 deletions.
6 changes: 5 additions & 1 deletion ballerina/metadata_types.bal
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,10 @@ public type EntityFieldMetadata record {|
# Represents the metadata associated with a simple field in the entity record.
#
# + columnName - The name of the SQL table column to which the field is mapped
# + dbGenerated - Whether the field is generated by the database
public type SimpleFieldMetadata record {|
string columnName;
boolean dbGenerated = false;
|};

# Represents the metadata associated with a field of an entity.
Expand All @@ -52,11 +54,13 @@ public type FieldMetadata SimpleFieldMetadata|EntityFieldMetadata;
# Only used by the generated persist clients and `persist:SQLClient`.
#
# + entityName - The name of the entity represented in the relation
# + refField - The name of the referenced column in the SQL table
# + refField - The name of the field in the entity that is being referenced
# + refColumn - The name of the column in the SQL table that is being referenced. If this is not provided, the `refField` is used as the `refColumn`

public type RelationMetadata record {|
string entityName;
string refField;
string? refColumn = ();
|};

# Represents the metadata associated with performing an SQL `JOIN` operation.
Expand Down
8 changes: 5 additions & 3 deletions ballerina/sql_client.bal
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,8 @@ public isolated client class SQLClient {
columnNames.push(self.escape(self.entityName) + "." + self.escape(fieldMetadata.columnName) + " AS " + self.escape(key));
} else {
// column is in another entity's table
columnNames.push(self.escape(fieldName) + "." + self.escape(fieldMetadata.relation.refField) + " AS " + self.escape(fieldName + "." + fieldMetadata.relation.refField));
columnNames.push(self.escape(fieldName) + "." + self.escape(fieldMetadata.relation.refColumn ?: fieldMetadata.relation.refField) + " AS " + self.escape(fieldName + "." + fieldMetadata.relation.refField));

}

}
Expand All @@ -313,7 +314,7 @@ public isolated client class SQLClient {
continue;
}

string columnName = fieldMetadata.relation.refField;
string columnName = fieldMetadata.relation.refColumn ?: fieldMetadata.relation.refField;
columnNames.push(self.escape(columnName));
}
return arrayToParameterizedQuery(columnNames);
Expand Down Expand Up @@ -478,7 +479,8 @@ public isolated client class SQLClient {

private isolated function getInsertableFields() returns string[] {
return from string key in self.fieldMetadata.keys()
where self.fieldMetadata.get(key) is SimpleFieldMetadata
let FieldMetadata metadataField = self.fieldMetadata.get(key)
where metadataField is SimpleFieldMetadata && !metadataField.dbGenerated
select key;
}

Expand Down
143 changes: 143 additions & 0 deletions ballerina/tests/hospital_persist_types.bal
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
// Copyright (c) 2024 WSO2 LLC. (http://www.wso2.com).
//
// 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.

// AUTO-GENERATED FILE. DO NOT MODIFY.
// This file is an auto-generated file by Ballerina persistence layer for model.
// It should not be modified by hand.
import ballerina/time;

public enum AppointmentStatus {
SCHEDULED = "SCHEDULED",
STARTED = "STARTED",
ENDED = "ENDED"
}

public enum PatientGender {
MALE = "MALE",
FEMALE = "FEMALE"
}

public type Appointment record {|
readonly int id;
string reason;
time:Civil appointmentTime;
AppointmentStatus status;
int patientId;
int doctorId;
|};

public type AppointmentOptionalized record {|
int id?;
string reason?;
time:Civil appointmentTime?;
AppointmentStatus status?;
int patientId?;
int doctorId?;
|};

public type AppointmentWithRelations record {|
*AppointmentOptionalized;
PatientOptionalized patient?;
DoctorOptionalized doctor?;
|};

public type AppointmentTargetType typedesc<AppointmentWithRelations>;

public type AppointmentInsert Appointment;

public type AppointmentUpdate record {|
string reason?;
time:Civil appointmentTime?;
AppointmentStatus status?;
int patientId?;
int doctorId?;
|};

public type Patient record {|
readonly int id;
string name;
int age;
string address;
string phoneNumber;
PatientGender gender;

|};

public type PatientOptionalized record {|
int id?;
string name?;
int age?;
string address?;
string phoneNumber?;
PatientGender gender?;
|};

public type PatientWithRelations record {|
*PatientOptionalized;
AppointmentOptionalized[] appointments?;
|};

public type PatientTargetType typedesc<PatientWithRelations>;

public type PatientInsert record {|
string name;
int age;
string address;
string phoneNumber;
PatientGender gender;
|};

public type PatientUpdate record {|
string name?;
int age?;
string address?;
string phoneNumber?;
PatientGender gender?;
|};

public type Doctor record {|
readonly int id;
string name;
string specialty;
string phoneNumber;
decimal? salary;

|};

public type DoctorOptionalized record {|
int id?;
string name?;
string specialty?;
string phoneNumber?;
decimal? salary?;
|};

public type DoctorWithRelations record {|
*DoctorOptionalized;
AppointmentOptionalized[] appointments?;
|};

public type DoctorTargetType typedesc<DoctorWithRelations>;

public type DoctorInsert Doctor;

public type DoctorUpdate record {|
string name?;
string specialty?;
string phoneNumber?;
decimal? salary?;
|};

37 changes: 37 additions & 0 deletions ballerina/tests/init-tests.bal
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,9 @@ function initMySqlTests() returns error? {
_ = check mysqlDbClient->execute(`TRUNCATE IntIdRecord`);
_ = check mysqlDbClient->execute(`TRUNCATE AllTypesIdRecord`);
_ = check mysqlDbClient->execute(`TRUNCATE CompositeAssociationRecord`);
_ = check mysqlDbClient->execute(`TRUNCATE Doctor`);
_ = check mysqlDbClient->execute(`TRUNCATE appointment`);
_ = check mysqlDbClient->execute(`TRUNCATE patients`);
_ = check mysqlDbClient->execute(`SET FOREIGN_KEY_CHECKS = 1`);
check mysqlDbClient.close();
}
Expand Down Expand Up @@ -232,6 +235,40 @@ function initMsSqlTests() returns error? {
PRIMARY KEY(id)
);
`);
_ = check mssqlDbClient->execute(`
CREATE TABLE [Doctor] (
[id] INT NOT NULL,
[name] VARCHAR(191) NOT NULL,
[specialty] VARCHAR(191) NOT NULL,
[phone_number] VARCHAR(191) NOT NULL,
[salary] DECIMAL(10,2),
PRIMARY KEY([id])
);
`);
_ = check mssqlDbClient->execute(`
CREATE TABLE [patients] (
[IDP] INT IDENTITY(1,1),
[name] VARCHAR(191) NOT NULL,
[age] INT NOT NULL,
[ADD_RESS] VARCHAR(191) NOT NULL,
[phoneNumber] CHAR(10) NOT NULL,
[gender] VARCHAR(6) CHECK ([gender] IN ('MALE', 'FEMALE')) NOT NULL,
PRIMARY KEY([IDP])
);
`);
_ = check mssqlDbClient->execute(`
CREATE TABLE [appointment] (
[id] INT NOT NULL,
[reason] VARCHAR(191) NOT NULL,
[appointmentTime] DATETIME2 NOT NULL,
[status] VARCHAR(9) CHECK ([status] IN ('SCHEDULED', 'STARTED', 'ENDED')) NOT NULL,
[patient_id] INT NOT NULL,
FOREIGN KEY([patient_id]) REFERENCES [patients]([IDP]),
[doctorId] INT NOT NULL,
FOREIGN KEY([doctorId]) REFERENCES [Doctor]([id]),
PRIMARY KEY([id])
);
`);
}

function initPostgreSqlTests() returns error? {
Expand Down
Loading

0 comments on commit 4d37e2f

Please sign in to comment.