handle>> db-close
] with-variable ;
-TUPLE: statement handle sql in-params out-params bind-params bound? type ;
+TUPLE: statement handle sql in-params out-params bind-params bound? type retries ;
TUPLE: simple-statement < statement ;
TUPLE: prepared-statement < statement ;
swap >>out-params
swap >>in-params
swap >>sql ;
-
+
: sql-row ( result-set -- seq )
dup #columns [ row-column ] with map ;
! See http://factorcode.org/license.txt for BSD license.
USING: accessors kernel math namespaces sequences random
strings math.parser math.intervals combinators
-math.bitfields.lib namespaces.lib db db.tuples db.types ;
+math.bitfields.lib namespaces.lib db db.tuples db.types
+sequences.lib db.sql classes words shuffle arrays ;
IN: db.queries
GENERIC: where ( specs obj -- )
] with filter ;
: where-clause ( tuple specs -- )
- dupd filter-slots
- dup empty? [
- 2drop
+ dupd filter-slots [
+ drop
] [
" where " 0% [
" and " 0%
] [
2dup slot-name>> swap get-slot-named where
] interleave drop
- ] if ;
+ ] if-empty ;
M: db <delete-tuples-statement> ( tuple table -- sql )
[
number>string " limit " prepend append
] curry change-sql drop ;
-: make-advanced-statement ( tuple advanced -- tuple' )
+: make-query ( tuple query -- tuple' )
dupd
{
[ group>> [ do-group ] [ drop ] if* ]
[ offset>> [ do-offset ] [ drop ] if* ]
} 2cleave ;
-M: db <advanced-select-statement> ( tuple class group order limit offset -- tuple )
- advanced-statement boa
- [ <select-by-slots-statement> ] dip make-advanced-statement ;
+M: db <query> ( tuple class group order limit offset -- tuple )
+ \ query boa
+ [ <select-by-slots-statement> ] dip make-query ;
+
+! select ID, NAME, SCORE from EXAM limit 1 offset 3
+
+: select-tuples* ( tuple -- statement )
+ dup
+ [
+ select 0,
+ dup class db-columns [ ", " 0, ]
+ [ dup column-name>> 0, 2, ] interleave
+ from 0,
+ class word-name 0,
+ ] { { } { } { } } nmake
+ >r >r parse-sql 4drop r> r>
+ <simple-statement> maybe-make-retryable do-select ;
+
+M: db <count-statement> ( tuple class groups -- statement )
+ f f f \ query boa
+ [ [ "select count(*) from " 0% 0% where-clause ] query-make ]
+ dip make-query ;
+
+: where-clause* ( tuple specs -- )
+ dupd filter-slots [
+ drop
+ ] [
+ \ where 0,
+ [ 2dup slot-name>> swap get-slot-named where ] map 2array 0,
+ drop
+ ] if-empty ;
+
+: delete-tuple* ( tuple -- sql )
+ dup
+ [
+ delete 0, from 0, dup class db-table 0,
+ dup class db-columns where-clause*
+ ] { { } { } { } } nmake
+ >r >r parse-sql 4drop r> r>
+ <simple-statement> maybe-make-retryable do-select ;
: sql-function, ( seq function -- )
sql% "(" sql% unclip sql% ")" sql% [ sql% ] each ;
+: sql-where ( seq -- )
+B
+ [
+ [ second 0, ]
+ [ first 0, ]
+ [ third 1, \ ? 0, ] tri
+ ] each ;
+
: sql-array% ( array -- )
+B
unclip
{
+ { \ create [ "create table" sql% ] }
+ { \ drop [ "drop table" sql% ] }
+ { \ insert [ "insert into" sql% ] }
+ { \ update [ "update" sql% ] }
+ { \ delete [ "delete" sql% ] }
+ { \ select [ B "select" sql% "," (sql-interleave) ] }
{ \ columns [ "," (sql-interleave) ] }
{ \ from [ "from" "," sql-interleave ] }
- { \ where [ "where" "and" sql-interleave ] }
+ { \ where [ B "where" 0, sql-where ] }
{ \ group-by [ "group by" "," sql-interleave ] }
{ \ having [ "having" "," sql-interleave ] }
{ \ order-by [ "order by" "," sql-interleave ] }
ERROR: no-sql-match ;
: sql% ( obj -- )
{
- { [ dup string? ] [ " " 0% 0% ] }
+ { [ dup string? ] [ 0, ] }
{ [ dup array? ] [ sql-array% ] }
{ [ dup number? ] [ number>string sql% ] }
{ [ dup symbol? ] [ unparse sql% ] }
} cond ;
: parse-sql ( obj -- sql in-spec out-spec in out )
- [
- unclip {
- { \ create [ "create table" sql% ] }
- { \ drop [ "drop table" sql% ] }
- { \ insert [ "insert into" sql% ] }
- { \ update [ "update" sql% ] }
- { \ delete [ "delete" sql% ] }
- { \ select [ "select" sql% ] }
- } case [ sql% ] each
- ] { "" { } { } { } { } } nmake ;
+ [ [ sql% ] each ] { { } { } { } } nmake ;
: random-exam ( -- exam )
f
- 6 [ CHAR: a CHAR: b [a,b] random ] replicate >string
+ 6 [ CHAR: a CHAR: z [a,b] random ] replicate >string
100 random
exam boa ;
}
] [
T{ exam } select-tuples
- ] unit-test ;
+ ] unit-test
+
+ [ 4 ] [ T{ exam } count-tuples ] unit-test ;
TUPLE: bignum-test id m n o ;
: <bignum-test> ( m n o -- obj )
HOOK: <update-tuple-statement> db ( class -- obj )
HOOK: <delete-tuples-statement> db ( tuple class -- obj )
HOOK: <select-by-slots-statement> db ( tuple class -- tuple )
-TUPLE: advanced-statement group order offset limit ;
-HOOK: <advanced-select-statement> db ( tuple class group order offset limit -- tuple )
+TUPLE: query group order offset limit ;
+HOOK: <query> db ( tuple class group order offset limit -- tuple )
+HOOK: <count-statement> db ( tuple class -- n )
HOOK: insert-tuple* db ( tuple statement -- )
[ make-retryable ] map
] [
retryable >>type
+ 10 >>retries
] if ;
: regenerate-params ( statement -- statement )
] 2map >>bind-params ;
M: retryable execute-statement* ( statement type -- )
- drop
- [
- [ query-results dispose t ]
- [ ]
- [ regenerate-params bind-statement* f ] cleanup
- ] curry 10 retry drop ;
+ drop [
+ [
+ [ query-results dispose t ]
+ [ ]
+ [ regenerate-params bind-statement* f ] cleanup
+ ] curry
+ ] [ retries>> ] bi retry drop ;
: resulting-tuple ( class row out-params -- tuple )
rot class new [
select-tuples length ;
: select-tuple ( tuple -- tuple/f )
- dup dup class f f f 1 <advanced-select-statement>
+ dup dup class f f f 1 <query>
do-select ?first ;
+
+: query ( tuple groups order offset limit -- tuples )
+ >r >r >r >r dup dup class r> r> r> r>
+ <query> do-select ;
+
+: do-count ( exemplar-tuple statement -- tuples )
+ [
+ [ bind-tuple ] [ nip default-query ] 2bi
+ ] with-disposal ;
+
+: count-tuples ( tuple groups -- n )
+ >r dup dup class r> <count-statement> do-count
+ dup length 1 = [ first first string>number ] [
+ [ first string>number ] map
+ ] if ;
continuations hashtables
hashtables.private io kernel math
namespaces prettyprint quotations sequences splitting
-state-parser strings ;
+strings ;
IN: html.parser.printer
SYMBOL: no-section
TUPLE: text-printer ;
TUPLE: ui-printer ;
TUPLE: src-printer ;
-UNION: printer text-printer ui-printer src-printer ;
+TUPLE: html-prettyprinter ;
+UNION: printer text-printer ui-printer src-printer html-prettyprinter ;
HOOK: print-tag printer ( tag -- )
HOOK: print-text-tag printer ( tag -- )
HOOK: print-comment-tag printer ( tag -- )
tag-text write
"-->" write ;
-M: printer print-dtd-tag
+M: printer print-dtd-tag ( tag -- )
"<!" write
tag-text write
">" write ;
M: src-printer print-opening-named-tag ( tag -- )
"<" write
- dup tag-name write
- tag-attributes dup assoc-empty? [ drop ] [ print-attributes ] if
+ [ tag-name write ]
+ [ tag-attributes dup assoc-empty? [ drop ] [ print-attributes ] if ] bi
">" write ;
M: src-printer print-closing-named-tag ( tag -- )
tag-name write
">" write ;
-TUPLE: unknown-tag-error tag ;
+SYMBOL: tab-width
+SYMBOL: #indentations
-C: <unknown-tag-error> unknown-tag-error
+: html-pp ( vector -- )
+ [
+ 0 #indentations set
+ 2 tab-width set
+
+ ] with-scope ;
+
+: print-tabs ( -- )
+ tab-width get #indentations get * CHAR: \s <repetition> write ;
+
+M: html-prettyprinter print-opening-named-tag ( tag -- )
+ print-tabs "<" write
+ tag-name write
+ ">\n" write ;
+
+M: html-prettyprinter print-closing-named-tag ( tag -- )
+ "</" write
+ tag-name write
+ ">" write ;
+
+ERROR: unknown-tag-error tag ;
M: printer print-tag ( tag -- )
{
[ print-closing-named-tag ] }
{ [ dup tag-name string? ]
[ print-opening-named-tag ] }
- [ <unknown-tag-error> throw ]
+ [ unknown-tag-error ]
} cond ;
-SYMBOL: tablestack
-
-: with-html-printer
- [
- V{ } clone tablestack set
- ] with-scope ;
+! SYMBOL: tablestack
+! : with-html-printer ( vector quot -- )
+ ! [ V{ } clone tablestack set ] with-scope ;
! { { 1 2 } { 3 4 } }
! H{ { table-gap { 10 10 } } } [
USING: assocs circular combinators continuations hashtables
hashtables.private io kernel math
namespaces prettyprint quotations sequences splitting
-state-parser strings ;
+state-parser strings sequences.lib ;
IN: html.parser.utils
: string-parse-end?
dup length rot length 1- - head next* ;
: trim1 ( seq ch -- newseq )
- [ ?head drop ] keep ?tail drop ;
+ [ ?head drop ] [ ?tail drop ] bi ;
: single-quote ( str -- newstr )
>r "'" r> "'" 3append ;
[ double-quote ] [ single-quote ] if ;
: quoted? ( str -- ? )
- dup length 1 > [
- [ first ] keep peek [ = ] keep "'\"" member? and
- ] [
- drop f
- ] if ;
+ [ [ first ] [ peek ] bi [ = ] keep "'\"" member? and ] [ f ] if-seq ;
: ?quote ( str -- newstr )
dup quoted? [ quote ] unless ;
dup quoted? [ but-last-slice rest-slice >string ] when ;
: quote? ( ch -- ? ) "'\"" member? ;
-