sijms / go-ora

Pure go oracle client
MIT License
789 stars 174 forks source link

Problem with Cascaded Types #410

Closed zedage closed 1 year ago

zedage commented 1 year ago

While further testing your driver, I believe to have found an issue with cascaded types. An "unsupported attribute type" error is returned while registering the type with the cascaded type attribute. I made a test to reproduce it. Please find the test set attached. Many thanks for your investigations.

main.go.gz

package main

import (
    "database/sql"
    "fmt"
    go_ora "github.com/sijms/go-ora/v2"
    "log"
)

type HkGoraIdObj struct {
    Id int64 `udt:"ID"`
}

type HkGoraTestSubObj struct {
    SubId   int64  `udt:"SUB_ID"`
    SubData string `udt:"SUB_DATA"`
}
type HkGoraTestObj struct {
    Id      int64              `udt:"ID"`
    Name    string             `udt:"NAME"`
    SubInfo []HkGoraTestSubObj `udt:"SUB_INFO"`
}

func execSimpleStmt(con *sql.DB, stmts ...string) {
    for _, stmt := range stmts {
        if _, err := con.Exec(stmt); err != nil {
            log.Println("Error when executing statement", stmt, err)
        }
    }
}

func createTypes(con *sql.DB) func() {
    log.Println("creating types")
    execSimpleStmt(con,
        "drop type HK_GORA_ID_COLL",
        "drop type HK_GORA_ID_OBJ",
        "drop type HK_GORA_TEST_COLL",
        "drop type HK_GORA_TEST_OBJ",
        "drop type HK_GORA_TEST_SUB_COLL",
        "drop type HK_GORA_TEST_SUB_OBJ",
        "create or replace type HK_GORA_ID_OBJ force as object(ID number(22,0));",
        "create or replace type HK_GORA_ID_COLL as table of HK_GORA_ID_OBJ;",
        "create or replace type HK_GORA_TEST_SUB_OBJ force as object(SUB_ID number(22,0), SUB_DATA varchar2(2000))",
        "create or replace type HK_GORA_TEST_SUB_COLL as table of HK_GORA_TEST_SUB_OBJ",
        "create or replace type HK_GORA_TEST_OBJ force as object(ID number(22,0), NAME varchar2(2000), SUB_INFO HK_GORA_TEST_SUB_COLL);",
        "create or replace type HK_GORA_TEST_COLL as table of HK_GORA_TEST_OBJ;")
    return func() {
        log.Println("dropping types")
        execSimpleStmt(con,
            "drop type HK_GORA_ID_COLL",
            "drop type HK_GORA_ID_OBJ",
            "drop type HK_GORA_TEST_COLL",
            "drop type HK_GORA_TEST_OBJ",
            "drop type HK_GORA_TEST_SUB_COLL",
            "drop type HK_GORA_TEST_SUB_OBJ")
    }
}

func getConnection() (*sql.DB, func()) {
    connectString := go_ora.BuildUrl("host", 1521, "nickel", "user", "pw", nil)
    log.Println("connectString", fmt.Sprintf("Oracle connect string: %s", connectString))
    dbCon, err := sql.Open("oracle", connectString)
    if err != nil {
        log.Fatal(err)
    }
    return dbCon, func() {
        if err = dbCon.Close(); err != nil {
            log.Fatal(err)
        }
    }
}

func registerTypes(con *sql.DB) {
    log.Println("registering types")
    err := go_ora.RegisterType(con, "HK_GORA_ID_OBJ", "HK_GORA_ID_COLL", HkGoraIdObj{})
    if err != nil {
        log.Fatalf("Error registering HK_GORA_ID_OBJ: %v", err)
    }
    err = go_ora.RegisterType(con, "HK_GORA_TEST_SUB_OBJ", "HK_GORA_TEST_SUB_COLL", HkGoraTestSubObj{})
    if err != nil {
        log.Fatalf("Error registering HK_GORA_TEST_SUB_OBJ: %v", err)
    }
    err = go_ora.RegisterType(con, "HK_GORA_TEST_OBJ", "HK_GORA_TEST_COLL", HkGoraTestObj{})
    if err != nil {
        log.Fatalf("Error registering HK_GORA_TEST_OBJ: %v", err)
    }
}

func main() {
    log.Println("Start test issue with cascaded types")
    con, deferFn := getConnection()
    defer deferFn()
    deferFn = createTypes(con)
    defer deferFn()
    registerTypes(con)
}
sijms commented 1 year ago

thanks @zedage I will investigate the code

sijms commented 1 year ago

fixed in next release 2.7.10