Skip to content

Commit 9cd1710

Browse files
Merge pull request #75 from oracle-samples/joboon-FixPLSQLAutoIncrement
Joboon fix plsql auto increment
2 parents b6b7f5e + e598598 commit 9cd1710

File tree

7 files changed

+114
-9
lines changed

7 files changed

+114
-9
lines changed

oracle/clause_builder.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -503,6 +503,8 @@ func shouldIncludeColumn(stmt *gorm.Statement, columnName string) bool {
503503
stmt.Schema.PrioritizedPrimaryField.AutoIncrement &&
504504
stmt.Schema.PrioritizedPrimaryField.DBName == columnName {
505505
return false
506+
} else if stmt.Schema.LookUpField(columnName).AutoIncrement {
507+
return false
506508
}
507509
return true
508510
}

oracle/create.go

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,8 @@ func buildBulkMergePLSQL(db *gorm.DB, createValues clause.Values, onConflictClau
398398
schema.PrioritizedPrimaryField.AutoIncrement &&
399399
strings.EqualFold(schema.PrioritizedPrimaryField.DBName, column.Name) {
400400
isAutoIncrement = true
401+
} else if stmt.Schema.LookUpField(column.Name).AutoIncrement {
402+
isAutoIncrement = true
401403
}
402404

403405
if !isConflictColumn && !isAutoIncrement {
@@ -520,7 +522,7 @@ func buildBulkMergePLSQL(db *gorm.DB, createValues clause.Values, onConflictClau
520522
" IF l_affected_records.COUNT > %d THEN :%d := l_affected_records(%d).",
521523
rowIdx, outParamIndex+1, rowIdx+1,
522524
))
523-
writeQuotedIdentifier(&plsqlBuilder, column)
525+
db.QuoteTo(&plsqlBuilder, column)
524526
plsqlBuilder.WriteString("; END IF;\n")
525527
} else {
526528
// datatypes.JSON (text-based) -> serialize to CLOB
@@ -529,13 +531,13 @@ func buildBulkMergePLSQL(db *gorm.DB, createValues clause.Values, onConflictClau
529531
" IF l_affected_records.COUNT > %d THEN :%d := JSON_SERIALIZE(l_affected_records(%d).",
530532
rowIdx, outParamIndex+1, rowIdx+1,
531533
))
532-
writeQuotedIdentifier(&plsqlBuilder, column)
534+
db.QuoteTo(&plsqlBuilder, column)
533535
plsqlBuilder.WriteString(" RETURNING CLOB); END IF;\n")
534536
}
535537
} else {
536538
stmt.Vars = append(stmt.Vars, sql.Out{Dest: createTypedDestination(field)})
537539
plsqlBuilder.WriteString(fmt.Sprintf(" IF l_affected_records.COUNT > %d THEN :%d := l_affected_records(%d).", rowIdx, outParamIndex+1, rowIdx+1))
538-
writeQuotedIdentifier(&plsqlBuilder, column)
540+
db.QuoteTo(&plsqlBuilder, column)
539541
plsqlBuilder.WriteString("; END IF;\n")
540542
}
541543
outParamIndex++
@@ -696,6 +698,8 @@ func shouldIncludeColumnInInsert(stmt *gorm.Statement, columnName string) bool {
696698
stmt.Schema.PrioritizedPrimaryField.AutoIncrement &&
697699
strings.EqualFold(stmt.Schema.PrioritizedPrimaryField.DBName, columnName) {
698700
return false
701+
} else if stmt.Schema.LookUpField(columnName).AutoIncrement {
702+
return false
699703
}
700704
return true
701705
}

