rothgar / gosqlite

Automatically exported from code.google.com/p/gosqlite
0 stars 0 forks source link

Execution of prepared statements don't update SQLite database #2

Open GoogleCodeExporter opened 8 years ago

GoogleCodeExporter commented 8 years ago
I'm very new to go, so apologies if this is a false positive.

What steps will reproduce the problem?
1. stmt := prepareStmt(...
2. stmt.Exec(bindings...
3.

What is the expected output? What do you see instead?
Starting on line 166: func (s *Stmt) Exec(args ...interface{}) os.Error
The function uses a for loop to bind all the parameters, but then immediately 
returns nil and doesn't execute the statement - well that's what I think is 
happening.

Avoiding prepared statements, and just using func (c *Conn) Exec(cmd string, 
args ...interface{}) os.Error works fine.

What version of the product are you using? On what operating system?
Currently Mac OS X.

Please provide any additional information below.
I think the (s *Stmt) Exec may need s.Finalize() before the return.

Thoughts?

Original issue reported on code.google.com by kro...@gmail.com on 22 Sep 2010 at 1:21

GoogleCodeExporter commented 8 years ago
Ok it looks like C.sqlite3_step(s.stmt) is never called for Prepared statements 
that are executed unlike func (c *Conn) Exec which calls  
C.sqlite3_step(s.stmt). 

I think C.sqlite3_step(s.stmt) (and error checking) should be moved out of func 
(c *Conn) Exec and put into func (s *Stmt) Exec.  Then func (c *Conn) Exec 
could return the result of func (s *Stmt) Exec.

Thoughts?

Original comment by kro...@gmail.com on 22 Sep 2010 at 1:33

GoogleCodeExporter commented 8 years ago
Ok, I've made the suggested changes and now it works as expected, at least by 
me - no idea what problems I may have introduced.  I've attached my "updated" 
version.

BTW this project is awesome.

Original comment by kro...@gmail.com on 22 Sep 2010 at 2:22

Attachments:

GoogleCodeExporter commented 8 years ago
I think it's better to not call Finalize in Stmt.Exec, since some people (like 
me) are reusing a Statement increase performance while doing millions of 
INSERTS.

If a Statement is reused, sqlite3_reset should be called after an error. 
Otherwise the next go call to Stmt.Exec will fail, and you end up dropping a 
valid INSERT after every INSERT that caused an error. So, what works for me, is 
to move the SQL execution out of Exec (which should probably be called Bind), 
and into a new Step() function, which just calls sqlite3_step. SQLite wrappers 
in other languages sometimes call this function something like ExecUpdate or 
Update, and then return the number of rows updated (or deleted) by the prepared 
statement.

func (s *Stmt) Step() os.Error {
    rv := C.sqlite3_step(s.stmt)
    err := Errno(rv)
    if err != Done {
        s.err = s.c.error(rv)
        C.sqlite3_reset(s.stmt)
        return s.err
    }
    return nil
}

Original comment by MattSpo...@gmail.com on 8 Oct 2010 at 7:54

Attachments: