Skip to content

Commit

Permalink
implements fetch, execute method.
Browse files Browse the repository at this point in the history
  • Loading branch information
yone098 committed Nov 23, 2009
1 parent 0cf1d84 commit f3986d5
Show file tree
Hide file tree
Showing 4 changed files with 225 additions and 67 deletions.
139 changes: 125 additions & 14 deletions mysql/core.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,25 @@ import "db"

type Connection struct {
/* pointer to struct mysql */
handle C.wm_mysql;
handle C.wmysql;
}

/* MYSQL cursors, will be renamed/refactored soon */
type Cursor struct {
/* statement we were created for */
statement *Statement;
/* connection we were created on */
connection *Connection;
/* the last query yielded results */
result bool;
}

type Statement struct {
/* pointer to struct mysql statement */
handle C.wres;
connection *Connection;
query string;
nfields int;
}

func init() {
Expand Down Expand Up @@ -47,7 +65,7 @@ func version() (data map[string]string, error os.Error)

// versionnumber
data["mysql.versionnumber"] = "";

return data, nil;
}

Expand All @@ -59,16 +77,16 @@ type ConnectionInfo map[string] Any;
// unsafe pointers instead of _C_typedefname.
func use(h interface {}) (rval unsafe.Pointer) {
switch ptr := h.(type) {
case C.wm_mysql: rval = unsafe.Pointer(ptr)
case C.wm_row: rval = unsafe.Pointer(ptr)
case C.wm_res: rval = unsafe.Pointer(ptr)
case C.wm_field: rval = unsafe.Pointer(ptr)
case C.wmysql: rval = unsafe.Pointer(ptr)
case C.wrow: rval = unsafe.Pointer(ptr)
case C.wres: rval = unsafe.Pointer(ptr)
case C.wfield: rval = unsafe.Pointer(ptr)
default: panic("Tried to use() unknown type\n")
}
return;
}

