From 2f20d0b90e331e138c45dc3b9dc9e5b939f44629 Mon Sep 17 00:00:00 2001 From: akhilravuri1 Date: Tue, 8 Jan 2019 13:00:44 +0530 Subject: [PATCH 1/5] github.com/ibmdb/go_ibm_db driver added --- .../ibmdb/go_ibm_db/API_DOCUMENTATION.md | 335 ++++++++++++++++++ .../ibmdb/go_ibm_db/CONTRIBUTING.md | 11 + src/github.com/ibmdb/go_ibm_db/LICENSE.md | 27 ++ src/github.com/ibmdb/go_ibm_db/README.md | 244 +++++++++++++ src/github.com/ibmdb/go_ibm_db/api/Makefile | 15 + src/github.com/ibmdb/go_ibm_db/api/api.go | 68 ++++ .../ibmdb/go_ibm_db/api/api_unix.go | 137 +++++++ .../ibmdb/go_ibm_db/api/api_windows.go | 133 +++++++ .../ibmdb/go_ibm_db/api/api_windows_386.go | 10 + .../ibmdb/go_ibm_db/api/api_windows_amd64.go | 10 + .../ibmdb/go_ibm_db/api/mksyscall_unix.pl | 132 +++++++ .../ibmdb/go_ibm_db/api/zapi_unix.go | 118 ++++++ .../ibmdb/go_ibm_db/api/zapi_windows.go | 161 +++++++++ src/github.com/ibmdb/go_ibm_db/column.go | 283 +++++++++++++++ src/github.com/ibmdb/go_ibm_db/conn.go | 47 +++ src/github.com/ibmdb/go_ibm_db/driver.go | 60 ++++ src/github.com/ibmdb/go_ibm_db/error.go | 72 ++++ src/github.com/ibmdb/go_ibm_db/handle.go | 44 +++ .../ibmdb/go_ibm_db/installer/setup.go | 235 ++++++++++++ src/github.com/ibmdb/go_ibm_db/odbcstmt.go | 157 ++++++++ src/github.com/ibmdb/go_ibm_db/param.go | 165 +++++++++ src/github.com/ibmdb/go_ibm_db/pooling.go | 205 +++++++++++ src/github.com/ibmdb/go_ibm_db/result.go | 22 ++ src/github.com/ibmdb/go_ibm_db/rows.go | 45 +++ src/github.com/ibmdb/go_ibm_db/stats.go | 33 ++ src/github.com/ibmdb/go_ibm_db/stmt.go | 99 ++++++ .../ibmdb/go_ibm_db/testdata/begin_test.go | 9 + .../ibmdb/go_ibm_db/testdata/close_test.go | 9 + .../ibmdb/go_ibm_db/testdata/columns_test.go | 9 + .../ibmdb/go_ibm_db/testdata/commit_test.go | 9 + .../ibmdb/go_ibm_db/testdata/conn_test.go | 9 + .../ibmdb/go_ibm_db/testdata/create_test.go | 9 + .../ibmdb/go_ibm_db/testdata/drop_test.go | 9 + .../ibmdb/go_ibm_db/testdata/insert_test.go | 9 + .../ibmdb/go_ibm_db/testdata/main.go | 250 +++++++++++++ .../ibmdb/go_ibm_db/testdata/next_test.go | 9 + .../ibmdb/go_ibm_db/testdata/poolopen_test.go | 10 + .../ibmdb/go_ibm_db/testdata/prepare_test.go | 9 + .../ibmdb/go_ibm_db/testdata/query_test.go | 9 + .../ibmdb/go_ibm_db/testdata/queryrow_test.go | 9 + .../ibmdb/go_ibm_db/testdata/scan_test.go | 9 + src/github.com/ibmdb/go_ibm_db/tx.go | 67 ++++ src/github.com/ibmdb/go_ibm_db/utf16.go | 55 +++ src/sqltest/drivers.go | 1 + src/sqltest/sql_test.go | 85 ++++- 45 files changed, 3448 insertions(+), 5 deletions(-) create mode 100644 src/github.com/ibmdb/go_ibm_db/API_DOCUMENTATION.md create mode 100644 src/github.com/ibmdb/go_ibm_db/CONTRIBUTING.md create mode 100644 src/github.com/ibmdb/go_ibm_db/LICENSE.md create mode 100644 src/github.com/ibmdb/go_ibm_db/README.md create mode 100644 src/github.com/ibmdb/go_ibm_db/api/Makefile create mode 100644 src/github.com/ibmdb/go_ibm_db/api/api.go create mode 100644 src/github.com/ibmdb/go_ibm_db/api/api_unix.go create mode 100644 src/github.com/ibmdb/go_ibm_db/api/api_windows.go create mode 100644 src/github.com/ibmdb/go_ibm_db/api/api_windows_386.go create mode 100644 src/github.com/ibmdb/go_ibm_db/api/api_windows_amd64.go create mode 100644 src/github.com/ibmdb/go_ibm_db/api/mksyscall_unix.pl create mode 100644 src/github.com/ibmdb/go_ibm_db/api/zapi_unix.go create mode 100644 src/github.com/ibmdb/go_ibm_db/api/zapi_windows.go create mode 100644 src/github.com/ibmdb/go_ibm_db/column.go create mode 100644 src/github.com/ibmdb/go_ibm_db/conn.go create mode 100644 src/github.com/ibmdb/go_ibm_db/driver.go create mode 100644 src/github.com/ibmdb/go_ibm_db/error.go create mode 100644 src/github.com/ibmdb/go_ibm_db/handle.go create mode 100644 src/github.com/ibmdb/go_ibm_db/installer/setup.go create mode 100644 src/github.com/ibmdb/go_ibm_db/odbcstmt.go create mode 100644 src/github.com/ibmdb/go_ibm_db/param.go create mode 100644 src/github.com/ibmdb/go_ibm_db/pooling.go create mode 100644 src/github.com/ibmdb/go_ibm_db/result.go create mode 100644 src/github.com/ibmdb/go_ibm_db/rows.go create mode 100644 src/github.com/ibmdb/go_ibm_db/stats.go create mode 100644 src/github.com/ibmdb/go_ibm_db/stmt.go create mode 100644 src/github.com/ibmdb/go_ibm_db/testdata/begin_test.go create mode 100644 src/github.com/ibmdb/go_ibm_db/testdata/close_test.go create mode 100644 src/github.com/ibmdb/go_ibm_db/testdata/columns_test.go create mode 100644 src/github.com/ibmdb/go_ibm_db/testdata/commit_test.go create mode 100644 src/github.com/ibmdb/go_ibm_db/testdata/conn_test.go create mode 100644 src/github.com/ibmdb/go_ibm_db/testdata/create_test.go create mode 100644 src/github.com/ibmdb/go_ibm_db/testdata/drop_test.go create mode 100644 src/github.com/ibmdb/go_ibm_db/testdata/insert_test.go create mode 100644 src/github.com/ibmdb/go_ibm_db/testdata/main.go create mode 100644 src/github.com/ibmdb/go_ibm_db/testdata/next_test.go create mode 100644 src/github.com/ibmdb/go_ibm_db/testdata/poolopen_test.go create mode 100644 src/github.com/ibmdb/go_ibm_db/testdata/prepare_test.go create mode 100644 src/github.com/ibmdb/go_ibm_db/testdata/query_test.go create mode 100644 src/github.com/ibmdb/go_ibm_db/testdata/queryrow_test.go create mode 100644 src/github.com/ibmdb/go_ibm_db/testdata/scan_test.go create mode 100644 src/github.com/ibmdb/go_ibm_db/tx.go create mode 100644 src/github.com/ibmdb/go_ibm_db/utf16.go diff --git a/src/github.com/ibmdb/go_ibm_db/API_DOCUMENTATION.md b/src/github.com/ibmdb/go_ibm_db/API_DOCUMENTATION.md new file mode 100644 index 0000000..57cfd4e --- /dev/null +++ b/src/github.com/ibmdb/go_ibm_db/API_DOCUMENTATION.md @@ -0,0 +1,335 @@ +# go-ibm_db API Documentation + +## Database APIs + +**Database APIs** + +1. [.Open(drivername,ConnectionString)](#OpenApi) +2. [.Prepare(sqlquery)](#PrepareApi) +3. [.Query(sqlquery)](#QueryApi) +4. [.Exec(sqlquery)](#ExecApi) +5. [.Begin()](#BeginApi) +6. [.Close()](#CloseApi) +7. [.Commit()](#CommitApi) +8. [.Rollback()](#RollbackApi) +9. [.QueryRow(sqlquery)](#QueryRowApi) +10. [.Columns()](#ColumnsApi) +11. [.Next()](#NextApi) +12. [.Scan(options)](#ScanApi) + +### 1) .Open(drivername,ConnectionString) + +open a connection to database +* **connectionString** - The connection string for your database. +* For distributed platforms, the connection string is typically defined as: `DATABASE=dbname;HOSTNAME=hostname;PORT=port;PROTOCOL=TCPIP;UID=username;PWD=passwd` + +```javascript +var connStr = flag.String("conn", "HOSTNAME=hostname;PORT=port;DATABASE=dbname;UID=uid;PWD=Pass", "connection string") +func dboper() error { +fmt.Println("connecting to driver"); +db, err:=sql.Open("drivername",*connStr); +if err != nil{ +return err; +} +defer db.Close() +} +``` +### 2) .Prepare(sqlquery) + +Prepare a statement for execution +* **sql** - SQL string to prepare + +Returns a ‘statement’ object + +```javascript +func oper() error{ +fmt.Println("connecting to go-ibm_db"); +db, err:=sql.Open("go-imb_db",*connStr); +if err != nil{ +return err; +} +defer db.Close() +st, err:=db.Prepare("select * from ak") +if err !=nil{ +return err +} +rows,err :=st.Query() +if err != nil{ +return err +} +defer rows.Close() +} +``` + +### 3) .Query(sqlquery) + +Issue a SQL query to the database + +If the query is executed then it will return the rows or it will return error + +```javascript + +func oper() error{ +fmt.Println("connecting to go-ibm_db"); +db, err:=sql.Open("go-ibm_db",*connStr); +if err != nil{ +return err; +} +defer db.Close() +rows,err :=db.Query(“select * from ak”) +if err != nil{ +return err +} +defer rows.Close() +} +``` + + +### 4) .Exec(sqlquery) + +Execute a prepared statement. + +Only DML commands are performed. No data is returned back. + +```javascript + +func oper() error{ +fmt.Println("connecting to go-ibm_db"); +db, err:=sql.Open("go-ibm_db",*connStr); +if err != nil{ +return err; +} +defer db.Close() +_,err=db.Exec("create table ghh(a int, b float, c double, d char, e varchar(30))") +if err != nil{ +return err +} +} +``` + +### 5) .Begin() + +Begin a transaction. + +```javascript + + +func oper() error{ +fmt.Println("connecting to go-ibm_db"); +db, err:=sql.Open("go-ibm_db",*connStr); +if err != nil{ +return err; +} +defer db.Close() +bg, err:=db.Begin() +if err !=nil{ +return err +} +return nil +} +``` + + + +### 6) .Close() + +Close the currently opened database. + +```javascript + +func dboper() error { +fmt.Println("connecting to go-ibm_db"); +db, err:=sql.Open("go-ibm_db",*connStr); +if err != nil{ +return err; +} +defer db.Close() +} +``` + + + +### 7) .Commit() + +Commit a transaction. + +```javascript + +func oper() error{ +fmt.Println("connecting to go-ibm_db"); +db, err:=sql.Open("go-ibm_db",*connStr); +if err != nil{ +return err; +} +defer db.Close() +bg, err:=db.Begin() +if err !=nil{ +return err +} +_,err=bg.Exec("create table ghh(a int,b float,c double,d char,e varchar(30))") +if err != nil{ +return err +} +err=bg.Commit() +if err != nil{ +return err +} +return nil +} +``` + + + + +### 8) .Rollback() + +Rollback a transaction. + +```javascript + + +func oper() error{ +fmt.Println("connecting to go-ibm_db"); +db, err:=sql.Open("go-ibm_db",*connStr); +if err != nil{ +return err; +} +defer db.Close() +bg, err:=db.Begin() +if err !=nil{ +return err +} +_,err=bg.Exec("create table ghh(a int,b float,c double,d char,e varchar(30))") +if err != nil{ +return err +} +err=bg.Rollback() +if err != nil{ +return err +} +return nil +} +``` + +### 9) .QueryRow(sqlquery) + +QueryRow executes a query that is expected to return at most one row. +If there are more rows then it will scan first and discards the rest. + +```javascript + +func oper() error{ +id := 123 +var username string +err := db.QueryRow("SELECT name FROM ak WHERE id=?", id).Scan(&username) + if err != nil { + return err +} +fmt.Printf("Username is %s\n", username) +return nil +} + +``` + +### 10) .Columns() + +Returns the column names. + +Returns error if the rows are closed. + +```javascript + +func oper() error{ +fmt.Println("connecting to databse"); +db, err:=sql.Open("go-ibm_db",*connStr); +if err != nil{ +return err; +} +defer db.Close() +st, err:=db.Prepare("select * from ak") +if err !=nil{ +return err +} +rows,err :=st.Query() +if err != nil{ +return err +} +defer rows.Close() +name11 := make([]string,1) +name11,err = rows.Columns() +fmt.Printf("%v",name11); +return nil +} +``` + +### 11) .Next() + +Prepares the next result row for reading with the scan api. + +```javascript + +func oper() error{ +fmt.Println("connecting to database"); +db, err:=sql.Open("go-ibm_db",*connStr); +if err != nil{ +return err; +} +defer db.Close() +rows,err :=db.Query() +if err != nil{ +return err +} +defer rows.Close() +for rows.Next(){ +var t string +var x string +err = rows.Scan(&t,&x) +if err != nil{ +return err +} +fmt.Printf("%v %v\n",t,x) +} +return nil +} +``` + +### 12) .Scan(options) + +copies the columns in the current row into the values pointed. + +```javascript + +func oper() error{ +fmt.Println("connecting to database"); +db, err:=sql.Open("go-ibm_db",*connStr); +if err != nil{ +return err; +} +defer db.Close() +rows,err :=db.Query() +if err != nil{ +return err +} +defer rows.Close() +for rows.Next(){ +var t string +var x string +err = rows.Scan(&t,&x) +if err != nil{ +return err +} +fmt.Printf("%v %v\n",t,x) +} +return nil +} +``` + + + + + + + + + + diff --git a/src/github.com/ibmdb/go_ibm_db/CONTRIBUTING.md b/src/github.com/ibmdb/go_ibm_db/CONTRIBUTING.md new file mode 100644 index 0000000..41c3376 --- /dev/null +++ b/src/github.com/ibmdb/go_ibm_db/CONTRIBUTING.md @@ -0,0 +1,11 @@ +# Developer's Certificate of Origin 1.1 + +By making a contribution to this project, I certify that: + +(a) The contribution was created in whole or in part by me and I have the right to submit it under the open source license indicated in the file; or + +(b) The contribution is based upon previous work that, to the best of my knowledge, is covered under an appropriate open source license and I have the right under that license to submit that work with modifications, whether created in whole or in part by me, under the same open source license (unless I am permitted to submit under a different license), as indicated in the file; or + +(c) The contribution was provided directly to me by some other person who certified (a), (b) or (c) and I have not modified it. + +(d) I understand and agree that this project and the contribution are public and that a record of the contribution (including all personal information I submit with it, including my sign-off) is maintained indefinitely and may be redistributed consistent with this project or the open source license(s) involved. \ No newline at end of file diff --git a/src/github.com/ibmdb/go_ibm_db/LICENSE.md b/src/github.com/ibmdb/go_ibm_db/LICENSE.md new file mode 100644 index 0000000..7448756 --- /dev/null +++ b/src/github.com/ibmdb/go_ibm_db/LICENSE.md @@ -0,0 +1,27 @@ +Copyright (c) 2012 The Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/src/github.com/ibmdb/go_ibm_db/README.md b/src/github.com/ibmdb/go_ibm_db/README.md new file mode 100644 index 0000000..3f7fcba --- /dev/null +++ b/src/github.com/ibmdb/go_ibm_db/README.md @@ -0,0 +1,244 @@ +# go_ibm_db + +Interface for GoLang to DB2 for z/OS, DB2 for LUW, DB2 for i. + +## API Documentation + +> For complete list of go_ibm_db APIs and examples please check [APIDocumentation.md](https://github.com/ibmdb/go_ibm_db/blob/master/API_DOCUMENTATION.md) + +## Prerequisite + +Golang should be installed in your system. + +## How to Install in Windows +``` +go get -d github.com/ibmdb/go_ibm_db + +If you already have a cli driver available in your system, add the path of the same to your Path windows environment variable +Example: Path = C:\Program Files\IBM\IBM DATA SERVER DRIVER\bin + + +If you do not have a clidriver in your system, go to installer folder where go_ibm_db is downloaded in your system (Example: C:\Users\uname\go\src\github.com\ibmdb\go_ibm_db\installer) and run setup.go file (go run setup.go). + +where uname is the username + +Above command will download clidriver. + +Add the path of the clidriver downloaded to your Path windows environment variable +(Example: Path=C:\Users\rakhil\go\src\github.com\ibmdb\go_ibm_db\installer\clidriver\bin) + + +``` + +## How to Install in Linux/Mac +``` +go get -d github.com/ibmdb/go_ibm_db + +If you already have a cli driver available in your system, set the below environment variables with the clidriver path + +export DB2HOME=/home/rakhil/dsdriver +export CGO_CFLAGS=-I$DB2HOME/include +export CGO_LDFLAGS=-L$DB2HOME/lib +Linux: +export LD_LIBRARY_PATH=/home/rakhil/dsdriver/lib +Mac: +export DYLD_LIBRARY_PATH=$DYLD_LIBRARY_PATH:/Applications/dsdriver/lib + +If you do not have a clidriver available in your system +go to installer folder where go_ibm_db is downloaded in your system (Example: /home/uname/go/src/github.com/imdb/go_ibm_db/installer) and run setup.go file (go run setup.go) +where uname is the username + +Above command will download clidriver. + +Set the below envronment variables with the path of the clidriver downloaded + +export DB2HOME=/home/uname/go/src/github.com/imdb/go_ibm_db/installer/clidriver +export CGO_CFLAGS=-I$DB2HOME/include +export CGO_LDFLAGS=-L$DB2HOME/lib +Linux: +export LD_LIBRARY_PATH=/home/uname/go/src/github.com/ibmdb/go_ibm_db/installer/clidriver/lib +Mac: +export DYLD_LIBRARY_PATH=$DYLD_LIBRARY_PATH:/home/uname/go/src/github.com/ibmdb/go_ibm_db/installer/clidriver/lib + + +``` + +## How to run sample program + +### example1.go:- + +``` +package main + +import ( + _ "github.com/ibmdb/go_ibm_db" + "database/sql" + "fmt" +) + +func main(){ + con:="HOSTNAME=host;DATABASE=name;PORT=number;UID=username;PWD=password" + db, err:=sql.Open("go_ibm_db", con) + if err != nil{ + + fmt.Println(err) + } + db.Close() +} +To run the sample:- go run example1.go +``` + +### example2.go:- + +``` +package main + +import ( + _ "github.com/ibmdb/go_ibm_db" + "database/sql" + "fmt" +) + +func Create_Con(con string) *sql.DB{ + db, err:=sql.Open("go_ibm_db", con) + if err != nil{ + + fmt.Println(err) + return nil + } + return db +} + +//creating a table + +func create(db *sql.DB) error{ + _,err:=db.Exec("DROP table SAMPLE") + if(err!=nil){ + _,err:=db.Exec("create table SAMPLE(ID varchar(20),NAME varchar(20),LOCATION varchar(20),POSITION varchar(20))") + if err != nil{ + return err + } + } else { + _,err:=db.Exec("create table SAMPLE(ID varchar(20),NAME varchar(20),LOCATION varchar(20),POSITION varchar(20))") + if err != nil{ + return err + } + } + fmt.Println("TABLE CREATED") + return nil +} + +//inserting row + +func insert(db *sql.DB) error{ + st, err:=db.Prepare("Insert into SAMPLE(ID,NAME,LOCATION,POSITION) values('3242','mike','hyd','manager')") + if err != nil{ + return err + } + st.Query() + return nil +} + +//this api selects the data from the table and prints it + +func display(db *sql.DB) error{ + st, err:=db.Prepare("select * from SAMPLE") + if err !=nil{ + return err + } + err=execquery(st) + if err!=nil{ + return err + } + return nil +} + + +func execquery(st *sql.Stmt) error{ + rows,err :=st.Query() + if err != nil{ + return err + } + cols, _ := rows.Columns() + fmt.Printf("%s %s %s %s\n",cols[0],cols[1],cols[2],cols[3]) + fmt.Println("-------------------------------------") + defer rows.Close() + for rows.Next(){ + var t,x,m,n string + err = rows.Scan(&t,&x,&m,&n) + if err != nil{ + return err + } + fmt.Printf("%v %v %v %v\n",t,x,m,n) + } + return nil +} + +func main(){ + con:="HOSTNAME=host;DATABASE=name;PORT=number;UID=username;PWD=password" + type Db *sql.DB + var re Db + re=Create_Con(con) + err:=create(re) + if err != nil{ + fmt.Println(err) + } + err=insert(re) + if err != nil{ + fmt.Println(err) + } + err=display(re) + if err != nil{ + fmt.Println(err) + } +} +To run the sample:- go run example2.go +``` + +### example3.go:-(POOLING) + +``` +package main + +import ( + a "github.com/ibmdb/go_ibm_db" + _"database/sql" + "fmt" +) + +func main(){ + con:="HOSTNAME=host;PORT=number;DATABASE=name;UID=username;PWD=password"; + pool:=a.Pconnect("PoolSize=100") + + //SetConnMaxLifetime will atake the value in SECONDS + db:=pool.Open(con,"SetConnMaxLifetime=30") + st, err:=db.Prepare("Insert into SAMPLE values('hi','hi','hi','hi')") + if err != nil{ + fmt.Println(err) + } + st.Query() + + //Here the the time out is default. + db1:=pool.Open(con) + st1, err:=db1.Prepare("Insert into SAMPLE values('hi1','hi1','hi1','hi1')") + if err != nil{ + fmt.Println(err) + } + st1.Query() + + db1.Close() + db.Close() + pool.Display() + pool.Release() + pool.Display() +} +To run the sample:- go run example3.go +``` +For Running the Tests: +====================== + +1) Put your connection string in the main.go file in testdata folder + +2) Now run go test command (use go test -v command for details) + + diff --git a/src/github.com/ibmdb/go_ibm_db/api/Makefile b/src/github.com/ibmdb/go_ibm_db/api/Makefile new file mode 100644 index 0000000..2bdd255 --- /dev/null +++ b/src/github.com/ibmdb/go_ibm_db/api/Makefile @@ -0,0 +1,15 @@ +# Copyright 2012 The Go Authors. All rights reserved. +# Use of this source code is governed by a BSD-style +# license that can be found in the LICENSE file. + +all: zapi_windows.go zapi_unix.go + +zapi_windows.go: api.go + $(GOROOT)/src/pkg/syscall/mksyscall_windows.pl $^ \ + | gofmt \ + > $@ + +zapi_unix.go: api.go + ./mksyscall_unix.pl $^ \ + | gofmt \ + > $@ diff --git a/src/github.com/ibmdb/go_ibm_db/api/api.go b/src/github.com/ibmdb/go_ibm_db/api/api.go new file mode 100644 index 0000000..aa7abae --- /dev/null +++ b/src/github.com/ibmdb/go_ibm_db/api/api.go @@ -0,0 +1,68 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package api + +import ( + "unicode/utf16" +) + +type ( + SQL_DATE_STRUCT struct { + Year SQLSMALLINT + Month SQLUSMALLINT + Day SQLUSMALLINT + } + + SQL_TIMESTAMP_STRUCT struct { + Year SQLSMALLINT + Month SQLUSMALLINT + Day SQLUSMALLINT + Hour SQLUSMALLINT + Minute SQLUSMALLINT + Second SQLUSMALLINT + Fraction SQLUINTEGER + } +) + +//sys SQLAllocHandle(handleType SQLSMALLINT, inputHandle SQLHANDLE, outputHandle *SQLHANDLE) (ret SQLRETURN) = odbc32.SQLAllocHandle +//sys SQLBindCol(statementHandle SQLHSTMT, columnNumber SQLUSMALLINT, targetType SQLSMALLINT, targetValuePtr SQLPOINTER, bufferLength SQLLEN, vallen *SQLLEN) (ret SQLRETURN) = odbc32.SQLBindCol +//sys SQLBindParameter(statementHandle SQLHSTMT, parameterNumber SQLUSMALLINT, inputOutputType SQLSMALLINT, valueType SQLSMALLINT, parameterType SQLSMALLINT, columnSize SQLULEN, decimalDigits SQLSMALLINT, parameterValue SQLPOINTER, bufferLength SQLLEN, ind *SQLLEN) (ret SQLRETURN) = odbc32.SQLBindParameter +//sys SQLCloseCursor(statementHandle SQLHSTMT) (ret SQLRETURN) = odbc32.SQLCloseCursor +//sys SQLDescribeCol(statementHandle SQLHSTMT, columnNumber SQLUSMALLINT, columnName *SQLWCHAR, bufferLength SQLSMALLINT, nameLengthPtr *SQLSMALLINT, dataTypePtr *SQLSMALLINT, columnSizePtr *SQLULEN, decimalDigitsPtr *SQLSMALLINT, nullablePtr *SQLSMALLINT) (ret SQLRETURN) = odbc32.SQLDescribeColW +//sys SQLDescribeParam(statementHandle SQLHSTMT, parameterNumber SQLUSMALLINT, dataTypePtr *SQLSMALLINT, parameterSizePtr *SQLULEN, decimalDigitsPtr *SQLSMALLINT, nullablePtr *SQLSMALLINT) (ret SQLRETURN) = odbc32.SQLDescribeParam +//sys SQLDisconnect(connectionHandle SQLHDBC) (ret SQLRETURN) = odbc32.SQLDisconnect +//sys SQLDriverConnect(connectionHandle SQLHDBC, windowHandle SQLHWND, inConnectionString *SQLWCHAR, stringLength1 SQLSMALLINT, outConnectionString *SQLWCHAR, bufferLength SQLSMALLINT, stringLength2Ptr *SQLSMALLINT, driverCompletion SQLUSMALLINT) (ret SQLRETURN) = odbc32.SQLDriverConnectW +//sys SQLEndTran(handleType SQLSMALLINT, handle SQLHANDLE, completionType SQLSMALLINT) (ret SQLRETURN) = odbc32.SQLEndTran +//sys SQLExecute(statementHandle SQLHSTMT) (ret SQLRETURN) = odbc32.SQLExecute +//sys SQLFetch(statementHandle SQLHSTMT) (ret SQLRETURN) = odbc32.SQLFetch +//sys SQLFreeHandle(handleType SQLSMALLINT, handle SQLHANDLE) (ret SQLRETURN) = odbc32.SQLFreeHandle +//sys SQLGetData(statementHandle SQLHSTMT, colOrParamNum SQLUSMALLINT, targetType SQLSMALLINT, targetValuePtr SQLPOINTER, bufferLength SQLLEN, vallen *SQLLEN) (ret SQLRETURN) = odbc32.SQLGetData +//sys SQLGetDiagRec(handleType SQLSMALLINT, handle SQLHANDLE, recNumber SQLSMALLINT, sqlState *SQLWCHAR, nativeErrorPtr *SQLINTEGER, messageText *SQLWCHAR, bufferLength SQLSMALLINT, textLengthPtr *SQLSMALLINT) (ret SQLRETURN) = odbc32.SQLGetDiagRecW +//sys SQLNumParams(statementHandle SQLHSTMT, parameterCountPtr *SQLSMALLINT) (ret SQLRETURN) = odbc32.SQLNumParams +//sys SQLNumResultCols(statementHandle SQLHSTMT, columnCountPtr *SQLSMALLINT) (ret SQLRETURN) = odbc32.SQLNumResultCols +//sys SQLPrepare(statementHandle SQLHSTMT, statementText *SQLWCHAR, textLength SQLINTEGER) (ret SQLRETURN) = odbc32.SQLPrepareW +//sys SQLRowCount(statementHandle SQLHSTMT, rowCountPtr *SQLLEN) (ret SQLRETURN) = odbc32.SQLRowCount +//sys SQLSetEnvAttr(environmentHandle SQLHENV, attribute SQLINTEGER, valuePtr SQLPOINTER, stringLength SQLINTEGER) (ret SQLRETURN) = odbc32.SQLSetEnvAttr +//sys SQLSetConnectAttr(connectionHandle SQLHDBC, attribute SQLINTEGER, valuePtr SQLPOINTER, stringLength SQLINTEGER) (ret SQLRETURN) = odbc32.SQLSetConnectAttrW + +// UTF16ToString returns the UTF-8 encoding of the UTF-16 sequence s, +// with a terminating NUL removed. +func UTF16ToString(s []uint16) string { + for i, v := range s { + if v == 0 { + s = s[0:i] + break + } + } + return string(utf16.Decode(s)) +} + +// StringToUTF16 returns the UTF-16 encoding of the UTF-8 string s, +// with a terminating NUL added. +func StringToUTF16(s string) []uint16 { return utf16.Encode([]rune(s + "\x00")) } + +// StringToUTF16Ptr returns pointer to the UTF-16 encoding of +// the UTF-8 string s, with a terminating NUL added. +func StringToUTF16Ptr(s string) *uint16 { return &StringToUTF16(s)[0] } diff --git a/src/github.com/ibmdb/go_ibm_db/api/api_unix.go b/src/github.com/ibmdb/go_ibm_db/api/api_unix.go new file mode 100644 index 0000000..302345d --- /dev/null +++ b/src/github.com/ibmdb/go_ibm_db/api/api_unix.go @@ -0,0 +1,137 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build darwin linux +// +build cgo + +package api + +// #cgo darwin LDFLAGS: -ldb2 +// #cgo linux LDFLAGS: -ldb2 +// #include +import "C" + +const ( + SQL_OV_ODBC3 = uintptr(C.SQL_OV_ODBC3) + + SQL_ATTR_ODBC_VERSION = C.SQL_ATTR_ODBC_VERSION + + SQL_DRIVER_NOPROMPT = C.SQL_DRIVER_NOPROMPT + + SQL_HANDLE_ENV = C.SQL_HANDLE_ENV + SQL_HANDLE_DBC = C.SQL_HANDLE_DBC + SQL_HANDLE_STMT = C.SQL_HANDLE_STMT + + SQL_SUCCESS = C.SQL_SUCCESS + SQL_SUCCESS_WITH_INFO = C.SQL_SUCCESS_WITH_INFO + SQL_INVALID_HANDLE = C.SQL_INVALID_HANDLE + SQL_NO_DATA = C.SQL_NO_DATA + SQL_NO_TOTAL = C.SQL_NO_TOTAL + SQL_NTS = C.SQL_NTS + SQL_MAX_MESSAGE_LENGTH = C.SQL_MAX_MESSAGE_LENGTH + SQL_NULL_HANDLE = uintptr(C.SQL_NULL_HANDLE) + SQL_NULL_HENV = uintptr(C.SQL_NULL_HENV) + SQL_NULL_HDBC = uintptr(C.SQL_NULL_HDBC) + SQL_NULL_HSTMT = uintptr(C.SQL_NULL_HSTMT) + + SQL_PARAM_INPUT = C.SQL_PARAM_INPUT + + SQL_NULL_DATA = C.SQL_NULL_DATA + SQL_DATA_AT_EXEC = C.SQL_DATA_AT_EXEC + + SQL_UNKNOWN_TYPE = C.SQL_UNKNOWN_TYPE + SQL_CHAR = C.SQL_CHAR + SQL_NUMERIC = C.SQL_NUMERIC + SQL_DECIMAL = C.SQL_DECIMAL + SQL_INTEGER = C.SQL_INTEGER + SQL_SMALLINT = C.SQL_SMALLINT + SQL_FLOAT = C.SQL_FLOAT + SQL_REAL = C.SQL_REAL + SQL_DOUBLE = C.SQL_DOUBLE + SQL_DATETIME = C.SQL_DATETIME + SQL_DATE = C.SQL_DATE + SQL_TIME = C.SQL_TIME + SQL_VARCHAR = C.SQL_VARCHAR + SQL_TYPE_DATE = C.SQL_TYPE_DATE + SQL_TYPE_TIME = C.SQL_TYPE_TIME + SQL_TYPE_TIMESTAMP = C.SQL_TYPE_TIMESTAMP + SQL_TIMESTAMP = C.SQL_TIMESTAMP + SQL_LONGVARCHAR = C.SQL_LONGVARCHAR + SQL_BINARY = C.SQL_BINARY + SQL_VARBINARY = C.SQL_VARBINARY + SQL_LONGVARBINARY = C.SQL_LONGVARBINARY + SQL_BIGINT = C.SQL_BIGINT + SQL_TINYINT = C.SQL_TINYINT + SQL_BIT = C.SQL_BIT + SQL_WCHAR = C.SQL_WCHAR + SQL_WVARCHAR = C.SQL_WVARCHAR + SQL_WLONGVARCHAR = C.SQL_WLONGVARCHAR + SQL_GUID = C.SQL_GUID + SQL_BLOB = C.SQL_BLOB + SQL_CLOB = C.SQL_CLOB + SQL_SIGNED_OFFSET = C.SQL_SIGNED_OFFSET + SQL_UNSIGNED_OFFSET = C.SQL_UNSIGNED_OFFSET + + // TODO(lukemauldin): Not defined in sqlext.h. Using windows value, but it is not supported. + SQL_SS_XML = -152 + + SQL_C_CHAR = C.SQL_C_CHAR + SQL_C_LONG = C.SQL_C_LONG + SQL_C_SHORT = C.SQL_C_SHORT + SQL_C_FLOAT = C.SQL_C_FLOAT + SQL_C_DOUBLE = C.SQL_C_DOUBLE + SQL_C_NUMERIC = C.SQL_C_NUMERIC + SQL_C_DATE = C.SQL_C_DATE + SQL_C_TIME = C.SQL_C_TIME + SQL_C_TYPE_TIMESTAMP = C.SQL_C_TYPE_TIMESTAMP + SQL_C_TIMESTAMP = C.SQL_C_TIMESTAMP + SQL_C_BINARY = C.SQL_C_BINARY + SQL_C_BIT = C.SQL_C_BIT + SQL_C_WCHAR = C.SQL_C_WCHAR + SQL_C_DEFAULT = C.SQL_C_DEFAULT + SQL_C_SBIGINT = C.SQL_C_SBIGINT + SQL_C_UBIGINT = C.SQL_C_UBIGINT + SQL_C_GUID = C.SQL_C_GUID + + SQL_COMMIT = C.SQL_COMMIT + SQL_ROLLBACK = C.SQL_ROLLBACK + + SQL_AUTOCOMMIT = C.SQL_AUTOCOMMIT + SQL_ATTR_AUTOCOMMIT = C.SQL_ATTR_AUTOCOMMIT + SQL_AUTOCOMMIT_OFF = C.SQL_AUTOCOMMIT_OFF + SQL_AUTOCOMMIT_ON = C.SQL_AUTOCOMMIT_ON + SQL_AUTOCOMMIT_DEFAULT = C.SQL_AUTOCOMMIT_DEFAULT + + SQL_IS_UINTEGER = C.SQL_IS_UINTEGER + + //Connection pooling + SQL_ATTR_CONNECTION_POOLING = C.SQL_ATTR_CONNECTION_POOLING + SQL_ATTR_CP_MATCH = C.SQL_ATTR_CP_MATCH + SQL_CP_OFF = uintptr(C.SQL_CP_OFF) + SQL_CP_ONE_PER_DRIVER = uintptr(C.SQL_CP_ONE_PER_DRIVER) + SQL_CP_ONE_PER_HENV = uintptr(C.SQL_CP_ONE_PER_HENV) + SQL_CP_DEFAULT = SQL_CP_OFF + SQL_CP_STRICT_MATCH = uintptr(C.SQL_CP_STRICT_MATCH) + SQL_CP_RELAXED_MATCH = uintptr(C.SQL_CP_RELAXED_MATCH) +) + +type ( + SQLHANDLE C.SQLHANDLE + SQLHENV C.SQLHENV + SQLHDBC C.SQLHDBC + SQLHSTMT C.SQLHSTMT + SQLHWND uintptr + + SQLWCHAR C.SQLWCHAR + SQLSCHAR C.SQLSCHAR + SQLSMALLINT C.SQLSMALLINT + SQLUSMALLINT C.SQLUSMALLINT + SQLINTEGER C.SQLINTEGER + SQLUINTEGER C.SQLUINTEGER + SQLPOINTER C.SQLPOINTER + SQLRETURN C.SQLRETURN + + SQLLEN C.SQLLEN + SQLULEN C.SQLULEN +) diff --git a/src/github.com/ibmdb/go_ibm_db/api/api_windows.go b/src/github.com/ibmdb/go_ibm_db/api/api_windows.go new file mode 100644 index 0000000..e3eba8f --- /dev/null +++ b/src/github.com/ibmdb/go_ibm_db/api/api_windows.go @@ -0,0 +1,133 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package api + +const ( + SQL_OV_ODBC3 = 3 + + SQL_ATTR_ODBC_VERSION = 200 + + SQL_DRIVER_NOPROMPT = 0 + + SQL_HANDLE_ENV = 1 + SQL_HANDLE_DBC = 2 + SQL_HANDLE_STMT = 3 + + SQL_SUCCESS = 0 + SQL_SUCCESS_WITH_INFO = 1 + SQL_INVALID_HANDLE = -2 + SQL_NO_DATA = 100 + SQL_NO_TOTAL = -4 + SQL_NTS = -3 + SQL_MAX_MESSAGE_LENGTH = 512 + SQL_NULL_HANDLE = 0 + SQL_NULL_HENV = 0 + SQL_NULL_HDBC = 0 + SQL_NULL_HSTMT = 0 + + SQL_PARAM_INPUT = 1 + + SQL_NULL_DATA = -1 + SQL_DATA_AT_EXEC = -2 + + SQL_UNKNOWN_TYPE = 0 + SQL_CHAR = 1 + SQL_NUMERIC = 2 + SQL_DECIMAL = 3 + SQL_INTEGER = 4 + SQL_SMALLINT = 5 + SQL_FLOAT = 6 + SQL_REAL = 7 + SQL_DOUBLE = 8 + SQL_DATETIME = 9 + SQL_DATE = 9 + SQL_TIME = 10 + SQL_VARCHAR = 12 + SQL_TYPE_DATE = 91 + SQL_TYPE_TIME = 92 + SQL_TYPE_TIMESTAMP = 93 + SQL_TIMESTAMP = 11 + SQL_LONGVARCHAR = -1 + SQL_BINARY = -2 + SQL_VARBINARY = -3 + SQL_LONGVARBINARY = -4 + SQL_BIGINT = -5 + SQL_TINYINT = -6 + SQL_BIT = -7 + SQL_WCHAR = -8 + SQL_WVARCHAR = -9 + SQL_WLONGVARCHAR = -10 + SQL_GUID = -11 + SQL_SIGNED_OFFSET = -20 + SQL_UNSIGNED_OFFSET = -22 + SQL_GRAPHIC = -95 + SQL_BLOB = -98 + SQL_CLOB = -99 + SQL_DBCLOB = -350 + SQL_SS_XML = -152 + + SQL_C_CHAR = SQL_CHAR + SQL_C_LONG = SQL_INTEGER + SQL_C_SHORT = SQL_SMALLINT + SQL_C_FLOAT = SQL_REAL + SQL_C_DOUBLE = SQL_DOUBLE + SQL_C_NUMERIC = SQL_NUMERIC + SQL_C_DATE = SQL_DATE + SQL_C_TIME = SQL_TIME + SQL_C_TYPE_TIMESTAMP = SQL_TYPE_TIMESTAMP + SQL_C_TIMESTAMP = SQL_TIMESTAMP + SQL_C_BINARY = SQL_BINARY + SQL_C_BIT = SQL_BIT + SQL_C_WCHAR = SQL_WCHAR + SQL_C_DEFAULT = 99 + SQL_C_SBIGINT = SQL_BIGINT + SQL_SIGNED_OFFSET + SQL_C_UBIGINT = SQL_BIGINT + SQL_UNSIGNED_OFFSET + SQL_C_GUID = SQL_GUID + + SQL_COMMIT = 0 + SQL_ROLLBACK = 1 + + SQL_AUTOCOMMIT = 102 + SQL_ATTR_AUTOCOMMIT = SQL_AUTOCOMMIT + SQL_AUTOCOMMIT_OFF = 0 + SQL_AUTOCOMMIT_ON = 1 + SQL_AUTOCOMMIT_DEFAULT = SQL_AUTOCOMMIT_ON + + SQL_IS_UINTEGER = -5 + + //Connection pooling + SQL_ATTR_CONNECTION_POOLING = 201 + SQL_ATTR_CP_MATCH = 202 + SQL_CP_OFF = 0 + SQL_CP_ONE_PER_DRIVER = 1 + SQL_CP_ONE_PER_HENV = 2 + SQL_CP_DEFAULT = SQL_CP_OFF + SQL_CP_STRICT_MATCH = 0 + SQL_CP_RELAXED_MATCH = 1 +) + +type ( + SQLHANDLE uintptr + SQLHENV SQLHANDLE + SQLHDBC SQLHANDLE + SQLHSTMT SQLHANDLE + SQLHWND uintptr + + SQLWCHAR uint16 + SQLSCHAR int8 + SQLSMALLINT int16 + SQLUSMALLINT uint16 + SQLINTEGER int32 + SQLUINTEGER uint32 + SQLPOINTER uintptr + SQLRETURN SQLSMALLINT + + SQLGUID struct { + Data1 uint32 + Data2 uint16 + Data3 uint16 + Data4 [8]byte + } +) diff --git a/src/github.com/ibmdb/go_ibm_db/api/api_windows_386.go b/src/github.com/ibmdb/go_ibm_db/api/api_windows_386.go new file mode 100644 index 0000000..2edf92a --- /dev/null +++ b/src/github.com/ibmdb/go_ibm_db/api/api_windows_386.go @@ -0,0 +1,10 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package api + +type ( + SQLLEN SQLINTEGER + SQLULEN SQLUINTEGER +) diff --git a/src/github.com/ibmdb/go_ibm_db/api/api_windows_amd64.go b/src/github.com/ibmdb/go_ibm_db/api/api_windows_amd64.go new file mode 100644 index 0000000..b603663 --- /dev/null +++ b/src/github.com/ibmdb/go_ibm_db/api/api_windows_amd64.go @@ -0,0 +1,10 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package api + +type ( + SQLLEN int64 + SQLULEN uint64 +) diff --git a/src/github.com/ibmdb/go_ibm_db/api/mksyscall_unix.pl b/src/github.com/ibmdb/go_ibm_db/api/mksyscall_unix.pl new file mode 100644 index 0000000..eb6ecf5 --- /dev/null +++ b/src/github.com/ibmdb/go_ibm_db/api/mksyscall_unix.pl @@ -0,0 +1,132 @@ +#!/usr/bin/perl +# Copyright 2012 The Go Authors. All rights reserved. +# Use of this source code is governed by a BSD-style +# license that can be found in the LICENSE file. + +# This program is based on $GOROOT/src/pkg/syscall/mksyscall_windows.pl. + +use strict; + +my $cmdline = "mksyscall_unix.pl " . join(' ', @ARGV); +my $errors = 0; + +binmode STDOUT; + +if($ARGV[0] =~ /^-/) { + print STDERR "usage: mksyscall_unix.pl [file ...]\n"; + exit 1; +} + +sub parseparamlist($) { + my ($list) = @_; + $list =~ s/^\s*//; + $list =~ s/\s*$//; + if($list eq "") { + return (); + } + return split(/\s*,\s*/, $list); +} + +sub parseparam($) { + my ($p) = @_; + if($p !~ /^(\S*) (\S*)$/) { + print STDERR "$ARGV:$.: malformed parameter: $p\n"; + $errors = 1; + return ("xx", "int"); + } + return ($1, $2); +} + +my $package = ""; +my $text = ""; +while(<>) { + chomp; + s/\s+/ /g; + s/^\s+//; + s/\s+$//; + $package = $1 if !$package && /^package (\S+)$/; + next if !/^\/\/sys /; + + # Line must be of the form + # func Open(path string, mode int, perm int) (fd int, err error) + # Split into name, in params, out params. + if(!/^\/\/sys (\w+)\(([^()]*)\)\s*(?:\(([^()]+)\))?\s*(?:\[failretval(.*)\])?\s*(?:=\s*(?:(\w*)\.)?(\w*))?$/) { + print STDERR "$ARGV:$.: malformed //sys declaration\n"; + $errors = 1; + next; + } + my ($func, $in, $out, $failcond, $modname, $sysname) = ($1, $2, $3, $4, $5, $6); + + # Split argument lists on comma. + my @in = parseparamlist($in); + my @out = parseparamlist($out); + + # System call name. + if($sysname eq "") { + $sysname = "$func"; + } + + # Go function header. + $out = join(', ', @out); + if($out ne "") { + $out = " ($out)"; + } + if($text ne "") { + $text .= "\n" + } + $text .= sprintf "func %s(%s)%s {\n", $func, join(', ', @in), $out; + + # Prepare arguments. + my @sqlin= (); + my @pin= (); + foreach my $p (@in) { + my ($name, $type) = parseparam($p); + + if($type =~ /^\*(SQLCHAR)/) { + push @sqlin, sprintf "(*C.%s)(unsafe.Pointer(%s))", $1, $name; + } elsif($type =~ /^\*(SQLWCHAR)/) { + push @sqlin, sprintf "(*C.%s)(unsafe.Pointer(%s))", $1, $name; + } elsif($type =~ /^\*(.*)$/) { + push @sqlin, sprintf "(*C.%s)(%s)", $1, $name; + } else { + push @sqlin, sprintf "C.%s(%s)", $type, $name; + } + push @pin, sprintf "\"%s=\", %s, ", $name, $name; + } + + $text .= sprintf "\tr := C.%s(%s)\n", $sysname, join(',', @sqlin); + if(0) { + $text .= sprintf "println(\"SYSCALL: %s(\", %s\") (\", r, \")\")\n", $func, join('", ", ', @pin); + } + $text .= "\treturn SQLRETURN(r)\n"; + $text .= "}\n"; +} + +if($errors) { + exit 1; +} + +print < +import "C" + +$text + +EOF +exit 0; diff --git a/src/github.com/ibmdb/go_ibm_db/api/zapi_unix.go b/src/github.com/ibmdb/go_ibm_db/api/zapi_unix.go new file mode 100644 index 0000000..d99a01a --- /dev/null +++ b/src/github.com/ibmdb/go_ibm_db/api/zapi_unix.go @@ -0,0 +1,118 @@ +// mksyscall_unix.pl api.go +// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT + +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build darwin linux +// +build cgo + +package api + +import "unsafe" + +// #cgo darwin LDFLAGS: -ldb2 +// #cgo linux LDFLAGS: -ldb2 +// #include +import "C" + +func SQLAllocHandle(handleType SQLSMALLINT, inputHandle SQLHANDLE, outputHandle *SQLHANDLE) (ret SQLRETURN) { + r := C.SQLAllocHandle(C.SQLSMALLINT(handleType), C.SQLHANDLE(inputHandle), (*C.SQLHANDLE)(outputHandle)) + return SQLRETURN(r) +} + +func SQLBindCol(statementHandle SQLHSTMT, columnNumber SQLUSMALLINT, targetType SQLSMALLINT, targetValuePtr SQLPOINTER, bufferLength SQLLEN, vallen *SQLLEN) (ret SQLRETURN) { + r := C.SQLBindCol(C.SQLHSTMT(statementHandle), C.SQLUSMALLINT(columnNumber), C.SQLSMALLINT(targetType), C.SQLPOINTER(targetValuePtr), C.SQLLEN(bufferLength), (*C.SQLLEN)(vallen)) + return SQLRETURN(r) +} + +func SQLBindParameter(statementHandle SQLHSTMT, parameterNumber SQLUSMALLINT, inputOutputType SQLSMALLINT, valueType SQLSMALLINT, parameterType SQLSMALLINT, columnSize SQLULEN, decimalDigits SQLSMALLINT, parameterValue SQLPOINTER, bufferLength SQLLEN, ind *SQLLEN) (ret SQLRETURN) { + r := C.SQLBindParameter(C.SQLHSTMT(statementHandle), C.SQLUSMALLINT(parameterNumber), C.SQLSMALLINT(inputOutputType), C.SQLSMALLINT(valueType), C.SQLSMALLINT(parameterType), C.SQLULEN(columnSize), C.SQLSMALLINT(decimalDigits), C.SQLPOINTER(parameterValue), C.SQLLEN(bufferLength), (*C.SQLLEN)(ind)) + return SQLRETURN(r) +} + +func SQLCloseCursor(statementHandle SQLHSTMT) (ret SQLRETURN) { + r := C.SQLCloseCursor(C.SQLHSTMT(statementHandle)) + return SQLRETURN(r) +} + +func SQLDescribeCol(statementHandle SQLHSTMT, columnNumber SQLUSMALLINT, columnName *SQLWCHAR, bufferLength SQLSMALLINT, nameLengthPtr *SQLSMALLINT, dataTypePtr *SQLSMALLINT, columnSizePtr *SQLULEN, decimalDigitsPtr *SQLSMALLINT, nullablePtr *SQLSMALLINT) (ret SQLRETURN) { + r := C.SQLDescribeColW(C.SQLHSTMT(statementHandle), C.SQLUSMALLINT(columnNumber), (*C.SQLWCHAR)(unsafe.Pointer(columnName)), C.SQLSMALLINT(bufferLength), (*C.SQLSMALLINT)(nameLengthPtr), (*C.SQLSMALLINT)(dataTypePtr), (*C.SQLULEN)(columnSizePtr), (*C.SQLSMALLINT)(decimalDigitsPtr), (*C.SQLSMALLINT)(nullablePtr)) + return SQLRETURN(r) +} + +func SQLDescribeParam(statementHandle SQLHSTMT, parameterNumber SQLUSMALLINT, dataTypePtr *SQLSMALLINT, parameterSizePtr *SQLULEN, decimalDigitsPtr *SQLSMALLINT, nullablePtr *SQLSMALLINT) (ret SQLRETURN) { + r := C.SQLDescribeParam(C.SQLHSTMT(statementHandle), C.SQLUSMALLINT(parameterNumber), (*C.SQLSMALLINT)(dataTypePtr), (*C.SQLULEN)(parameterSizePtr), (*C.SQLSMALLINT)(decimalDigitsPtr), (*C.SQLSMALLINT)(nullablePtr)) + return SQLRETURN(r) +} + +func SQLDisconnect(connectionHandle SQLHDBC) (ret SQLRETURN) { + r := C.SQLDisconnect(C.SQLHDBC(connectionHandle)) + return SQLRETURN(r) +} + +func SQLDriverConnect(connectionHandle SQLHDBC, windowHandle SQLHWND, inConnectionString *SQLWCHAR, stringLength1 SQLSMALLINT, outConnectionString *SQLWCHAR, bufferLength SQLSMALLINT, stringLength2Ptr *SQLSMALLINT, driverCompletion SQLUSMALLINT) (ret SQLRETURN) { + r := C.SQLDriverConnectW(C.SQLHDBC(connectionHandle), C.SQLHWND(windowHandle), (*C.SQLWCHAR)(unsafe.Pointer(inConnectionString)), C.SQLSMALLINT(stringLength1), (*C.SQLWCHAR)(unsafe.Pointer(outConnectionString)), C.SQLSMALLINT(bufferLength), (*C.SQLSMALLINT)(stringLength2Ptr), C.SQLUSMALLINT(driverCompletion)) + return SQLRETURN(r) +} + +func SQLEndTran(handleType SQLSMALLINT, handle SQLHANDLE, completionType SQLSMALLINT) (ret SQLRETURN) { + r := C.SQLEndTran(C.SQLSMALLINT(handleType), C.SQLHANDLE(handle), C.SQLSMALLINT(completionType)) + return SQLRETURN(r) +} + +func SQLExecute(statementHandle SQLHSTMT) (ret SQLRETURN) { + r := C.SQLExecute(C.SQLHSTMT(statementHandle)) + return SQLRETURN(r) +} + +func SQLFetch(statementHandle SQLHSTMT) (ret SQLRETURN) { + r := C.SQLFetch(C.SQLHSTMT(statementHandle)) + return SQLRETURN(r) +} + +func SQLFreeHandle(handleType SQLSMALLINT, handle SQLHANDLE) (ret SQLRETURN) { + r := C.SQLFreeHandle(C.SQLSMALLINT(handleType), C.SQLHANDLE(handle)) + return SQLRETURN(r) +} + +func SQLGetData(statementHandle SQLHSTMT, colOrParamNum SQLUSMALLINT, targetType SQLSMALLINT, targetValuePtr SQLPOINTER, bufferLength SQLLEN, vallen *SQLLEN) (ret SQLRETURN) { + r := C.SQLGetData(C.SQLHSTMT(statementHandle), C.SQLUSMALLINT(colOrParamNum), C.SQLSMALLINT(targetType), C.SQLPOINTER(targetValuePtr), C.SQLLEN(bufferLength), (*C.SQLLEN)(vallen)) + return SQLRETURN(r) +} + +func SQLGetDiagRec(handleType SQLSMALLINT, handle SQLHANDLE, recNumber SQLSMALLINT, sqlState *SQLWCHAR, nativeErrorPtr *SQLINTEGER, messageText *SQLWCHAR, bufferLength SQLSMALLINT, textLengthPtr *SQLSMALLINT) (ret SQLRETURN) { + r := C.SQLGetDiagRecW(C.SQLSMALLINT(handleType), C.SQLHANDLE(handle), C.SQLSMALLINT(recNumber), (*C.SQLWCHAR)(unsafe.Pointer(sqlState)), (*C.SQLINTEGER)(nativeErrorPtr), (*C.SQLWCHAR)(unsafe.Pointer(messageText)), C.SQLSMALLINT(bufferLength), (*C.SQLSMALLINT)(textLengthPtr)) + return SQLRETURN(r) +} + +func SQLNumParams(statementHandle SQLHSTMT, parameterCountPtr *SQLSMALLINT) (ret SQLRETURN) { + r := C.SQLNumParams(C.SQLHSTMT(statementHandle), (*C.SQLSMALLINT)(parameterCountPtr)) + return SQLRETURN(r) +} + +func SQLNumResultCols(statementHandle SQLHSTMT, columnCountPtr *SQLSMALLINT) (ret SQLRETURN) { + r := C.SQLNumResultCols(C.SQLHSTMT(statementHandle), (*C.SQLSMALLINT)(columnCountPtr)) + return SQLRETURN(r) +} + +func SQLPrepare(statementHandle SQLHSTMT, statementText *SQLWCHAR, textLength SQLINTEGER) (ret SQLRETURN) { + r := C.SQLPrepareW(C.SQLHSTMT(statementHandle), (*C.SQLWCHAR)(unsafe.Pointer(statementText)), C.SQLINTEGER(textLength)) + return SQLRETURN(r) +} + +func SQLRowCount(statementHandle SQLHSTMT, rowCountPtr *SQLLEN) (ret SQLRETURN) { + r := C.SQLRowCount(C.SQLHSTMT(statementHandle), (*C.SQLLEN)(rowCountPtr)) + return SQLRETURN(r) +} + +func SQLSetEnvAttr(environmentHandle SQLHENV, attribute SQLINTEGER, valuePtr SQLPOINTER, stringLength SQLINTEGER) (ret SQLRETURN) { + r := C.SQLSetEnvAttr(C.SQLHENV(environmentHandle), C.SQLINTEGER(attribute), C.SQLPOINTER(valuePtr), C.SQLINTEGER(stringLength)) + return SQLRETURN(r) +} + +func SQLSetConnectAttr(connectionHandle SQLHDBC, attribute SQLINTEGER, valuePtr SQLPOINTER, stringLength SQLINTEGER) (ret SQLRETURN) { + r := C.SQLSetConnectAttrW(C.SQLHDBC(connectionHandle), C.SQLINTEGER(attribute), C.SQLPOINTER(valuePtr), C.SQLINTEGER(stringLength)) + return SQLRETURN(r) +} diff --git a/src/github.com/ibmdb/go_ibm_db/api/zapi_windows.go b/src/github.com/ibmdb/go_ibm_db/api/zapi_windows.go new file mode 100644 index 0000000..ce0fd0f --- /dev/null +++ b/src/github.com/ibmdb/go_ibm_db/api/zapi_windows.go @@ -0,0 +1,161 @@ +// mksyscall_windows.pl api.go +// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT + +package api + +import "unsafe" +import "syscall" +import "os" + +var ( + mododbc32 = syscall.NewLazyDLL(GetDllName()) + + procSQLAllocHandle = mododbc32.NewProc("SQLAllocHandle") + procSQLBindCol = mododbc32.NewProc("SQLBindCol") + procSQLBindParameter = mododbc32.NewProc("SQLBindParameter") + procSQLCloseCursor = mododbc32.NewProc("SQLCloseCursor") + procSQLDescribeColW = mododbc32.NewProc("SQLDescribeColW") + procSQLDescribeParam = mododbc32.NewProc("SQLDescribeParam") + procSQLDisconnect = mododbc32.NewProc("SQLDisconnect") + procSQLDriverConnectW = mododbc32.NewProc("SQLDriverConnectW") + procSQLEndTran = mododbc32.NewProc("SQLEndTran") + procSQLExecute = mododbc32.NewProc("SQLExecute") + procSQLFetch = mododbc32.NewProc("SQLFetch") + procSQLFreeHandle = mododbc32.NewProc("SQLFreeHandle") + procSQLGetData = mododbc32.NewProc("SQLGetData") + procSQLGetDiagRecW = mododbc32.NewProc("SQLGetDiagRecW") + procSQLNumParams = mododbc32.NewProc("SQLNumParams") + procSQLNumResultCols = mododbc32.NewProc("SQLNumResultCols") + procSQLPrepareW = mododbc32.NewProc("SQLPrepareW") + procSQLRowCount = mododbc32.NewProc("SQLRowCount") + procSQLSetEnvAttr = mododbc32.NewProc("SQLSetEnvAttr") + procSQLSetConnectAttrW = mododbc32.NewProc("SQLSetConnectAttrW") +) + +func GetDllName() string { + if winArch := os.Getenv("PROCESSOR_ARCHITECTURE"); winArch == "x86" { + return "db2cli.dll" + } else { + return "db2cli64.dll" + } +} + +func SQLAllocHandle(handleType SQLSMALLINT, inputHandle SQLHANDLE, outputHandle *SQLHANDLE) (ret SQLRETURN) { + r0, _, _ := syscall.Syscall(procSQLAllocHandle.Addr(), 3, uintptr(handleType), uintptr(inputHandle), uintptr(unsafe.Pointer(outputHandle))) + ret = SQLRETURN(r0) + return +} + +func SQLBindCol(statementHandle SQLHSTMT, columnNumber SQLUSMALLINT, targetType SQLSMALLINT, targetValuePtr SQLPOINTER, bufferLength SQLLEN, vallen *SQLLEN) (ret SQLRETURN) { + r0, _, _ := syscall.Syscall6(procSQLBindCol.Addr(), 6, uintptr(statementHandle), uintptr(columnNumber), uintptr(targetType), uintptr(targetValuePtr), uintptr(bufferLength), uintptr(unsafe.Pointer(vallen))) + ret = SQLRETURN(r0) + return +} + +func SQLBindParameter(statementHandle SQLHSTMT, parameterNumber SQLUSMALLINT, inputOutputType SQLSMALLINT, valueType SQLSMALLINT, parameterType SQLSMALLINT, columnSize SQLULEN, decimalDigits SQLSMALLINT, parameterValue SQLPOINTER, bufferLength SQLLEN, ind *SQLLEN) (ret SQLRETURN) { + r0, _, _ := syscall.Syscall12(procSQLBindParameter.Addr(), 10, uintptr(statementHandle), uintptr(parameterNumber), uintptr(inputOutputType), uintptr(valueType), uintptr(parameterType), uintptr(columnSize), uintptr(decimalDigits), uintptr(parameterValue), uintptr(bufferLength), uintptr(unsafe.Pointer(ind)), 0, 0) + ret = SQLRETURN(r0) + return +} + +func SQLCloseCursor(statementHandle SQLHSTMT) (ret SQLRETURN) { + r0, _, _ := syscall.Syscall(procSQLCloseCursor.Addr(), 1, uintptr(statementHandle), 0, 0) + ret = SQLRETURN(r0) + return +} + +func SQLDescribeCol(statementHandle SQLHSTMT, columnNumber SQLUSMALLINT, columnName *SQLWCHAR, bufferLength SQLSMALLINT, nameLengthPtr *SQLSMALLINT, dataTypePtr *SQLSMALLINT, columnSizePtr *SQLULEN, decimalDigitsPtr *SQLSMALLINT, nullablePtr *SQLSMALLINT) (ret SQLRETURN) { + r0, _, _ := syscall.Syscall9(procSQLDescribeColW.Addr(), 9, uintptr(statementHandle), uintptr(columnNumber), uintptr(unsafe.Pointer(columnName)), uintptr(bufferLength), uintptr(unsafe.Pointer(nameLengthPtr)), uintptr(unsafe.Pointer(dataTypePtr)), uintptr(unsafe.Pointer(columnSizePtr)), uintptr(unsafe.Pointer(decimalDigitsPtr)), uintptr(unsafe.Pointer(nullablePtr))) + ret = SQLRETURN(r0) + return +} + +func SQLDescribeParam(statementHandle SQLHSTMT, parameterNumber SQLUSMALLINT, dataTypePtr *SQLSMALLINT, parameterSizePtr *SQLULEN, decimalDigitsPtr *SQLSMALLINT, nullablePtr *SQLSMALLINT) (ret SQLRETURN) { + r0, _, _ := syscall.Syscall6(procSQLDescribeParam.Addr(), 6, uintptr(statementHandle), uintptr(parameterNumber), uintptr(unsafe.Pointer(dataTypePtr)), uintptr(unsafe.Pointer(parameterSizePtr)), uintptr(unsafe.Pointer(decimalDigitsPtr)), uintptr(unsafe.Pointer(nullablePtr))) + ret = SQLRETURN(r0) + return +} + +func SQLDisconnect(connectionHandle SQLHDBC) (ret SQLRETURN) { + r0, _, _ := syscall.Syscall(procSQLDisconnect.Addr(), 1, uintptr(connectionHandle), 0, 0) + ret = SQLRETURN(r0) + return +} + +func SQLDriverConnect(connectionHandle SQLHDBC, windowHandle SQLHWND, inConnectionString *SQLWCHAR, stringLength1 SQLSMALLINT, outConnectionString *SQLWCHAR, bufferLength SQLSMALLINT, stringLength2Ptr *SQLSMALLINT, driverCompletion SQLUSMALLINT) (ret SQLRETURN) { + r0, _, _ := syscall.Syscall9(procSQLDriverConnectW.Addr(), 8, uintptr(connectionHandle), uintptr(windowHandle), uintptr(unsafe.Pointer(inConnectionString)), uintptr(stringLength1), uintptr(unsafe.Pointer(outConnectionString)), uintptr(bufferLength), uintptr(unsafe.Pointer(stringLength2Ptr)), uintptr(driverCompletion), 0) + ret = SQLRETURN(r0) + return +} + +func SQLEndTran(handleType SQLSMALLINT, handle SQLHANDLE, completionType SQLSMALLINT) (ret SQLRETURN) { + r0, _, _ := syscall.Syscall(procSQLEndTran.Addr(), 3, uintptr(handleType), uintptr(handle), uintptr(completionType)) + ret = SQLRETURN(r0) + return +} + +func SQLExecute(statementHandle SQLHSTMT) (ret SQLRETURN) { + r0, _, _ := syscall.Syscall(procSQLExecute.Addr(), 1, uintptr(statementHandle), 0, 0) + ret = SQLRETURN(r0) + return +} + +func SQLFetch(statementHandle SQLHSTMT) (ret SQLRETURN) { + r0, _, _ := syscall.Syscall(procSQLFetch.Addr(), 1, uintptr(statementHandle), 0, 0) + ret = SQLRETURN(r0) + return +} + +func SQLFreeHandle(handleType SQLSMALLINT, handle SQLHANDLE) (ret SQLRETURN) { + r0, _, _ := syscall.Syscall(procSQLFreeHandle.Addr(), 2, uintptr(handleType), uintptr(handle), 0) + ret = SQLRETURN(r0) + return +} + +func SQLGetData(statementHandle SQLHSTMT, colOrParamNum SQLUSMALLINT, targetType SQLSMALLINT, targetValuePtr SQLPOINTER, bufferLength SQLLEN, vallen *SQLLEN) (ret SQLRETURN) { + r0, _, _ := syscall.Syscall6(procSQLGetData.Addr(), 6, uintptr(statementHandle), uintptr(colOrParamNum), uintptr(targetType), uintptr(targetValuePtr), uintptr(bufferLength), uintptr(unsafe.Pointer(vallen))) + ret = SQLRETURN(r0) + return +} + +func SQLGetDiagRec(handleType SQLSMALLINT, handle SQLHANDLE, recNumber SQLSMALLINT, sqlState *SQLWCHAR, nativeErrorPtr *SQLINTEGER, messageText *SQLWCHAR, bufferLength SQLSMALLINT, textLengthPtr *SQLSMALLINT) (ret SQLRETURN) { + r0, _, _ := syscall.Syscall9(procSQLGetDiagRecW.Addr(), 8, uintptr(handleType), uintptr(handle), uintptr(recNumber), uintptr(unsafe.Pointer(sqlState)), uintptr(unsafe.Pointer(nativeErrorPtr)), uintptr(unsafe.Pointer(messageText)), uintptr(bufferLength), uintptr(unsafe.Pointer(textLengthPtr)), 0) + ret = SQLRETURN(r0) + return +} + +func SQLNumParams(statementHandle SQLHSTMT, parameterCountPtr *SQLSMALLINT) (ret SQLRETURN) { + r0, _, _ := syscall.Syscall(procSQLNumParams.Addr(), 2, uintptr(statementHandle), uintptr(unsafe.Pointer(parameterCountPtr)), 0) + ret = SQLRETURN(r0) + return +} + +func SQLNumResultCols(statementHandle SQLHSTMT, columnCountPtr *SQLSMALLINT) (ret SQLRETURN) { + r0, _, _ := syscall.Syscall(procSQLNumResultCols.Addr(), 2, uintptr(statementHandle), uintptr(unsafe.Pointer(columnCountPtr)), 0) + ret = SQLRETURN(r0) + return +} + +func SQLPrepare(statementHandle SQLHSTMT, statementText *SQLWCHAR, textLength SQLINTEGER) (ret SQLRETURN) { + r0, _, _ := syscall.Syscall(procSQLPrepareW.Addr(), 3, uintptr(statementHandle), uintptr(unsafe.Pointer(statementText)), uintptr(textLength)) + ret = SQLRETURN(r0) + return +} + +func SQLRowCount(statementHandle SQLHSTMT, rowCountPtr *SQLLEN) (ret SQLRETURN) { + r0, _, _ := syscall.Syscall(procSQLRowCount.Addr(), 2, uintptr(statementHandle), uintptr(unsafe.Pointer(rowCountPtr)), 0) + ret = SQLRETURN(r0) + return +} + +func SQLSetEnvAttr(environmentHandle SQLHENV, attribute SQLINTEGER, valuePtr SQLPOINTER, stringLength SQLINTEGER) (ret SQLRETURN) { + r0, _, _ := syscall.Syscall6(procSQLSetEnvAttr.Addr(), 4, uintptr(environmentHandle), uintptr(attribute), uintptr(valuePtr), uintptr(stringLength), 0, 0) + ret = SQLRETURN(r0) + return +} + +func SQLSetConnectAttr(connectionHandle SQLHDBC, attribute SQLINTEGER, valuePtr SQLPOINTER, stringLength SQLINTEGER) (ret SQLRETURN) { + r0, _, _ := syscall.Syscall6(procSQLSetConnectAttrW.Addr(), 4, uintptr(connectionHandle), uintptr(attribute), uintptr(valuePtr), uintptr(stringLength), 0, 0) + ret = SQLRETURN(r0) + return +} diff --git a/src/github.com/ibmdb/go_ibm_db/column.go b/src/github.com/ibmdb/go_ibm_db/column.go new file mode 100644 index 0000000..d78e7ff --- /dev/null +++ b/src/github.com/ibmdb/go_ibm_db/column.go @@ -0,0 +1,283 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package go_ibm_db + +import ( + "database/sql/driver" + "errors" + "fmt" + "time" + "unsafe" + + "github.com/ibmdb/go_ibm_db/api" +) + +type BufferLen api.SQLLEN + +func (l *BufferLen) IsNull() bool { + return int16(*l) == api.SQL_NULL_DATA +} + +func (l *BufferLen) GetData(h api.SQLHSTMT, idx int, ctype api.SQLSMALLINT, buf []byte) api.SQLRETURN { + return api.SQLGetData(h, api.SQLUSMALLINT(idx+1), ctype, + api.SQLPOINTER(unsafe.Pointer(&buf[0])), api.SQLLEN(len(buf)), + (*api.SQLLEN)(l)) +} + +func (l *BufferLen) Bind(h api.SQLHSTMT, idx int, ctype api.SQLSMALLINT, buf []byte) api.SQLRETURN { + return api.SQLBindCol(h, api.SQLUSMALLINT(idx+1), ctype, + api.SQLPOINTER(unsafe.Pointer(&buf[0])), api.SQLLEN(len(buf)), + (*api.SQLLEN)(l)) +} + +// Column provides access to row columns. +type Column interface { + Name() string + Bind(h api.SQLHSTMT, idx int) (bool, error) + Value(h api.SQLHSTMT, idx int) (driver.Value, error) +} + +func describeColumn(h api.SQLHSTMT, idx int, namebuf []uint16) (namelen int, sqltype api.SQLSMALLINT, size api.SQLULEN, ret api.SQLRETURN) { + var l, decimal, nullable api.SQLSMALLINT + ret = api.SQLDescribeCol(h, api.SQLUSMALLINT(idx+1), + (*api.SQLWCHAR)(unsafe.Pointer(&namebuf[0])), + api.SQLSMALLINT(len(namebuf)), &l, + &sqltype, &size, &decimal, &nullable) + return int(l), sqltype, size, ret +} + +// TODO(brainman): did not check for MS SQL timestamp + +func NewColumn(h api.SQLHSTMT, idx int) (Column, error) { + namebuf := make([]uint16, 150) + namelen, sqltype, size, ret := describeColumn(h, idx, namebuf) + if ret == api.SQL_SUCCESS_WITH_INFO && namelen > len(namebuf) { + // try again with bigger buffer + namebuf = make([]uint16, namelen) + namelen, sqltype, size, ret = describeColumn(h, idx, namebuf) + } + if IsError(ret) { + return nil, NewError("SQLDescribeCol", h) + } + if namelen > len(namebuf) { + // still complaining about buffer size + return nil, errors.New("Failed to allocate column name buffer") + } + b := &BaseColumn{ + name: api.UTF16ToString(namebuf[:namelen]), + } + switch sqltype { + case api.SQL_BIT: + return NewBindableColumn(b, api.SQL_C_BIT, 1), nil + case api.SQL_TINYINT, api.SQL_SMALLINT, api.SQL_INTEGER: + return NewBindableColumn(b, api.SQL_C_LONG, 4), nil + case api.SQL_BIGINT: + return NewBindableColumn(b, api.SQL_C_SBIGINT, 8), nil + case api.SQL_NUMERIC, api.SQL_DECIMAL, api.SQL_FLOAT, api.SQL_REAL, api.SQL_DOUBLE: + return NewBindableColumn(b, api.SQL_C_DOUBLE, 8), nil + case api.SQL_TYPE_TIMESTAMP: + var v api.SQL_TIMESTAMP_STRUCT + return NewBindableColumn(b, api.SQL_C_TYPE_TIMESTAMP, int(unsafe.Sizeof(v))), nil + case api.SQL_TYPE_DATE: + var v api.SQL_DATE_STRUCT + return NewBindableColumn(b, api.SQL_C_DATE, int(unsafe.Sizeof(v))), nil + case api.SQL_CHAR, api.SQL_VARCHAR, api.SQL_CLOB: + return NewVariableWidthColumn(b, api.SQL_C_CHAR, size), nil + case api.SQL_WCHAR, api.SQL_WVARCHAR: + return NewVariableWidthColumn(b, api.SQL_C_WCHAR, size), nil + case api.SQL_BINARY, api.SQL_VARBINARY, api.SQL_BLOB: + return NewVariableWidthColumn(b, api.SQL_C_BINARY, size), nil + case api.SQL_LONGVARCHAR: + return NewVariableWidthColumn(b, api.SQL_C_CHAR, 0), nil + case api.SQL_WLONGVARCHAR, api.SQL_SS_XML: + return NewVariableWidthColumn(b, api.SQL_C_WCHAR, 0), nil + case api.SQL_LONGVARBINARY: + return NewVariableWidthColumn(b, api.SQL_C_BINARY, 0), nil + default: + return nil, fmt.Errorf("unsupported column type %d", sqltype) + } + panic("unreachable") +} + +// BaseColumn implements common column functionality. +type BaseColumn struct { + name string + CType api.SQLSMALLINT +} + +func (c *BaseColumn) Name() string { + return c.name +} + +func (c *BaseColumn) Value(buf []byte) (driver.Value, error) { + var p unsafe.Pointer + if len(buf) > 0 { + p = unsafe.Pointer(&buf[0]) + } + switch c.CType { + case api.SQL_C_BIT: + return buf[0] != 0, nil + case api.SQL_C_LONG: + return *((*int32)(p)), nil + case api.SQL_C_SBIGINT: + return *((*int64)(p)), nil + case api.SQL_C_DOUBLE: + return *((*float64)(p)), nil + case api.SQL_C_CHAR: + return buf, nil + case api.SQL_C_WCHAR: + if p == nil { + return nil, nil + } + s := (*[1 << 20]uint16)(p)[:len(buf)/2] + return utf16toutf8(s), nil + case api.SQL_C_TYPE_TIMESTAMP: + t := (*api.SQL_TIMESTAMP_STRUCT)(p) + r := time.Date(int(t.Year), time.Month(t.Month), int(t.Day), + int(t.Hour), int(t.Minute), int(t.Second), int(t.Fraction), + time.Local) + return r, nil + case api.SQL_C_DATE: + t := (*api.SQL_DATE_STRUCT)(p) + r := time.Date(int(t.Year), time.Month(t.Month), int(t.Day), + 0, 0, 0, 0, time.Local) + return r, nil + case api.SQL_C_BINARY: + return buf, nil + } + return nil, fmt.Errorf("unsupported column ctype %d", c.CType) +} + +// BindableColumn allows access to columns that can have their buffers +// bound. Once bound at start, they are written to by odbc driver every +// time it fetches new row. This saves on syscall and, perhaps, some +// buffer copying. BindableColumn can be left unbound, then it behaves +// like NonBindableColumn when user reads data from it. +type BindableColumn struct { + *BaseColumn + IsBound bool + IsVariableWidth bool + Size int + Len BufferLen + Buffer []byte + smallBuf [8]byte // small inline memory buffer, so we do not need allocate external memory all the time +} + +func NewBindableColumn(b *BaseColumn, ctype api.SQLSMALLINT, bufSize int) *BindableColumn { + b.CType = ctype + c := &BindableColumn{BaseColumn: b, Size: bufSize} + if c.Size <= len(c.smallBuf) { + // use inline buffer + c.Buffer = c.smallBuf[:c.Size] + } else { + c.Buffer = make([]byte, c.Size) + } + return c +} + +func NewVariableWidthColumn(b *BaseColumn, ctype api.SQLSMALLINT, colWidth api.SQLULEN) Column { + if colWidth == 0 { + b.CType = ctype + return &NonBindableColumn{b} + } + l := int(colWidth) + switch ctype { + case api.SQL_C_WCHAR: + l += 1 // room for null-termination character + l *= 2 // wchars take 2 bytes each + case api.SQL_C_CHAR: + l += 1 // room for null-termination character + case api.SQL_C_BINARY: + // nothing to do + default: + panic(fmt.Errorf("do not know how wide column of ctype %d is", ctype)) + } + c := NewBindableColumn(b, ctype, l) + c.IsVariableWidth = true + return c +} + +func (c *BindableColumn) Bind(h api.SQLHSTMT, idx int) (bool, error) { + ret := c.Len.Bind(h, idx, c.CType, c.Buffer) + if IsError(ret) { + return false, NewError("SQLBindCol", h) + } + c.IsBound = true + return true, nil +} + +func (c *BindableColumn) Value(h api.SQLHSTMT, idx int) (driver.Value, error) { + if !c.IsBound { + ret := c.Len.GetData(h, idx, c.CType, c.Buffer) + if IsError(ret) { + return nil, NewError("SQLGetData", h) + } + } + if c.Len.IsNull() { + // is NULL + + return nil, nil + } + if !c.IsVariableWidth && int(c.Len) != c.Size { + panic(fmt.Errorf("wrong column #%d length %d returned, %d expected", idx, c.Len, c.Size)) + } + return c.BaseColumn.Value(c.Buffer[:c.Len]) +} + +// NonBindableColumn provide access to columns, that can't be bound. +// These are of character or binary type, and, usually, there is no +// limit for their width. +type NonBindableColumn struct { + *BaseColumn +} + +func (c *NonBindableColumn) Bind(h api.SQLHSTMT, idx int) (bool, error) { + return false, nil +} + +func (c *NonBindableColumn) Value(h api.SQLHSTMT, idx int) (driver.Value, error) { + var l BufferLen + var total []byte + b := make([]byte, 1024) +loop: + for { + ret := l.GetData(h, idx, c.CType, b) + switch ret { + case api.SQL_SUCCESS: + if l.IsNull() { + // is NULL + return nil, nil + } + total = append(total, b[:l]...) + break loop + case api.SQL_SUCCESS_WITH_INFO: + err := NewError("SQLGetData", h).(*Error) + if len(err.Diag) > 0 && err.Diag[0].State != "01004" { + return nil, err + } + i := len(b) + switch c.CType { + case api.SQL_C_WCHAR: + i -= 2 // remove wchar (2 bytes) null-termination character + case api.SQL_C_CHAR: + i-- // remove null-termination character + } + total = append(total, b[:i]...) + if l != api.SQL_NO_TOTAL { + // odbc gives us a hint about remaining data, + // lets get it in one go. + n := int(l) // total bytes for our data + n -= i // subtract already received + n += 2 // room for biggest (wchar) null-terminator + if len(b) < n { + b = make([]byte, n) + } + } + default: + return nil, NewError("SQLGetData", h) + } + } + return c.BaseColumn.Value(total) +} diff --git a/src/github.com/ibmdb/go_ibm_db/conn.go b/src/github.com/ibmdb/go_ibm_db/conn.go new file mode 100644 index 0000000..ef4a2e3 --- /dev/null +++ b/src/github.com/ibmdb/go_ibm_db/conn.go @@ -0,0 +1,47 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package go_ibm_db + +import ( + "database/sql/driver" + "unsafe" + + "github.com/ibmdb/go_ibm_db/api" +) + +type Conn struct { + h api.SQLHDBC + tx *Tx +} + +func (d *Driver) Open(dsn string) (driver.Conn, error) { + var out api.SQLHANDLE + ret := api.SQLAllocHandle(api.SQL_HANDLE_DBC, api.SQLHANDLE(d.h), &out) + if IsError(ret) { + return nil, NewError("SQLAllocHandle", d.h) + } + h := api.SQLHDBC(out) + drv.Stats.updateHandleCount(api.SQL_HANDLE_DBC, 1) + + b := api.StringToUTF16(dsn) + ret = api.SQLDriverConnect(h, 0, + (*api.SQLWCHAR)(unsafe.Pointer(&b[0])), api.SQLSMALLINT(len(b)), + nil, 0, nil, api.SQL_DRIVER_NOPROMPT) + if IsError(ret) { + defer releaseHandle(h) + return nil, NewError("SQLDriverConnect", h) + } + return &Conn{h: h}, nil +} + +func (c *Conn) Close() error { + ret := api.SQLDisconnect(c.h) + if IsError(ret) { + return NewError("SQLDisconnect", c.h) + } + h := c.h + c.h = api.SQLHDBC(api.SQL_NULL_HDBC) + return releaseHandle(h) +} diff --git a/src/github.com/ibmdb/go_ibm_db/driver.go b/src/github.com/ibmdb/go_ibm_db/driver.go new file mode 100644 index 0000000..29304b1 --- /dev/null +++ b/src/github.com/ibmdb/go_ibm_db/driver.go @@ -0,0 +1,60 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package odbc implements database/sql driver to access data via odbc interface. +// +package go_ibm_db + +import ( + "database/sql" + + "github.com/ibmdb/go_ibm_db/api" +) + +var drv Driver + +type Driver struct { + Stats + h api.SQLHENV // environment handle +} + +func initDriver() error { + + //Allocate environment handle + var out api.SQLHANDLE + in := api.SQLHANDLE(api.SQL_NULL_HANDLE) + ret := api.SQLAllocHandle(api.SQL_HANDLE_ENV, in, &out) + if IsError(ret) { + return NewError("SQLAllocHandle", api.SQLHENV(in)) + } + drv.h = api.SQLHENV(out) + drv.Stats.updateHandleCount(api.SQL_HANDLE_ENV, 1) + + // will use ODBC v3 + ret = api.SQLSetEnvAttr(drv.h, api.SQL_ATTR_ODBC_VERSION, + api.SQLPOINTER(api.SQL_OV_ODBC3), 0) + if IsError(ret) { + defer releaseHandle(drv.h) + return NewError("SQLSetEnvAttr ODBC v3", drv.h) + } + + return nil +} + +func (d *Driver) Close() error { + // TODO(brainman): who will call (*Driver).Close (to dispose all opened handles)? + h := d.h + d.h = api.SQLHENV(api.SQL_NULL_HENV) + return releaseHandle(h) +} + +func init() { + err := initDriver() + if err != nil { + panic(err) + } + //go's to databse/sql/sql.go 43 line + sql.Register("go_ibm_db", &drv) + +} diff --git a/src/github.com/ibmdb/go_ibm_db/error.go b/src/github.com/ibmdb/go_ibm_db/error.go new file mode 100644 index 0000000..7c56133 --- /dev/null +++ b/src/github.com/ibmdb/go_ibm_db/error.go @@ -0,0 +1,72 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package go_ibm_db + +import ( + "github.com/ibmdb/go_ibm_db/api" + "database/sql/driver" + "fmt" + "strings" + "unsafe" +) + +func IsError(ret api.SQLRETURN) bool { + return !(ret == api.SQL_SUCCESS || ret == api.SQL_SUCCESS_WITH_INFO) +} + +type DiagRecord struct { + State string + NativeError int + Message string +} + +func (r *DiagRecord) String() string { + return fmt.Sprintf("{%s} %s", r.State, r.Message) +} + +type Error struct { + APIName string + Diag []DiagRecord +} + +func (e *Error) Error() string { + ss := make([]string, len(e.Diag)) + for i, r := range e.Diag { + ss[i] = r.String() + } + return e.APIName + ": " + strings.Join(ss, "\n") +} + +func NewError(apiName string, handle interface{}) error { + h, ht := ToHandleAndType(handle) + err := &Error{APIName: apiName} + var ne api.SQLINTEGER + state := make([]uint16, 6) + msg := make([]uint16, api.SQL_MAX_MESSAGE_LENGTH) + for i := 1; ; i++ { + ret := api.SQLGetDiagRec(ht, h, api.SQLSMALLINT(i), + (*api.SQLWCHAR)(unsafe.Pointer(&state[0])), &ne, + (*api.SQLWCHAR)(unsafe.Pointer(&msg[0])), + api.SQLSMALLINT(len(msg)), nil) + if ret == api.SQL_NO_DATA { + break + } + if IsError(ret) { + panic(fmt.Errorf("SQLGetDiagRec failed: ret=%d", ret)) + } + r := DiagRecord{ + State: api.UTF16ToString(state), + NativeError: int(ne), + Message: api.UTF16ToString(msg), + } + if strings.Contains(r.Message, "CLI0106E") || + strings.Contains(r.Message, "CLI0107E") || + strings.Contains(r.Message, "CLI0108E") { + return driver.ErrBadConn + } + err.Diag = append(err.Diag, r) + } + return err +} diff --git a/src/github.com/ibmdb/go_ibm_db/handle.go b/src/github.com/ibmdb/go_ibm_db/handle.go new file mode 100644 index 0000000..d763491 --- /dev/null +++ b/src/github.com/ibmdb/go_ibm_db/handle.go @@ -0,0 +1,44 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package go_ibm_db + +import ( + "github.com/ibmdb/go_ibm_db/api" + "fmt" +) + +func ToHandleAndType(handle interface{}) (h api.SQLHANDLE, ht api.SQLSMALLINT) { + switch v := handle.(type) { + case api.SQLHENV: + if v == api.SQLHENV(api.SQL_NULL_HANDLE) { + ht = 0 + } else { + ht = api.SQL_HANDLE_ENV + } + h = api.SQLHANDLE(v) + case api.SQLHDBC: + ht = api.SQL_HANDLE_DBC + h = api.SQLHANDLE(v) + case api.SQLHSTMT: + ht = api.SQL_HANDLE_STMT + h = api.SQLHANDLE(v) + default: + panic(fmt.Errorf("unexpected handle type %T", v)) + } + return h, ht +} + +func releaseHandle(handle interface{}) error { + h, ht := ToHandleAndType(handle) + ret := api.SQLFreeHandle(ht, h) + if ret == api.SQL_INVALID_HANDLE { + return fmt.Errorf("SQLFreeHandle(%d, %d) returns SQL_INVALID_HANDLE", ht, h) + } + if IsError(ret) { + return NewError("SQLFreeHandle", handle) + } + drv.Stats.updateHandleCount(ht, -1) + return nil +} diff --git a/src/github.com/ibmdb/go_ibm_db/installer/setup.go b/src/github.com/ibmdb/go_ibm_db/installer/setup.go new file mode 100644 index 0000000..5453a37 --- /dev/null +++ b/src/github.com/ibmdb/go_ibm_db/installer/setup.go @@ -0,0 +1,235 @@ +package main + +import ( + "fmt" + "runtime" + "io" + "net/http" + "os" + "os/exec" + "archive/zip" + "archive/tar" + "compress/gzip" + "path/filepath" + "strings" +) +//func to Download +func DownloadFile(filepath string, url string) error { + out, err := os.Create(filepath) + if err != nil { + return err + } + defer out.Close() + resp, err := http.Get(url) + if err != nil { + return err + } + defer resp.Body.Close() + _, err = io.Copy(out, resp.Body) + if err != nil { + return err + } + return nil +} +//func to unzip +func Unzipping(sourcefile string) { + reader, err := zip.OpenReader(sourcefile) + if err != nil { + fmt.Println(err) + os.Exit(1) + } + defer reader.Close() + for _, f := range reader.Reader.File { + zipped, err := f.Open() + if err != nil { + fmt.Println(err) + os.Exit(1) + } + defer zipped.Close() + path := filepath.Join("./", f.Name) + if f.FileInfo().IsDir() { + os.MkdirAll(path, f.Mode()) + fmt.Println("Creating directory", path) + } else { + writer, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE, f.Mode()) + if err != nil { + fmt.Println(err) + os.Exit(1) + } + defer writer.Close() + if _, err = io.Copy(writer, zipped); err != nil { + fmt.Println(err) + os.Exit(1) + } + fmt.Println("Unzipping : ", path) + } + } +} +//Func to Untar +func Untaring(sourcefile string) { + file, err := os.Open(sourcefile) + if err != nil { + fmt.Println(err) + os.Exit(1) + } + defer file.Close() + var fileReader io.ReadCloser = file + if strings.HasSuffix(sourcefile, ".gz") { + if fileReader, err = gzip.NewReader(file); err != nil { + fmt.Println(err) + os.Exit(1) + } + defer fileReader.Close() + } + tarBallReader := tar.NewReader(fileReader) + for { + header, err := tarBallReader.Next() + if err != nil { + if err == io.EOF { + break + } + fmt.Println(err) + os.Exit(1) + } + filename := header.Name + switch header.Typeflag { + case tar.TypeDir: + fmt.Println("Creating directory :", filename) + err = os.MkdirAll(filename, os.FileMode(header.Mode)) + if err != nil { + fmt.Println(err) + os.Exit(1) + } + case tar.TypeReg: + fmt.Println("Untarring :", filename) + writer, err := os.Create(filename) + if err != nil { + fmt.Println(err) + os.Exit(1) + } + io.Copy(writer, tarBallReader) + err = os.Chmod(filename, os.FileMode(header.Mode)) + if err != nil { + fmt.Println(err) + os.Exit(1) + } + writer.Close() + default: + fmt.Printf("Unable to untar type : %c in file %s", header.Typeflag, filename) + } + } +} + +func linux_untar(clidriver string){ + out, _:= exec.Command("tar","xvzf",clidriver).Output() +fmt.Println(string(out[:])) +} + + +func main() { + var cliFileName string + var url string + i:=0 + _,a :=os.LookupEnv("IBM_DB_DIR") + _,b :=os.LookupEnv("IBM_DB_HOME") + _,c :=os.LookupEnv("IBM_DB_LIB") + if(!(a && b && c)){ + if runtime.GOOS == "aix" { + i=2 + const wordsize = 32 << (^uint(0) >> 32 & 1) + if wordsize==64 { + cliFileName = "aix64_odbc_cli.tar.gz" + } else { + cliFileName = "aix32_odbc_cli.tar.gz" + } + fmt.Printf("aix\n") + fmt.Printf(cliFileName) + }else if runtime.GOOS == "linux"{ + i=2 + if runtime.GOARCH == "ppc64le" { + const wordsize = 32 << (^uint(0) >> 32 & 1) + if wordsize==64{ + cliFileName= "ppc64le_odbc_cli.tar.gz" + } + }else if runtime.GOARCH == "ppc" { + const wordsize = 32 << (^uint(0) >> 32 & 1) + if wordsize==64{ + cliFileName="ppc64_odbc_cli.tar.gz" + }else{ + cliFileName="ppc32_odbc_cli.tar.gz" + } + }else if runtime.GOARCH == "amd64" { + const wordsize = 32 << (^uint(0) >> 32 & 1) + if wordsize==64{ + cliFileName="linuxx64_odbc_cli.tar.gz" + }else{ + cliFileName="linuxia32_odbc_cli.tar.gz" + } + }else if runtime.GOARCH == "390" { + const wordsize = 32 << (^uint(0) >> 32 & 1) + if wordsize==64{ + cliFileName="s390x64_odbc_cli.tar.gz" + }else{ + cliFileName="s390_odbc_cli.tar.gz" + } + } + fmt.Printf("linux\n") + fmt.Printf(cliFileName) + }else if runtime.GOOS=="windows"{ + i=1 + const wordsize = 32 << (^uint(0) >> 32 & 1) + if wordsize==64 { + cliFileName = "ntx64_odbc_cli.zip" + } else { + cliFileName = "nt32_odbc_cli.zip" + } + fmt.Printf("windows\n") + fmt.Printf(cliFileName) + }else if runtime.GOOS=="darwin"{ + const wordsize = 32 << (^uint(0) >> 32 & 1) + if wordsize==64 { + cliFileName = "macos64_odbc_cli.tar.gz" + } + fmt.Printf("darwin\n") + fmt.Printf(cliFileName) + }else if runtime.GOOS =="sunos"{ + i=2 + if runtime.GOARCH == "i86pc"{ + const wordsize = 32 << (^uint(0) >> 32 & 1) + if wordsize==64 { + cliFileName = "sunamd64_odbc_cli.tar.gz" + }else{ + cliFileName = "sunamd32_odbc_cli.tar.gz" + } + }else if runtime.GOARCH == "SUNW"{ + const wordsize = 32 << (^uint(0) >> 32 & 1) + if wordsize==64 { + cliFileName = "sun64_odbc_cli.tar.gz" + }else{ + cliFileName = "sun32_odbc_cli.tar.gz" + } + } + fmt.Printf("Sunos\n") + fmt.Printf(cliFileName) + }else{ + fmt.Println("not a known platform") + } + fileUrl:= "https://public.dhe.ibm.com/ibmdl/export/pub/software/data/db2/drivers/odbc_cli/" + cliFileName + fmt.Println(url) + fmt.Println("Downloading...") + err:=DownloadFile(cliFileName,fileUrl) + if err!=nil{ + fmt.Println(err) + }else{ + fmt.Println("download successful") + } + if(i == 1){ + Unzipping(cliFileName) + }else if(i==2){ + linux_untar(cliFileName) + + }else { + Untaring(cliFileName) + } + } +} \ No newline at end of file diff --git a/src/github.com/ibmdb/go_ibm_db/odbcstmt.go b/src/github.com/ibmdb/go_ibm_db/odbcstmt.go new file mode 100644 index 0000000..f75e26d --- /dev/null +++ b/src/github.com/ibmdb/go_ibm_db/odbcstmt.go @@ -0,0 +1,157 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package go_ibm_db + +import ( + "database/sql/driver" + "errors" + "fmt" + "sync" + "time" + "unsafe" + + "github.com/ibmdb/go_ibm_db/api" +) + +// TODO(brainman): see if I could use SQLExecDirect anywhere + +type ODBCStmt struct { + h api.SQLHSTMT + Parameters []Parameter + Cols []Column + // locking/lifetime + mu sync.Mutex + usedByStmt bool + usedByRows bool +} + +func (c *Conn) PrepareODBCStmt(query string) (*ODBCStmt, error) { + var out api.SQLHANDLE + ret := api.SQLAllocHandle(api.SQL_HANDLE_STMT, api.SQLHANDLE(c.h), &out) + if IsError(ret) { + return nil, NewError("SQLAllocHandle", c.h) + } + h := api.SQLHSTMT(out) + drv.Stats.updateHandleCount(api.SQL_HANDLE_STMT, 1) + + b := api.StringToUTF16(query) + ret = api.SQLPrepare(h, + (*api.SQLWCHAR)(unsafe.Pointer(&b[0])), api.SQLINTEGER(len(b))) + if IsError(ret) { + defer releaseHandle(h) + return nil, NewError("SQLPrepare", h) + } + ps, err := ExtractParameters(h) + if err != nil { + defer releaseHandle(h) + return nil, err + } + return &ODBCStmt{ + h: h, + Parameters: ps, + usedByStmt: true, + }, nil +} + +func (s *ODBCStmt) closeByStmt() error { + s.mu.Lock() + defer s.mu.Unlock() + if s.usedByStmt { + defer func() { s.usedByStmt = false }() + if !s.usedByRows { + return s.releaseHandle() + } + } + return nil +} + +func (s *ODBCStmt) closeByRows() error { + s.mu.Lock() + defer s.mu.Unlock() + if s.usedByRows { + defer func() { s.usedByRows = false }() + if s.usedByStmt { + ret := api.SQLCloseCursor(s.h) + if IsError(ret) { + return NewError("SQLCloseCursor", s.h) + } + return nil + } else { + return s.releaseHandle() + } + } + return nil +} + +func (s *ODBCStmt) releaseHandle() error { + h := s.h + s.h = api.SQLHSTMT(api.SQL_NULL_HSTMT) + return releaseHandle(h) +} + +var testingIssue5 bool // used during tests + +func (s *ODBCStmt) Exec(args []driver.Value) error { + + if len(args) != len(s.Parameters) { + return fmt.Errorf("wrong number of arguments %d, %d expected", len(args), len(s.Parameters)) + } + for i, a := range args { + // this could be done in 2 steps: + // 1) bind vars right after prepare; + // 2) set their (vars) values here; + // but rebinding parameters for every new parameter value + // should be efficient enough for our purpose. + s.Parameters[i].BindValue(s.h, i, a) + } + if testingIssue5 { + time.Sleep(10 * time.Microsecond) + } + ret := api.SQLExecute(s.h) + if ret == api.SQL_NO_DATA { + // success but no data to report + return nil + } + if IsError(ret) { + return NewError("SQLExecute", s.h) + } + return nil +} + +func (s *ODBCStmt) BindColumns() error { + // count columns + var n api.SQLSMALLINT + ret := api.SQLNumResultCols(s.h, &n) + if IsError(ret) { + return NewError("SQLNumResultCols", s.h) + } + if n < 1 { + return errors.New("Stmt did not create a result set") + } + // fetch column descriptions + s.Cols = make([]Column, n) + binding := true + for i := range s.Cols { + c, err := NewColumn(s.h, i) + if err != nil { + return err + } + s.Cols[i] = c + // Once we found one non-bindable column, we will not bind the rest. + // http://www.easysoft.com/developer/languages/c/odbc-tutorial-fetching-results.html + // ... One common restriction is that SQLGetData may only be called on columns after the last bound column. ... + if !binding { + continue + } + bound, err := s.Cols[i].Bind(s.h, i) + if err != nil { + return err + } + if !bound { + binding = false + } + } + return nil +} diff --git a/src/github.com/ibmdb/go_ibm_db/param.go b/src/github.com/ibmdb/go_ibm_db/param.go new file mode 100644 index 0000000..e1c23f8 --- /dev/null +++ b/src/github.com/ibmdb/go_ibm_db/param.go @@ -0,0 +1,165 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package go_ibm_db + +import ( + "github.com/ibmdb/go_ibm_db/api" + "database/sql/driver" + "fmt" + "time" + "unsafe" +) + +type Parameter struct { + SQLType api.SQLSMALLINT + Decimal api.SQLSMALLINT + Size api.SQLULEN + isDescribed bool + // Following fields store data used later by SQLExecute. + // The fields keep data alive and away from gc. + Data interface{} + StrLen_or_IndPtr api.SQLLEN +} + +// StoreStrLen_or_IndPtr stores v into StrLen_or_IndPtr field of p +// and returns address of that field. +func (p *Parameter) StoreStrLen_or_IndPtr(v api.SQLLEN) *api.SQLLEN { + p.StrLen_or_IndPtr = v + return &p.StrLen_or_IndPtr + +} + +func (p *Parameter) BindValue(h api.SQLHSTMT, idx int, v driver.Value) error { + // TODO(brainman): Reuse memory for previously bound values. If memory + // is reused, we, probably, do not need to call SQLBindParameter either. + var ctype, sqltype, decimal api.SQLSMALLINT + var size api.SQLULEN + var buflen api.SQLLEN + var plen *api.SQLLEN + var buf unsafe.Pointer + switch d := v.(type) { + case nil: + ctype = api.SQL_C_WCHAR + p.Data = nil + buf = nil + size = 1 + buflen = 0 + plen = p.StoreStrLen_or_IndPtr(api.SQL_NULL_DATA) + sqltype = api.SQL_WCHAR + case string: + ctype = api.SQL_C_WCHAR + b := api.StringToUTF16(d) + p.Data = b + buf = unsafe.Pointer(&b[0]) + l := len(b) + l -= 1 // remove terminating 0 + size = api.SQLULEN(l) + if size < 1 { + // size cannot be less then 1 even for empty fields + size = 1 + } + l *= 2 // every char takes 2 bytes + buflen = api.SQLLEN(l) + plen = p.StoreStrLen_or_IndPtr(buflen) + if p.isDescribed { + // only so we can handle very long (>4000 chars) parameters + sqltype = p.SQLType + } else { + sqltype = api.SQL_WCHAR + } + case int64: + ctype = api.SQL_C_SBIGINT + p.Data = &d + buf = unsafe.Pointer(&d) + sqltype = api.SQL_BIGINT + size = 8 + case bool: + var b byte + if d { + b = 1 + } + ctype = api.SQL_C_BIT + p.Data = &b + buf = unsafe.Pointer(&b) + sqltype = api.SQL_BIT + size = 1 + case float64: + ctype = api.SQL_C_DOUBLE + p.Data = &d + buf = unsafe.Pointer(&d) + sqltype = api.SQL_DOUBLE + size = 8 + case time.Time: + ctype = api.SQL_C_TYPE_TIMESTAMP + y, m, day := d.Date() + b := api.SQL_TIMESTAMP_STRUCT{ + Year: api.SQLSMALLINT(y), + Month: api.SQLUSMALLINT(m), + Day: api.SQLUSMALLINT(day), + Hour: api.SQLUSMALLINT(d.Hour()), + Minute: api.SQLUSMALLINT(d.Minute()), + Second: api.SQLUSMALLINT(d.Second()), + Fraction: api.SQLUINTEGER(d.Nanosecond()), + } + p.Data = &b + buf = unsafe.Pointer(&b) + sqltype = api.SQL_TYPE_TIMESTAMP + if p.isDescribed && p.SQLType == api.SQL_TYPE_TIMESTAMP { + decimal = p.Decimal + } + if decimal <= 0 { + // represented as yyyy-mm-dd hh:mm:ss.fff format in ms sql server + decimal = 3 + } + size = 20 + api.SQLULEN(decimal) + case []byte: + ctype = api.SQL_C_BINARY + b := make([]byte, len(d)) + copy(b, d) + p.Data = b + buf = unsafe.Pointer(&b[0]) + buflen = api.SQLLEN(len(b)) + plen = p.StoreStrLen_or_IndPtr(buflen) + size = api.SQLULEN(len(b)) + sqltype = api.SQL_BINARY + default: + panic(fmt.Errorf("unsupported type %T", v)) + } + ret := api.SQLBindParameter(h, api.SQLUSMALLINT(idx+1), + api.SQL_PARAM_INPUT, ctype, sqltype, size, decimal, + api.SQLPOINTER(buf), buflen, plen) + if IsError(ret) { + return NewError("SQLBindParameter", h) + } + return nil +} + +func ExtractParameters(h api.SQLHSTMT) ([]Parameter, error) { + // count parameters + var n, nullable api.SQLSMALLINT + ret := api.SQLNumParams(h, &n) + if IsError(ret) { + return nil, NewError("SQLNumParams", h) + } + if n <= 0 { + // no parameters + return nil, nil + } + ps := make([]Parameter, n) + // fetch param descriptions + for i := range ps { + p := &ps[i] + ret = api.SQLDescribeParam(h, api.SQLUSMALLINT(i+1), + &p.SQLType, &p.Size, &p.Decimal, &nullable) + if IsError(ret) { + // SQLDescribeParam is not implemented by freedts, + // it even fails for some statements on windows. + // Will try request without these descriptions + continue + } + p.isDescribed = true + } + return ps, nil +} diff --git a/src/github.com/ibmdb/go_ibm_db/pooling.go b/src/github.com/ibmdb/go_ibm_db/pooling.go new file mode 100644 index 0000000..f1e62f1 --- /dev/null +++ b/src/github.com/ibmdb/go_ibm_db/pooling.go @@ -0,0 +1,205 @@ +package go_ibm_db + +import ( + "database/sql" + "fmt" + "time" + "strconv" + "strings" +) + +type DBP struct{ +sql.DB +con string +n time.Duration +} + +type Pool struct{ +availablePool map[string] []*DBP +usedPool map[string] []*DBP +PoolSize int +} + +var b *Pool +var ConnMaxLifetime,PoolSize int + +//Pconnect will return the pool instance +func Pconnect(PoolSize string) (*Pool){ + var Size int + count:=len(PoolSize) + if count>0{ + opt:=strings.Split(PoolSize,"=") + if(opt[0] == "PoolSize"){ + Size,_=strconv.Atoi(opt[1]) + }else{ + fmt.Println("Not a valid parameter") + } + } else { + Size=100 + } + p:=&Pool{ + availablePool: make(map[string] []*DBP), + usedPool : make(map[string] []*DBP), + PoolSize : Size, + } + b=p + + return p +} + +var Psize int + +//Open will check for the connection in the pool +//If not opens a new connection and stores in the pool + +func (p *Pool) Open(Connstr string,options ...string)(*DBP){ + var Time time.Duration + count := len(options) + if count>0{ + for i:=0;i 1){ + dbpo:=val[0] + copy(val[0:],val[1:]) + val[len(val)-1]=nil + val=val[:len(val)-1] + p.availablePool[Connstr]=val + p.usedPool[Connstr]=append(p.usedPool[Connstr],dbpo) + dbpo.SetConnMaxLifetime(Time) + return dbpo + }else{ + dbpo:=val[0] + p.usedPool[Connstr]=append(p.usedPool[Connstr],dbpo) + delete(p.availablePool,Connstr) + dbpo.SetConnMaxLifetime(Time) + return dbpo + } + }else{ + db,err:=sql.Open("go_ibm_db",Connstr) + if err != nil{ + return nil + } + dbi:=&DBP{ + DB :*db, + con :Connstr, + n :Time, + } + p.usedPool[Connstr]=append(p.usedPool[Connstr],dbi) + dbi.SetConnMaxLifetime(Time) + return dbi + } + } else { + db,err:=sql.Open("go_ibm_db",Connstr) + if err != nil{ + return nil + } + dbi:=&DBP{ + DB :*db, + con :Connstr, + } + return dbi + } +} + +//Close will make the connection available for the next release + +func (d *DBP) Close(){ + Psize=Psize-1 + var pos int + i:=-1 + if valc,okc:=b.usedPool[d.con];okc{ + if(len(valc) > 1){ + for _,b:=range valc{ + i=i+1 + if b == d{ + pos = i + } + } + dbpc:=valc[pos] + copy(valc[pos:], valc[pos+1:]) + valc[len(valc)-1] = nil + valc = valc[:len(valc)-1] + b.usedPool[d.con]=valc + b.availablePool[d.con]=append(b.availablePool[d.con],dbpc) + } else { + dbpc := valc[0] + b.availablePool[d.con]=append(b.availablePool[d.con],dbpc) + delete(b.usedPool,d.con) + } + go d.Timeout() + } else { + d.DB.Close() + } +} + +//Timeout for closing the connection in pool + +func (d *DBP) Timeout(){ + var pos int + i:=-1 + select { + case <-time.After(d.n): + if valt,okt:=b.availablePool[d.con];okt{ + if(len(valt) > 1){ + for _,b:=range valt{ + i=i+1 + if b == d{ + pos = i + } + } + dbpt:=valt[pos] + copy(valt[pos:], valt[pos+1:]) + valt[len(valt)-1] = nil + valt = valt[:len(valt)-1] + b.availablePool[d.con]=valt + dbpt.DB.Close() + }else{ + dbpt:=valt[0] + dbpt.DB.Close() + delete(b.availablePool,d.con) + } + } + } +} + +//Release will close all the connections in the pool + +func (p *Pool) Release(){ + if(p.availablePool != nil){ + for _,vala := range p.availablePool{ + for _,dbpr := range vala{ + dbpr.DB.Close() + } + } + p.availablePool=nil + } + if(p.usedPool != nil){ + for _,valu := range p.usedPool{ + for _,dbpr := range valu{ + dbpr.DB.Close() + } + } + p.usedPool=nil + } +} + +// Display will print the values in the map + +func (p *Pool) Display(){ + fmt.Println(p.availablePool) + fmt.Println(p.usedPool) + fmt.Println(p.PoolSize) +} diff --git a/src/github.com/ibmdb/go_ibm_db/result.go b/src/github.com/ibmdb/go_ibm_db/result.go new file mode 100644 index 0000000..35bbd99 --- /dev/null +++ b/src/github.com/ibmdb/go_ibm_db/result.go @@ -0,0 +1,22 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package go_ibm_db + +import ( + "errors" +) + +type Result struct { + rowCount int64 +} + +func (r *Result) LastInsertId() (int64, error) { + // TODO(brainman): implement (*Resilt).LastInsertId + return 0, errors.New("not implemented") +} + +func (r *Result) RowsAffected() (int64, error) { + return r.rowCount, nil +} diff --git a/src/github.com/ibmdb/go_ibm_db/rows.go b/src/github.com/ibmdb/go_ibm_db/rows.go new file mode 100644 index 0000000..fb8859a --- /dev/null +++ b/src/github.com/ibmdb/go_ibm_db/rows.go @@ -0,0 +1,45 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package go_ibm_db + +import ( + "github.com/ibmdb/go_ibm_db/api" + "database/sql/driver" + "io" +) + +type Rows struct { + os *ODBCStmt +} + +func (r *Rows) Columns() []string { + names := make([]string, len(r.os.Cols)) + for i := 0; i < len(names); i++ { + names[i] = r.os.Cols[i].Name() + } + return names +} + +func (r *Rows) Next(dest []driver.Value) error { + ret := api.SQLFetch(r.os.h) + if ret == api.SQL_NO_DATA { + return io.EOF + } + if IsError(ret) { + return NewError("SQLFetch", r.os.h) + } + for i := range dest { + v, err := r.os.Cols[i].Value(r.os.h, i) + if err != nil { + return err + } + dest[i] = v + } + return nil +} + +func (r *Rows) Close() error { + return r.os.closeByRows() +} diff --git a/src/github.com/ibmdb/go_ibm_db/stats.go b/src/github.com/ibmdb/go_ibm_db/stats.go new file mode 100644 index 0000000..c3c4d27 --- /dev/null +++ b/src/github.com/ibmdb/go_ibm_db/stats.go @@ -0,0 +1,33 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package go_ibm_db + +import ( + "github.com/ibmdb/go_ibm_db/api" + "fmt" + "sync" +) + +type Stats struct { + EnvCount int + ConnCount int + StmtCount int + mu sync.Mutex +} + +func (s *Stats) updateHandleCount(handleType api.SQLSMALLINT, change int) { + s.mu.Lock() + defer s.mu.Unlock() + switch handleType { + case api.SQL_HANDLE_ENV: + s.EnvCount += change + case api.SQL_HANDLE_DBC: + s.ConnCount += change + case api.SQL_HANDLE_STMT: + s.StmtCount += change + default: + panic(fmt.Errorf("unexpected handle type %d", handleType)) + } +} diff --git a/src/github.com/ibmdb/go_ibm_db/stmt.go b/src/github.com/ibmdb/go_ibm_db/stmt.go new file mode 100644 index 0000000..4e9dc0f --- /dev/null +++ b/src/github.com/ibmdb/go_ibm_db/stmt.go @@ -0,0 +1,99 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package go_ibm_db + +import ( + "database/sql/driver" + "errors" + "sync" + + "github.com/ibmdb/go_ibm_db/api" +) + +type Stmt struct { + c *Conn + query string + os *ODBCStmt + mu sync.Mutex +} + +func (c *Conn) Prepare(query string) (driver.Stmt, error) { + os, err := c.PrepareODBCStmt(query) + if err != nil { + return nil, err + } + return &Stmt{c: c, os: os, query: query}, nil +} + +func (s *Stmt) NumInput() int { + if s.os == nil { + return -1 + } + return len(s.os.Parameters) +} + +func (s *Stmt) Close() error { + if s.os == nil { + return errors.New("Stmt is already closed") + } + ret := s.os.closeByStmt() + s.os = nil + return ret +} + +func (s *Stmt) Exec(args []driver.Value) (driver.Result, error) { + if s.os == nil { + return nil, errors.New("Stmt is closed") + } + + s.mu.Lock() + defer s.mu.Unlock() + if s.os.usedByRows { + s.os.closeByStmt() + s.os = nil + os, err := s.c.PrepareODBCStmt(s.query) + if err != nil { + return nil, err + } + s.os = os + } + err := s.os.Exec(args) + if err != nil { + return nil, err + } + var c api.SQLLEN + ret := api.SQLRowCount(s.os.h, &c) + if IsError(ret) { + return nil, NewError("SQLRowCount", s.os.h) + } + return &Result{rowCount: int64(c)}, nil +} + +func (s *Stmt) Query(args []driver.Value) (driver.Rows, error) { + if s.os == nil { + return nil, errors.New("Stmt is closed") + } + s.mu.Lock() + defer s.mu.Unlock() + if s.os.usedByRows { + s.os.closeByStmt() + s.os = nil + os, err := s.c.PrepareODBCStmt(s.query) + if err != nil { + return nil, err + } + s.os = os + } + err := s.os.Exec(args) + if err != nil { + return nil, err + } + err = s.os.BindColumns() + if err != nil { + return nil, err + } + s.os.usedByRows = true // now both Stmt and Rows refer to it + return &Rows{os: s.os}, nil +} diff --git a/src/github.com/ibmdb/go_ibm_db/testdata/begin_test.go b/src/github.com/ibmdb/go_ibm_db/testdata/begin_test.go new file mode 100644 index 0000000..075dc99 --- /dev/null +++ b/src/github.com/ibmdb/go_ibm_db/testdata/begin_test.go @@ -0,0 +1,9 @@ +package main + +import "testing" + +func TestBegin(t *testing.T){ + if(Begin() != nil){ + t.Error("table not displayed") +} +} \ No newline at end of file diff --git a/src/github.com/ibmdb/go_ibm_db/testdata/close_test.go b/src/github.com/ibmdb/go_ibm_db/testdata/close_test.go new file mode 100644 index 0000000..8ebb1ab --- /dev/null +++ b/src/github.com/ibmdb/go_ibm_db/testdata/close_test.go @@ -0,0 +1,9 @@ +package main + +import "testing" + +func TestClose(t *testing.T){ + if(Close() != nil){ + t.Error("Error in Scanning Query") +} +} \ No newline at end of file diff --git a/src/github.com/ibmdb/go_ibm_db/testdata/columns_test.go b/src/github.com/ibmdb/go_ibm_db/testdata/columns_test.go new file mode 100644 index 0000000..1c195ac --- /dev/null +++ b/src/github.com/ibmdb/go_ibm_db/testdata/columns_test.go @@ -0,0 +1,9 @@ +package main + +import "testing" + +func TestColumns(t *testing.T){ + if(Columns() != nil){ + t.Error("Error in displaying Query") +} +} \ No newline at end of file diff --git a/src/github.com/ibmdb/go_ibm_db/testdata/commit_test.go b/src/github.com/ibmdb/go_ibm_db/testdata/commit_test.go new file mode 100644 index 0000000..a0c425c --- /dev/null +++ b/src/github.com/ibmdb/go_ibm_db/testdata/commit_test.go @@ -0,0 +1,9 @@ +package main + +import "testing" + +func TestCommit(t *testing.T){ + if(Commit() != nil){ + t.Error("Error in commit query") +} +} \ No newline at end of file diff --git a/src/github.com/ibmdb/go_ibm_db/testdata/conn_test.go b/src/github.com/ibmdb/go_ibm_db/testdata/conn_test.go new file mode 100644 index 0000000..ce8a04b --- /dev/null +++ b/src/github.com/ibmdb/go_ibm_db/testdata/conn_test.go @@ -0,0 +1,9 @@ +package main + +import "testing" + +func TestCreateconnection(t *testing.T){ + if(Createconnection() == nil){ + t.Error("connection not formed") +} +} \ No newline at end of file diff --git a/src/github.com/ibmdb/go_ibm_db/testdata/create_test.go b/src/github.com/ibmdb/go_ibm_db/testdata/create_test.go new file mode 100644 index 0000000..03064fb --- /dev/null +++ b/src/github.com/ibmdb/go_ibm_db/testdata/create_test.go @@ -0,0 +1,9 @@ +package main + +import "testing" + +func TestCreatetable(t *testing.T){ + if(Createtable() != nil){ + t.Error("table not formed") +} +} \ No newline at end of file diff --git a/src/github.com/ibmdb/go_ibm_db/testdata/drop_test.go b/src/github.com/ibmdb/go_ibm_db/testdata/drop_test.go new file mode 100644 index 0000000..cfed09d --- /dev/null +++ b/src/github.com/ibmdb/go_ibm_db/testdata/drop_test.go @@ -0,0 +1,9 @@ +package main + +import "testing" + +func TestDrop(t *testing.T){ + if(Drop() != nil){ + t.Error("table not dropped") +} +} \ No newline at end of file diff --git a/src/github.com/ibmdb/go_ibm_db/testdata/insert_test.go b/src/github.com/ibmdb/go_ibm_db/testdata/insert_test.go new file mode 100644 index 0000000..542021c --- /dev/null +++ b/src/github.com/ibmdb/go_ibm_db/testdata/insert_test.go @@ -0,0 +1,9 @@ +package main + +import "testing" + +func TestInsert(t *testing.T){ + if(Insert() != nil){ + t.Error("table not formed") +} +} \ No newline at end of file diff --git a/src/github.com/ibmdb/go_ibm_db/testdata/main.go b/src/github.com/ibmdb/go_ibm_db/testdata/main.go new file mode 100644 index 0000000..ffe201e --- /dev/null +++ b/src/github.com/ibmdb/go_ibm_db/testdata/main.go @@ -0,0 +1,250 @@ +package main + +import ( + "fmt" + a "github.com/ibmdb/go_ibm_db" + "database/sql" + ) + +var con ="HOSTNAME=host;PORT=number;DATABASE=name;UID=username;PWD=password" + +func Createconnection()(db *sql.DB){ + db,_=sql.Open("go_ibm_db",con) + return db + } + + +func Createtable( ) error{ + db, err:=sql.Open("go_ibm_db", con) + db.Exec("DROP table rocket") + _,err=db.Exec("create table rocket(a int)") + _,err=db.Exec("create table rocket1(a int)") + if err != nil{ + return err + } + return nil +} +func Insert() error{ + db,err:=sql.Open("go_ibm_db",con) + _,err =db.Exec("insert into rocket values(1)") + if err != nil{ + return err + } + return nil +} + +func Drop() error{ + db,err:=sql.Open("go_ibm_db",con) + _,err =db.Exec("drop table rocket1") + if err != nil{ + return err + } + return nil +} + +func Prepare() error{ +db,_:=sql.Open("go_ibm_db",con) +_,err:=db.Prepare("select * from rocket") +if err!=nil{ +return err +} +return nil +} + +func Query() error{ +db,_:=sql.Open("go_ibm_db",con) +st,_:=db.Prepare("select * from rocket") +_,err:=st.Query() +if err != nil{ +return err +} +return nil +} + +func Scan() error{ +db,_:=sql.Open("go_ibm_db",con) +st,_:=db.Prepare("select * from rocket") +rows,err:=st.Query() +for rows.Next(){ +var a string +err = rows.Scan(&a) +if err != nil{ +return err +} +} +return nil +} + +func Next() error{ +db,_:=sql.Open("go_ibm_db",con) +st,_:=db.Prepare("select * from rocket") +rows,err:=st.Query() +for rows.Next(){ +var a string +err = rows.Scan(&a) +if err != nil{ +return err +} +} +return nil +} + +func Columns() error{ +db,_:=sql.Open("go_ibm_db",con) +st,_:=db.Prepare("select * from rocket") +rows,_:=st.Query() +_,err := rows.Columns() +if err != nil{ +return err +} +for rows.Next(){ +var a string +_ = rows.Scan(&a) +} +return nil +} + + + +func Queryrow() error{ +a:=1 +var uname int +db,err:=sql.Open("go_ibm_db",con) +err=db.QueryRow("select a from rocket where a=?",a).Scan(&uname) +if err != nil{ +return err +} +return nil +} + +func Begin() error{ +db,err:=sql.Open("go_ibm_db",con) +_,err=db.Begin() +if err != nil{ +return err +} +return nil +} + +func Commit() error{ + db,err:=sql.Open("go_ibm_db",con) + bg,err:=db.Begin() + db.Exec("DROP table u") + _,err=bg.Exec("create table u(id int)") + err=bg.Commit() + if err!=nil{ + return err + } + return nil +} + +func Close()(error){ + db,_:=sql.Open("go_ibm_db",con) + err:=db.Close() + if err!=nil{ + return err + } + return nil + } + +func PoolOpen() (int){ + pool:=a.Pconnect("PoolSize=50") + db:=pool.Open(con) + if(db == nil){ + return 0 + }else { + return 1 + } +} + +func main(){ +result:=Createconnection() +if(result != nil){ +fmt.Println("Pass") +} else { +fmt.Println("fail") +} + +result1:=Createtable() +if(result1 == nil){ +fmt.Println("Pass") +} else { +fmt.Println("fail") +} + +result2:=Insert() +if(result2 == nil){ +fmt.Println("Pass") +} else { +fmt.Println("fail") +} +result3:=Drop() +if(result3 == nil){ +fmt.Println("Pass") +} else { +fmt.Println("fail") +} +result4:=Prepare() +if(result4 == nil){ +fmt.Println("Pass") +} else { +fmt.Println("fail") +} +result5:=Query() +if(result5 == nil){ +fmt.Println("Pass") +} else { +fmt.Println("fail") +} + +result6:=Scan() +if(result6 == nil){ +fmt.Println("Pass") +} else { +fmt.Println("fail") +} +result7:=Next() +if(result7 == nil){ +fmt.Println("Pass") +} else { +fmt.Println("fail") +} + +result8:=Columns() +if(result8 == nil){ +fmt.Println("Pass") +} else { +fmt.Println("fail") +} + +result9:=Queryrow() +if(result9 == nil){ +fmt.Println("Pass") +} else { +fmt.Println("fail") +} +result10:=Begin() +if(result10== nil){ +fmt.Println("Pass") +} else { +fmt.Println("fail") +} +result11:=Commit() +if(result11 == nil){ +fmt.Println("Pass") +} else { +fmt.Println("fail") +} +result12:=Close() +if(result12 == nil){ +fmt.Println("Pass") +} else { +fmt.Println("fail") +} +result13:=PoolOpen() +if(result13 ==1){ +fmt.Println("Pass") +} else { +fmt.Println("fail") +} +} \ No newline at end of file diff --git a/src/github.com/ibmdb/go_ibm_db/testdata/next_test.go b/src/github.com/ibmdb/go_ibm_db/testdata/next_test.go new file mode 100644 index 0000000..b3fb56f --- /dev/null +++ b/src/github.com/ibmdb/go_ibm_db/testdata/next_test.go @@ -0,0 +1,9 @@ +package main + +import "testing" + +func TestNext(t *testing.T){ + if(Next() != nil){ + t.Error("Error in Scanning Query") +} +} \ No newline at end of file diff --git a/src/github.com/ibmdb/go_ibm_db/testdata/poolopen_test.go b/src/github.com/ibmdb/go_ibm_db/testdata/poolopen_test.go new file mode 100644 index 0000000..dc7a658 --- /dev/null +++ b/src/github.com/ibmdb/go_ibm_db/testdata/poolopen_test.go @@ -0,0 +1,10 @@ +package main + +import ( + "testing" +) +func TestPoolOpen(t *testing.T){ + if(PoolOpen() == 0){ + t.Error("pool connection not opened") + } +} \ No newline at end of file diff --git a/src/github.com/ibmdb/go_ibm_db/testdata/prepare_test.go b/src/github.com/ibmdb/go_ibm_db/testdata/prepare_test.go new file mode 100644 index 0000000..a65d5c3 --- /dev/null +++ b/src/github.com/ibmdb/go_ibm_db/testdata/prepare_test.go @@ -0,0 +1,9 @@ +package main + +import "testing" + +func TestPrepare(t *testing.T){ + if(Prepare() != nil){ + t.Error("Error in preparing Query") +} +} \ No newline at end of file diff --git a/src/github.com/ibmdb/go_ibm_db/testdata/query_test.go b/src/github.com/ibmdb/go_ibm_db/testdata/query_test.go new file mode 100644 index 0000000..906bff0 --- /dev/null +++ b/src/github.com/ibmdb/go_ibm_db/testdata/query_test.go @@ -0,0 +1,9 @@ +package main + +import "testing" + +func TestQuery(t *testing.T){ + if(Query() != nil){ + t.Error("table not displayed") +} +} \ No newline at end of file diff --git a/src/github.com/ibmdb/go_ibm_db/testdata/queryrow_test.go b/src/github.com/ibmdb/go_ibm_db/testdata/queryrow_test.go new file mode 100644 index 0000000..3472d9f --- /dev/null +++ b/src/github.com/ibmdb/go_ibm_db/testdata/queryrow_test.go @@ -0,0 +1,9 @@ +package main + +import "testing" + +func TestQueryrow(t *testing.T){ + if(Queryrow() != nil){ + t.Error("values not displayed") +} +} \ No newline at end of file diff --git a/src/github.com/ibmdb/go_ibm_db/testdata/scan_test.go b/src/github.com/ibmdb/go_ibm_db/testdata/scan_test.go new file mode 100644 index 0000000..a8c801d --- /dev/null +++ b/src/github.com/ibmdb/go_ibm_db/testdata/scan_test.go @@ -0,0 +1,9 @@ +package main + +import "testing" + +func TestScan(t *testing.T){ + if(Scan() != nil){ + t.Error("Error in Scanning Query") +} +} \ No newline at end of file diff --git a/src/github.com/ibmdb/go_ibm_db/tx.go b/src/github.com/ibmdb/go_ibm_db/tx.go new file mode 100644 index 0000000..7f3f6c6 --- /dev/null +++ b/src/github.com/ibmdb/go_ibm_db/tx.go @@ -0,0 +1,67 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package go_ibm_db + +import ( + "database/sql/driver" + "errors" + + "github.com/ibmdb/go_ibm_db/api" +) + +type Tx struct { + c *Conn +} + +func (c *Conn) setAutoCommitAttr(a uintptr) error { + ret := api.SQLSetConnectAttr(c.h, api.SQL_ATTR_AUTOCOMMIT, + api.SQLPOINTER(a), api.SQL_IS_UINTEGER) + if IsError(ret) { + return NewError("SQLSetConnectAttr", c.h) + } + return nil +} + +func (c *Conn) Begin() (driver.Tx, error) { + if c.tx != nil { + return nil, errors.New("already in a transaction") + } + err := c.setAutoCommitAttr(api.SQL_AUTOCOMMIT_OFF) + if err != nil { + return nil, err + } + c.tx = &Tx{c: c} + return c.tx, nil +} + +func (c *Conn) endTx(commit bool) error { + if c.tx == nil { + return errors.New("not in a transaction") + } + c.tx = nil + var howToEnd api.SQLSMALLINT + if commit { + howToEnd = api.SQL_COMMIT + } else { + howToEnd = api.SQL_ROLLBACK + } + ret := api.SQLEndTran(api.SQL_HANDLE_DBC, api.SQLHANDLE(c.h), howToEnd) + if IsError(ret) { + return NewError("SQLEndTran", c.h) + } + err := c.setAutoCommitAttr(api.SQL_AUTOCOMMIT_ON) + if err != nil { + return err + } + return nil +} + +func (tx *Tx) Commit() error { + return tx.c.endTx(true) +} + +func (tx *Tx) Rollback() error { + return tx.c.endTx(false) +} diff --git a/src/github.com/ibmdb/go_ibm_db/utf16.go b/src/github.com/ibmdb/go_ibm_db/utf16.go new file mode 100644 index 0000000..e67c405 --- /dev/null +++ b/src/github.com/ibmdb/go_ibm_db/utf16.go @@ -0,0 +1,55 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package go_ibm_db + +import ( + "unicode/utf16" + "unicode/utf8" +) + +const ( + replacementChar = '\uFFFD' // Unicode replacement character + + // 0xd800-0xdc00 encodes the high 10 bits of a pair. + // 0xdc00-0xe000 encodes the low 10 bits of a pair. + // the value is those 20 bits plus 0x10000. + surr1 = 0xd800 + surr2 = 0xdc00 + surr3 = 0xe000 +) + +// utf16toutf8 returns the UTF-8 encoding of the UTF-16 sequence s, +// with a terminating NUL removed. +func utf16toutf8(s []uint16) []byte { + for i, v := range s { + if v == 0 { + s = s[0:i] + break + } + } + buf := make([]byte, 0, len(s)*2) // allow 2 bytes for every rune + b := make([]byte, 4) + for i := 0; i < len(s); i++ { + var rr rune + switch r := s[i]; { + case surr1 <= r && r < surr2 && i+1 < len(s) && + surr2 <= s[i+1] && s[i+1] < surr3: + // valid surrogate sequence + rr = utf16.DecodeRune(rune(r), rune(s[i+1])) + i++ + case surr1 <= r && r < surr3: + // invalid surrogate sequence + rr = replacementChar + default: + // normal rune + rr = rune(r) + } + b := b[:cap(b)] + n := utf8.EncodeRune(b, rr) + b = b[:n] + buf = append(buf, b...) + } + return buf +} diff --git a/src/sqltest/drivers.go b/src/sqltest/drivers.go index 1c78b7f..eefb65f 100644 --- a/src/sqltest/drivers.go +++ b/src/sqltest/drivers.go @@ -2,6 +2,7 @@ package sqltest import ( _ "code.google.com/p/go-mysql-driver/mysql" + _ "github.com/ibmdb/go_ibm_db" _ "github.com/lib/pq" _ "github.com/mattn/go-sqlite3" _ "github.com/tgulacsi/goracle/godrv" diff --git a/src/sqltest/sql_test.go b/src/sqltest/sql_test.go index 267917c..ebcbf5a 100644 --- a/src/sqltest/sql_test.go +++ b/src/sqltest/sql_test.go @@ -25,10 +25,64 @@ var ( sqlite Tester = sqliteDB{} pq Tester = &pqDB{} oracle Tester = &oracleDB{} + db2 Tester = &db2DB{} ) const TablePrefix = "gosqltest_" +//db2DB validates the db2 driver by ibm (github.com/ibmdb/go_ibm_db) +type db2DB struct { + once sync.Once // guards init of running + running bool // whether port 50000 is listening +} + +func (d *db2DB) Running() bool { + d.once.Do(func() { + c, err := net.Dial("tcp", "localhost:50000") + if err == nil { + d.running = true + c.Close() + } + }) + return d.running +} + +func (d *db2DB) RunTest(t *testing.T, fn func(params)) { + if !d.Running() { + fmt.Printf("skipping test; no db2 running on localhost:50000\n") + return + } + user := os.Getenv("GOSQLTEST_DB2_USER") + if user == "" { + user = "root" + } + pass, ok := getenvOk("GOSQLTEST_DB2_PASS") + if !ok { + pass = "root" + } + dbName := "gosqltest" + db, err := sql.Open("go_ibm_db", fmt.Sprintf("HOSTNAME=localhost;PORT=50000;DATABASE=%s;UID=%s;PWD=%s", dbName, user, pass)) + if err != nil { + fmt.Printf("error connecting: %v \n", err) + } + + params := params{db2, t, db} + // Drop all tables in the test database. + rows, err := db.Query("select name from sysibm.systables") + if err != nil { + fmt.Printf("failed to enumerate tables: %v\n", err) + } + for rows.Next() { + var table string + if rows.Scan(&table) == nil && + strings.HasPrefix(strings.ToLower(table), strings.ToLower(TablePrefix)) { + params.mustExec("DROP TABLE " + table) + } + } + + fn(params) +} + // pqDB validates the postgres driver by Blake Mizerany (github.com/bmizerany/pq.go) type pqDB struct { once sync.Once // guards init of running @@ -287,12 +341,14 @@ func (o *oracleDB) RunTest(t *testing.T, fn func(params)) { func sqlBlobParam(t params, size int) string { switch t.dbType { - case sqlite: + case sqlite: return fmt.Sprintf("blob[%d]", size) case pq: return "bytea" case oracle: return fmt.Sprintf("RAW(%d)", size) + case db2: + return fmt.Sprintf("blob(%d)", size) } return fmt.Sprintf("VARBINARY(%d)", size) } @@ -302,10 +358,17 @@ func TestBlobs_MyMySQL(t *testing.T) { myMysql.RunTest(t, testBlobs) } func TestBlobs_GoMySQL(t *testing.T) { goMysql.RunTest(t, testBlobs) } func TestBlobs_PQ(t *testing.T) { pq.RunTest(t, testBlobs) } func TestBlobs_Oracle(t *testing.T) { oracle.RunTest(t, testBlobs) } +func TestBlobs_db2(t *testing.T) { db2.RunTest(t, testBlobs) } func testBlobs(t params) { var blob = []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15} - t.mustExec("create table " + TablePrefix + "foo (id integer primary key, bar " + sqlBlobParam(t, 16) + ")") + switch t.dbType { + case db2: + t.mustExec("create table " + TablePrefix + "foo (id integer primary key not null, bar " + sqlBlobParam(t, 16) + ")") + default: + t.mustExec("create table " + TablePrefix + "foo (id integer primary key, bar " + sqlBlobParam(t, 16) + ")") + } + t.mustExec(t.q("insert into "+TablePrefix+"foo (id, bar) values(?,?)"), 0, blob) want := fmt.Sprintf("%x", blob) @@ -333,13 +396,19 @@ func TestManyQueryRow_MyMySQL(t *testing.T) { myMysql.RunTest(t, testManyQueryRo func TestManyQueryRow_GoMySQL(t *testing.T) { goMysql.RunTest(t, testManyQueryRow) } func TestManyQueryRow_PQ(t *testing.T) { pq.RunTest(t, testManyQueryRow) } func TestManyQueryRow_Oracle(t *testing.T) { oracle.RunTest(t, testManyQueryRow) } +func TestManyQueryRow_db2(t *testing.T) { db2.RunTest(t, testManyQueryRow) } func testManyQueryRow(t params) { if testing.Short() { t.Logf("skipping in short mode") return } - t.mustExec("create table " + TablePrefix + "foo (id integer primary key, name varchar(50))") + switch t.dbType { + case db2: + t.mustExec("create table " + TablePrefix + "foo (id integer primary key not null, name varchar(50))") + default: + t.mustExec("create table " + TablePrefix + "foo (id integer primary key, name varchar(50))") + } t.mustExec(t.q("insert into "+TablePrefix+"foo (id, name) values(?,?)"), 1, "bob") var name string for i := 0; i < 10000; i++ { @@ -355,6 +424,7 @@ func TestTxQuery_MyMySQL(t *testing.T) { myMysql.RunTest(t, testTxQuery) } func TestTxQuery_GoMySQL(t *testing.T) { goMysql.RunTest(t, testTxQuery) } func TestTxQuery_PQ(t *testing.T) { pq.RunTest(t, testTxQuery) } func TestTxQuery_Oracle(t *testing.T) { oracle.RunTest(t, testTxQuery) } +func TestTxQuery_db2(t *testing.T) { db2.RunTest(t, testTxQuery) } func testTxQuery(t params) { tx, err := t.Begin() @@ -362,8 +432,12 @@ func testTxQuery(t params) { t.Fatal(err) } defer tx.Rollback() - - _, err = t.DB.Exec("create table " + TablePrefix + "foo (id integer primary key, name varchar(50))") + switch t.dbType { + case db2: + _, err = t.DB.Exec("create table " + TablePrefix + "foo (id integer primary key not null, name varchar(50))") + default: + _, err = t.DB.Exec("create table " + TablePrefix + "foo (id integer primary key, name varchar(50))") + } if err != nil { t.Logf("cannot drop table "+TablePrefix+"foo: %s", err) } @@ -398,6 +472,7 @@ func TestPreparedStmt_MyMySQL(t *testing.T) { myMysql.RunTest(t, testPreparedStm func TestPreparedStmt_GoMySQL(t *testing.T) { goMysql.RunTest(t, testPreparedStmt) } func TestPreparedStmt_PQ(t *testing.T) { pq.RunTest(t, testPreparedStmt) } func TestPreparedStmt_Oracle(t *testing.T) { oracle.RunTest(t, testPreparedStmt) } +func TestPreparedStmt_db2(t *testing.T) { db2.RunTest(t, testPreparedStmt) } func testPreparedStmt(t params) { t.mustExec("CREATE TABLE " + TablePrefix + "t (count INT)") From e55f2331facc6ced188822f5ff1d6e23799d6153 Mon Sep 17 00:00:00 2001 From: akhilravuri1 Date: Tue, 8 Jan 2019 13:07:22 +0530 Subject: [PATCH 2/5] removed driver --- .../ibmdb/go_ibm_db/API_DOCUMENTATION.md | 335 ------------------ .../ibmdb/go_ibm_db/CONTRIBUTING.md | 11 - src/github.com/ibmdb/go_ibm_db/LICENSE.md | 27 -- src/github.com/ibmdb/go_ibm_db/README.md | 244 ------------- src/github.com/ibmdb/go_ibm_db/api/Makefile | 15 - src/github.com/ibmdb/go_ibm_db/api/api.go | 68 ---- .../ibmdb/go_ibm_db/api/api_unix.go | 137 ------- .../ibmdb/go_ibm_db/api/api_windows.go | 133 ------- .../ibmdb/go_ibm_db/api/api_windows_386.go | 10 - .../ibmdb/go_ibm_db/api/api_windows_amd64.go | 10 - .../ibmdb/go_ibm_db/api/mksyscall_unix.pl | 132 ------- .../ibmdb/go_ibm_db/api/zapi_unix.go | 118 ------ .../ibmdb/go_ibm_db/api/zapi_windows.go | 161 --------- src/github.com/ibmdb/go_ibm_db/column.go | 283 --------------- src/github.com/ibmdb/go_ibm_db/conn.go | 47 --- src/github.com/ibmdb/go_ibm_db/driver.go | 60 ---- src/github.com/ibmdb/go_ibm_db/error.go | 72 ---- src/github.com/ibmdb/go_ibm_db/handle.go | 44 --- .../ibmdb/go_ibm_db/installer/setup.go | 235 ------------ src/github.com/ibmdb/go_ibm_db/odbcstmt.go | 157 -------- src/github.com/ibmdb/go_ibm_db/param.go | 165 --------- src/github.com/ibmdb/go_ibm_db/pooling.go | 205 ----------- src/github.com/ibmdb/go_ibm_db/result.go | 22 -- src/github.com/ibmdb/go_ibm_db/rows.go | 45 --- src/github.com/ibmdb/go_ibm_db/stats.go | 33 -- src/github.com/ibmdb/go_ibm_db/stmt.go | 99 ------ .../ibmdb/go_ibm_db/testdata/begin_test.go | 9 - .../ibmdb/go_ibm_db/testdata/close_test.go | 9 - .../ibmdb/go_ibm_db/testdata/columns_test.go | 9 - .../ibmdb/go_ibm_db/testdata/commit_test.go | 9 - .../ibmdb/go_ibm_db/testdata/conn_test.go | 9 - .../ibmdb/go_ibm_db/testdata/create_test.go | 9 - .../ibmdb/go_ibm_db/testdata/drop_test.go | 9 - .../ibmdb/go_ibm_db/testdata/insert_test.go | 9 - .../ibmdb/go_ibm_db/testdata/main.go | 250 ------------- .../ibmdb/go_ibm_db/testdata/next_test.go | 9 - .../ibmdb/go_ibm_db/testdata/poolopen_test.go | 10 - .../ibmdb/go_ibm_db/testdata/prepare_test.go | 9 - .../ibmdb/go_ibm_db/testdata/query_test.go | 9 - .../ibmdb/go_ibm_db/testdata/queryrow_test.go | 9 - .../ibmdb/go_ibm_db/testdata/scan_test.go | 9 - src/github.com/ibmdb/go_ibm_db/tx.go | 67 ---- src/github.com/ibmdb/go_ibm_db/utf16.go | 55 --- 43 files changed, 3367 deletions(-) delete mode 100644 src/github.com/ibmdb/go_ibm_db/API_DOCUMENTATION.md delete mode 100644 src/github.com/ibmdb/go_ibm_db/CONTRIBUTING.md delete mode 100644 src/github.com/ibmdb/go_ibm_db/LICENSE.md delete mode 100644 src/github.com/ibmdb/go_ibm_db/README.md delete mode 100644 src/github.com/ibmdb/go_ibm_db/api/Makefile delete mode 100644 src/github.com/ibmdb/go_ibm_db/api/api.go delete mode 100644 src/github.com/ibmdb/go_ibm_db/api/api_unix.go delete mode 100644 src/github.com/ibmdb/go_ibm_db/api/api_windows.go delete mode 100644 src/github.com/ibmdb/go_ibm_db/api/api_windows_386.go delete mode 100644 src/github.com/ibmdb/go_ibm_db/api/api_windows_amd64.go delete mode 100644 src/github.com/ibmdb/go_ibm_db/api/mksyscall_unix.pl delete mode 100644 src/github.com/ibmdb/go_ibm_db/api/zapi_unix.go delete mode 100644 src/github.com/ibmdb/go_ibm_db/api/zapi_windows.go delete mode 100644 src/github.com/ibmdb/go_ibm_db/column.go delete mode 100644 src/github.com/ibmdb/go_ibm_db/conn.go delete mode 100644 src/github.com/ibmdb/go_ibm_db/driver.go delete mode 100644 src/github.com/ibmdb/go_ibm_db/error.go delete mode 100644 src/github.com/ibmdb/go_ibm_db/handle.go delete mode 100644 src/github.com/ibmdb/go_ibm_db/installer/setup.go delete mode 100644 src/github.com/ibmdb/go_ibm_db/odbcstmt.go delete mode 100644 src/github.com/ibmdb/go_ibm_db/param.go delete mode 100644 src/github.com/ibmdb/go_ibm_db/pooling.go delete mode 100644 src/github.com/ibmdb/go_ibm_db/result.go delete mode 100644 src/github.com/ibmdb/go_ibm_db/rows.go delete mode 100644 src/github.com/ibmdb/go_ibm_db/stats.go delete mode 100644 src/github.com/ibmdb/go_ibm_db/stmt.go delete mode 100644 src/github.com/ibmdb/go_ibm_db/testdata/begin_test.go delete mode 100644 src/github.com/ibmdb/go_ibm_db/testdata/close_test.go delete mode 100644 src/github.com/ibmdb/go_ibm_db/testdata/columns_test.go delete mode 100644 src/github.com/ibmdb/go_ibm_db/testdata/commit_test.go delete mode 100644 src/github.com/ibmdb/go_ibm_db/testdata/conn_test.go delete mode 100644 src/github.com/ibmdb/go_ibm_db/testdata/create_test.go delete mode 100644 src/github.com/ibmdb/go_ibm_db/testdata/drop_test.go delete mode 100644 src/github.com/ibmdb/go_ibm_db/testdata/insert_test.go delete mode 100644 src/github.com/ibmdb/go_ibm_db/testdata/main.go delete mode 100644 src/github.com/ibmdb/go_ibm_db/testdata/next_test.go delete mode 100644 src/github.com/ibmdb/go_ibm_db/testdata/poolopen_test.go delete mode 100644 src/github.com/ibmdb/go_ibm_db/testdata/prepare_test.go delete mode 100644 src/github.com/ibmdb/go_ibm_db/testdata/query_test.go delete mode 100644 src/github.com/ibmdb/go_ibm_db/testdata/queryrow_test.go delete mode 100644 src/github.com/ibmdb/go_ibm_db/testdata/scan_test.go delete mode 100644 src/github.com/ibmdb/go_ibm_db/tx.go delete mode 100644 src/github.com/ibmdb/go_ibm_db/utf16.go diff --git a/src/github.com/ibmdb/go_ibm_db/API_DOCUMENTATION.md b/src/github.com/ibmdb/go_ibm_db/API_DOCUMENTATION.md deleted file mode 100644 index 57cfd4e..0000000 --- a/src/github.com/ibmdb/go_ibm_db/API_DOCUMENTATION.md +++ /dev/null @@ -1,335 +0,0 @@ -# go-ibm_db API Documentation - -## Database APIs - -**Database APIs** - -1. [.Open(drivername,ConnectionString)](#OpenApi) -2. [.Prepare(sqlquery)](#PrepareApi) -3. [.Query(sqlquery)](#QueryApi) -4. [.Exec(sqlquery)](#ExecApi) -5. [.Begin()](#BeginApi) -6. [.Close()](#CloseApi) -7. [.Commit()](#CommitApi) -8. [.Rollback()](#RollbackApi) -9. [.QueryRow(sqlquery)](#QueryRowApi) -10. [.Columns()](#ColumnsApi) -11. [.Next()](#NextApi) -12. [.Scan(options)](#ScanApi) - -### 1) .Open(drivername,ConnectionString) - -open a connection to database -* **connectionString** - The connection string for your database. -* For distributed platforms, the connection string is typically defined as: `DATABASE=dbname;HOSTNAME=hostname;PORT=port;PROTOCOL=TCPIP;UID=username;PWD=passwd` - -```javascript -var connStr = flag.String("conn", "HOSTNAME=hostname;PORT=port;DATABASE=dbname;UID=uid;PWD=Pass", "connection string") -func dboper() error { -fmt.Println("connecting to driver"); -db, err:=sql.Open("drivername",*connStr); -if err != nil{ -return err; -} -defer db.Close() -} -``` -### 2) .Prepare(sqlquery) - -Prepare a statement for execution -* **sql** - SQL string to prepare - -Returns a ‘statement’ object - -```javascript -func oper() error{ -fmt.Println("connecting to go-ibm_db"); -db, err:=sql.Open("go-imb_db",*connStr); -if err != nil{ -return err; -} -defer db.Close() -st, err:=db.Prepare("select * from ak") -if err !=nil{ -return err -} -rows,err :=st.Query() -if err != nil{ -return err -} -defer rows.Close() -} -``` - -### 3) .Query(sqlquery) - -Issue a SQL query to the database - -If the query is executed then it will return the rows or it will return error - -```javascript - -func oper() error{ -fmt.Println("connecting to go-ibm_db"); -db, err:=sql.Open("go-ibm_db",*connStr); -if err != nil{ -return err; -} -defer db.Close() -rows,err :=db.Query(“select * from ak”) -if err != nil{ -return err -} -defer rows.Close() -} -``` - - -### 4) .Exec(sqlquery) - -Execute a prepared statement. - -Only DML commands are performed. No data is returned back. - -```javascript - -func oper() error{ -fmt.Println("connecting to go-ibm_db"); -db, err:=sql.Open("go-ibm_db",*connStr); -if err != nil{ -return err; -} -defer db.Close() -_,err=db.Exec("create table ghh(a int, b float, c double, d char, e varchar(30))") -if err != nil{ -return err -} -} -``` - -### 5) .Begin() - -Begin a transaction. - -```javascript - - -func oper() error{ -fmt.Println("connecting to go-ibm_db"); -db, err:=sql.Open("go-ibm_db",*connStr); -if err != nil{ -return err; -} -defer db.Close() -bg, err:=db.Begin() -if err !=nil{ -return err -} -return nil -} -``` - - - -### 6) .Close() - -Close the currently opened database. - -```javascript - -func dboper() error { -fmt.Println("connecting to go-ibm_db"); -db, err:=sql.Open("go-ibm_db",*connStr); -if err != nil{ -return err; -} -defer db.Close() -} -``` - - - -### 7) .Commit() - -Commit a transaction. - -```javascript - -func oper() error{ -fmt.Println("connecting to go-ibm_db"); -db, err:=sql.Open("go-ibm_db",*connStr); -if err != nil{ -return err; -} -defer db.Close() -bg, err:=db.Begin() -if err !=nil{ -return err -} -_,err=bg.Exec("create table ghh(a int,b float,c double,d char,e varchar(30))") -if err != nil{ -return err -} -err=bg.Commit() -if err != nil{ -return err -} -return nil -} -``` - - - - -### 8) .Rollback() - -Rollback a transaction. - -```javascript - - -func oper() error{ -fmt.Println("connecting to go-ibm_db"); -db, err:=sql.Open("go-ibm_db",*connStr); -if err != nil{ -return err; -} -defer db.Close() -bg, err:=db.Begin() -if err !=nil{ -return err -} -_,err=bg.Exec("create table ghh(a int,b float,c double,d char,e varchar(30))") -if err != nil{ -return err -} -err=bg.Rollback() -if err != nil{ -return err -} -return nil -} -``` - -### 9) .QueryRow(sqlquery) - -QueryRow executes a query that is expected to return at most one row. -If there are more rows then it will scan first and discards the rest. - -```javascript - -func oper() error{ -id := 123 -var username string -err := db.QueryRow("SELECT name FROM ak WHERE id=?", id).Scan(&username) - if err != nil { - return err -} -fmt.Printf("Username is %s\n", username) -return nil -} - -``` - -### 10) .Columns() - -Returns the column names. - -Returns error if the rows are closed. - -```javascript - -func oper() error{ -fmt.Println("connecting to databse"); -db, err:=sql.Open("go-ibm_db",*connStr); -if err != nil{ -return err; -} -defer db.Close() -st, err:=db.Prepare("select * from ak") -if err !=nil{ -return err -} -rows,err :=st.Query() -if err != nil{ -return err -} -defer rows.Close() -name11 := make([]string,1) -name11,err = rows.Columns() -fmt.Printf("%v",name11); -return nil -} -``` - -### 11) .Next() - -Prepares the next result row for reading with the scan api. - -```javascript - -func oper() error{ -fmt.Println("connecting to database"); -db, err:=sql.Open("go-ibm_db",*connStr); -if err != nil{ -return err; -} -defer db.Close() -rows,err :=db.Query() -if err != nil{ -return err -} -defer rows.Close() -for rows.Next(){ -var t string -var x string -err = rows.Scan(&t,&x) -if err != nil{ -return err -} -fmt.Printf("%v %v\n",t,x) -} -return nil -} -``` - -### 12) .Scan(options) - -copies the columns in the current row into the values pointed. - -```javascript - -func oper() error{ -fmt.Println("connecting to database"); -db, err:=sql.Open("go-ibm_db",*connStr); -if err != nil{ -return err; -} -defer db.Close() -rows,err :=db.Query() -if err != nil{ -return err -} -defer rows.Close() -for rows.Next(){ -var t string -var x string -err = rows.Scan(&t,&x) -if err != nil{ -return err -} -fmt.Printf("%v %v\n",t,x) -} -return nil -} -``` - - - - - - - - - - diff --git a/src/github.com/ibmdb/go_ibm_db/CONTRIBUTING.md b/src/github.com/ibmdb/go_ibm_db/CONTRIBUTING.md deleted file mode 100644 index 41c3376..0000000 --- a/src/github.com/ibmdb/go_ibm_db/CONTRIBUTING.md +++ /dev/null @@ -1,11 +0,0 @@ -# Developer's Certificate of Origin 1.1 - -By making a contribution to this project, I certify that: - -(a) The contribution was created in whole or in part by me and I have the right to submit it under the open source license indicated in the file; or - -(b) The contribution is based upon previous work that, to the best of my knowledge, is covered under an appropriate open source license and I have the right under that license to submit that work with modifications, whether created in whole or in part by me, under the same open source license (unless I am permitted to submit under a different license), as indicated in the file; or - -(c) The contribution was provided directly to me by some other person who certified (a), (b) or (c) and I have not modified it. - -(d) I understand and agree that this project and the contribution are public and that a record of the contribution (including all personal information I submit with it, including my sign-off) is maintained indefinitely and may be redistributed consistent with this project or the open source license(s) involved. \ No newline at end of file diff --git a/src/github.com/ibmdb/go_ibm_db/LICENSE.md b/src/github.com/ibmdb/go_ibm_db/LICENSE.md deleted file mode 100644 index 7448756..0000000 --- a/src/github.com/ibmdb/go_ibm_db/LICENSE.md +++ /dev/null @@ -1,27 +0,0 @@ -Copyright (c) 2012 The Go Authors. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/src/github.com/ibmdb/go_ibm_db/README.md b/src/github.com/ibmdb/go_ibm_db/README.md deleted file mode 100644 index 3f7fcba..0000000 --- a/src/github.com/ibmdb/go_ibm_db/README.md +++ /dev/null @@ -1,244 +0,0 @@ -# go_ibm_db - -Interface for GoLang to DB2 for z/OS, DB2 for LUW, DB2 for i. - -## API Documentation - -> For complete list of go_ibm_db APIs and examples please check [APIDocumentation.md](https://github.com/ibmdb/go_ibm_db/blob/master/API_DOCUMENTATION.md) - -## Prerequisite - -Golang should be installed in your system. - -## How to Install in Windows -``` -go get -d github.com/ibmdb/go_ibm_db - -If you already have a cli driver available in your system, add the path of the same to your Path windows environment variable -Example: Path = C:\Program Files\IBM\IBM DATA SERVER DRIVER\bin - - -If you do not have a clidriver in your system, go to installer folder where go_ibm_db is downloaded in your system (Example: C:\Users\uname\go\src\github.com\ibmdb\go_ibm_db\installer) and run setup.go file (go run setup.go). - -where uname is the username - -Above command will download clidriver. - -Add the path of the clidriver downloaded to your Path windows environment variable -(Example: Path=C:\Users\rakhil\go\src\github.com\ibmdb\go_ibm_db\installer\clidriver\bin) - - -``` - -## How to Install in Linux/Mac -``` -go get -d github.com/ibmdb/go_ibm_db - -If you already have a cli driver available in your system, set the below environment variables with the clidriver path - -export DB2HOME=/home/rakhil/dsdriver -export CGO_CFLAGS=-I$DB2HOME/include -export CGO_LDFLAGS=-L$DB2HOME/lib -Linux: -export LD_LIBRARY_PATH=/home/rakhil/dsdriver/lib -Mac: -export DYLD_LIBRARY_PATH=$DYLD_LIBRARY_PATH:/Applications/dsdriver/lib - -If you do not have a clidriver available in your system -go to installer folder where go_ibm_db is downloaded in your system (Example: /home/uname/go/src/github.com/imdb/go_ibm_db/installer) and run setup.go file (go run setup.go) -where uname is the username - -Above command will download clidriver. - -Set the below envronment variables with the path of the clidriver downloaded - -export DB2HOME=/home/uname/go/src/github.com/imdb/go_ibm_db/installer/clidriver -export CGO_CFLAGS=-I$DB2HOME/include -export CGO_LDFLAGS=-L$DB2HOME/lib -Linux: -export LD_LIBRARY_PATH=/home/uname/go/src/github.com/ibmdb/go_ibm_db/installer/clidriver/lib -Mac: -export DYLD_LIBRARY_PATH=$DYLD_LIBRARY_PATH:/home/uname/go/src/github.com/ibmdb/go_ibm_db/installer/clidriver/lib - - -``` - -## How to run sample program - -### example1.go:- - -``` -package main - -import ( - _ "github.com/ibmdb/go_ibm_db" - "database/sql" - "fmt" -) - -func main(){ - con:="HOSTNAME=host;DATABASE=name;PORT=number;UID=username;PWD=password" - db, err:=sql.Open("go_ibm_db", con) - if err != nil{ - - fmt.Println(err) - } - db.Close() -} -To run the sample:- go run example1.go -``` - -### example2.go:- - -``` -package main - -import ( - _ "github.com/ibmdb/go_ibm_db" - "database/sql" - "fmt" -) - -func Create_Con(con string) *sql.DB{ - db, err:=sql.Open("go_ibm_db", con) - if err != nil{ - - fmt.Println(err) - return nil - } - return db -} - -//creating a table - -func create(db *sql.DB) error{ - _,err:=db.Exec("DROP table SAMPLE") - if(err!=nil){ - _,err:=db.Exec("create table SAMPLE(ID varchar(20),NAME varchar(20),LOCATION varchar(20),POSITION varchar(20))") - if err != nil{ - return err - } - } else { - _,err:=db.Exec("create table SAMPLE(ID varchar(20),NAME varchar(20),LOCATION varchar(20),POSITION varchar(20))") - if err != nil{ - return err - } - } - fmt.Println("TABLE CREATED") - return nil -} - -//inserting row - -func insert(db *sql.DB) error{ - st, err:=db.Prepare("Insert into SAMPLE(ID,NAME,LOCATION,POSITION) values('3242','mike','hyd','manager')") - if err != nil{ - return err - } - st.Query() - return nil -} - -//this api selects the data from the table and prints it - -func display(db *sql.DB) error{ - st, err:=db.Prepare("select * from SAMPLE") - if err !=nil{ - return err - } - err=execquery(st) - if err!=nil{ - return err - } - return nil -} - - -func execquery(st *sql.Stmt) error{ - rows,err :=st.Query() - if err != nil{ - return err - } - cols, _ := rows.Columns() - fmt.Printf("%s %s %s %s\n",cols[0],cols[1],cols[2],cols[3]) - fmt.Println("-------------------------------------") - defer rows.Close() - for rows.Next(){ - var t,x,m,n string - err = rows.Scan(&t,&x,&m,&n) - if err != nil{ - return err - } - fmt.Printf("%v %v %v %v\n",t,x,m,n) - } - return nil -} - -func main(){ - con:="HOSTNAME=host;DATABASE=name;PORT=number;UID=username;PWD=password" - type Db *sql.DB - var re Db - re=Create_Con(con) - err:=create(re) - if err != nil{ - fmt.Println(err) - } - err=insert(re) - if err != nil{ - fmt.Println(err) - } - err=display(re) - if err != nil{ - fmt.Println(err) - } -} -To run the sample:- go run example2.go -``` - -### example3.go:-(POOLING) - -``` -package main - -import ( - a "github.com/ibmdb/go_ibm_db" - _"database/sql" - "fmt" -) - -func main(){ - con:="HOSTNAME=host;PORT=number;DATABASE=name;UID=username;PWD=password"; - pool:=a.Pconnect("PoolSize=100") - - //SetConnMaxLifetime will atake the value in SECONDS - db:=pool.Open(con,"SetConnMaxLifetime=30") - st, err:=db.Prepare("Insert into SAMPLE values('hi','hi','hi','hi')") - if err != nil{ - fmt.Println(err) - } - st.Query() - - //Here the the time out is default. - db1:=pool.Open(con) - st1, err:=db1.Prepare("Insert into SAMPLE values('hi1','hi1','hi1','hi1')") - if err != nil{ - fmt.Println(err) - } - st1.Query() - - db1.Close() - db.Close() - pool.Display() - pool.Release() - pool.Display() -} -To run the sample:- go run example3.go -``` -For Running the Tests: -====================== - -1) Put your connection string in the main.go file in testdata folder - -2) Now run go test command (use go test -v command for details) - - diff --git a/src/github.com/ibmdb/go_ibm_db/api/Makefile b/src/github.com/ibmdb/go_ibm_db/api/Makefile deleted file mode 100644 index 2bdd255..0000000 --- a/src/github.com/ibmdb/go_ibm_db/api/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -# Copyright 2012 The Go Authors. All rights reserved. -# Use of this source code is governed by a BSD-style -# license that can be found in the LICENSE file. - -all: zapi_windows.go zapi_unix.go - -zapi_windows.go: api.go - $(GOROOT)/src/pkg/syscall/mksyscall_windows.pl $^ \ - | gofmt \ - > $@ - -zapi_unix.go: api.go - ./mksyscall_unix.pl $^ \ - | gofmt \ - > $@ diff --git a/src/github.com/ibmdb/go_ibm_db/api/api.go b/src/github.com/ibmdb/go_ibm_db/api/api.go deleted file mode 100644 index aa7abae..0000000 --- a/src/github.com/ibmdb/go_ibm_db/api/api.go +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package api - -import ( - "unicode/utf16" -) - -type ( - SQL_DATE_STRUCT struct { - Year SQLSMALLINT - Month SQLUSMALLINT - Day SQLUSMALLINT - } - - SQL_TIMESTAMP_STRUCT struct { - Year SQLSMALLINT - Month SQLUSMALLINT - Day SQLUSMALLINT - Hour SQLUSMALLINT - Minute SQLUSMALLINT - Second SQLUSMALLINT - Fraction SQLUINTEGER - } -) - -//sys SQLAllocHandle(handleType SQLSMALLINT, inputHandle SQLHANDLE, outputHandle *SQLHANDLE) (ret SQLRETURN) = odbc32.SQLAllocHandle -//sys SQLBindCol(statementHandle SQLHSTMT, columnNumber SQLUSMALLINT, targetType SQLSMALLINT, targetValuePtr SQLPOINTER, bufferLength SQLLEN, vallen *SQLLEN) (ret SQLRETURN) = odbc32.SQLBindCol -//sys SQLBindParameter(statementHandle SQLHSTMT, parameterNumber SQLUSMALLINT, inputOutputType SQLSMALLINT, valueType SQLSMALLINT, parameterType SQLSMALLINT, columnSize SQLULEN, decimalDigits SQLSMALLINT, parameterValue SQLPOINTER, bufferLength SQLLEN, ind *SQLLEN) (ret SQLRETURN) = odbc32.SQLBindParameter -//sys SQLCloseCursor(statementHandle SQLHSTMT) (ret SQLRETURN) = odbc32.SQLCloseCursor -//sys SQLDescribeCol(statementHandle SQLHSTMT, columnNumber SQLUSMALLINT, columnName *SQLWCHAR, bufferLength SQLSMALLINT, nameLengthPtr *SQLSMALLINT, dataTypePtr *SQLSMALLINT, columnSizePtr *SQLULEN, decimalDigitsPtr *SQLSMALLINT, nullablePtr *SQLSMALLINT) (ret SQLRETURN) = odbc32.SQLDescribeColW -//sys SQLDescribeParam(statementHandle SQLHSTMT, parameterNumber SQLUSMALLINT, dataTypePtr *SQLSMALLINT, parameterSizePtr *SQLULEN, decimalDigitsPtr *SQLSMALLINT, nullablePtr *SQLSMALLINT) (ret SQLRETURN) = odbc32.SQLDescribeParam -//sys SQLDisconnect(connectionHandle SQLHDBC) (ret SQLRETURN) = odbc32.SQLDisconnect -//sys SQLDriverConnect(connectionHandle SQLHDBC, windowHandle SQLHWND, inConnectionString *SQLWCHAR, stringLength1 SQLSMALLINT, outConnectionString *SQLWCHAR, bufferLength SQLSMALLINT, stringLength2Ptr *SQLSMALLINT, driverCompletion SQLUSMALLINT) (ret SQLRETURN) = odbc32.SQLDriverConnectW -//sys SQLEndTran(handleType SQLSMALLINT, handle SQLHANDLE, completionType SQLSMALLINT) (ret SQLRETURN) = odbc32.SQLEndTran -//sys SQLExecute(statementHandle SQLHSTMT) (ret SQLRETURN) = odbc32.SQLExecute -//sys SQLFetch(statementHandle SQLHSTMT) (ret SQLRETURN) = odbc32.SQLFetch -//sys SQLFreeHandle(handleType SQLSMALLINT, handle SQLHANDLE) (ret SQLRETURN) = odbc32.SQLFreeHandle -//sys SQLGetData(statementHandle SQLHSTMT, colOrParamNum SQLUSMALLINT, targetType SQLSMALLINT, targetValuePtr SQLPOINTER, bufferLength SQLLEN, vallen *SQLLEN) (ret SQLRETURN) = odbc32.SQLGetData -//sys SQLGetDiagRec(handleType SQLSMALLINT, handle SQLHANDLE, recNumber SQLSMALLINT, sqlState *SQLWCHAR, nativeErrorPtr *SQLINTEGER, messageText *SQLWCHAR, bufferLength SQLSMALLINT, textLengthPtr *SQLSMALLINT) (ret SQLRETURN) = odbc32.SQLGetDiagRecW -//sys SQLNumParams(statementHandle SQLHSTMT, parameterCountPtr *SQLSMALLINT) (ret SQLRETURN) = odbc32.SQLNumParams -//sys SQLNumResultCols(statementHandle SQLHSTMT, columnCountPtr *SQLSMALLINT) (ret SQLRETURN) = odbc32.SQLNumResultCols -//sys SQLPrepare(statementHandle SQLHSTMT, statementText *SQLWCHAR, textLength SQLINTEGER) (ret SQLRETURN) = odbc32.SQLPrepareW -//sys SQLRowCount(statementHandle SQLHSTMT, rowCountPtr *SQLLEN) (ret SQLRETURN) = odbc32.SQLRowCount -//sys SQLSetEnvAttr(environmentHandle SQLHENV, attribute SQLINTEGER, valuePtr SQLPOINTER, stringLength SQLINTEGER) (ret SQLRETURN) = odbc32.SQLSetEnvAttr -//sys SQLSetConnectAttr(connectionHandle SQLHDBC, attribute SQLINTEGER, valuePtr SQLPOINTER, stringLength SQLINTEGER) (ret SQLRETURN) = odbc32.SQLSetConnectAttrW - -// UTF16ToString returns the UTF-8 encoding of the UTF-16 sequence s, -// with a terminating NUL removed. -func UTF16ToString(s []uint16) string { - for i, v := range s { - if v == 0 { - s = s[0:i] - break - } - } - return string(utf16.Decode(s)) -} - -// StringToUTF16 returns the UTF-16 encoding of the UTF-8 string s, -// with a terminating NUL added. -func StringToUTF16(s string) []uint16 { return utf16.Encode([]rune(s + "\x00")) } - -// StringToUTF16Ptr returns pointer to the UTF-16 encoding of -// the UTF-8 string s, with a terminating NUL added. -func StringToUTF16Ptr(s string) *uint16 { return &StringToUTF16(s)[0] } diff --git a/src/github.com/ibmdb/go_ibm_db/api/api_unix.go b/src/github.com/ibmdb/go_ibm_db/api/api_unix.go deleted file mode 100644 index 302345d..0000000 --- a/src/github.com/ibmdb/go_ibm_db/api/api_unix.go +++ /dev/null @@ -1,137 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build darwin linux -// +build cgo - -package api - -// #cgo darwin LDFLAGS: -ldb2 -// #cgo linux LDFLAGS: -ldb2 -// #include -import "C" - -const ( - SQL_OV_ODBC3 = uintptr(C.SQL_OV_ODBC3) - - SQL_ATTR_ODBC_VERSION = C.SQL_ATTR_ODBC_VERSION - - SQL_DRIVER_NOPROMPT = C.SQL_DRIVER_NOPROMPT - - SQL_HANDLE_ENV = C.SQL_HANDLE_ENV - SQL_HANDLE_DBC = C.SQL_HANDLE_DBC - SQL_HANDLE_STMT = C.SQL_HANDLE_STMT - - SQL_SUCCESS = C.SQL_SUCCESS - SQL_SUCCESS_WITH_INFO = C.SQL_SUCCESS_WITH_INFO - SQL_INVALID_HANDLE = C.SQL_INVALID_HANDLE - SQL_NO_DATA = C.SQL_NO_DATA - SQL_NO_TOTAL = C.SQL_NO_TOTAL - SQL_NTS = C.SQL_NTS - SQL_MAX_MESSAGE_LENGTH = C.SQL_MAX_MESSAGE_LENGTH - SQL_NULL_HANDLE = uintptr(C.SQL_NULL_HANDLE) - SQL_NULL_HENV = uintptr(C.SQL_NULL_HENV) - SQL_NULL_HDBC = uintptr(C.SQL_NULL_HDBC) - SQL_NULL_HSTMT = uintptr(C.SQL_NULL_HSTMT) - - SQL_PARAM_INPUT = C.SQL_PARAM_INPUT - - SQL_NULL_DATA = C.SQL_NULL_DATA - SQL_DATA_AT_EXEC = C.SQL_DATA_AT_EXEC - - SQL_UNKNOWN_TYPE = C.SQL_UNKNOWN_TYPE - SQL_CHAR = C.SQL_CHAR - SQL_NUMERIC = C.SQL_NUMERIC - SQL_DECIMAL = C.SQL_DECIMAL - SQL_INTEGER = C.SQL_INTEGER - SQL_SMALLINT = C.SQL_SMALLINT - SQL_FLOAT = C.SQL_FLOAT - SQL_REAL = C.SQL_REAL - SQL_DOUBLE = C.SQL_DOUBLE - SQL_DATETIME = C.SQL_DATETIME - SQL_DATE = C.SQL_DATE - SQL_TIME = C.SQL_TIME - SQL_VARCHAR = C.SQL_VARCHAR - SQL_TYPE_DATE = C.SQL_TYPE_DATE - SQL_TYPE_TIME = C.SQL_TYPE_TIME - SQL_TYPE_TIMESTAMP = C.SQL_TYPE_TIMESTAMP - SQL_TIMESTAMP = C.SQL_TIMESTAMP - SQL_LONGVARCHAR = C.SQL_LONGVARCHAR - SQL_BINARY = C.SQL_BINARY - SQL_VARBINARY = C.SQL_VARBINARY - SQL_LONGVARBINARY = C.SQL_LONGVARBINARY - SQL_BIGINT = C.SQL_BIGINT - SQL_TINYINT = C.SQL_TINYINT - SQL_BIT = C.SQL_BIT - SQL_WCHAR = C.SQL_WCHAR - SQL_WVARCHAR = C.SQL_WVARCHAR - SQL_WLONGVARCHAR = C.SQL_WLONGVARCHAR - SQL_GUID = C.SQL_GUID - SQL_BLOB = C.SQL_BLOB - SQL_CLOB = C.SQL_CLOB - SQL_SIGNED_OFFSET = C.SQL_SIGNED_OFFSET - SQL_UNSIGNED_OFFSET = C.SQL_UNSIGNED_OFFSET - - // TODO(lukemauldin): Not defined in sqlext.h. Using windows value, but it is not supported. - SQL_SS_XML = -152 - - SQL_C_CHAR = C.SQL_C_CHAR - SQL_C_LONG = C.SQL_C_LONG - SQL_C_SHORT = C.SQL_C_SHORT - SQL_C_FLOAT = C.SQL_C_FLOAT - SQL_C_DOUBLE = C.SQL_C_DOUBLE - SQL_C_NUMERIC = C.SQL_C_NUMERIC - SQL_C_DATE = C.SQL_C_DATE - SQL_C_TIME = C.SQL_C_TIME - SQL_C_TYPE_TIMESTAMP = C.SQL_C_TYPE_TIMESTAMP - SQL_C_TIMESTAMP = C.SQL_C_TIMESTAMP - SQL_C_BINARY = C.SQL_C_BINARY - SQL_C_BIT = C.SQL_C_BIT - SQL_C_WCHAR = C.SQL_C_WCHAR - SQL_C_DEFAULT = C.SQL_C_DEFAULT - SQL_C_SBIGINT = C.SQL_C_SBIGINT - SQL_C_UBIGINT = C.SQL_C_UBIGINT - SQL_C_GUID = C.SQL_C_GUID - - SQL_COMMIT = C.SQL_COMMIT - SQL_ROLLBACK = C.SQL_ROLLBACK - - SQL_AUTOCOMMIT = C.SQL_AUTOCOMMIT - SQL_ATTR_AUTOCOMMIT = C.SQL_ATTR_AUTOCOMMIT - SQL_AUTOCOMMIT_OFF = C.SQL_AUTOCOMMIT_OFF - SQL_AUTOCOMMIT_ON = C.SQL_AUTOCOMMIT_ON - SQL_AUTOCOMMIT_DEFAULT = C.SQL_AUTOCOMMIT_DEFAULT - - SQL_IS_UINTEGER = C.SQL_IS_UINTEGER - - //Connection pooling - SQL_ATTR_CONNECTION_POOLING = C.SQL_ATTR_CONNECTION_POOLING - SQL_ATTR_CP_MATCH = C.SQL_ATTR_CP_MATCH - SQL_CP_OFF = uintptr(C.SQL_CP_OFF) - SQL_CP_ONE_PER_DRIVER = uintptr(C.SQL_CP_ONE_PER_DRIVER) - SQL_CP_ONE_PER_HENV = uintptr(C.SQL_CP_ONE_PER_HENV) - SQL_CP_DEFAULT = SQL_CP_OFF - SQL_CP_STRICT_MATCH = uintptr(C.SQL_CP_STRICT_MATCH) - SQL_CP_RELAXED_MATCH = uintptr(C.SQL_CP_RELAXED_MATCH) -) - -type ( - SQLHANDLE C.SQLHANDLE - SQLHENV C.SQLHENV - SQLHDBC C.SQLHDBC - SQLHSTMT C.SQLHSTMT - SQLHWND uintptr - - SQLWCHAR C.SQLWCHAR - SQLSCHAR C.SQLSCHAR - SQLSMALLINT C.SQLSMALLINT - SQLUSMALLINT C.SQLUSMALLINT - SQLINTEGER C.SQLINTEGER - SQLUINTEGER C.SQLUINTEGER - SQLPOINTER C.SQLPOINTER - SQLRETURN C.SQLRETURN - - SQLLEN C.SQLLEN - SQLULEN C.SQLULEN -) diff --git a/src/github.com/ibmdb/go_ibm_db/api/api_windows.go b/src/github.com/ibmdb/go_ibm_db/api/api_windows.go deleted file mode 100644 index e3eba8f..0000000 --- a/src/github.com/ibmdb/go_ibm_db/api/api_windows.go +++ /dev/null @@ -1,133 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package api - -const ( - SQL_OV_ODBC3 = 3 - - SQL_ATTR_ODBC_VERSION = 200 - - SQL_DRIVER_NOPROMPT = 0 - - SQL_HANDLE_ENV = 1 - SQL_HANDLE_DBC = 2 - SQL_HANDLE_STMT = 3 - - SQL_SUCCESS = 0 - SQL_SUCCESS_WITH_INFO = 1 - SQL_INVALID_HANDLE = -2 - SQL_NO_DATA = 100 - SQL_NO_TOTAL = -4 - SQL_NTS = -3 - SQL_MAX_MESSAGE_LENGTH = 512 - SQL_NULL_HANDLE = 0 - SQL_NULL_HENV = 0 - SQL_NULL_HDBC = 0 - SQL_NULL_HSTMT = 0 - - SQL_PARAM_INPUT = 1 - - SQL_NULL_DATA = -1 - SQL_DATA_AT_EXEC = -2 - - SQL_UNKNOWN_TYPE = 0 - SQL_CHAR = 1 - SQL_NUMERIC = 2 - SQL_DECIMAL = 3 - SQL_INTEGER = 4 - SQL_SMALLINT = 5 - SQL_FLOAT = 6 - SQL_REAL = 7 - SQL_DOUBLE = 8 - SQL_DATETIME = 9 - SQL_DATE = 9 - SQL_TIME = 10 - SQL_VARCHAR = 12 - SQL_TYPE_DATE = 91 - SQL_TYPE_TIME = 92 - SQL_TYPE_TIMESTAMP = 93 - SQL_TIMESTAMP = 11 - SQL_LONGVARCHAR = -1 - SQL_BINARY = -2 - SQL_VARBINARY = -3 - SQL_LONGVARBINARY = -4 - SQL_BIGINT = -5 - SQL_TINYINT = -6 - SQL_BIT = -7 - SQL_WCHAR = -8 - SQL_WVARCHAR = -9 - SQL_WLONGVARCHAR = -10 - SQL_GUID = -11 - SQL_SIGNED_OFFSET = -20 - SQL_UNSIGNED_OFFSET = -22 - SQL_GRAPHIC = -95 - SQL_BLOB = -98 - SQL_CLOB = -99 - SQL_DBCLOB = -350 - SQL_SS_XML = -152 - - SQL_C_CHAR = SQL_CHAR - SQL_C_LONG = SQL_INTEGER - SQL_C_SHORT = SQL_SMALLINT - SQL_C_FLOAT = SQL_REAL - SQL_C_DOUBLE = SQL_DOUBLE - SQL_C_NUMERIC = SQL_NUMERIC - SQL_C_DATE = SQL_DATE - SQL_C_TIME = SQL_TIME - SQL_C_TYPE_TIMESTAMP = SQL_TYPE_TIMESTAMP - SQL_C_TIMESTAMP = SQL_TIMESTAMP - SQL_C_BINARY = SQL_BINARY - SQL_C_BIT = SQL_BIT - SQL_C_WCHAR = SQL_WCHAR - SQL_C_DEFAULT = 99 - SQL_C_SBIGINT = SQL_BIGINT + SQL_SIGNED_OFFSET - SQL_C_UBIGINT = SQL_BIGINT + SQL_UNSIGNED_OFFSET - SQL_C_GUID = SQL_GUID - - SQL_COMMIT = 0 - SQL_ROLLBACK = 1 - - SQL_AUTOCOMMIT = 102 - SQL_ATTR_AUTOCOMMIT = SQL_AUTOCOMMIT - SQL_AUTOCOMMIT_OFF = 0 - SQL_AUTOCOMMIT_ON = 1 - SQL_AUTOCOMMIT_DEFAULT = SQL_AUTOCOMMIT_ON - - SQL_IS_UINTEGER = -5 - - //Connection pooling - SQL_ATTR_CONNECTION_POOLING = 201 - SQL_ATTR_CP_MATCH = 202 - SQL_CP_OFF = 0 - SQL_CP_ONE_PER_DRIVER = 1 - SQL_CP_ONE_PER_HENV = 2 - SQL_CP_DEFAULT = SQL_CP_OFF - SQL_CP_STRICT_MATCH = 0 - SQL_CP_RELAXED_MATCH = 1 -) - -type ( - SQLHANDLE uintptr - SQLHENV SQLHANDLE - SQLHDBC SQLHANDLE - SQLHSTMT SQLHANDLE - SQLHWND uintptr - - SQLWCHAR uint16 - SQLSCHAR int8 - SQLSMALLINT int16 - SQLUSMALLINT uint16 - SQLINTEGER int32 - SQLUINTEGER uint32 - SQLPOINTER uintptr - SQLRETURN SQLSMALLINT - - SQLGUID struct { - Data1 uint32 - Data2 uint16 - Data3 uint16 - Data4 [8]byte - } -) diff --git a/src/github.com/ibmdb/go_ibm_db/api/api_windows_386.go b/src/github.com/ibmdb/go_ibm_db/api/api_windows_386.go deleted file mode 100644 index 2edf92a..0000000 --- a/src/github.com/ibmdb/go_ibm_db/api/api_windows_386.go +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package api - -type ( - SQLLEN SQLINTEGER - SQLULEN SQLUINTEGER -) diff --git a/src/github.com/ibmdb/go_ibm_db/api/api_windows_amd64.go b/src/github.com/ibmdb/go_ibm_db/api/api_windows_amd64.go deleted file mode 100644 index b603663..0000000 --- a/src/github.com/ibmdb/go_ibm_db/api/api_windows_amd64.go +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package api - -type ( - SQLLEN int64 - SQLULEN uint64 -) diff --git a/src/github.com/ibmdb/go_ibm_db/api/mksyscall_unix.pl b/src/github.com/ibmdb/go_ibm_db/api/mksyscall_unix.pl deleted file mode 100644 index eb6ecf5..0000000 --- a/src/github.com/ibmdb/go_ibm_db/api/mksyscall_unix.pl +++ /dev/null @@ -1,132 +0,0 @@ -#!/usr/bin/perl -# Copyright 2012 The Go Authors. All rights reserved. -# Use of this source code is governed by a BSD-style -# license that can be found in the LICENSE file. - -# This program is based on $GOROOT/src/pkg/syscall/mksyscall_windows.pl. - -use strict; - -my $cmdline = "mksyscall_unix.pl " . join(' ', @ARGV); -my $errors = 0; - -binmode STDOUT; - -if($ARGV[0] =~ /^-/) { - print STDERR "usage: mksyscall_unix.pl [file ...]\n"; - exit 1; -} - -sub parseparamlist($) { - my ($list) = @_; - $list =~ s/^\s*//; - $list =~ s/\s*$//; - if($list eq "") { - return (); - } - return split(/\s*,\s*/, $list); -} - -sub parseparam($) { - my ($p) = @_; - if($p !~ /^(\S*) (\S*)$/) { - print STDERR "$ARGV:$.: malformed parameter: $p\n"; - $errors = 1; - return ("xx", "int"); - } - return ($1, $2); -} - -my $package = ""; -my $text = ""; -while(<>) { - chomp; - s/\s+/ /g; - s/^\s+//; - s/\s+$//; - $package = $1 if !$package && /^package (\S+)$/; - next if !/^\/\/sys /; - - # Line must be of the form - # func Open(path string, mode int, perm int) (fd int, err error) - # Split into name, in params, out params. - if(!/^\/\/sys (\w+)\(([^()]*)\)\s*(?:\(([^()]+)\))?\s*(?:\[failretval(.*)\])?\s*(?:=\s*(?:(\w*)\.)?(\w*))?$/) { - print STDERR "$ARGV:$.: malformed //sys declaration\n"; - $errors = 1; - next; - } - my ($func, $in, $out, $failcond, $modname, $sysname) = ($1, $2, $3, $4, $5, $6); - - # Split argument lists on comma. - my @in = parseparamlist($in); - my @out = parseparamlist($out); - - # System call name. - if($sysname eq "") { - $sysname = "$func"; - } - - # Go function header. - $out = join(', ', @out); - if($out ne "") { - $out = " ($out)"; - } - if($text ne "") { - $text .= "\n" - } - $text .= sprintf "func %s(%s)%s {\n", $func, join(', ', @in), $out; - - # Prepare arguments. - my @sqlin= (); - my @pin= (); - foreach my $p (@in) { - my ($name, $type) = parseparam($p); - - if($type =~ /^\*(SQLCHAR)/) { - push @sqlin, sprintf "(*C.%s)(unsafe.Pointer(%s))", $1, $name; - } elsif($type =~ /^\*(SQLWCHAR)/) { - push @sqlin, sprintf "(*C.%s)(unsafe.Pointer(%s))", $1, $name; - } elsif($type =~ /^\*(.*)$/) { - push @sqlin, sprintf "(*C.%s)(%s)", $1, $name; - } else { - push @sqlin, sprintf "C.%s(%s)", $type, $name; - } - push @pin, sprintf "\"%s=\", %s, ", $name, $name; - } - - $text .= sprintf "\tr := C.%s(%s)\n", $sysname, join(',', @sqlin); - if(0) { - $text .= sprintf "println(\"SYSCALL: %s(\", %s\") (\", r, \")\")\n", $func, join('", ", ', @pin); - } - $text .= "\treturn SQLRETURN(r)\n"; - $text .= "}\n"; -} - -if($errors) { - exit 1; -} - -print < -import "C" - -$text - -EOF -exit 0; diff --git a/src/github.com/ibmdb/go_ibm_db/api/zapi_unix.go b/src/github.com/ibmdb/go_ibm_db/api/zapi_unix.go deleted file mode 100644 index d99a01a..0000000 --- a/src/github.com/ibmdb/go_ibm_db/api/zapi_unix.go +++ /dev/null @@ -1,118 +0,0 @@ -// mksyscall_unix.pl api.go -// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT - -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build darwin linux -// +build cgo - -package api - -import "unsafe" - -// #cgo darwin LDFLAGS: -ldb2 -// #cgo linux LDFLAGS: -ldb2 -// #include -import "C" - -func SQLAllocHandle(handleType SQLSMALLINT, inputHandle SQLHANDLE, outputHandle *SQLHANDLE) (ret SQLRETURN) { - r := C.SQLAllocHandle(C.SQLSMALLINT(handleType), C.SQLHANDLE(inputHandle), (*C.SQLHANDLE)(outputHandle)) - return SQLRETURN(r) -} - -func SQLBindCol(statementHandle SQLHSTMT, columnNumber SQLUSMALLINT, targetType SQLSMALLINT, targetValuePtr SQLPOINTER, bufferLength SQLLEN, vallen *SQLLEN) (ret SQLRETURN) { - r := C.SQLBindCol(C.SQLHSTMT(statementHandle), C.SQLUSMALLINT(columnNumber), C.SQLSMALLINT(targetType), C.SQLPOINTER(targetValuePtr), C.SQLLEN(bufferLength), (*C.SQLLEN)(vallen)) - return SQLRETURN(r) -} - -func SQLBindParameter(statementHandle SQLHSTMT, parameterNumber SQLUSMALLINT, inputOutputType SQLSMALLINT, valueType SQLSMALLINT, parameterType SQLSMALLINT, columnSize SQLULEN, decimalDigits SQLSMALLINT, parameterValue SQLPOINTER, bufferLength SQLLEN, ind *SQLLEN) (ret SQLRETURN) { - r := C.SQLBindParameter(C.SQLHSTMT(statementHandle), C.SQLUSMALLINT(parameterNumber), C.SQLSMALLINT(inputOutputType), C.SQLSMALLINT(valueType), C.SQLSMALLINT(parameterType), C.SQLULEN(columnSize), C.SQLSMALLINT(decimalDigits), C.SQLPOINTER(parameterValue), C.SQLLEN(bufferLength), (*C.SQLLEN)(ind)) - return SQLRETURN(r) -} - -func SQLCloseCursor(statementHandle SQLHSTMT) (ret SQLRETURN) { - r := C.SQLCloseCursor(C.SQLHSTMT(statementHandle)) - return SQLRETURN(r) -} - -func SQLDescribeCol(statementHandle SQLHSTMT, columnNumber SQLUSMALLINT, columnName *SQLWCHAR, bufferLength SQLSMALLINT, nameLengthPtr *SQLSMALLINT, dataTypePtr *SQLSMALLINT, columnSizePtr *SQLULEN, decimalDigitsPtr *SQLSMALLINT, nullablePtr *SQLSMALLINT) (ret SQLRETURN) { - r := C.SQLDescribeColW(C.SQLHSTMT(statementHandle), C.SQLUSMALLINT(columnNumber), (*C.SQLWCHAR)(unsafe.Pointer(columnName)), C.SQLSMALLINT(bufferLength), (*C.SQLSMALLINT)(nameLengthPtr), (*C.SQLSMALLINT)(dataTypePtr), (*C.SQLULEN)(columnSizePtr), (*C.SQLSMALLINT)(decimalDigitsPtr), (*C.SQLSMALLINT)(nullablePtr)) - return SQLRETURN(r) -} - -func SQLDescribeParam(statementHandle SQLHSTMT, parameterNumber SQLUSMALLINT, dataTypePtr *SQLSMALLINT, parameterSizePtr *SQLULEN, decimalDigitsPtr *SQLSMALLINT, nullablePtr *SQLSMALLINT) (ret SQLRETURN) { - r := C.SQLDescribeParam(C.SQLHSTMT(statementHandle), C.SQLUSMALLINT(parameterNumber), (*C.SQLSMALLINT)(dataTypePtr), (*C.SQLULEN)(parameterSizePtr), (*C.SQLSMALLINT)(decimalDigitsPtr), (*C.SQLSMALLINT)(nullablePtr)) - return SQLRETURN(r) -} - -func SQLDisconnect(connectionHandle SQLHDBC) (ret SQLRETURN) { - r := C.SQLDisconnect(C.SQLHDBC(connectionHandle)) - return SQLRETURN(r) -} - -func SQLDriverConnect(connectionHandle SQLHDBC, windowHandle SQLHWND, inConnectionString *SQLWCHAR, stringLength1 SQLSMALLINT, outConnectionString *SQLWCHAR, bufferLength SQLSMALLINT, stringLength2Ptr *SQLSMALLINT, driverCompletion SQLUSMALLINT) (ret SQLRETURN) { - r := C.SQLDriverConnectW(C.SQLHDBC(connectionHandle), C.SQLHWND(windowHandle), (*C.SQLWCHAR)(unsafe.Pointer(inConnectionString)), C.SQLSMALLINT(stringLength1), (*C.SQLWCHAR)(unsafe.Pointer(outConnectionString)), C.SQLSMALLINT(bufferLength), (*C.SQLSMALLINT)(stringLength2Ptr), C.SQLUSMALLINT(driverCompletion)) - return SQLRETURN(r) -} - -func SQLEndTran(handleType SQLSMALLINT, handle SQLHANDLE, completionType SQLSMALLINT) (ret SQLRETURN) { - r := C.SQLEndTran(C.SQLSMALLINT(handleType), C.SQLHANDLE(handle), C.SQLSMALLINT(completionType)) - return SQLRETURN(r) -} - -func SQLExecute(statementHandle SQLHSTMT) (ret SQLRETURN) { - r := C.SQLExecute(C.SQLHSTMT(statementHandle)) - return SQLRETURN(r) -} - -func SQLFetch(statementHandle SQLHSTMT) (ret SQLRETURN) { - r := C.SQLFetch(C.SQLHSTMT(statementHandle)) - return SQLRETURN(r) -} - -func SQLFreeHandle(handleType SQLSMALLINT, handle SQLHANDLE) (ret SQLRETURN) { - r := C.SQLFreeHandle(C.SQLSMALLINT(handleType), C.SQLHANDLE(handle)) - return SQLRETURN(r) -} - -func SQLGetData(statementHandle SQLHSTMT, colOrParamNum SQLUSMALLINT, targetType SQLSMALLINT, targetValuePtr SQLPOINTER, bufferLength SQLLEN, vallen *SQLLEN) (ret SQLRETURN) { - r := C.SQLGetData(C.SQLHSTMT(statementHandle), C.SQLUSMALLINT(colOrParamNum), C.SQLSMALLINT(targetType), C.SQLPOINTER(targetValuePtr), C.SQLLEN(bufferLength), (*C.SQLLEN)(vallen)) - return SQLRETURN(r) -} - -func SQLGetDiagRec(handleType SQLSMALLINT, handle SQLHANDLE, recNumber SQLSMALLINT, sqlState *SQLWCHAR, nativeErrorPtr *SQLINTEGER, messageText *SQLWCHAR, bufferLength SQLSMALLINT, textLengthPtr *SQLSMALLINT) (ret SQLRETURN) { - r := C.SQLGetDiagRecW(C.SQLSMALLINT(handleType), C.SQLHANDLE(handle), C.SQLSMALLINT(recNumber), (*C.SQLWCHAR)(unsafe.Pointer(sqlState)), (*C.SQLINTEGER)(nativeErrorPtr), (*C.SQLWCHAR)(unsafe.Pointer(messageText)), C.SQLSMALLINT(bufferLength), (*C.SQLSMALLINT)(textLengthPtr)) - return SQLRETURN(r) -} - -func SQLNumParams(statementHandle SQLHSTMT, parameterCountPtr *SQLSMALLINT) (ret SQLRETURN) { - r := C.SQLNumParams(C.SQLHSTMT(statementHandle), (*C.SQLSMALLINT)(parameterCountPtr)) - return SQLRETURN(r) -} - -func SQLNumResultCols(statementHandle SQLHSTMT, columnCountPtr *SQLSMALLINT) (ret SQLRETURN) { - r := C.SQLNumResultCols(C.SQLHSTMT(statementHandle), (*C.SQLSMALLINT)(columnCountPtr)) - return SQLRETURN(r) -} - -func SQLPrepare(statementHandle SQLHSTMT, statementText *SQLWCHAR, textLength SQLINTEGER) (ret SQLRETURN) { - r := C.SQLPrepareW(C.SQLHSTMT(statementHandle), (*C.SQLWCHAR)(unsafe.Pointer(statementText)), C.SQLINTEGER(textLength)) - return SQLRETURN(r) -} - -func SQLRowCount(statementHandle SQLHSTMT, rowCountPtr *SQLLEN) (ret SQLRETURN) { - r := C.SQLRowCount(C.SQLHSTMT(statementHandle), (*C.SQLLEN)(rowCountPtr)) - return SQLRETURN(r) -} - -func SQLSetEnvAttr(environmentHandle SQLHENV, attribute SQLINTEGER, valuePtr SQLPOINTER, stringLength SQLINTEGER) (ret SQLRETURN) { - r := C.SQLSetEnvAttr(C.SQLHENV(environmentHandle), C.SQLINTEGER(attribute), C.SQLPOINTER(valuePtr), C.SQLINTEGER(stringLength)) - return SQLRETURN(r) -} - -func SQLSetConnectAttr(connectionHandle SQLHDBC, attribute SQLINTEGER, valuePtr SQLPOINTER, stringLength SQLINTEGER) (ret SQLRETURN) { - r := C.SQLSetConnectAttrW(C.SQLHDBC(connectionHandle), C.SQLINTEGER(attribute), C.SQLPOINTER(valuePtr), C.SQLINTEGER(stringLength)) - return SQLRETURN(r) -} diff --git a/src/github.com/ibmdb/go_ibm_db/api/zapi_windows.go b/src/github.com/ibmdb/go_ibm_db/api/zapi_windows.go deleted file mode 100644 index ce0fd0f..0000000 --- a/src/github.com/ibmdb/go_ibm_db/api/zapi_windows.go +++ /dev/null @@ -1,161 +0,0 @@ -// mksyscall_windows.pl api.go -// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT - -package api - -import "unsafe" -import "syscall" -import "os" - -var ( - mododbc32 = syscall.NewLazyDLL(GetDllName()) - - procSQLAllocHandle = mododbc32.NewProc("SQLAllocHandle") - procSQLBindCol = mododbc32.NewProc("SQLBindCol") - procSQLBindParameter = mododbc32.NewProc("SQLBindParameter") - procSQLCloseCursor = mododbc32.NewProc("SQLCloseCursor") - procSQLDescribeColW = mododbc32.NewProc("SQLDescribeColW") - procSQLDescribeParam = mododbc32.NewProc("SQLDescribeParam") - procSQLDisconnect = mododbc32.NewProc("SQLDisconnect") - procSQLDriverConnectW = mododbc32.NewProc("SQLDriverConnectW") - procSQLEndTran = mododbc32.NewProc("SQLEndTran") - procSQLExecute = mododbc32.NewProc("SQLExecute") - procSQLFetch = mododbc32.NewProc("SQLFetch") - procSQLFreeHandle = mododbc32.NewProc("SQLFreeHandle") - procSQLGetData = mododbc32.NewProc("SQLGetData") - procSQLGetDiagRecW = mododbc32.NewProc("SQLGetDiagRecW") - procSQLNumParams = mododbc32.NewProc("SQLNumParams") - procSQLNumResultCols = mododbc32.NewProc("SQLNumResultCols") - procSQLPrepareW = mododbc32.NewProc("SQLPrepareW") - procSQLRowCount = mododbc32.NewProc("SQLRowCount") - procSQLSetEnvAttr = mododbc32.NewProc("SQLSetEnvAttr") - procSQLSetConnectAttrW = mododbc32.NewProc("SQLSetConnectAttrW") -) - -func GetDllName() string { - if winArch := os.Getenv("PROCESSOR_ARCHITECTURE"); winArch == "x86" { - return "db2cli.dll" - } else { - return "db2cli64.dll" - } -} - -func SQLAllocHandle(handleType SQLSMALLINT, inputHandle SQLHANDLE, outputHandle *SQLHANDLE) (ret SQLRETURN) { - r0, _, _ := syscall.Syscall(procSQLAllocHandle.Addr(), 3, uintptr(handleType), uintptr(inputHandle), uintptr(unsafe.Pointer(outputHandle))) - ret = SQLRETURN(r0) - return -} - -func SQLBindCol(statementHandle SQLHSTMT, columnNumber SQLUSMALLINT, targetType SQLSMALLINT, targetValuePtr SQLPOINTER, bufferLength SQLLEN, vallen *SQLLEN) (ret SQLRETURN) { - r0, _, _ := syscall.Syscall6(procSQLBindCol.Addr(), 6, uintptr(statementHandle), uintptr(columnNumber), uintptr(targetType), uintptr(targetValuePtr), uintptr(bufferLength), uintptr(unsafe.Pointer(vallen))) - ret = SQLRETURN(r0) - return -} - -func SQLBindParameter(statementHandle SQLHSTMT, parameterNumber SQLUSMALLINT, inputOutputType SQLSMALLINT, valueType SQLSMALLINT, parameterType SQLSMALLINT, columnSize SQLULEN, decimalDigits SQLSMALLINT, parameterValue SQLPOINTER, bufferLength SQLLEN, ind *SQLLEN) (ret SQLRETURN) { - r0, _, _ := syscall.Syscall12(procSQLBindParameter.Addr(), 10, uintptr(statementHandle), uintptr(parameterNumber), uintptr(inputOutputType), uintptr(valueType), uintptr(parameterType), uintptr(columnSize), uintptr(decimalDigits), uintptr(parameterValue), uintptr(bufferLength), uintptr(unsafe.Pointer(ind)), 0, 0) - ret = SQLRETURN(r0) - return -} - -func SQLCloseCursor(statementHandle SQLHSTMT) (ret SQLRETURN) { - r0, _, _ := syscall.Syscall(procSQLCloseCursor.Addr(), 1, uintptr(statementHandle), 0, 0) - ret = SQLRETURN(r0) - return -} - -func SQLDescribeCol(statementHandle SQLHSTMT, columnNumber SQLUSMALLINT, columnName *SQLWCHAR, bufferLength SQLSMALLINT, nameLengthPtr *SQLSMALLINT, dataTypePtr *SQLSMALLINT, columnSizePtr *SQLULEN, decimalDigitsPtr *SQLSMALLINT, nullablePtr *SQLSMALLINT) (ret SQLRETURN) { - r0, _, _ := syscall.Syscall9(procSQLDescribeColW.Addr(), 9, uintptr(statementHandle), uintptr(columnNumber), uintptr(unsafe.Pointer(columnName)), uintptr(bufferLength), uintptr(unsafe.Pointer(nameLengthPtr)), uintptr(unsafe.Pointer(dataTypePtr)), uintptr(unsafe.Pointer(columnSizePtr)), uintptr(unsafe.Pointer(decimalDigitsPtr)), uintptr(unsafe.Pointer(nullablePtr))) - ret = SQLRETURN(r0) - return -} - -func SQLDescribeParam(statementHandle SQLHSTMT, parameterNumber SQLUSMALLINT, dataTypePtr *SQLSMALLINT, parameterSizePtr *SQLULEN, decimalDigitsPtr *SQLSMALLINT, nullablePtr *SQLSMALLINT) (ret SQLRETURN) { - r0, _, _ := syscall.Syscall6(procSQLDescribeParam.Addr(), 6, uintptr(statementHandle), uintptr(parameterNumber), uintptr(unsafe.Pointer(dataTypePtr)), uintptr(unsafe.Pointer(parameterSizePtr)), uintptr(unsafe.Pointer(decimalDigitsPtr)), uintptr(unsafe.Pointer(nullablePtr))) - ret = SQLRETURN(r0) - return -} - -func SQLDisconnect(connectionHandle SQLHDBC) (ret SQLRETURN) { - r0, _, _ := syscall.Syscall(procSQLDisconnect.Addr(), 1, uintptr(connectionHandle), 0, 0) - ret = SQLRETURN(r0) - return -} - -func SQLDriverConnect(connectionHandle SQLHDBC, windowHandle SQLHWND, inConnectionString *SQLWCHAR, stringLength1 SQLSMALLINT, outConnectionString *SQLWCHAR, bufferLength SQLSMALLINT, stringLength2Ptr *SQLSMALLINT, driverCompletion SQLUSMALLINT) (ret SQLRETURN) { - r0, _, _ := syscall.Syscall9(procSQLDriverConnectW.Addr(), 8, uintptr(connectionHandle), uintptr(windowHandle), uintptr(unsafe.Pointer(inConnectionString)), uintptr(stringLength1), uintptr(unsafe.Pointer(outConnectionString)), uintptr(bufferLength), uintptr(unsafe.Pointer(stringLength2Ptr)), uintptr(driverCompletion), 0) - ret = SQLRETURN(r0) - return -} - -func SQLEndTran(handleType SQLSMALLINT, handle SQLHANDLE, completionType SQLSMALLINT) (ret SQLRETURN) { - r0, _, _ := syscall.Syscall(procSQLEndTran.Addr(), 3, uintptr(handleType), uintptr(handle), uintptr(completionType)) - ret = SQLRETURN(r0) - return -} - -func SQLExecute(statementHandle SQLHSTMT) (ret SQLRETURN) { - r0, _, _ := syscall.Syscall(procSQLExecute.Addr(), 1, uintptr(statementHandle), 0, 0) - ret = SQLRETURN(r0) - return -} - -func SQLFetch(statementHandle SQLHSTMT) (ret SQLRETURN) { - r0, _, _ := syscall.Syscall(procSQLFetch.Addr(), 1, uintptr(statementHandle), 0, 0) - ret = SQLRETURN(r0) - return -} - -func SQLFreeHandle(handleType SQLSMALLINT, handle SQLHANDLE) (ret SQLRETURN) { - r0, _, _ := syscall.Syscall(procSQLFreeHandle.Addr(), 2, uintptr(handleType), uintptr(handle), 0) - ret = SQLRETURN(r0) - return -} - -func SQLGetData(statementHandle SQLHSTMT, colOrParamNum SQLUSMALLINT, targetType SQLSMALLINT, targetValuePtr SQLPOINTER, bufferLength SQLLEN, vallen *SQLLEN) (ret SQLRETURN) { - r0, _, _ := syscall.Syscall6(procSQLGetData.Addr(), 6, uintptr(statementHandle), uintptr(colOrParamNum), uintptr(targetType), uintptr(targetValuePtr), uintptr(bufferLength), uintptr(unsafe.Pointer(vallen))) - ret = SQLRETURN(r0) - return -} - -func SQLGetDiagRec(handleType SQLSMALLINT, handle SQLHANDLE, recNumber SQLSMALLINT, sqlState *SQLWCHAR, nativeErrorPtr *SQLINTEGER, messageText *SQLWCHAR, bufferLength SQLSMALLINT, textLengthPtr *SQLSMALLINT) (ret SQLRETURN) { - r0, _, _ := syscall.Syscall9(procSQLGetDiagRecW.Addr(), 8, uintptr(handleType), uintptr(handle), uintptr(recNumber), uintptr(unsafe.Pointer(sqlState)), uintptr(unsafe.Pointer(nativeErrorPtr)), uintptr(unsafe.Pointer(messageText)), uintptr(bufferLength), uintptr(unsafe.Pointer(textLengthPtr)), 0) - ret = SQLRETURN(r0) - return -} - -func SQLNumParams(statementHandle SQLHSTMT, parameterCountPtr *SQLSMALLINT) (ret SQLRETURN) { - r0, _, _ := syscall.Syscall(procSQLNumParams.Addr(), 2, uintptr(statementHandle), uintptr(unsafe.Pointer(parameterCountPtr)), 0) - ret = SQLRETURN(r0) - return -} - -func SQLNumResultCols(statementHandle SQLHSTMT, columnCountPtr *SQLSMALLINT) (ret SQLRETURN) { - r0, _, _ := syscall.Syscall(procSQLNumResultCols.Addr(), 2, uintptr(statementHandle), uintptr(unsafe.Pointer(columnCountPtr)), 0) - ret = SQLRETURN(r0) - return -} - -func SQLPrepare(statementHandle SQLHSTMT, statementText *SQLWCHAR, textLength SQLINTEGER) (ret SQLRETURN) { - r0, _, _ := syscall.Syscall(procSQLPrepareW.Addr(), 3, uintptr(statementHandle), uintptr(unsafe.Pointer(statementText)), uintptr(textLength)) - ret = SQLRETURN(r0) - return -} - -func SQLRowCount(statementHandle SQLHSTMT, rowCountPtr *SQLLEN) (ret SQLRETURN) { - r0, _, _ := syscall.Syscall(procSQLRowCount.Addr(), 2, uintptr(statementHandle), uintptr(unsafe.Pointer(rowCountPtr)), 0) - ret = SQLRETURN(r0) - return -} - -func SQLSetEnvAttr(environmentHandle SQLHENV, attribute SQLINTEGER, valuePtr SQLPOINTER, stringLength SQLINTEGER) (ret SQLRETURN) { - r0, _, _ := syscall.Syscall6(procSQLSetEnvAttr.Addr(), 4, uintptr(environmentHandle), uintptr(attribute), uintptr(valuePtr), uintptr(stringLength), 0, 0) - ret = SQLRETURN(r0) - return -} - -func SQLSetConnectAttr(connectionHandle SQLHDBC, attribute SQLINTEGER, valuePtr SQLPOINTER, stringLength SQLINTEGER) (ret SQLRETURN) { - r0, _, _ := syscall.Syscall6(procSQLSetConnectAttrW.Addr(), 4, uintptr(connectionHandle), uintptr(attribute), uintptr(valuePtr), uintptr(stringLength), 0, 0) - ret = SQLRETURN(r0) - return -} diff --git a/src/github.com/ibmdb/go_ibm_db/column.go b/src/github.com/ibmdb/go_ibm_db/column.go deleted file mode 100644 index d78e7ff..0000000 --- a/src/github.com/ibmdb/go_ibm_db/column.go +++ /dev/null @@ -1,283 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package go_ibm_db - -import ( - "database/sql/driver" - "errors" - "fmt" - "time" - "unsafe" - - "github.com/ibmdb/go_ibm_db/api" -) - -type BufferLen api.SQLLEN - -func (l *BufferLen) IsNull() bool { - return int16(*l) == api.SQL_NULL_DATA -} - -func (l *BufferLen) GetData(h api.SQLHSTMT, idx int, ctype api.SQLSMALLINT, buf []byte) api.SQLRETURN { - return api.SQLGetData(h, api.SQLUSMALLINT(idx+1), ctype, - api.SQLPOINTER(unsafe.Pointer(&buf[0])), api.SQLLEN(len(buf)), - (*api.SQLLEN)(l)) -} - -func (l *BufferLen) Bind(h api.SQLHSTMT, idx int, ctype api.SQLSMALLINT, buf []byte) api.SQLRETURN { - return api.SQLBindCol(h, api.SQLUSMALLINT(idx+1), ctype, - api.SQLPOINTER(unsafe.Pointer(&buf[0])), api.SQLLEN(len(buf)), - (*api.SQLLEN)(l)) -} - -// Column provides access to row columns. -type Column interface { - Name() string - Bind(h api.SQLHSTMT, idx int) (bool, error) - Value(h api.SQLHSTMT, idx int) (driver.Value, error) -} - -func describeColumn(h api.SQLHSTMT, idx int, namebuf []uint16) (namelen int, sqltype api.SQLSMALLINT, size api.SQLULEN, ret api.SQLRETURN) { - var l, decimal, nullable api.SQLSMALLINT - ret = api.SQLDescribeCol(h, api.SQLUSMALLINT(idx+1), - (*api.SQLWCHAR)(unsafe.Pointer(&namebuf[0])), - api.SQLSMALLINT(len(namebuf)), &l, - &sqltype, &size, &decimal, &nullable) - return int(l), sqltype, size, ret -} - -// TODO(brainman): did not check for MS SQL timestamp - -func NewColumn(h api.SQLHSTMT, idx int) (Column, error) { - namebuf := make([]uint16, 150) - namelen, sqltype, size, ret := describeColumn(h, idx, namebuf) - if ret == api.SQL_SUCCESS_WITH_INFO && namelen > len(namebuf) { - // try again with bigger buffer - namebuf = make([]uint16, namelen) - namelen, sqltype, size, ret = describeColumn(h, idx, namebuf) - } - if IsError(ret) { - return nil, NewError("SQLDescribeCol", h) - } - if namelen > len(namebuf) { - // still complaining about buffer size - return nil, errors.New("Failed to allocate column name buffer") - } - b := &BaseColumn{ - name: api.UTF16ToString(namebuf[:namelen]), - } - switch sqltype { - case api.SQL_BIT: - return NewBindableColumn(b, api.SQL_C_BIT, 1), nil - case api.SQL_TINYINT, api.SQL_SMALLINT, api.SQL_INTEGER: - return NewBindableColumn(b, api.SQL_C_LONG, 4), nil - case api.SQL_BIGINT: - return NewBindableColumn(b, api.SQL_C_SBIGINT, 8), nil - case api.SQL_NUMERIC, api.SQL_DECIMAL, api.SQL_FLOAT, api.SQL_REAL, api.SQL_DOUBLE: - return NewBindableColumn(b, api.SQL_C_DOUBLE, 8), nil - case api.SQL_TYPE_TIMESTAMP: - var v api.SQL_TIMESTAMP_STRUCT - return NewBindableColumn(b, api.SQL_C_TYPE_TIMESTAMP, int(unsafe.Sizeof(v))), nil - case api.SQL_TYPE_DATE: - var v api.SQL_DATE_STRUCT - return NewBindableColumn(b, api.SQL_C_DATE, int(unsafe.Sizeof(v))), nil - case api.SQL_CHAR, api.SQL_VARCHAR, api.SQL_CLOB: - return NewVariableWidthColumn(b, api.SQL_C_CHAR, size), nil - case api.SQL_WCHAR, api.SQL_WVARCHAR: - return NewVariableWidthColumn(b, api.SQL_C_WCHAR, size), nil - case api.SQL_BINARY, api.SQL_VARBINARY, api.SQL_BLOB: - return NewVariableWidthColumn(b, api.SQL_C_BINARY, size), nil - case api.SQL_LONGVARCHAR: - return NewVariableWidthColumn(b, api.SQL_C_CHAR, 0), nil - case api.SQL_WLONGVARCHAR, api.SQL_SS_XML: - return NewVariableWidthColumn(b, api.SQL_C_WCHAR, 0), nil - case api.SQL_LONGVARBINARY: - return NewVariableWidthColumn(b, api.SQL_C_BINARY, 0), nil - default: - return nil, fmt.Errorf("unsupported column type %d", sqltype) - } - panic("unreachable") -} - -// BaseColumn implements common column functionality. -type BaseColumn struct { - name string - CType api.SQLSMALLINT -} - -func (c *BaseColumn) Name() string { - return c.name -} - -func (c *BaseColumn) Value(buf []byte) (driver.Value, error) { - var p unsafe.Pointer - if len(buf) > 0 { - p = unsafe.Pointer(&buf[0]) - } - switch c.CType { - case api.SQL_C_BIT: - return buf[0] != 0, nil - case api.SQL_C_LONG: - return *((*int32)(p)), nil - case api.SQL_C_SBIGINT: - return *((*int64)(p)), nil - case api.SQL_C_DOUBLE: - return *((*float64)(p)), nil - case api.SQL_C_CHAR: - return buf, nil - case api.SQL_C_WCHAR: - if p == nil { - return nil, nil - } - s := (*[1 << 20]uint16)(p)[:len(buf)/2] - return utf16toutf8(s), nil - case api.SQL_C_TYPE_TIMESTAMP: - t := (*api.SQL_TIMESTAMP_STRUCT)(p) - r := time.Date(int(t.Year), time.Month(t.Month), int(t.Day), - int(t.Hour), int(t.Minute), int(t.Second), int(t.Fraction), - time.Local) - return r, nil - case api.SQL_C_DATE: - t := (*api.SQL_DATE_STRUCT)(p) - r := time.Date(int(t.Year), time.Month(t.Month), int(t.Day), - 0, 0, 0, 0, time.Local) - return r, nil - case api.SQL_C_BINARY: - return buf, nil - } - return nil, fmt.Errorf("unsupported column ctype %d", c.CType) -} - -// BindableColumn allows access to columns that can have their buffers -// bound. Once bound at start, they are written to by odbc driver every -// time it fetches new row. This saves on syscall and, perhaps, some -// buffer copying. BindableColumn can be left unbound, then it behaves -// like NonBindableColumn when user reads data from it. -type BindableColumn struct { - *BaseColumn - IsBound bool - IsVariableWidth bool - Size int - Len BufferLen - Buffer []byte - smallBuf [8]byte // small inline memory buffer, so we do not need allocate external memory all the time -} - -func NewBindableColumn(b *BaseColumn, ctype api.SQLSMALLINT, bufSize int) *BindableColumn { - b.CType = ctype - c := &BindableColumn{BaseColumn: b, Size: bufSize} - if c.Size <= len(c.smallBuf) { - // use inline buffer - c.Buffer = c.smallBuf[:c.Size] - } else { - c.Buffer = make([]byte, c.Size) - } - return c -} - -func NewVariableWidthColumn(b *BaseColumn, ctype api.SQLSMALLINT, colWidth api.SQLULEN) Column { - if colWidth == 0 { - b.CType = ctype - return &NonBindableColumn{b} - } - l := int(colWidth) - switch ctype { - case api.SQL_C_WCHAR: - l += 1 // room for null-termination character - l *= 2 // wchars take 2 bytes each - case api.SQL_C_CHAR: - l += 1 // room for null-termination character - case api.SQL_C_BINARY: - // nothing to do - default: - panic(fmt.Errorf("do not know how wide column of ctype %d is", ctype)) - } - c := NewBindableColumn(b, ctype, l) - c.IsVariableWidth = true - return c -} - -func (c *BindableColumn) Bind(h api.SQLHSTMT, idx int) (bool, error) { - ret := c.Len.Bind(h, idx, c.CType, c.Buffer) - if IsError(ret) { - return false, NewError("SQLBindCol", h) - } - c.IsBound = true - return true, nil -} - -func (c *BindableColumn) Value(h api.SQLHSTMT, idx int) (driver.Value, error) { - if !c.IsBound { - ret := c.Len.GetData(h, idx, c.CType, c.Buffer) - if IsError(ret) { - return nil, NewError("SQLGetData", h) - } - } - if c.Len.IsNull() { - // is NULL - - return nil, nil - } - if !c.IsVariableWidth && int(c.Len) != c.Size { - panic(fmt.Errorf("wrong column #%d length %d returned, %d expected", idx, c.Len, c.Size)) - } - return c.BaseColumn.Value(c.Buffer[:c.Len]) -} - -// NonBindableColumn provide access to columns, that can't be bound. -// These are of character or binary type, and, usually, there is no -// limit for their width. -type NonBindableColumn struct { - *BaseColumn -} - -func (c *NonBindableColumn) Bind(h api.SQLHSTMT, idx int) (bool, error) { - return false, nil -} - -func (c *NonBindableColumn) Value(h api.SQLHSTMT, idx int) (driver.Value, error) { - var l BufferLen - var total []byte - b := make([]byte, 1024) -loop: - for { - ret := l.GetData(h, idx, c.CType, b) - switch ret { - case api.SQL_SUCCESS: - if l.IsNull() { - // is NULL - return nil, nil - } - total = append(total, b[:l]...) - break loop - case api.SQL_SUCCESS_WITH_INFO: - err := NewError("SQLGetData", h).(*Error) - if len(err.Diag) > 0 && err.Diag[0].State != "01004" { - return nil, err - } - i := len(b) - switch c.CType { - case api.SQL_C_WCHAR: - i -= 2 // remove wchar (2 bytes) null-termination character - case api.SQL_C_CHAR: - i-- // remove null-termination character - } - total = append(total, b[:i]...) - if l != api.SQL_NO_TOTAL { - // odbc gives us a hint about remaining data, - // lets get it in one go. - n := int(l) // total bytes for our data - n -= i // subtract already received - n += 2 // room for biggest (wchar) null-terminator - if len(b) < n { - b = make([]byte, n) - } - } - default: - return nil, NewError("SQLGetData", h) - } - } - return c.BaseColumn.Value(total) -} diff --git a/src/github.com/ibmdb/go_ibm_db/conn.go b/src/github.com/ibmdb/go_ibm_db/conn.go deleted file mode 100644 index ef4a2e3..0000000 --- a/src/github.com/ibmdb/go_ibm_db/conn.go +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package go_ibm_db - -import ( - "database/sql/driver" - "unsafe" - - "github.com/ibmdb/go_ibm_db/api" -) - -type Conn struct { - h api.SQLHDBC - tx *Tx -} - -func (d *Driver) Open(dsn string) (driver.Conn, error) { - var out api.SQLHANDLE - ret := api.SQLAllocHandle(api.SQL_HANDLE_DBC, api.SQLHANDLE(d.h), &out) - if IsError(ret) { - return nil, NewError("SQLAllocHandle", d.h) - } - h := api.SQLHDBC(out) - drv.Stats.updateHandleCount(api.SQL_HANDLE_DBC, 1) - - b := api.StringToUTF16(dsn) - ret = api.SQLDriverConnect(h, 0, - (*api.SQLWCHAR)(unsafe.Pointer(&b[0])), api.SQLSMALLINT(len(b)), - nil, 0, nil, api.SQL_DRIVER_NOPROMPT) - if IsError(ret) { - defer releaseHandle(h) - return nil, NewError("SQLDriverConnect", h) - } - return &Conn{h: h}, nil -} - -func (c *Conn) Close() error { - ret := api.SQLDisconnect(c.h) - if IsError(ret) { - return NewError("SQLDisconnect", c.h) - } - h := c.h - c.h = api.SQLHDBC(api.SQL_NULL_HDBC) - return releaseHandle(h) -} diff --git a/src/github.com/ibmdb/go_ibm_db/driver.go b/src/github.com/ibmdb/go_ibm_db/driver.go deleted file mode 100644 index 29304b1..0000000 --- a/src/github.com/ibmdb/go_ibm_db/driver.go +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package odbc implements database/sql driver to access data via odbc interface. -// -package go_ibm_db - -import ( - "database/sql" - - "github.com/ibmdb/go_ibm_db/api" -) - -var drv Driver - -type Driver struct { - Stats - h api.SQLHENV // environment handle -} - -func initDriver() error { - - //Allocate environment handle - var out api.SQLHANDLE - in := api.SQLHANDLE(api.SQL_NULL_HANDLE) - ret := api.SQLAllocHandle(api.SQL_HANDLE_ENV, in, &out) - if IsError(ret) { - return NewError("SQLAllocHandle", api.SQLHENV(in)) - } - drv.h = api.SQLHENV(out) - drv.Stats.updateHandleCount(api.SQL_HANDLE_ENV, 1) - - // will use ODBC v3 - ret = api.SQLSetEnvAttr(drv.h, api.SQL_ATTR_ODBC_VERSION, - api.SQLPOINTER(api.SQL_OV_ODBC3), 0) - if IsError(ret) { - defer releaseHandle(drv.h) - return NewError("SQLSetEnvAttr ODBC v3", drv.h) - } - - return nil -} - -func (d *Driver) Close() error { - // TODO(brainman): who will call (*Driver).Close (to dispose all opened handles)? - h := d.h - d.h = api.SQLHENV(api.SQL_NULL_HENV) - return releaseHandle(h) -} - -func init() { - err := initDriver() - if err != nil { - panic(err) - } - //go's to databse/sql/sql.go 43 line - sql.Register("go_ibm_db", &drv) - -} diff --git a/src/github.com/ibmdb/go_ibm_db/error.go b/src/github.com/ibmdb/go_ibm_db/error.go deleted file mode 100644 index 7c56133..0000000 --- a/src/github.com/ibmdb/go_ibm_db/error.go +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package go_ibm_db - -import ( - "github.com/ibmdb/go_ibm_db/api" - "database/sql/driver" - "fmt" - "strings" - "unsafe" -) - -func IsError(ret api.SQLRETURN) bool { - return !(ret == api.SQL_SUCCESS || ret == api.SQL_SUCCESS_WITH_INFO) -} - -type DiagRecord struct { - State string - NativeError int - Message string -} - -func (r *DiagRecord) String() string { - return fmt.Sprintf("{%s} %s", r.State, r.Message) -} - -type Error struct { - APIName string - Diag []DiagRecord -} - -func (e *Error) Error() string { - ss := make([]string, len(e.Diag)) - for i, r := range e.Diag { - ss[i] = r.String() - } - return e.APIName + ": " + strings.Join(ss, "\n") -} - -func NewError(apiName string, handle interface{}) error { - h, ht := ToHandleAndType(handle) - err := &Error{APIName: apiName} - var ne api.SQLINTEGER - state := make([]uint16, 6) - msg := make([]uint16, api.SQL_MAX_MESSAGE_LENGTH) - for i := 1; ; i++ { - ret := api.SQLGetDiagRec(ht, h, api.SQLSMALLINT(i), - (*api.SQLWCHAR)(unsafe.Pointer(&state[0])), &ne, - (*api.SQLWCHAR)(unsafe.Pointer(&msg[0])), - api.SQLSMALLINT(len(msg)), nil) - if ret == api.SQL_NO_DATA { - break - } - if IsError(ret) { - panic(fmt.Errorf("SQLGetDiagRec failed: ret=%d", ret)) - } - r := DiagRecord{ - State: api.UTF16ToString(state), - NativeError: int(ne), - Message: api.UTF16ToString(msg), - } - if strings.Contains(r.Message, "CLI0106E") || - strings.Contains(r.Message, "CLI0107E") || - strings.Contains(r.Message, "CLI0108E") { - return driver.ErrBadConn - } - err.Diag = append(err.Diag, r) - } - return err -} diff --git a/src/github.com/ibmdb/go_ibm_db/handle.go b/src/github.com/ibmdb/go_ibm_db/handle.go deleted file mode 100644 index d763491..0000000 --- a/src/github.com/ibmdb/go_ibm_db/handle.go +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package go_ibm_db - -import ( - "github.com/ibmdb/go_ibm_db/api" - "fmt" -) - -func ToHandleAndType(handle interface{}) (h api.SQLHANDLE, ht api.SQLSMALLINT) { - switch v := handle.(type) { - case api.SQLHENV: - if v == api.SQLHENV(api.SQL_NULL_HANDLE) { - ht = 0 - } else { - ht = api.SQL_HANDLE_ENV - } - h = api.SQLHANDLE(v) - case api.SQLHDBC: - ht = api.SQL_HANDLE_DBC - h = api.SQLHANDLE(v) - case api.SQLHSTMT: - ht = api.SQL_HANDLE_STMT - h = api.SQLHANDLE(v) - default: - panic(fmt.Errorf("unexpected handle type %T", v)) - } - return h, ht -} - -func releaseHandle(handle interface{}) error { - h, ht := ToHandleAndType(handle) - ret := api.SQLFreeHandle(ht, h) - if ret == api.SQL_INVALID_HANDLE { - return fmt.Errorf("SQLFreeHandle(%d, %d) returns SQL_INVALID_HANDLE", ht, h) - } - if IsError(ret) { - return NewError("SQLFreeHandle", handle) - } - drv.Stats.updateHandleCount(ht, -1) - return nil -} diff --git a/src/github.com/ibmdb/go_ibm_db/installer/setup.go b/src/github.com/ibmdb/go_ibm_db/installer/setup.go deleted file mode 100644 index 5453a37..0000000 --- a/src/github.com/ibmdb/go_ibm_db/installer/setup.go +++ /dev/null @@ -1,235 +0,0 @@ -package main - -import ( - "fmt" - "runtime" - "io" - "net/http" - "os" - "os/exec" - "archive/zip" - "archive/tar" - "compress/gzip" - "path/filepath" - "strings" -) -//func to Download -func DownloadFile(filepath string, url string) error { - out, err := os.Create(filepath) - if err != nil { - return err - } - defer out.Close() - resp, err := http.Get(url) - if err != nil { - return err - } - defer resp.Body.Close() - _, err = io.Copy(out, resp.Body) - if err != nil { - return err - } - return nil -} -//func to unzip -func Unzipping(sourcefile string) { - reader, err := zip.OpenReader(sourcefile) - if err != nil { - fmt.Println(err) - os.Exit(1) - } - defer reader.Close() - for _, f := range reader.Reader.File { - zipped, err := f.Open() - if err != nil { - fmt.Println(err) - os.Exit(1) - } - defer zipped.Close() - path := filepath.Join("./", f.Name) - if f.FileInfo().IsDir() { - os.MkdirAll(path, f.Mode()) - fmt.Println("Creating directory", path) - } else { - writer, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE, f.Mode()) - if err != nil { - fmt.Println(err) - os.Exit(1) - } - defer writer.Close() - if _, err = io.Copy(writer, zipped); err != nil { - fmt.Println(err) - os.Exit(1) - } - fmt.Println("Unzipping : ", path) - } - } -} -//Func to Untar -func Untaring(sourcefile string) { - file, err := os.Open(sourcefile) - if err != nil { - fmt.Println(err) - os.Exit(1) - } - defer file.Close() - var fileReader io.ReadCloser = file - if strings.HasSuffix(sourcefile, ".gz") { - if fileReader, err = gzip.NewReader(file); err != nil { - fmt.Println(err) - os.Exit(1) - } - defer fileReader.Close() - } - tarBallReader := tar.NewReader(fileReader) - for { - header, err := tarBallReader.Next() - if err != nil { - if err == io.EOF { - break - } - fmt.Println(err) - os.Exit(1) - } - filename := header.Name - switch header.Typeflag { - case tar.TypeDir: - fmt.Println("Creating directory :", filename) - err = os.MkdirAll(filename, os.FileMode(header.Mode)) - if err != nil { - fmt.Println(err) - os.Exit(1) - } - case tar.TypeReg: - fmt.Println("Untarring :", filename) - writer, err := os.Create(filename) - if err != nil { - fmt.Println(err) - os.Exit(1) - } - io.Copy(writer, tarBallReader) - err = os.Chmod(filename, os.FileMode(header.Mode)) - if err != nil { - fmt.Println(err) - os.Exit(1) - } - writer.Close() - default: - fmt.Printf("Unable to untar type : %c in file %s", header.Typeflag, filename) - } - } -} - -func linux_untar(clidriver string){ - out, _:= exec.Command("tar","xvzf",clidriver).Output() -fmt.Println(string(out[:])) -} - - -func main() { - var cliFileName string - var url string - i:=0 - _,a :=os.LookupEnv("IBM_DB_DIR") - _,b :=os.LookupEnv("IBM_DB_HOME") - _,c :=os.LookupEnv("IBM_DB_LIB") - if(!(a && b && c)){ - if runtime.GOOS == "aix" { - i=2 - const wordsize = 32 << (^uint(0) >> 32 & 1) - if wordsize==64 { - cliFileName = "aix64_odbc_cli.tar.gz" - } else { - cliFileName = "aix32_odbc_cli.tar.gz" - } - fmt.Printf("aix\n") - fmt.Printf(cliFileName) - }else if runtime.GOOS == "linux"{ - i=2 - if runtime.GOARCH == "ppc64le" { - const wordsize = 32 << (^uint(0) >> 32 & 1) - if wordsize==64{ - cliFileName= "ppc64le_odbc_cli.tar.gz" - } - }else if runtime.GOARCH == "ppc" { - const wordsize = 32 << (^uint(0) >> 32 & 1) - if wordsize==64{ - cliFileName="ppc64_odbc_cli.tar.gz" - }else{ - cliFileName="ppc32_odbc_cli.tar.gz" - } - }else if runtime.GOARCH == "amd64" { - const wordsize = 32 << (^uint(0) >> 32 & 1) - if wordsize==64{ - cliFileName="linuxx64_odbc_cli.tar.gz" - }else{ - cliFileName="linuxia32_odbc_cli.tar.gz" - } - }else if runtime.GOARCH == "390" { - const wordsize = 32 << (^uint(0) >> 32 & 1) - if wordsize==64{ - cliFileName="s390x64_odbc_cli.tar.gz" - }else{ - cliFileName="s390_odbc_cli.tar.gz" - } - } - fmt.Printf("linux\n") - fmt.Printf(cliFileName) - }else if runtime.GOOS=="windows"{ - i=1 - const wordsize = 32 << (^uint(0) >> 32 & 1) - if wordsize==64 { - cliFileName = "ntx64_odbc_cli.zip" - } else { - cliFileName = "nt32_odbc_cli.zip" - } - fmt.Printf("windows\n") - fmt.Printf(cliFileName) - }else if runtime.GOOS=="darwin"{ - const wordsize = 32 << (^uint(0) >> 32 & 1) - if wordsize==64 { - cliFileName = "macos64_odbc_cli.tar.gz" - } - fmt.Printf("darwin\n") - fmt.Printf(cliFileName) - }else if runtime.GOOS =="sunos"{ - i=2 - if runtime.GOARCH == "i86pc"{ - const wordsize = 32 << (^uint(0) >> 32 & 1) - if wordsize==64 { - cliFileName = "sunamd64_odbc_cli.tar.gz" - }else{ - cliFileName = "sunamd32_odbc_cli.tar.gz" - } - }else if runtime.GOARCH == "SUNW"{ - const wordsize = 32 << (^uint(0) >> 32 & 1) - if wordsize==64 { - cliFileName = "sun64_odbc_cli.tar.gz" - }else{ - cliFileName = "sun32_odbc_cli.tar.gz" - } - } - fmt.Printf("Sunos\n") - fmt.Printf(cliFileName) - }else{ - fmt.Println("not a known platform") - } - fileUrl:= "https://public.dhe.ibm.com/ibmdl/export/pub/software/data/db2/drivers/odbc_cli/" + cliFileName - fmt.Println(url) - fmt.Println("Downloading...") - err:=DownloadFile(cliFileName,fileUrl) - if err!=nil{ - fmt.Println(err) - }else{ - fmt.Println("download successful") - } - if(i == 1){ - Unzipping(cliFileName) - }else if(i==2){ - linux_untar(cliFileName) - - }else { - Untaring(cliFileName) - } - } -} \ No newline at end of file diff --git a/src/github.com/ibmdb/go_ibm_db/odbcstmt.go b/src/github.com/ibmdb/go_ibm_db/odbcstmt.go deleted file mode 100644 index f75e26d..0000000 --- a/src/github.com/ibmdb/go_ibm_db/odbcstmt.go +++ /dev/null @@ -1,157 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package go_ibm_db - -import ( - "database/sql/driver" - "errors" - "fmt" - "sync" - "time" - "unsafe" - - "github.com/ibmdb/go_ibm_db/api" -) - -// TODO(brainman): see if I could use SQLExecDirect anywhere - -type ODBCStmt struct { - h api.SQLHSTMT - Parameters []Parameter - Cols []Column - // locking/lifetime - mu sync.Mutex - usedByStmt bool - usedByRows bool -} - -func (c *Conn) PrepareODBCStmt(query string) (*ODBCStmt, error) { - var out api.SQLHANDLE - ret := api.SQLAllocHandle(api.SQL_HANDLE_STMT, api.SQLHANDLE(c.h), &out) - if IsError(ret) { - return nil, NewError("SQLAllocHandle", c.h) - } - h := api.SQLHSTMT(out) - drv.Stats.updateHandleCount(api.SQL_HANDLE_STMT, 1) - - b := api.StringToUTF16(query) - ret = api.SQLPrepare(h, - (*api.SQLWCHAR)(unsafe.Pointer(&b[0])), api.SQLINTEGER(len(b))) - if IsError(ret) { - defer releaseHandle(h) - return nil, NewError("SQLPrepare", h) - } - ps, err := ExtractParameters(h) - if err != nil { - defer releaseHandle(h) - return nil, err - } - return &ODBCStmt{ - h: h, - Parameters: ps, - usedByStmt: true, - }, nil -} - -func (s *ODBCStmt) closeByStmt() error { - s.mu.Lock() - defer s.mu.Unlock() - if s.usedByStmt { - defer func() { s.usedByStmt = false }() - if !s.usedByRows { - return s.releaseHandle() - } - } - return nil -} - -func (s *ODBCStmt) closeByRows() error { - s.mu.Lock() - defer s.mu.Unlock() - if s.usedByRows { - defer func() { s.usedByRows = false }() - if s.usedByStmt { - ret := api.SQLCloseCursor(s.h) - if IsError(ret) { - return NewError("SQLCloseCursor", s.h) - } - return nil - } else { - return s.releaseHandle() - } - } - return nil -} - -func (s *ODBCStmt) releaseHandle() error { - h := s.h - s.h = api.SQLHSTMT(api.SQL_NULL_HSTMT) - return releaseHandle(h) -} - -var testingIssue5 bool // used during tests - -func (s *ODBCStmt) Exec(args []driver.Value) error { - - if len(args) != len(s.Parameters) { - return fmt.Errorf("wrong number of arguments %d, %d expected", len(args), len(s.Parameters)) - } - for i, a := range args { - // this could be done in 2 steps: - // 1) bind vars right after prepare; - // 2) set their (vars) values here; - // but rebinding parameters for every new parameter value - // should be efficient enough for our purpose. - s.Parameters[i].BindValue(s.h, i, a) - } - if testingIssue5 { - time.Sleep(10 * time.Microsecond) - } - ret := api.SQLExecute(s.h) - if ret == api.SQL_NO_DATA { - // success but no data to report - return nil - } - if IsError(ret) { - return NewError("SQLExecute", s.h) - } - return nil -} - -func (s *ODBCStmt) BindColumns() error { - // count columns - var n api.SQLSMALLINT - ret := api.SQLNumResultCols(s.h, &n) - if IsError(ret) { - return NewError("SQLNumResultCols", s.h) - } - if n < 1 { - return errors.New("Stmt did not create a result set") - } - // fetch column descriptions - s.Cols = make([]Column, n) - binding := true - for i := range s.Cols { - c, err := NewColumn(s.h, i) - if err != nil { - return err - } - s.Cols[i] = c - // Once we found one non-bindable column, we will not bind the rest. - // http://www.easysoft.com/developer/languages/c/odbc-tutorial-fetching-results.html - // ... One common restriction is that SQLGetData may only be called on columns after the last bound column. ... - if !binding { - continue - } - bound, err := s.Cols[i].Bind(s.h, i) - if err != nil { - return err - } - if !bound { - binding = false - } - } - return nil -} diff --git a/src/github.com/ibmdb/go_ibm_db/param.go b/src/github.com/ibmdb/go_ibm_db/param.go deleted file mode 100644 index e1c23f8..0000000 --- a/src/github.com/ibmdb/go_ibm_db/param.go +++ /dev/null @@ -1,165 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package go_ibm_db - -import ( - "github.com/ibmdb/go_ibm_db/api" - "database/sql/driver" - "fmt" - "time" - "unsafe" -) - -type Parameter struct { - SQLType api.SQLSMALLINT - Decimal api.SQLSMALLINT - Size api.SQLULEN - isDescribed bool - // Following fields store data used later by SQLExecute. - // The fields keep data alive and away from gc. - Data interface{} - StrLen_or_IndPtr api.SQLLEN -} - -// StoreStrLen_or_IndPtr stores v into StrLen_or_IndPtr field of p -// and returns address of that field. -func (p *Parameter) StoreStrLen_or_IndPtr(v api.SQLLEN) *api.SQLLEN { - p.StrLen_or_IndPtr = v - return &p.StrLen_or_IndPtr - -} - -func (p *Parameter) BindValue(h api.SQLHSTMT, idx int, v driver.Value) error { - // TODO(brainman): Reuse memory for previously bound values. If memory - // is reused, we, probably, do not need to call SQLBindParameter either. - var ctype, sqltype, decimal api.SQLSMALLINT - var size api.SQLULEN - var buflen api.SQLLEN - var plen *api.SQLLEN - var buf unsafe.Pointer - switch d := v.(type) { - case nil: - ctype = api.SQL_C_WCHAR - p.Data = nil - buf = nil - size = 1 - buflen = 0 - plen = p.StoreStrLen_or_IndPtr(api.SQL_NULL_DATA) - sqltype = api.SQL_WCHAR - case string: - ctype = api.SQL_C_WCHAR - b := api.StringToUTF16(d) - p.Data = b - buf = unsafe.Pointer(&b[0]) - l := len(b) - l -= 1 // remove terminating 0 - size = api.SQLULEN(l) - if size < 1 { - // size cannot be less then 1 even for empty fields - size = 1 - } - l *= 2 // every char takes 2 bytes - buflen = api.SQLLEN(l) - plen = p.StoreStrLen_or_IndPtr(buflen) - if p.isDescribed { - // only so we can handle very long (>4000 chars) parameters - sqltype = p.SQLType - } else { - sqltype = api.SQL_WCHAR - } - case int64: - ctype = api.SQL_C_SBIGINT - p.Data = &d - buf = unsafe.Pointer(&d) - sqltype = api.SQL_BIGINT - size = 8 - case bool: - var b byte - if d { - b = 1 - } - ctype = api.SQL_C_BIT - p.Data = &b - buf = unsafe.Pointer(&b) - sqltype = api.SQL_BIT - size = 1 - case float64: - ctype = api.SQL_C_DOUBLE - p.Data = &d - buf = unsafe.Pointer(&d) - sqltype = api.SQL_DOUBLE - size = 8 - case time.Time: - ctype = api.SQL_C_TYPE_TIMESTAMP - y, m, day := d.Date() - b := api.SQL_TIMESTAMP_STRUCT{ - Year: api.SQLSMALLINT(y), - Month: api.SQLUSMALLINT(m), - Day: api.SQLUSMALLINT(day), - Hour: api.SQLUSMALLINT(d.Hour()), - Minute: api.SQLUSMALLINT(d.Minute()), - Second: api.SQLUSMALLINT(d.Second()), - Fraction: api.SQLUINTEGER(d.Nanosecond()), - } - p.Data = &b - buf = unsafe.Pointer(&b) - sqltype = api.SQL_TYPE_TIMESTAMP - if p.isDescribed && p.SQLType == api.SQL_TYPE_TIMESTAMP { - decimal = p.Decimal - } - if decimal <= 0 { - // represented as yyyy-mm-dd hh:mm:ss.fff format in ms sql server - decimal = 3 - } - size = 20 + api.SQLULEN(decimal) - case []byte: - ctype = api.SQL_C_BINARY - b := make([]byte, len(d)) - copy(b, d) - p.Data = b - buf = unsafe.Pointer(&b[0]) - buflen = api.SQLLEN(len(b)) - plen = p.StoreStrLen_or_IndPtr(buflen) - size = api.SQLULEN(len(b)) - sqltype = api.SQL_BINARY - default: - panic(fmt.Errorf("unsupported type %T", v)) - } - ret := api.SQLBindParameter(h, api.SQLUSMALLINT(idx+1), - api.SQL_PARAM_INPUT, ctype, sqltype, size, decimal, - api.SQLPOINTER(buf), buflen, plen) - if IsError(ret) { - return NewError("SQLBindParameter", h) - } - return nil -} - -func ExtractParameters(h api.SQLHSTMT) ([]Parameter, error) { - // count parameters - var n, nullable api.SQLSMALLINT - ret := api.SQLNumParams(h, &n) - if IsError(ret) { - return nil, NewError("SQLNumParams", h) - } - if n <= 0 { - // no parameters - return nil, nil - } - ps := make([]Parameter, n) - // fetch param descriptions - for i := range ps { - p := &ps[i] - ret = api.SQLDescribeParam(h, api.SQLUSMALLINT(i+1), - &p.SQLType, &p.Size, &p.Decimal, &nullable) - if IsError(ret) { - // SQLDescribeParam is not implemented by freedts, - // it even fails for some statements on windows. - // Will try request without these descriptions - continue - } - p.isDescribed = true - } - return ps, nil -} diff --git a/src/github.com/ibmdb/go_ibm_db/pooling.go b/src/github.com/ibmdb/go_ibm_db/pooling.go deleted file mode 100644 index f1e62f1..0000000 --- a/src/github.com/ibmdb/go_ibm_db/pooling.go +++ /dev/null @@ -1,205 +0,0 @@ -package go_ibm_db - -import ( - "database/sql" - "fmt" - "time" - "strconv" - "strings" -) - -type DBP struct{ -sql.DB -con string -n time.Duration -} - -type Pool struct{ -availablePool map[string] []*DBP -usedPool map[string] []*DBP -PoolSize int -} - -var b *Pool -var ConnMaxLifetime,PoolSize int - -//Pconnect will return the pool instance -func Pconnect(PoolSize string) (*Pool){ - var Size int - count:=len(PoolSize) - if count>0{ - opt:=strings.Split(PoolSize,"=") - if(opt[0] == "PoolSize"){ - Size,_=strconv.Atoi(opt[1]) - }else{ - fmt.Println("Not a valid parameter") - } - } else { - Size=100 - } - p:=&Pool{ - availablePool: make(map[string] []*DBP), - usedPool : make(map[string] []*DBP), - PoolSize : Size, - } - b=p - - return p -} - -var Psize int - -//Open will check for the connection in the pool -//If not opens a new connection and stores in the pool - -func (p *Pool) Open(Connstr string,options ...string)(*DBP){ - var Time time.Duration - count := len(options) - if count>0{ - for i:=0;i 1){ - dbpo:=val[0] - copy(val[0:],val[1:]) - val[len(val)-1]=nil - val=val[:len(val)-1] - p.availablePool[Connstr]=val - p.usedPool[Connstr]=append(p.usedPool[Connstr],dbpo) - dbpo.SetConnMaxLifetime(Time) - return dbpo - }else{ - dbpo:=val[0] - p.usedPool[Connstr]=append(p.usedPool[Connstr],dbpo) - delete(p.availablePool,Connstr) - dbpo.SetConnMaxLifetime(Time) - return dbpo - } - }else{ - db,err:=sql.Open("go_ibm_db",Connstr) - if err != nil{ - return nil - } - dbi:=&DBP{ - DB :*db, - con :Connstr, - n :Time, - } - p.usedPool[Connstr]=append(p.usedPool[Connstr],dbi) - dbi.SetConnMaxLifetime(Time) - return dbi - } - } else { - db,err:=sql.Open("go_ibm_db",Connstr) - if err != nil{ - return nil - } - dbi:=&DBP{ - DB :*db, - con :Connstr, - } - return dbi - } -} - -//Close will make the connection available for the next release - -func (d *DBP) Close(){ - Psize=Psize-1 - var pos int - i:=-1 - if valc,okc:=b.usedPool[d.con];okc{ - if(len(valc) > 1){ - for _,b:=range valc{ - i=i+1 - if b == d{ - pos = i - } - } - dbpc:=valc[pos] - copy(valc[pos:], valc[pos+1:]) - valc[len(valc)-1] = nil - valc = valc[:len(valc)-1] - b.usedPool[d.con]=valc - b.availablePool[d.con]=append(b.availablePool[d.con],dbpc) - } else { - dbpc := valc[0] - b.availablePool[d.con]=append(b.availablePool[d.con],dbpc) - delete(b.usedPool,d.con) - } - go d.Timeout() - } else { - d.DB.Close() - } -} - -//Timeout for closing the connection in pool - -func (d *DBP) Timeout(){ - var pos int - i:=-1 - select { - case <-time.After(d.n): - if valt,okt:=b.availablePool[d.con];okt{ - if(len(valt) > 1){ - for _,b:=range valt{ - i=i+1 - if b == d{ - pos = i - } - } - dbpt:=valt[pos] - copy(valt[pos:], valt[pos+1:]) - valt[len(valt)-1] = nil - valt = valt[:len(valt)-1] - b.availablePool[d.con]=valt - dbpt.DB.Close() - }else{ - dbpt:=valt[0] - dbpt.DB.Close() - delete(b.availablePool,d.con) - } - } - } -} - -//Release will close all the connections in the pool - -func (p *Pool) Release(){ - if(p.availablePool != nil){ - for _,vala := range p.availablePool{ - for _,dbpr := range vala{ - dbpr.DB.Close() - } - } - p.availablePool=nil - } - if(p.usedPool != nil){ - for _,valu := range p.usedPool{ - for _,dbpr := range valu{ - dbpr.DB.Close() - } - } - p.usedPool=nil - } -} - -// Display will print the values in the map - -func (p *Pool) Display(){ - fmt.Println(p.availablePool) - fmt.Println(p.usedPool) - fmt.Println(p.PoolSize) -} diff --git a/src/github.com/ibmdb/go_ibm_db/result.go b/src/github.com/ibmdb/go_ibm_db/result.go deleted file mode 100644 index 35bbd99..0000000 --- a/src/github.com/ibmdb/go_ibm_db/result.go +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package go_ibm_db - -import ( - "errors" -) - -type Result struct { - rowCount int64 -} - -func (r *Result) LastInsertId() (int64, error) { - // TODO(brainman): implement (*Resilt).LastInsertId - return 0, errors.New("not implemented") -} - -func (r *Result) RowsAffected() (int64, error) { - return r.rowCount, nil -} diff --git a/src/github.com/ibmdb/go_ibm_db/rows.go b/src/github.com/ibmdb/go_ibm_db/rows.go deleted file mode 100644 index fb8859a..0000000 --- a/src/github.com/ibmdb/go_ibm_db/rows.go +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package go_ibm_db - -import ( - "github.com/ibmdb/go_ibm_db/api" - "database/sql/driver" - "io" -) - -type Rows struct { - os *ODBCStmt -} - -func (r *Rows) Columns() []string { - names := make([]string, len(r.os.Cols)) - for i := 0; i < len(names); i++ { - names[i] = r.os.Cols[i].Name() - } - return names -} - -func (r *Rows) Next(dest []driver.Value) error { - ret := api.SQLFetch(r.os.h) - if ret == api.SQL_NO_DATA { - return io.EOF - } - if IsError(ret) { - return NewError("SQLFetch", r.os.h) - } - for i := range dest { - v, err := r.os.Cols[i].Value(r.os.h, i) - if err != nil { - return err - } - dest[i] = v - } - return nil -} - -func (r *Rows) Close() error { - return r.os.closeByRows() -} diff --git a/src/github.com/ibmdb/go_ibm_db/stats.go b/src/github.com/ibmdb/go_ibm_db/stats.go deleted file mode 100644 index c3c4d27..0000000 --- a/src/github.com/ibmdb/go_ibm_db/stats.go +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package go_ibm_db - -import ( - "github.com/ibmdb/go_ibm_db/api" - "fmt" - "sync" -) - -type Stats struct { - EnvCount int - ConnCount int - StmtCount int - mu sync.Mutex -} - -func (s *Stats) updateHandleCount(handleType api.SQLSMALLINT, change int) { - s.mu.Lock() - defer s.mu.Unlock() - switch handleType { - case api.SQL_HANDLE_ENV: - s.EnvCount += change - case api.SQL_HANDLE_DBC: - s.ConnCount += change - case api.SQL_HANDLE_STMT: - s.StmtCount += change - default: - panic(fmt.Errorf("unexpected handle type %d", handleType)) - } -} diff --git a/src/github.com/ibmdb/go_ibm_db/stmt.go b/src/github.com/ibmdb/go_ibm_db/stmt.go deleted file mode 100644 index 4e9dc0f..0000000 --- a/src/github.com/ibmdb/go_ibm_db/stmt.go +++ /dev/null @@ -1,99 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package go_ibm_db - -import ( - "database/sql/driver" - "errors" - "sync" - - "github.com/ibmdb/go_ibm_db/api" -) - -type Stmt struct { - c *Conn - query string - os *ODBCStmt - mu sync.Mutex -} - -func (c *Conn) Prepare(query string) (driver.Stmt, error) { - os, err := c.PrepareODBCStmt(query) - if err != nil { - return nil, err - } - return &Stmt{c: c, os: os, query: query}, nil -} - -func (s *Stmt) NumInput() int { - if s.os == nil { - return -1 - } - return len(s.os.Parameters) -} - -func (s *Stmt) Close() error { - if s.os == nil { - return errors.New("Stmt is already closed") - } - ret := s.os.closeByStmt() - s.os = nil - return ret -} - -func (s *Stmt) Exec(args []driver.Value) (driver.Result, error) { - if s.os == nil { - return nil, errors.New("Stmt is closed") - } - - s.mu.Lock() - defer s.mu.Unlock() - if s.os.usedByRows { - s.os.closeByStmt() - s.os = nil - os, err := s.c.PrepareODBCStmt(s.query) - if err != nil { - return nil, err - } - s.os = os - } - err := s.os.Exec(args) - if err != nil { - return nil, err - } - var c api.SQLLEN - ret := api.SQLRowCount(s.os.h, &c) - if IsError(ret) { - return nil, NewError("SQLRowCount", s.os.h) - } - return &Result{rowCount: int64(c)}, nil -} - -func (s *Stmt) Query(args []driver.Value) (driver.Rows, error) { - if s.os == nil { - return nil, errors.New("Stmt is closed") - } - s.mu.Lock() - defer s.mu.Unlock() - if s.os.usedByRows { - s.os.closeByStmt() - s.os = nil - os, err := s.c.PrepareODBCStmt(s.query) - if err != nil { - return nil, err - } - s.os = os - } - err := s.os.Exec(args) - if err != nil { - return nil, err - } - err = s.os.BindColumns() - if err != nil { - return nil, err - } - s.os.usedByRows = true // now both Stmt and Rows refer to it - return &Rows{os: s.os}, nil -} diff --git a/src/github.com/ibmdb/go_ibm_db/testdata/begin_test.go b/src/github.com/ibmdb/go_ibm_db/testdata/begin_test.go deleted file mode 100644 index 075dc99..0000000 --- a/src/github.com/ibmdb/go_ibm_db/testdata/begin_test.go +++ /dev/null @@ -1,9 +0,0 @@ -package main - -import "testing" - -func TestBegin(t *testing.T){ - if(Begin() != nil){ - t.Error("table not displayed") -} -} \ No newline at end of file diff --git a/src/github.com/ibmdb/go_ibm_db/testdata/close_test.go b/src/github.com/ibmdb/go_ibm_db/testdata/close_test.go deleted file mode 100644 index 8ebb1ab..0000000 --- a/src/github.com/ibmdb/go_ibm_db/testdata/close_test.go +++ /dev/null @@ -1,9 +0,0 @@ -package main - -import "testing" - -func TestClose(t *testing.T){ - if(Close() != nil){ - t.Error("Error in Scanning Query") -} -} \ No newline at end of file diff --git a/src/github.com/ibmdb/go_ibm_db/testdata/columns_test.go b/src/github.com/ibmdb/go_ibm_db/testdata/columns_test.go deleted file mode 100644 index 1c195ac..0000000 --- a/src/github.com/ibmdb/go_ibm_db/testdata/columns_test.go +++ /dev/null @@ -1,9 +0,0 @@ -package main - -import "testing" - -func TestColumns(t *testing.T){ - if(Columns() != nil){ - t.Error("Error in displaying Query") -} -} \ No newline at end of file diff --git a/src/github.com/ibmdb/go_ibm_db/testdata/commit_test.go b/src/github.com/ibmdb/go_ibm_db/testdata/commit_test.go deleted file mode 100644 index a0c425c..0000000 --- a/src/github.com/ibmdb/go_ibm_db/testdata/commit_test.go +++ /dev/null @@ -1,9 +0,0 @@ -package main - -import "testing" - -func TestCommit(t *testing.T){ - if(Commit() != nil){ - t.Error("Error in commit query") -} -} \ No newline at end of file diff --git a/src/github.com/ibmdb/go_ibm_db/testdata/conn_test.go b/src/github.com/ibmdb/go_ibm_db/testdata/conn_test.go deleted file mode 100644 index ce8a04b..0000000 --- a/src/github.com/ibmdb/go_ibm_db/testdata/conn_test.go +++ /dev/null @@ -1,9 +0,0 @@ -package main - -import "testing" - -func TestCreateconnection(t *testing.T){ - if(Createconnection() == nil){ - t.Error("connection not formed") -} -} \ No newline at end of file diff --git a/src/github.com/ibmdb/go_ibm_db/testdata/create_test.go b/src/github.com/ibmdb/go_ibm_db/testdata/create_test.go deleted file mode 100644 index 03064fb..0000000 --- a/src/github.com/ibmdb/go_ibm_db/testdata/create_test.go +++ /dev/null @@ -1,9 +0,0 @@ -package main - -import "testing" - -func TestCreatetable(t *testing.T){ - if(Createtable() != nil){ - t.Error("table not formed") -} -} \ No newline at end of file diff --git a/src/github.com/ibmdb/go_ibm_db/testdata/drop_test.go b/src/github.com/ibmdb/go_ibm_db/testdata/drop_test.go deleted file mode 100644 index cfed09d..0000000 --- a/src/github.com/ibmdb/go_ibm_db/testdata/drop_test.go +++ /dev/null @@ -1,9 +0,0 @@ -package main - -import "testing" - -func TestDrop(t *testing.T){ - if(Drop() != nil){ - t.Error("table not dropped") -} -} \ No newline at end of file diff --git a/src/github.com/ibmdb/go_ibm_db/testdata/insert_test.go b/src/github.com/ibmdb/go_ibm_db/testdata/insert_test.go deleted file mode 100644 index 542021c..0000000 --- a/src/github.com/ibmdb/go_ibm_db/testdata/insert_test.go +++ /dev/null @@ -1,9 +0,0 @@ -package main - -import "testing" - -func TestInsert(t *testing.T){ - if(Insert() != nil){ - t.Error("table not formed") -} -} \ No newline at end of file diff --git a/src/github.com/ibmdb/go_ibm_db/testdata/main.go b/src/github.com/ibmdb/go_ibm_db/testdata/main.go deleted file mode 100644 index ffe201e..0000000 --- a/src/github.com/ibmdb/go_ibm_db/testdata/main.go +++ /dev/null @@ -1,250 +0,0 @@ -package main - -import ( - "fmt" - a "github.com/ibmdb/go_ibm_db" - "database/sql" - ) - -var con ="HOSTNAME=host;PORT=number;DATABASE=name;UID=username;PWD=password" - -func Createconnection()(db *sql.DB){ - db,_=sql.Open("go_ibm_db",con) - return db - } - - -func Createtable( ) error{ - db, err:=sql.Open("go_ibm_db", con) - db.Exec("DROP table rocket") - _,err=db.Exec("create table rocket(a int)") - _,err=db.Exec("create table rocket1(a int)") - if err != nil{ - return err - } - return nil -} -func Insert() error{ - db,err:=sql.Open("go_ibm_db",con) - _,err =db.Exec("insert into rocket values(1)") - if err != nil{ - return err - } - return nil -} - -func Drop() error{ - db,err:=sql.Open("go_ibm_db",con) - _,err =db.Exec("drop table rocket1") - if err != nil{ - return err - } - return nil -} - -func Prepare() error{ -db,_:=sql.Open("go_ibm_db",con) -_,err:=db.Prepare("select * from rocket") -if err!=nil{ -return err -} -return nil -} - -func Query() error{ -db,_:=sql.Open("go_ibm_db",con) -st,_:=db.Prepare("select * from rocket") -_,err:=st.Query() -if err != nil{ -return err -} -return nil -} - -func Scan() error{ -db,_:=sql.Open("go_ibm_db",con) -st,_:=db.Prepare("select * from rocket") -rows,err:=st.Query() -for rows.Next(){ -var a string -err = rows.Scan(&a) -if err != nil{ -return err -} -} -return nil -} - -func Next() error{ -db,_:=sql.Open("go_ibm_db",con) -st,_:=db.Prepare("select * from rocket") -rows,err:=st.Query() -for rows.Next(){ -var a string -err = rows.Scan(&a) -if err != nil{ -return err -} -} -return nil -} - -func Columns() error{ -db,_:=sql.Open("go_ibm_db",con) -st,_:=db.Prepare("select * from rocket") -rows,_:=st.Query() -_,err := rows.Columns() -if err != nil{ -return err -} -for rows.Next(){ -var a string -_ = rows.Scan(&a) -} -return nil -} - - - -func Queryrow() error{ -a:=1 -var uname int -db,err:=sql.Open("go_ibm_db",con) -err=db.QueryRow("select a from rocket where a=?",a).Scan(&uname) -if err != nil{ -return err -} -return nil -} - -func Begin() error{ -db,err:=sql.Open("go_ibm_db",con) -_,err=db.Begin() -if err != nil{ -return err -} -return nil -} - -func Commit() error{ - db,err:=sql.Open("go_ibm_db",con) - bg,err:=db.Begin() - db.Exec("DROP table u") - _,err=bg.Exec("create table u(id int)") - err=bg.Commit() - if err!=nil{ - return err - } - return nil -} - -func Close()(error){ - db,_:=sql.Open("go_ibm_db",con) - err:=db.Close() - if err!=nil{ - return err - } - return nil - } - -func PoolOpen() (int){ - pool:=a.Pconnect("PoolSize=50") - db:=pool.Open(con) - if(db == nil){ - return 0 - }else { - return 1 - } -} - -func main(){ -result:=Createconnection() -if(result != nil){ -fmt.Println("Pass") -} else { -fmt.Println("fail") -} - -result1:=Createtable() -if(result1 == nil){ -fmt.Println("Pass") -} else { -fmt.Println("fail") -} - -result2:=Insert() -if(result2 == nil){ -fmt.Println("Pass") -} else { -fmt.Println("fail") -} -result3:=Drop() -if(result3 == nil){ -fmt.Println("Pass") -} else { -fmt.Println("fail") -} -result4:=Prepare() -if(result4 == nil){ -fmt.Println("Pass") -} else { -fmt.Println("fail") -} -result5:=Query() -if(result5 == nil){ -fmt.Println("Pass") -} else { -fmt.Println("fail") -} - -result6:=Scan() -if(result6 == nil){ -fmt.Println("Pass") -} else { -fmt.Println("fail") -} -result7:=Next() -if(result7 == nil){ -fmt.Println("Pass") -} else { -fmt.Println("fail") -} - -result8:=Columns() -if(result8 == nil){ -fmt.Println("Pass") -} else { -fmt.Println("fail") -} - -result9:=Queryrow() -if(result9 == nil){ -fmt.Println("Pass") -} else { -fmt.Println("fail") -} -result10:=Begin() -if(result10== nil){ -fmt.Println("Pass") -} else { -fmt.Println("fail") -} -result11:=Commit() -if(result11 == nil){ -fmt.Println("Pass") -} else { -fmt.Println("fail") -} -result12:=Close() -if(result12 == nil){ -fmt.Println("Pass") -} else { -fmt.Println("fail") -} -result13:=PoolOpen() -if(result13 ==1){ -fmt.Println("Pass") -} else { -fmt.Println("fail") -} -} \ No newline at end of file diff --git a/src/github.com/ibmdb/go_ibm_db/testdata/next_test.go b/src/github.com/ibmdb/go_ibm_db/testdata/next_test.go deleted file mode 100644 index b3fb56f..0000000 --- a/src/github.com/ibmdb/go_ibm_db/testdata/next_test.go +++ /dev/null @@ -1,9 +0,0 @@ -package main - -import "testing" - -func TestNext(t *testing.T){ - if(Next() != nil){ - t.Error("Error in Scanning Query") -} -} \ No newline at end of file diff --git a/src/github.com/ibmdb/go_ibm_db/testdata/poolopen_test.go b/src/github.com/ibmdb/go_ibm_db/testdata/poolopen_test.go deleted file mode 100644 index dc7a658..0000000 --- a/src/github.com/ibmdb/go_ibm_db/testdata/poolopen_test.go +++ /dev/null @@ -1,10 +0,0 @@ -package main - -import ( - "testing" -) -func TestPoolOpen(t *testing.T){ - if(PoolOpen() == 0){ - t.Error("pool connection not opened") - } -} \ No newline at end of file diff --git a/src/github.com/ibmdb/go_ibm_db/testdata/prepare_test.go b/src/github.com/ibmdb/go_ibm_db/testdata/prepare_test.go deleted file mode 100644 index a65d5c3..0000000 --- a/src/github.com/ibmdb/go_ibm_db/testdata/prepare_test.go +++ /dev/null @@ -1,9 +0,0 @@ -package main - -import "testing" - -func TestPrepare(t *testing.T){ - if(Prepare() != nil){ - t.Error("Error in preparing Query") -} -} \ No newline at end of file diff --git a/src/github.com/ibmdb/go_ibm_db/testdata/query_test.go b/src/github.com/ibmdb/go_ibm_db/testdata/query_test.go deleted file mode 100644 index 906bff0..0000000 --- a/src/github.com/ibmdb/go_ibm_db/testdata/query_test.go +++ /dev/null @@ -1,9 +0,0 @@ -package main - -import "testing" - -func TestQuery(t *testing.T){ - if(Query() != nil){ - t.Error("table not displayed") -} -} \ No newline at end of file diff --git a/src/github.com/ibmdb/go_ibm_db/testdata/queryrow_test.go b/src/github.com/ibmdb/go_ibm_db/testdata/queryrow_test.go deleted file mode 100644 index 3472d9f..0000000 --- a/src/github.com/ibmdb/go_ibm_db/testdata/queryrow_test.go +++ /dev/null @@ -1,9 +0,0 @@ -package main - -import "testing" - -func TestQueryrow(t *testing.T){ - if(Queryrow() != nil){ - t.Error("values not displayed") -} -} \ No newline at end of file diff --git a/src/github.com/ibmdb/go_ibm_db/testdata/scan_test.go b/src/github.com/ibmdb/go_ibm_db/testdata/scan_test.go deleted file mode 100644 index a8c801d..0000000 --- a/src/github.com/ibmdb/go_ibm_db/testdata/scan_test.go +++ /dev/null @@ -1,9 +0,0 @@ -package main - -import "testing" - -func TestScan(t *testing.T){ - if(Scan() != nil){ - t.Error("Error in Scanning Query") -} -} \ No newline at end of file diff --git a/src/github.com/ibmdb/go_ibm_db/tx.go b/src/github.com/ibmdb/go_ibm_db/tx.go deleted file mode 100644 index 7f3f6c6..0000000 --- a/src/github.com/ibmdb/go_ibm_db/tx.go +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package go_ibm_db - -import ( - "database/sql/driver" - "errors" - - "github.com/ibmdb/go_ibm_db/api" -) - -type Tx struct { - c *Conn -} - -func (c *Conn) setAutoCommitAttr(a uintptr) error { - ret := api.SQLSetConnectAttr(c.h, api.SQL_ATTR_AUTOCOMMIT, - api.SQLPOINTER(a), api.SQL_IS_UINTEGER) - if IsError(ret) { - return NewError("SQLSetConnectAttr", c.h) - } - return nil -} - -func (c *Conn) Begin() (driver.Tx, error) { - if c.tx != nil { - return nil, errors.New("already in a transaction") - } - err := c.setAutoCommitAttr(api.SQL_AUTOCOMMIT_OFF) - if err != nil { - return nil, err - } - c.tx = &Tx{c: c} - return c.tx, nil -} - -func (c *Conn) endTx(commit bool) error { - if c.tx == nil { - return errors.New("not in a transaction") - } - c.tx = nil - var howToEnd api.SQLSMALLINT - if commit { - howToEnd = api.SQL_COMMIT - } else { - howToEnd = api.SQL_ROLLBACK - } - ret := api.SQLEndTran(api.SQL_HANDLE_DBC, api.SQLHANDLE(c.h), howToEnd) - if IsError(ret) { - return NewError("SQLEndTran", c.h) - } - err := c.setAutoCommitAttr(api.SQL_AUTOCOMMIT_ON) - if err != nil { - return err - } - return nil -} - -func (tx *Tx) Commit() error { - return tx.c.endTx(true) -} - -func (tx *Tx) Rollback() error { - return tx.c.endTx(false) -} diff --git a/src/github.com/ibmdb/go_ibm_db/utf16.go b/src/github.com/ibmdb/go_ibm_db/utf16.go deleted file mode 100644 index e67c405..0000000 --- a/src/github.com/ibmdb/go_ibm_db/utf16.go +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package go_ibm_db - -import ( - "unicode/utf16" - "unicode/utf8" -) - -const ( - replacementChar = '\uFFFD' // Unicode replacement character - - // 0xd800-0xdc00 encodes the high 10 bits of a pair. - // 0xdc00-0xe000 encodes the low 10 bits of a pair. - // the value is those 20 bits plus 0x10000. - surr1 = 0xd800 - surr2 = 0xdc00 - surr3 = 0xe000 -) - -// utf16toutf8 returns the UTF-8 encoding of the UTF-16 sequence s, -// with a terminating NUL removed. -func utf16toutf8(s []uint16) []byte { - for i, v := range s { - if v == 0 { - s = s[0:i] - break - } - } - buf := make([]byte, 0, len(s)*2) // allow 2 bytes for every rune - b := make([]byte, 4) - for i := 0; i < len(s); i++ { - var rr rune - switch r := s[i]; { - case surr1 <= r && r < surr2 && i+1 < len(s) && - surr2 <= s[i+1] && s[i+1] < surr3: - // valid surrogate sequence - rr = utf16.DecodeRune(rune(r), rune(s[i+1])) - i++ - case surr1 <= r && r < surr3: - // invalid surrogate sequence - rr = replacementChar - default: - // normal rune - rr = rune(r) - } - b := b[:cap(b)] - n := utf8.EncodeRune(b, rr) - b = b[:n] - buf = append(buf, b...) - } - return buf -} From dec31b5b565d5c1e22e76d79783066b6265c5c17 Mon Sep 17 00:00:00 2001 From: akhilravuri1 Date: Tue, 8 Jan 2019 14:12:42 +0530 Subject: [PATCH 3/5] github.com/ibmdb/go_ibm_db driver added --- README | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/README b/README index 5808154..9bc515b 100644 --- a/README +++ b/README @@ -86,3 +86,13 @@ this will result connecting to database user/password@sid The corner case where the sid is a full DSN (with port and everything) is not fully managed: only port 1521 on localhost is checked for accepting connections. If you really need the full DSN support, please mail me! + +**************************************************************************** +For DB2: +**************************************************************************** +create database gosqltest + +To set set your DB2 user / password run: + +$ export GOSQLTEST_DB2_USER=user +$ export GOSQLTEST_DB2_PASS=password From 3014c3525e6fba0ecc683dbd8463b2bbd931679e Mon Sep 17 00:00:00 2001 From: akhilravuri1 Date: Mon, 1 Apr 2019 15:33:04 +0530 Subject: [PATCH 4/5] driver updated --- .../ibmdb/go_ibm_db/API_DOCUMENTATION.md | 363 ++++++++++++++++++ .../ibmdb/go_ibm_db/CONTRIBUTING.md | 11 + src/github.com/ibmdb/go_ibm_db/LICENSE.md | 27 ++ src/github.com/ibmdb/go_ibm_db/README.md | 244 ++++++++++++ src/github.com/ibmdb/go_ibm_db/api/Makefile | 15 + src/github.com/ibmdb/go_ibm_db/api/api.go | 68 ++++ .../ibmdb/go_ibm_db/api/api_unix.go | 135 +++++++ .../ibmdb/go_ibm_db/api/api_windows.go | 129 +++++++ .../ibmdb/go_ibm_db/api/api_windows_386.go | 10 + .../ibmdb/go_ibm_db/api/api_windows_amd64.go | 10 + .../ibmdb/go_ibm_db/api/mksyscall_unix.pl | 132 +++++++ .../ibmdb/go_ibm_db/api/zapi_unix.go | 118 ++++++ .../ibmdb/go_ibm_db/api/zapi_windows.go | 161 ++++++++ src/github.com/ibmdb/go_ibm_db/column.go | 279 ++++++++++++++ src/github.com/ibmdb/go_ibm_db/conn.go | 47 +++ src/github.com/ibmdb/go_ibm_db/driver.go | 60 +++ src/github.com/ibmdb/go_ibm_db/error.go | 72 ++++ src/github.com/ibmdb/go_ibm_db/handle.go | 44 +++ .../ibmdb/go_ibm_db/installer/setup.go | 184 +++++++++ src/github.com/ibmdb/go_ibm_db/odbcstmt.go | 157 ++++++++ src/github.com/ibmdb/go_ibm_db/param.go | 165 ++++++++ src/github.com/ibmdb/go_ibm_db/pooling.go | 205 ++++++++++ src/github.com/ibmdb/go_ibm_db/result.go | 22 ++ src/github.com/ibmdb/go_ibm_db/rows.go | 45 +++ src/github.com/ibmdb/go_ibm_db/stats.go | 33 ++ src/github.com/ibmdb/go_ibm_db/stmt.go | 99 +++++ .../ibmdb/go_ibm_db/testdata/a_create_test.go | 9 + .../ibmdb/go_ibm_db/testdata/begin_test.go | 9 + .../ibmdb/go_ibm_db/testdata/close_test.go | 9 + .../ibmdb/go_ibm_db/testdata/columns_test.go | 9 + .../ibmdb/go_ibm_db/testdata/commit_test.go | 9 + .../ibmdb/go_ibm_db/testdata/conn_test.go | 9 + .../ibmdb/go_ibm_db/testdata/drop_test.go | 9 + .../ibmdb/go_ibm_db/testdata/insert_test.go | 9 + .../ibmdb/go_ibm_db/testdata/main.go | 250 ++++++++++++ .../ibmdb/go_ibm_db/testdata/next_test.go | 9 + .../ibmdb/go_ibm_db/testdata/poolopen_test.go | 10 + .../ibmdb/go_ibm_db/testdata/prepare_test.go | 9 + .../ibmdb/go_ibm_db/testdata/query_test.go | 9 + .../ibmdb/go_ibm_db/testdata/queryrow_test.go | 9 + .../ibmdb/go_ibm_db/testdata/scan_test.go | 9 + src/github.com/ibmdb/go_ibm_db/tx.go | 67 ++++ src/github.com/ibmdb/go_ibm_db/utf16.go | 55 +++ 43 files changed, 3334 insertions(+) create mode 100644 src/github.com/ibmdb/go_ibm_db/API_DOCUMENTATION.md create mode 100644 src/github.com/ibmdb/go_ibm_db/CONTRIBUTING.md create mode 100644 src/github.com/ibmdb/go_ibm_db/LICENSE.md create mode 100644 src/github.com/ibmdb/go_ibm_db/README.md create mode 100644 src/github.com/ibmdb/go_ibm_db/api/Makefile create mode 100644 src/github.com/ibmdb/go_ibm_db/api/api.go create mode 100644 src/github.com/ibmdb/go_ibm_db/api/api_unix.go create mode 100644 src/github.com/ibmdb/go_ibm_db/api/api_windows.go create mode 100644 src/github.com/ibmdb/go_ibm_db/api/api_windows_386.go create mode 100644 src/github.com/ibmdb/go_ibm_db/api/api_windows_amd64.go create mode 100644 src/github.com/ibmdb/go_ibm_db/api/mksyscall_unix.pl create mode 100644 src/github.com/ibmdb/go_ibm_db/api/zapi_unix.go create mode 100644 src/github.com/ibmdb/go_ibm_db/api/zapi_windows.go create mode 100644 src/github.com/ibmdb/go_ibm_db/column.go create mode 100644 src/github.com/ibmdb/go_ibm_db/conn.go create mode 100644 src/github.com/ibmdb/go_ibm_db/driver.go create mode 100644 src/github.com/ibmdb/go_ibm_db/error.go create mode 100644 src/github.com/ibmdb/go_ibm_db/handle.go create mode 100644 src/github.com/ibmdb/go_ibm_db/installer/setup.go create mode 100644 src/github.com/ibmdb/go_ibm_db/odbcstmt.go create mode 100644 src/github.com/ibmdb/go_ibm_db/param.go create mode 100644 src/github.com/ibmdb/go_ibm_db/pooling.go create mode 100644 src/github.com/ibmdb/go_ibm_db/result.go create mode 100644 src/github.com/ibmdb/go_ibm_db/rows.go create mode 100644 src/github.com/ibmdb/go_ibm_db/stats.go create mode 100644 src/github.com/ibmdb/go_ibm_db/stmt.go create mode 100644 src/github.com/ibmdb/go_ibm_db/testdata/a_create_test.go create mode 100644 src/github.com/ibmdb/go_ibm_db/testdata/begin_test.go create mode 100644 src/github.com/ibmdb/go_ibm_db/testdata/close_test.go create mode 100644 src/github.com/ibmdb/go_ibm_db/testdata/columns_test.go create mode 100644 src/github.com/ibmdb/go_ibm_db/testdata/commit_test.go create mode 100644 src/github.com/ibmdb/go_ibm_db/testdata/conn_test.go create mode 100644 src/github.com/ibmdb/go_ibm_db/testdata/drop_test.go create mode 100644 src/github.com/ibmdb/go_ibm_db/testdata/insert_test.go create mode 100644 src/github.com/ibmdb/go_ibm_db/testdata/main.go create mode 100644 src/github.com/ibmdb/go_ibm_db/testdata/next_test.go create mode 100644 src/github.com/ibmdb/go_ibm_db/testdata/poolopen_test.go create mode 100644 src/github.com/ibmdb/go_ibm_db/testdata/prepare_test.go create mode 100644 src/github.com/ibmdb/go_ibm_db/testdata/query_test.go create mode 100644 src/github.com/ibmdb/go_ibm_db/testdata/queryrow_test.go create mode 100644 src/github.com/ibmdb/go_ibm_db/testdata/scan_test.go create mode 100644 src/github.com/ibmdb/go_ibm_db/tx.go create mode 100644 src/github.com/ibmdb/go_ibm_db/utf16.go diff --git a/src/github.com/ibmdb/go_ibm_db/API_DOCUMENTATION.md b/src/github.com/ibmdb/go_ibm_db/API_DOCUMENTATION.md new file mode 100644 index 0000000..88cd535 --- /dev/null +++ b/src/github.com/ibmdb/go_ibm_db/API_DOCUMENTATION.md @@ -0,0 +1,363 @@ +# go-ibm_db API Documentation + +## Database APIs + +**Database APIs** + +1. [.Open(drivername,ConnectionString)](#OpenApi) +2. [.Prepare(sqlquery)](#PrepareApi) +3. [.Query(sqlquery)](#QueryApi) +4. [.Exec(sqlquery)](#ExecApi) +5. [.Begin()](#BeginApi) +6. [.Close()](#CloseApi) +7. [.Commit()](#CommitApi) +8. [.Rollback()](#RollbackApi) +9. [.QueryRow(sqlquery)](#QueryRowApi) +10. [.Columns()](#ColumnsApi) +11. [.Next()](#NextApi) +12. [.Scan(options)](#ScanApi) + +### 1) .Open(drivername,ConnectionString) + +open a connection to database +* **connectionString** - The connection string for your database. +* For distributed platforms, the connection string is typically defined as: `DATABASE=dbname;HOSTNAME=hostname;PORT=port;PROTOCOL=TCPIP;UID=username;PWD=passwd` + +```go +var connStr = flag.String("conn", "HOSTNAME=hostname;PORT=port;DATABASE=dbname;UID=uid;PWD=Pass", "connection string") +func dboper() error { + fmt.Println("connecting to driver"); + db, err := sql.Open("drivername",*connStr); + if err != nil { + return err; + } + + defer db.Close() +} +``` +### 2) .Prepare(sqlquery) + +Prepare a statement for execution +* **sql** - SQL string to prepare + +Returns a ‘statement’ object + +```go +func oper() error { + fmt.Println("connecting to go-ibm_db"); + db, err:=sql.Open("go-imb_db",*connStr); + if err != nil { + return err; + } + + defer db.Close() + + st, err := db.Prepare("select * from ak") + if err !=nil { + return err + } + + rows,err := st.Query() + if err != nil { + return err + } + + defer rows.Close() +} +``` + +### 3) .Query(sqlquery) + +Issue a SQL query to the database + +If the query is executed then it will return the rows or it will return error + +```go + +func oper() error { + fmt.Println("connecting to go-ibm_db"); + db, err := sql.Open("go-ibm_db",*connStr); + if err != nil { + return err; + } + + defer db.Close() + + rows,err := db.Query(“select * from ak”) + if err != nil { + return err + } + + defer rows.Close() +} +``` + + +### 4) .Exec(sqlquery) + +Execute a prepared statement. + +Only DML commands are performed. No data is returned back. + +```go + +func oper() error { + fmt.Println("connecting to go-ibm_db"); + db, err := sql.Open("go-ibm_db",*connStr); + if err != nil { + return err; + } + + defer db.Close() + + _,err = db.Exec("create table ghh(a int, b float, c double, d char, e varchar(30))") + if err != nil { + return err + } +} +``` + +### 5) .Begin() + +Begin a transaction. + +```go + + +func oper() error { + fmt.Println("connecting to go-ibm_db"); + db, err := sql.Open("go-ibm_db",*connStr); + if err != nil { + return err; + } + + defer db.Close() + + bg, err := db.Begin() + if err !=nil { + return err + } + + return nil +} +``` + + + +### 6) .Close() + +Close the currently opened database. + +```go + +func dboper() error { + fmt.Println("connecting to go-ibm_db"); + db, err := sql.Open("go-ibm_db",*connStr); + if err != nil { + return err; + } + + defer db.Close() +} +``` + + + +### 7) .Commit() + +Commit a transaction. + +```go + +func oper() error{ + fmt.Println("connecting to go-ibm_db"); + db, err := sql.Open("go-ibm_db",*connStr); + if err != nil{ + return err; + } + + + defer db.Close() + + bg, err := db.Begin() + if err != nil { + return err + } + + _,err=bg.Exec("create table ghh(a int,b float,c double,d char,e varchar(30))") + if err != nil { + return err + } + + err = bg.Commit() + if err != nil { + return err + } + + return nil +} +``` + + + + +### 8) .Rollback() + +Rollback a transaction. + +```go + + +func oper() error{ + fmt.Println("connecting to go-ibm_db"); + db, err := sql.Open("go-ibm_db",*connStr); + if err != nil { + return err; + } + + defer db.Close() + bg, err := db.Begin() + if err !=nil { + return err + } + + _,err=bg.Exec("create table ghh(a int,b float,c double,d char,e varchar(30))") + if err != nil { + return err + } + + err = bg.Rollback() + if err != nil { + return err + } + + return nil +} +``` + +### 9) .QueryRow(sqlquery) + +QueryRow executes a query that is expected to return at most one row. +If there are more rows then it will scan first and discards the rest. + +```go + +func oper() error { + id := 123 + var username string + err := db.QueryRow("SELECT name FROM ak WHERE id=?", id).Scan(&username) + if err != nil { + return err + } + + fmt.Printf("Username is %s\n", username) + return nil +} + +``` + +### 10) .Columns() + +Returns the column names. + +Returns error if the rows are closed. + +```go + +func oper() error { + fmt.Println("connecting to databse"); + db, err := sql.Open("go-ibm_db",*connStr); + if err != nil { + return err; + } + + defer db.Close() + + st, err := db.Prepare("select * from ak") + if err !=nil { + return err + } + + rows,err :=st.Query() + if err != nil { + return err + } + + defer rows.Close() + name11 := make([]string,1) + name11, err = rows.Columns() + fmt.Printf("%v",name11); + return nil +} +``` + +### 11) .Next() + +Prepares the next result row for reading with the scan api. + +```go + +func oper() error { + fmt.Println("connecting to database"); + db, err:=sql.Open("go-ibm_db",*connStr); + if err != nil { + return err; + } + + defer db.Close() + rows,err := db.Query() + if err != nil { + return err + } + + defer rows.Close() + for rows.Next() { + var t string + var x string + err = rows.Scan(&t, &x) + if err != nil { + return err + } + + fmt.Printf("%v %v\n",t,x) + } + + return nil +} +``` + +### 12) .Scan(options) + +copies the columns in the current row into the values pointed. + +```go + +func oper() error { + fmt.Println("connecting to database"); + db, err := sql.Open("go-ibm_db", *connStr); + if err != nil { + return err; + } + + defer db.Close() + + rows,err := db.Query() + if err != nil { + return err + } + + defer rows.Close() + for rows.Next() { + var t string + var x string + err = rows.Scan(&t, &x) + if err != nil { + return err + } + + fmt.Printf("%v %v\n",t,x) + } + return nil +} +``` + diff --git a/src/github.com/ibmdb/go_ibm_db/CONTRIBUTING.md b/src/github.com/ibmdb/go_ibm_db/CONTRIBUTING.md new file mode 100644 index 0000000..41c3376 --- /dev/null +++ b/src/github.com/ibmdb/go_ibm_db/CONTRIBUTING.md @@ -0,0 +1,11 @@ +# Developer's Certificate of Origin 1.1 + +By making a contribution to this project, I certify that: + +(a) The contribution was created in whole or in part by me and I have the right to submit it under the open source license indicated in the file; or + +(b) The contribution is based upon previous work that, to the best of my knowledge, is covered under an appropriate open source license and I have the right under that license to submit that work with modifications, whether created in whole or in part by me, under the same open source license (unless I am permitted to submit under a different license), as indicated in the file; or + +(c) The contribution was provided directly to me by some other person who certified (a), (b) or (c) and I have not modified it. + +(d) I understand and agree that this project and the contribution are public and that a record of the contribution (including all personal information I submit with it, including my sign-off) is maintained indefinitely and may be redistributed consistent with this project or the open source license(s) involved. \ No newline at end of file diff --git a/src/github.com/ibmdb/go_ibm_db/LICENSE.md b/src/github.com/ibmdb/go_ibm_db/LICENSE.md new file mode 100644 index 0000000..7448756 --- /dev/null +++ b/src/github.com/ibmdb/go_ibm_db/LICENSE.md @@ -0,0 +1,27 @@ +Copyright (c) 2012 The Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/src/github.com/ibmdb/go_ibm_db/README.md b/src/github.com/ibmdb/go_ibm_db/README.md new file mode 100644 index 0000000..8a40ace --- /dev/null +++ b/src/github.com/ibmdb/go_ibm_db/README.md @@ -0,0 +1,244 @@ +# go_ibm_db + +Interface for GoLang to DB2 for z/OS, DB2 for LUW, DB2 for i. + +## API Documentation + +> For complete list of go_ibm_db APIs and examples please check [APIDocumentation.md](https://github.com/ibmdb/go_ibm_db/blob/master/API_DOCUMENTATION.md) + +## Prerequisite + +Golang should be installed in your system. + +## How to Install in Windows +``` +go get -d github.com/ibmdb/go_ibm_db + +If you already have a cli driver available in your system, add the path of the same to your Path windows environment variable +Example: Path = C:\Program Files\IBM\IBM DATA SERVER DRIVER\bin + + +If you do not have a clidriver in your system, go to installer folder where go_ibm_db is downloaded in your system (Example: C:\Users\uname\go\src\github.com\ibmdb\go_ibm_db\installer) and run setup.go file (go run setup.go). + +where uname is the username + +Above command will download clidriver. + +Add the path of the clidriver downloaded to your Path windows environment variable +(Example: Path=C:\Users\rakhil\go\src\github.com\ibmdb\go_ibm_db\installer\clidriver\bin) + + +``` + +## How to Install in Linux/Mac +``` +go get -d github.com/ibmdb/go_ibm_db + +If you already have a cli driver available in your system, set the below environment variables with the clidriver path + +export DB2HOME=/home/rakhil/dsdriver +export CGO_CFLAGS=-I$DB2HOME/include +export CGO_LDFLAGS=-L$DB2HOME/lib +Linux: +export LD_LIBRARY_PATH=/home/rakhil/dsdriver/lib +Mac: +export DYLD_LIBRARY_PATH=$DYLD_LIBRARY_PATH:/Applications/dsdriver/lib + +If you do not have a clidriver available in your system +go to installer folder where go_ibm_db is downloaded in your system (Example: /home/uname/go/src/github.com/ibmdb/go_ibm_db/installer) and run setup.go file (go run setup.go) +where uname is the username + +Above command will download clidriver. + +Set the below envronment variables with the path of the clidriver downloaded + +export DB2HOME=/home/uname/go/src/github.com/ibmdb/go_ibm_db/installer/clidriver +export CGO_CFLAGS=-I$DB2HOME/include +export CGO_LDFLAGS=-L$DB2HOME/lib +Linux: +export LD_LIBRARY_PATH=/home/uname/go/src/github.com/ibmdb/go_ibm_db/installer/clidriver/lib +Mac: +export DYLD_LIBRARY_PATH=$DYLD_LIBRARY_PATH:/home/uname/go/src/github.com/ibmdb/go_ibm_db/installer/clidriver/lib + + +``` + +## How to run sample program + +### example1.go:- + +``` +package main + +import ( + _ "github.com/ibmdb/go_ibm_db" + "database/sql" + "fmt" +) + +func main(){ + con:="HOSTNAME=host;DATABASE=name;PORT=number;UID=username;PWD=password" + db, err:=sql.Open("go_ibm_db", con) + if err != nil{ + + fmt.Println(err) + } + db.Close() +} +To run the sample:- go run example1.go +``` + +### example2.go:- + +``` +package main + +import ( + _ "github.com/ibmdb/go_ibm_db" + "database/sql" + "fmt" +) + +func Create_Con(con string) *sql.DB{ + db, err:=sql.Open("go_ibm_db", con) + if err != nil{ + + fmt.Println(err) + return nil + } + return db +} + +//creating a table + +func create(db *sql.DB) error{ + _,err:=db.Exec("DROP table SAMPLE") + if(err!=nil){ + _,err:=db.Exec("create table SAMPLE(ID varchar(20),NAME varchar(20),LOCATION varchar(20),POSITION varchar(20))") + if err != nil{ + return err + } + } else { + _,err:=db.Exec("create table SAMPLE(ID varchar(20),NAME varchar(20),LOCATION varchar(20),POSITION varchar(20))") + if err != nil{ + return err + } + } + fmt.Println("TABLE CREATED") + return nil +} + +//inserting row + +func insert(db *sql.DB) error{ + st, err:=db.Prepare("Insert into SAMPLE(ID,NAME,LOCATION,POSITION) values('3242','mike','hyd','manager')") + if err != nil{ + return err + } + st.Query() + return nil +} + +//this api selects the data from the table and prints it + +func display(db *sql.DB) error{ + st, err:=db.Prepare("select * from SAMPLE") + if err !=nil{ + return err + } + err=execquery(st) + if err!=nil{ + return err + } + return nil +} + + +func execquery(st *sql.Stmt) error{ + rows,err :=st.Query() + if err != nil{ + return err + } + cols, _ := rows.Columns() + fmt.Printf("%s %s %s %s\n",cols[0],cols[1],cols[2],cols[3]) + fmt.Println("-------------------------------------") + defer rows.Close() + for rows.Next(){ + var t,x,m,n string + err = rows.Scan(&t,&x,&m,&n) + if err != nil{ + return err + } + fmt.Printf("%v %v %v %v\n",t,x,m,n) + } + return nil +} + +func main(){ + con:="HOSTNAME=host;DATABASE=name;PORT=number;UID=username;PWD=password" + type Db *sql.DB + var re Db + re=Create_Con(con) + err:=create(re) + if err != nil{ + fmt.Println(err) + } + err=insert(re) + if err != nil{ + fmt.Println(err) + } + err=display(re) + if err != nil{ + fmt.Println(err) + } +} +To run the sample:- go run example2.go +``` + +### example3.go:-(POOLING) + +``` +package main + +import ( + a "github.com/ibmdb/go_ibm_db" + _"database/sql" + "fmt" +) + +func main(){ + con:="HOSTNAME=host;PORT=number;DATABASE=name;UID=username;PWD=password"; + pool:=a.Pconnect("PoolSize=100") + + //SetConnMaxLifetime will atake the value in SECONDS + db:=pool.Open(con,"SetConnMaxLifetime=30") + st, err:=db.Prepare("Insert into SAMPLE values('hi','hi','hi','hi')") + if err != nil{ + fmt.Println(err) + } + st.Query() + + //Here the the time out is default. + db1:=pool.Open(con) + st1, err:=db1.Prepare("Insert into SAMPLE values('hi1','hi1','hi1','hi1')") + if err != nil{ + fmt.Println(err) + } + st1.Query() + + db1.Close() + db.Close() + pool.Display() + pool.Release() + pool.Display() +} +To run the sample:- go run example3.go +``` +For Running the Tests: +====================== + +1) Put your connection string in the main.go file in testdata folder + +2) Now run go test command (use go test -v command for details) + + diff --git a/src/github.com/ibmdb/go_ibm_db/api/Makefile b/src/github.com/ibmdb/go_ibm_db/api/Makefile new file mode 100644 index 0000000..2bdd255 --- /dev/null +++ b/src/github.com/ibmdb/go_ibm_db/api/Makefile @@ -0,0 +1,15 @@ +# Copyright 2012 The Go Authors. All rights reserved. +# Use of this source code is governed by a BSD-style +# license that can be found in the LICENSE file. + +all: zapi_windows.go zapi_unix.go + +zapi_windows.go: api.go + $(GOROOT)/src/pkg/syscall/mksyscall_windows.pl $^ \ + | gofmt \ + > $@ + +zapi_unix.go: api.go + ./mksyscall_unix.pl $^ \ + | gofmt \ + > $@ diff --git a/src/github.com/ibmdb/go_ibm_db/api/api.go b/src/github.com/ibmdb/go_ibm_db/api/api.go new file mode 100644 index 0000000..aa7abae --- /dev/null +++ b/src/github.com/ibmdb/go_ibm_db/api/api.go @@ -0,0 +1,68 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package api + +import ( + "unicode/utf16" +) + +type ( + SQL_DATE_STRUCT struct { + Year SQLSMALLINT + Month SQLUSMALLINT + Day SQLUSMALLINT + } + + SQL_TIMESTAMP_STRUCT struct { + Year SQLSMALLINT + Month SQLUSMALLINT + Day SQLUSMALLINT + Hour SQLUSMALLINT + Minute SQLUSMALLINT + Second SQLUSMALLINT + Fraction SQLUINTEGER + } +) + +//sys SQLAllocHandle(handleType SQLSMALLINT, inputHandle SQLHANDLE, outputHandle *SQLHANDLE) (ret SQLRETURN) = odbc32.SQLAllocHandle +//sys SQLBindCol(statementHandle SQLHSTMT, columnNumber SQLUSMALLINT, targetType SQLSMALLINT, targetValuePtr SQLPOINTER, bufferLength SQLLEN, vallen *SQLLEN) (ret SQLRETURN) = odbc32.SQLBindCol +//sys SQLBindParameter(statementHandle SQLHSTMT, parameterNumber SQLUSMALLINT, inputOutputType SQLSMALLINT, valueType SQLSMALLINT, parameterType SQLSMALLINT, columnSize SQLULEN, decimalDigits SQLSMALLINT, parameterValue SQLPOINTER, bufferLength SQLLEN, ind *SQLLEN) (ret SQLRETURN) = odbc32.SQLBindParameter +//sys SQLCloseCursor(statementHandle SQLHSTMT) (ret SQLRETURN) = odbc32.SQLCloseCursor +//sys SQLDescribeCol(statementHandle SQLHSTMT, columnNumber SQLUSMALLINT, columnName *SQLWCHAR, bufferLength SQLSMALLINT, nameLengthPtr *SQLSMALLINT, dataTypePtr *SQLSMALLINT, columnSizePtr *SQLULEN, decimalDigitsPtr *SQLSMALLINT, nullablePtr *SQLSMALLINT) (ret SQLRETURN) = odbc32.SQLDescribeColW +//sys SQLDescribeParam(statementHandle SQLHSTMT, parameterNumber SQLUSMALLINT, dataTypePtr *SQLSMALLINT, parameterSizePtr *SQLULEN, decimalDigitsPtr *SQLSMALLINT, nullablePtr *SQLSMALLINT) (ret SQLRETURN) = odbc32.SQLDescribeParam +//sys SQLDisconnect(connectionHandle SQLHDBC) (ret SQLRETURN) = odbc32.SQLDisconnect +//sys SQLDriverConnect(connectionHandle SQLHDBC, windowHandle SQLHWND, inConnectionString *SQLWCHAR, stringLength1 SQLSMALLINT, outConnectionString *SQLWCHAR, bufferLength SQLSMALLINT, stringLength2Ptr *SQLSMALLINT, driverCompletion SQLUSMALLINT) (ret SQLRETURN) = odbc32.SQLDriverConnectW +//sys SQLEndTran(handleType SQLSMALLINT, handle SQLHANDLE, completionType SQLSMALLINT) (ret SQLRETURN) = odbc32.SQLEndTran +//sys SQLExecute(statementHandle SQLHSTMT) (ret SQLRETURN) = odbc32.SQLExecute +//sys SQLFetch(statementHandle SQLHSTMT) (ret SQLRETURN) = odbc32.SQLFetch +//sys SQLFreeHandle(handleType SQLSMALLINT, handle SQLHANDLE) (ret SQLRETURN) = odbc32.SQLFreeHandle +//sys SQLGetData(statementHandle SQLHSTMT, colOrParamNum SQLUSMALLINT, targetType SQLSMALLINT, targetValuePtr SQLPOINTER, bufferLength SQLLEN, vallen *SQLLEN) (ret SQLRETURN) = odbc32.SQLGetData +//sys SQLGetDiagRec(handleType SQLSMALLINT, handle SQLHANDLE, recNumber SQLSMALLINT, sqlState *SQLWCHAR, nativeErrorPtr *SQLINTEGER, messageText *SQLWCHAR, bufferLength SQLSMALLINT, textLengthPtr *SQLSMALLINT) (ret SQLRETURN) = odbc32.SQLGetDiagRecW +//sys SQLNumParams(statementHandle SQLHSTMT, parameterCountPtr *SQLSMALLINT) (ret SQLRETURN) = odbc32.SQLNumParams +//sys SQLNumResultCols(statementHandle SQLHSTMT, columnCountPtr *SQLSMALLINT) (ret SQLRETURN) = odbc32.SQLNumResultCols +//sys SQLPrepare(statementHandle SQLHSTMT, statementText *SQLWCHAR, textLength SQLINTEGER) (ret SQLRETURN) = odbc32.SQLPrepareW +//sys SQLRowCount(statementHandle SQLHSTMT, rowCountPtr *SQLLEN) (ret SQLRETURN) = odbc32.SQLRowCount +//sys SQLSetEnvAttr(environmentHandle SQLHENV, attribute SQLINTEGER, valuePtr SQLPOINTER, stringLength SQLINTEGER) (ret SQLRETURN) = odbc32.SQLSetEnvAttr +//sys SQLSetConnectAttr(connectionHandle SQLHDBC, attribute SQLINTEGER, valuePtr SQLPOINTER, stringLength SQLINTEGER) (ret SQLRETURN) = odbc32.SQLSetConnectAttrW + +// UTF16ToString returns the UTF-8 encoding of the UTF-16 sequence s, +// with a terminating NUL removed. +func UTF16ToString(s []uint16) string { + for i, v := range s { + if v == 0 { + s = s[0:i] + break + } + } + return string(utf16.Decode(s)) +} + +// StringToUTF16 returns the UTF-16 encoding of the UTF-8 string s, +// with a terminating NUL added. +func StringToUTF16(s string) []uint16 { return utf16.Encode([]rune(s + "\x00")) } + +// StringToUTF16Ptr returns pointer to the UTF-16 encoding of +// the UTF-8 string s, with a terminating NUL added. +func StringToUTF16Ptr(s string) *uint16 { return &StringToUTF16(s)[0] } diff --git a/src/github.com/ibmdb/go_ibm_db/api/api_unix.go b/src/github.com/ibmdb/go_ibm_db/api/api_unix.go new file mode 100644 index 0000000..d89ecbe --- /dev/null +++ b/src/github.com/ibmdb/go_ibm_db/api/api_unix.go @@ -0,0 +1,135 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build darwin linux +// +build cgo + +package api + +// #cgo darwin LDFLAGS: -ldb2 +// #cgo linux LDFLAGS: -ldb2 +// #include +import "C" + +const ( + SQL_OV_ODBC3 = uintptr(C.SQL_OV_ODBC3) + + SQL_ATTR_ODBC_VERSION = C.SQL_ATTR_ODBC_VERSION + + SQL_DRIVER_NOPROMPT = C.SQL_DRIVER_NOPROMPT + + SQL_HANDLE_ENV = C.SQL_HANDLE_ENV + SQL_HANDLE_DBC = C.SQL_HANDLE_DBC + SQL_HANDLE_STMT = C.SQL_HANDLE_STMT + + SQL_SUCCESS = C.SQL_SUCCESS + SQL_SUCCESS_WITH_INFO = C.SQL_SUCCESS_WITH_INFO + SQL_INVALID_HANDLE = C.SQL_INVALID_HANDLE + SQL_NO_DATA = C.SQL_NO_DATA + SQL_NO_TOTAL = C.SQL_NO_TOTAL + SQL_NTS = C.SQL_NTS + SQL_MAX_MESSAGE_LENGTH = C.SQL_MAX_MESSAGE_LENGTH + SQL_NULL_HANDLE = uintptr(C.SQL_NULL_HANDLE) + SQL_NULL_HENV = uintptr(C.SQL_NULL_HENV) + SQL_NULL_HDBC = uintptr(C.SQL_NULL_HDBC) + SQL_NULL_HSTMT = uintptr(C.SQL_NULL_HSTMT) + + SQL_PARAM_INPUT = C.SQL_PARAM_INPUT + + SQL_NULL_DATA = C.SQL_NULL_DATA + SQL_DATA_AT_EXEC = C.SQL_DATA_AT_EXEC + + SQL_UNKNOWN_TYPE = C.SQL_UNKNOWN_TYPE + SQL_CHAR = C.SQL_CHAR + SQL_NUMERIC = C.SQL_NUMERIC + SQL_DECIMAL = C.SQL_DECIMAL + SQL_INTEGER = C.SQL_INTEGER + SQL_SMALLINT = C.SQL_SMALLINT + SQL_FLOAT = C.SQL_FLOAT + SQL_REAL = C.SQL_REAL + SQL_DOUBLE = C.SQL_DOUBLE + SQL_DATETIME = C.SQL_DATETIME + SQL_DATE = C.SQL_DATE + SQL_TIME = C.SQL_TIME + SQL_VARCHAR = C.SQL_VARCHAR + SQL_TYPE_DATE = C.SQL_TYPE_DATE + SQL_TYPE_TIME = C.SQL_TYPE_TIME + SQL_TYPE_TIMESTAMP = C.SQL_TYPE_TIMESTAMP + SQL_TIMESTAMP = C.SQL_TIMESTAMP + SQL_LONGVARCHAR = C.SQL_LONGVARCHAR + SQL_BINARY = C.SQL_BINARY + SQL_VARBINARY = C.SQL_VARBINARY + SQL_LONGVARBINARY = C.SQL_LONGVARBINARY + SQL_BIGINT = C.SQL_BIGINT + SQL_TINYINT = C.SQL_TINYINT + SQL_BIT = C.SQL_BIT + SQL_WCHAR = C.SQL_WCHAR + SQL_WVARCHAR = C.SQL_WVARCHAR + SQL_WLONGVARCHAR = C.SQL_WLONGVARCHAR + SQL_GUID = C.SQL_GUID + SQL_SIGNED_OFFSET = C.SQL_SIGNED_OFFSET + SQL_UNSIGNED_OFFSET = C.SQL_UNSIGNED_OFFSET + + // TODO(lukemauldin): Not defined in sqlext.h. Using windows value, but it is not supported. + SQL_SS_XML = -152 + + SQL_C_CHAR = C.SQL_C_CHAR + SQL_C_LONG = C.SQL_C_LONG + SQL_C_SHORT = C.SQL_C_SHORT + SQL_C_FLOAT = C.SQL_C_FLOAT + SQL_C_DOUBLE = C.SQL_C_DOUBLE + SQL_C_NUMERIC = C.SQL_C_NUMERIC + SQL_C_DATE = C.SQL_C_DATE + SQL_C_TIME = C.SQL_C_TIME + SQL_C_TYPE_TIMESTAMP = C.SQL_C_TYPE_TIMESTAMP + SQL_C_TIMESTAMP = C.SQL_C_TIMESTAMP + SQL_C_BINARY = C.SQL_C_BINARY + SQL_C_BIT = C.SQL_C_BIT + SQL_C_WCHAR = C.SQL_C_WCHAR + SQL_C_DEFAULT = C.SQL_C_DEFAULT + SQL_C_SBIGINT = C.SQL_C_SBIGINT + SQL_C_UBIGINT = C.SQL_C_UBIGINT + SQL_C_GUID = C.SQL_C_GUID + + SQL_COMMIT = C.SQL_COMMIT + SQL_ROLLBACK = C.SQL_ROLLBACK + + SQL_AUTOCOMMIT = C.SQL_AUTOCOMMIT + SQL_ATTR_AUTOCOMMIT = C.SQL_ATTR_AUTOCOMMIT + SQL_AUTOCOMMIT_OFF = C.SQL_AUTOCOMMIT_OFF + SQL_AUTOCOMMIT_ON = C.SQL_AUTOCOMMIT_ON + SQL_AUTOCOMMIT_DEFAULT = C.SQL_AUTOCOMMIT_DEFAULT + + SQL_IS_UINTEGER = C.SQL_IS_UINTEGER + + //Connection pooling + SQL_ATTR_CONNECTION_POOLING = C.SQL_ATTR_CONNECTION_POOLING + SQL_ATTR_CP_MATCH = C.SQL_ATTR_CP_MATCH + SQL_CP_OFF = uintptr(C.SQL_CP_OFF) + SQL_CP_ONE_PER_DRIVER = uintptr(C.SQL_CP_ONE_PER_DRIVER) + SQL_CP_ONE_PER_HENV = uintptr(C.SQL_CP_ONE_PER_HENV) + SQL_CP_DEFAULT = SQL_CP_OFF + SQL_CP_STRICT_MATCH = uintptr(C.SQL_CP_STRICT_MATCH) + SQL_CP_RELAXED_MATCH = uintptr(C.SQL_CP_RELAXED_MATCH) +) + +type ( + SQLHANDLE C.SQLHANDLE + SQLHENV C.SQLHENV + SQLHDBC C.SQLHDBC + SQLHSTMT C.SQLHSTMT + SQLHWND uintptr + + SQLWCHAR C.SQLWCHAR + SQLSCHAR C.SQLSCHAR + SQLSMALLINT C.SQLSMALLINT + SQLUSMALLINT C.SQLUSMALLINT + SQLINTEGER C.SQLINTEGER + SQLUINTEGER C.SQLUINTEGER + SQLPOINTER C.SQLPOINTER + SQLRETURN C.SQLRETURN + + SQLLEN C.SQLLEN + SQLULEN C.SQLULEN +) diff --git a/src/github.com/ibmdb/go_ibm_db/api/api_windows.go b/src/github.com/ibmdb/go_ibm_db/api/api_windows.go new file mode 100644 index 0000000..843c363 --- /dev/null +++ b/src/github.com/ibmdb/go_ibm_db/api/api_windows.go @@ -0,0 +1,129 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package api + +const ( + SQL_OV_ODBC3 = 3 + + SQL_ATTR_ODBC_VERSION = 200 + + SQL_DRIVER_NOPROMPT = 0 + + SQL_HANDLE_ENV = 1 + SQL_HANDLE_DBC = 2 + SQL_HANDLE_STMT = 3 + + SQL_SUCCESS = 0 + SQL_SUCCESS_WITH_INFO = 1 + SQL_INVALID_HANDLE = -2 + SQL_NO_DATA = 100 + SQL_NO_TOTAL = -4 + SQL_NTS = -3 + SQL_MAX_MESSAGE_LENGTH = 512 + SQL_NULL_HANDLE = 0 + SQL_NULL_HENV = 0 + SQL_NULL_HDBC = 0 + SQL_NULL_HSTMT = 0 + + SQL_PARAM_INPUT = 1 + + SQL_NULL_DATA = -1 + SQL_DATA_AT_EXEC = -2 + + SQL_UNKNOWN_TYPE = 0 + SQL_CHAR = 1 + SQL_NUMERIC = 2 + SQL_DECIMAL = 3 + SQL_INTEGER = 4 + SQL_SMALLINT = 5 + SQL_FLOAT = 6 + SQL_REAL = 7 + SQL_DOUBLE = 8 + SQL_DATETIME = 9 + SQL_DATE = 9 + SQL_TIME = 10 + SQL_VARCHAR = 12 + SQL_TYPE_DATE = 91 + SQL_TYPE_TIME = 92 + SQL_TYPE_TIMESTAMP = 93 + SQL_TIMESTAMP = 11 + SQL_LONGVARCHAR = -1 + SQL_BINARY = -2 + SQL_VARBINARY = -3 + SQL_LONGVARBINARY = -4 + SQL_BIGINT = -5 + SQL_TINYINT = -6 + SQL_BIT = -7 + SQL_WCHAR = -8 + SQL_WVARCHAR = -9 + SQL_WLONGVARCHAR = -10 + SQL_GUID = -11 + SQL_SIGNED_OFFSET = -20 + SQL_UNSIGNED_OFFSET = -22 + SQL_SS_XML = -152 + + SQL_C_CHAR = SQL_CHAR + SQL_C_LONG = SQL_INTEGER + SQL_C_SHORT = SQL_SMALLINT + SQL_C_FLOAT = SQL_REAL + SQL_C_DOUBLE = SQL_DOUBLE + SQL_C_NUMERIC = SQL_NUMERIC + SQL_C_DATE = SQL_DATE + SQL_C_TIME = SQL_TIME + SQL_C_TYPE_TIMESTAMP = SQL_TYPE_TIMESTAMP + SQL_C_TIMESTAMP = SQL_TIMESTAMP + SQL_C_BINARY = SQL_BINARY + SQL_C_BIT = SQL_BIT + SQL_C_WCHAR = SQL_WCHAR + SQL_C_DEFAULT = 99 + SQL_C_SBIGINT = SQL_BIGINT + SQL_SIGNED_OFFSET + SQL_C_UBIGINT = SQL_BIGINT + SQL_UNSIGNED_OFFSET + SQL_C_GUID = SQL_GUID + + SQL_COMMIT = 0 + SQL_ROLLBACK = 1 + + SQL_AUTOCOMMIT = 102 + SQL_ATTR_AUTOCOMMIT = SQL_AUTOCOMMIT + SQL_AUTOCOMMIT_OFF = 0 + SQL_AUTOCOMMIT_ON = 1 + SQL_AUTOCOMMIT_DEFAULT = SQL_AUTOCOMMIT_ON + + SQL_IS_UINTEGER = -5 + + //Connection pooling + SQL_ATTR_CONNECTION_POOLING = 201 + SQL_ATTR_CP_MATCH = 202 + SQL_CP_OFF = 0 + SQL_CP_ONE_PER_DRIVER = 1 + SQL_CP_ONE_PER_HENV = 2 + SQL_CP_DEFAULT = SQL_CP_OFF + SQL_CP_STRICT_MATCH = 0 + SQL_CP_RELAXED_MATCH = 1 +) + +type ( + SQLHANDLE uintptr + SQLHENV SQLHANDLE + SQLHDBC SQLHANDLE + SQLHSTMT SQLHANDLE + SQLHWND uintptr + + SQLWCHAR uint16 + SQLSCHAR int8 + SQLSMALLINT int16 + SQLUSMALLINT uint16 + SQLINTEGER int32 + SQLUINTEGER uint32 + SQLPOINTER uintptr + SQLRETURN SQLSMALLINT + + SQLGUID struct { + Data1 uint32 + Data2 uint16 + Data3 uint16 + Data4 [8]byte + } +) diff --git a/src/github.com/ibmdb/go_ibm_db/api/api_windows_386.go b/src/github.com/ibmdb/go_ibm_db/api/api_windows_386.go new file mode 100644 index 0000000..2edf92a --- /dev/null +++ b/src/github.com/ibmdb/go_ibm_db/api/api_windows_386.go @@ -0,0 +1,10 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package api + +type ( + SQLLEN SQLINTEGER + SQLULEN SQLUINTEGER +) diff --git a/src/github.com/ibmdb/go_ibm_db/api/api_windows_amd64.go b/src/github.com/ibmdb/go_ibm_db/api/api_windows_amd64.go new file mode 100644 index 0000000..b603663 --- /dev/null +++ b/src/github.com/ibmdb/go_ibm_db/api/api_windows_amd64.go @@ -0,0 +1,10 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package api + +type ( + SQLLEN int64 + SQLULEN uint64 +) diff --git a/src/github.com/ibmdb/go_ibm_db/api/mksyscall_unix.pl b/src/github.com/ibmdb/go_ibm_db/api/mksyscall_unix.pl new file mode 100644 index 0000000..eb6ecf5 --- /dev/null +++ b/src/github.com/ibmdb/go_ibm_db/api/mksyscall_unix.pl @@ -0,0 +1,132 @@ +#!/usr/bin/perl +# Copyright 2012 The Go Authors. All rights reserved. +# Use of this source code is governed by a BSD-style +# license that can be found in the LICENSE file. + +# This program is based on $GOROOT/src/pkg/syscall/mksyscall_windows.pl. + +use strict; + +my $cmdline = "mksyscall_unix.pl " . join(' ', @ARGV); +my $errors = 0; + +binmode STDOUT; + +if($ARGV[0] =~ /^-/) { + print STDERR "usage: mksyscall_unix.pl [file ...]\n"; + exit 1; +} + +sub parseparamlist($) { + my ($list) = @_; + $list =~ s/^\s*//; + $list =~ s/\s*$//; + if($list eq "") { + return (); + } + return split(/\s*,\s*/, $list); +} + +sub parseparam($) { + my ($p) = @_; + if($p !~ /^(\S*) (\S*)$/) { + print STDERR "$ARGV:$.: malformed parameter: $p\n"; + $errors = 1; + return ("xx", "int"); + } + return ($1, $2); +} + +my $package = ""; +my $text = ""; +while(<>) { + chomp; + s/\s+/ /g; + s/^\s+//; + s/\s+$//; + $package = $1 if !$package && /^package (\S+)$/; + next if !/^\/\/sys /; + + # Line must be of the form + # func Open(path string, mode int, perm int) (fd int, err error) + # Split into name, in params, out params. + if(!/^\/\/sys (\w+)\(([^()]*)\)\s*(?:\(([^()]+)\))?\s*(?:\[failretval(.*)\])?\s*(?:=\s*(?:(\w*)\.)?(\w*))?$/) { + print STDERR "$ARGV:$.: malformed //sys declaration\n"; + $errors = 1; + next; + } + my ($func, $in, $out, $failcond, $modname, $sysname) = ($1, $2, $3, $4, $5, $6); + + # Split argument lists on comma. + my @in = parseparamlist($in); + my @out = parseparamlist($out); + + # System call name. + if($sysname eq "") { + $sysname = "$func"; + } + + # Go function header. + $out = join(', ', @out); + if($out ne "") { + $out = " ($out)"; + } + if($text ne "") { + $text .= "\n" + } + $text .= sprintf "func %s(%s)%s {\n", $func, join(', ', @in), $out; + + # Prepare arguments. + my @sqlin= (); + my @pin= (); + foreach my $p (@in) { + my ($name, $type) = parseparam($p); + + if($type =~ /^\*(SQLCHAR)/) { + push @sqlin, sprintf "(*C.%s)(unsafe.Pointer(%s))", $1, $name; + } elsif($type =~ /^\*(SQLWCHAR)/) { + push @sqlin, sprintf "(*C.%s)(unsafe.Pointer(%s))", $1, $name; + } elsif($type =~ /^\*(.*)$/) { + push @sqlin, sprintf "(*C.%s)(%s)", $1, $name; + } else { + push @sqlin, sprintf "C.%s(%s)", $type, $name; + } + push @pin, sprintf "\"%s=\", %s, ", $name, $name; + } + + $text .= sprintf "\tr := C.%s(%s)\n", $sysname, join(',', @sqlin); + if(0) { + $text .= sprintf "println(\"SYSCALL: %s(\", %s\") (\", r, \")\")\n", $func, join('", ", ', @pin); + } + $text .= "\treturn SQLRETURN(r)\n"; + $text .= "}\n"; +} + +if($errors) { + exit 1; +} + +print < +import "C" + +$text + +EOF +exit 0; diff --git a/src/github.com/ibmdb/go_ibm_db/api/zapi_unix.go b/src/github.com/ibmdb/go_ibm_db/api/zapi_unix.go new file mode 100644 index 0000000..a89d124 --- /dev/null +++ b/src/github.com/ibmdb/go_ibm_db/api/zapi_unix.go @@ -0,0 +1,118 @@ +// mksyscall_unix.pl api.go +// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT + +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build darwin linux +// +build cgo + +package api + +import "unsafe" + +// #cgo darwin LDFLAGS: -ldb2 +// #cgo linux LDFLAGS: -ldb2 +// #include +import "C" + +func SQLAllocHandle(handleType SQLSMALLINT, inputHandle SQLHANDLE, outputHandle *SQLHANDLE) (ret SQLRETURN) { + r := C.SQLAllocHandle(C.SQLSMALLINT(handleType), C.SQLHANDLE(inputHandle), (*C.SQLHANDLE)(outputHandle)) + return SQLRETURN(r) +} + +func SQLBindCol(statementHandle SQLHSTMT, columnNumber SQLUSMALLINT, targetType SQLSMALLINT, targetValuePtr []byte, bufferLength SQLLEN, vallen *SQLLEN) (ret SQLRETURN) { + r := C.SQLBindCol(C.SQLHSTMT(statementHandle), C.SQLUSMALLINT(columnNumber), C.SQLSMALLINT(targetType), C.SQLPOINTER(&targetValuePtr[0]), C.SQLLEN(bufferLength), (*C.SQLLEN)(vallen)) + return SQLRETURN(r) +} + +func SQLBindParameter(statementHandle SQLHSTMT, parameterNumber SQLUSMALLINT, inputOutputType SQLSMALLINT, valueType SQLSMALLINT, parameterType SQLSMALLINT, columnSize SQLULEN, decimalDigits SQLSMALLINT, parameterValue SQLPOINTER, bufferLength SQLLEN, ind *SQLLEN) (ret SQLRETURN) { + r := C.SQLBindParameter(C.SQLHSTMT(statementHandle), C.SQLUSMALLINT(parameterNumber), C.SQLSMALLINT(inputOutputType), C.SQLSMALLINT(valueType), C.SQLSMALLINT(parameterType), C.SQLULEN(columnSize), C.SQLSMALLINT(decimalDigits), C.SQLPOINTER(parameterValue), C.SQLLEN(bufferLength), (*C.SQLLEN)(ind)) + return SQLRETURN(r) +} + +func SQLCloseCursor(statementHandle SQLHSTMT) (ret SQLRETURN) { + r := C.SQLCloseCursor(C.SQLHSTMT(statementHandle)) + return SQLRETURN(r) +} + +func SQLDescribeCol(statementHandle SQLHSTMT, columnNumber SQLUSMALLINT, columnName *SQLWCHAR, bufferLength SQLSMALLINT, nameLengthPtr *SQLSMALLINT, dataTypePtr *SQLSMALLINT, columnSizePtr *SQLULEN, decimalDigitsPtr *SQLSMALLINT, nullablePtr *SQLSMALLINT) (ret SQLRETURN) { + r := C.SQLDescribeColW(C.SQLHSTMT(statementHandle), C.SQLUSMALLINT(columnNumber), (*C.SQLWCHAR)(unsafe.Pointer(columnName)), C.SQLSMALLINT(bufferLength), (*C.SQLSMALLINT)(nameLengthPtr), (*C.SQLSMALLINT)(dataTypePtr), (*C.SQLULEN)(columnSizePtr), (*C.SQLSMALLINT)(decimalDigitsPtr), (*C.SQLSMALLINT)(nullablePtr)) + return SQLRETURN(r) +} + +func SQLDescribeParam(statementHandle SQLHSTMT, parameterNumber SQLUSMALLINT, dataTypePtr *SQLSMALLINT, parameterSizePtr *SQLULEN, decimalDigitsPtr *SQLSMALLINT, nullablePtr *SQLSMALLINT) (ret SQLRETURN) { + r := C.SQLDescribeParam(C.SQLHSTMT(statementHandle), C.SQLUSMALLINT(parameterNumber), (*C.SQLSMALLINT)(dataTypePtr), (*C.SQLULEN)(parameterSizePtr), (*C.SQLSMALLINT)(decimalDigitsPtr), (*C.SQLSMALLINT)(nullablePtr)) + return SQLRETURN(r) +} + +func SQLDisconnect(connectionHandle SQLHDBC) (ret SQLRETURN) { + r := C.SQLDisconnect(C.SQLHDBC(connectionHandle)) + return SQLRETURN(r) +} + +func SQLDriverConnect(connectionHandle SQLHDBC, windowHandle SQLHWND, inConnectionString *SQLWCHAR, stringLength1 SQLSMALLINT, outConnectionString *SQLWCHAR, bufferLength SQLSMALLINT, stringLength2Ptr *SQLSMALLINT, driverCompletion SQLUSMALLINT) (ret SQLRETURN) { + r := C.SQLDriverConnectW(C.SQLHDBC(connectionHandle), C.SQLHWND(windowHandle), (*C.SQLWCHAR)(unsafe.Pointer(inConnectionString)), C.SQLSMALLINT(stringLength1), (*C.SQLWCHAR)(unsafe.Pointer(outConnectionString)), C.SQLSMALLINT(bufferLength), (*C.SQLSMALLINT)(stringLength2Ptr), C.SQLUSMALLINT(driverCompletion)) + return SQLRETURN(r) +} + +func SQLEndTran(handleType SQLSMALLINT, handle SQLHANDLE, completionType SQLSMALLINT) (ret SQLRETURN) { + r := C.SQLEndTran(C.SQLSMALLINT(handleType), C.SQLHANDLE(handle), C.SQLSMALLINT(completionType)) + return SQLRETURN(r) +} + +func SQLExecute(statementHandle SQLHSTMT) (ret SQLRETURN) { + r := C.SQLExecute(C.SQLHSTMT(statementHandle)) + return SQLRETURN(r) +} + +func SQLFetch(statementHandle SQLHSTMT) (ret SQLRETURN) { + r := C.SQLFetch(C.SQLHSTMT(statementHandle)) + return SQLRETURN(r) +} + +func SQLFreeHandle(handleType SQLSMALLINT, handle SQLHANDLE) (ret SQLRETURN) { + r := C.SQLFreeHandle(C.SQLSMALLINT(handleType), C.SQLHANDLE(handle)) + return SQLRETURN(r) +} + +func SQLGetData(statementHandle SQLHSTMT, colOrParamNum SQLUSMALLINT, targetType SQLSMALLINT, targetValuePtr SQLPOINTER, bufferLength SQLLEN, vallen *SQLLEN) (ret SQLRETURN) { + r := C.SQLGetData(C.SQLHSTMT(statementHandle), C.SQLUSMALLINT(colOrParamNum), C.SQLSMALLINT(targetType), C.SQLPOINTER(targetValuePtr), C.SQLLEN(bufferLength), (*C.SQLLEN)(vallen)) + return SQLRETURN(r) +} + +func SQLGetDiagRec(handleType SQLSMALLINT, handle SQLHANDLE, recNumber SQLSMALLINT, sqlState *SQLWCHAR, nativeErrorPtr *SQLINTEGER, messageText *SQLWCHAR, bufferLength SQLSMALLINT, textLengthPtr *SQLSMALLINT) (ret SQLRETURN) { + r := C.SQLGetDiagRecW(C.SQLSMALLINT(handleType), C.SQLHANDLE(handle), C.SQLSMALLINT(recNumber), (*C.SQLWCHAR)(unsafe.Pointer(sqlState)), (*C.SQLINTEGER)(nativeErrorPtr), (*C.SQLWCHAR)(unsafe.Pointer(messageText)), C.SQLSMALLINT(bufferLength), (*C.SQLSMALLINT)(textLengthPtr)) + return SQLRETURN(r) +} + +func SQLNumParams(statementHandle SQLHSTMT, parameterCountPtr *SQLSMALLINT) (ret SQLRETURN) { + r := C.SQLNumParams(C.SQLHSTMT(statementHandle), (*C.SQLSMALLINT)(parameterCountPtr)) + return SQLRETURN(r) +} + +func SQLNumResultCols(statementHandle SQLHSTMT, columnCountPtr *SQLSMALLINT) (ret SQLRETURN) { + r := C.SQLNumResultCols(C.SQLHSTMT(statementHandle), (*C.SQLSMALLINT)(columnCountPtr)) + return SQLRETURN(r) +} + +func SQLPrepare(statementHandle SQLHSTMT, statementText *SQLWCHAR, textLength SQLINTEGER) (ret SQLRETURN) { + r := C.SQLPrepareW(C.SQLHSTMT(statementHandle), (*C.SQLWCHAR)(unsafe.Pointer(statementText)), C.SQLINTEGER(textLength)) + return SQLRETURN(r) +} + +func SQLRowCount(statementHandle SQLHSTMT, rowCountPtr *SQLLEN) (ret SQLRETURN) { + r := C.SQLRowCount(C.SQLHSTMT(statementHandle), (*C.SQLLEN)(rowCountPtr)) + return SQLRETURN(r) +} + +func SQLSetEnvAttr(environmentHandle SQLHENV, attribute SQLINTEGER, valuePtr SQLPOINTER, stringLength SQLINTEGER) (ret SQLRETURN) { + r := C.SQLSetEnvAttr(C.SQLHENV(environmentHandle), C.SQLINTEGER(attribute), C.SQLPOINTER(valuePtr), C.SQLINTEGER(stringLength)) + return SQLRETURN(r) +} + +func SQLSetConnectAttr(connectionHandle SQLHDBC, attribute SQLINTEGER, valuePtr SQLPOINTER, stringLength SQLINTEGER) (ret SQLRETURN) { + r := C.SQLSetConnectAttrW(C.SQLHDBC(connectionHandle), C.SQLINTEGER(attribute), C.SQLPOINTER(valuePtr), C.SQLINTEGER(stringLength)) + return SQLRETURN(r) +} diff --git a/src/github.com/ibmdb/go_ibm_db/api/zapi_windows.go b/src/github.com/ibmdb/go_ibm_db/api/zapi_windows.go new file mode 100644 index 0000000..690af91 --- /dev/null +++ b/src/github.com/ibmdb/go_ibm_db/api/zapi_windows.go @@ -0,0 +1,161 @@ +// mksyscall_windows.pl api.go +// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT + +package api + +import "unsafe" +import "syscall" +import "os" + +var ( + mododbc32 = syscall.NewLazyDLL(GetDllName()) + + procSQLAllocHandle = mododbc32.NewProc("SQLAllocHandle") + procSQLBindCol = mododbc32.NewProc("SQLBindCol") + procSQLBindParameter = mododbc32.NewProc("SQLBindParameter") + procSQLCloseCursor = mododbc32.NewProc("SQLCloseCursor") + procSQLDescribeColW = mododbc32.NewProc("SQLDescribeColW") + procSQLDescribeParam = mododbc32.NewProc("SQLDescribeParam") + procSQLDisconnect = mododbc32.NewProc("SQLDisconnect") + procSQLDriverConnectW = mododbc32.NewProc("SQLDriverConnectW") + procSQLEndTran = mododbc32.NewProc("SQLEndTran") + procSQLExecute = mododbc32.NewProc("SQLExecute") + procSQLFetch = mododbc32.NewProc("SQLFetch") + procSQLFreeHandle = mododbc32.NewProc("SQLFreeHandle") + procSQLGetData = mododbc32.NewProc("SQLGetData") + procSQLGetDiagRecW = mododbc32.NewProc("SQLGetDiagRecW") + procSQLNumParams = mododbc32.NewProc("SQLNumParams") + procSQLNumResultCols = mododbc32.NewProc("SQLNumResultCols") + procSQLPrepareW = mododbc32.NewProc("SQLPrepareW") + procSQLRowCount = mododbc32.NewProc("SQLRowCount") + procSQLSetEnvAttr = mododbc32.NewProc("SQLSetEnvAttr") + procSQLSetConnectAttrW = mododbc32.NewProc("SQLSetConnectAttrW") +) + +func GetDllName() string { + if winArch := os.Getenv("PROCESSOR_ARCHITECTURE"); winArch == "x86" { + return "db2cli.dll" + } else { + return "db2cli64.dll" + } +} + +func SQLAllocHandle(handleType SQLSMALLINT, inputHandle SQLHANDLE, outputHandle *SQLHANDLE) (ret SQLRETURN) { + r0, _, _ := syscall.Syscall(procSQLAllocHandle.Addr(), 3, uintptr(handleType), uintptr(inputHandle), uintptr(unsafe.Pointer(outputHandle))) + ret = SQLRETURN(r0) + return +} + +func SQLBindCol(statementHandle SQLHSTMT, columnNumber SQLUSMALLINT, targetType SQLSMALLINT, targetValuePtr []byte, bufferLength SQLLEN, vallen *SQLLEN) (ret SQLRETURN) { + r0, _, _ := syscall.Syscall6(procSQLBindCol.Addr(), 6, uintptr(statementHandle), uintptr(columnNumber), uintptr(targetType), uintptr(unsafe.Pointer(&targetValuePtr[0])), uintptr(bufferLength), uintptr(unsafe.Pointer(vallen))) + ret = SQLRETURN(r0) + return +} + +func SQLBindParameter(statementHandle SQLHSTMT, parameterNumber SQLUSMALLINT, inputOutputType SQLSMALLINT, valueType SQLSMALLINT, parameterType SQLSMALLINT, columnSize SQLULEN, decimalDigits SQLSMALLINT, parameterValue SQLPOINTER, bufferLength SQLLEN, ind *SQLLEN) (ret SQLRETURN) { + r0, _, _ := syscall.Syscall12(procSQLBindParameter.Addr(), 10, uintptr(statementHandle), uintptr(parameterNumber), uintptr(inputOutputType), uintptr(valueType), uintptr(parameterType), uintptr(columnSize), uintptr(decimalDigits), uintptr(parameterValue), uintptr(bufferLength), uintptr(unsafe.Pointer(ind)), 0, 0) + ret = SQLRETURN(r0) + return +} + +func SQLCloseCursor(statementHandle SQLHSTMT) (ret SQLRETURN) { + r0, _, _ := syscall.Syscall(procSQLCloseCursor.Addr(), 1, uintptr(statementHandle), 0, 0) + ret = SQLRETURN(r0) + return +} + +func SQLDescribeCol(statementHandle SQLHSTMT, columnNumber SQLUSMALLINT, columnName *SQLWCHAR, bufferLength SQLSMALLINT, nameLengthPtr *SQLSMALLINT, dataTypePtr *SQLSMALLINT, columnSizePtr *SQLULEN, decimalDigitsPtr *SQLSMALLINT, nullablePtr *SQLSMALLINT) (ret SQLRETURN) { + r0, _, _ := syscall.Syscall9(procSQLDescribeColW.Addr(), 9, uintptr(statementHandle), uintptr(columnNumber), uintptr(unsafe.Pointer(columnName)), uintptr(bufferLength), uintptr(unsafe.Pointer(nameLengthPtr)), uintptr(unsafe.Pointer(dataTypePtr)), uintptr(unsafe.Pointer(columnSizePtr)), uintptr(unsafe.Pointer(decimalDigitsPtr)), uintptr(unsafe.Pointer(nullablePtr))) + ret = SQLRETURN(r0) + return +} + +func SQLDescribeParam(statementHandle SQLHSTMT, parameterNumber SQLUSMALLINT, dataTypePtr *SQLSMALLINT, parameterSizePtr *SQLULEN, decimalDigitsPtr *SQLSMALLINT, nullablePtr *SQLSMALLINT) (ret SQLRETURN) { + r0, _, _ := syscall.Syscall6(procSQLDescribeParam.Addr(), 6, uintptr(statementHandle), uintptr(parameterNumber), uintptr(unsafe.Pointer(dataTypePtr)), uintptr(unsafe.Pointer(parameterSizePtr)), uintptr(unsafe.Pointer(decimalDigitsPtr)), uintptr(unsafe.Pointer(nullablePtr))) + ret = SQLRETURN(r0) + return +} + +func SQLDisconnect(connectionHandle SQLHDBC) (ret SQLRETURN) { + r0, _, _ := syscall.Syscall(procSQLDisconnect.Addr(), 1, uintptr(connectionHandle), 0, 0) + ret = SQLRETURN(r0) + return +} + +func SQLDriverConnect(connectionHandle SQLHDBC, windowHandle SQLHWND, inConnectionString *SQLWCHAR, stringLength1 SQLSMALLINT, outConnectionString *SQLWCHAR, bufferLength SQLSMALLINT, stringLength2Ptr *SQLSMALLINT, driverCompletion SQLUSMALLINT) (ret SQLRETURN) { + r0, _, _ := syscall.Syscall9(procSQLDriverConnectW.Addr(), 8, uintptr(connectionHandle), uintptr(windowHandle), uintptr(unsafe.Pointer(inConnectionString)), uintptr(stringLength1), uintptr(unsafe.Pointer(outConnectionString)), uintptr(bufferLength), uintptr(unsafe.Pointer(stringLength2Ptr)), uintptr(driverCompletion), 0) + ret = SQLRETURN(r0) + return +} + +func SQLEndTran(handleType SQLSMALLINT, handle SQLHANDLE, completionType SQLSMALLINT) (ret SQLRETURN) { + r0, _, _ := syscall.Syscall(procSQLEndTran.Addr(), 3, uintptr(handleType), uintptr(handle), uintptr(completionType)) + ret = SQLRETURN(r0) + return +} + +func SQLExecute(statementHandle SQLHSTMT) (ret SQLRETURN) { + r0, _, _ := syscall.Syscall(procSQLExecute.Addr(), 1, uintptr(statementHandle), 0, 0) + ret = SQLRETURN(r0) + return +} + +func SQLFetch(statementHandle SQLHSTMT) (ret SQLRETURN) { + r0, _, _ := syscall.Syscall(procSQLFetch.Addr(), 1, uintptr(statementHandle), 0, 0) + ret = SQLRETURN(r0) + return +} + +func SQLFreeHandle(handleType SQLSMALLINT, handle SQLHANDLE) (ret SQLRETURN) { + r0, _, _ := syscall.Syscall(procSQLFreeHandle.Addr(), 2, uintptr(handleType), uintptr(handle), 0) + ret = SQLRETURN(r0) + return +} + +func SQLGetData(statementHandle SQLHSTMT, colOrParamNum SQLUSMALLINT, targetType SQLSMALLINT, targetValuePtr SQLPOINTER, bufferLength SQLLEN, vallen *SQLLEN) (ret SQLRETURN) { + r0, _, _ := syscall.Syscall6(procSQLGetData.Addr(), 6, uintptr(statementHandle), uintptr(colOrParamNum), uintptr(targetType), uintptr(targetValuePtr), uintptr(bufferLength), uintptr(unsafe.Pointer(vallen))) + ret = SQLRETURN(r0) + return +} + +func SQLGetDiagRec(handleType SQLSMALLINT, handle SQLHANDLE, recNumber SQLSMALLINT, sqlState *SQLWCHAR, nativeErrorPtr *SQLINTEGER, messageText *SQLWCHAR, bufferLength SQLSMALLINT, textLengthPtr *SQLSMALLINT) (ret SQLRETURN) { + r0, _, _ := syscall.Syscall9(procSQLGetDiagRecW.Addr(), 8, uintptr(handleType), uintptr(handle), uintptr(recNumber), uintptr(unsafe.Pointer(sqlState)), uintptr(unsafe.Pointer(nativeErrorPtr)), uintptr(unsafe.Pointer(messageText)), uintptr(bufferLength), uintptr(unsafe.Pointer(textLengthPtr)), 0) + ret = SQLRETURN(r0) + return +} + +func SQLNumParams(statementHandle SQLHSTMT, parameterCountPtr *SQLSMALLINT) (ret SQLRETURN) { + r0, _, _ := syscall.Syscall(procSQLNumParams.Addr(), 2, uintptr(statementHandle), uintptr(unsafe.Pointer(parameterCountPtr)), 0) + ret = SQLRETURN(r0) + return +} + +func SQLNumResultCols(statementHandle SQLHSTMT, columnCountPtr *SQLSMALLINT) (ret SQLRETURN) { + r0, _, _ := syscall.Syscall(procSQLNumResultCols.Addr(), 2, uintptr(statementHandle), uintptr(unsafe.Pointer(columnCountPtr)), 0) + ret = SQLRETURN(r0) + return +} + +func SQLPrepare(statementHandle SQLHSTMT, statementText *SQLWCHAR, textLength SQLINTEGER) (ret SQLRETURN) { + r0, _, _ := syscall.Syscall(procSQLPrepareW.Addr(), 3, uintptr(statementHandle), uintptr(unsafe.Pointer(statementText)), uintptr(textLength)) + ret = SQLRETURN(r0) + return +} + +func SQLRowCount(statementHandle SQLHSTMT, rowCountPtr *SQLLEN) (ret SQLRETURN) { + r0, _, _ := syscall.Syscall(procSQLRowCount.Addr(), 2, uintptr(statementHandle), uintptr(unsafe.Pointer(rowCountPtr)), 0) + ret = SQLRETURN(r0) + return +} + +func SQLSetEnvAttr(environmentHandle SQLHENV, attribute SQLINTEGER, valuePtr SQLPOINTER, stringLength SQLINTEGER) (ret SQLRETURN) { + r0, _, _ := syscall.Syscall6(procSQLSetEnvAttr.Addr(), 4, uintptr(environmentHandle), uintptr(attribute), uintptr(valuePtr), uintptr(stringLength), 0, 0) + ret = SQLRETURN(r0) + return +} + +func SQLSetConnectAttr(connectionHandle SQLHDBC, attribute SQLINTEGER, valuePtr SQLPOINTER, stringLength SQLINTEGER) (ret SQLRETURN) { + r0, _, _ := syscall.Syscall6(procSQLSetConnectAttrW.Addr(), 4, uintptr(connectionHandle), uintptr(attribute), uintptr(valuePtr), uintptr(stringLength), 0, 0) + ret = SQLRETURN(r0) + return +} diff --git a/src/github.com/ibmdb/go_ibm_db/column.go b/src/github.com/ibmdb/go_ibm_db/column.go new file mode 100644 index 0000000..cb1804d --- /dev/null +++ b/src/github.com/ibmdb/go_ibm_db/column.go @@ -0,0 +1,279 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package go_ibm_db + +import ( + "github.com/ibmdb/go_ibm_db/api" + "database/sql/driver" + "errors" + "fmt" + "time" + "unsafe" +) + +type BufferLen api.SQLLEN + +func (l *BufferLen) IsNull() bool { + return *l == api.SQL_NULL_DATA +} + +func (l *BufferLen) GetData(h api.SQLHSTMT, idx int, ctype api.SQLSMALLINT, buf []byte) api.SQLRETURN { + return api.SQLGetData(h, api.SQLUSMALLINT(idx+1), ctype, + api.SQLPOINTER(unsafe.Pointer(&buf[0])), api.SQLLEN(len(buf)), + (*api.SQLLEN)(l)) +} + +func (l *BufferLen) Bind(h api.SQLHSTMT, idx int, ctype api.SQLSMALLINT, buf []byte) api.SQLRETURN { + return api.SQLBindCol(h, api.SQLUSMALLINT(idx+1), ctype, buf, api.SQLLEN(len(buf)),(*api.SQLLEN)(l)) +} + +// Column provides access to row columns. +type Column interface { + Name() string + Bind(h api.SQLHSTMT, idx int) (bool, error) + Value(h api.SQLHSTMT, idx int) (driver.Value, error) +} + +func describeColumn(h api.SQLHSTMT, idx int, namebuf []uint16) (namelen int, sqltype api.SQLSMALLINT, size api.SQLULEN, ret api.SQLRETURN) { + var l, decimal, nullable api.SQLSMALLINT + ret = api.SQLDescribeCol(h, api.SQLUSMALLINT(idx+1), + (*api.SQLWCHAR)(unsafe.Pointer(&namebuf[0])), + api.SQLSMALLINT(len(namebuf)), &l, + &sqltype, &size, &decimal, &nullable) + return int(l), sqltype, size, ret +} + +// TODO(brainman): did not check for MS SQL timestamp + +func NewColumn(h api.SQLHSTMT, idx int) (Column, error) { + namebuf := make([]uint16, 150) + namelen, sqltype, size, ret := describeColumn(h, idx, namebuf) + if ret == api.SQL_SUCCESS_WITH_INFO && namelen > len(namebuf) { + // try again with bigger buffer + namebuf = make([]uint16, namelen) + namelen, sqltype, size, ret = describeColumn(h, idx, namebuf) + } + if IsError(ret) { + return nil, NewError("SQLDescribeCol", h) + } + if namelen > len(namebuf) { + // still complaining about buffer size + return nil, errors.New("Failed to allocate column name buffer") + } + b := &BaseColumn{ + name: api.UTF16ToString(namebuf[:namelen]), + } + switch sqltype { + case api.SQL_BIT: + return NewBindableColumn(b, api.SQL_C_BIT, 1), nil + case api.SQL_TINYINT, api.SQL_SMALLINT, api.SQL_INTEGER: + return NewBindableColumn(b, api.SQL_C_LONG, 4), nil + case api.SQL_BIGINT: + return NewBindableColumn(b, api.SQL_C_SBIGINT, 8), nil + case api.SQL_NUMERIC, api.SQL_DECIMAL, api.SQL_FLOAT, api.SQL_REAL, api.SQL_DOUBLE: + return NewBindableColumn(b, api.SQL_C_DOUBLE, 8), nil + case api.SQL_TYPE_TIMESTAMP: + var v api.SQL_TIMESTAMP_STRUCT + return NewBindableColumn(b, api.SQL_C_TYPE_TIMESTAMP, int(unsafe.Sizeof(v))), nil + case api.SQL_TYPE_DATE: + var v api.SQL_DATE_STRUCT + return NewBindableColumn(b, api.SQL_C_DATE, int(unsafe.Sizeof(v))), nil + case api.SQL_CHAR, api.SQL_VARCHAR: + return NewVariableWidthColumn(b, api.SQL_C_CHAR, size), nil + case api.SQL_WCHAR, api.SQL_WVARCHAR: + return NewVariableWidthColumn(b, api.SQL_C_WCHAR, size), nil + case api.SQL_BINARY, api.SQL_VARBINARY: + return NewVariableWidthColumn(b, api.SQL_C_BINARY, size), nil + case api.SQL_LONGVARCHAR: + return NewVariableWidthColumn(b, api.SQL_C_CHAR, 0), nil + case api.SQL_WLONGVARCHAR, api.SQL_SS_XML: + return NewVariableWidthColumn(b, api.SQL_C_WCHAR, 0), nil + case api.SQL_LONGVARBINARY: + return NewVariableWidthColumn(b, api.SQL_C_BINARY, 0), nil + default: + return nil, fmt.Errorf("unsupported column type %d", sqltype) + } + panic("unreachable") +} + +// BaseColumn implements common column functionality. +type BaseColumn struct { + name string + CType api.SQLSMALLINT +} + +func (c *BaseColumn) Name() string { + return c.name +} + +func (c *BaseColumn) Value(buf []byte) (driver.Value, error) { + var p unsafe.Pointer + if len(buf) > 0 { + p = unsafe.Pointer(&buf[0]) + } + switch c.CType { + case api.SQL_C_BIT: + return buf[0] != 0, nil + case api.SQL_C_LONG: + return *((*int32)(p)), nil + case api.SQL_C_SBIGINT: + return *((*int64)(p)), nil + case api.SQL_C_DOUBLE: + return *((*float64)(p)), nil + case api.SQL_C_CHAR: + return buf, nil + case api.SQL_C_WCHAR: + if p == nil { + return nil, nil + } + s := (*[1 << 20]uint16)(p)[:len(buf)/2] + return utf16toutf8(s), nil + case api.SQL_C_TYPE_TIMESTAMP: + t := (*api.SQL_TIMESTAMP_STRUCT)(p) + r := time.Date(int(t.Year), time.Month(t.Month), int(t.Day), + int(t.Hour), int(t.Minute), int(t.Second), int(t.Fraction), + time.Local) + return r, nil + case api.SQL_C_DATE: + t := (*api.SQL_DATE_STRUCT)(p) + r := time.Date(int(t.Year), time.Month(t.Month), int(t.Day), + 0, 0, 0, 0, time.Local) + return r, nil + case api.SQL_C_BINARY: + return buf, nil + } + return nil, fmt.Errorf("unsupported column ctype %d", c.CType) +} + +// BindableColumn allows access to columns that can have their buffers +// bound. Once bound at start, they are written to by odbc driver every +// time it fetches new row. This saves on syscall and, perhaps, some +// buffer copying. BindableColumn can be left unbound, then it behaves +// like NonBindableColumn when user reads data from it. +type BindableColumn struct { + *BaseColumn + IsBound bool + IsVariableWidth bool + Size int + Len BufferLen + Buffer []byte + smallBuf [8]byte // small inline memory buffer, so we do not need allocate external memory all the time +} + +func NewBindableColumn(b *BaseColumn, ctype api.SQLSMALLINT, bufSize int) *BindableColumn { + b.CType = ctype + c := &BindableColumn{BaseColumn: b, Size: bufSize} + if c.Size <= len(c.smallBuf) { + // use inline buffer + c.Buffer = c.smallBuf[:c.Size] + } else { + c.Buffer = make([]byte, c.Size) + } + return c +} + +func NewVariableWidthColumn(b *BaseColumn, ctype api.SQLSMALLINT, colWidth api.SQLULEN) Column { + if colWidth == 0 { + b.CType = ctype + return &NonBindableColumn{b} + } + l := int(colWidth) + switch ctype { + case api.SQL_C_WCHAR: + l += 1 // room for null-termination character + l *= 2 // wchars take 2 bytes each + case api.SQL_C_CHAR: + l += 1 // room for null-termination character + case api.SQL_C_BINARY: + // nothing to do + default: + panic(fmt.Errorf("do not know how wide column of ctype %d is", ctype)) + } + c := NewBindableColumn(b, ctype, l) + c.IsVariableWidth = true + return c +} + +func (c *BindableColumn) Bind(h api.SQLHSTMT, idx int) (bool, error) { + ret := c.Len.Bind(h, idx, c.CType, c.Buffer) + if IsError(ret) { + return false, NewError("SQLBindCol", h) + } + c.IsBound = true + return true, nil +} + +func (c *BindableColumn) Value(h api.SQLHSTMT, idx int) (driver.Value, error) { + if !c.IsBound { + ret := c.Len.GetData(h, idx, c.CType, c.Buffer) + if IsError(ret) { + return nil, NewError("SQLGetData", h) + } + } + if c.Len.IsNull() { + // is NULL + return nil, nil + } + if !c.IsVariableWidth && int(c.Len) != c.Size { + panic(fmt.Errorf("wrong column #%d length %d returned, %d expected", idx, c.Len, c.Size)) + } + return c.BaseColumn.Value(c.Buffer[:c.Len]) +} + +// NonBindableColumn provide access to columns, that can't be bound. +// These are of character or binary type, and, usually, there is no +// limit for their width. +type NonBindableColumn struct { + *BaseColumn +} + +func (c *NonBindableColumn) Bind(h api.SQLHSTMT, idx int) (bool, error) { + return false, nil +} + +func (c *NonBindableColumn) Value(h api.SQLHSTMT, idx int) (driver.Value, error) { + var l BufferLen + var total []byte + b := make([]byte, 1024) +loop: + for { + ret := l.GetData(h, idx, c.CType, b) + switch ret { + case api.SQL_SUCCESS: + if l.IsNull() { + // is NULL + return nil, nil + } + total = append(total, b[:l]...) + break loop + case api.SQL_SUCCESS_WITH_INFO: + err := NewError("SQLGetData", h).(*Error) + if len(err.Diag) > 0 && err.Diag[0].State != "01004" { + return nil, err + } + i := len(b) + switch c.CType { + case api.SQL_C_WCHAR: + i -= 2 // remove wchar (2 bytes) null-termination character + case api.SQL_C_CHAR: + i-- // remove null-termination character + } + total = append(total, b[:i]...) + if l != api.SQL_NO_TOTAL { + // odbc gives us a hint about remaining data, + // lets get it in one go. + n := int(l) // total bytes for our data + n -= i // subtract already received + n += 2 // room for biggest (wchar) null-terminator + if len(b) < n { + b = make([]byte, n) + } + } + default: + return nil, NewError("SQLGetData", h) + } + } + return c.BaseColumn.Value(total) +} diff --git a/src/github.com/ibmdb/go_ibm_db/conn.go b/src/github.com/ibmdb/go_ibm_db/conn.go new file mode 100644 index 0000000..ef4a2e3 --- /dev/null +++ b/src/github.com/ibmdb/go_ibm_db/conn.go @@ -0,0 +1,47 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package go_ibm_db + +import ( + "database/sql/driver" + "unsafe" + + "github.com/ibmdb/go_ibm_db/api" +) + +type Conn struct { + h api.SQLHDBC + tx *Tx +} + +func (d *Driver) Open(dsn string) (driver.Conn, error) { + var out api.SQLHANDLE + ret := api.SQLAllocHandle(api.SQL_HANDLE_DBC, api.SQLHANDLE(d.h), &out) + if IsError(ret) { + return nil, NewError("SQLAllocHandle", d.h) + } + h := api.SQLHDBC(out) + drv.Stats.updateHandleCount(api.SQL_HANDLE_DBC, 1) + + b := api.StringToUTF16(dsn) + ret = api.SQLDriverConnect(h, 0, + (*api.SQLWCHAR)(unsafe.Pointer(&b[0])), api.SQLSMALLINT(len(b)), + nil, 0, nil, api.SQL_DRIVER_NOPROMPT) + if IsError(ret) { + defer releaseHandle(h) + return nil, NewError("SQLDriverConnect", h) + } + return &Conn{h: h}, nil +} + +func (c *Conn) Close() error { + ret := api.SQLDisconnect(c.h) + if IsError(ret) { + return NewError("SQLDisconnect", c.h) + } + h := c.h + c.h = api.SQLHDBC(api.SQL_NULL_HDBC) + return releaseHandle(h) +} diff --git a/src/github.com/ibmdb/go_ibm_db/driver.go b/src/github.com/ibmdb/go_ibm_db/driver.go new file mode 100644 index 0000000..29304b1 --- /dev/null +++ b/src/github.com/ibmdb/go_ibm_db/driver.go @@ -0,0 +1,60 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package odbc implements database/sql driver to access data via odbc interface. +// +package go_ibm_db + +import ( + "database/sql" + + "github.com/ibmdb/go_ibm_db/api" +) + +var drv Driver + +type Driver struct { + Stats + h api.SQLHENV // environment handle +} + +func initDriver() error { + + //Allocate environment handle + var out api.SQLHANDLE + in := api.SQLHANDLE(api.SQL_NULL_HANDLE) + ret := api.SQLAllocHandle(api.SQL_HANDLE_ENV, in, &out) + if IsError(ret) { + return NewError("SQLAllocHandle", api.SQLHENV(in)) + } + drv.h = api.SQLHENV(out) + drv.Stats.updateHandleCount(api.SQL_HANDLE_ENV, 1) + + // will use ODBC v3 + ret = api.SQLSetEnvAttr(drv.h, api.SQL_ATTR_ODBC_VERSION, + api.SQLPOINTER(api.SQL_OV_ODBC3), 0) + if IsError(ret) { + defer releaseHandle(drv.h) + return NewError("SQLSetEnvAttr ODBC v3", drv.h) + } + + return nil +} + +func (d *Driver) Close() error { + // TODO(brainman): who will call (*Driver).Close (to dispose all opened handles)? + h := d.h + d.h = api.SQLHENV(api.SQL_NULL_HENV) + return releaseHandle(h) +} + +func init() { + err := initDriver() + if err != nil { + panic(err) + } + //go's to databse/sql/sql.go 43 line + sql.Register("go_ibm_db", &drv) + +} diff --git a/src/github.com/ibmdb/go_ibm_db/error.go b/src/github.com/ibmdb/go_ibm_db/error.go new file mode 100644 index 0000000..7c56133 --- /dev/null +++ b/src/github.com/ibmdb/go_ibm_db/error.go @@ -0,0 +1,72 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package go_ibm_db + +import ( + "github.com/ibmdb/go_ibm_db/api" + "database/sql/driver" + "fmt" + "strings" + "unsafe" +) + +func IsError(ret api.SQLRETURN) bool { + return !(ret == api.SQL_SUCCESS || ret == api.SQL_SUCCESS_WITH_INFO) +} + +type DiagRecord struct { + State string + NativeError int + Message string +} + +func (r *DiagRecord) String() string { + return fmt.Sprintf("{%s} %s", r.State, r.Message) +} + +type Error struct { + APIName string + Diag []DiagRecord +} + +func (e *Error) Error() string { + ss := make([]string, len(e.Diag)) + for i, r := range e.Diag { + ss[i] = r.String() + } + return e.APIName + ": " + strings.Join(ss, "\n") +} + +func NewError(apiName string, handle interface{}) error { + h, ht := ToHandleAndType(handle) + err := &Error{APIName: apiName} + var ne api.SQLINTEGER + state := make([]uint16, 6) + msg := make([]uint16, api.SQL_MAX_MESSAGE_LENGTH) + for i := 1; ; i++ { + ret := api.SQLGetDiagRec(ht, h, api.SQLSMALLINT(i), + (*api.SQLWCHAR)(unsafe.Pointer(&state[0])), &ne, + (*api.SQLWCHAR)(unsafe.Pointer(&msg[0])), + api.SQLSMALLINT(len(msg)), nil) + if ret == api.SQL_NO_DATA { + break + } + if IsError(ret) { + panic(fmt.Errorf("SQLGetDiagRec failed: ret=%d", ret)) + } + r := DiagRecord{ + State: api.UTF16ToString(state), + NativeError: int(ne), + Message: api.UTF16ToString(msg), + } + if strings.Contains(r.Message, "CLI0106E") || + strings.Contains(r.Message, "CLI0107E") || + strings.Contains(r.Message, "CLI0108E") { + return driver.ErrBadConn + } + err.Diag = append(err.Diag, r) + } + return err +} diff --git a/src/github.com/ibmdb/go_ibm_db/handle.go b/src/github.com/ibmdb/go_ibm_db/handle.go new file mode 100644 index 0000000..d763491 --- /dev/null +++ b/src/github.com/ibmdb/go_ibm_db/handle.go @@ -0,0 +1,44 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package go_ibm_db + +import ( + "github.com/ibmdb/go_ibm_db/api" + "fmt" +) + +func ToHandleAndType(handle interface{}) (h api.SQLHANDLE, ht api.SQLSMALLINT) { + switch v := handle.(type) { + case api.SQLHENV: + if v == api.SQLHENV(api.SQL_NULL_HANDLE) { + ht = 0 + } else { + ht = api.SQL_HANDLE_ENV + } + h = api.SQLHANDLE(v) + case api.SQLHDBC: + ht = api.SQL_HANDLE_DBC + h = api.SQLHANDLE(v) + case api.SQLHSTMT: + ht = api.SQL_HANDLE_STMT + h = api.SQLHANDLE(v) + default: + panic(fmt.Errorf("unexpected handle type %T", v)) + } + return h, ht +} + +func releaseHandle(handle interface{}) error { + h, ht := ToHandleAndType(handle) + ret := api.SQLFreeHandle(ht, h) + if ret == api.SQL_INVALID_HANDLE { + return fmt.Errorf("SQLFreeHandle(%d, %d) returns SQL_INVALID_HANDLE", ht, h) + } + if IsError(ret) { + return NewError("SQLFreeHandle", handle) + } + drv.Stats.updateHandleCount(ht, -1) + return nil +} diff --git a/src/github.com/ibmdb/go_ibm_db/installer/setup.go b/src/github.com/ibmdb/go_ibm_db/installer/setup.go new file mode 100644 index 0000000..bc093dc --- /dev/null +++ b/src/github.com/ibmdb/go_ibm_db/installer/setup.go @@ -0,0 +1,184 @@ +package main + +import ( + "archive/zip" + "fmt" + "io" + "net/http" + "os" + "os/exec" + "path/filepath" + "runtime" + "strings" +) + +func downloadFile(filepath string, url string) error { + out, err := os.Create(filepath) + if err != nil { + return err + } + defer out.Close() + resp, err := http.Get(url) + if err != nil { + return err + } + defer resp.Body.Close() + _, err = io.Copy(out, resp.Body) + if err != nil { + return err + } + return nil +} + +func unzipping(sourcefile string) { + reader, err := zip.OpenReader(sourcefile) + if err != nil { + fmt.Println(err) + os.Exit(1) + } + defer reader.Close() + for _, f := range reader.Reader.File { + zipped, err := f.Open() + if err != nil { + fmt.Println(err) + os.Exit(1) + } + defer zipped.Close() + path := filepath.Join("./", f.Name) + if f.FileInfo().IsDir() { + os.MkdirAll(path, f.Mode()) + fmt.Println("Creating directory", path) + } else { + writer, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE, f.Mode()) + if err != nil { + fmt.Println(err) + os.Exit(1) + } + defer writer.Close() + if _, err = io.Copy(writer, zipped); err != nil { + fmt.Println(err) + os.Exit(1) + } + fmt.Println("Unzipping : ", path) + } + } +} + +func linux_untar(clidriver string) { + out, _ := exec.Command("tar", "xvzf", clidriver).Output() + fmt.Println(string(out[:])) +} + +func main() { + var cliFileName string + var url string + var i int + _, a := os.LookupEnv("IBM_DB_DIR") + _, b := os.LookupEnv("IBM_DB_HOME") + _, c := os.LookupEnv("IBM_DB_LIB") + out, _ := exec.Command("go", "env", "GOPATH").Output() + str := strings.TrimSpace(string(out)) + path := filepath.Join(str, "/src/github.com/ibmdb/go_ibm_db/installer/clidriver") + if !(a && b && c) { + if _, err := os.Stat(path); os.IsNotExist(err) { + if runtime.GOOS == "windows" { + i = 1 + const wordsize = 32 << (^uint(0) >> 32 & 1) + if wordsize == 64 { + cliFileName = "ntx64_odbc_cli.zip" + } else { + cliFileName = "nt32_odbc_cli.zip" + } + fmt.Printf("windows\n") + fmt.Println(cliFileName) + } else if runtime.GOOS == "linux" { + i = 2 + if runtime.GOARCH == "ppc64le" { + const wordsize = 32 << (^uint(0) >> 32 & 1) + if wordsize == 64 { + cliFileName = "ppc64le_odbc_cli.tar.gz" + } + } else if runtime.GOARCH == "ppc" { + const wordsize = 32 << (^uint(0) >> 32 & 1) + if wordsize == 64 { + cliFileName = "ppc64_odbc_cli.tar.gz" + } else { + cliFileName = "ppc32_odbc_cli.tar.gz" + } + } else if runtime.GOARCH == "amd64" { + const wordsize = 32 << (^uint(0) >> 32 & 1) + if wordsize == 64 { + cliFileName = "linuxx64_odbc_cli.tar.gz" + } else { + cliFileName = "linuxia32_odbc_cli.tar.gz" + } + } else if runtime.GOARCH == "390" { + const wordsize = 32 << (^uint(0) >> 32 & 1) + if wordsize == 64 { + cliFileName = "s390x64_odbc_cli.tar.gz" + } else { + cliFileName = "s390_odbc_cli.tar.gz" + } + } + fmt.Printf("linux\n") + fmt.Println(cliFileName) + } else if runtime.GOOS == "aix" { + i = 2 + const wordsize = 32 << (^uint(0) >> 32 & 1) + if wordsize == 64 { + cliFileName = "aix64_odbc_cli.tar.gz" + } else { + cliFileName = "aix32_odbc_cli.tar.gz" + } + fmt.Printf("aix\n") + fmt.Printf(cliFileName) + } else if runtime.GOOS == "sunos" { + i = 2 + if runtime.GOARCH == "i86pc" { + const wordsize = 32 << (^uint(0) >> 32 & 1) + if wordsize == 64 { + cliFileName = "sunamd64_odbc_cli.tar.gz" + } else { + cliFileName = "sunamd32_odbc_cli.tar.gz" + } + } else if runtime.GOARCH == "SUNW" { + const wordsize = 32 << (^uint(0) >> 32 & 1) + if wordsize == 64 { + cliFileName = "sun64_odbc_cli.tar.gz" + } else { + cliFileName = "sun32_odbc_cli.tar.gz" + } + } + fmt.Printf("Sunos\n") + fmt.Printf(cliFileName) + } else if runtime.GOOS == "darwin" { + i = 2 + const wordsize = 32 << (^uint(0) >> 32 & 1) + if wordsize == 64 { + cliFileName = "macos64_odbc_cli.tar.gz" + } + fmt.Printf("darwin\n") + fmt.Printf(cliFileName) + } else { + fmt.Println("not a known platform") + os.Exit(1) + } + fileUrl := "https://public.dhe.ibm.com/ibmdl/export/pub/software/data/db2/drivers/odbc_cli/" + cliFileName + fmt.Println(url) + fmt.Println("Downloading...") + err := downloadFile(cliFileName, fileUrl) + if err != nil { + fmt.Println(err) + } else { + fmt.Println("download successful") + } + if i == 1 { + unzipping(cliFileName) + } else { + linux_untar(cliFileName) + } + } else { + fmt.Println("Clidriver Already exits in the directory") + } + } +} diff --git a/src/github.com/ibmdb/go_ibm_db/odbcstmt.go b/src/github.com/ibmdb/go_ibm_db/odbcstmt.go new file mode 100644 index 0000000..f75e26d --- /dev/null +++ b/src/github.com/ibmdb/go_ibm_db/odbcstmt.go @@ -0,0 +1,157 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package go_ibm_db + +import ( + "database/sql/driver" + "errors" + "fmt" + "sync" + "time" + "unsafe" + + "github.com/ibmdb/go_ibm_db/api" +) + +// TODO(brainman): see if I could use SQLExecDirect anywhere + +type ODBCStmt struct { + h api.SQLHSTMT + Parameters []Parameter + Cols []Column + // locking/lifetime + mu sync.Mutex + usedByStmt bool + usedByRows bool +} + +func (c *Conn) PrepareODBCStmt(query string) (*ODBCStmt, error) { + var out api.SQLHANDLE + ret := api.SQLAllocHandle(api.SQL_HANDLE_STMT, api.SQLHANDLE(c.h), &out) + if IsError(ret) { + return nil, NewError("SQLAllocHandle", c.h) + } + h := api.SQLHSTMT(out) + drv.Stats.updateHandleCount(api.SQL_HANDLE_STMT, 1) + + b := api.StringToUTF16(query) + ret = api.SQLPrepare(h, + (*api.SQLWCHAR)(unsafe.Pointer(&b[0])), api.SQLINTEGER(len(b))) + if IsError(ret) { + defer releaseHandle(h) + return nil, NewError("SQLPrepare", h) + } + ps, err := ExtractParameters(h) + if err != nil { + defer releaseHandle(h) + return nil, err + } + return &ODBCStmt{ + h: h, + Parameters: ps, + usedByStmt: true, + }, nil +} + +func (s *ODBCStmt) closeByStmt() error { + s.mu.Lock() + defer s.mu.Unlock() + if s.usedByStmt { + defer func() { s.usedByStmt = false }() + if !s.usedByRows { + return s.releaseHandle() + } + } + return nil +} + +func (s *ODBCStmt) closeByRows() error { + s.mu.Lock() + defer s.mu.Unlock() + if s.usedByRows { + defer func() { s.usedByRows = false }() + if s.usedByStmt { + ret := api.SQLCloseCursor(s.h) + if IsError(ret) { + return NewError("SQLCloseCursor", s.h) + } + return nil + } else { + return s.releaseHandle() + } + } + return nil +} + +func (s *ODBCStmt) releaseHandle() error { + h := s.h + s.h = api.SQLHSTMT(api.SQL_NULL_HSTMT) + return releaseHandle(h) +} + +var testingIssue5 bool // used during tests + +func (s *ODBCStmt) Exec(args []driver.Value) error { + + if len(args) != len(s.Parameters) { + return fmt.Errorf("wrong number of arguments %d, %d expected", len(args), len(s.Parameters)) + } + for i, a := range args { + // this could be done in 2 steps: + // 1) bind vars right after prepare; + // 2) set their (vars) values here; + // but rebinding parameters for every new parameter value + // should be efficient enough for our purpose. + s.Parameters[i].BindValue(s.h, i, a) + } + if testingIssue5 { + time.Sleep(10 * time.Microsecond) + } + ret := api.SQLExecute(s.h) + if ret == api.SQL_NO_DATA { + // success but no data to report + return nil + } + if IsError(ret) { + return NewError("SQLExecute", s.h) + } + return nil +} + +func (s *ODBCStmt) BindColumns() error { + // count columns + var n api.SQLSMALLINT + ret := api.SQLNumResultCols(s.h, &n) + if IsError(ret) { + return NewError("SQLNumResultCols", s.h) + } + if n < 1 { + return errors.New("Stmt did not create a result set") + } + // fetch column descriptions + s.Cols = make([]Column, n) + binding := true + for i := range s.Cols { + c, err := NewColumn(s.h, i) + if err != nil { + return err + } + s.Cols[i] = c + // Once we found one non-bindable column, we will not bind the rest. + // http://www.easysoft.com/developer/languages/c/odbc-tutorial-fetching-results.html + // ... One common restriction is that SQLGetData may only be called on columns after the last bound column. ... + if !binding { + continue + } + bound, err := s.Cols[i].Bind(s.h, i) + if err != nil { + return err + } + if !bound { + binding = false + } + } + return nil +} diff --git a/src/github.com/ibmdb/go_ibm_db/param.go b/src/github.com/ibmdb/go_ibm_db/param.go new file mode 100644 index 0000000..e1c23f8 --- /dev/null +++ b/src/github.com/ibmdb/go_ibm_db/param.go @@ -0,0 +1,165 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package go_ibm_db + +import ( + "github.com/ibmdb/go_ibm_db/api" + "database/sql/driver" + "fmt" + "time" + "unsafe" +) + +type Parameter struct { + SQLType api.SQLSMALLINT + Decimal api.SQLSMALLINT + Size api.SQLULEN + isDescribed bool + // Following fields store data used later by SQLExecute. + // The fields keep data alive and away from gc. + Data interface{} + StrLen_or_IndPtr api.SQLLEN +} + +// StoreStrLen_or_IndPtr stores v into StrLen_or_IndPtr field of p +// and returns address of that field. +func (p *Parameter) StoreStrLen_or_IndPtr(v api.SQLLEN) *api.SQLLEN { + p.StrLen_or_IndPtr = v + return &p.StrLen_or_IndPtr + +} + +func (p *Parameter) BindValue(h api.SQLHSTMT, idx int, v driver.Value) error { + // TODO(brainman): Reuse memory for previously bound values. If memory + // is reused, we, probably, do not need to call SQLBindParameter either. + var ctype, sqltype, decimal api.SQLSMALLINT + var size api.SQLULEN + var buflen api.SQLLEN + var plen *api.SQLLEN + var buf unsafe.Pointer + switch d := v.(type) { + case nil: + ctype = api.SQL_C_WCHAR + p.Data = nil + buf = nil + size = 1 + buflen = 0 + plen = p.StoreStrLen_or_IndPtr(api.SQL_NULL_DATA) + sqltype = api.SQL_WCHAR + case string: + ctype = api.SQL_C_WCHAR + b := api.StringToUTF16(d) + p.Data = b + buf = unsafe.Pointer(&b[0]) + l := len(b) + l -= 1 // remove terminating 0 + size = api.SQLULEN(l) + if size < 1 { + // size cannot be less then 1 even for empty fields + size = 1 + } + l *= 2 // every char takes 2 bytes + buflen = api.SQLLEN(l) + plen = p.StoreStrLen_or_IndPtr(buflen) + if p.isDescribed { + // only so we can handle very long (>4000 chars) parameters + sqltype = p.SQLType + } else { + sqltype = api.SQL_WCHAR + } + case int64: + ctype = api.SQL_C_SBIGINT + p.Data = &d + buf = unsafe.Pointer(&d) + sqltype = api.SQL_BIGINT + size = 8 + case bool: + var b byte + if d { + b = 1 + } + ctype = api.SQL_C_BIT + p.Data = &b + buf = unsafe.Pointer(&b) + sqltype = api.SQL_BIT + size = 1 + case float64: + ctype = api.SQL_C_DOUBLE + p.Data = &d + buf = unsafe.Pointer(&d) + sqltype = api.SQL_DOUBLE + size = 8 + case time.Time: + ctype = api.SQL_C_TYPE_TIMESTAMP + y, m, day := d.Date() + b := api.SQL_TIMESTAMP_STRUCT{ + Year: api.SQLSMALLINT(y), + Month: api.SQLUSMALLINT(m), + Day: api.SQLUSMALLINT(day), + Hour: api.SQLUSMALLINT(d.Hour()), + Minute: api.SQLUSMALLINT(d.Minute()), + Second: api.SQLUSMALLINT(d.Second()), + Fraction: api.SQLUINTEGER(d.Nanosecond()), + } + p.Data = &b + buf = unsafe.Pointer(&b) + sqltype = api.SQL_TYPE_TIMESTAMP + if p.isDescribed && p.SQLType == api.SQL_TYPE_TIMESTAMP { + decimal = p.Decimal + } + if decimal <= 0 { + // represented as yyyy-mm-dd hh:mm:ss.fff format in ms sql server + decimal = 3 + } + size = 20 + api.SQLULEN(decimal) + case []byte: + ctype = api.SQL_C_BINARY + b := make([]byte, len(d)) + copy(b, d) + p.Data = b + buf = unsafe.Pointer(&b[0]) + buflen = api.SQLLEN(len(b)) + plen = p.StoreStrLen_or_IndPtr(buflen) + size = api.SQLULEN(len(b)) + sqltype = api.SQL_BINARY + default: + panic(fmt.Errorf("unsupported type %T", v)) + } + ret := api.SQLBindParameter(h, api.SQLUSMALLINT(idx+1), + api.SQL_PARAM_INPUT, ctype, sqltype, size, decimal, + api.SQLPOINTER(buf), buflen, plen) + if IsError(ret) { + return NewError("SQLBindParameter", h) + } + return nil +} + +func ExtractParameters(h api.SQLHSTMT) ([]Parameter, error) { + // count parameters + var n, nullable api.SQLSMALLINT + ret := api.SQLNumParams(h, &n) + if IsError(ret) { + return nil, NewError("SQLNumParams", h) + } + if n <= 0 { + // no parameters + return nil, nil + } + ps := make([]Parameter, n) + // fetch param descriptions + for i := range ps { + p := &ps[i] + ret = api.SQLDescribeParam(h, api.SQLUSMALLINT(i+1), + &p.SQLType, &p.Size, &p.Decimal, &nullable) + if IsError(ret) { + // SQLDescribeParam is not implemented by freedts, + // it even fails for some statements on windows. + // Will try request without these descriptions + continue + } + p.isDescribed = true + } + return ps, nil +} diff --git a/src/github.com/ibmdb/go_ibm_db/pooling.go b/src/github.com/ibmdb/go_ibm_db/pooling.go new file mode 100644 index 0000000..f1e62f1 --- /dev/null +++ b/src/github.com/ibmdb/go_ibm_db/pooling.go @@ -0,0 +1,205 @@ +package go_ibm_db + +import ( + "database/sql" + "fmt" + "time" + "strconv" + "strings" +) + +type DBP struct{ +sql.DB +con string +n time.Duration +} + +type Pool struct{ +availablePool map[string] []*DBP +usedPool map[string] []*DBP +PoolSize int +} + +var b *Pool +var ConnMaxLifetime,PoolSize int + +//Pconnect will return the pool instance +func Pconnect(PoolSize string) (*Pool){ + var Size int + count:=len(PoolSize) + if count>0{ + opt:=strings.Split(PoolSize,"=") + if(opt[0] == "PoolSize"){ + Size,_=strconv.Atoi(opt[1]) + }else{ + fmt.Println("Not a valid parameter") + } + } else { + Size=100 + } + p:=&Pool{ + availablePool: make(map[string] []*DBP), + usedPool : make(map[string] []*DBP), + PoolSize : Size, + } + b=p + + return p +} + +var Psize int + +//Open will check for the connection in the pool +//If not opens a new connection and stores in the pool + +func (p *Pool) Open(Connstr string,options ...string)(*DBP){ + var Time time.Duration + count := len(options) + if count>0{ + for i:=0;i 1){ + dbpo:=val[0] + copy(val[0:],val[1:]) + val[len(val)-1]=nil + val=val[:len(val)-1] + p.availablePool[Connstr]=val + p.usedPool[Connstr]=append(p.usedPool[Connstr],dbpo) + dbpo.SetConnMaxLifetime(Time) + return dbpo + }else{ + dbpo:=val[0] + p.usedPool[Connstr]=append(p.usedPool[Connstr],dbpo) + delete(p.availablePool,Connstr) + dbpo.SetConnMaxLifetime(Time) + return dbpo + } + }else{ + db,err:=sql.Open("go_ibm_db",Connstr) + if err != nil{ + return nil + } + dbi:=&DBP{ + DB :*db, + con :Connstr, + n :Time, + } + p.usedPool[Connstr]=append(p.usedPool[Connstr],dbi) + dbi.SetConnMaxLifetime(Time) + return dbi + } + } else { + db,err:=sql.Open("go_ibm_db",Connstr) + if err != nil{ + return nil + } + dbi:=&DBP{ + DB :*db, + con :Connstr, + } + return dbi + } +} + +//Close will make the connection available for the next release + +func (d *DBP) Close(){ + Psize=Psize-1 + var pos int + i:=-1 + if valc,okc:=b.usedPool[d.con];okc{ + if(len(valc) > 1){ + for _,b:=range valc{ + i=i+1 + if b == d{ + pos = i + } + } + dbpc:=valc[pos] + copy(valc[pos:], valc[pos+1:]) + valc[len(valc)-1] = nil + valc = valc[:len(valc)-1] + b.usedPool[d.con]=valc + b.availablePool[d.con]=append(b.availablePool[d.con],dbpc) + } else { + dbpc := valc[0] + b.availablePool[d.con]=append(b.availablePool[d.con],dbpc) + delete(b.usedPool,d.con) + } + go d.Timeout() + } else { + d.DB.Close() + } +} + +//Timeout for closing the connection in pool + +func (d *DBP) Timeout(){ + var pos int + i:=-1 + select { + case <-time.After(d.n): + if valt,okt:=b.availablePool[d.con];okt{ + if(len(valt) > 1){ + for _,b:=range valt{ + i=i+1 + if b == d{ + pos = i + } + } + dbpt:=valt[pos] + copy(valt[pos:], valt[pos+1:]) + valt[len(valt)-1] = nil + valt = valt[:len(valt)-1] + b.availablePool[d.con]=valt + dbpt.DB.Close() + }else{ + dbpt:=valt[0] + dbpt.DB.Close() + delete(b.availablePool,d.con) + } + } + } +} + +//Release will close all the connections in the pool + +func (p *Pool) Release(){ + if(p.availablePool != nil){ + for _,vala := range p.availablePool{ + for _,dbpr := range vala{ + dbpr.DB.Close() + } + } + p.availablePool=nil + } + if(p.usedPool != nil){ + for _,valu := range p.usedPool{ + for _,dbpr := range valu{ + dbpr.DB.Close() + } + } + p.usedPool=nil + } +} + +// Display will print the values in the map + +func (p *Pool) Display(){ + fmt.Println(p.availablePool) + fmt.Println(p.usedPool) + fmt.Println(p.PoolSize) +} diff --git a/src/github.com/ibmdb/go_ibm_db/result.go b/src/github.com/ibmdb/go_ibm_db/result.go new file mode 100644 index 0000000..35bbd99 --- /dev/null +++ b/src/github.com/ibmdb/go_ibm_db/result.go @@ -0,0 +1,22 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package go_ibm_db + +import ( + "errors" +) + +type Result struct { + rowCount int64 +} + +func (r *Result) LastInsertId() (int64, error) { + // TODO(brainman): implement (*Resilt).LastInsertId + return 0, errors.New("not implemented") +} + +func (r *Result) RowsAffected() (int64, error) { + return r.rowCount, nil +} diff --git a/src/github.com/ibmdb/go_ibm_db/rows.go b/src/github.com/ibmdb/go_ibm_db/rows.go new file mode 100644 index 0000000..fb8859a --- /dev/null +++ b/src/github.com/ibmdb/go_ibm_db/rows.go @@ -0,0 +1,45 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package go_ibm_db + +import ( + "github.com/ibmdb/go_ibm_db/api" + "database/sql/driver" + "io" +) + +type Rows struct { + os *ODBCStmt +} + +func (r *Rows) Columns() []string { + names := make([]string, len(r.os.Cols)) + for i := 0; i < len(names); i++ { + names[i] = r.os.Cols[i].Name() + } + return names +} + +func (r *Rows) Next(dest []driver.Value) error { + ret := api.SQLFetch(r.os.h) + if ret == api.SQL_NO_DATA { + return io.EOF + } + if IsError(ret) { + return NewError("SQLFetch", r.os.h) + } + for i := range dest { + v, err := r.os.Cols[i].Value(r.os.h, i) + if err != nil { + return err + } + dest[i] = v + } + return nil +} + +func (r *Rows) Close() error { + return r.os.closeByRows() +} diff --git a/src/github.com/ibmdb/go_ibm_db/stats.go b/src/github.com/ibmdb/go_ibm_db/stats.go new file mode 100644 index 0000000..c3c4d27 --- /dev/null +++ b/src/github.com/ibmdb/go_ibm_db/stats.go @@ -0,0 +1,33 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package go_ibm_db + +import ( + "github.com/ibmdb/go_ibm_db/api" + "fmt" + "sync" +) + +type Stats struct { + EnvCount int + ConnCount int + StmtCount int + mu sync.Mutex +} + +func (s *Stats) updateHandleCount(handleType api.SQLSMALLINT, change int) { + s.mu.Lock() + defer s.mu.Unlock() + switch handleType { + case api.SQL_HANDLE_ENV: + s.EnvCount += change + case api.SQL_HANDLE_DBC: + s.ConnCount += change + case api.SQL_HANDLE_STMT: + s.StmtCount += change + default: + panic(fmt.Errorf("unexpected handle type %d", handleType)) + } +} diff --git a/src/github.com/ibmdb/go_ibm_db/stmt.go b/src/github.com/ibmdb/go_ibm_db/stmt.go new file mode 100644 index 0000000..4e9dc0f --- /dev/null +++ b/src/github.com/ibmdb/go_ibm_db/stmt.go @@ -0,0 +1,99 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package go_ibm_db + +import ( + "database/sql/driver" + "errors" + "sync" + + "github.com/ibmdb/go_ibm_db/api" +) + +type Stmt struct { + c *Conn + query string + os *ODBCStmt + mu sync.Mutex +} + +func (c *Conn) Prepare(query string) (driver.Stmt, error) { + os, err := c.PrepareODBCStmt(query) + if err != nil { + return nil, err + } + return &Stmt{c: c, os: os, query: query}, nil +} + +func (s *Stmt) NumInput() int { + if s.os == nil { + return -1 + } + return len(s.os.Parameters) +} + +func (s *Stmt) Close() error { + if s.os == nil { + return errors.New("Stmt is already closed") + } + ret := s.os.closeByStmt() + s.os = nil + return ret +} + +func (s *Stmt) Exec(args []driver.Value) (driver.Result, error) { + if s.os == nil { + return nil, errors.New("Stmt is closed") + } + + s.mu.Lock() + defer s.mu.Unlock() + if s.os.usedByRows { + s.os.closeByStmt() + s.os = nil + os, err := s.c.PrepareODBCStmt(s.query) + if err != nil { + return nil, err + } + s.os = os + } + err := s.os.Exec(args) + if err != nil { + return nil, err + } + var c api.SQLLEN + ret := api.SQLRowCount(s.os.h, &c) + if IsError(ret) { + return nil, NewError("SQLRowCount", s.os.h) + } + return &Result{rowCount: int64(c)}, nil +} + +func (s *Stmt) Query(args []driver.Value) (driver.Rows, error) { + if s.os == nil { + return nil, errors.New("Stmt is closed") + } + s.mu.Lock() + defer s.mu.Unlock() + if s.os.usedByRows { + s.os.closeByStmt() + s.os = nil + os, err := s.c.PrepareODBCStmt(s.query) + if err != nil { + return nil, err + } + s.os = os + } + err := s.os.Exec(args) + if err != nil { + return nil, err + } + err = s.os.BindColumns() + if err != nil { + return nil, err + } + s.os.usedByRows = true // now both Stmt and Rows refer to it + return &Rows{os: s.os}, nil +} diff --git a/src/github.com/ibmdb/go_ibm_db/testdata/a_create_test.go b/src/github.com/ibmdb/go_ibm_db/testdata/a_create_test.go new file mode 100644 index 0000000..03064fb --- /dev/null +++ b/src/github.com/ibmdb/go_ibm_db/testdata/a_create_test.go @@ -0,0 +1,9 @@ +package main + +import "testing" + +func TestCreatetable(t *testing.T){ + if(Createtable() != nil){ + t.Error("table not formed") +} +} \ No newline at end of file diff --git a/src/github.com/ibmdb/go_ibm_db/testdata/begin_test.go b/src/github.com/ibmdb/go_ibm_db/testdata/begin_test.go new file mode 100644 index 0000000..075dc99 --- /dev/null +++ b/src/github.com/ibmdb/go_ibm_db/testdata/begin_test.go @@ -0,0 +1,9 @@ +package main + +import "testing" + +func TestBegin(t *testing.T){ + if(Begin() != nil){ + t.Error("table not displayed") +} +} \ No newline at end of file diff --git a/src/github.com/ibmdb/go_ibm_db/testdata/close_test.go b/src/github.com/ibmdb/go_ibm_db/testdata/close_test.go new file mode 100644 index 0000000..8ebb1ab --- /dev/null +++ b/src/github.com/ibmdb/go_ibm_db/testdata/close_test.go @@ -0,0 +1,9 @@ +package main + +import "testing" + +func TestClose(t *testing.T){ + if(Close() != nil){ + t.Error("Error in Scanning Query") +} +} \ No newline at end of file diff --git a/src/github.com/ibmdb/go_ibm_db/testdata/columns_test.go b/src/github.com/ibmdb/go_ibm_db/testdata/columns_test.go new file mode 100644 index 0000000..1c195ac --- /dev/null +++ b/src/github.com/ibmdb/go_ibm_db/testdata/columns_test.go @@ -0,0 +1,9 @@ +package main + +import "testing" + +func TestColumns(t *testing.T){ + if(Columns() != nil){ + t.Error("Error in displaying Query") +} +} \ No newline at end of file diff --git a/src/github.com/ibmdb/go_ibm_db/testdata/commit_test.go b/src/github.com/ibmdb/go_ibm_db/testdata/commit_test.go new file mode 100644 index 0000000..a0c425c --- /dev/null +++ b/src/github.com/ibmdb/go_ibm_db/testdata/commit_test.go @@ -0,0 +1,9 @@ +package main + +import "testing" + +func TestCommit(t *testing.T){ + if(Commit() != nil){ + t.Error("Error in commit query") +} +} \ No newline at end of file diff --git a/src/github.com/ibmdb/go_ibm_db/testdata/conn_test.go b/src/github.com/ibmdb/go_ibm_db/testdata/conn_test.go new file mode 100644 index 0000000..ce8a04b --- /dev/null +++ b/src/github.com/ibmdb/go_ibm_db/testdata/conn_test.go @@ -0,0 +1,9 @@ +package main + +import "testing" + +func TestCreateconnection(t *testing.T){ + if(Createconnection() == nil){ + t.Error("connection not formed") +} +} \ No newline at end of file diff --git a/src/github.com/ibmdb/go_ibm_db/testdata/drop_test.go b/src/github.com/ibmdb/go_ibm_db/testdata/drop_test.go new file mode 100644 index 0000000..cfed09d --- /dev/null +++ b/src/github.com/ibmdb/go_ibm_db/testdata/drop_test.go @@ -0,0 +1,9 @@ +package main + +import "testing" + +func TestDrop(t *testing.T){ + if(Drop() != nil){ + t.Error("table not dropped") +} +} \ No newline at end of file diff --git a/src/github.com/ibmdb/go_ibm_db/testdata/insert_test.go b/src/github.com/ibmdb/go_ibm_db/testdata/insert_test.go new file mode 100644 index 0000000..542021c --- /dev/null +++ b/src/github.com/ibmdb/go_ibm_db/testdata/insert_test.go @@ -0,0 +1,9 @@ +package main + +import "testing" + +func TestInsert(t *testing.T){ + if(Insert() != nil){ + t.Error("table not formed") +} +} \ No newline at end of file diff --git a/src/github.com/ibmdb/go_ibm_db/testdata/main.go b/src/github.com/ibmdb/go_ibm_db/testdata/main.go new file mode 100644 index 0000000..ffe201e --- /dev/null +++ b/src/github.com/ibmdb/go_ibm_db/testdata/main.go @@ -0,0 +1,250 @@ +package main + +import ( + "fmt" + a "github.com/ibmdb/go_ibm_db" + "database/sql" + ) + +var con ="HOSTNAME=host;PORT=number;DATABASE=name;UID=username;PWD=password" + +func Createconnection()(db *sql.DB){ + db,_=sql.Open("go_ibm_db",con) + return db + } + + +func Createtable( ) error{ + db, err:=sql.Open("go_ibm_db", con) + db.Exec("DROP table rocket") + _,err=db.Exec("create table rocket(a int)") + _,err=db.Exec("create table rocket1(a int)") + if err != nil{ + return err + } + return nil +} +func Insert() error{ + db,err:=sql.Open("go_ibm_db",con) + _,err =db.Exec("insert into rocket values(1)") + if err != nil{ + return err + } + return nil +} + +func Drop() error{ + db,err:=sql.Open("go_ibm_db",con) + _,err =db.Exec("drop table rocket1") + if err != nil{ + return err + } + return nil +} + +func Prepare() error{ +db,_:=sql.Open("go_ibm_db",con) +_,err:=db.Prepare("select * from rocket") +if err!=nil{ +return err +} +return nil +} + +func Query() error{ +db,_:=sql.Open("go_ibm_db",con) +st,_:=db.Prepare("select * from rocket") +_,err:=st.Query() +if err != nil{ +return err +} +return nil +} + +func Scan() error{ +db,_:=sql.Open("go_ibm_db",con) +st,_:=db.Prepare("select * from rocket") +rows,err:=st.Query() +for rows.Next(){ +var a string +err = rows.Scan(&a) +if err != nil{ +return err +} +} +return nil +} + +func Next() error{ +db,_:=sql.Open("go_ibm_db",con) +st,_:=db.Prepare("select * from rocket") +rows,err:=st.Query() +for rows.Next(){ +var a string +err = rows.Scan(&a) +if err != nil{ +return err +} +} +return nil +} + +func Columns() error{ +db,_:=sql.Open("go_ibm_db",con) +st,_:=db.Prepare("select * from rocket") +rows,_:=st.Query() +_,err := rows.Columns() +if err != nil{ +return err +} +for rows.Next(){ +var a string +_ = rows.Scan(&a) +} +return nil +} + + + +func Queryrow() error{ +a:=1 +var uname int +db,err:=sql.Open("go_ibm_db",con) +err=db.QueryRow("select a from rocket where a=?",a).Scan(&uname) +if err != nil{ +return err +} +return nil +} + +func Begin() error{ +db,err:=sql.Open("go_ibm_db",con) +_,err=db.Begin() +if err != nil{ +return err +} +return nil +} + +func Commit() error{ + db,err:=sql.Open("go_ibm_db",con) + bg,err:=db.Begin() + db.Exec("DROP table u") + _,err=bg.Exec("create table u(id int)") + err=bg.Commit() + if err!=nil{ + return err + } + return nil +} + +func Close()(error){ + db,_:=sql.Open("go_ibm_db",con) + err:=db.Close() + if err!=nil{ + return err + } + return nil + } + +func PoolOpen() (int){ + pool:=a.Pconnect("PoolSize=50") + db:=pool.Open(con) + if(db == nil){ + return 0 + }else { + return 1 + } +} + +func main(){ +result:=Createconnection() +if(result != nil){ +fmt.Println("Pass") +} else { +fmt.Println("fail") +} + +result1:=Createtable() +if(result1 == nil){ +fmt.Println("Pass") +} else { +fmt.Println("fail") +} + +result2:=Insert() +if(result2 == nil){ +fmt.Println("Pass") +} else { +fmt.Println("fail") +} +result3:=Drop() +if(result3 == nil){ +fmt.Println("Pass") +} else { +fmt.Println("fail") +} +result4:=Prepare() +if(result4 == nil){ +fmt.Println("Pass") +} else { +fmt.Println("fail") +} +result5:=Query() +if(result5 == nil){ +fmt.Println("Pass") +} else { +fmt.Println("fail") +} + +result6:=Scan() +if(result6 == nil){ +fmt.Println("Pass") +} else { +fmt.Println("fail") +} +result7:=Next() +if(result7 == nil){ +fmt.Println("Pass") +} else { +fmt.Println("fail") +} + +result8:=Columns() +if(result8 == nil){ +fmt.Println("Pass") +} else { +fmt.Println("fail") +} + +result9:=Queryrow() +if(result9 == nil){ +fmt.Println("Pass") +} else { +fmt.Println("fail") +} +result10:=Begin() +if(result10== nil){ +fmt.Println("Pass") +} else { +fmt.Println("fail") +} +result11:=Commit() +if(result11 == nil){ +fmt.Println("Pass") +} else { +fmt.Println("fail") +} +result12:=Close() +if(result12 == nil){ +fmt.Println("Pass") +} else { +fmt.Println("fail") +} +result13:=PoolOpen() +if(result13 ==1){ +fmt.Println("Pass") +} else { +fmt.Println("fail") +} +} \ No newline at end of file diff --git a/src/github.com/ibmdb/go_ibm_db/testdata/next_test.go b/src/github.com/ibmdb/go_ibm_db/testdata/next_test.go new file mode 100644 index 0000000..b3fb56f --- /dev/null +++ b/src/github.com/ibmdb/go_ibm_db/testdata/next_test.go @@ -0,0 +1,9 @@ +package main + +import "testing" + +func TestNext(t *testing.T){ + if(Next() != nil){ + t.Error("Error in Scanning Query") +} +} \ No newline at end of file diff --git a/src/github.com/ibmdb/go_ibm_db/testdata/poolopen_test.go b/src/github.com/ibmdb/go_ibm_db/testdata/poolopen_test.go new file mode 100644 index 0000000..dc7a658 --- /dev/null +++ b/src/github.com/ibmdb/go_ibm_db/testdata/poolopen_test.go @@ -0,0 +1,10 @@ +package main + +import ( + "testing" +) +func TestPoolOpen(t *testing.T){ + if(PoolOpen() == 0){ + t.Error("pool connection not opened") + } +} \ No newline at end of file diff --git a/src/github.com/ibmdb/go_ibm_db/testdata/prepare_test.go b/src/github.com/ibmdb/go_ibm_db/testdata/prepare_test.go new file mode 100644 index 0000000..a65d5c3 --- /dev/null +++ b/src/github.com/ibmdb/go_ibm_db/testdata/prepare_test.go @@ -0,0 +1,9 @@ +package main + +import "testing" + +func TestPrepare(t *testing.T){ + if(Prepare() != nil){ + t.Error("Error in preparing Query") +} +} \ No newline at end of file diff --git a/src/github.com/ibmdb/go_ibm_db/testdata/query_test.go b/src/github.com/ibmdb/go_ibm_db/testdata/query_test.go new file mode 100644 index 0000000..906bff0 --- /dev/null +++ b/src/github.com/ibmdb/go_ibm_db/testdata/query_test.go @@ -0,0 +1,9 @@ +package main + +import "testing" + +func TestQuery(t *testing.T){ + if(Query() != nil){ + t.Error("table not displayed") +} +} \ No newline at end of file diff --git a/src/github.com/ibmdb/go_ibm_db/testdata/queryrow_test.go b/src/github.com/ibmdb/go_ibm_db/testdata/queryrow_test.go new file mode 100644 index 0000000..3472d9f --- /dev/null +++ b/src/github.com/ibmdb/go_ibm_db/testdata/queryrow_test.go @@ -0,0 +1,9 @@ +package main + +import "testing" + +func TestQueryrow(t *testing.T){ + if(Queryrow() != nil){ + t.Error("values not displayed") +} +} \ No newline at end of file diff --git a/src/github.com/ibmdb/go_ibm_db/testdata/scan_test.go b/src/github.com/ibmdb/go_ibm_db/testdata/scan_test.go new file mode 100644 index 0000000..a8c801d --- /dev/null +++ b/src/github.com/ibmdb/go_ibm_db/testdata/scan_test.go @@ -0,0 +1,9 @@ +package main + +import "testing" + +func TestScan(t *testing.T){ + if(Scan() != nil){ + t.Error("Error in Scanning Query") +} +} \ No newline at end of file diff --git a/src/github.com/ibmdb/go_ibm_db/tx.go b/src/github.com/ibmdb/go_ibm_db/tx.go new file mode 100644 index 0000000..7f3f6c6 --- /dev/null +++ b/src/github.com/ibmdb/go_ibm_db/tx.go @@ -0,0 +1,67 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package go_ibm_db + +import ( + "database/sql/driver" + "errors" + + "github.com/ibmdb/go_ibm_db/api" +) + +type Tx struct { + c *Conn +} + +func (c *Conn) setAutoCommitAttr(a uintptr) error { + ret := api.SQLSetConnectAttr(c.h, api.SQL_ATTR_AUTOCOMMIT, + api.SQLPOINTER(a), api.SQL_IS_UINTEGER) + if IsError(ret) { + return NewError("SQLSetConnectAttr", c.h) + } + return nil +} + +func (c *Conn) Begin() (driver.Tx, error) { + if c.tx != nil { + return nil, errors.New("already in a transaction") + } + err := c.setAutoCommitAttr(api.SQL_AUTOCOMMIT_OFF) + if err != nil { + return nil, err + } + c.tx = &Tx{c: c} + return c.tx, nil +} + +func (c *Conn) endTx(commit bool) error { + if c.tx == nil { + return errors.New("not in a transaction") + } + c.tx = nil + var howToEnd api.SQLSMALLINT + if commit { + howToEnd = api.SQL_COMMIT + } else { + howToEnd = api.SQL_ROLLBACK + } + ret := api.SQLEndTran(api.SQL_HANDLE_DBC, api.SQLHANDLE(c.h), howToEnd) + if IsError(ret) { + return NewError("SQLEndTran", c.h) + } + err := c.setAutoCommitAttr(api.SQL_AUTOCOMMIT_ON) + if err != nil { + return err + } + return nil +} + +func (tx *Tx) Commit() error { + return tx.c.endTx(true) +} + +func (tx *Tx) Rollback() error { + return tx.c.endTx(false) +} diff --git a/src/github.com/ibmdb/go_ibm_db/utf16.go b/src/github.com/ibmdb/go_ibm_db/utf16.go new file mode 100644 index 0000000..e67c405 --- /dev/null +++ b/src/github.com/ibmdb/go_ibm_db/utf16.go @@ -0,0 +1,55 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package go_ibm_db + +import ( + "unicode/utf16" + "unicode/utf8" +) + +const ( + replacementChar = '\uFFFD' // Unicode replacement character + + // 0xd800-0xdc00 encodes the high 10 bits of a pair. + // 0xdc00-0xe000 encodes the low 10 bits of a pair. + // the value is those 20 bits plus 0x10000. + surr1 = 0xd800 + surr2 = 0xdc00 + surr3 = 0xe000 +) + +// utf16toutf8 returns the UTF-8 encoding of the UTF-16 sequence s, +// with a terminating NUL removed. +func utf16toutf8(s []uint16) []byte { + for i, v := range s { + if v == 0 { + s = s[0:i] + break + } + } + buf := make([]byte, 0, len(s)*2) // allow 2 bytes for every rune + b := make([]byte, 4) + for i := 0; i < len(s); i++ { + var rr rune + switch r := s[i]; { + case surr1 <= r && r < surr2 && i+1 < len(s) && + surr2 <= s[i+1] && s[i+1] < surr3: + // valid surrogate sequence + rr = utf16.DecodeRune(rune(r), rune(s[i+1])) + i++ + case surr1 <= r && r < surr3: + // invalid surrogate sequence + rr = replacementChar + default: + // normal rune + rr = rune(r) + } + b := b[:cap(b)] + n := utf8.EncodeRune(b, rr) + b = b[:n] + buf = append(buf, b...) + } + return buf +} From 0c5d8549620ff4a629bbd979d339a43bd8215f22 Mon Sep 17 00:00:00 2001 From: akhilravuri1 Date: Mon, 1 Apr 2019 17:53:38 +0530 Subject: [PATCH 5/5] blob support added --- .../ibmdb/go_ibm_db/api/api_unix.go | 19 ++++++++++++++++++ .../ibmdb/go_ibm_db/api/api_windows.go | 20 +++++++++++++++++++ src/github.com/ibmdb/go_ibm_db/column.go | 2 +- 3 files changed, 40 insertions(+), 1 deletion(-) diff --git a/src/github.com/ibmdb/go_ibm_db/api/api_unix.go b/src/github.com/ibmdb/go_ibm_db/api/api_unix.go index d89ecbe..a026f62 100644 --- a/src/github.com/ibmdb/go_ibm_db/api/api_unix.go +++ b/src/github.com/ibmdb/go_ibm_db/api/api_unix.go @@ -68,8 +68,11 @@ const ( SQL_WVARCHAR = C.SQL_WVARCHAR SQL_WLONGVARCHAR = C.SQL_WLONGVARCHAR SQL_GUID = C.SQL_GUID + SQL_BLOB = C.SQL_BLOB + SQL_CLOB = C.SQL_CLOB SQL_SIGNED_OFFSET = C.SQL_SIGNED_OFFSET SQL_UNSIGNED_OFFSET = C.SQL_UNSIGNED_OFFSET + SQL_DBCLOB = C.SQL_DBCLOB // TODO(lukemauldin): Not defined in sqlext.h. Using windows value, but it is not supported. SQL_SS_XML = -152 @@ -91,6 +94,10 @@ const ( SQL_C_SBIGINT = C.SQL_C_SBIGINT SQL_C_UBIGINT = C.SQL_C_UBIGINT SQL_C_GUID = C.SQL_C_GUID + SQL_C_DBCHAR = C.SQL_C_DBCHAR + SQL_C_TYPE_DATE = C.SQL_C_TYPE_DATE + SQL_C_TYPE_TIME = C.SQL_C_TYPE_TIME + SQL_COMMIT = C.SQL_COMMIT SQL_ROLLBACK = C.SQL_ROLLBACK @@ -100,6 +107,18 @@ const ( SQL_AUTOCOMMIT_OFF = C.SQL_AUTOCOMMIT_OFF SQL_AUTOCOMMIT_ON = C.SQL_AUTOCOMMIT_ON SQL_AUTOCOMMIT_DEFAULT = C.SQL_AUTOCOMMIT_DEFAULT + SQL_DESC_PRECISION = C.SQL_DESC_PRECISION + SQL_DESC_SCALE = C.SQL_DESC_SCALE + SQL_DESC_LENGTH = C.SQL_DESC_LENGTH + SQL_DESC_CONCISE_TYPE = C.SQL_DESC_CONCISE_TYPE + SQL_DESC_TYPE_NAME = C.SQL_DESC_TYPE_NAME + SQL_COLUMN_TYPE = C.SQL_COLUMN_TYPE + SQL_COLUMN_TYPE_NAME = C.SQL_COLUMN_TYPE_NAME + MAX_FIELD_SIZE = 1024 + SQL_DESC_NULLABLE = C.SQL_DESC_NULLABLE + SQL_NULLABLE = C.SQL_NULLABLE + SQL_NO_NULLS = C.SQL_NO_NULLS + SQL_DECFLOAT = C.SQL_DECFLOAT SQL_IS_UINTEGER = C.SQL_IS_UINTEGER diff --git a/src/github.com/ibmdb/go_ibm_db/api/api_windows.go b/src/github.com/ibmdb/go_ibm_db/api/api_windows.go index 843c363..2f81683 100644 --- a/src/github.com/ibmdb/go_ibm_db/api/api_windows.go +++ b/src/github.com/ibmdb/go_ibm_db/api/api_windows.go @@ -48,6 +48,7 @@ const ( SQL_TYPE_DATE = 91 SQL_TYPE_TIME = 92 SQL_TYPE_TIMESTAMP = 93 + SQL_NEED_DATA = 99 SQL_TIMESTAMP = 11 SQL_LONGVARCHAR = -1 SQL_BINARY = -2 @@ -62,6 +63,10 @@ const ( SQL_GUID = -11 SQL_SIGNED_OFFSET = -20 SQL_UNSIGNED_OFFSET = -22 + SQL_GRAPHIC = -95 + SQL_BLOB = -98 + SQL_CLOB = -99 + SQL_DBCLOB = -350 SQL_SS_XML = -152 SQL_C_CHAR = SQL_CHAR @@ -77,10 +82,13 @@ const ( SQL_C_BINARY = SQL_BINARY SQL_C_BIT = SQL_BIT SQL_C_WCHAR = SQL_WCHAR + SQL_C_DBCHAR = SQL_DBCLOB SQL_C_DEFAULT = 99 SQL_C_SBIGINT = SQL_BIGINT + SQL_SIGNED_OFFSET SQL_C_UBIGINT = SQL_BIGINT + SQL_UNSIGNED_OFFSET SQL_C_GUID = SQL_GUID + SQL_C_TYPE_DATE = SQL_TYPE_DATE + SQL_C_TYPE_TIME = SQL_TYPE_TIME SQL_COMMIT = 0 SQL_ROLLBACK = 1 @@ -102,6 +110,18 @@ const ( SQL_CP_DEFAULT = SQL_CP_OFF SQL_CP_STRICT_MATCH = 0 SQL_CP_RELAXED_MATCH = 1 + SQL_DESC_PRECISION = 1005 + SQL_DESC_SCALE = 1006 + SQL_DESC_LENGTH = 1003 + SQL_DESC_CONCISE_TYPE = SQL_COLUMN_TYPE + SQL_DESC_TYPE_NAME = SQL_COLUMN_TYPE_NAME + SQL_COLUMN_TYPE = 2 + SQL_COLUMN_TYPE_NAME = 14 + MAX_FIELD_SIZE = 1024 + SQL_DESC_NULLABLE = 1008 + SQL_NULLABLE = 1 + SQL_NO_NULLS = 0 + SQL_DECFLOAT = -360 ) type ( diff --git a/src/github.com/ibmdb/go_ibm_db/column.go b/src/github.com/ibmdb/go_ibm_db/column.go index cb1804d..de12abf 100644 --- a/src/github.com/ibmdb/go_ibm_db/column.go +++ b/src/github.com/ibmdb/go_ibm_db/column.go @@ -84,7 +84,7 @@ func NewColumn(h api.SQLHSTMT, idx int) (Column, error) { return NewVariableWidthColumn(b, api.SQL_C_CHAR, size), nil case api.SQL_WCHAR, api.SQL_WVARCHAR: return NewVariableWidthColumn(b, api.SQL_C_WCHAR, size), nil - case api.SQL_BINARY, api.SQL_VARBINARY: + case api.SQL_BINARY, api.SQL_VARBINARY,api.SQL_BLOB: return NewVariableWidthColumn(b, api.SQL_C_BINARY, size), nil case api.SQL_LONGVARCHAR: return NewVariableWidthColumn(b, api.SQL_C_CHAR, 0), nil