go-goracle / goracle

Go database/sql driver for connecting to Oracle Database, using the ODPI-C library

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Error with SQL statement finished with ';'

tredoe opened this issue · comments

Describe the bug
The driver gives a failure when a SQL statement is finished with ';'

package main

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

	_ "gopkg.in/goracle.v2"
)

const (
	dbname = "demo0"
	user   = "demo"
	pass   = "***"
)

func main() {
	db, err := connectDB()
	if err != nil {
		log.Fatal("Connect Error: %s", err)
	}
	if err = db.Ping(); err != nil {
		log.Fatalf("Ping Error: %s", err)
	}
	defer db.Close()
	fmt.Println("Connected: ok")

	if _, err = db.Exec(table); err != nil {
		log.Fatalf("Create Error: %s", err)
	}
	if _, err = db.Exec(insert); err != nil {
		log.Fatalf("Insert Error: %s", err)
	}
	if _, err = db.Exec("drop table foo"); err != nil {
		log.Fatalf("Drop Error: %s", err)
	}
	fmt.Println("OK")
}

func connectDB() (*sql.DB, error) {
	driver := "goracle"
	connString := fmt.Sprintf("oracle://%s:%s@127.0.0.1/%s", user, pass, dbname)
	return sql.Open(driver, connString)
}

const (
	table = `
CREATE TABLE foo (
    id smallint  PRIMARY KEY NOT NULL,
    name varchar2(10) NOT NULL
);
`
	insert = `
INSERT INTO foo
    (id, name)
  VALUES
    (0, 'foo');
`
)

To Reproduce
Steps to reproduce the behavior:

  1. go run test_oracle.go
  2. See error:
Create Error: dpiStmt_execute(mode=32 arrLen=-1): ORA-00922: missing or invalid option

Your oracle client version
Oracle Database 18c Express Edition Release 18.0.0.0.0

Your goracle version
v2.22.4

Your go version
go version go1.13.4 windows/amd64

Your gcc version
gcc --version
gcc (GCC) 4.8.3

Machine:

  • OS: Windows
  • Architecture amd64
  • Version: 10

That error is expected. The trailing semicolon should not be included!

SQL plus needs the trailing semicolon:
https://stackoverflow.com/questions/8406835/oracle-sql-plus-how-to-end-command-in-sql-file

Then, all other Go drivers that I've tested (MySQL, PostgreSQL, SQLite, IBM DB2) allow such semicolon.

So, which is the reason for that it been invalid with this driver?

Yes, SQL*Plus expects the separator as it is dealing with a stream. Note that for some statements (packages, procedures, triggers, etc.), the separator is the slash (/) and not a semicolon (;). This is just the way that the Oracle Client libraries work. You can request a change if you wish by contacting Oracle Support.

So, is not possible to use two statements in the same execution since Oracle has not a separator character, is it?

table = `
CREATE TABLE foo (
    id smallint  PRIMARY KEY NOT NULL,
    name varchar2(10) NOT NULL
)
CREATE TABLE bar (
    id smallint  PRIMARY KEY NOT NULL,
    name varchar2(10) NOT NULL
)
`

Right. You can only execute one statement at a time. You cannot execute multiple statements at the same time as in your example.

You can execute multiple SQL statements in the one execution "round-trip" to the database as long as you wrap them in PL/SQL. This has scalability advantages.

begin 
  execute immediate 'DROP TABLE mytab'; exception when others then if sqlcode <> -942 then raise; end if;
  execute immediate 'CREATE TABLE mytab (id NUMBER, name VARCHAR2(40))';
end;

Note that PL/SQL statements will require that final ';' at the very end.