2008-02-03 16:06:31 -05:00
|
|
|
! Copyright (C) 2007, 2008 Doug Coleman.
|
2008-02-01 18:43:44 -05:00
|
|
|
! See http://factorcode.org/license.txt for BSD license.
|
|
|
|
USING: arrays assocs alien alien.syntax continuations io
|
2008-02-13 17:51:16 -05:00
|
|
|
kernel math math.parser namespaces prettyprint quotations
|
|
|
|
sequences debugger db db.postgresql.lib db.postgresql.ffi
|
2008-02-15 15:01:44 -05:00
|
|
|
db.tuples db.types tools.annotations math.ranges
|
2008-03-10 14:56:58 -04:00
|
|
|
combinators sequences.lib classes locals words tools.walker
|
2008-04-05 21:22:33 -04:00
|
|
|
namespaces.lib accessors ;
|
2008-02-01 18:43:44 -05:00
|
|
|
IN: db.postgresql
|
|
|
|
|
2008-04-05 21:22:33 -04:00
|
|
|
TUPLE: postgresql-db < db
|
|
|
|
host port pgopts pgtty db user pass ;
|
|
|
|
|
|
|
|
TUPLE: postgresql-statement < throwable-statement ;
|
|
|
|
|
|
|
|
TUPLE: postgresql-result-set < result-set ;
|
|
|
|
|
2008-02-22 18:06:00 -05:00
|
|
|
: <postgresql-statement> ( statement in out -- postgresql-statement )
|
2008-04-05 21:22:33 -04:00
|
|
|
postgresql-statement construct-statement ;
|
2008-02-01 18:43:44 -05:00
|
|
|
|
2008-02-25 15:50:42 -05:00
|
|
|
M: postgresql-db make-db* ( seq tuple -- db )
|
2008-04-05 21:22:33 -04:00
|
|
|
>r first4 r>
|
|
|
|
swap >>db
|
|
|
|
swap >>pass
|
|
|
|
swap >>user
|
|
|
|
swap >>host ;
|
|
|
|
|
|
|
|
M: postgresql-db db-open ( db -- db )
|
|
|
|
dup {
|
|
|
|
[ host>> ]
|
|
|
|
[ port>> ]
|
|
|
|
[ pgopts>> ]
|
|
|
|
[ pgtty>> ]
|
|
|
|
[ db>> ]
|
|
|
|
[ user>> ]
|
|
|
|
[ pass>> ]
|
|
|
|
} cleave connect-postgres >>handle ;
|
2008-02-01 18:43:44 -05:00
|
|
|
|
|
|
|
M: postgresql-db dispose ( db -- )
|
2008-04-05 21:22:33 -04:00
|
|
|
handle>> PQfinish ;
|
2008-02-01 18:43:44 -05:00
|
|
|
|
2008-02-27 19:28:32 -05:00
|
|
|
M: postgresql-statement bind-statement* ( statement -- )
|
2008-02-12 18:19:55 -05:00
|
|
|
drop ;
|
2008-02-01 18:43:44 -05:00
|
|
|
|
2008-02-22 18:06:00 -05:00
|
|
|
M: postgresql-statement bind-tuple ( tuple statement -- )
|
|
|
|
[
|
|
|
|
statement-in-params
|
|
|
|
[ sql-spec-slot-name swap get-slot-named ] with map
|
|
|
|
] keep set-statement-bind-params ;
|
|
|
|
|
2008-02-03 16:06:31 -05:00
|
|
|
M: postgresql-result-set #rows ( result-set -- n )
|
2008-04-05 21:22:33 -04:00
|
|
|
handle>> PQntuples ;
|
2008-02-01 18:43:44 -05:00
|
|
|
|
2008-02-03 16:06:31 -05:00
|
|
|
M: postgresql-result-set #columns ( result-set -- n )
|
2008-04-05 21:22:33 -04:00
|
|
|
handle>> PQnfields ;
|
2008-02-01 18:43:44 -05:00
|
|
|
|
2008-03-10 14:56:58 -04:00
|
|
|
M: postgresql-result-set row-column ( result-set column -- obj )
|
2008-03-10 18:00:28 -04:00
|
|
|
>r dup result-set-handle swap result-set-n r> pq-get-string ;
|
2008-02-03 00:28:33 -05:00
|
|
|
|
2008-03-10 14:56:58 -04:00
|
|
|
M: postgresql-result-set row-column-typed ( result-set column -- obj )
|
|
|
|
dup pick result-set-out-params nth sql-spec-type
|
|
|
|
>r >r [ result-set-handle ] [ result-set-n ] bi r> r> postgresql-column-typed ;
|
2008-02-15 15:01:44 -05:00
|
|
|
|
2008-02-03 16:06:31 -05:00
|
|
|
M: postgresql-statement query-results ( query -- result-set )
|
2008-02-22 18:06:00 -05:00
|
|
|
dup statement-bind-params [
|
2008-02-03 16:06:31 -05:00
|
|
|
over [ bind-statement ] keep
|
|
|
|
do-postgresql-bound-statement
|
|
|
|
] [
|
|
|
|
dup do-postgresql-statement
|
|
|
|
] if*
|
2008-04-05 21:22:33 -04:00
|
|
|
postgresql-result-set construct-result-set
|
2008-02-03 16:06:31 -05:00
|
|
|
dup init-result-set ;
|
|
|
|
|
2008-02-15 00:39:20 -05:00
|
|
|
M: postgresql-result-set advance-row ( result-set -- )
|
|
|
|
dup result-set-n 1+ swap set-result-set-n ;
|
|
|
|
|
|
|
|
M: postgresql-result-set more-rows? ( result-set -- ? )
|
|
|
|
dup result-set-n swap result-set-max < ;
|
2008-02-01 18:43:44 -05:00
|
|
|
|
|
|
|
M: postgresql-statement dispose ( query -- )
|
|
|
|
dup statement-handle PQclear
|
2008-02-03 00:28:33 -05:00
|
|
|
f swap set-statement-handle ;
|
|
|
|
|
|
|
|
M: postgresql-result-set dispose ( result-set -- )
|
|
|
|
dup result-set-handle PQclear
|
|
|
|
0 0 f roll {
|
2008-02-03 16:06:31 -05:00
|
|
|
set-result-set-n set-result-set-max set-result-set-handle
|
2008-02-03 00:28:33 -05:00
|
|
|
} set-slots ;
|
2008-02-01 18:43:44 -05:00
|
|
|
|
|
|
|
M: postgresql-statement prepare-statement ( statement -- )
|
|
|
|
[
|
2008-04-05 21:22:33 -04:00
|
|
|
>r db get handle>> "" r>
|
2008-02-20 12:30:48 -05:00
|
|
|
dup statement-sql swap statement-in-params
|
2008-02-03 16:06:31 -05:00
|
|
|
length f PQprepare postgresql-error
|
2008-02-01 18:43:44 -05:00
|
|
|
] keep set-statement-handle ;
|
|
|
|
|
2008-02-22 18:06:00 -05:00
|
|
|
M: postgresql-db <simple-statement> ( sql in out -- statement )
|
2008-02-01 18:43:44 -05:00
|
|
|
<postgresql-statement> ;
|
|
|
|
|
2008-02-22 18:06:00 -05:00
|
|
|
M: postgresql-db <prepared-statement> ( sql in out -- statement )
|
|
|
|
<postgresql-statement> dup prepare-statement ;
|
2008-02-03 16:06:31 -05:00
|
|
|
|
|
|
|
M: postgresql-db begin-transaction ( -- )
|
|
|
|
"BEGIN" sql-command ;
|
|
|
|
|
|
|
|
M: postgresql-db commit-transaction ( -- )
|
|
|
|
"COMMIT" sql-command ;
|
|
|
|
|
|
|
|
M: postgresql-db rollback-transaction ( -- )
|
|
|
|
"ROLLBACK" sql-command ;
|
2008-02-13 17:51:16 -05:00
|
|
|
|
2008-02-19 17:00:50 -05:00
|
|
|
SYMBOL: postgresql-counter
|
2008-02-22 18:06:00 -05:00
|
|
|
: bind-name% ( -- )
|
2008-02-19 17:00:50 -05:00
|
|
|
CHAR: $ 0,
|
|
|
|
postgresql-counter [ inc ] keep get 0# ;
|
2008-02-14 02:27:54 -05:00
|
|
|
|
2008-02-22 18:06:00 -05:00
|
|
|
M: postgresql-db bind% ( spec -- )
|
|
|
|
1, bind-name% ;
|
|
|
|
|
|
|
|
: postgresql-make ( class quot -- )
|
|
|
|
>r sql-props r>
|
2008-03-15 08:57:38 -04:00
|
|
|
[ postgresql-counter off call ] { "" { } { } } nmake
|
|
|
|
<postgresql-statement> ; inline
|
2008-02-14 02:27:54 -05:00
|
|
|
|
2008-02-22 18:06:00 -05:00
|
|
|
: create-table-sql ( class -- statement )
|
2008-02-19 17:00:50 -05:00
|
|
|
[
|
2008-02-22 18:06:00 -05:00
|
|
|
"create table " 0% 0%
|
|
|
|
"(" 0%
|
|
|
|
[ ", " 0% ] [
|
|
|
|
dup sql-spec-column-name 0%
|
|
|
|
" " 0%
|
|
|
|
dup sql-spec-type t lookup-type 0%
|
|
|
|
modifiers 0%
|
|
|
|
] interleave ");" 0%
|
|
|
|
] postgresql-make ;
|
2008-02-14 02:27:54 -05:00
|
|
|
|
2008-02-22 18:06:00 -05:00
|
|
|
: create-function-sql ( class -- statement )
|
2008-02-13 17:51:16 -05:00
|
|
|
[
|
2008-02-22 18:06:00 -05:00
|
|
|
>r remove-id r>
|
|
|
|
"create function add_" 0% dup 0%
|
|
|
|
"(" 0%
|
|
|
|
over [ "," 0% ]
|
|
|
|
[
|
|
|
|
sql-spec-type f lookup-type 0%
|
|
|
|
] interleave
|
|
|
|
")" 0%
|
|
|
|
" returns bigint as '" 0%
|
|
|
|
|
|
|
|
"insert into " 0%
|
|
|
|
dup 0%
|
|
|
|
"(" 0%
|
|
|
|
over [ ", " 0% ] [ sql-spec-column-name 0% ] interleave
|
|
|
|
") values(" 0%
|
|
|
|
swap [ ", " 0% ] [ drop bind-name% ] interleave
|
|
|
|
"); " 0%
|
|
|
|
"select currval(''" 0% 0% "_id_seq'');' language sql;" 0%
|
|
|
|
] postgresql-make ;
|
2008-02-13 17:51:16 -05:00
|
|
|
|
2008-02-22 18:06:00 -05:00
|
|
|
M: postgresql-db create-sql-statement ( class -- seq )
|
2008-02-13 17:51:16 -05:00
|
|
|
[
|
2008-02-22 18:06:00 -05:00
|
|
|
[ create-table-sql , ] keep
|
|
|
|
dup db-columns find-primary-key native-id?
|
2008-02-25 16:13:00 -05:00
|
|
|
[ create-function-sql , ] [ drop ] if
|
2008-02-19 17:00:50 -05:00
|
|
|
] { } make ;
|
2008-02-13 17:51:16 -05:00
|
|
|
|
2008-02-22 18:06:00 -05:00
|
|
|
: drop-function-sql ( class -- statement )
|
|
|
|
[
|
|
|
|
"drop function add_" 0% 0%
|
|
|
|
"(" 0%
|
|
|
|
remove-id
|
|
|
|
[ ", " 0% ] [ sql-spec-type f lookup-type 0% ] interleave
|
|
|
|
");" 0%
|
|
|
|
] postgresql-make ;
|
|
|
|
|
|
|
|
: drop-table-sql ( table -- statement )
|
|
|
|
[
|
|
|
|
"drop table " 0% 0% ";" 0% drop
|
2008-02-25 16:13:00 -05:00
|
|
|
] postgresql-make ;
|
2008-02-22 18:06:00 -05:00
|
|
|
|
|
|
|
M: postgresql-db drop-sql-statement ( class -- seq )
|
2008-02-19 17:00:50 -05:00
|
|
|
[
|
2008-02-22 18:06:00 -05:00
|
|
|
[ drop-table-sql , ] keep
|
|
|
|
dup db-columns find-primary-key native-id?
|
2008-02-25 16:13:00 -05:00
|
|
|
[ drop-function-sql , ] [ drop ] if
|
2008-02-19 17:00:50 -05:00
|
|
|
] { } make ;
|
2008-02-18 17:52:00 -05:00
|
|
|
|
2008-02-25 15:50:42 -05:00
|
|
|
M: postgresql-db <insert-native-statement> ( class -- statement )
|
2008-02-19 17:00:50 -05:00
|
|
|
[
|
2008-02-22 18:06:00 -05:00
|
|
|
"select add_" 0% 0%
|
2008-02-19 17:00:50 -05:00
|
|
|
"(" 0%
|
2008-02-22 18:06:00 -05:00
|
|
|
dup find-primary-key 2,
|
|
|
|
remove-id
|
2008-02-19 17:00:50 -05:00
|
|
|
[ ", " 0% ] [ bind% ] interleave
|
|
|
|
");" 0%
|
|
|
|
] postgresql-make ;
|
2008-02-18 17:52:00 -05:00
|
|
|
|
2008-03-17 01:26:05 -04:00
|
|
|
M: postgresql-db <insert-nonnative-statement> ( class -- statement )
|
2008-02-19 17:00:50 -05:00
|
|
|
[
|
2008-02-22 18:06:00 -05:00
|
|
|
"insert into " 0% 0%
|
2008-02-19 17:00:50 -05:00
|
|
|
"(" 0%
|
2008-02-22 18:06:00 -05:00
|
|
|
dup [ ", " 0% ] [ sql-spec-column-name 0% ] interleave
|
|
|
|
")" 0%
|
|
|
|
|
|
|
|
" values(" 0%
|
2008-02-19 17:00:50 -05:00
|
|
|
[ ", " 0% ] [ bind% ] interleave
|
|
|
|
");" 0%
|
|
|
|
] postgresql-make ;
|
|
|
|
|
2008-02-25 15:50:42 -05:00
|
|
|
M: postgresql-db insert-tuple* ( tuple statement -- )
|
|
|
|
query-modify-tuple ;
|
|
|
|
|
2008-02-24 13:32:36 -05:00
|
|
|
M: postgresql-db <update-tuple-statement> ( class -- statement )
|
2008-02-19 17:00:50 -05:00
|
|
|
[
|
|
|
|
"update " 0% 0%
|
|
|
|
" set " 0%
|
|
|
|
dup remove-id
|
|
|
|
[ ", " 0% ]
|
|
|
|
[ dup sql-spec-column-name 0% " = " 0% bind% ] interleave
|
|
|
|
" where " 0%
|
|
|
|
find-primary-key
|
|
|
|
dup sql-spec-column-name 0% " = " 0% bind%
|
2008-02-22 18:06:00 -05:00
|
|
|
] postgresql-make ;
|
2008-02-19 17:00:50 -05:00
|
|
|
|
2008-02-24 13:32:36 -05:00
|
|
|
M: postgresql-db <delete-tuple-statement> ( class -- statement )
|
2008-02-19 17:00:50 -05:00
|
|
|
[
|
|
|
|
"delete from " 0% 0%
|
|
|
|
" where " 0%
|
|
|
|
find-primary-key
|
|
|
|
dup sql-spec-column-name 0% " = " 0% bind%
|
2008-02-22 18:06:00 -05:00
|
|
|
] postgresql-make ;
|
2008-02-18 17:52:00 -05:00
|
|
|
|
2008-02-22 18:06:00 -05:00
|
|
|
M: postgresql-db <select-by-slots-statement> ( tuple class -- statement )
|
2008-02-19 17:00:50 -05:00
|
|
|
[
|
2008-02-22 18:06:00 -05:00
|
|
|
! tuple columns table
|
|
|
|
"select " 0%
|
|
|
|
over [ ", " 0% ]
|
2008-02-19 17:00:50 -05:00
|
|
|
[ dup sql-spec-column-name 0% 2, ] interleave
|
2008-02-18 17:52:00 -05:00
|
|
|
|
2008-02-22 18:06:00 -05:00
|
|
|
" from " 0% 0%
|
2008-02-19 17:00:50 -05:00
|
|
|
[ sql-spec-slot-name swap get-slot-named ] with subset
|
2008-03-10 18:00:28 -04:00
|
|
|
dup empty? [
|
|
|
|
drop
|
|
|
|
] [
|
|
|
|
" where " 0%
|
|
|
|
[ " and " 0% ]
|
|
|
|
[ dup sql-spec-column-name 0% " = " 0% bind% ] interleave
|
|
|
|
] if ";" 0%
|
2008-02-22 18:06:00 -05:00
|
|
|
] postgresql-make ;
|
2008-02-19 17:00:50 -05:00
|
|
|
|
|
|
|
M: postgresql-db type-table ( -- hash )
|
|
|
|
H{
|
|
|
|
{ +native-id+ "integer" }
|
|
|
|
{ TEXT "text" }
|
|
|
|
{ VARCHAR "varchar" }
|
|
|
|
{ INTEGER "integer" }
|
2008-02-21 16:57:18 -05:00
|
|
|
{ DOUBLE "real" }
|
2008-03-10 18:00:28 -04:00
|
|
|
{ DATE "date" }
|
|
|
|
{ TIME "time" }
|
|
|
|
{ DATETIME "timestamp" }
|
2008-02-20 12:30:48 -05:00
|
|
|
{ TIMESTAMP "timestamp" }
|
2008-03-10 18:00:28 -04:00
|
|
|
{ BLOB "bytea" }
|
|
|
|
{ FACTOR-BLOB "bytea" }
|
2008-02-19 17:00:50 -05:00
|
|
|
} ;
|
|
|
|
|
|
|
|
M: postgresql-db create-type-table ( -- hash )
|
|
|
|
H{
|
|
|
|
{ +native-id+ "serial primary key" }
|
|
|
|
} ;
|
|
|
|
|
|
|
|
: postgresql-compound ( str n -- newstr )
|
2008-02-20 12:30:48 -05:00
|
|
|
over {
|
2008-02-21 16:57:18 -05:00
|
|
|
{ "default" [ first number>string join-space ] }
|
|
|
|
{ "varchar" [ first number>string paren append ] }
|
|
|
|
{ "references" [
|
2008-02-20 12:30:48 -05:00
|
|
|
first2 >r [ unparse join-space ] keep db-columns r>
|
2008-02-21 16:57:18 -05:00
|
|
|
swap [ sql-spec-slot-name = ] with find nip
|
|
|
|
sql-spec-column-name paren append
|
|
|
|
] }
|
2008-02-20 12:30:48 -05:00
|
|
|
[ "no compound found" 3array throw ]
|
|
|
|
} case ;
|
2008-02-19 17:00:50 -05:00
|
|
|
|
2008-02-20 12:30:48 -05:00
|
|
|
M: postgresql-db compound-modifier ( str seq -- newstr )
|
2008-02-19 17:00:50 -05:00
|
|
|
postgresql-compound ;
|
2008-02-13 17:51:16 -05:00
|
|
|
|
2008-02-19 17:00:50 -05:00
|
|
|
M: postgresql-db modifier-table ( -- hashtable )
|
2008-02-13 17:51:16 -05:00
|
|
|
H{
|
2008-02-18 17:52:00 -05:00
|
|
|
{ +native-id+ "primary key" }
|
2008-02-13 17:51:16 -05:00
|
|
|
{ +assigned-id+ "primary key" }
|
2008-02-20 12:30:48 -05:00
|
|
|
{ +foreign-id+ "references" }
|
2008-02-13 17:51:16 -05:00
|
|
|
{ +autoincrement+ "autoincrement" }
|
|
|
|
{ +unique+ "unique" }
|
|
|
|
{ +default+ "default" }
|
|
|
|
{ +null+ "null" }
|
|
|
|
{ +not-null+ "not null" }
|
|
|
|
} ;
|
|
|
|
|
2008-02-19 17:00:50 -05:00
|
|
|
M: postgresql-db compound-type ( str n -- newstr )
|
|
|
|
postgresql-compound ;
|