Commit 62a31153 authored by gwenn's avatar gwenn

Introduce Stmt#Select method.

parent ee538ffb
......@@ -39,7 +39,7 @@ Conn#GetAutocommit
Conn#EnableLoadExtension/LoadExtension
Conn#IntegrityCheck
Stmt#ExecInsert/ExecUpdate
Stmt#Insert/ExecDml/Select
Stmt#BindParameterCount/BindParameterIndex(name)/BindParameterName(index)
Stmt#ClearBindings
Stmt#ColumnCount/ColumnNames/ColumnIndex(name)/ColumnName(index)/ColumnType(index)
......
......@@ -347,7 +347,7 @@ func goXAuxDataDestroy(ad unsafe.Pointer) {
if c != nil {
delete(contexts, c.sc)
}
// fmt.Printf("Contexts: %v\n", contexts)
// fmt.Printf("Contexts: %v\n", contexts)
}
//export goXFunc
......@@ -404,7 +404,7 @@ func goXFinal(scp, udfp unsafe.Pointer) {
udf.final(c)
}
}
// fmt.Printf("Contexts: %v\n", contexts)
// fmt.Printf("Contexts: %v\n", contexts)
}
//export goXDestroy
......
......@@ -26,17 +26,15 @@ func (c *Conn) Databases() (map[string]string, error) {
defer s.Finalize()
var databases map[string]string = make(map[string]string)
var name, file string
for {
if ok, err := s.Next(); err != nil {
return nil, err
} else if !ok {
break
}
err = s.Scan(nil, &name, &file)
if err != nil {
return nil, err
err = s.Select(func(s *Stmt) (err error) {
if err = s.Scan(nil, &name, &file); err != nil {
return
}
databases[name] = file
return
})
if err != nil {
return nil, err
}
return databases, nil
}
......@@ -50,18 +48,13 @@ func (c *Conn) Tables() ([]string, error) {
}
defer s.Finalize()
var tables []string = make([]string, 0, 20)
var name string
for {
if ok, err := s.Next(); err != nil {
return nil, err
} else if !ok {
break
}
err = s.Scan(&name)
if err != nil {
return nil, err
}
err = s.Select(func(s *Stmt) (err error) {
name, _ := s.ScanText(0)
tables = append(tables, name)
return
})
if err != nil {
return nil, err
}
return tables, nil
}
......@@ -86,18 +79,16 @@ func (c *Conn) Columns(table string) ([]Column, error) {
}
defer s.Finalize()
var columns []Column = make([]Column, 0, 20)
for {
if ok, err := s.Next(); err != nil {
return nil, err
} else if !ok {
break
}
err = s.Select(func(s *Stmt) (err error) {
c := Column{}
err = s.Scan(&c.Cid, &c.Name, &c.DataType, &c.NotNull, &c.DfltValue, &c.Pk)
if err != nil {
return nil, err
if err = s.Scan(&c.Cid, &c.Name, &c.DataType, &c.NotNull, &c.DfltValue, &c.Pk); err != nil {
return
}
columns = append(columns, c)
return
})
if err != nil {
return nil, err
}
return columns, nil
}
......@@ -120,15 +111,9 @@ func (c *Conn) ForeignKeys(table string) (map[int]*ForeignKey, error) {
var fks = make(map[int]*ForeignKey)
var id, seq int
var ref, from, to string
for {
if ok, err := s.Next(); err != nil {
return nil, err
} else if !ok {
break
}
err = s.NamedScan("id", &id, "seq", &seq, "table", &ref, "from", &from, "to", &to)
if err != nil {
return nil, err
err = s.Select(func(s *Stmt) (err error) {
if err = s.NamedScan("id", &id, "seq", &seq, "table", &ref, "from", &from, "to", &to); err != nil {
return
}
fk, ex := fks[id]
if !ex {
......@@ -138,6 +123,10 @@ func (c *Conn) ForeignKeys(table string) (map[int]*ForeignKey, error) {
// TODO Ensure columns are appended in the correct order...
fk.From = append(fk.From, from)
fk.To = append(fk.To, to)
return
})
if err != nil {
return nil, err
}
return fks, nil
}
......@@ -157,18 +146,16 @@ func (c *Conn) Indexes(table string) ([]Index, error) {
}
defer s.Finalize()
var indexes []Index = make([]Index, 0, 5)
for {
if ok, err := s.Next(); err != nil {
return nil, err
} else if !ok {
break
}
err = s.Select(func(s *Stmt) (err error) {
i := Index{}
err = s.Scan(nil, &i.Name, &i.Unique)
if err != nil {
return nil, err
if err = s.Scan(nil, &i.Name, &i.Unique); err != nil {
return
}
indexes = append(indexes, i)
return
})
if err != nil {
return nil, err
}
return indexes, nil
}
......@@ -182,18 +169,16 @@ func (c *Conn) IndexColumns(index string) ([]Column, error) {
}
defer s.Finalize()
var columns []Column = make([]Column, 0, 5)
for {
if ok, err := s.Next(); err != nil {
return nil, err
} else if !ok {
break
}
err = s.Select(func(s *Stmt) (err error) {
c := Column{}
err = s.Scan(nil, &c.Cid, &c.Name)
if err != nil {
return nil, err
if err = s.Scan(nil, &c.Cid, &c.Name); err != nil {
return
}
columns = append(columns, c)
return
})
if err != nil {
return nil, err
}
return columns, nil
}
......
......@@ -532,7 +532,7 @@ func (s *Stmt) Exec(args ...interface{}) error {
// Like Exec but returns the number of rows that were changed or inserted or deleted.
// Don't use it with SELECT or anything that returns data.
func (s *Stmt) ExecUpdate(args ...interface{}) (int, error) {
func (s *Stmt) ExecDml(args ...interface{}) (int, error) {
err := s.Exec(args...)
if err != nil {
return -1, err
......@@ -540,10 +540,10 @@ func (s *Stmt) ExecUpdate(args ...interface{}) (int, error) {
return s.c.Changes(), nil
}
// Like Exec but returns the autoincremented rowid.
// Like ExecDml but returns the autoincremented rowid.
// Don't use it with SELECT or anything that returns data.
func (s *Stmt) ExecInsert(args ...interface{}) (int64, error) {
n, err := s.ExecUpdate(args...)
func (s *Stmt) Insert(args ...interface{}) (int64, error) {
n, err := s.ExecDml(args...)
if err != nil {
return -1, err
}
......@@ -553,6 +553,29 @@ func (s *Stmt) ExecInsert(args ...interface{}) (int64, error) {
return s.c.LastInsertRowid(), nil
}
// The callback function is invoked for each result row coming out of the statement.
//
// s, err := c.Prepare(...)
// // TODO error handling
// defer s.Finalize()
// err = s.Select(func(s *Stmt) error {
// //Scan
// })
// // TODO error handling
func (s *Stmt) Select(rowCallbackHandler func(s *Stmt) error) error {
for {
if ok, err := s.Next(); err != nil {
return err
} else if !ok {
break
}
if err := rowCallbackHandler(s); err != nil {
return err
}
}
return nil
}
// Number of SQL parameters
// Calls http://sqlite.org/c3ref/bind_parameter_count.html
func (s *Stmt) BindParameterCount() int {
......@@ -789,11 +812,14 @@ func (s *Stmt) ColumnType(index int) Type {
// defer stmt.Finalize()
// var id int
// var name string
// for sqlite.Must(stmt.Next()) {
// err = stmt.NamedScan("name", &name, "id", &id)
// // TODO error handling
// err = s.Select(func(s *Stmt) (err error) {
// if err = stmt.NamedScan("name", &name, "id", &id); err != nil {
// return
// }
// fmt.Println(id, name)
// }
// return
// })
// // TODO error handling
//
// NULL value is converted to 0 if arg type is *int,*int64,*float,*float64, to "" for *string, to []byte{} for *[]byte and to false for *bool.
// Calls sqlite3_column_count, sqlite3_column_name and sqlite3_column_(blob|double|int|int64|text) depending on args type.
......@@ -827,11 +853,14 @@ func (s *Stmt) NamedScan(args ...interface{}) error {
// defer stmt.Finalize()
// var id int
// var name string
// for sqlite.Must(stmt.Next()) {
// err = stmt.Scan(&id, &name)
// // TODO error handling
// err = s.Select(func(s *Stmt) error {
// if err = stmt.Scan(&id, &name); err != nil {
// return
// }
// fmt.Println(id, name)
// }
// return
// })
// // TODO error handling
//
// NULL value is converted to 0 if arg type is *int,*int64,*float,*float64, to "" for *string, to []byte{} for *[]byte and to false for *bool.
// TODO How to avoid NULL conversion?
......
......@@ -167,7 +167,7 @@ func TestInsertWithStatement(t *testing.T) {
db.Begin()
for i := 0; i < 1000; i++ {
c, ierr := s.ExecUpdate(float64(i)*float64(3.14), i, "hello")
c, ierr := s.ExecDml(float64(i)*float64(3.14), i, "hello")
checkNoError(t, ierr, "insert error: %s")
if c != 1 {
t.Errorf("insert error: %d but got 1", c)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment