sijms / go-ora

Pure go oracle client
MIT License
771 stars 169 forks source link

Trigger panic when the number of rows in the table is >= 3 #493

Closed CoiaPrant233 closed 6 months ago

CoiaPrant233 commented 6 months ago
runtime error: index out of range [4] with length 4
D:/Program Files/Go/src/runtime/panic.go:114 (0x437a7b)
C:/Users/Administrator/go/pkg/mod/github.com/sijms/go-ora/v2@v2.8.4/data_set.go:90 (0xa3bcf5)
C:/Users/Administrator/go/pkg/mod/github.com/sijms/go-ora/v2@v2.8.4/data_set.go:74 (0xa3bbbd)
C:/Users/Administrator/go/pkg/mod/github.com/sijms/go-ora/v2@v2.8.4/command.go:723 (0xa28378)
C:/Users/Administrator/go/pkg/mod/github.com/sijms/go-ora/v2@v2.8.4/command.go:2284 (0xa30dce)
C:/Users/Administrator/go/pkg/mod/github.com/sijms/go-ora/v2@v2.8.4/command.go:2186 (0xa30804)
C:/Users/Administrator/go/pkg/mod/github.com/sijms/go-ora/v2@v2.8.4/command.go:2254 (0xa30b45)
C:/Users/Administrator/go/pkg/mod/github.com/sijms/go-ora/v2@v2.8.4/connection.go:1094 (0xa36ab1)
D:/Program Files/Go/src/database/sql/ctxutil.go:48 (0x515e76)
D:/Program Files/Go/src/database/sql/sql.go:1748 (0x51e3e4)
D:/Program Files/Go/src/database/sql/sql.go:3502 (0x525f41)
D:/Program Files/Go/src/database/sql/sql.go:1743 (0x51dd68)
D:/Program Files/Go/src/database/sql/sql.go:2497 (0x521264)
C:/Users/Administrator/go/pkg/mod/gorm.io/gorm@v1.25.5/callbacks/query.go:20 (0x957371)
C:/Users/Administrator/go/pkg/mod/gorm.io/gorm@v1.25.5/callbacks.go:130 (0x5d3d34)
C:/Users/Administrator/go/pkg/mod/gorm.io/gorm@v1.25.5/finisher_api.go:170 (0x5db4d3)
sijms commented 6 months ago

would you please explain more details what is column type and if you give example code to produce error will be better

CoiaPrant233 commented 6 months ago
type Keywords struct {
    Id int64 `gorm:"column:id; primaryKey"`

    Key        string `gorm:"column:key; not null; unique"`
    Value      string `gorm:"column:value; not null"`
    Ignored    bool   `gorm:"column:ignored; not null; default:false"`
}

gorm driver: gitlab.com/CoiaPrant/gorm-oracle

CoiaPrant233 commented 6 months ago

Another problem:

var id int64
db.Exec(`INSERT INTO "keywords" ("key","value","ignored") VALUES (?, ?, ?) RETURNING "id" INTO ':4'`, "demo", "demo", 0, sql.Out{Dest: &id})

Error

ORA-03146: invalid buffer length for TTC field
sijms commented 6 months ago

Another problem:

var id int64
db.Exec(`INSERT INTO "keywords" ("key","value","ignored") VALUES (?, ?, ?) RETURNING "id" INTO ':4'`, "demo", "demo", 0, sql.Out{Dest: &id})

Error

ORA-03146: invalid buffer length for TTC field

why use ? as a parameter place holder. supported place holder is :parName

CoiaPrant233 commented 6 months ago

Another problem:

var id int64
db.Exec(`INSERT INTO "keywords" ("key","value","ignored") VALUES (?, ?, ?) RETURNING "id" INTO ':4'`, "demo", "demo", 0, sql.Out{Dest: &id})

Error

ORA-03146: invalid buffer length for TTC field

why use ? as a parameter place holder. supported place holder is :parName

Sorry, I copy my code to here and edit it wrong.

var id int64
db.Exec(`INSERT INTO "keywords" ("key","value","ignored") VALUES (:1, :2, :3) RETURNING "id" INTO ':4'`, "demo", "demo", 0, sql.Out{Dest: &id})

Also return the same error

If remove returning clause, its working.

sijms commented 6 months ago

the issue caused by returning this is the code that detect RETURNING

ret._hasReturnClause, err = regexp.MatchString(`\bRETURNING\b\s+(\w+\s*,\s*)*\s*\w+\s+\bINTO\b`, uCmdText)
if err != nil {
    ret._hasReturnClause = false
}

the value of of ret._hasReturnClause will be false because of " which is not detected with regex I replace the regex


