add last inserted row, # changes to simple-result info

The info keys are 'insert-id, 'affected-rows, as for mysql.
This commit is contained in:
Ryan Culpepper 2012-12-27 21:03:07 -05:00
parent a6f03ee38f
commit 681558328e
6 changed files with 75 additions and 51 deletions

View File

@ -362,7 +362,7 @@
[(struct ok-packet (affected-rows insert-id status warnings message))
(when wbox (set-box! wbox warnings))
(vector 'command `((affected-rows . ,affected-rows)
(insert-id . ,insert-id)
(insert-id . ,(if (zero? insert-id) #f insert-id))
(status . ,status)
(message . ,message)))]
[(struct result-set-header-packet (fields extra))

View File

@ -379,7 +379,7 @@
(define/private (query1:expect-completion fsym)
(match (recv-message fsym)
[(struct CommandComplete (command)) `((command . ,command))]
[(struct CommandComplete (command)) command]
[(struct EmptyQueryResponse ()) '()]
[other-r (query1:error fsym other-r)]))

View File

@ -267,7 +267,7 @@
(define (parse:CommandComplete p)
(with-length-in p #\C
(let* ([command (io:read-null-terminated-string p)])
(make-CommandComplete command))))
(make-CommandComplete (string->command-alist command)))))
(define-struct CopyInResponse (format column-formats) #:transparent)
(define (parse:CopyInResponse p)
@ -527,45 +527,25 @@
[(transaction) #\T]
[(failed) #\E]))
(define (string->command s)
(cond [(regexp-match #rx"^SELECT *$" s)
=> (lambda (m) (list 'select))]
[(regexp-match #rx"^INSERT ([0-9]*) ([0-9]*) *$" s)
(define (string->command-alist s)
(cond [(regexp-match #rx"^INSERT ([0-9]*) ([0-9]*) *$" s)
=> (lambda (m)
(list 'insert
(string->number (cadr m))
(string->number (caddr m))))]
[(regexp-match #rx"^DELETE ([0-9]* *$)" s)
`((insert-id . ,(let ([oid (string->number (cadr m))])
(if (zero? oid) #f oid)))
(affected-rows . ,(string->number (caddr m)))))]
[(regexp-match #rx"^DELETE ([0-9]*) *$" s)
=> (lambda (m)
(list 'delete (string->number (cadr m))))]
`((affected-rows . ,(string->number (cadr m)))))]
[(regexp-match #rx"^UPDATE ([0-9]*) *$" s)
=> (lambda (m)
(list 'update (string->number (cadr m))))]
[(regexp-match #rx"^MOVE ([0-9]*) *$" s)
=> (lambda (m)
(list 'move (string->number (cadr m))))]
[(regexp-match #rx"^FETCH ([0-9]*) *$" s)
=> (lambda (m)
(list 'fetch (string->number (cadr m))))]
[(regexp-match #rx"^(CREATE|ALTER|DROP) ([A-Z]*) *$" s)
=> (lambda (m)
(list (string->symbol (string-downcase (cadr m)))
(string->symbol (string-downcase (caddr m)))))]
[else s]))
(define (command->string s)
(if (list? s)
(apply string-append
(case (car s)
[(insert) "INSERT"]
[(delete) "DELETE"]
[(update) "UPDATE"]
[(move) "MOVE"]
[(fetch) "FETCH"]
[else s])
(map (lambda (n) (format " ~a" n))
(cdr s)))
s))
`((affected-rows . ,(string->number (cadr m)))))]
#|
[(regexp-match #rx"^SELECT *$" s) ...]
[(regexp-match #rx"^MOVE ([0-9]*) *$" s) ...]
[(regexp-match #rx"^FETCH ([0-9]*) *$" s) ...]
[(regexp-match #rx"^(CREATE|ALTER|DROP) ([A-Z]*) *$" s) ...]
|#
[else '()]))
;; dvec layout is #(name table-oid col-oid typeid typelen typemod text/binary)

View File

@ -67,13 +67,17 @@
(for ([i (in-naturals 1)]
[param (in-list params)])
(load-param fsym db stmt i param))
(let ([info
(for/list ([i (in-range (sqlite3_column_count stmt))])
`((name . ,(sqlite3_column_name stmt i))
(decltype . ,(sqlite3_column_decltype stmt i))))]
[result
(or cursor?
(step* fsym db stmt #f +inf.0))])
(let* ([info
(for/list ([i (in-range (sqlite3_column_count stmt))])
`((name . ,(sqlite3_column_name stmt i))
(decltype . ,(sqlite3_column_decltype stmt i))))]
[saved-last-insert-rowid
(and (null? info) (sqlite3_last_insert_rowid db))]
[saved-total-changes
(and (null? info) (sqlite3_total_changes db))]
[result
(or cursor?
(step* fsym db stmt #f +inf.0))])
(unless (eq? (get-tx-status) 'invalid)
(set-tx-status! fsym (read-tx-status)))
(unless cursor?
@ -83,7 +87,18 @@
[(and (pair? info) cursor?)
(cursor-result info pst (box #f))]
[else
(simple-result '())])))))
(simple-result
(let ([last-insert-rowid (sqlite3_last_insert_rowid db)]
[total-changes (sqlite3_total_changes db)])
;; Not all statements clear last_insert_rowid, changes; so
;; extra guards to make sure results are relevant.
`((insert-id
. ,(and (not (= last-insert-rowid saved-last-insert-rowid))
last-insert-rowid))
(affected-rows
. ,(if (> total-changes saved-total-changes)
(sqlite3_changes db)
0)))))])))))
(define/public (fetch/cursor fsym cursor fetch-size)
(let ([pst (cursor-result-pst cursor)]

View File

@ -182,10 +182,14 @@
(_fun _sqlite3_database
-> _int))
(define-sqlite sqlite3_last_insert_rowid
(define-sqlite sqlite3_total_changes
(_fun _sqlite3_database
-> _int))
(define-sqlite sqlite3_last_insert_rowid
(_fun _sqlite3_database
-> _int64))
;; ----------------------------------------
#|

View File

@ -297,14 +297,39 @@ A general query result is either a @racket[simple-result] or a
@racket[rows-result].
@defstruct*[simple-result
([info any/c])]{
([info (listof (cons/c symbol? any/c))])]{
Represents the result of a SQL statement that does not return a
relation, such as an @tt{INSERT} or @tt{DELETE} statement.
The @racket[info] field is usually an association list, but do not
rely on its contents; it varies based on database system and may
change in future versions of this library (even new minor versions).
The @racket[info] field is an association list, but its contents vary
based on database system and may change in future versions of this
library (even new minor versions). The following keys are supported for
multiple database systems:
@itemlist[
@item{@racket['insert-id]: If the value is a positive integer, the
statement was an @tt{INSERT} statement and the value is a
system-specific identifier for the inserted row. For PostgreSQL, the
value is the row's OID, if the table has OIDs (for an alternative, see
the @tt{INSERT ... RETURNING} statement). For MySQL, the value is the
same as the result of
@hyperlink["http://dev.mysql.com/doc/refman/5.0/en/information-functions.html#function_last-insert-id"]{last_insert_id}
function---that is, the value of the row's @tt{AUTO_INCREMENT}
field. If there is no such field, the value is @racket[#f]. For
SQLite, the value is the same as the result of the
@hyperlink["http://www.sqlite.org/lang_corefunc.html#last_insert_rowid"]{last_insert_rowid}
function---that is, the
@hyperlink["http://www.sqlite.org/lang_createtable.html#rowid"]{ROWID}
of the inserted row.}
@item{@racket['affected-rows]: The number (a nonnegative integer) of
rows inserted by an @tt{INSERT} statement, modified by an @tt{UPDATE}
statement, or deleted by a @tt{DELETE} statement. Only directly
affected rows are counted; rows affected because of triggers or
integrity constraint actions are not counted.}
]
}
@defstruct*[rows-result