sijms / go-ora

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

Prepared statement is closed if a subsequent FETCH call return zero rows #461

Closed nenadnoveljic closed 10 months ago

nenadnoveljic commented 10 months ago

The test case:

package main

import (
    "database/sql"
    "fmt"
    "log"
    "strconv"

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

const HOST = "localhost"
const PORT = 1521
const SERVICE_NAME = "XE"
const USER = <ADD_USER_HERE>
const PASSWORD = <ADD_PASSWORD_HERE>

const prefetchRows = 10

func main() {
    connectionOptions := map[string]string{
        "prefetch_rows": strconv.Itoa(prefetchRows),
    }

    databaseUrl := go_ora.BuildUrl(HOST, PORT, SERVICE_NAME, USER, PASSWORD,
        connectionOptions)
    db, err := sql.Open("oracle", databaseUrl)
    if err != nil {
        log.Fatalf("failed to connect %s", err)
    }
    err = db.Ping()
    if err != nil {
        log.Fatalf("failed to ping %s", err)
    }

    q := fmt.Sprintf("select 1 from v$sql_plan_statistics_all where rownum <= %d", prefetchRows)
    // No error with prefetchRows+1 or prefetchRows-1

    stmt, err := db.Prepare(q)
    if err != nil {
        log.Fatal(err)
    }

    for i := 1; i <= 2; i++ {
        rows, err := stmt.Query()
        if err != nil {
            log.Fatalf("iteration: %d failed to query %s", i, err)
        }
        defer rows.Close()
        var n int64
        for rows.Next() {
            err = rows.Scan(&n)
            if err != nil {
                log.Fatalf("failed to scan %s")
            }
        }
    }
}

Error message: iteration: 2 failed to query ORA-03120: two-task conversion routine: integer overflow exit status 1

SQL trace:

PARSING IN CURSOR #140406525523384 len=58 dep=0 uid=111 oct=3 lid=111 tim=1411710386391 hv=399689972 ad='b6ab2ff0' sqlid='g0hnmthbx5k7n'
PARSE #140406525523384:c=211456,e=219217,p=0,cr=8,cu=0,mis=1,r=0,dep=0,og=1,plh=1218663495,tim=1411710386386
EXEC #140406525523384:c=0,e=261,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=1,plh=1218663495,tim=1411710387003
FETCH #140406525523384:c=826,e=1174,p=0,cr=0,cu=0,mis=0,r=10,dep=0,og=1,plh=1218663495,tim=1411710388682
FETCH #140406525523384:c=78,e=79,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=1,plh=1218663495,tim=1411710391776
CLOSE #140406525523384:c=0,e=454,dep=0,type=0,tim=1411710466857

The prepared statement always returns 10 rows. Those rows were returned by the first fetch call (r=10). The second fetch call returned no rows (r=0). Immediately after came an implicit CLOSE call. Expectedly, the next execution of the prepared statement failed.

sijms commented 10 months ago

the issue is related to disable compression field in command.go so I comment this field and all its usage the issue fixed in next release

sijms commented 10 months ago

fixed in v2.7.20