factor/extra/db/postgresql/postgresql.factor

310 lines
8.3 KiB
Factor
Raw Normal View History

! 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
kernel math math.parser namespaces prettyprint quotations
sequences debugger db db.postgresql.lib db.postgresql.ffi
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-20 00:18:12 -04:00
namespaces.lib accessors random ;
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 < statement ;
2008-04-05 21:22:33 -04:00
TUPLE: postgresql-result-set < result-set ;
: <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
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
M: postgresql-statement bind-statement* ( statement -- )
2008-02-12 18:19:55 -05:00
drop ;
2008-02-01 18:43:44 -05:00
M: postgresql-statement bind-tuple ( tuple statement -- )
2008-04-20 00:18:12 -04:00
tuck in-params>>
[ slot-name>> swap get-slot-named ] with map
>>bind-params drop ;
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
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-04-20 00:48:07 -04:00
: result-handle-n ( result-set -- handle n )
[ handle>> ] [ n>> ] bi ;
2008-03-10 14:56:58 -04:00
M: postgresql-result-set row-column ( result-set column -- obj )
2008-04-20 00:48:07 -04:00
>r result-handle-n r> pq-get-string ;
2008-03-10 14:56:58 -04:00
M: postgresql-result-set row-column-typed ( result-set column -- obj )
2008-04-20 00:41:48 -04:00
dup pick out-params>> nth type>>
2008-04-20 00:48:07 -04:00
>r >r result-handle-n r> r> postgresql-column-typed ;
M: postgresql-statement query-results ( query -- result-set )
2008-04-20 00:41:48 -04:00
dup bind-params>> [
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
dup init-result-set ;
M: postgresql-result-set advance-row ( result-set -- )
2008-04-20 00:41:48 -04:00
[ 1+ ] change-n drop ;
M: postgresql-result-set more-rows? ( result-set -- ? )
2008-04-20 00:41:48 -04:00
[ n>> ] [ max>> ] bi < ;
2008-02-01 18:43:44 -05:00
M: postgresql-statement dispose ( query -- )
2008-04-20 00:41:48 -04:00
dup handle>> PQclear
f >>handle drop ;
M: postgresql-result-set dispose ( result-set -- )
2008-04-20 00:41:48 -04:00
[ handle>> PQclear ]
[
0 >>n
0 >>max
f >>handle drop
] bi ;
2008-02-01 18:43:44 -05:00
M: postgresql-statement prepare-statement ( statement -- )
2008-04-20 00:41:48 -04:00
dup
>r db get handle>> "" r>
[ sql>> ] [ in-params>> ] bi
length f PQprepare postgresql-error
>>handle drop ;
2008-02-01 18:43:44 -05:00
M: postgresql-db <simple-statement> ( sql in out -- statement )
2008-02-01 18:43:44 -05:00
<postgresql-statement> ;
M: postgresql-db <prepared-statement> ( sql in out -- statement )
<postgresql-statement> dup prepare-statement ;
M: postgresql-db begin-transaction ( -- )
"BEGIN" sql-command ;
M: postgresql-db commit-transaction ( -- )
"COMMIT" sql-command ;
M: postgresql-db rollback-transaction ( -- )
"ROLLBACK" sql-command ;
SYMBOL: postgresql-counter
: bind-name% ( -- )
CHAR: $ 0,
2008-04-20 00:41:48 -04:00
postgresql-counter [ inc ] [ get 0# ] bi ;
M: postgresql-db bind% ( spec -- )
2008-04-20 00:18:12 -04:00
bind-name% 1, ;
M: postgresql-db bind# ( spec obj -- )
>r bind-name% f swap type>> r> <literal-bind> 1, ;
: postgresql-make ( class quot -- )
>r sql-props r>
2008-03-15 08:57:38 -04:00
[ postgresql-counter off call ] { "" { } { } } nmake
<postgresql-statement> ; inline
: create-table-sql ( class -- statement )
[
"create table " 0% 0%
2008-04-20 00:18:12 -04:00
"(" 0% [ ", " 0% ] [
dup column-name>> 0%
" " 0%
2008-04-20 00:18:12 -04:00
dup type>> t lookup-type 0%
modifiers 0%
] interleave ");" 0%
] postgresql-make ;
: create-function-sql ( class -- statement )
[
>r remove-id r>
"create function add_" 0% dup 0%
"(" 0%
over [ "," 0% ]
[
2008-04-20 00:41:48 -04:00
type>> f lookup-type 0%
] interleave
")" 0%
" returns bigint as '" 0%
"insert into " 0%
dup 0%
"(" 0%
2008-04-20 00:41:48 -04:00
over [ ", " 0% ] [ column-name>> 0% ] interleave
") values(" 0%
swap [ ", " 0% ] [ drop bind-name% ] interleave
"); " 0%
"select currval(''" 0% 0% "_id_seq'');' language sql;" 0%
] postgresql-make ;
M: postgresql-db create-sql-statement ( class -- seq )
[
[ create-table-sql , ] keep
dup db-columns find-primary-key native-id?
[ create-function-sql , ] [ drop ] if
] { } make ;
: drop-function-sql ( class -- statement )
[
"drop function add_" 0% 0%
"(" 0%
remove-id
2008-04-20 00:41:48 -04:00
[ ", " 0% ] [ type>> f lookup-type 0% ] interleave
");" 0%
] postgresql-make ;
: drop-table-sql ( table -- statement )
[
"drop table " 0% 0% ";" 0% drop
] postgresql-make ;
M: postgresql-db drop-sql-statement ( class -- seq )
[
[ drop-table-sql , ] keep
dup db-columns find-primary-key native-id?
[ drop-function-sql , ] [ drop ] if
] { } make ;
M: postgresql-db <insert-native-statement> ( class -- statement )
[
"select add_" 0% 0%
"(" 0%
dup find-primary-key 2,
remove-id
[ ", " 0% ] [ bind% ] interleave
");" 0%
] postgresql-make ;
2008-03-17 01:26:05 -04:00
M: postgresql-db <insert-nonnative-statement> ( class -- statement )
[
"insert into " 0% 0%
"(" 0%
2008-04-20 00:41:48 -04:00
dup [ ", " 0% ] [ column-name>> 0% ] interleave
")" 0%
" values(" 0%
[ ", " 0% ] [ bind% ] interleave
");" 0%
] postgresql-make ;
M: postgresql-db insert-tuple* ( tuple statement -- )
query-modify-tuple ;
M: postgresql-db <update-tuple-statement> ( class -- statement )
[
"update " 0% 0%
" set " 0%
dup remove-id
[ ", " 0% ]
2008-04-20 00:41:48 -04:00
[ dup column-name>> 0% " = " 0% bind% ] interleave
" where " 0%
find-primary-key
2008-04-20 00:41:48 -04:00
dup column-name>> 0% " = " 0% bind%
] postgresql-make ;
M: postgresql-db <delete-tuple-statement> ( class -- statement )
[
"delete from " 0% 0%
" where " 0%
find-primary-key
2008-04-20 00:41:48 -04:00
dup column-name>> 0% " = " 0% bind%
] postgresql-make ;
M: postgresql-db <select-by-slots-statement> ( tuple class -- statement )
[
"select " 0%
over [ ", " 0% ]
2008-04-20 00:41:48 -04:00
[ dup column-name>> 0% 2, ] interleave
" from " 0% 0%
2008-04-20 00:41:48 -04:00
[ slot-name>> swap get-slot-named ] with subset
2008-03-10 18:00:28 -04:00
dup empty? [
drop
] [
" where " 0%
[ " and " 0% ]
2008-04-20 00:41:48 -04:00
[ dup column-name>> 0% " = " 0% bind% ] interleave
2008-03-10 18:00:28 -04:00
] if ";" 0%
] postgresql-make ;
M: postgresql-db type-table ( -- hash )
H{
{ +native-id+ "integer" }
2008-04-20 00:18:12 -04:00
{ +random-id+ "bigint" }
{ TEXT "text" }
{ VARCHAR "varchar" }
{ INTEGER "integer" }
{ DOUBLE "real" }
2008-03-10 18:00:28 -04:00
{ DATE "date" }
{ TIME "time" }
{ DATETIME "timestamp" }
{ TIMESTAMP "timestamp" }
2008-03-10 18:00:28 -04:00
{ BLOB "bytea" }
{ FACTOR-BLOB "bytea" }
} ;
M: postgresql-db create-type-table ( -- hash )
H{
{ +native-id+ "serial primary key" }
2008-04-20 00:18:12 -04:00
{ +random-id+ "bigint primary key" }
} ;
: postgresql-compound ( str n -- newstr )
over {
{ "default" [ first number>string join-space ] }
{ "varchar" [ first number>string paren append ] }
{ "references" [
first2 >r [ unparse join-space ] keep db-columns r>
2008-04-20 00:41:48 -04:00
swap [ slot-name>> = ] with find nip
column-name>> paren append
] }
[ "no compound found" 3array throw ]
} case ;
M: postgresql-db compound-modifier ( str seq -- newstr )
postgresql-compound ;
M: postgresql-db modifier-table ( -- hashtable )
H{
{ +native-id+ "primary key" }
{ +assigned-id+ "primary key" }
2008-04-20 00:18:12 -04:00
{ +random-id+ "primary key" }
{ +foreign-id+ "references" }
{ +autoincrement+ "autoincrement" }
{ +unique+ "unique" }
{ +default+ "default" }
{ +null+ "null" }
{ +not-null+ "not null" }
2008-04-20 00:18:12 -04:00
{ system-random-generator "" }
{ secure-random-generator "" }
{ random-generator "" }
} ;
M: postgresql-db compound-type ( str n -- newstr )
postgresql-compound ;