Merge branch 'master' of git://factorcode.org/git/factor

db4
Slava Pestov 2008-09-25 02:46:48 -05:00
commit 583673afa8
10 changed files with 192 additions and 54 deletions

View File

@ -1,7 +1,7 @@
! Copyright (C) 2008 Doug Coleman. ! Copyright (C) 2008 Doug Coleman.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: classes kernel help.markup help.syntax sequences USING: classes kernel help.markup help.syntax sequences
alien assocs strings math multiline ; alien assocs strings math multiline quotations ;
IN: db IN: db
HELP: db HELP: db
@ -45,7 +45,22 @@ HELP: prepared-statement
{ $description } ; { $description } ;
HELP: result-set HELP: result-set
{ $description } ; { $description "An object encapsulating a raw SQL result object. There are two ways in which a result set can be accessed, but they are specific to the database backend in use."
{ $subsection "db-random-access-result-set" }
{ $subsection "db-sequential-result-set" }
} ;
HELP: init-result-set
{ $values
{ "result-set" result-set } }
{ $description "" } ;
HELP: new-result-set
{ $values
{ "query" "a query" } { "handle" alien } { "class" class }
{ "result-set" result-set } }
{ $description "Creates a new " { $link result-set } " object of type " { $snippet "class" } "." } ;
HELP: new-statement HELP: new-statement
{ $values { "sql" string } { "in" sequence } { "out" sequence } { "class" class } { "statement" statement } } { $values { "sql" string } { "in" sequence } { "out" sequence } { "class" class } { "statement" statement } }
@ -81,7 +96,7 @@ HELP: query-results
{ $values { "query" object } { $values { "query" object }
{ "result-set" result-set } { "result-set" result-set }
} }
{ $description "" } ; { $description "Returns a " { $link result-set } " object representing the reults of a SQL query." } ;
HELP: #rows HELP: #rows
{ $values { "result-set" result-set } { "n" integer } } { $values { "result-set" result-set } { "n" integer } }
@ -95,32 +110,119 @@ HELP: row-column
{ $values { "result-set" result-set } { "column" integer } { $values { "result-set" result-set } { "column" integer }
{ "obj" object } { "obj" object }
} }
{ $description "" } ; { $description "Returns the value indexed by " { $snippet "column" } " in the current row of a " { $link result-set } "." } ;
HELP: row-column-typed HELP: row-column-typed
{ $values { "result-set" result-set } { "column" integer } { $values { "result-set" result-set } { "column" integer }
{ "sql" "sql" } } { "sql" "sql" } }
{ $description "" } ; { $description "Returns the value indexed by " { $snippet "column" } " in the current row of a " { $link result-set } " and converts the result based on a type stored in the " { $link result-set } "'s " { $slot "out-params" } "." } ;
HELP: advance-row HELP: advance-row
{ $values { "result-set" result-set } } { $values { "result-set" result-set } }
; { $description "Advanced the pointer to an underlying SQL result set stored in a " { $link result-set } " object." } ;
HELP: more-rows? HELP: more-rows?
{ $values { "result-set" result-set } { "?" "a boolean" } } { $values { "result-set" result-set } { "?" "a boolean" } }
; { $description "Returns true if the " { $link result-set } " has more rows to traverse." } ;
HELP: execute-statement* HELP: execute-statement*
{ $values { "statement" statement } { "type" object } } { $values { "statement" statement } { "type" object } }
{ $description } ; { $description } ;
HELP: execute-one-statement
{ $values
{ "statement" null } }
{ $description "" } ;
HELP: execute-statement HELP: execute-statement
{ $values { "statement" statement } } { $values { "statement" statement } }
{ $description } ; { $description "" } ;
HELP: begin-transaction
{ $description "Begins a new transaction. User code should make use of the " { $link with-transaction } " combinator." } ;
HELP: bind-statement
{ $values
{ "obj" object } { "statement" null } }
{ $description "" } ;
HELP: commit-transaction
{ $description "Commits a transaction. User code should make use of the " { $link with-transaction } " combinator." } ;
HELP: default-query
{ $values
{ "query" null }
{ "result-set" null } }
{ $description "" } ;
HELP: in-transaction
{ $description "A variable that is set true when a transaction is in progress." } ;
HELP: in-transaction?
{ $values
{ "?" "a boolean" } }
{ $description "Returns true if there is currently a transaction in progress in this scope." } ;
HELP: query-each
{ $values
{ "statement" null } { "quot" quotation } }
{ $description "" } ;
HELP: query-map
{ $values
{ "statement" null } { "quot" quotation }
{ "seq" sequence } }
{ $description "" } ;
HELP: rollback-transaction
{ $description "Rolls back a transaction; no data is committed to the database. User code should make use of the " { $link with-transaction } " combinator." } ;
HELP: sql-command
{ $values
{ "sql" string } }
{ $description "Executes a SQL string using the databse in the " { $link db } " symbol." } ;
HELP: sql-query
{ $values
{ "sql" string }
{ "rows" "an array of arrays of strings" } }
{ $description "Runs a SQL query of raw text in the database in the " { $link db } " symbol. Each row is returned as an array of strings; no type-conversions are done on the resulting data." } ;
{ sql-command sql-query } related-words
HELP: sql-row
{ $values
{ "result-set" result-set }
{ "seq" sequence } }
{ $description "Returns the current row in a " { $link result-set } " as an array of strings." } ;
HELP: sql-row-typed
{ $values
{ "result-set" result-set }
{ "seq" sequence } }
{ $description "Returns the current row in a " { $link result-set } " as an array of typed Factor objects." } ;
{ sql-row sql-row-typed } related-words
HELP: with-db
{ $values
{ "seq" sequence } { "class" class } { "quot" quotation } }
{ $description "Calls the quotation with a database bound to the " { $link db } " symbol. The database called is based on the " { $snippet "class" } " with the " } ;
HELP: with-transaction
{ $values
{ "quot" quotation } }
{ $description "" } ;
ARTICLE: "db" "Database library" ARTICLE: "db" "Database library"
{ $subsection "db-custom-database-combinators" } { $subsection "db-custom-database-combinators" }
{ $subsection "db-protocol" } { $subsection "db-protocol" }
{ $subsection "db-result-sets" }
{ $subsection "db-lowlevel-tutorial" } { $subsection "db-lowlevel-tutorial" }
"Higher-level database:" "Higher-level database:"
{ $vocab-subsection "Database types" "db.types" } { $vocab-subsection "Database types" "db.types" }
@ -135,6 +237,40 @@ ARTICLE: "db" "Database library"
{ $subsection "db-porting-the-library" } { $subsection "db-porting-the-library" }
; ;
ARTICLE: "db-random-access-result-set" "Random access result sets"
"Random-access result sets do not have to be traversed in order. For instance, PostgreSQL's result set object can be accessed as a matrix with i,j coordinates."
$nl
"Databases which work in this way must provide methods for the following traversal words:"
{ $subsection #rows }
{ $subsection #columns }
{ $subsection row-column }
{ $subsection row-column-typed } ;
ARTICLE: "db-sequential-result-set" "Sequential result sets"
"Sequential result sets can be iterated one element after the next. SQLite's result sets offer this method of traversal."
$nl
"Databases which work in this way must provide methods for the following traversal words:"
{ $subsection more-rows? }
{ $subsection advance-row }
{ $subsection row-column }
{ $subsection row-column-typed } ;
ARTICLE: "db-result-sets" "Result sets"
"Result sets are the encapsulated, database-specific results from a SQL query."
$nl
"Two possible protocols for iterating over result sets exist:"
{ $subsection "db-random-access-result-set" }
{ $subsection "db-sequential-result-set" }
"Query the number of rows or columns:"
{ $subsection #rows }
{ $subsection #columns }
"Traversing a result set:"
{ $subsection advance-row }
{ $subsection more-rows? }
"Pulling out a single row of results:"
{ $subsection row-column }
{ $subsection row-column-typed } ;
ARTICLE: "db-protocol" "Low-level database protocol" ARTICLE: "db-protocol" "Low-level database protocol"
"The high-level protocol (see " { $vocab-link "db.tuples" } ") uses this low-level protocol for executing statements and queries." "The high-level protocol (see " { $vocab-link "db.tuples" } ") uses this low-level protocol for executing statements and queries."
; ;
@ -157,7 +293,6 @@ USING: db.sqlite db io.files ;
{ "my-database.db" temp-file } sqlite-db rot with-db ; { "my-database.db" temp-file } sqlite-db rot with-db ;
"> } "> }
; ;
ABOUT: "db" ABOUT: "db"

View File

@ -80,11 +80,14 @@ GENERIC: execute-statement* ( statement type -- )
M: object execute-statement* ( statement type -- ) M: object execute-statement* ( statement type -- )
drop query-results dispose ; drop query-results dispose ;
: execute-one-statement ( statement -- )
dup type>> execute-statement* ;
: execute-statement ( statement -- ) : execute-statement ( statement -- )
dup sequence? [ dup sequence? [
[ execute-statement ] each [ execute-one-statement ] each
] [ ] [
dup type>> execute-statement* execute-one-statement
] if ; ] if ;
: bind-statement ( obj statement -- ) : bind-statement ( obj statement -- )

View File

@ -1,7 +1,7 @@
! Copyright (C) 2008 Doug Coleman. ! Copyright (C) 2008 Doug Coleman.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: classes help.markup help.syntax io.streams.string kernel USING: classes help.markup help.syntax io.streams.string kernel
quotations sequences strings multiline math ; quotations sequences strings multiline math db.types ;
IN: db.tuples IN: db.tuples
HELP: define-persistent HELP: define-persistent

View File

@ -518,6 +518,7 @@ string-encoding-test "STRING_ENCODING_TEST" {
! [ ] [ T{ exam f f "Kenny" 60 } insert-tuple ] unit-test ! [ ] [ T{ exam f f "Kenny" 60 } insert-tuple ] unit-test
! [ ] [ T{ exam f f "Cartman" 41 } insert-tuple ] unit-test ! [ ] [ T{ exam f f "Cartman" 41 } insert-tuple ] unit-test
[ ] [ 10 [ random-exam insert-tuple ] times ] unit-test [ ] [ 10 [ random-exam insert-tuple ] times ] unit-test
[ 5 ] [ <query> T{ exam { score T{ interval { from { 0 t } } { to { 100 t } } } } } >>tuple 5 >>limit select-tuples length ] unit-test
! [ ] [ T{ exam { name "Kenny" } } >query ] unit-test ! [ ] [ T{ exam { name "Kenny" } } >query ] unit-test
! [ ] [ query ] unit-test ! [ ] [ query ] unit-test
; ;

View File

@ -3,7 +3,7 @@
USING: arrays assocs classes db kernel namespaces USING: arrays assocs classes db kernel namespaces
classes.tuple words sequences slots math accessors classes.tuple words sequences slots math accessors
math.parser io prettyprint db.types continuations math.parser io prettyprint db.types continuations
destructors mirrors sets ; destructors mirrors sets db.types ;
IN: db.tuples IN: db.tuples
<PRIVATE <PRIVATE

View File

@ -1,14 +1,9 @@
! Copyright (C) 2008 Doug Coleman. ! Copyright (C) 2008 Doug Coleman.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: classes hashtables help.markup help.syntax io.streams.string kernel sequences strings ; USING: classes hashtables help.markup help.syntax io.streams.string
kernel sequences strings math ;
IN: db.types IN: db.types
HELP: (lookup-type)
{ $values
{ "obj" object }
{ "string" string } }
{ $description "" } ;
HELP: +autoincrement+ HELP: +autoincrement+
{ $description "" } ; { $description "" } ;
@ -55,7 +50,7 @@ HELP: <low-level-binding>
{ $description "" } ; { $description "" } ;
HELP: BIG-INTEGER HELP: BIG-INTEGER
{ $description "A 64-bit integer." } ; { $description "A 64-bit integer. Whether this number is signed or unsigned depends on the database backend." } ;
HELP: BLOB HELP: BLOB
{ $description "A serialized Factor object. The database library automatically serializes the object for a SQL insert or update and deserializes it on a tuple query." } ; { $description "A serialized Factor object. The database library automatically serializes the object for a SQL insert or update and deserializes it on a tuple query." } ;
@ -73,13 +68,13 @@ HELP: DOUBLE
{ $description "Corresponds to Factor's 64bit floating-point numbers." } ; { $description "Corresponds to Factor's 64bit floating-point numbers." } ;
HELP: FACTOR-BLOB HELP: FACTOR-BLOB
{ $description "" } ; { $description "A serialized Factor object." } ;
HELP: INTEGER HELP: INTEGER
{ $description "" } ; { $description "A small integer, at least 32 bits in length. Whether this number is signed or unsigned depends on the database backend." } ;
HELP: NULL HELP: NULL
{ $description "" } ; { $description "The SQL null type." } ;
HELP: REAL HELP: REAL
{ $description "" } ; { $description "" } ;
@ -94,16 +89,18 @@ HELP: TIME
{ $description "" } ; { $description "" } ;
HELP: TIMESTAMP HELP: TIMESTAMP
{ $description "" } ; { $description "A Factor timestamp." } ;
HELP: UNSIGNED-BIG-INTEGER HELP: UNSIGNED-BIG-INTEGER
{ $description "" } ; { $description "For portability, if a number is known to be 64bit, then this datatype may be used. Some databases, like SQLite, cannot store arbitrary bignums as BIGINT types. If storing arbitrary bignums, use " { $link FACTOR-BLOB } "." } ;
{ INTEGER SIGNED-BIG-INTEGER UNSIGNED-BIG-INTEGER } related-words
HELP: URL HELP: URL
{ $description "" } ; { $description "A Factor " { $link "urls" } " object." } ;
HELP: VARCHAR HELP: VARCHAR
{ $description "" } ; { $description "The SQL varchar type. This type can take an integer as an argument." } ;
HELP: assigned-id-spec? HELP: assigned-id-spec?
{ $values { $values
@ -135,18 +132,19 @@ HELP: db-assigned-id-spec?
HELP: find-primary-key HELP: find-primary-key
{ $values { $values
{ "specs" null } { "specs" "an array of sql-specs" }
{ "obj" object } } { "obj" object } }
{ $description "" } ; { $description "Returns the row from the sql-specs array." }
{ $notes "This is a low-level word." } ;
HELP: generator-bind HELP: generator-bind
{ $description "" } ; { $description "" } ;
HELP: get-slot-named HELP: get-slot-named
{ $values { $values
{ "name" null } { "obj" object } { "name" "a slot name" } { "tuple" tuple }
{ "value" null } } { "value" "the value stored in the slot" } }
{ $description "" } ; { $description "Returns the value stored in a tuple slot, where the tuple slot is a string." } ;
HELP: join-space HELP: join-space
{ $values { $values
@ -192,23 +190,11 @@ HELP: normalize-spec
{ "spec" null } } { "spec" null } }
{ $description "" } ; { $description "" } ;
HELP: number>string*
{ $values
{ "n/string" null }
{ "string" string } }
{ $description "" } ;
HELP: offset-of-slot HELP: offset-of-slot
{ $values { $values
{ "string" string } { "obj" object } { "string" string } { "tuple" tuple }
{ "n" null } } { "n" integer } }
{ $description "" } ; { $description "Returns the offset of a tuple slot accessed by name." } ;
HELP: paren
{ $values
{ "string" string }
{ "new-string" null } }
{ $description "" } ;
HELP: persistent-table HELP: persistent-table
{ $values { $values
@ -294,7 +280,6 @@ ARTICLE: "db.types" "Database types"
{ $subsection BLOB } { $subsection BLOB }
{ $subsection FACTOR-BLOB } { $subsection FACTOR-BLOB }
"Factor URLs:" "Factor URLs:"
{ $subsection URL } { $subsection URL } ;
;
ABOUT: "db.types" ABOUT: "db.types"

View File

@ -126,11 +126,11 @@ ERROR: no-sql-type ;
HOOK: bind% db ( spec -- ) HOOK: bind% db ( spec -- )
HOOK: bind# db ( spec obj -- ) HOOK: bind# db ( spec obj -- )
: offset-of-slot ( string obj -- n ) : offset-of-slot ( string tuple -- n )
class superclasses [ "slots" word-prop ] map concat class superclasses [ "slots" word-prop ] map concat
slot-named offset>> ; slot-named offset>> ;
: get-slot-named ( name obj -- value ) : get-slot-named ( name tuple -- value )
tuck offset-of-slot slot ; tuck offset-of-slot slot ;
: set-slot-named ( value name obj -- ) : set-slot-named ( value name obj -- )

View File

@ -141,3 +141,12 @@ link-no-follow? off
[ "<p><a href='Factor'>Factor</a>-rific!</p>" ] [ "<p><a href='Factor'>Factor</a>-rific!</p>" ]
[ "[[Factor]]-rific!" convert-farkup ] unit-test [ "[[Factor]]-rific!" convert-farkup ] unit-test
[ "<p>[ factor { 1 2 3 }]</p>" ]
[ "[ factor { 1 2 3 }]" convert-farkup ] unit-test
[ "<p>paragraph\n<hr/></p>" ]
[ "paragraph\n___" convert-farkup ] unit-test
[ "<p>paragraph\n a ___ b</p>" ]
[ "paragraph\n a ___ b" convert-farkup ] unit-test

View File

@ -38,6 +38,7 @@ TUPLE: line ;
EBNF: parse-farkup EBNF: parse-farkup
nl = ("\r\n" | "\r" | "\n") => [[ drop "\n" ]] nl = ("\r\n" | "\r" | "\n") => [[ drop "\n" ]]
whitespace = " " | "\t" | nl
heading1 = "=" (!("=" | nl).)+ "=" heading1 = "=" (!("=" | nl).)+ "="
=> [[ second >string heading1 boa ]] => [[ second >string heading1 boa ]]
@ -107,7 +108,7 @@ table = ((table-row nl => [[ first ]] )+ table-row? | table-row)
text = (!(nl | code | heading | inline-delimiter | table ).)+ text = (!(nl | code | heading | inline-delimiter | table ).)+
=> [[ >string ]] => [[ >string ]]
paragraph-item = (table | nl list | code | text | inline-tag | inline-delimiter)+ paragraph-item = (table | nl list | nl line | code | text | inline-tag | inline-delimiter)+
paragraph = ((paragraph-item nl => [[ first ]])+ nl+ => [[ first ]] paragraph = ((paragraph-item nl => [[ first ]])+ nl+ => [[ first ]]
| (paragraph-item nl)+ paragraph-item? | (paragraph-item nl)+ paragraph-item?
| paragraph-item) | paragraph-item)
@ -133,7 +134,7 @@ line = '___'
=> [[ drop line new ]] => [[ drop line new ]]
named-code = '[' (!('{' | nl | '[').)+ '{' (!("}]").)+ "}]" named-code = '[' (!('{' | whitespace | '[').)+ '{' (!("}]").)+ "}]"
=> [[ [ second >string ] [ fourth >string ] bi code boa ]] => [[ [ second >string ] [ fourth >string ] bi code boa ]]
simple-code simple-code

View File

@ -28,6 +28,10 @@ Ordered lists:
# with three # with three
# numbered items # numbered items
Horizontal lines:
___
Tables: Tables:
|a table|with|four|columns| |a table|with|four|columns|