in-query returns a sequence of single value (#468)

this is an trade-off since dynamically-valued interfaces are almost impossible to typecheck
https://github.com/racket/typed-racket/pull/468

Also, the `SQL-Datum` is now more precision, since `Any` shadows
all opaque types (such as `SQL-Null`) which may lead to contract errors.
This commit is contained in:
WarGrey Gyoudmon Ju 2017-01-07 00:34:54 +08:00 committed by Sam Tobin-Hochstadt
parent 4e02bd44ab
commit 3077af848b
3 changed files with 47 additions and 13 deletions

View File

@ -1,24 +1,26 @@
#lang typed/racket
#lang typed/racket/base
(provide (all-defined-out))
(require (for-syntax racket/base))
(require (for-syntax racket/syntax))
(define-type Data-Source data-source)
(define-type Simple-Result simple-result)
(define-type Rows-Result rows-result)
(define-type Null-Mode (U 'preserve-null 'list))
(define-type Group-Mode (U 'preserve-null 'list))
(define-type Isolation-Level (U 'serializable 'repeatable-read 'read-committed 'read-uncommitted False))
(define-type Schema-Option (U 'search-or-current 'search 'current))
(define-type SQL-Datum Any)
(define-type SQL-Datum (U Boolean String Real Char Bytes SQL-Null))
(define-type SQL-Type (List Boolean (Option Symbol) SQL-Datum))
(define-type Statement (U String Prepared-Statement Virtual-Statement Statement-Binding))
(define-type SQL-Field (U String Natural))
(define-type SQL-Grouping (U SQL-Field (Vectorof SQL-Field)))
(define-type SQL-Group (U SQL-Grouping (Vectorof SQL-Grouping)))
(define-type SQL-Group (U SQL-Grouping (Listof SQL-Grouping)))
(define-type SQL-Dictionary (HashTable SQL-Field (U (Vectorof SQL-Datum) (Listof (Vectorof SQL-Datum)))))
(require/typed/provide
db/base
@ -59,22 +61,22 @@
(require/typed/provide
db/base
[query-exec (-> Connection Statement SQL-Datum * Void)]
[query-list (All (a) (-> Connection Statement SQL-Datum * (Listof a)))]
[query-list (-> Connection Statement SQL-Datum * (Listof SQL-Datum))]
[query-row (-> Connection Statement SQL-Datum * (Vectorof SQL-Datum))]
[query-maybe-row (-> Connection Statement SQL-Datum * (Option (Vectorof SQL-Datum)))]
[query-value (-> Connection Statement SQL-Datum * SQL-Datum)]
[query-maybe-value (-> Connection Statement SQL-Datum * (Option SQL-Datum))]
[query-rows (-> Connection Statement
[#:group SQL-Group]
[#:group-mode (Listof Null-Mode)]
[#:group-mode (Listof Group-Mode)]
SQL-Datum *
(Listof (Vectorof SQL-Datum)))]
[in-query (-> Connection Statement
[#:fetch (U Positive-Integer +inf.0)]
[#:group SQL-Group]
[#:group-mode (Listof Null-Mode)]
[#:group-mode (Listof Group-Mode)]
SQL-Datum *
(Sequenceof (Vectorof SQL-Datum)))])
(Sequenceof SQL-Datum))])
(require/typed/provide
db/base
@ -82,13 +84,13 @@
[#:struct rows-result ([headers : (Listof Any)] [rows : (Listof (Vectorof SQL-Datum))])]
[query (-> Connection Statement SQL-Datum * (U Simple-Result Rows-Result))]
[group-rows (->* (Rows-Result #:group SQL-Group)
(#:group-mode (Listof Null-Mode))
(#:group-mode (Listof Group-Mode))
Rows-Result)]
[rows->dict (->* (Rows-Result
#:key SQL-Field ; if Grouping/c: required a flat contract but got a chaperone one
#:key SQL-Field
#:value SQL-Grouping)
(#:value-mode (Listof Null-Mode))
(HashTable (U SQL-Field SQL-Null) SQL-Grouping))])
(#:value-mode (Listof Group-Mode))
SQL-Dictionary)])
(require/typed/provide
db/base

View File

@ -1,4 +1,4 @@
#lang typed/racket
#lang typed/racket/base
(provide (all-defined-out))

View File

@ -0,0 +1,32 @@
#lang typed/racket
;; https://github.com/racket/typed-racket/issues/460
;; https://github.com/racket/typed-racket/pull/468
(require typed/db)
(define sqlite : Connection (sqlite3-connect #:database 'memory))
(struct master ([id : Integer] [type : Symbol] [name : String] [sql : String])
#:prefab #:type-name Master
#:constructor-name make-master)
(define record : Master
(make-master (current-milliseconds) 'table "manual_index"
"CREATE TABLE manual_index(id, name, content);"))
(query-exec sqlite (master-sql record))
(query-exec sqlite "insert into manual_index values ($1, $2, $3)"
(master-id record) (master-name record) (~s record))
(for ([s (in-query sqlite "SELECT content FROM manual_index WHERE name = $1;" (master-name record))])
(define ?record (with-input-from-string (~a s) read))
(if (not (master? ?record))
(fprintf (current-error-port) "in-query: unexpected value: ~s"
?record)
(fprintf (current-output-port) "[~a]~a: ~s~n"
(master-type ?record)
(master-name ?record)
(master-sql ?record))))
(disconnect sqlite)