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
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..a026f62
--- /dev/null
+++ b/src/github.com/ibmdb/go_ibm_db/api/api_unix.go
@@ -0,0 +1,154 @@
+// 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
+ SQL_DBCLOB = C.SQL_DBCLOB
+
+ // 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_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
+
+ 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_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
+
+ //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..2f81683
--- /dev/null
+++ b/src/github.com/ibmdb/go_ibm_db/api/api_windows.go
@@ -0,0 +1,149 @@
+// 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_NEED_DATA = 99
+ 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_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
+
+ 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
+ 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 (
+ 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..de12abf
--- /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,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..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
+}
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)")