Skip to content

Commit

Permalink
Implement Context and ColumnType interface (#15)
Browse files Browse the repository at this point in the history
* test context functions without monetdb driver specific implementation

* first step implementing context interfaces and named parameters

* Implement named parameters and context methods

* add more tests and fix bugs

* add example scripts

* fix bug when fetches more results after the first 100

* add more connection settings, specifically timezone

* small cleanup before next release
  • Loading branch information
arjenderijke committed Jan 24, 2024
1 parent 3b9d9d8 commit f731612
Show file tree
Hide file tree
Showing 26 changed files with 2,354 additions and 107 deletions.
4 changes: 0 additions & 4 deletions .github/workflows/windows.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,6 @@ jobs:
- name: Get Golang
run: choco install golang

- name: Get dependencies
run: |
go get -v -t -d ./...
- name: Build
run: go build -v ./...

Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
go-monetdb
MonetDB-Go
==========

MonetDB driver for Go.
Expand Down Expand Up @@ -46,7 +46,7 @@ If the `port` is blank, then the default port `50000` will be used.

## API Documentation

https://pkg.go.dev/github.com/fajran/go-monetdb
https://pkg.go.dev/github.com/MonetDB/MonetDB-Go

## Testing

Expand Down
99 changes: 99 additions & 0 deletions examples/cancel_context/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/

package main

import (
"context"
"database/sql"
"os"
"time"

_ "github.com/MonetDB/MonetDB-Go/src"
)

var (
ctx context.Context
cancel context.CancelFunc
)

func main () {
db, err := sql.Open("monetdb", "monetdb:monetdb@localhost:50000/monetdb")
if err != nil {
println(err.Error())
os.Exit(1)
}
if db == nil {
println("db is not created")
os.Exit(1)
}
if pingErr := db.Ping(); pingErr != nil {
println(pingErr.Error())
os.Exit(1)
}
defer db.Close()

_, createErr := db.Exec("create procedure sleep(i int) external name alarm.sleep")
if createErr != nil {
println(createErr.Error())
}

println("Run a query that is cancelled by a timeout")
ctx, cancel = context.WithTimeout(context.Background(), 100*time.Millisecond)
defer cancel()

if _, execErr := db.ExecContext(ctx, "CALL sys.sleep(200)"); execErr != nil {
println(execErr.Error())
}
if ctx.Err() != nil {
println(ctx.Err().Error())
}

println("Run a query that finishes before the timeout")
ctx, cancel = context.WithTimeout(context.Background(), 300*time.Millisecond)
defer cancel()

if _, execErr := db.ExecContext(ctx, "CALL sys.sleep(200)"); execErr != nil {
println(execErr.Error())
} else {
println("The query finished before the timeout")
if ctx.Err() != nil {
println(ctx.Err().Error())
}
}

println("Run a query that gives an error")
ctx, cancel = context.WithTimeout(context.Background(), 300*time.Millisecond)
defer cancel()

if _, execErr := db.ExecContext(ctx, "select * from test1"); execErr != nil {
println(execErr.Error())
} else {
println("The query finished before the timeout")
if ctx.Err() != nil {
println(ctx.Err().Error())
}
}

println("Run a query that returns a result")
ctx, cancel = context.WithTimeout(context.Background(), 100*time.Millisecond)
defer cancel()

var name int
selectErr := db.QueryRowContext(ctx, "select 42").Scan(&name)
switch {
case selectErr == sql.ErrNoRows:
println("Query did not return a result")
case selectErr != nil:
println(selectErr.Error())
default:
println("Value of name is", name)
}

_, dropErr := db.Exec("drop procedure sleep")
if dropErr != nil {
println(dropErr.Error())
}
}
132 changes: 132 additions & 0 deletions examples/named_params/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/

package main

import (
"database/sql"
"os"

_ "github.com/MonetDB/MonetDB-Go/src"
)

func main() {
db, err := sql.Open("monetdb", "monetdb:monetdb@localhost:50000/monetdb")
if err != nil {
println(err.Error())
os.Exit(1)
}
if db == nil {
println("db is not created")
os.Exit(1)
}
if pingErr := db.Ping(); pingErr != nil {
println(pingErr.Error())
os.Exit(1)
}
defer db.Close()

_, err = db.Exec("create table test1 ( name varchar(16), value integer)")
if err != nil {
println(err.Error())
os.Exit(1)
}

result, err := db.Exec("insert into test1 values ( 'name1', 16 )")
if err != nil {
println(err.Error())
}
if result == nil {
println("query did not return a result object")
os.Exit(1)
}
rId, err := result.LastInsertId()
if err != nil {
println("Could not get id from result")
os.Exit(1)
}
println("Last inserted id", rId)

nRows, err := result.RowsAffected()
if err != nil {
println("Could not get number of rows from result")
os.Exit(1)
}
println("Number of rows", nRows)

rows, err := db.Query("select * from test1")
if err != nil {
println(err.Error())
os.Exit(1)
}
defer rows.Close()

if rows == nil {
println("empty result")
os.Exit(1)
}
for rows.Next() {
var name string
var val int
if err := rows.Scan(&name, &val); err != nil {
println(err.Error())
}
}
if err := rows.Err(); err != nil {
println(err.Error())
}

rows, err = db.Query("select * from test1 where name = :name and value = :value", sql.Named("name", "name1"), sql.Named("value", 16))
if err != nil {
println(err.Error())
os.Exit(1)
}
defer rows.Close()

if rows == nil {
println("empty result")
os.Exit(1)
}
columnlist, err := rows.Columns()
if err != nil {
println(err.Error())
os.Exit(1)
}
for i, column := range columnlist {
if i == 0 {
if column != "name" {
println("unexpected column name")
}
}
if i == 1 {
if column != "value" {
println("unexpected column name")
}
}
}
for rows.Next() {
var name string
var value int
if err := rows.Scan(&name, &value); err != nil {
println(err.Error())
os.Exit(1)
}
if name != "name1" {
println("unexpected value for name field")
}
if value != 16 {
println("unexpected value for value field")
}
}
if err := rows.Err(); err != nil {
println(err.Error())
}

_, err = db.Exec("drop table test1")
if err != nil {
println(err.Error())
}

}
104 changes: 104 additions & 0 deletions examples/prepared_stmt/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/

package main

import (
"database/sql"
"os"

_ "github.com/MonetDB/MonetDB-Go/src"
)

func main() {
db, err := sql.Open("monetdb", "monetdb:monetdb@localhost:50000/monetdb")
if err != nil {
println(err.Error())
os.Exit(1)
}
if db == nil {
println("db is not created")
os.Exit(1)
}
if pingErr := db.Ping(); pingErr != nil {
println(pingErr.Error())
os.Exit(1)
}
defer db.Close()

_, err = db.Exec("create table test3 ( id int, name varchar(16))")
if err != nil {
println(err.Error())
os.Exit(1)
}

stmt, err := db.Prepare("insert into test3 values ( ?, ? )")
if err != nil {
println(err.Error())
}
if stmt == nil {
println("Statement is nil")
os.Exit(1)
}
defer stmt.Close()

result, err := stmt.Exec(1, "name1" )
if err != nil {
println(err.Error())
}
if result == nil {
println("query did not return a result object")
os.Exit(1)
}
rId, err := result.LastInsertId()
if err != nil {
println("Could not get id from result")
os.Exit(1)
}
println("Last inserted id", rId)

nRows, err := result.RowsAffected()
if err != nil {
println("Could not get number of rows from result")
os.Exit(1)
}
println("Number of rows", nRows)

stmt, err = db.Prepare("select * from test3 where id = ?")
if err != nil {
println(err.Error())
}
if stmt == nil {
println("Statement is nil")
os.Exit(1)
}
defer stmt.Close()

rows, err := stmt.Query(1)
if err != nil {
println(err.Error())
}
if rows == nil {
println("query returned no rows")
os.Exit(1)
}
defer rows.Close()

for rows.Next() {
var id int
var name string
if err := rows.Scan(&id, &name); err != nil {
println(err.Error())
}
}
if err := rows.Err(); err != nil {
println(err.Error())
}

_, err = db.Exec("drop table test3")
if err != nil {
println(err.Error())
}
}

0 comments on commit f731612

Please sign in to comment.