oracle/delete.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -299,14 +299,14 @@ func buildBulkDeletePLSQL(db *gorm.DB) {
299299
" IF l_deleted_records.COUNT > %d THEN :%d := l_deleted_records(%d).",
300300
rowIdx, outParamIndex+1, rowIdx+1,
301301
))
302-
writeQuotedIdentifier(&plsqlBuilder, column)
302+
db.QuoteTo(&plsqlBuilder, column)
303303
plsqlBuilder.WriteString("; END IF;\n")
304304
} else {
305305
// JSON -> text bind
306306
stmt.Vars = append(stmt.Vars, sql.Out{Dest: new(string)})
307307
plsqlBuilder.WriteString(fmt.Sprintf(" IF l_deleted_records.COUNT > %d THEN\n", rowIdx))
308308
plsqlBuilder.WriteString(fmt.Sprintf(" :%d := JSON_SERIALIZE(l_deleted_records(%d).", outParamIndex+1, rowIdx+1))
309-
writeQuotedIdentifier(&plsqlBuilder, column)
309+
db.QuoteTo(&plsqlBuilder, column)
310310
plsqlBuilder.WriteString(" RETURNING CLOB);\n")
311311
plsqlBuilder.WriteString(" END IF;\n")
312312
}
@@ -316,7 +316,7 @@ func buildBulkDeletePLSQL(db *gorm.DB) {
316316
stmt.Vars = append(stmt.Vars, sql.Out{Dest: dest})
317317
plsqlBuilder.WriteString(fmt.Sprintf(" IF l_deleted_records.COUNT > %d THEN\n", rowIdx))
318318
plsqlBuilder.WriteString(fmt.Sprintf(" :%d := l_deleted_records(%d).", outParamIndex+1, rowIdx+1))
319-
writeQuotedIdentifier(&plsqlBuilder, column)
319+
db.QuoteTo(&plsqlBuilder, column)
320320
plsqlBuilder.WriteString(";\n")
321321
plsqlBuilder.WriteString(" END IF;\n")
322322
}

