]> gitweb.factorcode.org Git - factor.git/commitdiff
db.mysql: Add low-level MySQL support
authorGiftpflanze <gifti@tools.wmflabs.org>
Sun, 27 Mar 2022 13:04:15 +0000 (15:04 +0200)
committerJohn Benediktsson <mrjbq7@gmail.com>
Sun, 27 Mar 2022 18:26:50 +0000 (11:26 -0700)
extra/db/mysql/authors.txt [new file with mode: 0644]
extra/db/mysql/ffi/authors.txt [new file with mode: 0644]
extra/db/mysql/ffi/ffi.factor [new file with mode: 0644]
extra/db/mysql/mysql.factor [new file with mode: 0644]
extra/db/mysql/summary.txt [new file with mode: 0644]
extra/db/mysql/tags.txt [new file with mode: 0644]

diff --git a/extra/db/mysql/authors.txt b/extra/db/mysql/authors.txt
new file mode 100644 (file)
index 0000000..25356e4
--- /dev/null
@@ -0,0 +1,2 @@
+Doug Coleman
+Giftpflanze
diff --git a/extra/db/mysql/ffi/authors.txt b/extra/db/mysql/ffi/authors.txt
new file mode 100644 (file)
index 0000000..5f0b498
--- /dev/null
@@ -0,0 +1,3 @@
+Berlin Brown
+Doug Coleman
+Giftpflanze
diff --git a/extra/db/mysql/ffi/ffi.factor b/extra/db/mysql/ffi/ffi.factor
new file mode 100644 (file)
index 0000000..15c1de7
--- /dev/null
@@ -0,0 +1,32 @@
+! Copyright (C) 2007 Berlin Brown, 2008 Doug Coleman, 2021 Giftpflanze.
+! See http://factorcode.org/license.txt for BSD license.
+! Adapted from mysql.h and mysql.c
+! Tested with MariaDB version 10.1.39
+USING: alien alien.c-types alien.libraries alien.syntax
+combinators system ;
+IN: db.mysql.ffi
+
+<< "mysql" {
+    { [ os windows? ] [ "libmySQL.dll" stdcall ] }
+    { [ os macosx? ] [ "libmysqlclient.14.dylib" cdecl ] }
+    { [ os unix? ] [ "libmysqlclient.so" cdecl ] }
+} cond add-library >>
+
+LIBRARY: mysql
+
+FUNCTION: uint mysql_errno ( void* mysql )
+FUNCTION: c-string mysql_error ( void* mysql )
+FUNCTION: void* mysql_init ( void* mysql )
+FUNCTION: int mysql_options ( void* mysql, int option, void* arg
+)
+FUNCTION: void* mysql_real_connect ( void* mysql, c-string host,
+c-string user, c-string password, c-string db, int port,
+c-string unixsocket, long clientflag )
+FUNCTION: int mysql_query ( void* mysql, c-string query )
+FUNCTION: void* mysql_use_result ( void* mysql )
+FUNCTION: uint mysql_field_count ( void* mysql )
+FUNCTION: uint mysql_num_fields ( void* result )
+FUNCTION: char** mysql_fetch_row ( void* result )
+FUNCTION: ulong* mysql_fetch_lengths ( void* result )
+FUNCTION: void mysql_free_result ( void* result )
+FUNCTION: void mysql_close ( void* mysql )
diff --git a/extra/db/mysql/mysql.factor b/extra/db/mysql/mysql.factor
new file mode 100644 (file)
index 0000000..6fa8a86
--- /dev/null
@@ -0,0 +1,85 @@
+! Copyright (C) 2008 Doug Coleman, 2021 Giftpflanze.
+! See http://factorcode.org/license.txt for license.
+USING: accessors alien.c-types alien.data arrays byte-arrays
+combinators db db.mysql.ffi db.private destructors
+io.encodings.string io.encodings.utf8 kernel math namespaces
+sequences specialized-arrays ;
+IN: db.mysql
+
+SPECIALIZED-ARRAYS: char ulong void* ;
+
+TUPLE: mysql-db host user password db port ;
+TUPLE: mysql-db-connection < db-connection ;
+TUPLE: mysql-statement < statement ;
+TUPLE: mysql-result-set < result-set
+    #columns has-more? pointers lengths ;
+
+: <mysql-db> ( -- mysql-db )
+    mysql-db new ;
+
+M: mysql-db db-open ( db -- conn )
+    f mysql_init
+    dup [ "Not enough memory to allocate mysql handle." throw ]
+    unless
+    dup 20 1 int <ref> mysql_options drop ! MYSQL_OPT_RECONNECT
+    dup rot {
+        [ host>> ]
+        [ user>> ]
+        [ password>> ]
+        [ db>> ]
+        [ port>> 0 or ]
+    } cleave f 0 mysql_real_connect
+    [ mysql_error throw ] unless
+    mysql-db-connection new-db-connection swap >>handle ;
+
+M: mysql-db-connection db-close ( h -- )
+    mysql_close ;
+
+M: mysql-db-connection parse-db-error ;
+
+M: mysql-db-connection <simple-statement> ( str in out -- stmt )
+    mysql-statement new-statement ;
+
+M: mysql-db-connection <prepared-statement> <simple-statement> ;
+
+M: mysql-statement dispose drop ;
+
+M: mysql-statement query-results ( stmt -- rs )
+    db-connection get handle>> dup pick sql>> mysql_query
+    zero? [ mysql_error throw ] unless dup mysql_use_result
+    dup [
+        nip dup mysql_num_fields
+        [ mysql-result-set new-result-set ] dip
+        >>#columns dup advance-row
+    ] [
+        swap dup mysql_field_count
+        zero? [ drop ] [ mysql_error throw ] if
+        mysql-result-set new-result-set
+    ] if ;
+
+M: mysql-result-set #columns ( rs -- #c )
+    #columns>> ;
+
+M: mysql-result-set advance-row ( rs -- )
+    dup handle>> dup mysql_fetch_row
+    [
+        swap mysql_fetch_lengths pick #columns>>
+        [ <direct-void*-array> >>pointers ]
+        [ <direct-ulong-array> >>lengths ] bi-curry bi*
+        t >>has-more?
+    ] [
+        db-connection get handle>> dup mysql_errno zero?
+        [ 2drop f >>has-more? f >>pointers f >>lengths ]
+        [ mysql_error throw ] if
+    ] if* drop ;
+
+M: mysql-result-set dispose ( d -- )
+    [ mysql_free_result f ] change-handle drop ;
+
+M: mysql-result-set more-rows? ( rs -- ? )
+    has-more?>> ;
+
+M: mysql-result-set row-column ( rs i -- str )
+    swap [ pointers>> ] [ lengths>> ] bi
+    [ nth ] bi-curry@ bi <direct-char-array>
+    >byte-array utf8 decode ;
diff --git a/extra/db/mysql/summary.txt b/extra/db/mysql/summary.txt
new file mode 100644 (file)
index 0000000..2bb0341
--- /dev/null
@@ -0,0 +1 @@
+MySQL database binding
diff --git a/extra/db/mysql/tags.txt b/extra/db/mysql/tags.txt
new file mode 100644 (file)
index 0000000..aa0d57e
--- /dev/null
@@ -0,0 +1 @@
+database