oracle / odpi

ODPI-C: Oracle Database Programming Interface for Drivers and Applications
https://oracle.github.io/odpi/
Other
268 stars 78 forks source link

GetObject and other object-related API questions #21

Closed tgulacsi closed 7 years ago

tgulacsi commented 7 years ago
      objType := (*C.dpiObjectType)(C.malloc(C.sizeof_void))
      if C.dpiConn_getObjectType(c.dpiConn, cName, C.uint32_t(len(name)), (**C.dpiObjectType)(unsafe.Pointer(&objType))) == C.DPI_FAILURE {
          C.free(unsafe.Pointer(objType))
          return nil, errors.Wrapf(c.getError(), "getObjectType(%q) conn=%p", name, c.dpiConn)
      }

result:

$ go install && go test -run=Object
--- FAIL: TestObject (3.58s)
        conn.go:147: msg="PrepareContext" shortcut="--GET_OBJECT_TYPE--"
        stmt.go:235: msg="QueryContext" args=[]driver.NamedValue{driver.NamedValue{Name:"", Ordinal:1, Value:"test_pkg_obj.int_tab_typ"}}
        z_test.go:710: ORA-04043: DPI-1002: invalid dpiStmt handle
                getObjectType("test_pkg_obj.int_tab_typ") conn=0x1778470
                gopkg.in/goracle%2ev2.(*conn).GetObjectType
                        /home/gthomas/src/gopkg.in/goracle.v2/obj.go:165
                gopkg.in/goracle%2ev2.(*statement).QueryContext

here c.dpiConn is a proper *dpiConn. Why is an "invalid dpiStmt handle" error returned?

anthony-tuininga commented 7 years ago

Can you set the environment variable DPI_DEBUG_LEVEL=7 when building your driver? That will show the references and their types as well as which functions are being called. That should help track down what is happening here. At least I hope so!

tgulacsi commented 7 years ago
ODPI: fn dpiPool_create(0x2340b60)
ODPI: ref 0x235dec0 (dpiPool) -> 1 [NEW]
ODPI: fn dpiPool_setTimeout(0x235dec0)
ODPI: fn dpiPool_setStmtCacheSize(0x235dec0)
ODPI: fn dpiPool_acquireConnection(0x235dec0)
ODPI: ref 0x23f64c0 (dpiConn) -> 1 [NEW]
ODPI: ref 0x235dec0 (dpiPool) -> 2
ODPI: fn dpiConn_prepareStmt(0x23f64c0)
ODPI: ref 0x23f6630 (dpiStmt) -> 1 [NEW]
ODPI: ref 0x23f64c0 (dpiConn) -> 2
ODPI: fn dpiStmt_execute(0x23f6630)
ODPI: fn dpiStmt_getBindCount(0x23f6630)
ODPI: fn dpiStmt_execute(0x23f6630)
ODPI: fn dpiStmt_getRowCount(0x23f6630)
ODPI: fn dpiStmt_release(0x23f6630)
ODPI: ref 0x23f6630 (dpiStmt) -> 0
ODPI: ref 0x23f64c0 (dpiConn) -> 1
ODPI: fn dpiPool_acquireConnection(0x235dec0)
ODPI: ref 0x23f6540 (dpiConn) -> 1 [NEW]
ODPI: ref 0x235dec0 (dpiPool) -> 3
ODPI: fn dpiStmt_execute((nil))
ODPI: fn dpiStmt_execute((nil))
ODPI: fn dpiConn_getObjectType(0x23f64c0)
ODPI: fn dpiStmt_release((nil))
ODPI: fn dpiConn_rollback(0x23f6540)
ODPI: fn dpiPool_acquireConnection(0x235dec0)
ODPI: ref 0x23f6610 (dpiConn) -> 1 [NEW]
ODPI: ref 0x235dec0 (dpiPool) -> 4
ODPI: fn dpiConn_prepareStmt(0x23f6610)
ODPI: ref 0x2486ba0 (dpiStmt) -> 1 [NEW]
ODPI: ref 0x23f6610 (dpiConn) -> 2
ODPI: fn dpiStmt_execute(0x2486ba0)
ODPI: fn dpiStmt_getBindCount(0x2486ba0)
ODPI: fn dpiStmt_execute(0x2486ba0)
ODPI: fn dpiStmt_getRowCount(0x2486ba0)
ODPI: fn dpiStmt_release(0x2486ba0)
ODPI: ref 0x2486ba0 (dpiStmt) -> 0
ODPI: ref 0x23f6610 (dpiConn) -> 1
--- FAIL: TestObject (1.32s)
        conn.go:147: msg="PrepareContext" shortcut="--GET_OBJECT_TYPE--"
        stmt.go:235: msg="QueryContext" args=[]driver.NamedValue{driver.NamedValue{Name:"", Ordinal:1, Value:"test_pkg_obj.int_tab_typ"}}
        z_test.go:710: ORA-04043: DPI-1002: invalid dpiStmt handle
                getObjectType("test_pkg_obj.int_tab_typ") conn=0x23f64c0
                gopkg.in/goracle%2ev2.(*conn).GetObjectType
                        /home/gthomas/src/gopkg.in/goracle.v2/obj.go:165
                gopkg.in/goracle%2ev2.(*statement).QueryContext
                        /home/gthomas/src/gopkg.in/goracle.v2/stmt.go:237
                database/sql.ctxDriverStmtQuery
