From 7995ba4e4d41f49c049ad11cea0dd58b0e414af9 Mon Sep 17 00:00:00 2001 From: Giftpflanze Date: Sun, 27 Mar 2022 15:04:15 +0200 Subject: [PATCH] db.mysql: Add low-level MySQL support --- extra/db/mysql/authors.txt | 2 + extra/db/mysql/ffi/authors.txt | 3 ++ extra/db/mysql/ffi/ffi.factor | 32 +++++++++++++ extra/db/mysql/mysql.factor | 85 ++++++++++++++++++++++++++++++++++ extra/db/mysql/summary.txt | 1 + extra/db/mysql/tags.txt | 1 + 6 files changed, 124 insertions(+) create mode 100644 extra/db/mysql/authors.txt create mode 100644 extra/db/mysql/ffi/authors.txt create mode 100644 extra/db/mysql/ffi/ffi.factor create mode 100644 extra/db/mysql/mysql.factor create mode 100644 extra/db/mysql/summary.txt create mode 100644 extra/db/mysql/tags.txt diff --git a/extra/db/mysql/authors.txt b/extra/db/mysql/authors.txt new file mode 100644 index 0000000000..25356e4e77 --- /dev/null +++ b/extra/db/mysql/authors.txt @@ -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 index 0000000000..5f0b498037 --- /dev/null +++ b/extra/db/mysql/ffi/authors.txt @@ -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 index 0000000000..15c1de732a --- /dev/null +++ b/extra/db/mysql/ffi/ffi.factor @@ -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 index 0000000000..6fa8a86170 --- /dev/null +++ b/extra/db/mysql/mysql.factor @@ -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 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 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 ( str in out -- stmt ) + mysql-statement new-statement ; + +M: mysql-db-connection ; + +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>> + [ >>pointers ] + [ >>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 + >byte-array utf8 decode ; diff --git a/extra/db/mysql/summary.txt b/extra/db/mysql/summary.txt new file mode 100644 index 0000000000..2bb0341cbb --- /dev/null +++ b/extra/db/mysql/summary.txt @@ -0,0 +1 @@ +MySQL database binding diff --git a/extra/db/mysql/tags.txt b/extra/db/mysql/tags.txt new file mode 100644 index 0000000000..aa0d57e895 --- /dev/null +++ b/extra/db/mysql/tags.txt @@ -0,0 +1 @@ +database -- 2.34.1