sijms / go-ora

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

Object with field type of array not parsed #495

Closed bikain closed 6 months ago

bikain commented 6 months ago

Oracle objects:

create or replace type typeChild as object(
  id number,
  name varchar2(100)
);
create or replace type typeChildArray as table of typeChild;
create or replace type typeParentNew as object(
  id         number,
  value      varchar2(100),
  childArray typeChildArray
)

I use example for cascade type: https://github.com/sijms/go-ora/blob/25a8737060a93190f7a0cca50b49b31d2ac2a206/v2/TestIssues/cascade_type_test.go#L18 GO code:

package main

import (
    "database/sql"
    "fmt"

    go_ora "github.com/sijms/go-ora/v2"
)

type typeChild struct {
    Id   int    `udt:"ID"`
    Name string `udt:"NAME"`
}

type typeParent struct {
    Id         int         `udt:"ID"`
    Value      string      `udt:"VALUE"`
    ChildArray []typeChild `udt:"CHILDARRAY"`
}

func connect() *sql.DB {
    dataSourceName := "***"
    sql, err := sql.Open("oracle", dataSourceName)
    if err != nil {
        panic(err)
    }
    return sql
}

func testParentIn(db *sql.DB) {
    var parent typeParent
    parent.Id = 0
    parent.Value = `value`
    parent.ChildArray = append(parent.ChildArray, typeChild{Id: 1, Value: "value child"})
    err := go_ora.RegisterType(db, "TYPECHILD", "TYPECHILDARRAY", typeChild{})
    if err != nil {
        fmt.Println("err RegisterType typeChild:", err)
    }

    err = go_ora.RegisterType(db, "TYPEPARENTNEW", "", typeParent{})
    if err != nil {
        fmt.Println("err RegisterType typeChild:", err)
    }

    _, err = db.Exec(`
    begin
        //kp.pk_log.log('[GO] ' || xmltype(:p).getclobval);
        dbms_output.put_line('[GO]' || xmltype(:p).getclobval);
    end;`,
        parent,
    )

    if err != nil {
        fmt.Println("err testParentIn:", err)
        return
    }
}

func testParentOut(db *sql.DB) {
    var parent typeParent

    err := go_ora.RegisterType(db, "TYPECHILD", "TYPECHILDARRAY", typeChild{})
    if err != nil {
        fmt.Println("err RegisterType typeChild:", err)
    }

    err = go_ora.RegisterType(db, "TYPEPARENTNEW", "", typeParent{})
    if err != nil {
        fmt.Println("err RegisterType typeChild:", err)
    }

    _, err = db.Exec(`
    declare
        v_child typeChild := typeChild(null,null);
        v_parent typeParentNew := typeParentNew(null,null,null);
    begin
        v_parent.id := 0;
        v_parent.value := 'value';
        v_parent.childArray := typeChildArray();
        for i in 1..3 loop
            v_child := typeChild(null,null);
            v_child.id := i;
            v_child.name := 'name ' || i;
            v_parent.childArray.extend;
            v_parent.childArray(v_parent.childArray.count) := v_child;
        end loop;
        :p := v_parent;
    end;`,
        go_ora.Out{Dest: &parent},
    )

    if err != nil {
        fmt.Println("err testParentOut:", err)
        return
    }

    fmt.Println("testParentOut:", parent)
}

func main() {
    fmt.Println("Hello world")

    db := connect()
    defer db.Close()

    testParentOut(db)

    testParentIn(db)

    fmt.Scanf(" ")
}

Result: err testParentOut: Invalid Input Number 880131010300030d84010d02c102066e616d6520310d84010d02c103066e616d6520320d84010d02c104066e616d652033 err testParentIn: ORA-00600: internal error code, arguments: [kopp2upic#329], [13], [12], [0], [], [], [], [], [], [], [], []

It's code correct for work with cascade type? Or need something else?

Client: go-ora: github.com/sijms/go-ora/v2 v2.8.5 go: 1.21.3 oracle-client: 12.2.0.1.0

sijms commented 6 months ago

fixed in next release

sijms commented 6 months ago

fixed in v2.8.6 testing file nested_udt_array_test.go