func LastError(mysql C.wm_mysql) os.Error {
func LastError(mysql C.wmysql) os.Error {
if err := C.wm_error(use(mysql)); *err != 0 {
return os.NewError(C.GoString(err));
}
Expand All @@ -85,10 +103,10 @@ func open(info ConnectionInfo) (connection db.Connection, error os.Error)
conn := new (Connection);
conn.handle = C.wm_init(nil);
C.wm_real_connect(
use(conn.handle),
args[0],
args[1],
args[2],
use(conn.handle),
args[0],
args[1],
args[2],
args[3],
C.int(port));

Expand All @@ -99,7 +117,7 @@ func open(info ConnectionInfo) (connection db.Connection, error os.Error)
if error = LastError(conn.handle); error != nil {
conn.handle = nil;
}

connection = conn;

return;
Expand All @@ -125,15 +143,63 @@ func (self *Connection) error() (error os.Error) {
*/
func (self *Connection) Prepare(query string) (statement db.Statement, error os.Error)
{
return nil, nil;
s := new(Statement);
s.query = query;
s.connection = self;

statement = s;

return;
}

/*
Execute precompiled Statement with given parameters (if any).
*/
func (self *Connection) Execute(statement db.Statement, parameters ...) (cursor db.Cursor, error os.Error)
{
return nil, nil;
// TODO lock
s, ok := statement.(*Statement);
if !ok {
error = &InterfaceError{"Execute: Not an mysql statement!"};
return;
}
// TODO bind parameter
query := fmt.Sprintf(s.query, parameters);
q := C.CString(query);
rcode := C.wms_query(use(self.handle), q);
C.free(unsafe.Pointer(q));

if error = LastError(self.handle); error != nil || rcode != 0 {
if error == nil {
error = os.NewError("Query failed.")
}
return;
}
s.nfields = int(C.wfield_count(use(self.handle)));
s.handle = C.wm_store_result(use(self.handle));
error = LastError(self.handle);
if error != nil || (s.handle == nil && s.nfields > 0) {
if error == nil {
error = os.NewError("No results returned.");
s.cleanup();
}
return;
}
c := new(Cursor);
c.statement = s;
c.connection = self;
c.result = true;
cursor = c;

return;
}

func (self *Statement) cleanup() {
if self.handle != nil {
C.wm_free_result(use(self.handle));
self.handle = nil;
self.nfields = 0;
}
}

func (self *Connection) Close() (error os.Error) {
Expand All @@ -142,6 +208,51 @@ func (self *Connection) Close() (error os.Error) {
return;
}

/* === Cursor === */


func (self *Cursor) FetchOne() (data []interface {}, error os.Error)
{
if !self.result {
error = &InterfaceError{"FetchOne: No results to fetch!"};
return;
}

row := C.wm_fetch_row(use(self.statement.handle));
error = LastError(self.connection.handle);

if row != nil && error == nil {
data = make([]interface {}, self.statement.nfields);
for i := 0; i < self.statement.nfields; i += 1 {
data[i] = C.GoString(C.wm_row(use(row), C.int(i)));
}
}

return;
}

func (self *Cursor) FetchMany(count int) ([][]interface {}, os.Error)
{
return nil, nil;
}

func (self *Cursor) FetchAll() ([][]interface {}, os.Error)
{
return nil, nil;
}

// Returns the number of rows returned from the current result set.
func (self *Cursor) RowCount() uint64 {
if !self.result { return 0 }
return uint64(C.wm_num_rows(use(self.statement.handle)));
}

func (self *Cursor) Close() os.Error
{
self.statement.cleanup();
return nil;
}



func parseConnInfo(info ConnectionInfo) (host string, port int, uname string,
Expand Down
57 changes: 52 additions & 5 deletions mysql/example.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"db/mysql";
"fmt";
"os";
"rand";
)

func main() {
Expand All @@ -17,22 +18,68 @@ func main() {

info := mysql.ConnectionInfo{
"host": "localhost",
"port": 0,
"uname": "username",
"pass": "password",
"dbname": "userdbname"
"port": 3306,
"uname": "yone098",
"pass": "yone098",
"dbname": "golang"
};
c, e := mysql.Open(info);
if e != nil {
fmt.Printf("open error: %s\n", e.String());
os.Exit(1);
}
fmt.Printf("connection: %s\n", c);
fmt.Printf("About to prepare statement\n");
s, e := c.Prepare("CREATE TEMPORARY TABLE __hello (i INT)");
if e != nil {
fmt.Printf("error: %s\n", e.String());
os.Exit(1);
}
fmt.Printf("statement: %s\n", s);

fmt.Printf("About to execute query\n");
cur, e := c.Execute(s);
if e != nil {
fmt.Printf("error: %s\n", e.String());
os.Exit(1);
}
fmt.Printf("corsor: %s\n", cur);

fmt.Printf("Inserting 30 random ints");
for i := 0; i < 30; i+=1 {
s, e = c.Prepare("INSERT INTO __hello (i) values(%d)");
cur, e = c.Execute(s, rand.Int());
if e != nil {
fmt.Printf("insert error: %s\n", e.String());
os.Exit(1);
}
}

s, e = c.Prepare("SELECT * FROM __hello ORDER BY i ASC");
if e != nil {
fmt.Printf("error: %s\n", e.String());
os.Exit(1);
}
fmt.Printf("statement: %s\n", s);

fmt.Printf("About to execute query\n");
cur, e = c.Execute(s);
if e != nil {
fmt.Printf("error: %s\n", e.String());
os.Exit(1);
}
fmt.Printf("corsor: %s\n", cur);

fmt.Printf("About to fech one row\n");
tuple, e := cur.FetchOne();
for i := 0; tuple != nil; tuple, e = cur.FetchOne() {
i++;
fmt.Printf("row[%d]: %s\n", i, tuple[0]);
}
cur.Close();
e = c.Close();
if e != nil {
fmt.Printf("close error: %s\n", e.String());
os.Exit(1);
}

}
44 changes: 22 additions & 22 deletions mysql/wrapper.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,81 +6,81 @@
#include <stdio.h>
#include <mysql.h>

wm_mysql wm_init(wm_mysql mysql) {
return (wm_mysql)mysql_init((MYSQL *)mysql);
wmysql wm_init(wmysql mysql) {
return (wmysql)mysql_init((MYSQL *)mysql);
}


int wm_errno(wm_mysql mysql) {
int wm_errno(wmysql mysql) {
return mysql_errno((MYSQL *)mysql);
}

const char *wm_error(wm_mysql mysql) {
const char *wm_error(wmysql mysql) {
return mysql_error((MYSQL *)mysql);
}

wm_mysql wm_real_connect(wm_mysql mysql, const char *host, const char *user,
wmysql wm_real_connect(wmysql mysql, const char *host, const char *user,
const char* passwd, const char *db, int port) {
return (wm_mysql)mysql_real_connect((MYSQL *)mysql, host, user, passwd, db,
return (wmysql)mysql_real_connect((MYSQL *)mysql, host, user, passwd, db,
port, NULL, 0);
}

void wm_close(wm_mysql mysql) {
void wm_close(wmysql mysql) {
mysql_close((MYSQL *)mysql);
}

unsigned long wm_get_client_version(void) {
return mysql_get_client_version();
}

void mw_free_result(wm_res res) {
void wm_free_result(wres res) {
mysql_free_result((MYSQL_RES *)res);
}

int mw_query(wm_mysql mysql, const char *q) {
int wms_query(wmysql mysql, const char *q) {
return mysql_query((MYSQL *)mysql, q);
}

wm_res mw_store_result(wm_mysql mysql) {
return (wm_res)mysql_store_result((MYSQL *)mysql);
wres wm_store_result(wmysql mysql) {
return (wres)mysql_store_result((MYSQL *)mysql);
}

char *mw_row(wm_row row, int i) {
char *wm_row(wrow row, int i) {
return (char *)((MYSQL_ROW)row)[i];
}

const char *mw_field_name_at(wm_field field, int i) {
const char *wfield_name_at(wfield field, int i) {
return ((MYSQL_FIELD *)field)[i].name;
}

int mw_field_type_at(wm_field field, int i) {
int wfield_type_at(wfield field, int i) {
return ((MYSQL_FIELD *)field)[i].type;
}

int mw_field_count(wm_mysql mysql) {
int wfield_count(wmysql mysql) {
return mysql_field_count((MYSQL *)mysql);
}

int mw_num_fields(wm_res res) {
int wm_num_fields(wres res) {
return mysql_num_fields((MYSQL_RES *)res);
}

wm_field mw_fetch_fields(wm_res res) {
return (wm_field)mysql_fetch_fields((MYSQL_RES *)res);
wfield wm_fetch_fields(wres res) {
return (wfield)mysql_fetch_fields((MYSQL_RES *)res);
}

wm_row mw_fetch_row(wm_res res) {
wrow wm_fetch_row(wres res) {
return mysql_fetch_row((MYSQL_RES *)res);
}

unsigned long long mw_num_rows(wm_res res) {
unsigned long long wm_num_rows(wres res) {
return mysql_num_rows((MYSQL_RES *)res);
}

void mw_thread_init(void) {
void wm_thread_init(void) {
(void)mysql_thread_init();
}

void mw_thread_end(void) {
void wm_thread_end(void) {
mysql_thread_end();
}
Loading

0 comments on commit f3986d5

Please sign in to comment.