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
44 changes: 44 additions & 0 deletions oracle/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -424,6 +424,50 @@ func writeQuotedIdentifier(builder *strings.Builder, identifier string) {
builder.WriteByte('"')
}

// writeTableRecordCollectionDecl writes the PL/SQL declarations needed to
// define a custom record type and a collection of that record type,
// based on the schema of the given table.
//
// Specifically, it generates:
// - A RECORD type (`t_record`) with fields corresponding to the table's columns.
// - A nested TABLE type (`t_records`) of `t_record`.
//
// The declarations are written into the provided strings.Builder in the
// correct PL/SQL syntax, so they can be used as part of a larger PL/SQL block.
//
// Example output:
//
// TYPE t_record IS RECORD (
// "id" "users"."id"%TYPE,
// "created_at" "users"."created_at"%TYPE,
// ...
// );
// TYPE t_records IS TABLE OF t_record;
//
// Parameters:
// - plsqlBuilder: The builder to write the PL/SQL code into.
// - dbNames: The slice containing the column names.
// - table: The table name
func writeTableRecordCollectionDecl(plsqlBuilder *strings.Builder, dbNames []string, table string) {
// Declare a record where each element has the same structure as a row from the given table
plsqlBuilder.WriteString(" TYPE t_record IS RECORD (\n")
for i, field := range dbNames {
if i > 0 {
plsqlBuilder.WriteString(",\n")
}
plsqlBuilder.WriteString(" ")
writeQuotedIdentifier(plsqlBuilder, field)
plsqlBuilder.WriteString(" ")
writeQuotedIdentifier(plsqlBuilder, table)
plsqlBuilder.WriteString(".")
writeQuotedIdentifier(plsqlBuilder, field)
plsqlBuilder.WriteString("%TYPE")
}
plsqlBuilder.WriteString("\n")
plsqlBuilder.WriteString(" );\n")
plsqlBuilder.WriteString(" TYPE t_records IS TABLE OF t_record;\n")
}

// Helper function to check if a value represents NULL
func isNullValue(value interface{}) bool {
if value == nil {
Expand Down
8 changes: 2 additions & 6 deletions oracle/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -285,9 +285,7 @@ func buildBulkMergePLSQL(db *gorm.DB, createValues clause.Values, onConflictClau

// Start PL/SQL block
plsqlBuilder.WriteString("DECLARE\n")
plsqlBuilder.WriteString(" TYPE t_records IS TABLE OF ")
writeQuotedIdentifier(&plsqlBuilder, stmt.Table)
plsqlBuilder.WriteString("%ROWTYPE;\n")
writeTableRecordCollectionDecl(&plsqlBuilder, stmt.Schema.DBNames, stmt.Table)
plsqlBuilder.WriteString(" l_affected_records t_records;\n")

// Create array types and variables for each column
Expand Down Expand Up @@ -526,9 +524,7 @@ func buildBulkInsertOnlyPLSQL(db *gorm.DB, createValues clause.Values) {

// Start PL/SQL block
plsqlBuilder.WriteString("DECLARE\n")
plsqlBuilder.WriteString(" TYPE t_records IS TABLE OF ")
writeQuotedIdentifier(&plsqlBuilder, stmt.Table)
plsqlBuilder.WriteString("%ROWTYPE;\n")
writeTableRecordCollectionDecl(&plsqlBuilder, stmt.Schema.DBNames, stmt.Table)
plsqlBuilder.WriteString(" l_inserted_records t_records;\n")

// Create array types and variables for each column
Expand Down
4 changes: 1 addition & 3 deletions oracle/delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -239,9 +239,7 @@ func buildBulkDeletePLSQL(db *gorm.DB) {

// Start PL/SQL block
plsqlBuilder.WriteString("DECLARE\n")
plsqlBuilder.WriteString(" TYPE t_records IS TABLE OF ")
writeQuotedIdentifier(&plsqlBuilder, stmt.Table)
plsqlBuilder.WriteString("%ROWTYPE;\n")
writeTableRecordCollectionDecl(&plsqlBuilder, stmt.Schema.DBNames, stmt.Table)
plsqlBuilder.WriteString(" l_deleted_records t_records;\n")
plsqlBuilder.WriteString("BEGIN\n")

Expand Down
4 changes: 1 addition & 3 deletions oracle/update.go
Original file line number Diff line number Diff line change
Expand Up @@ -476,9 +476,7 @@ func buildUpdatePLSQL(db *gorm.DB) {

// Start PL/SQL block
plsqlBuilder.WriteString("DECLARE\n")
plsqlBuilder.WriteString(" TYPE t_records IS TABLE OF ")
writeQuotedIdentifier(&plsqlBuilder, stmt.Table)
plsqlBuilder.WriteString("%ROWTYPE;\n")
writeTableRecordCollectionDecl(&plsqlBuilder, stmt.Schema.DBNames, stmt.Table)
plsqlBuilder.WriteString(" l_updated_records t_records;\n")
plsqlBuilder.WriteString("BEGIN\n")

Expand Down
7 changes: 3 additions & 4 deletions tests/gorm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ func TestOpen(t *testing.T) {
}

func TestReturningWithNullToZeroValues(t *testing.T) {
t.Skip()
// This user struct will leverage the existing users table, but override
// the Name field to default to null.
type user struct {
Expand All @@ -72,7 +71,7 @@ func TestReturningWithNullToZeroValues(t *testing.T) {
}

got := user{}
results := DB.First(&got, "id = ?", u1.ID)
results := DB.First(&got, "\"id\" = ?", u1.ID)
if results.Error != nil {
t.Fatalf("errors happened on first: %v", results.Error)
} else if results.RowsAffected != 1 {
Expand All @@ -81,7 +80,7 @@ func TestReturningWithNullToZeroValues(t *testing.T) {
t.Fatalf("first expects: %v, got %v", u1, got)
}

results = DB.Select("id, name").Find(&got)
results = DB.Select("\"id\", \"name\"").Find(&got)
if results.Error != nil {
t.Fatalf("errors happened on first: %v", results.Error)
} else if results.RowsAffected != 1 {
Expand Down Expand Up @@ -112,7 +111,7 @@ func TestReturningWithNullToZeroValues(t *testing.T) {
}

var gotUsers []user
results = DB.Where("id in (?, ?)", u1.ID, u2.ID).Order("id asc").Select("id, name").Find(&gotUsers)
results = DB.Where("\"id\" in (?, ?)", u1.ID, u2.ID).Order("\"id\" asc").Select("\"id\", \"name\"").Find(&gotUsers)
if results.Error != nil {
t.Fatalf("errors happened on first: %v", results.Error)
} else if results.RowsAffected != 2 {
Expand Down
2 changes: 1 addition & 1 deletion tests/passed-tests.txt
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ TestGenericsReuse
TestGenericsWithTransaction
TestGenericsToSQL
TestOpen
#TestReturningWithNullToZeroValues
TestReturningWithNullToZeroValues
TestGroupBy
TestRunCallbacks
TestCallbacksWithErrors
Expand Down
Loading