ret._hasReturnClause, err = regexp.MatchString(`\bRETURNING\b\s+.*\s+\bINTO\b`, uCmdText)
if err != nil {
    ret._hasReturnClause = false
}
CoiaPrant233 commented 6 months ago

and the range index out of bug also fixed?

sijms commented 6 months ago

I test the code no error

CoiaPrant233 commented 6 months ago

but it's panic should i provide a demo program?

sijms commented 6 months ago

yes please I need to reproduce the error to fix it

CoiaPrant233 commented 5 months ago

Sorry for later

I reconfirm bug. Trigger panic when the number of rows in the table is >= 3

Example

package main

import (
    "log"
    "os"
    "time"

    oracle "gitlab.com/CoiaPrant/gorm-oracle"
    "gorm.io/gorm"

    "gorm.io/gorm/clause"
    gorm_logger "gorm.io/gorm/logger"
)

const (
    HOST     = ""
    PORT     = 1522
    SERVICE  = ""
    USER     = ""
    PASSWORD = ""

    AUTH_TYPE       = ""
    WALLET_PATH     = "." // dir
    WALLET_PASSWORD = ""

    SSL        = true
    SSL_VERIFY = true
    TRACE_FILE = ""
)

type Column struct {
    Id int64 `gorm:"column:id; primaryKey"`

    Key   string `gorm:"column:key; not null; unique"`
    Value string `gorm:"column:value; not null"`
}

func (Column) TableName() string {
    return "kvs"
}

func main() {
    var dialector gorm.Dialector
    {
        options := make(map[string]string)

        if AUTH_TYPE != "" {
            options["AUTH TYPE"] = AUTH_TYPE
        }

        if WALLET_PATH != "" {
            options["WALLET"] = WALLET_PATH
        }

        if WALLET_PASSWORD != "" {
            options["WALLET PASSWORD"] = WALLET_PASSWORD
        }

        if SSL {
            options["SSL"] = "TRUE"

            if SSL_VERIFY {
                options["SSL VERIFY"] = "TRUE"
            }
        }

        dialector = oracle.New(oracle.Config{
            DSN:               oracle.BuildUrl(HOST, PORT, SERVICE, USER, PASSWORD, options),
            DefaultStringSize: 4000,
        })
    }

    db, err := gorm.Open(dialector, &gorm.Config{
        Logger: gorm_logger.New(log.New(os.Stdout, "\r\n", log.LstdFlags), gorm_logger.Config{
            SlowThreshold:             200 * time.Millisecond,
            LogLevel:                  gorm_logger.Info,
            IgnoreRecordNotFoundError: true,
        }),
        AllowGlobalUpdate: true,
    })
    if err != nil {
        panic(err)
    }

    db.Migrator().DropTable("kvs")
    err = db.AutoMigrate(Column{})
    if err != nil {
        panic(err)
    }

    db.Unscoped().Create(&Column{Key: "hello"})
    db.Unscoped().Create(&Column{Key: "world"})
    db.Unscoped().Create(&Column{Key: "hello world"})

    DB := db.Unscoped().Begin()

    var columns []Column
    err = DB.Unscoped().Clauses(clause.Locking{Strength: "UPDATE"}).Find(&columns).Error
    if err != nil {
        DB.Rollback()
        panic(err)
    }

    DB.Commit()
}
sijms commented 4 months ago

this is the code I test. I successfully insert 10 rows in the table

package main

import (
    "database/sql"
    "fmt"
    _ "github.com/sijms/go-ora/v2"
    go_ora "github.com/sijms/go-ora/v2"
    oracle "gitlab.com/CoiaPrant/gorm-oracle"
    "gorm.io/gorm"
    "os"
    "strconv"
)

type Keywords struct {
    Id int64 `gorm:"column:id; primaryKey"`

    Key     string `gorm:"column:key; not null; unique"`
    Value   string `gorm:"column:value; not null"`
    Ignored bool   `gorm:"column:ignored; not null; default:false"`
}

func main() {
    var err error
    db, err := gorm.Open(oracle.Open(os.Getenv("DSN_CLOUD")), &gorm.Config{})
    if err != nil {
        fmt.Println("can't connect: ", err)
        return
    }
    err = db.AutoMigrate(&Keywords{})
    if err != nil {
        fmt.Println("can't migrate: ", err)
        return
    }
    for x := 0; x < 10; x++ {
        model := &Keywords{
            Key:     strconv.Itoa(x + 1),
            Value:   "demo_" + strconv.Itoa(x+1),
            Ignored: false,
        }
        tx := db.Create(model)
        tx.Commit()
        fmt.Println("ID: ", model.Id)
    }
}