oracle/update.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -572,17 +572,17 @@ func buildUpdatePLSQL(db *gorm.DB) {
572572
if isJSONField(field) {
573573
if isRawMessageField(field) {
574574
plsqlBuilder.WriteString(fmt.Sprintf("l_updated_records(%d).", rowIdx+1))
575-
writeQuotedIdentifier(&plsqlBuilder, column)
575+
db.QuoteTo(&plsqlBuilder, column)
576576
} else {
577577
// serialize JSON so it binds as text
578578
plsqlBuilder.WriteString("JSON_SERIALIZE(")
579579
plsqlBuilder.WriteString(fmt.Sprintf("l_updated_records(%d).", rowIdx+1))
580-
writeQuotedIdentifier(&plsqlBuilder, column)
580+
db.QuoteTo(&plsqlBuilder, column)
581581
plsqlBuilder.WriteString(" RETURNING CLOB)")
582582
}
583583
} else {
584584
plsqlBuilder.WriteString(fmt.Sprintf("l_updated_records(%d).", rowIdx+1))
585-
writeQuotedIdentifier(&plsqlBuilder, column)
585+
db.QuoteTo(&plsqlBuilder, column)
586586
}
587587

588588
plsqlBuilder.WriteString("; END IF;\n")

tests/associations_test.go

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,11 @@
3939
package tests
4040

4141
import (
42+
"errors"
4243
"strings"
4344
"testing"
4445

46+
"github.com/google/uuid"
4547
. "github.com/oracle-samples/gorm-oracle/tests/utils"
4648

4749
"gorm.io/gorm"
@@ -543,3 +545,66 @@ func TestBasicManyToManyAssociation(t *testing.T) {
543545

544546
AssertAssociationCount(t, user, "Languages", 0, "after clear")
545547
}
548+
549+
func TestSaveAssociationWithAutoIncrementField(t *testing.T) {
550+
DB.Migrator().DropTable(&FolderData{}, &FolderProperty{})
551+
DB.Migrator().CreateTable(&FolderData{}, &FolderProperty{})
552+
553+
id := uuid.New().String()
554+
folder := FolderData{
555+
ID: id,
556+
Name: "My Folder",
557+
Properties: []FolderProperty{
558+
{
559+
ID: id,
560+
Key: "foo1",
561+
Value: "bar1",
562+
},
563+
{
564+
ID: id,
565+
Key: "foo2",
566+
Value: "bar2",
567+
},
568+
},
569+
}
570+
571+
if err := DB.Create(&folder).Error; err != nil {
572+
t.Errorf("Failed to insert data, got %v", err)
573+
}
574+
575+
createdFolder := FolderData{}
576+
if err := DB.Model(&FolderData{}).Preload("Properties").First(&createdFolder).Error; err != nil {
577+
t.Errorf("Failed to query data, got %v", err)
578+
}
579+
580+
CheckFolderData(t, createdFolder, folder)
581+
582+
createdFolder.Properties[1].Value = "baz1"
583+
createdFolder.Properties = append(createdFolder.Properties, FolderProperty{
584+
ID: id,
585+
Key: "foo3",
586+
Value: "bar3",
587+
})
588+
createdFolder.Properties = append(createdFolder.Properties, FolderProperty{
589+
ID: id,
590+
Key: "foo4",
591+
Value: "bar4",
592+
})
593+
DB.Save(&createdFolder)
594+
595+
updatedFolder := FolderData{}
596+
if err := DB.Model(&FolderData{}).Preload("Properties").First(&updatedFolder).Error; err != nil {
597+
t.Errorf("Failed to query data, got %v", err)
598+
}
599+
600+
CheckFolderData(t, updatedFolder, createdFolder)
601+
602+
if err := DB.Select(clause.Associations).Delete(&createdFolder).Error; err != nil {
603+
t.Errorf("Failed to delete data, got %v", err)
604+
}
605+
606+
result := FolderData{}
607+
if err := DB.Where("\"folder_id\" = ?", createdFolder.ID).First(&result).Error; err == nil || !errors.Is(err, gorm.ErrRecordNotFound) {
608+
t.Errorf("should returns record not found error, but got %v", err)
609+
}
610+
}

tests/helper_test.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -357,3 +357,24 @@ func db(unscoped bool) *gorm.DB {
357357
return DB
358358
}
359359
}
360+
361+
func CheckFolderData(t *testing.T, folderData FolderData, expect FolderData) {
362+
tests.AssertObjEqual(t, folderData, expect, "ID", "Name")
363+
t.Run("Properties", func(t *testing.T) {
364+
if len(folderData.Properties) != len(expect.Properties) {
365+
t.Fatalf("properties should equal, expect: %v, got %v", len(expect.Properties), len(folderData.Properties))
366+
}
367+
368+
sort.Slice(folderData.Properties, func(i, j int) bool {
369+
return folderData.Properties[i].ID > folderData.Properties[j].ID
370+
})
371+
372+
sort.Slice(expect.Properties, func(i, j int) bool {
373+
return expect.Properties[i].ID > expect.Properties[j].ID
374+
})
375+
376+
for idx, property := range folderData.Properties {
377+
tests.AssertObjEqual(t, property, expect.Properties[idx], "Seq", "ID", "Key", "Value")
378+
}
379+
})
380+
}

tests/utils/models.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,3 +102,16 @@ type Child struct {
102102
ParentID *uint
103103
Parent *Parent
104104
}
105+
106+
type FolderProperty struct {
107+
Seq uint64 `gorm:"autoIncrement"`
108+
ID string `gorm:"primaryKey;column:folder_id"`
109+
Key string `gorm:"primaryKey;unique"`
110+
Value string
111+
}
112+
113+
type FolderData struct {
114+
ID string `gorm:"primaryKey;column:folder_id"`
115+
Name string `gorm:"column:folder_nm"`
116+
Properties []FolderProperty `gorm:"foreignKey:ID;PRELOAD:false"`
117+
}

0 commit comments

Comments
 (0)