tgulacsi commented 7 years ago

I'll try a database/sql-free, "as direct as possible" call.

tgulacsi commented 7 years ago

Ok, a more direct call (without the dance to get a dpiConn from database/sql.Conn):

! go install && go test -run=ObjectD
ODPI: fn dpiPool_create(0x2596b30)
ODPI: ref 0x25b3e90 (dpiPool) -> 1 [NEW]
ODPI: fn dpiPool_setTimeout(0x25b3e90)
ODPI: fn dpiPool_setStmtCacheSize(0x25b3e90)
ODPI: fn dpiPool_acquireConnection(0x25b3e90)
ODPI: ref 0x264c470 (dpiConn) -> 1 [NEW]
ODPI: ref 0x25b3e90 (dpiPool) -> 2
ODPI: fn dpiConn_prepareStmt(0x264c470)
ODPI: ref 0x264c5e0 (dpiStmt) -> 1 [NEW]
ODPI: ref 0x264c470 (dpiConn) -> 2
ODPI: fn dpiStmt_execute(0x264c5e0)
ODPI: fn dpiStmt_getRowCount(0x264c5e0)
ODPI: fn dpiStmt_release(0x264c5e0)
ODPI: ref 0x264c5e0 (dpiStmt) -> 0
ODPI: ref 0x264c470 (dpiConn) -> 1
ODPI: fn dpiConn_getObjectType(0x264c470)
ODPI: fn dpiConn_prepareStmt(0x264c470)
ODPI: ref 0x264c4f0 (dpiStmt) -> 1 [NEW]
ODPI: ref 0x264c470 (dpiConn) -> 2
ODPI: fn dpiStmt_execute(0x264c4f0)
ODPI: fn dpiStmt_getRowCount(0x264c4f0)
ODPI: fn dpiStmt_release(0x264c4f0)
ODPI: ref 0x264c4f0 (dpiStmt) -> 0
ODPI: ref 0x264c470 (dpiConn) -> 1
--- FAIL: TestObjectDirect (0.22s)
        obj_test.go:67: ORA-04043: object test_pkg_obj.tab_typ does not exist

                getObjectType("test_pkg_obj.tab_typ") conn=0x264c470
                gopkg.in/goracle%2ev2.(*conn).GetObjectType
                        /home/gthomas/src/gopkg.in/goracle.v2/obj.go:165
                gopkg.in/goracle%2ev2.TestObjectDirect

where

CREATE OR REPLACE PACKAGE test_pkg_obj IS
  TYPE int_tab_typ IS TABLE OF PLS_INTEGER INDEX BY PLS_INTEGER;
  TYPE rec_typ IS RECORD (int PLS_INTEGER, num NUMBER, vc VARCHAR2(1000), c CHAR(1000), dt DATE);
  TYPE tab_typ IS TABLE OF rec_typ INDEX BY PLS_INTEGER;
END;

So, maybe I misunderstood, and GetObject(Type) can NOT manage types defined only in PL/SQL packages, only types resident in the DB (created by CREATE TYPE)?

anthony-tuininga commented 7 years ago

Hmm, looking at your error message again, it looks like you have part of ORA-4043 (object does not exist) with a DPI error message. Is it possible the error isn't being caught properly?

anthony-tuininga commented 7 years ago

So, maybe I misunderstood, and GetObject(Type) can NOT manage types defined only in PL/SQL packages, only types resident in the DB (created by CREATE TYPE)?

It can support types defined in PL/SQL packages, but only if you are running 12.1 or higher on both the database and on the client. If you have 11.2 anywhere in the equation it won't work.

tgulacsi commented 7 years ago

Ah, I see. Though I use Instant Client 12.1, my db is 11.2. Thanks for the clarification, and sorry for the noise!

anthony-tuininga commented 7 years ago

No problem. Glad to be of help. :-)

cjbj commented 7 years ago

Note to self: We need to doc these things better