factor/basis/db/postgresql/lib/lib.factor

176 lines
5.6 KiB
Factor
Raw Normal View History

! Copyright (C) 2008 Doug Coleman.
! See http://factorcode.org/license.txt for BSD license.
2008-02-01 18:43:44 -05:00
USING: arrays continuations db io kernel math namespaces
quotations sequences db.postgresql.ffi alien alien.c-types
alien.data db.types tools.walker ascii splitting math.parser
combinators libc calendar.format byte-arrays destructors
prettyprint accessors strings serialize io.encodings.binary
io.encodings.utf8 alien.strings io.streams.byte-array summary
present urls specialized-arrays db.private ;
SPECIALIZED-ARRAY: uint
SPECIALIZED-ARRAY: void*
2008-02-01 18:43:44 -05:00
IN: db.postgresql.lib
: postgresql-result-error-message ( res -- str/f )
dup zero? [
drop f
] [
PQresultErrorMessage [ blank? ] trim
2008-02-01 18:43:44 -05:00
] if ;
: postgres-result-error ( res -- )
postgresql-result-error-message [ throw ] when* ;
: (postgresql-error-message) ( handle -- str )
PQerrorMessage
"\n" split [ [ blank? ] trim ] map "\n" join ;
2008-02-01 18:43:44 -05:00
: postgresql-error-message ( -- str )
2008-12-17 22:04:17 -05:00
db-connection get handle>> (postgresql-error-message) ;
2008-02-01 18:43:44 -05:00
: postgresql-error ( res -- res )
dup [ postgresql-error-message throw ] unless ;
2008-04-20 00:18:12 -04:00
ERROR: postgresql-result-null ;
M: postgresql-result-null summary ( obj -- str )
drop "PQexec returned f." ;
: postgresql-result-ok? ( res -- ? )
[ postgresql-result-null ] unless*
2008-02-01 18:43:44 -05:00
PQresultStatus
PGRES_COMMAND_OK PGRES_TUPLES_OK 2array member? ;
: connect-postgres ( host port pgopts pgtty db user pass -- conn )
PQsetdbLogin
dup PQstatus zero? [ (postgresql-error-message) throw ] unless ;
2008-02-01 18:43:44 -05:00
: do-postgresql-statement ( statement -- res )
2008-12-17 22:04:17 -05:00
db-connection get handle>> swap sql>> PQexec dup postgresql-result-ok? [
2008-04-20 00:48:07 -04:00
[ postgresql-result-error-message ] [ PQclear ] bi throw
2008-02-01 18:43:44 -05:00
] unless ;
2008-03-11 01:05:22 -04:00
: type>oid ( symbol -- n )
dup array? [ first ] when
{
{ BLOB [ BYTEA-OID ] }
{ FACTOR-BLOB [ BYTEA-OID ] }
[ drop 0 ]
} case ;
: type>param-format ( symbol -- n )
dup array? [ first ] when
{
{ BLOB [ 1 ] }
{ FACTOR-BLOB [ 1 ] }
[ drop 0 ]
} case ;
: param-types ( statement -- seq )
in-params>> [ type>> type>oid ] uint-array{ } map-as ;
2008-03-11 01:05:22 -04:00
: malloc-byte-array/length ( byte-array -- alien length )
2008-05-14 20:03:07 -04:00
[ malloc-byte-array &free ] [ length ] bi ;
2008-03-11 01:05:22 -04:00
: default-param-value ( obj -- alien n )
2008-05-14 20:03:07 -04:00
number>string* dup [ utf8 malloc-string &free ] when 0 ;
2008-04-23 23:23:22 -04:00
2008-03-11 01:05:22 -04:00
: param-values ( statement -- seq seq2 )
2008-04-20 00:41:48 -04:00
[ bind-params>> ] [ in-params>> ] bi
2008-03-11 01:05:22 -04:00
[
2008-11-29 13:18:09 -05:00
[ value>> ] [ type>> ] bi* {
2008-03-11 01:05:22 -04:00
{ FACTOR-BLOB [
2008-04-20 00:41:48 -04:00
dup [ object>bytes malloc-byte-array/length ] [ 0 ] if
] }
{ BLOB [ dup [ malloc-byte-array/length ] [ 0 ] if ] }
2008-04-23 23:23:22 -04:00
{ DATE [ dup [ timestamp>ymd ] when default-param-value ] }
{ TIME [ dup [ timestamp>hms ] when default-param-value ] }
{ DATETIME [ dup [ timestamp>ymdhms ] when default-param-value ] }
{ TIMESTAMP [ dup [ timestamp>ymdhms ] when default-param-value ] }
2008-06-12 19:04:01 -04:00
{ URL [ dup [ present ] when default-param-value ] }
2008-04-23 23:23:22 -04:00
[ drop default-param-value ]
2008-03-11 01:05:22 -04:00
} case 2array
2008-09-06 20:13:59 -04:00
] 2map flip [
f f
2008-03-11 01:05:22 -04:00
] [
first2 [ void* >c-array ] [ uint >c-array ] bi*
2008-09-06 20:13:59 -04:00
] if-empty ;
2008-03-11 01:05:22 -04:00
: param-formats ( statement -- seq )
in-params>> [ type>> type>param-format ] uint-array{ } map-as ;
2008-03-11 01:05:22 -04:00
: do-postgresql-bound-statement ( statement -- res )
2008-03-10 18:00:28 -04:00
[
2008-12-17 22:04:17 -05:00
[ db-connection get handle>> ] dip
2008-03-11 01:05:22 -04:00
{
2008-04-20 00:41:48 -04:00
[ sql>> ]
[ bind-params>> length ]
2008-03-11 01:05:22 -04:00
[ param-types ]
[ param-values ]
[ param-formats ]
} cleave
0 PQexecParams dup postgresql-result-ok? [
2008-04-20 00:41:48 -04:00
[ postgresql-result-error-message ] [ PQclear ] bi throw
2008-03-11 01:05:22 -04:00
] unless
] with-destructors ;
: pq-get-is-null ( handle row column -- ? )
PQgetisnull 1 = ;
2008-03-10 18:00:28 -04:00
: pq-get-string ( handle row column -- obj )
2008-04-21 01:13:12 -04:00
3dup PQgetvalue utf8 alien>string
dup empty? [ [ pq-get-is-null f ] dip ? ] [ [ 3drop ] dip ] if ;
2008-03-10 18:00:28 -04:00
: pq-get-number ( handle row column -- obj )
pq-get-string dup [ string>number ] when ;
2008-03-11 01:05:22 -04:00
TUPLE: postgresql-malloc-destructor alien ;
C: <postgresql-malloc-destructor> postgresql-malloc-destructor
M: postgresql-malloc-destructor dispose ( obj -- )
alien>> PQfreemem ;
2008-05-14 20:03:07 -04:00
: &postgresql-free ( alien -- alien )
2008-05-14 20:41:39 -04:00
dup <postgresql-malloc-destructor> &dispose drop ; inline
2008-03-11 01:05:22 -04:00
2008-03-10 18:00:28 -04:00
: pq-get-blob ( handle row column -- obj/f )
2008-03-11 01:05:22 -04:00
[ PQgetvalue ] 3keep 3dup PQgetlength
2008-03-10 18:00:28 -04:00
dup 0 > [
[ 3drop ] dip
2008-03-11 01:05:22 -04:00
[
memory>byte-array >string
{ uint }
2008-03-11 01:05:22 -04:00
[
PQunescapeBytea dup zero? [
postgresql-result-error-message throw
] [
2008-05-14 20:03:07 -04:00
&postgresql-free
2008-03-11 01:05:22 -04:00
] if
] with-out-parameters memory>byte-array
2008-03-11 01:05:22 -04:00
] with-destructors
2008-03-10 18:00:28 -04:00
] [
2008-03-11 01:05:22 -04:00
drop pq-get-is-null nip [ f ] [ B{ } clone ] if
2008-03-10 18:00:28 -04:00
] if ;
2008-03-10 14:56:58 -04:00
: postgresql-column-typed ( handle row column type -- obj )
dup array? [ first ] when
{
{ +db-assigned-id+ [ pq-get-number ] }
2008-04-21 14:11:19 -04:00
{ +random-id+ [ pq-get-number ] }
2008-03-10 18:00:28 -04:00
{ INTEGER [ pq-get-number ] }
{ BIG-INTEGER [ pq-get-number ] }
{ DOUBLE [ pq-get-number ] }
{ TEXT [ pq-get-string ] }
{ VARCHAR [ pq-get-string ] }
{ DATE [ pq-get-string dup [ ymd>timestamp ] when ] }
{ TIME [ pq-get-string dup [ hms>timestamp ] when ] }
{ TIMESTAMP [ pq-get-string dup [ ymdhms>timestamp ] when ] }
{ DATETIME [ pq-get-string dup [ ymdhms>timestamp ] when ] }
{ BLOB [ pq-get-blob ] }
2008-06-12 19:04:01 -04:00
{ URL [ pq-get-string dup [ >url ] when ] }
2008-03-11 01:05:22 -04:00
{ FACTOR-BLOB [
pq-get-blob
dup [ bytes>object ] when ] }
2008-03-10 14:56:58 -04:00
[ no-sql-type ]
} case ;