diff --git a/.ci/clang-3.4.sh b/.ci/clang-3.4.sh index 55e6152..deae7be 100755 --- a/.ci/clang-3.4.sh +++ b/.ci/clang-3.4.sh @@ -1,7 +1,9 @@ -sudo apt-get install -y libuv-dev zlib1g-dev clang-3.4 libssl-dev +sudo apt-get install -y zlib1g-dev clang-3.4 libssl-dev CC="clang" CXX="clang++" +.ci/install-libuv.sh autoreconf -fi ./configure --enable-debug -make check +make +make check 2>/dev/null diff --git a/.ci/clang-ia32.sh b/.ci/clang-ia32.sh index 0d91291..8cfef16 100755 --- a/.ci/clang-ia32.sh +++ b/.ci/clang-ia32.sh @@ -1,4 +1,4 @@ -sudo apt-get install -y libc6-dev libc6-dev:i386 libuv-dev:i386 zlib1g-dev:i386 build-essential g++ gcc libtool libssl-dev:i386 +sudo apt-get install -y libc6-dev libc6-dev:i386 zlib1g-dev:i386 build-essential g++ gcc libtool libssl-dev:i386 sudo apt-get install -y gcc-multilib g++-multilib clang @@ -8,6 +8,8 @@ export CFLAGS="-m32" export CXXFLAGS="-m32" export CPPFLAGS="-m32" export LDFLAGS="-m32" +.ci/install-libuv.sh autoreconf -fi ./configure --enable-debug -make check +make +make check 2>/dev/null diff --git a/.ci/clang.sh b/.ci/clang.sh index 8e0d4c8..354522b 100755 --- a/.ci/clang.sh +++ b/.ci/clang.sh @@ -1,7 +1,9 @@ -sudo apt-get install -y libuv-dev zlib1g-dev clang libssl-dev +sudo apt-get install -y zlib1g-dev clang libssl-dev CC="clang" CXX="clang++" +.ci/install-libuv.sh autoreconf -fi ./configure --enable-debug -make check +make +make check 2>/dev/null diff --git a/.ci/cppcheck.sh b/.ci/cppcheck.sh index c4091c7..9b7cec0 100755 --- a/.ci/cppcheck.sh +++ b/.ci/cppcheck.sh @@ -1,5 +1,6 @@ -sudo apt-get install -y cppcheck libuv-dev +sudo apt-get install -y cppcheck +.ci/install-libuv.sh autoreconf -fi ./configure --enable-debug cppcheck --quiet --enable=all --error-exitcode=1 src tests examples diff --git a/.ci/docs.sh b/.ci/docs.sh index e11f8c3..c9cd907 100755 --- a/.ci/docs.sh +++ b/.ci/docs.sh @@ -1,5 +1,6 @@ -sudo apt-get install -y python-sphinx libuv-dev +sudo apt-get install -y python-sphinx +.ci/install-libuv.sh autoreconf -fi ./configure make html diff --git a/.ci/gcc-distcheck.sh b/.ci/gcc-distcheck.sh new file mode 100755 index 0000000..5f4b03b --- /dev/null +++ b/.ci/gcc-distcheck.sh @@ -0,0 +1,6 @@ +sudo apt-get install -y zlib1g-dev libssl-dev + +.ci/install-libuv.sh +autoreconf -fi +./configure --enable-debug +make distcheck 2>/dev/null diff --git a/.ci/gcc-ia32.sh b/.ci/gcc-ia32.sh index 4501ae2..205c310 100755 --- a/.ci/gcc-ia32.sh +++ b/.ci/gcc-ia32.sh @@ -1,4 +1,4 @@ -sudo apt-get install -y libc6-dev libc6-dev:i386 libuv-dev:i386 zlib1g-dev:i386 build-essential g++ gcc libtool libssl-dev:i386 +sudo apt-get install -y libc6-dev libc6-dev:i386 zlib1g-dev:i386 build-essential g++ gcc libtool libssl-dev:i386 sudo apt-get install -y gcc-multilib g++-multilib @@ -6,6 +6,8 @@ export CFLAGS="-m32" export CXXFLAGS="-m32" export LDFLAGS="-m32" export CPPFLAGS="-m32" +.ci/install-libuv.sh autoreconf -fi ./configure --enable-debug -make check +make +make check 2>/dev/null diff --git a/.ci/gcc.sh b/.ci/gcc.sh deleted file mode 100755 index caf479f..0000000 --- a/.ci/gcc.sh +++ /dev/null @@ -1,5 +0,0 @@ -sudo apt-get install -y libuv-dev zlib1g-dev libssl-dev - -autoreconf -fi -./configure --enable-debug -make check diff --git a/.ci/install-libuv.sh b/.ci/install-libuv.sh new file mode 100755 index 0000000..452e37b --- /dev/null +++ b/.ci/install-libuv.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +mkdir ~/tmp +cd ~/tmp +wget https://github.com/libuv/libuv/archive/v1.4.2.tar.gz +tar -zxvf v1.4.2.tar.gz +cd libuv-1.4.2 +./autogen.sh +./configure --prefix=/usr +make +sudo make install diff --git a/.ci/no-optional.sh b/.ci/no-optional.sh index d83dcf9..f1ed3d0 100755 --- a/.ci/no-optional.sh +++ b/.ci/no-optional.sh @@ -1,6 +1,7 @@ -sudo apt-get install -y libuv-dev sudo apt-get remove -y zlib1g-dev libssl-dev +.ci/install-libuv.sh autoreconf -fi ./configure --enable-debug -make check +make +make check 2>/dev/null diff --git a/.ci/scanbuild.sh b/.ci/scanbuild.sh new file mode 100755 index 0000000..64ad1f6 --- /dev/null +++ b/.ci/scanbuild.sh @@ -0,0 +1,8 @@ +sudo apt-get install -y zlib1g-dev clang-3.4 libssl-dev + +CC="clang" +CXX="clang++" +.ci/install-libuv.sh +autoreconf -fi +./configure --enable-debug +scan-build --use-cc=clang --use-c++=clang++ --status-bugs make diff --git a/.ci/valgrind.sh b/.ci/valgrind.sh index 453880b..e5bbae1 100755 --- a/.ci/valgrind.sh +++ b/.ci/valgrind.sh @@ -1,5 +1,6 @@ -sudo apt-get install -y libuv-dev zlib1g-dev valgrind libssl-dev +sudo apt-get install -y zlib1g-dev valgrind libssl-dev +.ci/install-libuv.sh autoreconf -fi ./configure --enable-debug -TESTS_ENVIRONMENT="./libtool --mode=execute valgrind --error-exitcode=1 --leak-check=yes --track-fds=no --malloc-fill=A5 --free-fill=DE --suppressions=valgrind.supp" make check +TESTS_ENVIRONMENT="./libtool --mode=execute valgrind --error-exitcode=1 --leak-check=yes --track-fds=no --malloc-fill=A5 --free-fill=DE --suppressions=valgrind.supp" make check 2>/dev/null diff --git a/.gitignore b/.gitignore index 8b4d6fe..79d998a 100644 --- a/.gitignore +++ b/.gitignore @@ -45,6 +45,7 @@ test-suite.log version.h docs/latex libattachsql-config +libattachsql.pc examples/* !examples/*\.c !examples/*\.sql diff --git a/.travis.yml b/.travis.yml index 72be484..c40013d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,6 @@ language: cpp before_install: - - sudo apt-add-repository ppa:linuxjedi/ppa -y - sudo apt-get update -qq - mysql -uroot -e "grant all on *.* to 'test'@'localhost' identified by 'test';" - sudo cp $(pwd)/.ci/ssl.cnf /etc/mysql/conf.d/ @@ -25,7 +24,7 @@ env: - CI_SCRIPTS="$PROJECT_ROOT/.ci" - "MYSQL_SOCK=/var/run/mysqld/mysqld.sock" matrix: - - CI_TARGET=gcc + - CI_TARGET=gcc-distcheck - CI_TARGET=gcc-ia32 - CI_TARGET=clang - CI_TARGET=clang-ia32 @@ -33,4 +32,5 @@ env: - CI_TARGET=no-optional - CI_TARGET=valgrind - CI_TARGET=cppcheck + - CI_TARGET=scanbuild - CI_TARGET=docs diff --git a/.zuul.yaml b/.zuul.yaml new file mode 100644 index 0000000..3f86df1 --- /dev/null +++ b/.zuul.yaml @@ -0,0 +1,54 @@ +- job: + name: scanbuild + run: playbooks/scanbuild.yaml + timeout: 7200 + nodeset: + nodes: + - name: xenial + label: ubuntu-xenial + +- job: + name: clang + run: playbooks/clang.yaml + timeout: 7200 + nodeset: + nodes: + - name: xenial + label: ubuntu-xenial + +- job: + name: distcheck + run: playbooks/distcheck.yaml + timeout: 7200 + nodeset: + nodes: + - name: xenial + label: ubuntu-xenial + +- job: + name: docs + run: playbooks/docs.yaml + timeout: 7200 + nodeset: + nodes: + - name: xenial + label: ubuntu-xenial + +- job: + name: valgrind + run: playbooks/valgrind.yaml + timeout: 7200 + nodeset: + nodes: + - name: xenial + label: ubuntu-xenial + +- project: + check: + jobs: + - scanbuild + - noop + - clang + - distcheck + - docs + - valgrind diff --git a/Makefile.am b/Makefile.am index 6a602c4..468f958 100644 --- a/Makefile.am +++ b/Makefile.am @@ -23,6 +23,9 @@ BUILT_SOURCES= EXTRA_DIST= CONFIGURE_DEPENDENCIES= +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = libattachsql.pc + #includes additional rules from aminclude.am @INC_AMINCLUDE@ DISTCLEANFILES+= aminclude.am @@ -36,9 +39,8 @@ dist_aclocal_DATA= TESTS+= ${check_PROGRAMS} include m4/include.am -include src/ascore/include.am -include src/asql/include.am -include libattachsql-1.0/include.am +include src/include.am +include libattachsql2/include.am include tests/include.am include examples/include.am include rpm/include.mk @@ -46,6 +48,7 @@ include docs/include.am include yatl/include.am dist_bin_SCRIPTS+= @GENERIC_CONFIG@ +DISTCLEANFILES+= @GENERIC_CONFIG@ # Cleanup individual files in order to preserve uninstall/etc order maintainer-clean-local: diff --git a/README.rst b/README.rst index 399efd2..9cf6b85 100644 --- a/README.rst +++ b/README.rst @@ -16,6 +16,8 @@ libattachsql * Waffle.io: |waffle| * Read The Docs status: |docs| +**The "master" branch has an unstable API, please us the v1.0 branch for a stable API** + Compiling --------- diff --git a/VERSION b/VERSION index ac39a10..227cea2 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.9.0 +2.0.0 diff --git a/bindep.txt b/bindep.txt new file mode 100644 index 0000000..3cbd5ab --- /dev/null +++ b/bindep.txt @@ -0,0 +1,12 @@ +build-essential [platform:dpkg] +libuv-devel [platform:rpm build] +libuv1-dev [platform:dpkg build] +zlib-devel [platform:rpm build] +zlib1g-dev [platform:dpkg build] +openssl-devel [platform:rpm build] +libssl-dev [platform:dpkg build] +libuv [platform:rpm] +libuv1 [platform:dpkg] +zlib [platform:rpm] +zlib1g [platform:dpkg] +openssl diff --git a/configure.ac b/configure.ac index 2a08f38..9c3be7e 100644 --- a/configure.ac +++ b/configure.ac @@ -7,28 +7,29 @@ # Use and distribution licensed under the BSD license. See # the COPYING file in this directory for full text. +AC_COPYRIGHT([2014 Hewlett-Packard Development Company, L.P.]) +#AC_REVISION([m4_esyscmd_s([git describe --always])]) +AC_PREREQ([2.63]) + # These two needed for RHEL/CentOS 6 m4_ifndef([m4_esyscmd_s], [m4_define([m4_chomp_all],[m4_format([[%.*s]], m4_bregexp(m4_translit([[$1]],[/],[/]),[/*$]), [$1])])] [m4_define([m4_esyscmd_s], [m4_chomp_all(m4_esyscmd([$1]))])]) m4_ifndef([AS_VAR_COPY], [m4_define([AS_VAR_COPY], [AS_LITERAL_IF([$1[]$2], [$1=$$2],[eval $1=\$$2])])]) -AC_COPYRIGHT([2014 Hewlett-Packard Development Company, L.P.]) -#AC_REVISION([m4_esyscmd_s([git describe --always])]) -AC_PREREQ([2.63]) - # NOTE: Major version should be < 100 and minor/patch < 256 or bad things will # happen in src/asql/utility.cc AC_INIT([libattachsql],m4_esyscmd_s([tr -d '\n' < VERSION]),[andrew@linuxjedi.co.uk],[libattachsql],[http://libattachsql.org]) m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) -# Setup the compilers early on -AC_PROG_CC([cc gcc clang]) -AC_PROG_CXX([c++ g++ clang++]) # Must come before AM_INIT_AUTOMAKE. AC_CONFIG_AUX_DIR([build-aux]) AC_CANONICAL_HOST AC_CONFIG_MACRO_DIR([m4]) +# Setup the compilers early on +AC_PROG_CC([cc gcc clang]) +AC_PROG_CXX([c++ g++ clang++]) + # Automake version before 1.13 (when the serial-tests option was dnl still the default) still defined the badly obsolete macro.  'AC_PROG_INSTALL'. AM_INIT_AUTOMAKE(1.11 no-define color-tests -Wno-portability subdir-objects foreign tar-ustar m4_ifndef([AC_PROG_INSTALL], [serial-tests])) @@ -45,7 +46,7 @@ PROTECT_AC_USE_SYSTEM_EXTENSIONS AC_CONFIG_HEADERS([config.h:config.in])dnl Keep filename to 8.3 for MS-DOS. # shared library versioning -LIBATTACHSQL_LIBRARY_VERSION=1:0:0 +LIBATTACHSQL_LIBRARY_VERSION=2:0:0 # | | | # +------+ | +---+ # | | | @@ -78,9 +79,6 @@ AC_DEFUN([CHECK_FOR_MINGW], ]) CHECK_FOR_MINGW -# Specialty checks -AX_CXX_CINTTYPES - # Checks for programs. AC_CHECK_PROGS([LSB_RELEASE],[lsb_release]) AC_CHECK_PROGS([DPKG_GENSYMBOLS],[dpkg-gensymbols]) @@ -111,23 +109,27 @@ CHECK_FOR_CXXABI # Checks for typedefs, structures, and compiler characteristics. -# Checks for library functions. -AX_PRINTF_STRERROR - -AX_PTHREAD_TIMEDJOIN_NP - -AX_CHECK_LIBRARY([LIBUV], [uv.h], [uv], [], [AC_MSG_ERROR(could not find libuv)]) -AX_CHECK_LIBRARY([ZLIB], [zlib.h], [z], [], [AC_MSG_WARN(could not find zlib)]) -AX_CHECK_OPENSSL([ax_cv_openssl=yes - AC_DEFINE([HAVE_OPENSSL], [1], [Define to 1 if you have OpenSSL]) - ], [ - ax_cv_openssl=no - AC_MSG_WARN(could not find openssl)]) +PKG_CHECK_MODULES([LIBUV], [libuv >= 1.0 libuv < 2.0], [ax_cv_libuv=yes], [AC_MSG_ERROR(could not find a suitable version of libuv)]) +PKG_CHECK_MODULES([ZLIB], [zlib >= 1.2], [ + ax_cv_zlib=yes + AC_DEFINE([HAVE_ZLIB], [1], [Defined to 1 if you have zlib]) + ], [ + ax_cv_zlib=no + AC_MSG_WARN(could not find a suitable version of zlib) + ]) +PKG_CHECK_MODULES([OPENSSL], [openssl >= 0.9.8], [ + ax_cv_openssl=yes + AC_DEFINE([HAVE_OPENSSL], [1], [Defined to 1 if you have OpenSSL]) + ], [ + ax_cv_openssl=no + AC_MSG_WARN(could not find openssl) + ]) AX_ENDIAN AX_HEX_VERSION([LIBATTACHSQL],[$VERSION]) AC_SUBST([RPM_RELEASE],[1]) AX_HARDEN_COMPILER_FLAGS +AX_UNIVERSAL_BINARY AC_DEFINE_UNQUOTED([C_COMPILER_VENDOR],["$ax_cv_c_compiler_vendor"],[Compiler vendor]) AC_DEFINE_UNQUOTED([CXX_COMPILER_VENDOR],["$ax_cv_cxx_compiler_vendor"],[Compiler vendor]) @@ -147,6 +149,7 @@ AX_AM_JOBSERVER([yes]) AC_CONFIG_FILES([Makefile rpm/libattachsql.spec version.h + libattachsql.pc ]) AX_CREATE_GENERIC_CONFIG @@ -173,8 +176,8 @@ echo " * LDFLAGS Flags: $LDFLAGS" echo " * Assertions enabled: $ax_enable_assert" echo " * Debug enabled: $ax_enable_debug" echo " * Warnings as failure: $ac_cv_warnings_as_errors" -echo " * libuv: $ax_cv_have_LIBUV" -echo " * zlib: $ax_cv_have_ZLIB" +echo " * libuv: $ax_cv_libuv" +echo " * zlib: $ax_cv_zlib" echo " * openssl: $ax_cv_openssl" echo " * make -j: $enable_jobserver" echo " * VCS checkout: $ac_cv_vcs_system" diff --git a/docs/api/compiling.rst b/docs/api/compiling.rst index 4f49720..a5a5622 100644 --- a/docs/api/compiling.rst +++ b/docs/api/compiling.rst @@ -8,7 +8,7 @@ Make sure that your application includes the main libAttachSQL include as follow .. code-block:: c - #include + #include This will pull in all the libAttachSQL functions and constants you may require for your application. diff --git a/docs/api/connection.rst b/docs/api/connection.rst index f68c1fc..8e90e76 100644 --- a/docs/api/connection.rst +++ b/docs/api/connection.rst @@ -21,6 +21,25 @@ attachsql_connect_create() .. versionadded:: 0.1.0 +Example +^^^^^^^ + +.. code-block:: c + + attachsql_connect_t *con= NULL; + attachsql_error_t *error= NULL; + + // Note: we are not connecting here, just defining the connection + con= attachsql_connect_create("localhost", 3306, "test", "test", "testdb", &error); + + if (error != NULL) + { + printf("Error occurred: %s\n", attachsql_error_message(error)); + attachsql_error_free(error); + return -1; + } + + attachsql_connect_destroy() --------------------------- @@ -32,6 +51,21 @@ attachsql_connect_destroy() .. versionadded:: 0.1.0 +Example +^^^^^^^ + +.. code-block:: c + + attachsql_connect_t *con= NULL; + attachsql_error_t *error= NULL; + + con= attachsql_connect_create("localhost", 3306, "test", "test", "testdb", error); + // Do lots with the connection here + ... + attachsql_connect_destroy(con); + + + attachsql_connect() ------------------- @@ -46,21 +80,35 @@ attachsql_connect() .. versionadded:: 0.1.0 .. versionchanged:: 0.5.0 -attachsql_connect_set_callback() --------------------------------- +Example +^^^^^^^ -.. c:function:: void attachsql_connect_set_callback(attachsql_connect_t *con, attachsql_callback_fn *function, void *context) +.. code-block:: c - Sets a callback function which will be executed on connection complete, error, eof or row ready events. + attachsql_connect_t *con= NULL; + attachsql_error_t *error= NULL; - .. note:: - The callback will only be called as part of an execution of another function such as :c:func:`attachsql_connect_poll` + // Note: we are not connecting here, just defining the connection + con= attachsql_connect_create("localhost", 3306, "test", "test", "testdb", &error); - :param con: The connection object to bind the callback functino to - :param function: The callback function - :param context: A pointer to some data which will be passed to the callback function upon execution + if (error != NULL) + { + printf("Error occurred: %s\n", attachsql_error_message(error)); + attachsql_error_free(error); + return -1; + } - .. versionadded:: 0.1.0 + // Note: we are not connecting here either, just requesting the connection takes place + if (!attachsql_connect(con, &error)) + { + printf("Error occurred\n"); + if (error != NULL) + { + printf("Message: %s\n", attachsql_error_message(error)); + attachsql_error_free(error); + return -1; + } + } attachsql_connect_get_server_version() -------------------------------------- @@ -74,6 +122,18 @@ attachsql_connect_get_server_version() .. versionadded:: 0.1.0 +Example +^^^^^^^ + +.. code-block:: c + + attachsql_connect_t *con= NULL; + + // Connect here + ... + + printf("Server version: %s\n", attachsql_connect_get_server_version(con)); + attachsql_connect_poll() ------------------------ @@ -87,6 +147,42 @@ attachsql_connect_poll() .. versionadded:: 0.1.0 +Example +^^^^^^^ + +.. code-block:: c + + attachsql_return_t ret= ATTACHSQL_RETURN_NONE; + attachsql_connect_t *con= NULL; + attachsql_query_row_st *row; + attachsql_error_t *error; + const char *query= "SELECT * FROM t1 WHERE name='fred'"; + uint16_t columns, current_column; + + con= attachsql_connect_create("localhost", 3306, "test", "test", "testdb", NULL); + + attachsql_query(con, strlen(query), query, 0, NULL, &error); + + while ((ret != ATTACHSQL_RETURN_EOF) && (error == NULL)) + { + ret= attachsql_connect_poll(con, &error); + if (ret != ATTACHSQL_RETURN_ROW_READY) + { + continue; + } + row= attachsql_query_row_get(con, &error); + columns= attachsql_query_column_count(con); + for (current_column= 0; current_column < columns; current_column++) + { + printf("%.*s ", (int)row[current_column].length, row[current_column].data); + } + printf("\n"); + attachsql_query_row_next(con); + } + // Error handling and cleanup here + ... + + attachsql_connect_set_option() ------------------------------ @@ -101,6 +197,17 @@ attachsql_connect_set_option() .. versionadded:: 0.1.0 +Example +^^^^^^^ + +.. code-block:: c + + attachsql_connect_t *con= NULL; + + // Note: we are not connecting here, just defining the connection + con= attachsql_connect_create("localhost", 3306, "test", "test", "", NULL); + bool compress= attachsql_connect_set_option(con, ATTACHSQL_OPTION_COMPRESS, NULL); + attachsql_connect_set_ssl() --------------------------- @@ -122,3 +229,20 @@ attachsql_connect_set_ssl() .. versionadded:: 0.3.0 .. versionchanged:: 0.5.0 + +Example +^^^^^^^ + +.. code-block:: c + + attachsql_connect_t *con= NULL; + attachsql_error_t *error= NULL; + + con= attachsql_connect_create("localhost", 3306, "test", "test", "", NULL); + attachsql_connect_set_ssl(con, "client-key.pem", "client-cert.pem", "ca-cert.pem", NULL, NULL, false, &error); + if (error and (attachsql_error_code(error) == 3002)) + { + printf("Server does not support SSL\n"); + attachsql_error_free(error); + return -1; + } diff --git a/docs/api/error.rst b/docs/api/error.rst index 6938247..5b6d74c 100644 --- a/docs/api/error.rst +++ b/docs/api/error.rst @@ -13,6 +13,24 @@ attachsql_error_free() .. versionadded:: 0.1.0 .. versionchanged:: 0.5.0 +Example +^^^^^^^ + +.. code-block:: c + + attachsql_connect_t *con= NULL; + attachsql_error_t *error= NULL; + + // Note: we are not connecting here, just defining the connection + con= attachsql_connect_create("localhost", 3306, "test", "test", "testdb", &error); + + if (error != NULL) + { + printf("Error occurred: %s\n", attachsql_error_message(error)); + attachsql_error_free(error); + return -1; + } + attachsql_error_code() ---------------------- @@ -25,6 +43,24 @@ attachsql_error_code() .. versionadded:: 0.5.0 +Example +^^^^^^^ + +.. code-block:: c + + attachsql_connect_t *con= NULL; + attachsql_error_t *error= NULL; + + // Note: we are not connecting here, just defining the connection + con= attachsql_connect_create("localhost", 3306, "test", "test", "testdb", &error); + + if (error != NULL) + { + printf("Error occurred, code: %d\n", attachsql_error_code(error)); + attachsql_error_free(error); + return -1; + } + attachsql_error_message() ------------------------- @@ -37,8 +73,26 @@ attachsql_error_message() .. versionadded:: 0.5.0 -attachsql_error_code() ----------------------- +Example +^^^^^^^ + +.. code-block:: c + + attachsql_connect_t *con= NULL; + attachsql_error_t *error= NULL; + + // Note: we are not connecting here, just defining the connection + con= attachsql_connect_create("localhost", 3306, "test", "test", "testdb", &error); + + if (error != NULL) + { + printf("Error occurred: %s\n", attachsql_error_message(error)); + attachsql_error_free(error); + return -1; + } + +attachsql_error_sqlstate() +-------------------------- .. c:function:: char *attachsql_error_sqlstate(attachsql_error_t *err) @@ -52,3 +106,20 @@ attachsql_error_code() .. versionadded:: 0.5.0 +Example +^^^^^^^ + +.. code-block:: c + + attachsql_connect_t *con= NULL; + attachsql_error_t *error= NULL; + + // Note: we are not connecting here, just defining the connection + con= attachsql_connect_create("localhost", 3306, "test", "test", "testdb", &error); + + if (error != NULL) + { + printf("Error occurred, sqlstate: %5s\n", attachsql_error_sqlstate(error)); + attachsql_error_free(error); + return -1; + } diff --git a/docs/api/examples.rst b/docs/api/examples.rst index d60fe84..c77a1d0 100644 --- a/docs/api/examples.rst +++ b/docs/api/examples.rst @@ -1,6 +1,8 @@ API Examples ============ +.. _basic-query-example: + A Basic Query ------------- @@ -89,6 +91,8 @@ At the end of the program everything is cleaned up nicely: attachsql_query_close(con); attachsql_connect_destroy(con); +.. _escaped-query-example: + An Escaped Query ---------------- @@ -145,6 +149,8 @@ The resulting query generated before sending to the MySQL server is: SELECT * FROM t1 WHERE name = 'fred' AND age > 30; +.. _buffered-results-example: + Buffered Results ---------------- @@ -187,6 +193,7 @@ We can now loop through :c:func:`attachsql_query_buffer_row_get` to retrieve the printf("\n"); } +.. _prepared-statements-example: Prepared Statements ------------------- @@ -258,35 +265,36 @@ And finally instead of closing a query, we are closing a statement. attachsql_statement_close(con); -Group Conncetions ------------------ +.. _pool-connections-example: + +Pool Connections +---------------- -libAttachSQL has the ability to group several connections into a single event loop. This makes this more efficient for many connections on a single thread. There is a slightly different access pattern for this which relies on callback. +libAttachSQL has the ability to pool several connections into a single event loop. This makes this more efficient for many connections on a single thread. There is a slightly different access pattern for this which relies on callback. -In this example we will make three simultaneous queries to the server on three connections in a single connection group. All three will be executed in parallel and as such will return in a random order. The example file can be found at ``examples/group_query.c``. +In this example we will make three simultaneous queries to the server on three connections in a single connection pool. All three will be executed in parallel and as such will return in a random order. The example file can be found at ``examples/pool_query.c``. Source Code ^^^^^^^^^^^ -.. literalinclude:: ../../examples/group_query.c +.. literalinclude:: ../../examples/pool_query.c :language: c Breaking it Down ^^^^^^^^^^^^^^^^ -First we create the group object which the connections will be attached to: +First we create the pool object which the connections will be attached to: .. code-block:: c - group= attachsql_group_create(NULL); + pool= attachsql_pool_create(callbk, NULL, NULL); -Then we create the connections, add the connections to the group and set the callback function for the connections. This is repeated 3 times, once for every connection: +Then we create the connections, add the connections to the pool and set the callback function for the connections. This is repeated 3 times, once for every connection: .. code-block:: c con[0]= attachsql_connect_create("localhost", 3306, "test", "test", "testdb", NULL); - attachsql_group_add_connection(group, con[0], &error); - attachsql_connect_set_callback(con[0], callbk, &con_no[0]); + attachsql_pool_add_connection(pool, con[0], &error); We can now send a query to each of these connections: @@ -300,27 +308,27 @@ We can now send a query to each of these connections: attachsql_query(con[1], strlen(query2), query2, 0, NULL, &error); attachsql_query(con[2], strlen(query3), query3, 0, NULL, &error); -The group method uses callbacks instead of polling and checking the results. So you only need to run the group event loop whenever ready. This is non-blocking and will only fire a callback if there is data ready: +The pool method uses callbacks instead of polling and checking the results. So you only need to run the pool event loop whenever ready. This is non-blocking and will only fire a callback if there is data ready: .. code-block:: c while(done_count < 3) { - attachsql_group_run(group); + attachsql_pool_run(pool); } When there is an event to be triggered such as a row ready in the buffer the callback is triggered: .. code-block:: c - void callbk(attachsql_connect_t *current_con, attachsql_events_t events, void *context, attachsql_error_t *error) + void callbk(attachsql_connect_t *current_con, uint32_t connection_id, attachsql_events_t events, void *context, attachsql_error_t *error) In this callback function we are using a switch statement to find out which event was fired and act appropriately. The connected event fires when connection and handshake is complete: .. code-block:: c case ATTACHSQL_EVENT_CONNECTED: - printf("Connected event on con %d\n", *con_no); + printf("Connected event on con %d\n", connection_id); break; The error event fires when an error occurs. It is up to the application to clean up the error: @@ -328,7 +336,7 @@ The error event fires when an error occurs. It is up to the application to clea .. code-block:: c case ATTACHSQL_EVENT_ERROR: - printf("Error exists on con %d: %d", *con_no, attachsql_error_code(error)); + printf("Error exists on con %d: %d", connection_id, attachsql_error_code(error)); attachsql_error_free(error); break; @@ -337,7 +345,7 @@ The EOF event fires when we have reached the end of the query results: .. code-block:: c case ATTACHSQL_EVENT_EOF: - printf("Connection %d finished\n", *con_no); + printf("Connection %d finished\n", connection_id); done_count++; attachsql_query_close(current_con); @@ -350,15 +358,15 @@ Finally the row ready event fires when a row is ready for processing in the buff columns= attachsql_query_column_count(current_con); for (col=0; col < columns; col++) { - printf("Con: %d, Column: %d, Length: %zu, Data: %.*s ", *con_no, col, row[col].length, (int)row[col].length, row[col].data); + printf("Con: %d, Column: %d, Length: %zu, Data: %.*s ", connection_id, col, row[col].length, (int)row[col].length, row[col].data); } attachsql_query_row_next(current_con); printf("\n"); break; -After the main while() loop has finished the group needs to be destroyed. This will cleanup all underlying connections: +After the main while() loop has finished the pool needs to be destroyed. This will cleanup all underlying connections: .. code-block:: c - attachsql_group_destroy(group); + attachsql_pool_destroy(pool); break; diff --git a/docs/api/group.rst b/docs/api/group.rst deleted file mode 100644 index 8ef1cd5..0000000 --- a/docs/api/group.rst +++ /dev/null @@ -1,61 +0,0 @@ -Connection Group Functions -========================== - -attachsql_group_create() ------------------------- - -.. c:function:: attachsql_group_t *attachsql_group_create(attachsql_error_t **error) - - Creates and initializes a connection group object - - :param error: A pointer to a pointer of an error object which is created if an error occurs - :returns: A newly created group object or :c:type:`NULL` on failure - - .. versionadded:: 0.9.0 - -attachsql_group_destroy() -------------------------- - -.. c:function:: void attachsql_group_destroy(attachsql_group_t *group) - - Destroys a connection group along with all the underlying connections. - - .. warning:: - Do NOT use :c:func:`attachsql_connect_destroy` on any connection used by a connection group. This will cause a double-free to occur. - - :param group: The group object to destroy - - .. versionadded:: 0.9.0 - -attachsql_group_add_connection() --------------------------------- - -.. c:function:: void attachsql_group_add_connection(attachsql_group_t *group, attachsql_connect_t *con, attachsql_error_t **error) - - Adds a connection to the group object. - - .. warning:: - * This should be a newly created connection with :c:func:`attachsql_connect_create` that has not yet connected to the server. - * You should NOT use :c:func:`attachsql_connect_poll` with a connection in a group - * You should NOT use :c:func:`attachsql_connect_destroy` with a connection in a group - * See the examples in this documentation for more information - - :param group: The connection group object to add to - :param con: The connection object to add - :param error: A pointer to a pointer of an error object which is created if an error occurs - - .. versionadded:: 0.9.0 - -attachsql_group_run() ---------------------- - -.. c:function:: void attachsql_group_run(attachsql_group_t *group) - - Runs the event loop for the connection group, firing the callbacks if any event has occurred. - - .. warning:: - This function is not reentrant, trying to call it on the same group with two threads will invoke undefined behaviour — it may block the process indefinitely, it may eat all your laundry, it will probably crash - - :param group: The connection group to run - - .. versionadded:: 0.9.0 diff --git a/docs/api/pool.rst b/docs/api/pool.rst new file mode 100644 index 0000000..8e1735a --- /dev/null +++ b/docs/api/pool.rst @@ -0,0 +1,178 @@ +Connection Pool Functions +========================= + +attachsql_pool_create() +------------------------ + +.. c:function:: attachsql_pool_t *attachsql_pool_create(attachsql_callback_fn *function, void *context, attachsql_error_t **error) + + Creates and initializes a connection pool object + + :param function: The callback function + :param context: A pointer to some data which will be passed to the callback function upon execution + :param error: A pointer to a pointer of an error object which is created if an error occurs + :returns: A newly created pool object or :c:type:`NULL` on failure + + .. versionadded:: 0.9.0 + + .. versionchanged:: 2.0.0 + * Renamed `group` to `pool` + * Callback API added + +Example +^^^^^^^ + +.. code-block:: c + + // User defined callback function + void my_callback(attachsql_t *current_con, uint32_t connection_id, attachsql_events_t events, void *context, attachsql_error_t *error) + { + // User data which needs typecasting back to the type that was sent + char *my_data= (char*)context; + attachsql_query_row_st *row; + uint16_t columns, col; + + switch(events) + { + case ATTACHSQL_EVENT_CONNECTED: + printf("Connected event!\n"); + break; + case ATTACHSQL_EVENT_ERROR: + printf("Error occurred: %d\n", attachsql_error_code(error)); + attachsql_error_free(error); + break; + case ATTACHSQL_EVENT_EOF: + printf("Connection has finished query"); + break; + case ATTACHSQL_EVENT_ROW_READY: + row= attachsql_query_row_get(current_con, &error); + columns= attachsql_query_column_count(current_con); + for (col=0; col < columns; col++) + { + printf("Con: %d, Column: %d, Length: %zu, Data: %.*s ", *con_no, col, row[col].length, (int)row[col].length, row[col].data); + } + attachsql_query_row_next(current_con); + printf("\n"); + break; + case ATTACHSQL_EVENT_NONE: + // This should never happen! + break; + } + } + + void main(int argc, char *argv[]) + { + attachsql_pool_t *pool= NULL; + attachsql_error_t *error= NULL; + char arbitrary_data[]= "Callback context data"; + + pool= attachsql_pool_create(my_callback, arbitrary_data, &error); + + if (error != NULL) + { + printf("Error occurred: %s\n", attachsql_error_message(error)); + attachsql_error_free(error); + return -1; + } + // Do stuff here + ... + } + +.. seealso:: :ref:`pool-connections-example` example + +attachsql_pool_destroy() +------------------------- + +.. c:function:: void attachsql_pool_destroy(attachsql_pool_t *pool) + + Destroys a connection pool along with all the underlying connections. + + .. warning:: + Do NOT use :c:func:`attachsql_connect_destroy` on any connection used by a connection pool. This will cause a double-free to occur. + + :param pool: The pool object to destroy + + .. versionadded:: 0.9.0 + + .. versionchanged:: 2.0.0 + Renamed `group` to `pool` + +Example +^^^^^^^ + +.. code-block:: c + + attachsql_pool_t *pool= NULL; + attachsql_error_t *error= NULL; + + pool= attachsql_pool_create(my_callback, NULL, &error); + + // Do stuff with the pool + ... + + attachsql_pool_destroy(pool); + +.. seealso:: :ref:`pool-connections-example` example + +attachsql_pool_add_connection() +-------------------------------- + +.. c:function:: void attachsql_pool_add_connection(attachsql_pool_t *pool, attachsql_connect_t *con, attachsql_error_t **error) + + Adds a connection to the pool object. + + .. warning:: + * This should be a newly created connection with :c:func:`attachsql_connect_create` that has not yet connected to the server. + * You should NOT use :c:func:`attachsql_connect_poll` with a connection in a pool + * You should NOT use :c:func:`attachsql_connect_destroy` with a connection in a pool + * See the examples in this documentation for more information + + :param pool: The connection pool object to add to + :param con: The connection object to add + :param error: A pointer to a pointer of an error object which is created if an error occurs + + .. versionadded:: 0.9.0 + + .. versionchanged:: 2.0.0 + Renamed `group` to `pool` + +Example +^^^^^^^ + +.. code-block:: c + + attachsql_connect_t *con1= NULL; + attachsql_pool_t *pool= NULL; + attachsql_error_t *error= NULL; + + pool= attachsql_pool_create(my_callback, NULL, NULL); + con1= attachsql_connect_create("localhost", 3306, "test", "test", "testdb", NULL); + attachsql_pool_add_connection(pool, con1, &error); + + // Do things with the pool here + ... + +.. seealso:: :ref:`pool-connections-example` example + +attachsql_pool_run() +--------------------- + +.. c:function:: void attachsql_pool_run(attachsql_pool_t *pool) + + Runs the event loop for the connection pool, firing the callbacks if any event has occurred. + + .. warning:: + This function is not reentrant, trying to call it on the same pool with two threads will invoke undefined behaviour — it may block the process indefinitely, it may eat all your laundry, it will probably crash + + :param pool: The connection pool to run + + .. versionadded:: 0.9.0 + + .. versionchanged:: 2.0.0 + Renamed `group` to `pool` + +Example +^^^^^^^ + +See the :ref:`pool-connections-example` example + diff --git a/docs/api/query.rst b/docs/api/query.rst index 88d09d6..28debb5 100644 --- a/docs/api/query.rst +++ b/docs/api/query.rst @@ -27,6 +27,11 @@ attachsql_query() .. versionadded:: 0.1.0 .. versionchanged:: 0.5.0 +Example +^^^^^^^ + +See the following examples: :ref:`basic-query-example` and :ref:`escaped-query-example` + attachsql_query_close() ----------------------- @@ -38,6 +43,19 @@ attachsql_query_close() .. versionadded:: 0.1.0 +Example +^^^^^^^ + +.. code-block:: c + + attachsql_connect_t *con; + + // Connect, send a query and process results + ... + attachsql_query_close(con); + +.. seealso:: :ref:`basic-query-example` example + attachsql_query_column_count() ------------------------------ @@ -45,11 +63,37 @@ attachsql_query_column_count() Returns the number of columns in a query result + .. note:: at least the first row must be received to access this metadata + :param con: The connection object the query is on :returns: The column count or ``0`` if there is no active query .. versionadded:: 0.1.0 +Example +^^^^^^^ + +.. code-block:: c + + attachsql_connect_t *con; + uint16_t columns; + + con= attachsql_connect_create("localhost", 3306, "test", "test", "testdb", NULL); + attachsql_query(con, strlen(query), query, 0, NULL, &error); + + while ((ret != ATTACHSQL_RETURN_EOF) && (error == NULL)) + { + ret= attachsql_connect_poll(con, &error); + if (ret != ATTACHSQL_RETURN_ROW_READY) + { + continue; + } + columns= attachsql_query_column_count(con); + ... + + +.. seealso:: :ref:`basic-query-example` example + attachsql_query_column_get() ---------------------------- @@ -57,12 +101,30 @@ attachsql_query_column_get() Gets column information for a specified column from a given query + .. note:: The resulting struct is free'd automatically when :c:func:`attachsql_query_close` is called. The user should not attempt to free it. + :param con: The connection object the query is on :param column: The column number to retrieve :returns: The column data or :c:type:`NULL` if there is no such column .. versionadded:: 0.1.0 +Example +^^^^^^^ + +.. code-block:: c + + attachsql_connect_t *con; + attachsql_query_column_st *column_data; + + con= attachsql_connect_create("localhost", 3306, "test", "test", "testdb", NULL); + attachsql_query(con, strlen(query), query, 0, NULL, &error); + // Poll here until first row in result is ready + ... + column_data= attachsql_query_column_get(con, 0); + printf("Table: %s, Column: %s\n", column_data->table, column_data->column); + + attachsql_query_row_get() ------------------------- @@ -82,6 +144,11 @@ attachsql_query_row_get() .. versionadded:: 0.1.0 +Example +^^^^^^^ + +See :ref:`basic-query-example` example + attachsql_query_row_next() -------------------------- @@ -99,6 +166,31 @@ attachsql_query_row_next() .. versionadded:: 0.1.0 +Example +^^^^^^^ + +.. code-block:: c + + attachsql_connect_t *con; + attachsql_error_t *error= NULL; + // Connect and execute query + ... + while ((ret != ATTACHSQL_RETURN_EOF) && (error == NULL)) + { + ret= attachsql_connect_poll(con, &error); + if (ret != ATTACHSQL_RETURN_ROW_READY) + { + continue; + } + row= attachsql_query_row_get(con, &error); + columns= attachsql_query_column_count(con); + // Do something with the row + ... + attachsql_query_row_next(con); + } + +.. seealso:: :ref:`basic-query-example` example + attachsql_connection_last_insert_id() ------------------------------------- @@ -111,6 +203,19 @@ attachsql_connection_last_insert_id() .. versionadded:: 0.1.0 +Example +^^^^^^^ + +.. code-block:: c + + attachsql_connect_t *con; + uint64_t insert_id; + // Execute a query + ... + attachsql_query_close(con); + + insert_id= attachsql_connection_last_insert_id(con); + attachsql_query_affected_rows() ------------------------------- @@ -123,6 +228,19 @@ attachsql_query_affected_rows() .. versionadded:: 0.1.0 +Example +^^^^^^^ + +.. code-block:: c + + attachsql_connect_t *con; + uint64_t affected_rows; + // Execute a query + ... + + affected_rows= attachsql_query_affected_rows(con); + attachsql_query_close(con); + attachsql_query_warning_count() ------------------------------- @@ -135,6 +253,20 @@ attachsql_query_warning_count() .. versionadded:: 0.1.0 +Example +^^^^^^^ + +.. code-block:: c + + attachsql_connect_t *con; + uint32_t warning_count; + // Execute a query + ... + + warning_count= attachsql_query_warning_count(con); + attachsql_query_close(con); + + attachsql_query_info() ---------------------- @@ -142,11 +274,27 @@ attachsql_query_info() Returns a string of information on the previous query. + .. note:: this is freed internally when the connection is destroyed and should not be freed by the application. + :param con: The connection object the query was on :returns: A string of the info or :c:type:`NULL` if there is none .. versionadded:: 0.1.0 +Example +^^^^^^^ + +.. code-block:: c + + attachsql_connect_t *con; + const char *query_info; + // Execute a query + ... + + query_info= attachsql_query_info(con); + printf("%s\n", query_info); + attachsql_query_close(con); + attachsql_query_next_result() ----------------------------- @@ -159,6 +307,57 @@ attachsql_query_next_result() .. versionadded:: 0.1.0 +Example +^^^^^^^ + +.. code-block:: c + + attachsql_connect_t *con; + attachsql_error_t *error= NULL; + const char *data= "SHOW PROCESSLIST; SHOW PROCESSLIST"; + attachsql_return_t aret= ATTACHSQL_RETURN_NONE; + attachsql_query_row_st *row; + uint16_t columns, col; + + con= attachsql_connect_create("localhost", 3306, "test", "test", "", NULL); + attachsql_connect_set_option(con, ATTACHSQL_OPTION_MULTI_STATEMENTS, NULL); + attachsql_query(con, strlen(data), data, 0, NULL, &error); + while(aret != ATTACHSQL_RETURN_EOF) + { + aret= attachsql_connect_poll(con, &error); + if (aret == ATTACHSQL_RETURN_ROW_READY) + { + row= attachsql_query_row_get(con, &error); + columns= attachsql_query_column_count(con); + for (col=0; col < columns; col++) + { + printf("Column: %d, Length: %zu, Data: %.*s ", col, row[col].length, (int)row[col].length, row[col].data); + } + attachsql_query_row_next(con); + printf("\n"); + } + } + attachsql_query_close(con); + aret= attachsql_query_next_result(con); + while(aret != ATTACHSQL_RETURN_EOF) + { + aret= attachsql_connect_poll(con, &error); + if (aret == ATTACHSQL_RETURN_ROW_READY) + { + row= attachsql_query_row_get(con, &error); + columns= attachsql_query_column_count(con); + for (col=0; col < columns; col++) + { + printf("Column: %d, Length: %zu, Data: %.*s ", col, row[col].length, (int)row[col].length, row[col].data); + } + attachsql_query_row_next(con); + printf("\n"); + } + } + attachsql_query_close(con); + attachsql_query_next_result(con); + attachsql_connect_destroy(con); + attachsql_query_buffer_rows() ----------------------------- @@ -175,6 +374,21 @@ attachsql_query_buffer_rows() .. versionadded:: 0.2.0 +Example +^^^^^^^ + +.. code-block:: c + + attachsql_connect_t *con= NULL; + attachsql_error_t *error= NULL; + const char *query= "SELECT * FROM t1 WHERE name='fred'"; + + con= attachsql_connect_create("localhost", 3306, "test", "test", "testdb", NULL); + attachsql_query_buffer_rows(con, true); + attachsql_query(con, strlen(query), query, 0, NULL, &error); + +.. seealso:: :ref:`buffered-results-example` example + attachsql_query_row_count() --------------------------- @@ -187,6 +401,34 @@ attachsql_query_row_count() .. versionadded:: 0.2.0 +Example +^^^^^^^ + +.. code-block:: c + + attachsql_connect_t *con; + attachsql_error_t *error= NULL; + const char *query= "SELECT * FROM t1 WHERE name='fred'"; + uint64_t row_count; + + con= attachsql_connect_create("localhost", 3306, "test", "test", "testdb", NULL); + attachsql_query_buffer_rows(con, true); + attachsql_query(con, strlen(query), query, 0, NULL, &error); + + while ((ret != ATTACHSQL_RETURN_EOF) && (error == NULL)) + { + ret= attachsql_connect_poll(con, &error); + } + if (error != NULL) + { + printf("Error occurred: %s", attachsql_error_message(error)); + return 1; + } + row_count= attachsql_query_row_count(con); + ... + +.. seealso:: :ref:`buffered-results-example` example + attachsql_query_buffer_row_get() -------------------------------- @@ -199,6 +441,11 @@ attachsql_query_buffer_row_get() .. versionadded:: 0.2.0 +Example +^^^^^^^ + +See :ref:`buffered-results-example` example + attachsql_query_row_get_offset() -------------------------------- @@ -211,3 +458,41 @@ attachsql_query_row_get_offset() :returns: An array of row data, the number of elements in the array can be found with :c:func:`attachsql_query_column_count` .. versionadded:: 0.2.0 + +Example +^^^^^^^ + +.. code-block:: c + + attachsql_connect_t *con= NULL; + attachsql_error_t *error= NULL; + const char *query= "SELECT * FROM t1 WHERE name='fred'"; + attachsql_return_t ret= ATTACHSQL_RETURN_NONE; + attachsql_query_row_st *row; + uint16_t columns, current_column; + + con= attachsql_connect_create("localhost", 3306, "test", "test", "testdb", NULL); + attachsql_query_buffer_rows(con, true); + attachsql_query(con, strlen(query), query, 0, NULL, &error); + + while ((ret != ATTACHSQL_RETURN_EOF) && (error == NULL)) + { + ret= attachsql_connect_poll(con, &error); + } + if (error != NULL) + { + printf("Error occurred: %s", attachsql_error_message(error)); + return 1; + } + + columns= attachsql_query_column_count(con); + // Get row 2 (the third row in a result set) + row= attachsql_query_buffer_row_get(con, 2); + for (current_column= 0; current_column < columns; current_column++) + { + printf("%.*s ", (int)row[current_column].length, row[current_column].data); + } + printf("\n"); + attachsql_query_close(con); + attachsql_connect_destroy(con); + diff --git a/docs/api/statement.rst b/docs/api/statement.rst index 69a2547..789182d 100644 --- a/docs/api/statement.rst +++ b/docs/api/statement.rst @@ -20,6 +20,33 @@ attachsql_statement_prepare() .. versionadded:: 0.4.0 .. versionchanged:: 0.5.0 +Example +^^^^^^^ + +.. code-block:: c + + attachsql_connect_t *con= NULL; + attachsql_error_t *error= NULL; + const char *query= "SELECT * FROM t1 WHERE name = ? AND age > ?"; + attachsql_return_t ret= ATTACHSQL_RETURN_NONE; + + con= attachsql_connect_create("localhost", 3306, "test", "test", "testdb", NULL); + attachsql_statement_prepare(con, strlen(query), query, &error); + while((ret != ATTACHSQL_RETURN_EOF) && (error == NULL)) + { + ret= attachsql_connect_poll(con, &error); + } + if (error != NULL) + { + printf("Error occurred: %s", attachsql_error_message(error)); + attachsql_error_free(error); + attachsql_statement_close(con); + attachsql_connect_destroy(con); + return 1; + } + +.. seealso:: :ref:`prepared-statements-example` example + attachsql_statement_execute() ----------------------------- @@ -27,6 +54,8 @@ attachsql_statement_execute() Executes a prepared statement + .. note:: the statement should be prepared and parameters set prior to execution + :param con: The connection the statement is on :param error: A pointer to a pointer of an error object which is created if an error occurs :returns: ``true`` on success or ``false`` on failure @@ -34,6 +63,11 @@ attachsql_statement_execute() .. versionadded:: 0.4.0 .. versionchanged:: 0.5.0 +Example +^^^^^^^ + +See the :ref:`prepared-statements-example` example + attachsql_statement_reset() --------------------------- @@ -48,6 +82,22 @@ attachsql_statement_reset() .. versionadded:: 0.4.0 .. versionchanged:: 0.5.0 +Example +^^^^^^^ + +.. code-block:: c + + attachsql_connect_t *con= NULL; + attachsql_error_t *error= NULL; + attachsql_return_t ret= ATTACHSQL_RETURN_NONE; + // Connect and run a prepared statement + ... + attachsql_statement_reset(con, &error); + while((ret != ATTACHSQL_RETURN_EOF) && (error == NULL)) + { + ret= attachsql_connect_poll(con, &error); + } + attachsql_statement_close() --------------------------- @@ -59,6 +109,18 @@ attachsql_statement_close() .. versionadded:: 0.4.0 +Example +^^^^^^^ + +.. code-block:: c + + attachsql_connect_t *con= NULL; + // Connect and execute a statement + ... + attachsql_statement_close(con); + +.. seealso:: :ref:`prepared-statements-example` example + attachsql_statement_send_long_data() ------------------------------------ @@ -76,6 +138,17 @@ attachsql_statement_send_long_data() .. versionadded:: 0.4.0 .. versionchanged:: 0.5.0 +Example +^^^^^^^ + +.. code-block:: c + + attachsql_connect_t *con= NULL; + const char query[]= "INSERT INTO blog_text SET text=?"; + // Connect and prepare a statement + ... + attachsql_statement_send_long_data(con, 0, strlen(text), text, &error); + attachsql_statement_get_param_count() ------------------------------------- @@ -88,6 +161,26 @@ attachsql_statement_get_param_count() .. versionadded:: 0.4.0 +Example +^^^^^^^ + +.. code-block:: c + + attachsql_connect_t *con= NULL; + attachsql_error_t *error= NULL; + const char *query= "SELECT * FROM t1 WHERE name = ? AND age > ?"; + attachsql_return_t ret= ATTACHSQL_RETURN_NONE; + uint16_t param_count; + + con= attachsql_connect_create("localhost", 3306, "test", "test", "testdb", NULL); + attachsql_statement_prepare(con, strlen(query), query, &error); + while((ret != ATTACHSQL_RETURN_EOF) && (error == NULL)) + { + ret= attachsql_connect_poll(con, &error); + } + param_count= attachsql_statement_get_param_count(con); + + attachsql_statement_set_int() ----------------------------- @@ -104,6 +197,28 @@ attachsql_statement_set_int() .. versionadded:: 0.4.0 .. versionchanged:: 0.5.0 +Example +^^^^^^^ + +.. code-block:: c + + attachsql_connect_t *con= NULL; + attachsql_error_t *error= NULL; + const char *query= "SELECT * FROM t1 WHERE name = ? AND age > ?"; + attachsql_return_t ret= ATTACHSQL_RETURN_NONE; + + con= attachsql_connect_create("localhost", 3306, "test", "test", "testdb", NULL); + attachsql_statement_prepare(con, strlen(query), query, &error); + while((ret != ATTACHSQL_RETURN_EOF) && (error == NULL)) + { + ret= attachsql_connect_poll(con, &error); + } + + int32_t age= 32; + attachsql_statement_set_int(con, 1, age, NULL); + +.. seealso:: :ref:`prepared-statements-example` example + attachsql_statement_set_unsigned_int() -------------------------------------- @@ -120,6 +235,26 @@ attachsql_statement_set_unsigned_int() .. versionadded:: 0.4.0 .. versionchanged:: 0.5.0 +Example +^^^^^^^ + +.. code-block:: c + + attachsql_connect_t *con= NULL; + attachsql_error_t *error= NULL; + const char *query= "SELECT * FROM t1 WHERE name = ? AND age > ?"; + attachsql_return_t ret= ATTACHSQL_RETURN_NONE; + + con= attachsql_connect_create("localhost", 3306, "test", "test", "testdb", NULL); + attachsql_statement_prepare(con, strlen(query), query, &error); + while((ret != ATTACHSQL_RETURN_EOF) && (error == NULL)) + { + ret= attachsql_connect_poll(con, &error); + } + + uint32_t age= 32; + attachsql_statement_set_unsigned_int(con, 1, age, NULL); + attachsql_statement_set_bigint() -------------------------------- @@ -136,6 +271,26 @@ attachsql_statement_set_bigint() .. versionadded:: 0.4.0 .. versionchanged:: 0.5.0 +Example +^^^^^^^ + +.. code-block:: c + + attachsql_connect_t *con= NULL; + attachsql_error_t *error= NULL; + const char *query= "SELECT * FROM t1 WHERE name = ? AND age > ?"; + attachsql_return_t ret= ATTACHSQL_RETURN_NONE; + + con= attachsql_connect_create("localhost", 3306, "test", "test", "testdb", NULL); + attachsql_statement_prepare(con, strlen(query), query, &error); + while((ret != ATTACHSQL_RETURN_EOF) && (error == NULL)) + { + ret= attachsql_connect_poll(con, &error); + } + + int64_t age= 32; + attachsql_statement_set_bigint(con, 1, age, NULL); + attachsql_statement_set_unsigned_bigint() ----------------------------------------- @@ -152,21 +307,25 @@ attachsql_statement_set_unsigned_bigint() .. versionadded:: 0.4.0 .. versionchanged:: 0.5.0 -attachsql_statement_set_float() -------------------------------- +Example +^^^^^^^ -.. c:function:: bool attachsql_statement_set_float(attachsql_connect_t *con, uint16_t param, float value, attachsql_error_t **error) +.. code-block:: c - Sets a float value for a given parameter + attachsql_connect_t *con= NULL; + attachsql_error_t *error= NULL; + const char *query= "SELECT * FROM t1 WHERE name = ? AND age > ?"; + attachsql_return_t ret= ATTACHSQL_RETURN_NONE; - :param con: The connection the statement is on - :param param: The parameter to set (starting at 0) - :param value: The value for the parameter - :param error: A pointer to a pointer of an error object which is created if an error occurs - :returns: ``true`` on success or ``false`` on failure + con= attachsql_connect_create("localhost", 3306, "test", "test", "testdb", NULL); + attachsql_statement_prepare(con, strlen(query), query, &error); + while((ret != ATTACHSQL_RETURN_EOF) && (error == NULL)) + { + ret= attachsql_connect_poll(con, &error); + } - .. versionadded:: 0.4.0 - .. versionchanged:: 0.5.0 + uint64_t age= 32; + attachsql_statement_set_unsigned_bigint(con, 1, age, NULL); attachsql_statement_set_double() -------------------------------- @@ -184,6 +343,26 @@ attachsql_statement_set_double() .. versionadded:: 0.4.0 .. versionchanged:: 0.5.0 +Example +^^^^^^^ + +.. code-block:: c + + attachsql_connect_t *con= NULL; + attachsql_error_t *error= NULL; + const char *query= "SELECT * FROM t1 WHERE type = ? AND length > ?"; + attachsql_return_t ret= ATTACHSQL_RETURN_NONE; + + con= attachsql_connect_create("localhost", 3306, "test", "test", "testdb", NULL); + attachsql_statement_prepare(con, strlen(query), query, &error); + while((ret != ATTACHSQL_RETURN_EOF) && (error == NULL)) + { + ret= attachsql_connect_poll(con, &error); + } + + float length= 3.6; + attachsql_statement_set_unsigned_bigint(con, 1, length, NULL); + attachsql_statement_set_string() -------------------------------- @@ -201,6 +380,34 @@ attachsql_statement_set_string() .. versionadded:: 0.4.0 .. versionchanged:: 0.5.0 +Example +^^^^^^^ + +.. code-block:: c + + attachsql_connect_t *con= NULL; + attachsql_error_t *error= NULL; + const char *query= "SELECT * FROM t1 WHERE name = ? AND age > ?"; + attachsql_return_t ret= ATTACHSQL_RETURN_NONE; + + con= attachsql_connect_create("localhost", 3306, "test", "test", "testdb", NULL); + attachsql_statement_prepare(con, strlen(query), query, &error); + while((ret != ATTACHSQL_RETURN_EOF) && (error == NULL)) + { + ret= attachsql_connect_poll(con, &error); + } + if (error != NULL) + { + printf("Error occurred: %s", attachsql_error_message(error)); + attachsql_error_free(error); + attachsql_statement_close(con); + attachsql_connect_destroy(con); + return 1; + } + + const char *name= "fred"; + attachsql_statement_set_string(con, 0, strlen(name), name, NULL); + attachsql_statement_set_binary() -------------------------------- @@ -218,6 +425,34 @@ attachsql_statement_set_binary() .. versionadded:: 0.4.0 .. versionchanged:: 0.5.0 +Example +^^^^^^^ + +.. code-block:: c + + attachsql_connect_t *con= NULL; + attachsql_error_t *error= NULL; + const char *query= "INSERT INTO t1 SET data = ?"; + attachsql_return_t ret= ATTACHSQL_RETURN_NONE; + + con= attachsql_connect_create("localhost", 3306, "test", "test", "testdb", NULL); + attachsql_statement_prepare(con, strlen(query), query, &error); + while((ret != ATTACHSQL_RETURN_EOF) && (error == NULL)) + { + ret= attachsql_connect_poll(con, &error); + } + if (error != NULL) + { + printf("Error occurred: %s", attachsql_error_message(error)); + attachsql_error_free(error); + attachsql_statement_close(con); + attachsql_connect_destroy(con); + return 1; + } + + const char data[]= {0xc0, 0xff, 0xee}; + attachsql_statement_set_binary(con, 0, 3, data, NULL); + attachsql_statement_set_null() ------------------------------ @@ -233,6 +468,33 @@ attachsql_statement_set_null() .. versionadded:: 0.4.0 .. versionchanged:: 0.5.0 +Example +^^^^^^^ + +.. code-block:: c + + attachsql_connect_t *con= NULL; + attachsql_error_t *error= NULL; + const char *query= "INSERT INTO t1 SET data = ?"; + attachsql_return_t ret= ATTACHSQL_RETURN_NONE; + + con= attachsql_connect_create("localhost", 3306, "test", "test", "testdb", NULL); + attachsql_statement_prepare(con, strlen(query), query, &error); + while((ret != ATTACHSQL_RETURN_EOF) && (error == NULL)) + { + ret= attachsql_connect_poll(con, &error); + } + if (error != NULL) + { + printf("Error occurred: %s", attachsql_error_message(error)); + attachsql_error_free(error); + attachsql_statement_close(con); + attachsql_connect_destroy(con); + return 1; + } + + attachsql_statement_set_null(con, 0, NULL); + attachsql_statement_set_datetime() ---------------------------------- @@ -255,6 +517,34 @@ attachsql_statement_set_datetime() .. versionadded:: 0.4.0 .. versionchanged:: 0.5.0 +Example +^^^^^^^ + +.. code-block:: c + + attachsql_connect_t *con= NULL; + attachsql_error_t *error= NULL; + const char *query= "INSERT INTO t1 SET post_date = ?"; + attachsql_return_t ret= ATTACHSQL_RETURN_NONE; + + con= attachsql_connect_create("localhost", 3306, "test", "test", "testdb", NULL); + attachsql_statement_prepare(con, strlen(query), query, &error); + while((ret != ATTACHSQL_RETURN_EOF) && (error == NULL)) + { + ret= attachsql_connect_poll(con, &error); + } + if (error != NULL) + { + printf("Error occurred: %s", attachsql_error_message(error)); + attachsql_error_free(error); + attachsql_statement_close(con); + attachsql_connect_destroy(con); + return 1; + } + + attachsql_statement_set_datetime(con, 0, 2014, 10, 6, 21, 50, 20, 324560, NULL); + + attachsql_statement_set_time() ------------------------------ @@ -275,6 +565,33 @@ attachsql_statement_set_time() .. versionadded:: 0.4.0 .. versionchanged:: 0.5.0 +Example +^^^^^^^ + +.. code-block:: c + + attachsql_connect_t *con= NULL; + attachsql_error_t *error= NULL; + const char *query= "INSERT INTO t1 SET post_time = ?"; + attachsql_return_t ret= ATTACHSQL_RETURN_NONE; + + con= attachsql_connect_create("localhost", 3306, "test", "test", "testdb", NULL); + attachsql_statement_prepare(con, strlen(query), query, &error); + while((ret != ATTACHSQL_RETURN_EOF) && (error == NULL)) + { + ret= attachsql_connect_poll(con, &error); + } + if (error != NULL) + { + printf("Error occurred: %s", attachsql_error_message(error)); + attachsql_error_free(error); + attachsql_statement_close(con); + attachsql_connect_destroy(con); + return 1; + } + + attachsql_statement_set_time(con, 0, 21, 50, 20, 324560, false, NULL); + attachsql_statement_row_get() ----------------------------- @@ -289,6 +606,11 @@ attachsql_statement_row_get() .. versionadded:: 0.4.0 .. versionchanged:: 0.5.0 +Example +^^^^^^^ + +See the :ref:`prepared-statements-example` example + attachsql_statement_get_int() ----------------------------- @@ -303,6 +625,47 @@ attachsql_statement_get_int() .. versionadded:: 0.4.0 +Example +^^^^^^^ + +.. code-block:: c + + attachsql_connect_t *con= NULL; + attachsql_error_t *error= NULL; + const char *query= "SELECT * FROM t1 WHERE name = ? AND age > ?"; + attachsql_return_t ret= ATTACHSQL_RETURN_NONE; + + con= attachsql_connect_create("localhost", 3306, "test", "test", "testdb", NULL); + attachsql_statement_prepare(con, strlen(query), query, &error); + while((ret != ATTACHSQL_RETURN_EOF) && (error == NULL)) + { + ret= attachsql_connect_poll(con, &error); + } + + const char *name= "fred"; + uint32_t age= 30; + attachsql_statement_set_string(con, 0, strlen(name), name, NULL); + attachsql_statement_set_int(con, 1, age, NULL); + attachsql_statement_execute(con, &error); + ret= ATTACHSQL_RETURN_NONE; + while ((ret != ATTACHSQL_RETURN_EOF) && (error == NULL)) + { + ret= attachsql_connect_poll(con, &error); + if (ret != ATTACHSQL_RETURN_ROW_READY) + { + continue; + } + attachsql_statement_row_get(con, &error); + printf("ID: %d, ", attachsql_statement_get_int(con, 0, &error)); + size_t len; + char *name_data= attachsql_statement_get_char(con, 1, &len, &error); + printf("Name: %.*s, ", (int)len, name_data); + printf("Age: %d\n", attachsql_statement_get_int(con, 2, &error)); + attachsql_statement_row_next(con); + } + +.. seealso:: :ref:`prepared-statements-example` example + attachsql_statement_get_unsigned_int() -------------------------------------- @@ -317,6 +680,45 @@ attachsql_statement_get_unsigned_int() .. versionadded:: 0.4.0 +Example +^^^^^^^ + +.. code-block:: c + + attachsql_connect_t *con= NULL; + attachsql_error_t *error= NULL; + const char *query= "SELECT * FROM t1 WHERE name = ? AND age > ?"; + attachsql_return_t ret= ATTACHSQL_RETURN_NONE; + + con= attachsql_connect_create("localhost", 3306, "test", "test", "testdb", NULL); + attachsql_statement_prepare(con, strlen(query), query, &error); + while((ret != ATTACHSQL_RETURN_EOF) && (error == NULL)) + { + ret= attachsql_connect_poll(con, &error); + } + + const char *name= "fred"; + uint32_t age= 30; + attachsql_statement_set_string(con, 0, strlen(name), name, NULL); + attachsql_statement_set_int(con, 1, age, NULL); + attachsql_statement_execute(con, &error); + ret= ATTACHSQL_RETURN_NONE; + while ((ret != ATTACHSQL_RETURN_EOF) && (error == NULL)) + { + ret= attachsql_connect_poll(con, &error); + if (ret != ATTACHSQL_RETURN_ROW_READY) + { + continue; + } + attachsql_statement_row_get(con, &error); + printf("ID: %d, ", attachsql_statement_get_unsigned_int(con, 0, &error)); + size_t len; + char *name_data= attachsql_statement_get_char(con, 1, &len, &error); + printf("Name: %.*s, ", (int)len, name_data); + printf("Age: %d\n", attachsql_statement_get_unsigned_int(con, 2, &error)); + attachsql_statement_row_next(con); + } + attachsql_statement_get_bigint() -------------------------------- @@ -331,6 +733,46 @@ attachsql_statement_get_bigint() .. versionadded:: 0.4.0 +Example +^^^^^^^ + +.. code-block:: c + + attachsql_connect_t *con= NULL; + attachsql_error_t *error= NULL; + const char *query= "SELECT * FROM t1 WHERE name = ? AND age > ?"; + attachsql_return_t ret= ATTACHSQL_RETURN_NONE; + + con= attachsql_connect_create("localhost", 3306, "test", "test", "testdb", NULL); + attachsql_statement_prepare(con, strlen(query), query, &error); + while((ret != ATTACHSQL_RETURN_EOF) && (error == NULL)) + { + ret= attachsql_connect_poll(con, &error); + } + + const char *name= "fred"; + uint32_t age= 30; + attachsql_statement_set_string(con, 0, strlen(name), name, NULL); + attachsql_statement_set_int(con, 1, age, NULL); + attachsql_statement_execute(con, &error); + ret= ATTACHSQL_RETURN_NONE; + while ((ret != ATTACHSQL_RETURN_EOF) && (error == NULL)) + { + ret= attachsql_connect_poll(con, &error); + if (ret != ATTACHSQL_RETURN_ROW_READY) + { + continue; + } + attachsql_statement_row_get(con, &error); + printf("ID: %lld, ", attachsql_statement_get_bigint(con, 0, &error)); + size_t len; + char *name_data= attachsql_statement_get_char(con, 1, &len, &error); + printf("Name: %.*s, ", (int)len, name_data); + printf("Age: %d\n", attachsql_statement_get_int(con, 2, &error)); + attachsql_statement_row_next(con); + } + + attachsql_statement_get_unsigned_bigint() ----------------------------------------- @@ -345,19 +787,44 @@ attachsql_statement_get_unsigned_bigint() .. versionadded:: 0.4.0 -attachsql_statement_get_float() -------------------------------- - -.. c:function:: float attachsql_statement_get_float(attachsql_connect_t *con, uint16_t column, attachsql_error_t **error) - - Retrieves a float value from a column of a result set. Converting a non-float where possible. An error condition will occur if conversion is not possible. - - :param con: The connection the statement is on - :param column: The column number to retrieve data from (starting at 0) - :param error: A pointer to a pointer of an error object which is created if an error occurs - :returns: The float value (or 0 upon error) - - .. versionadded:: 0.4.0 +Example +^^^^^^^ + +.. code-block:: c + + attachsql_connect_t *con= NULL; + attachsql_error_t *error= NULL; + const char *query= "SELECT * FROM t1 WHERE name = ? AND age > ?"; + attachsql_return_t ret= ATTACHSQL_RETURN_NONE; + + con= attachsql_connect_create("localhost", 3306, "test", "test", "testdb", NULL); + attachsql_statement_prepare(con, strlen(query), query, &error); + while((ret != ATTACHSQL_RETURN_EOF) && (error == NULL)) + { + ret= attachsql_connect_poll(con, &error); + } + + const char *name= "fred"; + uint32_t age= 30; + attachsql_statement_set_string(con, 0, strlen(name), name, NULL); + attachsql_statement_set_int(con, 1, age, NULL); + attachsql_statement_execute(con, &error); + ret= ATTACHSQL_RETURN_NONE; + while ((ret != ATTACHSQL_RETURN_EOF) && (error == NULL)) + { + ret= attachsql_connect_poll(con, &error); + if (ret != ATTACHSQL_RETURN_ROW_READY) + { + continue; + } + attachsql_statement_row_get(con, &error); + printf("ID: %llu, ", attachsql_statement_get_unsigned_bigint(con, 0, &error)); + size_t len; + char *name_data= attachsql_statement_get_char(con, 1, &len, &error); + printf("Name: %.*s, ", (int)len, name_data); + printf("Age: %d\n", attachsql_statement_get_int(con, 2, &error)); + attachsql_statement_row_next(con); + } attachsql_statement_get_double() -------------------------------- @@ -373,6 +840,45 @@ attachsql_statement_get_double() .. versionadded:: 0.4.0 +Example +^^^^^^^ + +.. code-block:: c + + attachsql_connect_t *con= NULL; + attachsql_error_t *error= NULL; + const char *query= "SELECT * FROM t1 WHERE type = ? AND size > ?"; + attachsql_return_t ret= ATTACHSQL_RETURN_NONE; + + con= attachsql_connect_create("localhost", 3306, "test", "test", "testdb", NULL); + attachsql_statement_prepare(con, strlen(query), query, &error); + while((ret != ATTACHSQL_RETURN_EOF) && (error == NULL)) + { + ret= attachsql_connect_poll(con, &error); + } + + const char *type= "pole"; + uint32_t size= 6.5; + attachsql_statement_set_string(con, 0, strlen(type), type, NULL); + attachsql_statement_set_int(con, 1, size, NULL); + attachsql_statement_execute(con, &error); + ret= ATTACHSQL_RETURN_NONE; + while ((ret != ATTACHSQL_RETURN_EOF) && (error == NULL)) + { + ret= attachsql_connect_poll(con, &error); + if (ret != ATTACHSQL_RETURN_ROW_READY) + { + continue; + } + attachsql_statement_row_get(con, &error); + printf("ID: %d, ", attachsql_statement_get_int(con, 0, &error)); + size_t len; + char *type_data= attachsql_statement_get_char(con, 1, &len, &error); + printf("Type: %.*s, ", (int)len, type_data); + printf("Size: %f\n", attachsql_statement_get_double(con, 2, &error)); + attachsql_statement_row_next(con); + } + attachsql_statement_get_char() ------------------------------ @@ -388,6 +894,47 @@ attachsql_statement_get_char() .. versionadded:: 0.4.0 +Example +^^^^^^^ + +.. code-block:: c + + attachsql_connect_t *con= NULL; + attachsql_error_t *error= NULL; + const char *query= "SELECT * FROM t1 WHERE name = ? AND age > ?"; + attachsql_return_t ret= ATTACHSQL_RETURN_NONE; + + con= attachsql_connect_create("localhost", 3306, "test", "test", "testdb", NULL); + attachsql_statement_prepare(con, strlen(query), query, &error); + while((ret != ATTACHSQL_RETURN_EOF) && (error == NULL)) + { + ret= attachsql_connect_poll(con, &error); + } + + const char *name= "fred"; + uint32_t age= 30; + attachsql_statement_set_string(con, 0, strlen(name), name, NULL); + attachsql_statement_set_int(con, 1, age, NULL); + attachsql_statement_execute(con, &error); + ret= ATTACHSQL_RETURN_NONE; + while ((ret != ATTACHSQL_RETURN_EOF) && (error == NULL)) + { + ret= attachsql_connect_poll(con, &error); + if (ret != ATTACHSQL_RETURN_ROW_READY) + { + continue; + } + attachsql_statement_row_get(con, &error); + printf("ID: %d, ", attachsql_statement_get_int(con, 0, &error)); + size_t len; + char *name_data= attachsql_statement_get_char(con, 1, &len, &error); + printf("Name: %.*s, ", (int)len, name_data); + printf("Age: %d\n", attachsql_statement_get_int(con, 2, &error)); + attachsql_statement_row_next(con); + } + +.. seealso:: :ref:`prepared-statements-example` example + attachsql_statement_get_column_type() ------------------------------------- @@ -401,6 +948,52 @@ attachsql_statement_get_column_type() .. versionadded:: 0.9.0 +Example +^^^^^^^ + +.. code-block:: c + + attachsql_connect_t *con= NULL; + attachsql_error_t *error= NULL; + const char *query= "SELECT * FROM t1 WHERE name = ? AND age > ?"; + attachsql_return_t ret= ATTACHSQL_RETURN_NONE; + + con= attachsql_connect_create("localhost", 3306, "test", "test", "testdb", NULL); + attachsql_statement_prepare(con, strlen(query), query, &error); + while((ret != ATTACHSQL_RETURN_EOF) && (error == NULL)) + { + ret= attachsql_connect_poll(con, &error); + } + + const char *name= "fred"; + uint32_t age= 30; + attachsql_statement_set_string(con, 0, strlen(name), name, NULL); + attachsql_statement_set_int(con, 1, age, NULL); + attachsql_statement_execute(con, &error); + ret= ATTACHSQL_RETURN_NONE; + while ((ret != ATTACHSQL_RETURN_EOF) && (error == NULL)) + { + ret= attachsql_connect_poll(con, &error); + if (ret != ATTACHSQL_RETURN_ROW_READY) + { + continue; + } + attachsql_statement_row_get(con, &error); + printf("ID: %d, ", attachsql_statement_get_int(con, 0, &error)); + size_t len; + char *name_data= attachsql_statement_get_char(con, 1, &len, &error); + printf("Name: %.*s, ", (int)len, name_data); + if (attachsql_statement_get_type(con, 2) == ATTACHSQL_COLUMN_TYPE_LONG) + { + printf("Age: %d\n", attachsql_statement_get_int(con, 2, &error)); + } + else + { + printf("Age column is an unexpected type"); + } + attachsql_statement_row_next(con); + } + attachsql_statement_row_next() ------------------------------ @@ -412,6 +1005,11 @@ attachsql_statement_row_next() .. versionadded:: 0.9.0 +Example +^^^^^^^ + +See the :ref:`prepared-statements-example` example + attachsql_statement_get_column_count() -------------------------------------- @@ -423,3 +1021,37 @@ attachsql_statement_get_column_count() :returns: The column count or ``0`` if there is no active statement .. versionadded:: 0.9.0 + +Example +^^^^^^^ + +.. code-block:: c + + attachsql_connect_t *con= NULL; + attachsql_error_t *error= NULL; + const char *query= "SELECT * FROM t1 WHERE name = ? AND age > ?"; + attachsql_return_t ret= ATTACHSQL_RETURN_NONE; + + con= attachsql_connect_create("localhost", 3306, "test", "test", "testdb", NULL); + attachsql_statement_prepare(con, strlen(query), query, &error); + while((ret != ATTACHSQL_RETURN_EOF) && (error == NULL)) + { + ret= attachsql_connect_poll(con, &error); + } + + const char *name= "fred"; + uint32_t age= 30; + attachsql_statement_set_string(con, 0, strlen(name), name, NULL); + attachsql_statement_set_int(con, 1, age, NULL); + attachsql_statement_execute(con, &error); + ret= ATTACHSQL_RETURN_NONE; + while ((ret != ATTACHSQL_RETURN_EOF) && (error == NULL)) + { + ret= attachsql_connect_poll(con, &error); + if (ret != ATTACHSQL_RETURN_ROW_READY) + { + continue; + } + break; + } + printf("%d columns\n", attachsql_statement_get_column_count(con)); diff --git a/docs/api/types.rst b/docs/api/types.rst index 52647ab..99a2b14 100644 --- a/docs/api/types.rst +++ b/docs/api/types.rst @@ -12,9 +12,9 @@ Basic Types An error object allocated by many functions in the library and needs to be freed by the user using :c:func:`attachsql_error_free`. -.. c:type:: attachsql_group_t +.. c:type:: attachsql_pool_t - An object containing a group of connections to be executed using the same event loop. + An object containing a pool of connections to be executed using the same event loop. Builtin Types ------------- @@ -165,11 +165,12 @@ Callbacks .. c:type:: attachsql_callback_fn - A callback function template for use with :c:func:`attachsql_connect_set_callback`. Defined as: + A callback function template for use with :c:func:`attachsql_pool_create`. Defined as: - .. c:function:: void (attachsql_callback_fn)(attachsql_connect_t *con, attachsql_events_t events, void *context, attachsql_error_t *error) + .. c:function:: void (attachsql_callback_fn)(attachsql_connect_t *con, uint32_t connection_id, attachsql_events_t events, void *context, attachsql_error_t *error) :param con: The connection object + :param connection_id: A unique ID given to the connection by libAttachSQL, *NOT* the MySQL thread ID :param events: The event triggered :param context: A user defined pointer which is set along with the callback :param error: An error object (if an error occurred) @@ -190,8 +191,6 @@ ENUMs +------------------------------------+--------------------------------------------------------------------+ | ``ATTACHSQL_RETURN_CONNECTING`` | Connection/handshake currently in-progress | +------------------------------------+--------------------------------------------------------------------+ - | ``ATTACHSQL_RETURN_IDLE`` | Connection is idle and waiting for a command | - +------------------------------------+--------------------------------------------------------------------+ | ``ATTACHSQL_RETURN_PROCESSING`` | The query is currently processing | +------------------------------------+--------------------------------------------------------------------+ | ``ATTACHSQL_RETURN_ROW_READY`` | A row is ready for retrieval from the buffer | diff --git a/docs/appendix/version_history.rst b/docs/appendix/version_history.rst index 2626e91..f125aff 100644 --- a/docs/appendix/version_history.rst +++ b/docs/appendix/version_history.rst @@ -1,6 +1,63 @@ Version History =============== +Version 2.0 +----------- + +Version 2.0.0 Beta (Not yet released) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +* Removed the IDLE return state, it was causing confusion and the EOF state did the same (`Issue #179 `_) +* Removed ``attachsql_statement_set_float()`` and ``attachsql_statement_get_float()``. The double functions should be used instead (`Issue #181 `_) +* All `group` functions and types have been renamed to `pool` +* Configure now checks version numbers for dependencies +* libAttachSQL now requires libuv 1.4 or above +* Build system cleanups +* Callbacks are now in the connection pool rather than individual connections (`Issue #131 `_) + + +Version 1.0 +----------- + +Version 1.0.3 GA (2015-02-19) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +* Fixed compiling Mac universal in debug mode (`Issue #167 `_) +* Fixed test cases when MySQL is in a alternative timezone (`Issue #168 `_) +* Fixed self-signed certificates in test suite (`Issue #170 `_) +* Fixed Ubuntu 12.04 test verbosity breaking Travis CI (`Issue #174 `_) +* Fixed expired SSL certificates in test suite (`Issue #176 `_) +* Added many examples to the documentation (`Issue #172 `_) +* Slightly improved performance of prepared statement prepare phase (`Issue #166 `_) + +Version 1.0.2 GA (2014-12-02) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +* Fixed compiler issues in Mac OS X 10.10 (`Issue #151 `_) +* Added universal (x86 and x86_64) binary support for Mac OS X (`Issue #153 `_) +* Fixed cleanup for distcheck (`Issue #155 `_) +* Fixed debuginfo RPM building (`Issue #157 `_) +* Fixed crash on statement cleanup with unused connection (`Issue #159 `_) +* Fixed incorrect column count check on prepared statement get_* functions (`Issue #162 `_) + +Version 1.0.1 GA (2014-11-16) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +* Removed libuv calls that were not needed (`Issue #139 `_) +* Allow batched command sending which removes the need to stop the entire event loop when a command is sent (`Issue #140 `_) +* Add a next packet stack for further batch command support (`Issue #143 `_) +* Fix segfault when destroying an unused connection (`Issue #147 `_) + +Version 1.0.0 GA (2014-10-21) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +* Fixed a lockup with many connections using connection groups (`Issue #124 `_) +* Fixed prepared statement with semi-block hangs (`Issue #128 `_) +* Fixed SSL+compression on the same connection (`Issue #127 `_) +* Fixed compression and SSL when used with Connection Groups (`Issue #125 `_) +* Improved error handling for connect and network errors (`Issue #133 `_) +* Some clang static analysis based code cleanups + Version 0.9 ----------- @@ -16,11 +73,11 @@ Version 0.9.0 RC (2014-10-14) * Added new connection groups feature (`Issue #115 `_) * Changed :c:type:`attachsql_callback_fn` to include an error object. **THIS BREAKS API OVER 0.5.0** - * Added :c:type:`attachsql_group_t` - * Added :c:func:`attachsql_group_create` - * Added :c:func:`attachsql_group_destroy` - * Added :c:func:`attachsql_group_add_connection` - * Added :c:func:`attachsql_group_run` + * Added ``attachsql_group_t`` + * Added ``attachsql_group_create()`` + * Added ``attachsql_group_destroy()`` + * Added ``attachsql_group_add_connection()`` + * Added ``attachsql_group_run()`` * Packet processing is now part of the event loop * Added example @@ -74,7 +131,7 @@ Incompatible changes * :c:func:`attachsql_statement_set_unsigned_int` * :c:func:`attachsql_statement_set_bigint` * :c:func:`attachsql_statement_set_unsigned_bigint` - * :c:func:`attachsql_statement_set_float` + * ``attachsql_statement_set_float()`` * :c:func:`attachsql_statement_set_double` * :c:func:`attachsql_statement_set_string` * :c:func:`attachsql_statement_set_binary` diff --git a/docs/contributors/introduction.rst b/docs/contributors/introduction.rst index f251e5a..54e59a1 100644 --- a/docs/contributors/introduction.rst +++ b/docs/contributors/introduction.rst @@ -8,17 +8,17 @@ Layout The code for libAttachSQL in several parts: -+-----------------------+--------------------------------------+ -| Directory | Contents | -+=======================+======================================+ -| ``/src/ascore`` | The core internal protocol functions | -+-----------------------+--------------------------------------+ -| ``/src/asql`` | The public API functions | -+-----------------------+--------------------------------------+ -| ``/libattachsql-1.0`` | The public API headers | -+-----------------------+--------------------------------------+ -| ``/tests/asql`` | Unit tests for the public API | -+-----------------------+--------------------------------------+ ++--------------------+-------------------------------+ +| Directory | Contents | ++====================+===============================+ +| ``/src`` | The API source code | ++--------------------+-------------------------------+ +| ``/libattachsql2`` | The public API headers | ++--------------------+-------------------------------+ +| ``/tests/asql`` | Unit tests for the public API | ++--------------------+-------------------------------+ +| ``/examples`` | Usage examples for the API | ++--------------------+-------------------------------+ In each case if any files are added or removed the ``include.am`` file in that directory will require updating to reflect the change. @@ -62,7 +62,7 @@ Function Visibility The code and build system only exposes public API functions as usable symbols in the finished binary. This cuts down on binary size quite significantly and also discourages use of undocumented functionality that was not designed for public use. -When adding a new API function to ``/libattachsql-1.0`` always add ``ASQL_API`` on its own on the line above the function definition in the header. This tells the build system this is an API function to be included. +When adding a new API function to ``/libattachsql2`` always add ``ASQL_API`` on its own on the line above the function definition in the header. This tells the build system this is an API function to be included. License Headers --------------- diff --git a/docs/contributors/test_cases.rst b/docs/contributors/test_cases.rst index 5e980ea..08a0e29 100644 --- a/docs/contributors/test_cases.rst +++ b/docs/contributors/test_cases.rst @@ -12,19 +12,19 @@ The ``.travis.yml`` file sets this up automatically for Travis CI test runs. Adding a Test Case ------------------ -Test cases are basic C/C++ applications in the ``tests/asql/`` directory. To add a test case to the suite. To add a test edit the ``include.am`` and add the following (replacing *query* with whatever the test is called): +Test cases are basic C/C++ applications in the ``tests/`` directory. To add a test case to the suite. To add a test edit the ``include.am`` and add the following (replacing *query* with whatever the test is called): .. code-block:: makefile - t_asql_query_SOURCES= tests/asql/query.cc - t_asql_query_LDADD= src/asql/libattachsql.la + t_query_SOURCES= tests/query.cc + t_query_LDADD= src/libattachsql.la if BUILD_WIN32 - t_asql_query_LDADD+= -lws2_32 - t_asql_query_LDADD+= -lpsapi - t_asql_query_LDADD+= -liphlpapi + t_query_LDADD+= -lws2_32 + t_query_LDADD+= -lpsapi + t_query_LDADD+= -liphlpapi endif - check_PROGRAMS+= t/asql/query - noinst_PROGRAMS+= t/asql/query + check_PROGRAMS+= t/query + noinst_PROGRAMS+= t/query Using YATL diff --git a/docs/index.rst b/docs/index.rst index fb7b196..54974a1 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -24,7 +24,7 @@ API Documentation api/connection api/query api/statement - api/group + api/pool api/error api/utility api/compiling diff --git a/docs/introduction/compiling.rst b/docs/introduction/compiling.rst index 65f0e9c..cb7ac7f 100644 --- a/docs/introduction/compiling.rst +++ b/docs/introduction/compiling.rst @@ -3,34 +3,37 @@ Compiling libAttachSQL libAttachSQL is designed to be compiled with GCC or CLang on a modern Linux distrubition or Mac OSX. -Prerequisites -------------- - -libAttachSQL requires *libuv 0.10* to be installed. For RedHat 6.x this is in the EPEL repositories so make sure those are enabled first. In RedHat/Fedora this is installed using: +On a Mac you should have XCode along with XCode's console tools installed along with `Homebrew `_. You will need to following once homebrew is installed to get the proper dev environment: .. code-block:: bash - sudo yum install libuv-devel + brew install autoconf automake libtool pkg-config -On a Mac we recommend using `Homebrew `_ to install this: +Prerequisites +------------- + +libAttachSQL requires *libuv 1.x* to be installed. For Fedora 22 this can be installed using: .. code-block:: bash - brew install libuv + sudo dnf install libuv-devel -Ubuntu 12.04 does not have libuv in its repositories so LinuxJedi created a PPA for this dependency (simply a backport from 14.04) which is used for the Travis CI tests. It can be found at: ``_. To install it simply do: +On a Mac we recommend using Homebrew to install this: .. code-block:: bash - sudo apt-add-repository ppa:linuxjedi/ppa - sudo apt-get update - sudo apt-get install libuv-dev + brew install libuv -More current versions of Ubuntu have libuv and it can be installed using: +For most other Linux operating systems version 0.10 or 0.11 is still in the repositories so this currently needs to be compiled from source: .. code-block:: bash - sudo apt-get install libuv-dev + git clone git://github.com/libuv/libuv + cd libuv + ./autogen.sh + ./configure --prefix=/usr + make + sudo make install Optional Libraries ------------------ @@ -137,3 +140,5 @@ The build system for libAttachSQL has the capability to build RPMs. To build RP ./configure make dist-rpm +.. note:: + The package ``redhat-rpm-config`` is required for building the RPM because this generates the debuginfo RPM. diff --git a/examples/basic_query.c b/examples/basic_query.c index cdb3f5d..2899215 100644 --- a/examples/basic_query.c +++ b/examples/basic_query.c @@ -15,7 +15,7 @@ * */ -#include +#include #include #include #include diff --git a/examples/buffered_query.c b/examples/buffered_query.c index 039d590..d9f94af 100644 --- a/examples/buffered_query.c +++ b/examples/buffered_query.c @@ -15,7 +15,7 @@ * */ -#include +#include #include #include #include diff --git a/examples/escaped_query.c b/examples/escaped_query.c index 7980daa..0f48cda 100644 --- a/examples/escaped_query.c +++ b/examples/escaped_query.c @@ -15,7 +15,7 @@ * */ -#include +#include #include #include #include diff --git a/examples/include.am b/examples/include.am index 021eba3..7cbecd6 100644 --- a/examples/include.am +++ b/examples/include.am @@ -9,7 +9,7 @@ # All paths should be given relative to the root examples_basic_query_SOURCES= examples/basic_query.c -examples_basic_query_LDADD= src/asql/libattachsql.la +examples_basic_query_LDADD= src/libattachsql.la if BUILD_WIN32 examples_basic_query_LDADD+= -lws2_32 examples_basic_query_LDADD+= -lpsapi @@ -19,7 +19,7 @@ endif noinst_PROGRAMS+= examples/basic_query examples_buffered_query_SOURCES= examples/buffered_query.c -examples_buffered_query_LDADD= src/asql/libattachsql.la +examples_buffered_query_LDADD= src/libattachsql.la if BUILD_WIN32 examples_buffered_query_LDADD+= -lws2_32 examples_buffered_query_LDADD+= -lpsapi @@ -29,7 +29,7 @@ endif noinst_PROGRAMS+= examples/buffered_query examples_escaped_query_SOURCES= examples/escaped_query.c -examples_escaped_query_LDADD= src/asql/libattachsql.la +examples_escaped_query_LDADD= src/libattachsql.la if BUILD_WIN32 examples_escaped_query_LDADD+= -lws2_32 examples_escaped_query_LDADD+= -lpsapi @@ -39,7 +39,7 @@ endif noinst_PROGRAMS+= examples/escaped_query examples_prepared_statement_SOURCES= examples/prepared_statement.c -examples_prepared_statement_LDADD= src/asql/libattachsql.la +examples_prepared_statement_LDADD= src/libattachsql.la if BUILD_WIN32 examples_prepared_statement_LDADD+= -lws2_32 examples_prepared_statement_LDADD+= -lpsapi @@ -48,15 +48,15 @@ examples_prepared_statement_LDADD+= -lstdc++ endif noinst_PROGRAMS+= examples/prepared_statement -examples_group_query_SOURCES= examples/group_query.c -examples_group_query_LDADD= src/asql/libattachsql.la +examples_pool_query_SOURCES= examples/pool_query.c +examples_pool_query_LDADD= src/libattachsql.la if BUILD_WIN32 -examples_group_query_LDADD+= -lws2_32 -examples_group_query_LDADD+= -lpsapi -examples_group_query_LDADD+= -liphlpapi -examples_group_query_CFLAGS= -D__USE_MINGW_ANSI_STDIO -examples_group_query_LDADD+= -lstdc++ +examples_pool_query_LDADD+= -lws2_32 +examples_pool_query_LDADD+= -lpsapi +examples_pool_query_LDADD+= -liphlpapi +examples_pool_query_CFLAGS= -D__USE_MINGW_ANSI_STDIO +examples_pool_query_LDADD+= -lstdc++ endif -noinst_PROGRAMS+= examples/group_query +noinst_PROGRAMS+= examples/pool_query diff --git a/examples/group_query.c b/examples/pool_query.c similarity index 67% rename from examples/group_query.c rename to examples/pool_query.c index 10014f5..02accf4 100644 --- a/examples/group_query.c +++ b/examples/pool_query.c @@ -15,31 +15,30 @@ * */ -#include +#include #include #include #include -uint8_t done_count= 0; +static uint8_t done_count= 0; -void callbk(attachsql_connect_t *current_con, attachsql_events_t events, void *context, attachsql_error_t *error); - -void callbk(attachsql_connect_t *current_con, attachsql_events_t events, void *context, attachsql_error_t *error) +static void callbk(attachsql_connect_t *current_con, uint32_t connection_id, attachsql_events_t events, void *context, attachsql_error_t *error) { - uint8_t *con_no= (uint8_t*)context; + (void) context; attachsql_query_row_st *row; uint16_t columns, col; switch(events) { case ATTACHSQL_EVENT_CONNECTED: - printf("Connected event on con %d\n", *con_no); + printf("Connected event on con %d\n", connection_id); break; case ATTACHSQL_EVENT_ERROR: - printf("Error exists on con %d: %d", *con_no, attachsql_error_code(error)); + printf("Error exists on con %d: %d", connection_id, attachsql_error_code(error)); + done_count++; attachsql_error_free(error); break; case ATTACHSQL_EVENT_EOF: - printf("Connection %d finished\n", *con_no); + printf("Connection %d finished\n", connection_id); done_count++; attachsql_query_close(current_con); break; @@ -48,7 +47,7 @@ void callbk(attachsql_connect_t *current_con, attachsql_events_t events, void *c columns= attachsql_query_column_count(current_con); for (col=0; col < columns; col++) { - printf("Con: %d, Column: %d, Length: %zu, Data: %.*s ", *con_no, col, row[col].length, (int)row[col].length, row[col].data); + printf("Con: %d, Column: %d, Length: %zu, Data: %.*s ", connection_id, col, row[col].length, (int)row[col].length, row[col].data); } attachsql_query_row_next(current_con); printf("\n"); @@ -63,30 +62,26 @@ int main(int argc, char *argv[]) (void) argc; (void) argv; attachsql_connect_t *con[3]; - attachsql_group_t *group; + attachsql_pool_t *pool; attachsql_error_t *error= NULL; const char *query1= "SELECT * FROM t1 WHERE name='fred'"; const char *query2= "SELECT * FROM t1 WHERE age >= 40"; const char *query3= "SELECT * FROM t1 WHERE age < 40"; - uint8_t con_no[3]= {0, 1, 2}; - group= attachsql_group_create(NULL); + pool= attachsql_pool_create(callbk, NULL, NULL); con[0]= attachsql_connect_create("localhost", 3306, "test", "test", "testdb", NULL); - attachsql_group_add_connection(group, con[0], &error); - attachsql_connect_set_callback(con[0], callbk, &con_no[0]); + attachsql_pool_add_connection(pool, con[0], &error); con[1]= attachsql_connect_create("localhost", 3306, "test", "test", "testdb", NULL); - attachsql_group_add_connection(group, con[1], &error); - attachsql_connect_set_callback(con[1], callbk, &con_no[1]); + attachsql_pool_add_connection(pool, con[1], &error); con[2]= attachsql_connect_create("localhost", 3306, "test", "test", "testdb", NULL); - attachsql_group_add_connection(group, con[2], &error); - attachsql_connect_set_callback(con[2], callbk, &con_no[2]); + attachsql_pool_add_connection(pool, con[2], &error); attachsql_query(con[0], strlen(query1), query1, 0, NULL, &error); attachsql_query(con[1], strlen(query2), query2, 0, NULL, &error); attachsql_query(con[2], strlen(query3), query3, 0, NULL, &error); while(done_count < 3) { - attachsql_group_run(group); + attachsql_pool_run(pool); } - attachsql_group_destroy(group); + attachsql_pool_destroy(pool); } diff --git a/examples/prepared_statement.c b/examples/prepared_statement.c index bdcbda4..66655a3 100644 --- a/examples/prepared_statement.c +++ b/examples/prepared_statement.c @@ -15,7 +15,7 @@ * */ -#include +#include #include #include #include diff --git a/libattachsql-1.0/include.am b/libattachsql-1.0/include.am deleted file mode 100644 index a17da1a..0000000 --- a/libattachsql-1.0/include.am +++ /dev/null @@ -1,13 +0,0 @@ -# vim:ft=automake -# included from Top Level Makefile.am -# All paths should be given relative to the root - -nobase_include_HEADERS+= libattachsql-1.0/attachsql.h -nobase_include_HEADERS+= libattachsql-1.0/connect.h -nobase_include_HEADERS+= libattachsql-1.0/constants.h -nobase_include_HEADERS+= libattachsql-1.0/error.h -nobase_include_HEADERS+= libattachsql-1.0/group.h -nobase_include_HEADERS+= libattachsql-1.0/query.h -nobase_include_HEADERS+= libattachsql-1.0/utility.h -nobase_include_HEADERS+= libattachsql-1.0/statement.h -nobase_include_HEADERS+= libattachsql-1.0/visibility.h diff --git a/libattachsql.pc.in b/libattachsql.pc.in new file mode 100644 index 0000000..f6e4c73 --- /dev/null +++ b/libattachsql.pc.in @@ -0,0 +1,11 @@ +prefix=@prefix@ +exec_prefix=@prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: @PACKAGE_NAME@ +Version: @PACKAGE_VERSION@ +Description: a non-blocking C connector for MySQL servers. + +Libs: -L${libdir} -luv @LIBS@ +Cflags: -I${includedir} diff --git a/libattachsql-1.0/attachsql.h b/libattachsql2/attachsql.h similarity index 68% rename from libattachsql-1.0/attachsql.h rename to libattachsql2/attachsql.h index a433806..0331d10 100644 --- a/libattachsql-1.0/attachsql.h +++ b/libattachsql2/attachsql.h @@ -5,7 +5,7 @@ * not use this file except in compliance with the License. You may obtain * a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE2 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT @@ -30,13 +30,13 @@ typedef uint16_t in_port_t; #endif /* These four need to go first, in this order */ -#include -#include -#include -#include +#include +#include +#include +#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include diff --git a/libattachsql-1.0/connect.h b/libattachsql2/connect.h similarity index 93% rename from libattachsql-1.0/connect.h rename to libattachsql2/connect.h index f5b7f3d..4b778e1 100644 --- a/libattachsql-1.0/connect.h +++ b/libattachsql2/connect.h @@ -27,9 +27,6 @@ attachsql_connect_t *attachsql_connect_create(const char *host, in_port_t port, ASQL_API void attachsql_connect_destroy(attachsql_connect_t *con); -ASQL_API -void attachsql_connect_set_callback(attachsql_connect_t *con, attachsql_callback_fn *function, void *context); - ASQL_API const char *attachsql_connect_get_server_version(attachsql_connect_t *con); diff --git a/libattachsql-1.0/constants.h b/libattachsql2/constants.h similarity index 97% rename from libattachsql-1.0/constants.h rename to libattachsql2/constants.h index 4aad1b4..cb6643f 100644 --- a/libattachsql-1.0/constants.h +++ b/libattachsql2/constants.h @@ -44,7 +44,6 @@ enum attachsql_return_t ATTACHSQL_RETURN_NONE, ATTACHSQL_RETURN_NOT_CONNECTED, ATTACHSQL_RETURN_CONNECTING, - ATTACHSQL_RETURN_IDLE, ATTACHSQL_RETURN_PROCESSING, ATTACHSQL_RETURN_ROW_READY, ATTACHSQL_RETURN_ERROR, @@ -174,8 +173,8 @@ typedef enum attachsql_error_codes_t attachsql_error_codes_t; typedef struct attachsql_error_t attachsql_error_t; -struct attachsql_group_t; -typedef struct attachsql_group_t attachsql_group_t; +struct attachsql_pool_t; +typedef struct attachsql_pool_t attachsql_pool_t; enum attachsql_column_flags_t { @@ -220,7 +219,7 @@ enum attachsql_query_parameter_type_t typedef enum attachsql_query_parameter_type_t attachsql_query_parameter_type_t; -typedef void (attachsql_callback_fn)(attachsql_connect_t *con, attachsql_events_t events, void *context, attachsql_error_t *error); +typedef void (attachsql_callback_fn)(attachsql_connect_t *con, uint32_t connection_id, attachsql_events_t events, void *context, attachsql_error_t *error); #ifdef __cplusplus } diff --git a/libattachsql-1.0/error.h b/libattachsql2/error.h similarity index 100% rename from libattachsql-1.0/error.h rename to libattachsql2/error.h diff --git a/libattachsql2/include.am b/libattachsql2/include.am new file mode 100644 index 0000000..881cd60 --- /dev/null +++ b/libattachsql2/include.am @@ -0,0 +1,14 @@ +# vim:ft=automake +# included from Top Level Makefile.am +# All paths should be given relative to the root + +nobase_include_HEADERS+= libattachsql2/attachsql.h +nobase_include_HEADERS+= libattachsql2/connect.h +nobase_include_HEADERS+= libattachsql2/constants.h +nobase_include_HEADERS+= libattachsql2/error.h +nobase_include_HEADERS+= libattachsql2/pool.h +nobase_include_HEADERS+= libattachsql2/query.h +nobase_include_HEADERS+= libattachsql2/utility.h +nobase_include_HEADERS+= libattachsql2/statement.h +nobase_include_HEADERS+= libattachsql2/structs.h +nobase_include_HEADERS+= libattachsql2/visibility.h diff --git a/libattachsql-1.0/group.h b/libattachsql2/pool.h similarity index 70% rename from libattachsql-1.0/group.h rename to libattachsql2/pool.h index 054c671..8d33832 100644 --- a/libattachsql-1.0/group.h +++ b/libattachsql2/pool.h @@ -22,16 +22,16 @@ extern "C" { #endif ASQL_API -attachsql_group_t *attachsql_group_create(attachsql_error_t **error); +attachsql_pool_t *attachsql_pool_create(attachsql_callback_fn *function, void *context, attachsql_error_t **error); ASQL_API -void attachsql_group_destroy(attachsql_group_t *group); +void attachsql_pool_destroy(attachsql_pool_t *pool); ASQL_API -void attachsql_group_add_connection(attachsql_group_t *group, attachsql_connect_t *con, attachsql_error_t **error); +void attachsql_pool_add_connection(attachsql_pool_t *pool, attachsql_connect_t *con, attachsql_error_t **error); ASQL_API -void attachsql_group_run(attachsql_group_t *group); +void attachsql_pool_run(attachsql_pool_t *pool); #ifdef __cplusplus } diff --git a/libattachsql-1.0/query.h b/libattachsql2/query.h similarity index 100% rename from libattachsql-1.0/query.h rename to libattachsql2/query.h diff --git a/libattachsql-1.0/statement.h b/libattachsql2/statement.h similarity index 94% rename from libattachsql-1.0/statement.h rename to libattachsql2/statement.h index 541f5cc..efbd5a2 100644 --- a/libattachsql-1.0/statement.h +++ b/libattachsql2/statement.h @@ -48,9 +48,6 @@ bool attachsql_statement_set_bigint(attachsql_connect_t *con, uint16_t param, in ASQL_API bool attachsql_statement_set_unsigned_bigint(attachsql_connect_t *con, uint16_t param, uint64_t value, attachsql_error_t **error); -ASQL_API -bool attachsql_statement_set_float(attachsql_connect_t *con, uint16_t param, float value, attachsql_error_t **error); - ASQL_API bool attachsql_statement_set_double(attachsql_connect_t *con, uint16_t param, double value, attachsql_error_t **error); @@ -87,9 +84,6 @@ uint64_t attachsql_statement_get_bigint_unsigned(attachsql_connect_t *con, uint1 ASQL_API double attachsql_statement_get_double(attachsql_connect_t *con, uint16_t column, attachsql_error_t **error); -ASQL_API -float attachsql_statement_get_float(attachsql_connect_t *con, uint16_t column, attachsql_error_t **error); - ASQL_API char *attachsql_statement_get_char(attachsql_connect_t *con, uint16_t column, size_t *length, attachsql_error_t **error); diff --git a/libattachsql-1.0/structs.h b/libattachsql2/structs.h similarity index 100% rename from libattachsql-1.0/structs.h rename to libattachsql2/structs.h diff --git a/libattachsql-1.0/utility.h b/libattachsql2/utility.h similarity index 100% rename from libattachsql-1.0/utility.h rename to libattachsql2/utility.h diff --git a/libattachsql-1.0/visibility.h b/libattachsql2/visibility.h similarity index 100% rename from libattachsql-1.0/visibility.h rename to libattachsql2/visibility.h diff --git a/m4/ax_check_library.m4 b/m4/ax_check_library.m4 deleted file mode 100644 index dd27ff4..0000000 --- a/m4/ax_check_library.m4 +++ /dev/null @@ -1,95 +0,0 @@ -# =========================================================================== -# http://www.gnu.org/software/autoconf-archive/ax_check_library.html -# =========================================================================== -# -# SYNOPSIS -# -# AX_CHECK_LIBRARY(VARIABLE-PREFIX, HEADER-FILE, LIBRARY-FILE, -# [ACTION-IF-FOUND], [ACTION-IF-NOT_FOUND]) -# -# DESCRIPTION -# -# Provides a generic test for a given library, similar in concept to the -# PKG_CHECK_MODULES macro used by pkg-config. -# -# Most simplest libraries can be checked against simply through the -# presence of a header file and a library to link to. This macro allows to -# wrap around the test so that it doesn't have to be recreated each time. -# -# Rather than define --with-$LIBRARY arguments, it uses variables in the -# same way that PKG_CHECK_MODULES does. It doesn't, though, use the same -# names, since you shouldn't provide a value for LIBS or CFLAGS but rather -# for LDFLAGS and CPPFLAGS, to tell the linker and compiler where to find -# libraries and headers respectively. -# -# If the library is find, HAVE_PREFIX is defined, and in all cases -# PREFIX_LDFLAGS and PREFIX_CPPFLAGS are substituted. -# -# Example: -# -# AX_CHECK_LIBRARY([LIBEVENT], [event.h], [event], [], -# [AC_MSG_ERROR([Unable to find libevent])]) -# -# LICENSE -# -# Copyright (c) 2012 Brian Aker -# Copyright (c) 2010 Diego Elio Petteno` -# -# This program is free software: you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the -# Free Software Foundation, either version 3 of the License, or (at your -# option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General -# Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program. If not, see . -# -# As a special exception, the respective Autoconf Macro's copyright owner -# gives unlimited permission to copy, distribute and modify the configure -# scripts that are the output of Autoconf when processing the Macro. You -# need not follow the terms of the GNU General Public License when using -# or distributing such scripts, even though portions of the text of the -# Macro appear in them. The GNU General Public License (GPL) does govern -# all other use of the material that constitutes the Autoconf Macro. -# -# This special exception to the GPL applies to versions of the Autoconf -# Macro released by the Autoconf Archive. When you make and distribute a -# modified version of the Autoconf Macro, you may extend this special -# exception to the GPL to apply to your modified version as well. - -#serial 7 - -AC_DEFUN([AX_CHECK_LIBRARY], - [AC_ARG_VAR($1[_CPPFLAGS],[C preprocessor flags for ]$1[ headers]) - AC_ARG_VAR($1[_LDFLAGS],[linker flags for ]$1[ libraries]) - - AC_CACHE_VAL(AS_TR_SH([ax_cv_have_]$1), - [AX_SAVE_FLAGS - - AS_IF([test "x$]$1[_CPPFLAGS" != "x"], - [CPPFLAGS="$CPPFLAGS $]$1[_CPPFLAGS"]) - - AS_IF([test "x$]$1[_LDFLAGS" != "x"], - [LDFLAGS="$LDFLAGS $]$1[_LDFLAGS"]) - - AC_CHECK_HEADER($2, [ - AC_CHECK_LIB($3, [main], - [AS_TR_SH([ax_cv_have_]$1)=yes], - [AS_TR_SH([ax_cv_have_]$1)=no]) - ], [AS_TR_SH([ax_cv_have_]$1)=no]) - - AX_RESTORE_FLAGS - ]) - - AS_IF([test "$]AS_TR_SH([ax_cv_have_]$1)[" = "yes"], - [AC_DEFINE([HAVE_]$1, [1], [Define to 1 if ]$1[ is found]) - AC_SUBST($1[_CPPFLAGS]) - AC_SUBST($1[_LDFLAGS]) - AC_SUBST($1[_LIB],[-l]$3) - ifelse([$4], , :, [$4])], - [ifelse([$5], , :, [$5])]) - ]) diff --git a/m4/ax_check_openssl.m4 b/m4/ax_check_openssl.m4 deleted file mode 100644 index d53c444..0000000 --- a/m4/ax_check_openssl.m4 +++ /dev/null @@ -1,126 +0,0 @@ -# =========================================================================== -# http://www.gnu.org/software/autoconf-archive/ax_check_openssl.html -# =========================================================================== -# -# SYNOPSIS -# -# AX_CHECK_OPENSSL([action-if-found[, action-if-not-found]]) -# -# DESCRIPTION -# -# Look for OpenSSL in a number of default spots, or in a user-selected -# spot (via --with-openssl). Sets -# -# OPENSSL_INCLUDES to the include directives required -# OPENSSL_LIBS to the -l directives required -# OPENSSL_LDFLAGS to the -L or -R flags required -# -# and calls ACTION-IF-FOUND or ACTION-IF-NOT-FOUND appropriately -# -# This macro sets OPENSSL_INCLUDES such that source files should use the -# openssl/ directory in include directives: -# -# #include -# -# LICENSE -# -# Copyright (c) 2009,2010 Zmanda Inc. -# Copyright (c) 2009,2010 Dustin J. Mitchell -# -# Copying and distribution of this file, with or without modification, are -# permitted in any medium without royalty provided the copyright notice -# and this notice are preserved. This file is offered as-is, without any -# warranty. - -#serial 9 - -AU_ALIAS([CHECK_SSL], [AX_CHECK_OPENSSL]) -AC_DEFUN([AX_CHECK_OPENSSL], [ - found=false - AC_ARG_WITH([openssl], - [AS_HELP_STRING([--with-openssl=DIR], - [root of the OpenSSL directory])], - [ - case "$withval" in - "" | y | ye | yes | n | no) - AC_MSG_ERROR([Invalid --with-openssl value]) - ;; - *) ssldirs="$withval" - ;; - esac - ], [ - # if pkg-config is installed and openssl has installed a .pc file, - # then use that information and don't search ssldirs - AC_PATH_PROG([PKG_CONFIG], [pkg-config]) - if test x"$PKG_CONFIG" != x""; then - OPENSSL_LDFLAGS=`$PKG_CONFIG openssl --libs-only-L 2>/dev/null` - if test $? = 0; then - OPENSSL_LIBS=`$PKG_CONFIG openssl --libs-only-l 2>/dev/null` - OPENSSL_INCLUDES=`$PKG_CONFIG openssl --cflags-only-I 2>/dev/null` - found=true - fi - fi - - # no such luck; use some default ssldirs - if ! $found; then - ssldirs="/usr/local/ssl /usr/lib/ssl /usr/ssl /usr/pkg /usr/local /usr" - fi - ] - ) - - - # note that we #include , so the OpenSSL headers have to be in - # an 'openssl' subdirectory - - if ! $found; then - OPENSSL_INCLUDES= - for ssldir in $ssldirs; do - AC_MSG_CHECKING([for openssl/ssl.h in $ssldir]) - if test -f "$ssldir/include/openssl/ssl.h"; then - OPENSSL_INCLUDES="-I$ssldir/include" - OPENSSL_LDFLAGS="-L$ssldir/lib" - OPENSSL_LIBS="-lssl -lcrypto" - found=true - AC_MSG_RESULT([yes]) - break - else - AC_MSG_RESULT([no]) - fi - done - - # if the file wasn't found, well, go ahead and try the link anyway -- maybe - # it will just work! - fi - - # try the preprocessor and linker with our new flags, - # being careful not to pollute the global LIBS, LDFLAGS, and CPPFLAGS - - AC_MSG_CHECKING([whether compiling and linking against OpenSSL works]) - echo "Trying link with OPENSSL_LDFLAGS=$OPENSSL_LDFLAGS;" \ - "OPENSSL_LIBS=$OPENSSL_LIBS; OPENSSL_INCLUDES=$OPENSSL_INCLUDES" >&AS_MESSAGE_LOG_FD - - save_LIBS="$LIBS" - save_LDFLAGS="$LDFLAGS" - save_CPPFLAGS="$CPPFLAGS" - LDFLAGS="$LDFLAGS $OPENSSL_LDFLAGS" - LIBS="$OPENSSL_LIBS $LIBS" - CPPFLAGS="$OPENSSL_INCLUDES $CPPFLAGS" - AC_LINK_IFELSE( - [AC_LANG_PROGRAM([#include ], [SSL_new(NULL)])], - [ - AC_MSG_RESULT([yes]) - $1 - ], [ - OPENSSL_LIBS="" - AC_MSG_RESULT([no]) - $2 - ]) - - CPPFLAGS="$save_CPPFLAGS" - LDFLAGS="$save_LDFLAGS" - LIBS="$save_LIBS" - - AC_SUBST([OPENSSL_INCLUDES]) - AC_SUBST([OPENSSL_LIBS]) - AC_SUBST([OPENSSL_LDFLAGS]) -]) diff --git a/m4/ax_dlopen.m4 b/m4/ax_dlopen.m4 deleted file mode 100644 index 514c578..0000000 --- a/m4/ax_dlopen.m4 +++ /dev/null @@ -1,10 +0,0 @@ -#serial 2 - -AC_DEFUN([AX_DLOPEN], - [AS_IF([test "x$enable_shared" = xyes], - [AX_CHECK_LIBRARY([DL],[dlfcn.h],[dl], - [AC_DEFINE([HAVE_LIBDL],[1],[Have dlopen]) - AC_CHECK_LIB([dl],[dlopen],[AC_DEFINE([HAVE_DLOPEN],[1],[Have dlopen])]) - AC_CHECK_LIB([dl],[dladdr],[AC_DEFINE([HAVE_DLADDR],[1],[Have dladdr])])])]) - ]) - diff --git a/m4/ax_gcc_version.m4 b/m4/ax_gcc_version.m4 deleted file mode 100644 index 0d92474..0000000 --- a/m4/ax_gcc_version.m4 +++ /dev/null @@ -1,65 +0,0 @@ -# =========================================================================== -# http://www.gnu.org/software/autoconf-archive/ax_gcc_version.html -# =========================================================================== -# -# SYNOPSIS -# -# AX_GCC_VERSION -# -# DESCRIPTION -# -# This macro retrieves the gcc version and returns it in the GCC_VERSION -# variable if available, an empty string otherwise. -# -# LICENSE -# -# Copyright (c) 2009 Francesco Salvestrini -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the -# Free Software Foundation; either version 2 of the License, or (at your -# option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General -# Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program. If not, see . -# -# As a special exception, the respective Autoconf Macro's copyright owner -# gives unlimited permission to copy, distribute and modify the configure -# scripts that are the output of Autoconf when processing the Macro. You -# need not follow the terms of the GNU General Public License when using -# or distributing such scripts, even though portions of the text of the -# Macro appear in them. The GNU General Public License (GPL) does govern -# all other use of the material that constitutes the Autoconf Macro. -# -# This special exception to the GPL applies to versions of the Autoconf -# Macro released by the Autoconf Archive. When you make and distribute a -# modified version of the Autoconf Macro, you may extend this special -# exception to the GPL to apply to your modified version as well. - -#serial 8 - -AC_DEFUN([AX_GCC_VERSION], [ - GCC_VERSION="" - AX_GCC_OPTION([-dumpversion],[],[],[ - ax_gcc_version_option=yes - ],[ - ax_gcc_version_option=no - ]) - AS_IF([test "x$GCC" = "xyes"],[ - AS_IF([test "x$ax_gcc_version_option" != "xno"],[ - AC_CACHE_CHECK([gcc version],[ax_cv_gcc_version],[ - ax_cv_gcc_version="`$CC -dumpversion`" - AS_IF([test "x$ax_cv_gcc_version" = "x"],[ - ax_cv_gcc_version="" - ]) - ]) - GCC_VERSION=$ax_cv_gcc_version - ]) - ]) - AC_SUBST([GCC_VERSION]) -]) diff --git a/m4/ax_harden_compiler_flags.m4 b/m4/ax_harden_compiler_flags.m4 index c85a759..56204e4 100644 --- a/m4/ax_harden_compiler_flags.m4 +++ b/m4/ax_harden_compiler_flags.m4 @@ -51,7 +51,7 @@ # -Wdeclaration-after-statement is counter to C99 # _APPEND_COMPILE_FLAGS_ERROR([-pedantic]) -#serial 17 +#serial 19 AC_DEFUN([_WARNINGS_AS_ERRORS], [AC_CACHE_CHECK([if all warnings into errors],[ac_cv_warnings_as_errors], @@ -162,6 +162,7 @@ AC_DEFUN([_HARDEN_CC_COMPILER_FLAGS], _APPEND_COMPILE_FLAGS_ERROR([-Wunused-parameter]) _APPEND_COMPILE_FLAGS_ERROR([-Wunused-local-typedefs]) _APPEND_COMPILE_FLAGS_ERROR([-Wwrite-strings]) + _APPEND_COMPILE_FLAGS_ERROR([-Wno-deprecated-declarations]) _APPEND_COMPILE_FLAGS_ERROR([-fwrapv]) _APPEND_COMPILE_FLAGS_ERROR([-pipe]) AS_IF([test "x$MINGW" = xyes], @@ -266,6 +267,7 @@ AC_DEFUN([_HARDEN_CXX_COMPILER_FLAGS], _APPEND_COMPILE_FLAGS_ERROR([-Wunused-local-typedefs]) _APPEND_COMPILE_FLAGS_ERROR([-Wwrite-strings]) _APPEND_COMPILE_FLAGS_ERROR([-Wformat-security]) + _APPEND_COMPILE_FLAGS_ERROR([-Wno-deprecated-declarations]) _APPEND_COMPILE_FLAGS_ERROR([-fwrapv]) _APPEND_COMPILE_FLAGS_ERROR([-pipe]) AS_IF([test "x$MINGW" = xyes], @@ -276,7 +278,9 @@ AC_DEFUN([_HARDEN_CXX_COMPILER_FLAGS], _APPEND_COMPILE_FLAGS_ERROR([-Wlong-long]) # GCC 4.5 removed this. # _APPEND_COMPILE_FLAGS_ERROR([-Wunreachable-code]) - +# Disable c++11 long long warning for brew openssl on Mac + AS_IF([test "$ax_cv_c_compiler_vendor" = "clang"],[ + _APPEND_COMPILE_FLAGS_ERROR([-Wno-c++11-long-long])]) AS_IF([test "x$ax_enable_debug" = xno], [AS_IF([test "x$ac_cv_vcs_checkout" = xyes], [AS_IF([test "x${host_os}" != "xmingw"], diff --git a/m4/ax_mac_universal.m4 b/m4/ax_mac_universal.m4 new file mode 100644 index 0000000..9fcf598 --- /dev/null +++ b/m4/ax_mac_universal.m4 @@ -0,0 +1,62 @@ +# SYNOPSIS +# +# AX_UNIVERSAL_BINARY() +# +# DESCRIPTION +# +# --enable-universal-binary +# +# LICENSE +# +# Copyright 2014 Hewlett-Packard Development Company, L.P. +# All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +#serial 1 + +AC_DEFUN([AX_UNIVERSAL_BINARY], + [AC_ARG_ENABLE([universal-binary], + [AC_HELP_STRING([--enable-universal-binary=auto], + [Apple combined x86 & x86_64 binary support])],, + [enable_universal_binary=auto]) + have_universal_binary=no + if test x"enable_universal_binary" != x"no"; then + AC_CANONICAL_HOST + AC_MSG_CHECKING([for universal binary support]) + case $host in *-apple-darwin*) + save_CFLAGS="$CFLAGS" + save_CXXFLAGS="$CXXFLAGS" + save_LDFLAGS="$LDFLAGS" + CFLAGS="$CFLAGS -arch x86_64 -arch i386" + CXXFLAGS="$CXXFLAGS -arch x86_64 -arch i386" + LDFLAGS="$LDFLAGS -arch x86_64 -arch i386" + AC_LINK_IFELSE([AC_LANG_SOURCE([int main() {return 0;}])], + [have_universal_binary=yes]) + if test x"$have_universal_binary" = x"no"; then + CFLAGS="$save_CFLAGS" + CXXFLAGS="$save_CXXFLAGS" + LDFLAGS="$save_LDFLAGS" + fi + ;; + esac + AC_MSG_RESULT($have_universal_binary) + fi + case "$have_universal_binary:$enable_universal_binary" in + no:yes) AC_MSG_ERROR([no universal binary support on this host]) ;; + yse:*) AC_MSG_WARN([disabling dependency tracking]) + AM_CONDITIONAL([AMDEP],[false]) + AM_CONDITIONAL([am__fastdepCC],[false]) + AMDEPBACKSLASH= + ;; + esac]) diff --git a/m4/ax_printf_strerror.m4 b/m4/ax_printf_strerror.m4 deleted file mode 100644 index c4cf052..0000000 --- a/m4/ax_printf_strerror.m4 +++ /dev/null @@ -1,68 +0,0 @@ -# =========================================================================== -# https://github.com/BrianAker/ddm4/ -# =========================================================================== -# -# SYNOPSIS -# -# AX_PRINTF_STRERROR() -# -# DESCRIPTION -# -# Check to see if printf() has %s implemented (i.e. can handle strerror -# internally) -# -# LICENSE -# -# Copyright (C) 2013 Brian Aker All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# -# * The names of its contributors may not be used to endorse or -# promote products derived from this software without specific prior -# written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#serial 1 - -AC_DEFUN([AX_PRINTF_STRERROR], - [AC_PREREQ([2.63])dnl - AC_CACHE_CHECK([printf() has strerror option], - [ax_cv_have_printf_strerror], - [AC_LANG_PUSH([C++]) - AC_RUN_IFELSE([AC_LANG_PROGRAM([[#include - #include - #include - #include - #include - ]], - [[char buffer[1024]; errno=0; snprintf(buffer, sizeof(buffer), "%m"); if (strcmp("Success", buffer) !=0 ) return EXIT_FAILURE;]])], - [ax_cv_have_printf_strerror=yes], - [ax_cv_have_printf_strerror=no], - [ax_cv_have_printf_strerror=no]) - AC_LANG_POP]) - AC_MSG_CHECKING([checking for cxx_gcc_abi_demangle]) - AC_MSG_RESULT(["$ax_cv_have_printf_strerror"]) - AS_IF([test "x$ax_cv_have_printf_strerror" = xyes], - [AC_DEFINE([HAVE_PRINTF_STRERROR],[1],[define if printf supports directly print errno])]) - ]) diff --git a/m4/ax_pthread.m4 b/m4/ax_pthread.m4 deleted file mode 100644 index 1805579..0000000 --- a/m4/ax_pthread.m4 +++ /dev/null @@ -1,332 +0,0 @@ -# =========================================================================== -# http://www.gnu.org/software/autoconf-archive/ax_pthread.html -# =========================================================================== -# -# SYNOPSIS -# -# AX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]]) -# -# DESCRIPTION -# -# This macro figures out how to build C programs using POSIX threads. It -# sets the PTHREAD_LIBS output variable to the threads library and linker -# flags, and the PTHREAD_CFLAGS output variable to any special C compiler -# flags that are needed. (The user can also force certain compiler -# flags/libs to be tested by setting these environment variables.) -# -# Also sets PTHREAD_CC to any special C compiler that is needed for -# multi-threaded programs (defaults to the value of CC otherwise). (This -# is necessary on AIX to use the special cc_r compiler alias.) -# -# NOTE: You are assumed to not only compile your program with these flags, -# but also link it with them as well. e.g. you should link with -# $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS -# -# If you are only building threads programs, you may wish to use these -# variables in your default LIBS, CFLAGS, and CC: -# -# LIBS="$PTHREAD_LIBS $LIBS" -# CFLAGS="$CFLAGS $PTHREAD_CFLAGS" -# CC="$PTHREAD_CC" -# -# In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute constant -# has a nonstandard name, defines PTHREAD_CREATE_JOINABLE to that name -# (e.g. PTHREAD_CREATE_UNDETACHED on AIX). -# -# Also HAVE_PTHREAD_PRIO_INHERIT is defined if pthread is found and the -# PTHREAD_PRIO_INHERIT symbol is defined when compiling with -# PTHREAD_CFLAGS. -# -# ACTION-IF-FOUND is a list of shell commands to run if a threads library -# is found, and ACTION-IF-NOT-FOUND is a list of commands to run it if it -# is not found. If ACTION-IF-FOUND is not specified, the default action -# will define HAVE_PTHREAD. -# -# Please let the authors know if this macro fails on any platform, or if -# you have any other suggestions or comments. This macro was based on work -# by SGJ on autoconf scripts for FFTW (http://www.fftw.org/) (with help -# from M. Frigo), as well as ac_pthread and hb_pthread macros posted by -# Alejandro Forero Cuervo to the autoconf macro repository. We are also -# grateful for the helpful feedback of numerous users. -# -# Updated for Autoconf 2.68 by Daniel Richard G. -# -# LICENSE -# -# Copyright (c) 2008 Steven G. Johnson -# Copyright (c) 2011 Daniel Richard G. -# -# This program is free software: you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the -# Free Software Foundation, either version 3 of the License, or (at your -# option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General -# Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program. If not, see . -# -# As a special exception, the respective Autoconf Macro's copyright owner -# gives unlimited permission to copy, distribute and modify the configure -# scripts that are the output of Autoconf when processing the Macro. You -# need not follow the terms of the GNU General Public License when using -# or distributing such scripts, even though portions of the text of the -# Macro appear in them. The GNU General Public License (GPL) does govern -# all other use of the material that constitutes the Autoconf Macro. -# -# This special exception to the GPL applies to versions of the Autoconf -# Macro released by the Autoconf Archive. When you make and distribute a -# modified version of the Autoconf Macro, you may extend this special -# exception to the GPL to apply to your modified version as well. - -#serial 23 - -AU_ALIAS([ACX_PTHREAD], [AX_PTHREAD]) -AC_DEFUN([AX_PTHREAD], [ -AC_REQUIRE([AC_CANONICAL_HOST]) -AC_LANG_PUSH([C]) -ax_pthread_ok=no - -# We used to check for pthread.h first, but this fails if pthread.h -# requires special compiler flags (e.g. on True64 or Sequent). -# It gets checked for in the link test anyway. - -# First of all, check if the user has set any of the PTHREAD_LIBS, -# etcetera environment variables, and if threads linking works using -# them: -if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then - save_CFLAGS="$CFLAGS" - CFLAGS="$CFLAGS $PTHREAD_CFLAGS" - save_LIBS="$LIBS" - LIBS="$PTHREAD_LIBS $LIBS" - AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS]) - AC_TRY_LINK_FUNC([pthread_join], [ax_pthread_ok=yes]) - AC_MSG_RESULT([$ax_pthread_ok]) - if test x"$ax_pthread_ok" = xno; then - PTHREAD_LIBS="" - PTHREAD_CFLAGS="" - fi - LIBS="$save_LIBS" - CFLAGS="$save_CFLAGS" -fi - -# We must check for the threads library under a number of different -# names; the ordering is very important because some systems -# (e.g. DEC) have both -lpthread and -lpthreads, where one of the -# libraries is broken (non-POSIX). - -# Create a list of thread flags to try. Items starting with a "-" are -# C compiler flags, and other items are library names, except for "none" -# which indicates that we try without any flags at all, and "pthread-config" -# which is a program returning the flags for the Pth emulation library. - -ax_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config" - -# The ordering *is* (sometimes) important. Some notes on the -# individual items follow: - -# pthreads: AIX (must check this before -lpthread) -# none: in case threads are in libc; should be tried before -Kthread and -# other compiler flags to prevent continual compiler warnings -# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h) -# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) -# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread) -# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads) -# -pthreads: Solaris/gcc -# -mthreads: Mingw32/gcc, Lynx/gcc -# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it -# doesn't hurt to check since this sometimes defines pthreads too; -# also defines -D_REENTRANT) -# ... -mt is also the pthreads flag for HP/aCC -# pthread: Linux, etcetera -# --thread-safe: KAI C++ -# pthread-config: use pthread-config program (for GNU Pth library) - -case ${host_os} in - solaris*) - - # On Solaris (at least, for some versions), libc contains stubbed - # (non-functional) versions of the pthreads routines, so link-based - # tests will erroneously succeed. (We need to link with -pthreads/-mt/ - # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather - # a function called by this macro, so we could check for that, but - # who knows whether they'll stub that too in a future libc.) So, - # we'll just look for -pthreads and -lpthread first: - - ax_pthread_flags="-pthreads pthread -mt -pthread $ax_pthread_flags" - ;; - - darwin*) - ax_pthread_flags="none -pthread $ax_pthread_flags" - ;; -esac - -# Clang doesn't consider unrecognized options an error unless we specify -# -Werror. We throw in some extra Clang-specific options to ensure that -# this doesn't happen for GCC, which also accepts -Werror. - -AC_MSG_CHECKING([if compiler needs -Werror to reject unknown flags]) -save_CFLAGS="$CFLAGS" -ax_pthread_extra_flags="-Werror" -CFLAGS="$CFLAGS $ax_pthread_extra_flags -Wunknown-warning-option -Wsizeof-array-argument" -AC_COMPILE_IFELSE([AC_LANG_PROGRAM([int foo(void);],[foo()])], - [AC_MSG_RESULT([yes])], - [ax_pthread_extra_flags= - AC_MSG_RESULT([no])]) -CFLAGS="$save_CFLAGS" - -if test x"$ax_pthread_ok" = xno; then -for flag in $ax_pthread_flags; do - - case $flag in - none) - AC_MSG_CHECKING([whether pthreads work without any flags]) - ;; - - -*) - AC_MSG_CHECKING([whether pthreads work with $flag]) - PTHREAD_CFLAGS="$flag" - ;; - - pthread-config) - AC_CHECK_PROG([ax_pthread_config], [pthread-config], [yes], [no]) - if test x"$ax_pthread_config" = xno; then continue; fi - PTHREAD_CFLAGS="`pthread-config --cflags`" - PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`" - ;; - - *) - AC_MSG_CHECKING([for the pthreads library -l$flag]) - PTHREAD_LIBS="-l$flag" - ;; - esac - - save_LIBS="$LIBS" - save_CFLAGS="$CFLAGS" - LIBS="$PTHREAD_LIBS $LIBS" - CFLAGS="$CFLAGS $PTHREAD_CFLAGS $ax_pthread_extra_flags" - - # Check for various functions. We must include pthread.h, - # since some functions may be macros. (On the Sequent, we - # need a special flag -Kthread to make this header compile.) - # We check for pthread_join because it is in -lpthread on IRIX - # while pthread_create is in libc. We check for pthread_attr_init - # due to DEC craziness with -lpthreads. We check for - # pthread_cleanup_push because it is one of the few pthread - # functions on Solaris that doesn't have a non-functional libc stub. - # We try pthread_create on general principles. - AC_LINK_IFELSE([AC_LANG_PROGRAM([#include - static void routine(void *a) { a = 0; } - static void *start_routine(void *a) { return a; }], - [pthread_t th; pthread_attr_t attr; - pthread_create(&th, 0, start_routine, 0); - pthread_join(th, 0); - pthread_attr_init(&attr); - pthread_cleanup_push(routine, 0); - pthread_cleanup_pop(0) /* ; */])], - [ax_pthread_ok=yes], - []) - - LIBS="$save_LIBS" - CFLAGS="$save_CFLAGS" - - AC_MSG_RESULT([$ax_pthread_ok]) - if test "x$ax_pthread_ok" = xyes; then - break; - fi - - PTHREAD_LIBS="" - PTHREAD_CFLAGS="" -done -fi - -# Various other checks: -if test "x$ax_pthread_ok" = xyes; then - save_LIBS="$LIBS" - LIBS="$PTHREAD_LIBS $LIBS" - save_CFLAGS="$CFLAGS" - CFLAGS="$CFLAGS $PTHREAD_CFLAGS" - - # Detect AIX lossage: JOINABLE attribute is called UNDETACHED. - AC_MSG_CHECKING([for joinable pthread attribute]) - attr_name=unknown - for attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do - AC_LINK_IFELSE([AC_LANG_PROGRAM([#include ], - [int attr = $attr; return attr /* ; */])], - [attr_name=$attr; break], - []) - done - AC_MSG_RESULT([$attr_name]) - if test "$attr_name" != PTHREAD_CREATE_JOINABLE; then - AC_DEFINE_UNQUOTED([PTHREAD_CREATE_JOINABLE], [$attr_name], - [Define to necessary symbol if this constant - uses a non-standard name on your system.]) - fi - - AC_MSG_CHECKING([if more special flags are required for pthreads]) - flag=no - case ${host_os} in - aix* | freebsd* | darwin*) flag="-D_THREAD_SAFE";; - osf* | hpux*) flag="-D_REENTRANT";; - solaris*) - if test "$GCC" = "yes"; then - flag="-D_REENTRANT" - else - # TODO: What about Clang on Solaris? - flag="-mt -D_REENTRANT" - fi - ;; - esac - AC_MSG_RESULT([$flag]) - if test "x$flag" != xno; then - PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS" - fi - - AC_CACHE_CHECK([for PTHREAD_PRIO_INHERIT], - [ax_cv_PTHREAD_PRIO_INHERIT], [ - AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]], - [[int i = PTHREAD_PRIO_INHERIT;]])], - [ax_cv_PTHREAD_PRIO_INHERIT=yes], - [ax_cv_PTHREAD_PRIO_INHERIT=no]) - ]) - AS_IF([test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes"], - [AC_DEFINE([HAVE_PTHREAD_PRIO_INHERIT], [1], [Have PTHREAD_PRIO_INHERIT.])]) - - LIBS="$save_LIBS" - CFLAGS="$save_CFLAGS" - - # More AIX lossage: compile with *_r variant - if test "x$GCC" != xyes; then - case $host_os in - aix*) - AS_CASE(["x/$CC"], - [x*/c89|x*/c89_128|x*/c99|x*/c99_128|x*/cc|x*/cc128|x*/xlc|x*/xlc_v6|x*/xlc128|x*/xlc128_v6], - [#handle absolute path differently from PATH based program lookup - AS_CASE(["x$CC"], - [x/*], - [AS_IF([AS_EXECUTABLE_P([${CC}_r])],[PTHREAD_CC="${CC}_r"])], - [AC_CHECK_PROGS([PTHREAD_CC],[${CC}_r],[$CC])])]) - ;; - esac - fi -fi - -test -n "$PTHREAD_CC" || PTHREAD_CC="$CC" - -AC_SUBST([PTHREAD_LIBS]) -AC_SUBST([PTHREAD_CFLAGS]) -AC_SUBST([PTHREAD_CC]) - -# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: -if test x"$ax_pthread_ok" = xyes; then - ifelse([$1],,[AC_DEFINE([HAVE_PTHREAD],[1],[Define if you have POSIX threads libraries and header files.])],[$1]) - : -else - ax_pthread_ok=no - $2 -fi -AC_LANG_POP -])dnl AX_PTHREAD diff --git a/m4/ax_pthread_timedjoin_np.m4 b/m4/ax_pthread_timedjoin_np.m4 deleted file mode 100644 index 39de8fa..0000000 --- a/m4/ax_pthread_timedjoin_np.m4 +++ /dev/null @@ -1,50 +0,0 @@ -# =========================================================================== -# http:// -# =========================================================================== -# -# SYNOPSIS -# -# AX_PTHREAD_TIMEDJOIN_NP() -# -# DESCRIPTION -# -# Check for pthread_timedjoin_np support. -# -# LICENSE -# -# Copyright (c) 2012 Brian Aker -# -# Copying and distribution of this file, with or without modification, are -# permitted in any medium without royalty provided the copyright notice -# and this notice are preserved. This file is offered as-is, without any -# warranty. - -#serial 6 - -AC_DEFUN([AX_PTHREAD_TIMEDJOIN_NP], - [AC_PREREQ([2.63])dnl - AC_REQUIRE([AX_PTHREAD]) - AC_CACHE_CHECK([check for pthread_timedjoin_np], [ax_cv_pthread_timedjoin_np], - [AX_SAVE_FLAGS - CFLAGS="$PTHREAD_CFLAGS" - LIBS="$PTHREAD_LIBS" - AC_LANG_PUSH([C]) - AC_LINK_IFELSE( - [AC_LANG_PROGRAM( - [ -#include -#include - ],[ - pthread_t thread; - pthread_timedjoin_np(thread, NULL, NULL); - ])], - [ax_cv_pthread_timedjoin_np=yes],[]) - - AC_LANG_POP - AX_RESTORE_FLAGS - ]) - - AS_IF([test "$ax_cv_pthread_timedjoin_np" = yes], - [AC_DEFINE(HAVE_PTHREAD_TIMEDJOIN_NP,[1],[Define if pthread_timedjoin_np is present in pthread.h.])], - [AC_DEFINE(HAVE_PTHREAD_TIMEDJOIN_NP,[0],[Define if pthread_timedjoin_np is present in pthread.h.])]) - ]) diff --git a/m4/config_extra.m4 b/m4/config_extra.m4 index a862032..6ac9773 100644 --- a/m4/config_extra.m4 +++ b/m4/config_extra.m4 @@ -50,6 +50,7 @@ AH_TOP([ /* Define to make inttypes.h work on some platforms */ #define __STDC_FORMAT_MACROS 1 +#define __STDC_LIMIT_MACROS 1 /* _SYS_FEATURE_TESTS_H is Solaris, _FEATURES_H is GCC */ #if defined( _SYS_FEATURE_TESTS_H) || defined(_FEATURES_H) diff --git a/m4/have_cinttypes.m4 b/m4/have_cinttypes.m4 deleted file mode 100644 index fbd8c0d..0000000 --- a/m4/have_cinttypes.m4 +++ /dev/null @@ -1,97 +0,0 @@ -# =========================================================================== -# http://tangent.org/ -# =========================================================================== -# -# SYNOPSIS -# -# AX_CXX_CINTTYPES() -# -# DESCRIPTION -# -# Example: -# -# LICENSE -# -# Copyright (c) 2012 Brian Aker` -# -# This program is free software: you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the -# Free Software Foundation, either version 3 of the License, or (at your -# option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General -# Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program. If not, see . -# -# As a special exception, the respective Autoconf Macro's copyright owner -# gives unlimited permission to copy, distribute and modify the configure -# scripts that are the output of Autoconf when processing the Macro. You -# need not follow the terms of the GNU General Public License when using -# or distributing such scripts, even though portions of the text of the -# Macro appear in them. The GNU General Public License (GPL) does govern -# all other use of the material that constitutes the Autoconf Macro. -# -# This special exception to the GPL applies to versions of the Autoconf -# Macro released by the Autoconf Archive. When you make and distribute a -# modified version of the Autoconf Macro, you may extend this special -# exception to the GPL to apply to your modified version as well. - -#serial 3 - -AC_DEFUN([AX_CXX_CINTTYPES], [ - AC_REQUIRE([AC_PROG_CXX]) - AC_REQUIRE([AC_PROG_CXXCPP]) - AC_REQUIRE([AX_CXX_CSTDINT]) - - AC_CACHE_CHECK([for location of cinttypes], [ac_cv_cxx_cinttypes], [ - AX_SAVE_FLAGS - CXXFLAGS="${CXX_STANDARD} ${CXXFLAGS}" - AC_LANG_PUSH([C++]) - - AC_COMPILE_IFELSE([ - AC_LANG_PROGRAM([#include ], [ - uint32_t foo= UINT32_C(1); - ])], - [ac_cxx_cinttypes_cinttypes=""]) - -# Look for tr1/cinttypes - AS_IF([test -z "$ac_cxx_cinttypes_cinttypes"],[ - AC_COMPILE_IFELSE([ - AC_LANG_PROGRAM([#include ], [ - uint32_t foo= UINT32_C(1); - ])], - [ac_cxx_cinttypes_tr1_cinttypes=""]) - -# Look for boost/cinttypes.hpp - AS_IF([test -z "$ac_cxx_cinttypes_tr1_cinttypes"],[ - AC_COMPILE_IFELSE([ - AC_LANG_PROGRAM([#include ], [ - uint32_t foo= UINT32_C(1); - ])], - [ac_cxx_cinttypes_boost_cinttypes_hpp=""]) - ]) - ]) - - AC_LANG_POP - AX_RESTORE_FLAGS - - AS_IF([test -n "$ac_cxx_cinttypes_cinttypes"], [ac_cv_cxx_cinttypes=$ac_cxx_cinttypes_cinttypes], - [test -n "$ac_cxx_cinttypes_tr1_cinttypes"], [ac_cv_cxx_cinttypes=$ac_cxx_cinttypes_tr1_cinttypes], - [test -n "$ac_cxx_cinttypes_boost_cinttypes_hpp"], [ac_cv_cxx_cinttypes=$ac_cxx_cinttypes_boost_cinttypes_hpp]) - ]) - - AS_IF([ test -n "$ac_cv_cxx_cinttypes"], [ - AC_MSG_RESULT([$ac_cv_cxx_cinttypes]) - ],[ - ac_cv_cxx_cinttypes="" - AC_MSG_WARN([Could not find a cinttypes header.]) - AC_MSG_RESULT([$ac_cv_cxx_cinttypes]) - ]) - - AC_DEFINE([__STDC_LIMIT_MACROS],[1],[Use STDC Limit Macros in C++]) - AC_DEFINE_UNQUOTED([CINTTYPES_H],[$ac_cv_cxx_cinttypes],[the location of ]) - ]) diff --git a/m4/have_cstdint.m4 b/m4/have_cstdint.m4 deleted file mode 100644 index cdd63c7..0000000 --- a/m4/have_cstdint.m4 +++ /dev/null @@ -1,89 +0,0 @@ -# =========================================================================== -# http://tangent.org/ -# =========================================================================== -# -# SYNOPSIS -# -# AX_CXX_CSTDINT() -# -# DESCRIPTION -# -# Example: -# -# LICENSE -# -# Copyright (c) 2012 Brian Aker` -# -# This program is free software: you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the -# Free Software Foundation, either version 3 of the License, or (at your -# option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General -# Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program. If not, see . -# -# As a special exception, the respective Autoconf Macro's copyright owner -# gives unlimited permission to copy, distribute and modify the configure -# scripts that are the output of Autoconf when processing the Macro. You -# need not follow the terms of the GNU General Public License when using -# or distributing such scripts, even though portions of the text of the -# Macro appear in them. The GNU General Public License (GPL) does govern -# all other use of the material that constitutes the Autoconf Macro. -# -# This special exception to the GPL applies to versions of the Autoconf -# Macro released by the Autoconf Archive. When you make and distribute a -# modified version of the Autoconf Macro, you may extend this special -# exception to the GPL to apply to your modified version as well. - -#serial 3 - - -AC_DEFUN([AX_CXX_CSTDINT], [ - AC_REQUIRE([AC_PROG_CXX]) - AC_REQUIRE([AC_PROG_CXXCPP]) - - AC_CACHE_CHECK([for location of cstdint], [ac_cv_cxx_cstdint], [ - AC_LANG_PUSH([C++]) - AX_SAVE_FLAGS - CXXFLAGS="${CXX_STANDARD} ${CXXFLAGS}" - - AC_COMPILE_IFELSE([ - AC_LANG_PROGRAM([#include ], [ - uint32_t t - ])], - [ac_cxx_cstdint_cstdint=""]) - - AS_IF([test -z "$ac_cxx_cstdint_cstdint"],[ - AC_COMPILE_IFELSE([ - AC_LANG_PROGRAM([#include ], [ uint32_t t ])], - [ac_cxx_cstdint_tr1_cstdint=""]) - - AS_IF([test -z "$ac_cxx_cstdint_tr1_cstdint"],[ - AC_COMPILE_IFELSE([ - AC_LANG_PROGRAM([#include ], [ uint32_t t ])], - [ac_cxx_cstdint_boost_cstdint_hpp=""]) - ]) - ]) - - AC_LANG_POP - AX_RESTORE_FLAGS - - AS_IF([test -n "$ac_cxx_cstdint_cstdint"], [ac_cv_cxx_cstdint=$ac_cxx_cstdint_cstdint], - [test -n "$ac_cxx_cstdint_tr1_cstdint"], [ac_cv_cxx_cstdint=$ac_cxx_cstdint_tr1_cstdint], - [test -n "$ac_cxx_cstdint_boost_cstdint_hpp"], [ac_cv_cxx_cstdint=$ac_cxx_cstdint_boost_cstdint_hpp]) - ]) - - AS_IF([test -n "$ac_cv_cxx_cstdint"], [AC_MSG_RESULT([$ac_cv_cxx_cstdint])], [ - ac_cv_cxx_cstdint="" - AC_MSG_WARN([Could not find a cstdint header.]) - AC_MSG_RESULT([$ac_cv_cxx_cstdint]) - ]) - -AC_DEFINE_UNQUOTED([CSTDINT_H],[$ac_cv_cxx_cstdint], [the location of ]) - - ]) diff --git a/playbooks/clang.yaml b/playbooks/clang.yaml new file mode 100644 index 0000000..0f732a9 --- /dev/null +++ b/playbooks/clang.yaml @@ -0,0 +1,17 @@ +- hosts: xenial + name: CLang Build + tasks: + - name: Build with Clang + shell: + cmd: | + autoreconf -fi + ./configure --enable-debug + make + make check + args: + chdir: ~/src/github.com/libattachsql/libattachsql/ + executable: /bin/bash + environment: + CC: clang + CXX: clang++ + diff --git a/playbooks/distcheck.yaml b/playbooks/distcheck.yaml new file mode 100644 index 0000000..de533d3 --- /dev/null +++ b/playbooks/distcheck.yaml @@ -0,0 +1,12 @@ +- hosts: xenial + name: GCC Dist Check + tasks: + - name: Build with dist check + shell: + cmd: | + autoreconf -fi + ./configure --enable-debug + make distcheck + args: + chdir: ~/src/github.com/libattachsql/libattachsql/ + executable: /bin/bash diff --git a/playbooks/docs.yaml b/playbooks/docs.yaml new file mode 100644 index 0000000..e390172 --- /dev/null +++ b/playbooks/docs.yaml @@ -0,0 +1,12 @@ +- hosts: xenial + name: Build docs + tasks: + - name: Build with Sphinx + shell: + cmd: | + autoreconf -fi + ./configure + make html + args: + chdir: ~/src/github.com/libattachsql/libattachsql/ + executable: /bin/bash diff --git a/playbooks/scanbuild.yaml b/playbooks/scanbuild.yaml new file mode 100644 index 0000000..a74c734 --- /dev/null +++ b/playbooks/scanbuild.yaml @@ -0,0 +1,18 @@ +- hosts: xenial + name: CLang Scan Build + tasks: + - name: Build and run Clang ScanBuild + shell: + cmd: | + autoreconf -fi + ./configure --enable-debug + make + make clean + scan-build --use-cc=clang --use-c++=clang --status-bugs make + args: + chdir: ~/src/github.com/libattachsql/libattachsql/ + executable: /bin/bash + environment: + CC: clang + CXX: clang++ + diff --git a/playbooks/valgrind.yaml b/playbooks/valgrind.yaml new file mode 100644 index 0000000..a0ec438 --- /dev/null +++ b/playbooks/valgrind.yaml @@ -0,0 +1,13 @@ +- hosts: xenial + name: CLang Scan Build + tasks: + - name: Build and run Clang ScanBuild + shell: + cmd: | + autoreconf -fi + ./configure --enable-debug + TESTS_ENVIRONMENT="./libtool --mode=execute valgrind --error-exitcode=1 --leak-check=yes --track-fds=no --malloc-fill=A5 --free-fill=DE --suppressions=valgrind.supp" make check 2>/dev/null + args: + chdir: ~/src/github.com/libattachsql/libattachsql/ + executable: /bin/bash + diff --git a/rpm/include.mk b/rpm/include.mk index 0c42481..d47ae22 100644 --- a/rpm/include.mk +++ b/rpm/include.mk @@ -26,6 +26,7 @@ $(DIST_ARCHIVES): $(DISTFILES) $(MAKE) $(AM_MAKEFLAGS) dist-gzip $(RPM_SOURCE): $(DIST_ARCHIVES) $(RPM_BUILDDIR) + @mkdir -p $(RPM_SOURCEDIR) @cp $< $@ $(RPM_BUILD_TARGET): rpm/@PACKAGE@.spec $(RPM_SOURCE) diff --git a/rpm/libattachsql.spec.in b/rpm/libattachsql.spec.in index e27b1ab..865c210 100644 --- a/rpm/libattachsql.spec.in +++ b/rpm/libattachsql.spec.in @@ -4,8 +4,13 @@ Version: @VERSION@ Release: 1 License: Apache2 Group: System Environment/Libraries -BuildRequires: libuv-devel zlib-devel openssl-devel -Requires libuv zlib openssl +BuildRequires: libuv-devel >= 1.0 +BuildRequires: zlib-devel +BuildRequires: openssl-devel +BuildRequires: redhat-rpm-config +Requires: libuv >= 1.0 +Requires: zlib +Requires: openssl URL: https://libattachsql.org/ Packager: Andrew Hutchings @@ -60,7 +65,8 @@ mkdir -p $RPM_BUILD_ROOT/ %files devel %defattr(-,root,root,-) %doc LICENSE README.rst -%{_includedir}/libattachsql-1.0/*.h +%{_includedir}/libattachsql2/*.h +%{_libdir}/pkgconfig/libattachsql.pc %changelog * Tue Aug 05 2014 Andrew Hutchings diff --git a/src/ascore/ascore.h b/src/ascore.h similarity index 70% rename from src/ascore/ascore.h rename to src/ascore.h index 1f77a63..ac4c8bf 100644 --- a/src/ascore/ascore.h +++ b/src/ascore.h @@ -19,14 +19,16 @@ #include +#include + /* These two need to go first, in this order */ -#include "src/ascore/constants.h" -#include "src/ascore/structs.h" -#include "src/ascore/return.h" -#include "src/ascore/pack_macros.h" -#include "src/ascore/pack.h" -#include "src/ascore/net.h" -#include "src/ascore/connect.h" -#include "src/ascore/command.h" -#include "src/ascore/buffer.h" -#include "src/ascore/statement.h" +#include "constants.h" +#include "structs.h" +#include "return.h" +#include "pack_macros.h" +#include "pack.h" +#include "net.h" +#include "connect.h" +#include "command.h" +#include "buffer.h" +#include "statement.h" diff --git a/src/ascore/command.cc b/src/ascore/command.cc deleted file mode 100644 index f2ba2f8..0000000 --- a/src/ascore/command.cc +++ /dev/null @@ -1,213 +0,0 @@ -/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab: - * Copyright 2014 Hewlett-Packard Development Company, L.P. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. You may obtain - * a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - * - */ - -#include "command.h" -#include "net.h" - -#ifdef HAVE_ZLIB -ascore_command_status_t ascore_command_send_compressed(ascon_st *con, ascore_command_t command, char *data, size_t length) -{ - ascore_send_compressed_packet(con, data, length, command); - if (con->status == ASCORE_CON_STATUS_IDLE) - { - if (command == ASCORE_COMMAND_STMT_PREPARE) - { - con->next_packet_type= ASCORE_PACKET_TYPE_PREPARE_RESPONSE; - } - else - { - con->next_packet_type= ASCORE_PACKET_TYPE_RESPONSE; - } - uv_read_start(con->uv_objects.stream, on_alloc, ascore_read_data_cb); - con->command_status= ASCORE_COMMAND_STATUS_SEND; - con->status= ASCORE_CON_STATUS_BUSY; - if (con->options.semi_block) - { - uv_run(con->uv_objects.loop, UV_RUN_ONCE); - } - else - { - uv_run(con->uv_objects.loop, UV_RUN_NOWAIT); - } - return ASCORE_COMMAND_STATUS_SEND; - } - return con->command_status; -} -#endif - -ascore_command_status_t ascore_command_send(ascon_st *con, ascore_command_t command, char *data, size_t length) -{ - uv_buf_t send_buffer[3]; - int ret; - - if (con->status != ASCORE_CON_STATUS_IDLE) - { - /* Server not ready */ - return con->command_status; - } - - /* Reset a bunch of internals */ - con->result.current_column= 0; - con->affected_rows= 0; - con->insert_id= 0; - con->server_status= 0; - con->warning_count= 0; - con->server_errno= 0; - - asdebug("Sending command 0x%02X to server", command); - con->local_errcode= ASRET_OK; - con->errmsg[0]= '\0'; - - ascore_pack_int3(con->packet_header, length + 1 + con->write_buffer_extra); - con->packet_number= 0; - con->packet_header[3] = con->packet_number; - -#ifdef HAVE_ZLIB - if (con->client_capabilities & ASCORE_CAPABILITY_COMPRESS) - { - return ascore_command_send_compressed(con, command, data, length); - } -#endif - - con->write_buffer[0]= command; - send_buffer[0].base= con->packet_header; - send_buffer[0].len= 4; - send_buffer[1].base= con->write_buffer; - send_buffer[1].len= 1 + con->write_buffer_extra; - con->write_buffer_extra= 0; - if (length > 0) - { - send_buffer[2].base= data; - send_buffer[2].len= length; - asdebug("Sending %zd bytes with command to server", length); - asdebug_hex(data, length); -#ifdef HAVE_OPENSSL - if (con->ssl.handshake_done) - { - ret= ascore_ssl_buffer_write(con, send_buffer, 3); - } - else -#endif - { - uv_write_t *req= new (std::nothrow) uv_write_t; - ret= uv_write(req, con->uv_objects.stream, send_buffer, 3, on_write); - } - } - else - { - asdebug("Sending command with no data"); -#ifdef HAVE_OPENSSL - if (con->ssl.handshake_done) - { - ret= ascore_ssl_buffer_write(con, send_buffer, 2); - } - else -#endif - { - uv_write_t *req= new (std::nothrow) uv_write_t; - ret= uv_write(req, con->uv_objects.stream, send_buffer, 2, on_write); - } - } - if (ret != 0) - { - con->local_errcode= ASRET_NET_WRITE_ERROR; - asdebug("Write fail: %s", uv_err_name(uv_last_error(con->uv_objects.loop))); - con->command_status= ASCORE_COMMAND_STATUS_SEND_FAILED; - con->next_packet_type= ASCORE_PACKET_TYPE_NONE; - con->local_errcode= ASRET_NET_WRITE_ERROR; - snprintf(con->errmsg, ASCORE_ERROR_BUFFER_SIZE, "Query send failed: %s", uv_err_name(uv_last_error(con->uv_objects.loop))); - return con->command_status; - } - - if (command == ASCORE_COMMAND_STMT_PREPARE) - { - con->next_packet_type= ASCORE_PACKET_TYPE_PREPARE_RESPONSE; - } - else if ((command == ASCORE_COMMAND_STMT_RESET) || (command == ASCORE_COMMAND_STMT_CLOSE)) - { - con->next_packet_type= ASCORE_PACKET_TYPE_NONE; - } - else - { - con->next_packet_type= ASCORE_PACKET_TYPE_RESPONSE; - } - if ((command != ASCORE_COMMAND_STMT_RESET) && (command != ASCORE_COMMAND_STMT_CLOSE)) - { - uv_read_start(con->uv_objects.stream, on_alloc, ascore_read_data_cb); - } - con->command_status= ASCORE_COMMAND_STATUS_SEND; - con->status= ASCORE_CON_STATUS_BUSY; - if (con->options.semi_block) - { - uv_run(con->uv_objects.loop, UV_RUN_ONCE); - } - else - { - uv_run(con->uv_objects.loop, UV_RUN_NOWAIT); - } - return ASCORE_COMMAND_STATUS_SEND; -} - -ascore_command_status_t ascore_get_next_row(ascon_st *con) -{ - ascore_buffer_packet_read_end(con->read_buffer); - con->next_packet_type= ASCORE_PACKET_TYPE_ROW; - con->command_status= ASCORE_COMMAND_STATUS_READ_ROW; - ascore_con_process_packets(con); - return con->command_status; -} - -bool ascore_command_next_result(ascon_st *con) -{ - if (con == NULL) - { - return false; - } - if (con->server_status & ASCORE_SERVER_STATUS_MORE_RESULTS) - { - /* Reset a bunch of internals */ - con->result.current_column= 0; - con->affected_rows= 0; - con->insert_id= 0; - con->server_status= 0; - con->warning_count= 0; - con->server_errno= 0; - con->next_packet_type= ASCORE_PACKET_TYPE_RESPONSE; - uv_read_start(con->uv_objects.stream, on_alloc, ascore_read_data_cb); - con->command_status= ASCORE_COMMAND_STATUS_READ_RESPONSE; - con->status= ASCORE_CON_STATUS_BUSY; - if (con->options.semi_block) - { - uv_run(con->uv_objects.loop, UV_RUN_ONCE); - } - else - { - uv_run(con->uv_objects.loop, UV_RUN_NOWAIT); - } - return true; - } - return false; -} - -void ascore_command_free(ascon_st *con) -{ - if (con->result.columns != NULL) - { - delete[] con->result.columns; - } - con->result.columns= NULL; -} diff --git a/src/ascore/connect.cc b/src/ascore/connect.cc deleted file mode 100644 index cafd550..0000000 --- a/src/ascore/connect.cc +++ /dev/null @@ -1,655 +0,0 @@ -/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab: - * Copyright 2014 Hewlett-Packard Development Company, L.P. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. You may obtain - * a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - * - */ - -#include "config.h" -#include "common.h" -#include "connect.h" -#include "sha1.h" -#include "net.h" -#include -#include -#ifdef HAVE_OPENSSL -# include -#endif - -ascon_st *ascore_con_create(const char *host, in_port_t port, const char *user, const char *pass, const char *schema) -{ - ascon_st *con; - - con = new (std::nothrow) ascon_st; - if (con == NULL) - { - return NULL; - } - - con->host= host; - con->port= port; - if ((user == NULL) or (strlen(user) > ASCORE_MAX_USER_SIZE)) - { - con->local_errcode= ASRET_USER_TOO_LONG; - con->status= ASCORE_CON_STATUS_PARAMETER_ERROR; - return con; - } - con->user= user; - // We don't really care how long pass is since we itterate though it during - // SHA1 passes. Needs to be nul terminated. NULL is also acceptable. - con->pass= pass; - if ((schema == NULL) or (strlen(schema) > ASCORE_MAX_SCHEMA_SIZE)) - { - con->local_errcode= ASRET_SCHEMA_TOO_LONG; - con->status= ASCORE_CON_STATUS_PARAMETER_ERROR; - return con; - } - con->schema= schema; - - return con; -} - -void ascore_con_destroy(ascon_st *con) -{ - if (con == NULL) - { - return; - } - - if (con->read_buffer != NULL) - { - ascore_buffer_free(con->read_buffer); - } - - if (con->read_buffer_compress != NULL) - { - ascore_buffer_free(con->read_buffer_compress); - } - - if (con->uncompressed_buffer != NULL) - { - free(con->uncompressed_buffer); - } - - if (con->compressed_buffer != NULL) - { - free(con->compressed_buffer); - } - -#ifdef HAVE_OPENSSL - if (con->ssl.bio_buffer != NULL) - { - free(con->ssl.bio_buffer); - } - if (con->ssl.write_buffer != NULL) - { - ascore_buffer_free(con->ssl.write_buffer); - } - /* This frees BIOs as well */ - if (con->ssl.ssl != NULL) - { - SSL_free(con->ssl.ssl); - } - if (con->ssl.context != NULL) - { - SSL_CTX_free(con->ssl.context); - } -#endif - if (con->uv_objects.stream != NULL) - { - uv_check_stop(&con->uv_objects.check); - uv_close((uv_handle_t*)con->uv_objects.stream, NULL); - if (not con->in_group) - { - uv_run(con->uv_objects.loop, UV_RUN_DEFAULT); - } - } - if (not con->in_group) - { - uv_loop_delete(con->uv_objects.loop); - delete con; - } -} - -void on_resolved(uv_getaddrinfo_t *resolver, int status, struct addrinfo *res) -{ - ascon_st *con= (ascon_st *)resolver->data; - - asdebug("Resolver callback"); - if (status != 0) - { - asdebug("DNS lookup failure: %s", uv_err_name(uv_last_error(resolver->loop))); - con->status= ASCORE_CON_STATUS_CONNECT_FAILED; - con->local_errcode= ASRET_DNS_ERROR; - snprintf(con->errmsg, ASCORE_ERROR_BUFFER_SIZE, "DNS lookup failure: %s", uv_err_name(uv_last_error(resolver->loop))); - return; - } - char addr[17] = {'\0'}; - - uv_ip4_name((struct sockaddr_in*) res->ai_addr, addr, 16); - asdebug("DNS lookup success: %s", addr); - uv_tcp_init(resolver->loop, &con->uv_objects.socket.tcp); - con->uv_objects.socket.tcp.data= con; - con->uv_objects.connect_req.data= (void*) &con->uv_objects.socket.tcp; - uv_tcp_connect(&con->uv_objects.connect_req, &con->uv_objects.socket.tcp, *(struct sockaddr_in*) res->ai_addr, on_connect); - - uv_freeaddrinfo(res); -} - -ascore_con_status_t ascore_con_poll(ascon_st *con) -{ - //asdebug("Connection poll"); - if (con == NULL) - { - return ASCORE_CON_STATUS_PARAMETER_ERROR; - } - - if ((con->status == ASCORE_CON_STATUS_NOT_CONNECTED) or (con->status == ASCORE_CON_STATUS_CONNECT_FAILED) or (con->status == ASCORE_CON_STATUS_IDLE) or (con->status == ASCORE_CON_STATUS_SSL_ERROR)) - { - return con->status; - } -#ifdef HAVE_OPENSSL - if (con->ssl.handshake_done) - { - ascore_ssl_run(con); - } -#endif - if (con->options.semi_block) - { - uv_run(con->uv_objects.loop, UV_RUN_ONCE); - } - else - { - uv_run(con->uv_objects.loop, UV_RUN_NOWAIT); - } - - return con->status; -} - -void ascore_check_for_data_cb(uv_check_t *handle, int status) -{ - (void) status; - asdebug("Check called"); - struct ascon_st *con= (struct ascon_st*)handle->data; - ascore_con_process_packets(con); -} - -ascore_con_status_t ascore_connect(ascon_st *con) -{ - int ret; - - if (con == NULL) - { - return ASCORE_CON_STATUS_PARAMETER_ERROR; - } - - con->uv_objects.hints.ai_family = PF_INET; - con->uv_objects.hints.ai_socktype = SOCK_STREAM; - con->uv_objects.hints.ai_protocol = IPPROTO_TCP; - con->uv_objects.hints.ai_flags = 0; - - if (con->status != ASCORE_CON_STATUS_NOT_CONNECTED) - { - return con->status; - } - - if (not con->in_group) - { - con->uv_objects.loop= uv_loop_new(); - } - if (con->uv_objects.loop == NULL) - { - asdebug("Loop initalize failure"); - con->local_errcode= ASRET_OUT_OF_MEMORY_ERROR; - snprintf(con->errmsg, ASCORE_ERROR_BUFFER_SIZE, "Loop initialization failure, either out of memory or out of file descripitors (usually the latter)"); - con->status= ASCORE_CON_STATUS_CONNECT_FAILED; - return con->status; - } - - snprintf(con->str_port, 6, "%d", con->port); - // If port is 0 and no explicit option set then assume we mean UDS - // instead of TCP - if (con->options.protocol == ASCORE_CON_PROTOCOL_UNKNOWN) - { - if (con->port == 0) - { - con->options.protocol= ASCORE_CON_PROTOCOL_UDS; - } - else - { - con->options.protocol= ASCORE_CON_PROTOCOL_TCP; - } - } - switch(con->options.protocol) - { - case ASCORE_CON_PROTOCOL_TCP: - asdebug("TCP connection"); - asdebug("Async DNS lookup: %s", con->host); - con->uv_objects.resolver.data= con; - ret= uv_getaddrinfo(con->uv_objects.loop, &con->uv_objects.resolver, on_resolved, con->host, con->str_port, &con->uv_objects.hints); - if (ret) - { - asdebug("DNS lookup fail: %s", uv_err_name(uv_last_error(con->uv_objects.loop))); - con->local_errcode= ASRET_DNS_ERROR; - snprintf(con->errmsg, ASCORE_ERROR_BUFFER_SIZE, "DNS lookup failure: %s", uv_err_name(uv_last_error(con->uv_objects.loop))); - con->status= ASCORE_CON_STATUS_CONNECT_FAILED; - return con->status; - } - con->status= ASCORE_CON_STATUS_CONNECTING; - if (con->options.semi_block) - { - uv_run(con->uv_objects.loop, UV_RUN_ONCE); - } - else - { - uv_run(con->uv_objects.loop, UV_RUN_NOWAIT); - } - break; - case ASCORE_CON_PROTOCOL_UDS: - asdebug("UDS connection"); - uv_pipe_init(con->uv_objects.loop, &con->uv_objects.socket.uds, 1); - con->uv_objects.socket.uds.data= con; - con->uv_objects.connect_req.data= (void*) &con->uv_objects.socket.uds; - con->status= ASCORE_CON_STATUS_CONNECTING; - uv_pipe_connect(&con->uv_objects.connect_req, &con->uv_objects.socket.uds, con->host, on_connect); - if (con->options.semi_block) - { - uv_run(con->uv_objects.loop, UV_RUN_ONCE); - } - else - { - uv_run(con->uv_objects.loop, UV_RUN_NOWAIT); - } - break; - case ASCORE_CON_PROTOCOL_UNKNOWN: - asdebug("Unknown protocol, this shouldn't happen"); - con->status= ASCORE_CON_STATUS_CONNECT_FAILED; - } - - return con->status; -} - - -void on_connect(uv_connect_t *req, int status) -{ - ascon_st *con= (ascon_st*)req->handle->data; - asdebug("Connect event callback"); - if (status != 0) - { - asdebug("Connect fail: %s", uv_err_name(uv_last_error(req->handle->loop))); - con->local_errcode= ASRET_CONNECT_ERROR; - con->status= ASCORE_CON_STATUS_CONNECT_FAILED; - snprintf(con->errmsg, ASCORE_ERROR_BUFFER_SIZE, "Connection failed: %s", uv_err_name(uv_last_error(req->handle->loop))); - return; - } - asdebug("Connection succeeded!"); - con->next_packet_type= ASCORE_PACKET_TYPE_HANDSHAKE; - // maybe move the set con->stream to connect function - con->uv_objects.stream= (uv_stream_t*)req->data; - uv_check_init(con->uv_objects.loop, &con->uv_objects.check); - con->uv_objects.check.data= con; - uv_check_start(&con->uv_objects.check, ascore_check_for_data_cb); - uv_read_start((uv_stream_t*)req->data, on_alloc, ascore_read_data_cb); -} - -uv_buf_t on_alloc(uv_handle_t *client, size_t suggested_size) -{ - size_t buffer_free; - uv_buf_t buf; - ascon_st *con= (ascon_st*) client->data; - -#ifdef HAVE_OPENSSL - if (con->ssl.handshake_done && (con->ssl.bio_buffer_size < suggested_size)) - { - asdebug("Increasing SSL read buffer to %zd", suggested_size); - char *realloc_buffer= (char*)realloc(con->ssl.bio_buffer, suggested_size); - if (realloc_buffer) - { - con->ssl.bio_buffer= realloc_buffer; - con->ssl.bio_buffer_size= suggested_size; - } - else - { - con->local_errcode= ASRET_OUT_OF_MEMORY_ERROR; - asdebug("SSL buffer realloc failure"); - con->command_status= ASCORE_COMMAND_STATUS_SEND_FAILED; - con->next_packet_type= ASCORE_PACKET_TYPE_NONE; - } - } -#endif - - if (not con->options.compression) - { - asdebug("%zd bytes requested for read buffer", suggested_size); - - if (con->read_buffer == NULL) - { - asdebug("Creating read buffer"); - con->read_buffer= ascore_buffer_create(); - } - buffer_free= ascore_buffer_get_available(con->read_buffer); - if (buffer_free < suggested_size) - { - asdebug("Enlarging buffer, free: %zd, requested: %zd", buffer_free, suggested_size); - ascore_buffer_increase(con->read_buffer); - buffer_free= ascore_buffer_get_available(con->read_buffer); - } - buf.base= con->read_buffer->buffer_write_ptr; - buf.len= buffer_free; - } - else - { - asdebug("%zd bytes requested for compressed read buffer", suggested_size); - - if (con->read_buffer_compress == NULL) - { - asdebug("Creating compressed read buffer"); - con->read_buffer_compress= ascore_buffer_create(); - } - buffer_free= ascore_buffer_get_available(con->read_buffer_compress); - if (buffer_free < suggested_size) - { - asdebug("Enlarging compress buffer, free: %zd, requested: %zd", buffer_free, suggested_size); - ascore_buffer_increase(con->read_buffer_compress); - buffer_free= ascore_buffer_get_available(con->read_buffer_compress); - } - buf.base= con->read_buffer_compress->buffer_write_ptr; - buf.len= buffer_free; - } - -#ifdef HAVE_OPENSSL - if (con->ssl.handshake_done) - { - buf.base= con->ssl.bio_buffer; - buf.len= con->ssl.bio_buffer_size; - } -#endif - - return buf; -} - -void ascore_packet_read_handshake(ascon_st *con) -{ - asdebug("Connect handshake packet"); - buffer_st *buffer= con->read_buffer; - - // Protocol version - if (buffer->buffer_read_ptr[0] != 10) - { - // Note that 255 is a special immediate auth fail case - asdebug("Bad protocol version"); - con->local_errcode= ASRET_BAD_PROTOCOL; - snprintf(con->errmsg, ASCORE_ERROR_BUFFER_SIZE, "Incompatible protocol version"); - return; - } - - // Server version (null-terminated string) - buffer->buffer_read_ptr++; - strncpy(con->server_version, buffer->buffer_read_ptr, ASCORE_MAX_SERVER_VERSION_LEN); - con->server_version[ASCORE_MAX_SERVER_VERSION_LEN - 1]= '\0'; - buffer->buffer_read_ptr+= strlen(con->server_version) + 1; - - // Thread ID - con->thread_id= ascore_unpack_int4(buffer->buffer_read_ptr); - buffer->buffer_read_ptr+= 4; - - // Scramble buffer and 1 byte filler - memcpy(con->scramble_buffer, buffer->buffer_read_ptr, 8); - buffer->buffer_read_ptr+= 9; - - // Server capabilities - con->server_capabilities= (ascore_capabilities_t)ascore_unpack_int2(buffer->buffer_read_ptr); - buffer->buffer_read_ptr+= 2; - // Check MySQL 4.1 protocol capability is on, we won't support old auth - if (not (con->server_capabilities & ASCORE_CAPABILITY_PROTOCOL_41)) - { - asdebug("MySQL <4.1 Auth not supported"); - con->local_errcode= ASRET_NO_OLD_AUTH; - snprintf(con->errmsg, ASCORE_ERROR_BUFFER_SIZE, "MySQL 4.1 protocol and higher required"); - } - - con->charset= buffer->buffer_read_ptr[0]; - buffer->buffer_read_ptr++; - - con->server_status= ascore_unpack_int2(buffer->buffer_read_ptr); - // 13 byte filler and unrequired scramble length (until auth plugins) - buffer->buffer_read_ptr+= 15; - - memcpy(con->scramble_buffer + 8, buffer->buffer_read_ptr, 12); - // '\0' scramble terminator - buffer->buffer_read_ptr+= 13; - - // MySQL 5.5 onwards has more password plugin stuff here, ignore for now - ascore_packet_read_end(con); - - // Create response packet - ascore_handshake_response(con); -} - -void ascore_handshake_response(ascon_st *con) -{ - unsigned char *buffer_ptr; - uint32_t capabilities; - - asdebug("Sending handshake response"); - buffer_ptr= (unsigned char*)con->write_buffer; - if (con->next_packet_type != ASCORE_PACKET_TYPE_HANDSHAKE_SSL) - { - uv_read_start(con->uv_objects.stream, on_alloc, ascore_read_data_cb); - } - - capabilities= con->server_capabilities & ASCORE_CAPABILITY_CLIENT; - capabilities|= ASCORE_CAPABILITY_MULTI_RESULTS; - capabilities|= con->client_capabilities; - -#ifdef HAVE_OPENSSL - if (con->ssl.ssl != NULL) - { - if (not (con->server_capabilities & ASCORE_CAPABILITY_SSL)) - { - asdebug("SSL disabled on server"); - con->local_errcode= ASRET_NET_SSL_ERROR; - snprintf(con->errmsg, ASCORE_ERROR_BUFFER_SIZE, "SSL auth not supported enabled on server"); - con->command_status= ASCORE_COMMAND_STATUS_SEND_FAILED; - con->next_packet_type= ASCORE_PACKET_TYPE_NONE; - con->status= ASCORE_CON_STATUS_CONNECT_FAILED; - return; - } - capabilities |= ASCORE_CAPABILITY_SSL; - } -#endif - - ascore_pack_int4(buffer_ptr, capabilities); - buffer_ptr+= 4; - - // Set max packet size to our buffer size for now - ascore_pack_int4(buffer_ptr, ASCORE_DEFAULT_BUFFER_SIZE); - buffer_ptr+= 4; - - // Change this when we support charsets - buffer_ptr[0]= 0; - buffer_ptr++; - - // 0x00 padding for 23 bytes - memset(buffer_ptr, 0, 23); - buffer_ptr+= 23; - -#ifdef HAVE_OPENSSL - if ((con->ssl.ssl != NULL) and (con->next_packet_type != ASCORE_PACKET_TYPE_HANDSHAKE_SSL)) - { - /* for SSL we do a short handshake ending here in plain text, - * no user/password sent. - * The enablement of the SSL capability tells the server that OpenSSL - * handshake happens next followed by a full MySQL handshake packet with - * user/pass encrypted - */ - ascore_send_data(con, con->write_buffer, (size_t)(buffer_ptr - (unsigned char*)con->write_buffer)); - con->next_packet_type= ASCORE_PACKET_TYPE_HANDSHAKE_SSL; - ascore_handshake_response(con); - return; - } - - if ((con->ssl.ssl != NULL) and (con->next_packet_type == ASCORE_PACKET_TYPE_HANDSHAKE_SSL)) - { - /* second entry into handshake for SSL, this response and all other send / - * receives should be encrypted from now on - */ - con->ssl.enabled= true; - } -#endif - - // User name - memcpy(buffer_ptr, con->user, strlen(con->user)); - buffer_ptr+= strlen(con->user); - buffer_ptr[0]= '\0'; - buffer_ptr++; - - // Password - // TODO: add support for password plugins - if (con->pass[0] != '\0') - { - asret_t ret; - buffer_ptr[0]= SHA1_DIGEST_LENGTH; // probably should use char packing? - buffer_ptr++; - ret= scramble_password(con, (unsigned char*)buffer_ptr); - if (ret != ASRET_OK) - { - asdebug("Scramble problem!"); - con->local_errcode= ASRET_BAD_SCRAMBLE; - return; - } - buffer_ptr+= SHA1_DIGEST_LENGTH; - } - else - { - buffer_ptr[0]= '\0'; - buffer_ptr++; - } - - if (con->schema != NULL) - { - memcpy(buffer_ptr, con->schema, strlen(con->schema)); - buffer_ptr+= strlen(con->schema); - } - buffer_ptr[0]= '\0'; - buffer_ptr++; - ascore_send_data(con, con->write_buffer, (size_t)(buffer_ptr - (unsigned char*)con->write_buffer)); - con->next_packet_type= ASCORE_PACKET_TYPE_RESPONSE; -} - -asret_t scramble_password(ascon_st *con, unsigned char *buffer) -{ - SHA1_CTX ctx; - unsigned char stage1[SHA1_DIGEST_LENGTH]; - unsigned char stage2[SHA1_DIGEST_LENGTH]; - uint8_t it; - - if (con->scramble_buffer[0] == '\0') - { - asdebug("No scramble supplied from server"); - return ASRET_NO_SCRAMBLE; - } - - // Double hash the password - SHA1Init(&ctx); - SHA1Update(&ctx, (unsigned char*)con->pass, strlen(con->pass)); - SHA1Final(stage1, &ctx); - SHA1Init(&ctx); - SHA1Update(&ctx, stage1, SHA1_DIGEST_LENGTH); - SHA1Final(stage2, &ctx); - - // Hash the scramble with the double hash - SHA1Init(&ctx); - SHA1Update(&ctx, con->scramble_buffer, SHA1_DIGEST_LENGTH); - SHA1Update(&ctx, stage2, SHA1_DIGEST_LENGTH); - SHA1Final(buffer, &ctx); - - // XOR the hash with the stage1 hash - for (it= 0; it < SHA1_DIGEST_LENGTH; it++) - { - buffer[it]= buffer[it] ^ stage1[it]; - } - - return ASRET_OK; -} - -void ascore_library_init(void) -{ -#ifdef HAVE_OPENSSL - SSL_load_error_strings(); - SSL_library_init(); -#endif -} - -#ifdef HAVE_OPENSSL -bool ascore_con_set_ssl(ascon_st *con, const char *key, const char *cert, const char *ca, const char *capath, const char *cipher, bool verify) -{ - con->ssl.context= SSL_CTX_new(TLSv1_client_method()); - - if (cipher != NULL) - { - if (SSL_CTX_set_cipher_list(con->ssl.context, cipher) != 1) - { - strncpy(con->errmsg, "Error setting SSL cipher list", ASCORE_ERROR_BUFFER_SIZE - 1); - con->errmsg[ASCORE_ERROR_BUFFER_SIZE - 1]= '\0'; - return false; - } - } - - if (SSL_CTX_load_verify_locations(con->ssl.context, ca, capath) != 1) - { - strncpy(con->errmsg, "Error loading the SSL certificate authority file", ASCORE_ERROR_BUFFER_SIZE -1); - con->errmsg[ASCORE_ERROR_BUFFER_SIZE - 1]= '\0'; - return false; - } - - if (cert != NULL) - { - if (SSL_CTX_use_certificate_file(con->ssl.context, cert, SSL_FILETYPE_PEM) != 1) - { - strncpy(con->errmsg, "Error loading the SSL certificate file", ASCORE_ERROR_BUFFER_SIZE - 1); - con->errmsg[ASCORE_ERROR_BUFFER_SIZE - 1]= '\0'; - return false; - } - - if (key == NULL) - { - key= cert; - } - - if (SSL_CTX_use_PrivateKey_file(con->ssl.context, key, SSL_FILETYPE_PEM) != 1) - { - strncpy(con->errmsg, "Cannot load the SSL key file", ASCORE_ERROR_BUFFER_SIZE - 1); - con->errmsg[ASCORE_ERROR_BUFFER_SIZE - 1]= '\0'; - return false; - } - - if (SSL_CTX_check_private_key(con->ssl.context) != 1) - { - strncpy(con->errmsg, "Error validating the SSL private key", ASCORE_ERROR_BUFFER_SIZE - 1); - con->errmsg[ASCORE_ERROR_BUFFER_SIZE - 1]= '\0'; - return false; - } - } - - if (verify) - { - SSL_CTX_set_verify(con->ssl.context, SSL_VERIFY_PEER, NULL); - } - con->ssl.ssl= SSL_new(con->ssl.context); - /* force client handshake mode to allow SSL_write before handshake complete */ - SSL_set_connect_state(con->ssl.ssl); - - return true; -} -#endif diff --git a/src/ascore/constants.h b/src/ascore/constants.h deleted file mode 100644 index 68b83e2..0000000 --- a/src/ascore/constants.h +++ /dev/null @@ -1,270 +0,0 @@ -/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab: - * Copyright 2014 Hewlett-Packard Development Company, L.P. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. You may obtain - * a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - * - */ - -#pragma once - -#include "config.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define ASCORE_DEFAULT_PORT 3306 -#define ASCORE_ERROR_BUFFER_SIZE 255 -#define ASCORE_MAX_SERVER_VERSION_LEN 32 -#define ASCORE_MAX_USER_SIZE 16 -#define ASCORE_MAX_SCHEMA_SIZE 64 -#define ASCORE_MAX_TABLE_SIZE 64 -#define ASCORE_MAX_COLUMN_SIZE 64 -#define ASCORE_MAX_DEFAULT_VALUE_SIZE 2048 -#define ASCORE_MAX_MESSAGE_LEN 2048 -#define ASCORE_SQLSTATE_SIZE 5 -#define ASCORE_WRITE_BUFFER_SIZE 1024 -#define ASCORE_MINIMUM_COMPRESS_SIZE 50 -#define ASCORE_STMT_EXEC_DEFAULT_SIZE 16*1024 - -#define ASCORE_STMT_PARAM_UNSIGNED_BIT 0x8000 - -enum ascore_con_protocol_t -{ - ASCORE_CON_PROTOCOL_UNKNOWN, - ASCORE_CON_PROTOCOL_UDS, - ASCORE_CON_PROTOCOL_TCP -}; - -enum ascore_con_options_t -{ - ASCORE_CON_OPTION_POLLING, - ASCORE_CON_OPTION_RAW_SCRAMBLE, - ASCORE_CON_OPTION_FOUND_ROWS, - ASCORE_CON_OPTION_INTERACTIVE, - ASCORE_CON_OPTION_MULTI_STATEMENTS, - ASCORE_CON_OPTION_AUTH_PLUGIN, - ASCORE_CON_OPTION_PROTOCOL_TCP, - ASCORE_CON_OPTION_PROTOCOL_UDS -}; - -enum ascore_con_status_t -{ - ASCORE_CON_STATUS_PARAMETER_ERROR, - ASCORE_CON_STATUS_NOT_CONNECTED, - ASCORE_CON_STATUS_CONNECTING, - ASCORE_CON_STATUS_CONNECT_FAILED, - ASCORE_CON_STATUS_BUSY, - ASCORE_CON_STATUS_IDLE, - ASCORE_CON_STATUS_SSL_ERROR -}; - -enum ascore_packet_type_t -{ - ASCORE_PACKET_TYPE_NONE, - ASCORE_PACKET_TYPE_HANDSHAKE, - ASCORE_PACKET_TYPE_HANDSHAKE_SSL, - ASCORE_PACKET_TYPE_RESPONSE, - ASCORE_PACKET_TYPE_PREPARE_RESPONSE, - ASCORE_PACKET_TYPE_PREPARE_PARAMETER, - ASCORE_PACKET_TYPE_PREPARE_COLUMN, - ASCORE_PACKET_TYPE_COLUMN, - ASCORE_PACKET_TYPE_ROW, - ASCORE_PACKET_TYPE_STMT_ROW -}; - -enum ascore_capabilities_t -{ - ASCORE_CAPABILITY_NONE= 0, - ASCORE_CAPABILITY_LONG_PASSWORD= (1 << 0), - ASCORE_CAPABILITY_FOUND_ROWS= (1 << 1), - ASCORE_CAPABILITY_LONG_FLAG= (1 << 2), - ASCORE_CAPABILITY_CONNECT_WITH_DB= (1 << 3), - ASCORE_CAPABILITY_NO_SCHEMA= (1 << 4), - ASCORE_CAPABILITY_COMPRESS= (1 << 5), - ASCORE_CAPABILITY_ODBC= (1 << 6), - ASCORE_CAPABILITY_LOCAL_FILES= (1 << 7), - ASCORE_CAPABILITY_IGNORE_SPACE= (1 << 8), - ASCORE_CAPABILITY_PROTOCOL_41= (1 << 9), - ASCORE_CAPABILITY_INTERACTIVE= (1 << 10), - ASCORE_CAPABILITY_SSL= (1 << 11), - ASCORE_CAPABILITY_IGNORE_SIGPIPE= (1 << 12), - ASCORE_CAPABILITY_TRANSACTIONS= (1 << 13), - ASCORE_CAPABILITY_RESERVED= (1 << 14), - ASCORE_CAPABILITY_SERCURE_CONNECTION= (1 << 15), - ASCORE_CAPABILITY_MULTI_STATEMENTS= (1 << 16), - ASCORE_CAPABILITY_MULTI_RESULTS= (1 << 17), - ASCORE_CAPABILITY_PLUGIN_AUTH= (1 << 19), - ASCORE_CAPABILITY_CLIENT= (ASCORE_CAPABILITY_LONG_PASSWORD | - ASCORE_CAPABILITY_FOUND_ROWS | - ASCORE_CAPABILITY_LONG_FLAG | - ASCORE_CAPABILITY_CONNECT_WITH_DB | - ASCORE_CAPABILITY_PLUGIN_AUTH | - ASCORE_CAPABILITY_TRANSACTIONS | - ASCORE_CAPABILITY_PROTOCOL_41 | - ASCORE_CAPABILITY_SERCURE_CONNECTION) -}; - - -enum ascore_command_status_t -{ - ASCORE_COMMAND_STATUS_NONE, - ASCORE_COMMAND_STATUS_CONNECTED, - ASCORE_COMMAND_STATUS_SEND, - ASCORE_COMMAND_STATUS_SEND_FAILED, - ASCORE_COMMAND_STATUS_READ_RESPONSE, - ASCORE_COMMAND_STATUS_READ_COLUMN, - ASCORE_COMMAND_STATUS_READ_ROW, - ASCORE_COMMAND_STATUS_READ_FAILED, - ASCORE_COMMAND_STATUS_ROW_IN_BUFFER, - ASCORE_COMMAND_STATUS_READ_STMT_PARAM, - ASCORE_COMMAND_STATUS_READ_STMT_COLUMN, - ASCORE_COMMAND_STATUS_READ_STMT_ROW, - ASCORE_COMMAND_STATUS_EOF -}; - -enum ascore_command_t -{ - ASCORE_COMMAND_SLEEP= 0x00, - ASCORE_COMMAND_QUIT= 0x01, - ASCORE_COMMAND_INITDB= 0x02, - ASCORE_COMMAND_QUERY= 0x03, - ASCORE_COMMAND_FIELD_LIST= 0x04, - ASCORE_COMMAND_CREATE_DB= 0x05, - ASCORE_COMMAND_DROP_DB= 0x06, - ASCORE_COMMAND_REFRESH= 0x07, - ASCORE_COMMAND_SHUTDOWN= 0x08, - ASCORE_COMMAND_STATISTICS= 0x09, - ASCORE_COMMAND_PROCESS_INFO= 0x0a, - ASCORE_COMMAND_CONNECT= 0x0b, - ASCORE_COMMAND_PROCESS_KILL= 0x0c, - ASCORE_COMMAND_DEBUG= 0x0d, - ASCORE_COMMAND_PING= 0x0e, - ASCORE_COMMAND_TIME= 0x0f, - ASCORE_COMMAND_DELAYED_INSERT= 0x10, - ASCORE_COMMAND_CHANGE_USER= 0x11, - ASCORE_COMMAND_BINLOG_DUMP= 0x12, - ASCORE_COMMAND_TABLE_DUMP= 0x13, - ASCORE_COMMAND_CONNECT_OUT= 0x14, /* Internal (unused) */ - ASCORE_COMMAND_REGISTER_SLAVE= 0x15, - ASCORE_COMMAND_STMT_PREPARE= 0x16, - ASCORE_COMMAND_STMT_EXECUTE= 0x17, - ASCORE_COMMAND_STMT_SEND_LONG_DATA= 0x18, - ASCORE_COMMAND_STMT_CLOSE= 0x19, - ASCORE_COMMAND_STMT_RESET= 0x1a, - ASCORE_COMMAND_SET_OPTION= 0x1b, - ASCORE_COMMAND_STMT_FETCH= 0x1c, - ASCORE_COMMAND_DAEMON= 0x1d, - ASCORE_COMMAND_BINLOG_DUMP_GTID= 0x1e, - ASCORE_COMMAND_RESET_CONNECTION= 0x1f -}; - -enum ascore_column_type_t -{ - ASCORE_COLUMN_TYPE_DECIMAL= 0x00, - ASCORE_COLUMN_TYPE_TINY= 0x01, - ASCORE_COLUMN_TYPE_SHORT= 0x02, - ASCORE_COLUMN_TYPE_LONG= 0x03, - ASCORE_COLUMN_TYPE_FLOAT= 0x04, - ASCORE_COLUMN_TYPE_DOUBLE= 0x05, - ASCORE_COLUMN_TYPE_NULL= 0x06, - ASCORE_COLUMN_TYPE_TIMESTAMP= 0x07, - ASCORE_COLUMN_TYPE_LONGLONG= 0x08, - ASCORE_COLUMN_TYPE_INT24= 0x09, - ASCORE_COLUMN_TYPE_DATE= 0x0a, - ASCORE_COLUMN_TYPE_TIME= 0x0b, - ASCORE_COLUMN_TYPE_DATETIME= 0x0c, - ASCORE_COLUMN_TYPE_YEAR= 0x0d, - ASCORE_COLUMN_TYPE_NEWDATE= 0x0e, // Internal only - ASCORE_COLUMN_TYPE_VARCHAR= 0x0f, - ASCORE_COLUMN_TYPE_BIT= 0x10, - ASCORE_COLUMN_TYPE_TIMESTAMP2= 0x11, // Internal only - ASCORE_COLUMN_TYPE_DATETIME2= 0x12, // Internal only - ASCORE_COLUMN_TYPE_TIME2= 0x13, // Internal only - ASCORE_COLUMN_TYPE_NEWDECIMAL= 0xf6, - ASCORE_COLUMN_TYPE_ENUM= 0xf7, - ASCORE_COLUMN_TYPE_SET= 0xf8, - ASCORE_COLUMN_TYPE_TINY_BLOB= 0xf9, - ASCORE_COLUMN_TYPE_MEDIUM_BLOB= 0xfa, - ASCORE_COLUMN_TYPE_LONG_BLOB= 0xfb, - ASCORE_COLUMN_TYPE_BLOB= 0xfc, - ASCORE_COLUMN_TYPE_VARSTRING= 0xfd, - ASCORE_COLUMN_TYPE_STRING= 0xfe, - ASCORE_COLUMN_TYPE_GEOMETRY= 0xff -}; - -enum ascore_column_flags_t -{ - ASCORE_COLUMN_FLAGS_NONE= 0, - ASCORE_COLUMN_FLAGS_NOT_NULL= (1 << 0), - ASCORE_COLUMN_FLAGS_PRIMARY_KEY= (1 << 1), - ASCORE_COLUMN_FLAGS_UNIQUE_KEY= (1 << 2), - ASCORE_COLUMN_FLAGS_MULTIPLE_KEY= (1 << 3), - ASCORE_COLUMN_FLAGS_BLOB= (1 << 4), - ASCORE_COLUMN_FLAGS_UNSIGNED= (1 << 5), - ASCORE_COLUMN_FLAGS_ZEROFILL= (1 << 6), - ASCORE_COLUMN_FLAGS_BINARY= (1 << 7), - ASCORE_COLUMN_FLAGS_ENUM= (1 << 8), - ASCORE_COLUMN_FLAGS_AUTO_INCREMENT= (1 << 9), - ASCORE_COLUMN_FLAGS_TIMESTAMP= (1 << 10), - ASCORE_COLUMN_FLAGS_SET= (1 << 11), - ASCORE_COLUMN_FLAGS_NO_DEFAULT_VALUE= (1 << 12), - ASCORE_COLUMN_FLAGS_ON_UPDATE_NOW= (1 << 13), - ASCORE_COLUMN_FLAGS_PART_KEY= (1 << 14), - ASCORE_COLUMN_FLAGS_NUM= (1 << 15), - ASCORE_COLUMN_FLAGS_GROUP= (1 << 15), // NUM and GROUP are both this - ASCORE_COLUMN_FLAGS_UNIQUE= (1 << 16), - ASCORE_COLUMN_FLAGS_BINCMP= (1 << 17), - ASCORE_COLUMN_FLAGS_GET_FIELD_COLUMNS= (1 << 18), - ASCORE_COLUMN_FLAGS_IN_PART_FUNC= (1 << 19), - ASCORE_COLUMN_FLAGS_IN_ADD_INDEX= (1 << 20), - ASCORE_COLUMN_FLAGS_RENAMED= (1 << 21) -}; - -enum ascore_server_status_t -{ - ASCORE_SERVER_STATUS_NONE= 0, - ASCORE_SERVER_STATUS_IN_TRANSACTION= (1 << 0), - ASCORE_SERVER_STATUS_AUTOCOMMIT= (1 << 1), - // (1 << 2) unusued - ASCORE_SERVER_STATUS_MORE_RESULTS= (1 << 3), - ASCORE_SERVER_STATUS_NO_GOOD_INDEX= (1 << 4), - ASCORE_SERVER_STATUS_NO_INDEX= (1 << 5), - ASCORE_SERVER_STATUS_CURSOR_EXISTS= (1 << 6), - ASCORE_SERVER_STATUS_LAST_ROW_SENT= (1 << 7), - ASCORE_SERVER_STATUS_DB_DROPPED= (1 << 8), - ASCORE_SERVER_STATUS_NO_BACKSLASH_ESCAPES= (1 << 9), - ASCORE_SERVER_STATUS_METADATA_CHANGED= (1 << 10), - ASCORE_SERVER_STATUS_QUERY_WAS_SLOW= (1 << 11), - ASCORE_SERVER_STATUS_PS_OUT_PARAMS= (1 << 12), - ASCORE_SERVER_STATUS_IN_TRANSACTION_READ_ONLY= (1 << 13) -}; - -enum ascore_stmt_state_t -{ - ASCORE_STMT_STATE_NONE, - ASCORE_STMT_STATE_PREPARED, - ASCORE_STMT_STATE_EXECUTED -}; - -enum ascore_stmt_cursor_t -{ - ASCORE_STMT_CURSOR_NONE= 0x00, - ASCORE_STMT_CURSOR_READ_ONLY= 0x01, - ASCORE_STMT_CURSOR_FOR_UPDATE= 0x02, - ASCORE_STMT_CURSOR_SCROLLABLE= 0x03 -}; -#ifdef __cplusplus -} -#endif - diff --git a/src/ascore/include.am b/src/ascore/include.am deleted file mode 100644 index 24b2d53..0000000 --- a/src/ascore/include.am +++ /dev/null @@ -1,18 +0,0 @@ -# vim:ft=automake -# included from Top Level Makefile.am -# All paths should be given relative to the root - -noinst_HEADERS+= src/ascore/ascore.h -noinst_HEADERS+= src/ascore/buffer.h -noinst_HEADERS+= src/ascore/connect.h -noinst_HEADERS+= src/ascore/constants.h -noinst_HEADERS+= src/ascore/command.h -noinst_HEADERS+= src/ascore/common.h -noinst_HEADERS+= src/ascore/debug.h -noinst_HEADERS+= src/ascore/net.h -noinst_HEADERS+= src/ascore/pack.h -noinst_HEADERS+= src/ascore/pack_macros.h -noinst_HEADERS+= src/ascore/return.h -noinst_HEADERS+= src/ascore/sha1.h -noinst_HEADERS+= src/ascore/structs.h -noinst_HEADERS+= src/ascore/statement.h diff --git a/src/ascore/net.h b/src/ascore/net.h deleted file mode 100644 index a3f9e90..0000000 --- a/src/ascore/net.h +++ /dev/null @@ -1,67 +0,0 @@ -/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab: - * Copyright 2014 Hewlett-Packard Development Company, L.P. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. You may obtain - * a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - * - */ - -#pragma once - -#include "common.h" - -#ifdef __cplusplus -extern "C" { -#endif - -void ascore_send_data(ascon_st *con, char *data, size_t length); - -void on_write(uv_write_t *req, int status); - -void ascore_read_data_cb(uv_stream_t* tcp, ssize_t read_size, const uv_buf_t buf); - -bool ascore_con_process_packets(ascon_st *con); - -void ascore_packet_read_end(ascon_st *con); - -void ascore_packet_read_response(ascon_st *con); - -void ascore_packet_read_prepare_response(ascon_st *con); - -void ascore_packet_read_prepare_parameter(ascon_st *con); - -void ascore_packet_read_prepare_column(ascon_st *con); - -void ascore_packet_get_column(ascon_st *con, column_t *column); - -void ascore_packet_read_column(ascon_st *con); - -void ascore_packet_stmt_read_row(ascon_st *con); - -void ascore_packet_read_row(ascon_st *con); - -#ifdef HAVE_ZLIB -void ascore_send_compressed_packet(ascon_st *con, char *data, size_t length, uint8_t command); -#endif - -#ifdef HAVE_OPENSSL -void ascore_ssl_run(ascon_st *con); - -void ascore_ssl_data_check(ascon_st *con); - -void ascore_ssl_handle_error(ascon_st *con, int result); - -#endif - -#ifdef __cplusplus -} -#endif diff --git a/src/ascore/statement.cc b/src/ascore/statement.cc deleted file mode 100644 index f2ab5e3..0000000 --- a/src/ascore/statement.cc +++ /dev/null @@ -1,302 +0,0 @@ -/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab: - * Copyright 2014 Hewlett-Packard Development Company, L.P. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. You may obtain - * a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - * - */ - -#include "config.h" -#include "common.h" -#include "statement.h" -#include "command.h" -#include "net.h" - -ascore_stmt_st *ascore_stmt_prepare(ascon_st *con, size_t length, const char *statement) -{ - con->stmt= new (std::nothrow) ascore_stmt_st; - - if (con->stmt == NULL) - { - con->local_errcode= ASRET_OUT_OF_MEMORY_ERROR; - con->command_status= ASCORE_COMMAND_STATUS_SEND_FAILED; - con->next_packet_type= ASCORE_PACKET_TYPE_NONE; - return NULL; - } - - con->stmt->con= con; - asdebug("Sending MySQL prepare"); - ascore_command_send(con, ASCORE_COMMAND_STMT_PREPARE, (char*)statement, length); - return con->stmt; -} - -bool ascore_stmt_execute(ascore_stmt_st *stmt) -{ - char *buffer_pos= NULL; - uint16_t param_count= 0; - - /* Need minimum of 2K plus a bit extra for packet header */ - if (not ascore_stmt_check_buffer_size(stmt, 2060)) - { - return false; - } - buffer_pos= stmt->exec_buffer; - - /* statement ID */ - ascore_pack_int4(buffer_pos, stmt->id); - buffer_pos+= 4; - /* cursor flags */ - buffer_pos[0]= ASCORE_STMT_CURSOR_NONE; - buffer_pos++; - /* iteration count (always 1) */ - ascore_pack_int4(buffer_pos, 1); - buffer_pos+= 4; - /* NULL bitmask */ - if (stmt->param_count > 0) - { - uint16_t null_bytes= (stmt->param_count + 7) / 8; - memset(buffer_pos, 0, null_bytes); - param_count= stmt->param_count; - for (uint16_t param= 0; param < stmt->param_count; param++) - { - if (stmt->param_data[param].type == ASCORE_COLUMN_TYPE_NULL) - { - buffer_pos[param/8] |= (1 << (param % 8)); - param_count--; - } - } - buffer_pos+= null_bytes; - } - /* New bind? */ - buffer_pos[0]= stmt->new_bind; - buffer_pos++; - /* Bind params - * First part is type of each parameter, 2 bytes per type - * Second part is the parameters themselves - * param_count is the number of params without NULL since they don't store type data - */ - char *param_type_pos= buffer_pos; - size_t param_bytes= 0; - size_t buffer_bytes= 0; - buffer_pos+= (param_count * 2); - for (uint16_t param= 0; param < stmt->param_count; param++) - { - ascore_stmt_param_st *param_data= &stmt->param_data[param]; - - uint16_t type= (uint16_t)param_data->type; - if (type == ASCORE_COLUMN_TYPE_NULL) - { - continue; - } - if (param_data->is_unsigned) - { - type|= ASCORE_STMT_PARAM_UNSIGNED_BIT; - } - ascore_pack_int2(¶m_type_pos[param * 2], type); - - /* Long data skipped */ - if (param_data->is_long_data) - { - continue; - } - - /* Check buffer for at least ascore_datetime_st bytes - * restore pointers too - */ - param_bytes= param_type_pos - stmt->exec_buffer; - buffer_bytes= buffer_pos - stmt->exec_buffer; - if (not ascore_stmt_check_buffer_size(stmt, sizeof(ascore_datetime_st))) - { - return false; - } - param_type_pos= stmt->exec_buffer + param_bytes; - buffer_pos= stmt->exec_buffer + buffer_bytes; - - switch (param_data->type) - { - case ASCORE_COLUMN_TYPE_TINY: - buffer_pos[0]= param_data->data.tinyint_data; - buffer_pos++; - break; - case ASCORE_COLUMN_TYPE_SHORT: - ascore_pack_int2(buffer_pos, param_data->data.smallint_data); - buffer_pos+= 2; - break; - case ASCORE_COLUMN_TYPE_LONG: - ascore_pack_int4(buffer_pos, param_data->data.int_data); - buffer_pos+= 4; - break; - case ASCORE_COLUMN_TYPE_LONGLONG: - ascore_pack_int8(buffer_pos, param_data->data.bigint_data); - buffer_pos+= 8; - break; - case ASCORE_COLUMN_TYPE_FLOAT: - memcpy(buffer_pos, ¶m_data->data.float_data, 4); - buffer_pos+= 4; - break; - case ASCORE_COLUMN_TYPE_DOUBLE: - memcpy(buffer_pos, ¶m_data->data.double_data, 8); - buffer_pos+= 8; - break; - case ASCORE_COLUMN_TYPE_TIME: - buffer_pos= ascore_pack_time(buffer_pos, param_data->data.datetime_data); - break; - case ASCORE_COLUMN_TYPE_DATE: - buffer_pos= ascore_pack_datetime(buffer_pos, param_data->data.datetime_data, true); - break; - case ASCORE_COLUMN_TYPE_DATETIME: - case ASCORE_COLUMN_TYPE_TIMESTAMP: - buffer_pos= ascore_pack_datetime(buffer_pos, param_data->data.datetime_data, false); - break; - case ASCORE_COLUMN_TYPE_STRING: - case ASCORE_COLUMN_TYPE_BLOB: - /* check buffer for size */ - param_bytes= param_type_pos - stmt->exec_buffer; - buffer_bytes= buffer_pos - stmt->exec_buffer; - if (not ascore_stmt_check_buffer_size(stmt, param_data->length)) - { - return false; - } - param_type_pos= stmt->exec_buffer + param_bytes; - buffer_pos= stmt->exec_buffer + buffer_bytes; - buffer_pos= ascore_pack_data(buffer_pos, param_data->length, param_data->data.string_data); - break; - case ASCORE_COLUMN_TYPE_NULL: - /* Already handled in the NULL bitmask we should not get here */ - /* The following should never happen, but are listed to make compilers happy bunnies */ - case ASCORE_COLUMN_TYPE_INT24: - case ASCORE_COLUMN_TYPE_YEAR: - case ASCORE_COLUMN_TYPE_NEWDATE: - case ASCORE_COLUMN_TYPE_VARCHAR: - case ASCORE_COLUMN_TYPE_BIT: - case ASCORE_COLUMN_TYPE_TIMESTAMP2: - case ASCORE_COLUMN_TYPE_DATETIME2: - case ASCORE_COLUMN_TYPE_TIME2: - case ASCORE_COLUMN_TYPE_NEWDECIMAL: - case ASCORE_COLUMN_TYPE_ENUM: - case ASCORE_COLUMN_TYPE_SET: - case ASCORE_COLUMN_TYPE_TINY_BLOB: - case ASCORE_COLUMN_TYPE_MEDIUM_BLOB: - case ASCORE_COLUMN_TYPE_LONG_BLOB: - case ASCORE_COLUMN_TYPE_VARSTRING: - case ASCORE_COLUMN_TYPE_GEOMETRY: - case ASCORE_COLUMN_TYPE_DECIMAL: - default: - stmt->con->local_errcode= ASRET_BAD_STMT_PARAMETER; - asdebug("Bad stmt parameter type provided: %d", param_data->type); - stmt->con->command_status= ASCORE_COMMAND_STATUS_SEND_FAILED; - stmt->con->next_packet_type= ASCORE_PACKET_TYPE_NONE; - return false; - break; - } - } - if (ascore_command_send(stmt->con, ASCORE_COMMAND_STMT_EXECUTE, stmt->exec_buffer, buffer_pos - stmt->exec_buffer) != ASCORE_COMMAND_STATUS_SEND) - { - return false; - } - return true; -} - -bool ascore_stmt_check_buffer_size(ascore_stmt_st *stmt, size_t required) -{ - char *realloc_buffer= NULL; - - if (stmt->exec_buffer_length < required) - { - size_t new_size= 0; - if (stmt->exec_buffer_length == 0) - { - new_size= ASCORE_STMT_EXEC_DEFAULT_SIZE; - } - else - { - new_size= stmt->exec_buffer_length * 2; - } - realloc_buffer= (char*)realloc(stmt->exec_buffer, new_size); - if (realloc_buffer == NULL) - { - stmt->con->local_errcode= ASRET_OUT_OF_MEMORY_ERROR; - asdebug("Exec buffer realloc failure"); - stmt->con->command_status= ASCORE_COMMAND_STATUS_SEND_FAILED; - stmt->con->next_packet_type= ASCORE_PACKET_TYPE_NONE; - return false; - } - stmt->exec_buffer= realloc_buffer; - stmt->exec_buffer_length= new_size; - } - return true; -} - -ascore_command_status_t ascore_stmt_fetch(ascore_stmt_st *stmt) -{ - ascore_buffer_packet_read_end(stmt->con->read_buffer); - stmt->con->next_packet_type= ASCORE_PACKET_TYPE_STMT_ROW; - stmt->con->command_status= ASCORE_COMMAND_STATUS_READ_STMT_ROW; - ascore_con_process_packets(stmt->con); - return stmt->con->command_status; -} - -void ascore_stmt_destroy(ascore_stmt_st *stmt) -{ - if (stmt->column_count > 0) - { - delete[] stmt->columns; - } - - if (stmt->param_count > 0) - { - delete[] stmt->params; - } - - if (stmt->exec_buffer_length > 0) - { - free(stmt->exec_buffer); - } - - if (stmt->param_data != NULL) - { - for (uint16_t param= 0; param < stmt->param_count; param++) - { - if (stmt->param_data[param].datetime_alloc) - { - delete stmt->param_data[param].data.datetime_data; - } - } - delete[] stmt->param_data; - } - - stmt->con->stmt= NULL; - stmt->con->write_buffer_extra= 4; - ascore_command_free(stmt->con); - ascore_pack_int4(&stmt->con->write_buffer[1], stmt->id); - ascore_command_send(stmt->con, ASCORE_COMMAND_STMT_CLOSE, NULL, 0); - delete stmt; -} - -ascore_command_status_t ascore_stmt_reset(ascore_stmt_st *stmt) -{ - stmt->con->write_buffer_extra= 4; - ascore_pack_int4(&stmt->con->write_buffer[1], stmt->id); - - return ascore_command_send(stmt->con, ASCORE_COMMAND_STMT_RESET, NULL, 0); -} - -ascore_command_status_t ascore_stmt_send_long_data(ascore_stmt_st *stmt, uint16_t param, size_t length, char *data) -{ - stmt->con->write_buffer_extra= 6; - ascore_pack_int4(&stmt->con->write_buffer[1], stmt->id); - ascore_pack_int2(&stmt->con->write_buffer[5], param); - - return ascore_command_send(stmt->con, ASCORE_COMMAND_STMT_SEND_LONG_DATA, data, length); -} - - diff --git a/src/ascore/statement.h b/src/ascore/statement.h deleted file mode 100644 index bba4f85..0000000 --- a/src/ascore/statement.h +++ /dev/null @@ -1,43 +0,0 @@ -/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab: - * Copyright 2014 Hewlett-Packard Development Company, L.P. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. You may obtain - * a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - * - */ - -#pragma once - -#include "config.h" -#include "common.h" - -#ifdef __cplusplus -extern "C" { -#endif - -ascore_stmt_st *ascore_stmt_prepare(ascon_st *con, size_t length, const char *statement); - -bool ascore_stmt_execute(ascore_stmt_st *stmt); - -bool ascore_stmt_check_buffer_size(ascore_stmt_st *stmt, size_t required); - -ascore_command_status_t ascore_stmt_fetch(ascore_stmt_st *stmt); - -void ascore_stmt_destroy(ascore_stmt_st *stmt); - -ascore_command_status_t ascore_stmt_reset(ascore_stmt_st *stmt); - -ascore_command_status_t ascore_stmt_send_long_data(ascore_stmt_st *stmt, uint16_t param, size_t length, char *data); - -#ifdef __cplusplus -} -#endif diff --git a/src/asql/common.h b/src/asql/common.h deleted file mode 100644 index 377014b..0000000 --- a/src/asql/common.h +++ /dev/null @@ -1,27 +0,0 @@ -/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab: - * Copyright 2014 Hewlett-Packard Development Company, L.P. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. You may obtain - * a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - * - */ - -#pragma once - -#ifdef __cplusplus -#include -#endif - -#include -#include "src/asql/structs_internal.h" -#include "src/asql/error_internal.h" - diff --git a/src/asql/connect.cc b/src/asql/connect.cc deleted file mode 100644 index 7c0f51d..0000000 --- a/src/asql/connect.cc +++ /dev/null @@ -1,414 +0,0 @@ -/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab: - * Copyright 2014 Hewlett-Packard Development Company, L.P. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. You may obtain - * a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - * - */ - -#include "config.h" -#include "src/asql/common.h" -#include "src/ascore/ascore.h" -#include "src/asql/query_internal.h" -#include "src/asql/connect_internal.h" - -attachsql_connect_t *attachsql_connect_create(const char *host, in_port_t port, const char *user, const char *pass, const char *schema, attachsql_error_t **error) -{ - attachsql_connect_t *con= NULL; - - con= new (std::nothrow) attachsql_connect_t; - if (con == NULL) - { - attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_PARAMETER, ATTACHSQL_ERROR_LEVEL_ERROR, "82100", "Allocation failure for connection object"); - return NULL; - } - con->core_con= ascore_con_create(host, port, user, pass, schema); - if (con->core_con == NULL) - { - attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_ALLOC, ATTACHSQL_ERROR_LEVEL_ERROR, "82100", "Allocation failure for connection object"); - return NULL; - } - - if (con->core_con->status == ASCORE_CON_STATUS_PARAMETER_ERROR) - { - if (con->core_con->local_errcode == ASRET_USER_TOO_LONG) - { - attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_PARAMETER, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", "User name too long"); - } - else if (con->core_con->local_errcode == ASRET_SCHEMA_TOO_LONG) - { - attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_PARAMETER, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", "Schema too long"); - } - attachsql_connect_destroy(con); - return NULL; - } - - return con; -} - -void attachsql_connect_destroy(attachsql_connect_t *con) -{ - if (con == NULL) - { - return; - } - - if (con->in_query) - { - attachsql_query_close(con); - } - - if (con->core_con != NULL) - { - bool in_group= con->core_con->in_group; - ascore_con_destroy(con->core_con); - if (not in_group) - { - delete con; - } - } -} - -void attachsql_connect_set_callback(attachsql_connect_t *con, attachsql_callback_fn *function, void *context) -{ - con->callback_fn= function; - con->callback_context= context; -} - -const char *attachsql_connect_get_server_version(attachsql_connect_t *con) -{ - if (con == NULL) - { - return NULL; - } - - return con->core_con->server_version; -} - -uint32_t attachsql_connect_get_connection_id(attachsql_connect_t *con) -{ - if (con == NULL) - { - return 0; - } - return con->core_con->thread_id; -} - -attachsql_return_t attachsql_connect_poll(attachsql_connect_t *con, attachsql_error_t **error) -{ - ascore_con_status_t status; - - if (con == NULL) - { - attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_PARAMETER, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", "Invalid connection object"); - return ATTACHSQL_RETURN_ERROR; - } - if (not con->core_con->in_group) - { - status= ascore_con_poll(con->core_con); - } - else - { - status= con->core_con->status; - } - - switch (status) - { - case ASCORE_CON_STATUS_PARAMETER_ERROR: - attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_PARAMETER, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", "Bad parameter"); - if (con->callback_fn != NULL) - { - con->callback_fn(con, ATTACHSQL_EVENT_ERROR, con->callback_context, *error); - } - return ATTACHSQL_RETURN_ERROR; - break; - case ASCORE_CON_STATUS_NOT_CONNECTED: - return ATTACHSQL_RETURN_NOT_CONNECTED; - break; - case ASCORE_CON_STATUS_CONNECTING: - return ATTACHSQL_RETURN_CONNECTING; - break; - case ASCORE_CON_STATUS_CONNECT_FAILED: - if (con->core_con->local_errcode == ASRET_DNS_ERROR) - { - attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_HOST_UNKNOWN, ATTACHSQL_ERROR_LEVEL_ERROR, "08000", con->core_con->errmsg); - } - else if (con->core_con->server_errno != 0) - { - attachsql_error_server_create(con, error); - } - else - { - if (con->core_con->errmsg[0] != '\0') - { - attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_CONNECT, ATTACHSQL_ERROR_LEVEL_ERROR, "08000", con->core_con->errmsg); - } - else - { - attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_CONNECT, ATTACHSQL_ERROR_LEVEL_ERROR, "08000", "Unknown connection failure"); - } - } - if (con->callback_fn != NULL) - { - con->callback_fn(con, ATTACHSQL_EVENT_ERROR, con->callback_context, *error); - } - return ATTACHSQL_RETURN_ERROR; - break; - case ASCORE_CON_STATUS_BUSY: - return ATTACHSQL_RETURN_PROCESSING; - break; - case ASCORE_CON_STATUS_SSL_ERROR: - attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_SSL, ATTACHSQL_ERROR_LEVEL_ERROR, "08000", con->core_con->errmsg); - if (con->callback_fn != NULL) - { - con->callback_fn(con, ATTACHSQL_EVENT_ERROR, con->callback_context, *error); - } - return ATTACHSQL_RETURN_ERROR; - break; - case ASCORE_CON_STATUS_IDLE: - if (con->core_con->server_errno != 0) - { - // Server error during query - attachsql_error_server_create(con, error); - if (con->callback_fn != NULL) - { - con->callback_fn(con, ATTACHSQL_EVENT_ERROR, con->callback_context, *error); - } - return ATTACHSQL_RETURN_ERROR; - } - else if (con->core_con->command_status == ASCORE_COMMAND_STATUS_EOF) - { - if (con->callback_fn != NULL) - { - con->callback_fn(con, ATTACHSQL_EVENT_EOF, con->callback_context, NULL); - } - con->all_rows_buffered= true; - con->core_con->command_status= ASCORE_COMMAND_STATUS_NONE; - return ATTACHSQL_RETURN_EOF; - } - else if (con->core_con->command_status == ASCORE_COMMAND_STATUS_ROW_IN_BUFFER) - { - if (con->buffer_rows) - { - return attachsql_query_row_buffer(con, error); - } - else - { - if (con->callback_fn != NULL) - { - con->callback_fn(con, ATTACHSQL_EVENT_ROW_READY, con->callback_context, NULL); - } - return ATTACHSQL_RETURN_ROW_READY; - } - } - else if (con->core_con->command_status == ASCORE_COMMAND_STATUS_CONNECTED) - { - if (con->callback_fn != NULL) - { - con->callback_fn(con, ATTACHSQL_EVENT_CONNECTED, con->callback_context, NULL); - } - if (con->query_buffer_length > 0) - { - return attachsql_connect_query(con, error); - } - } - return ATTACHSQL_RETURN_IDLE; - break; - } - /* If we get this far 1. our compiler needs shooting for not catching a - * missing case statement and 2. something bad probably happened anyway */ - attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_UNKNOWN, ATTACHSQL_ERROR_LEVEL_ERROR, "99999", "Unkown error occurred"); - return ATTACHSQL_RETURN_ERROR; -} - -attachsql_return_t attachsql_connect_query(attachsql_connect_t *con, attachsql_error_t **error) -{ - ascore_command_status_t ret; - - if (con->query_buffer_statement) - { - con->stmt= ascore_stmt_prepare(con->core_con, con->query_buffer_length, con->query_buffer); - ret= con->core_con->command_status; - } - else - { - ret= ascore_command_send(con->core_con, ASCORE_COMMAND_QUERY, con->query_buffer, con->query_buffer_length); - } - if (ret == ASCORE_COMMAND_STATUS_SEND_FAILED) - { - attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_SERVER_GONE, ATTACHSQL_ERROR_LEVEL_ERROR, "08006", con->core_con->errmsg); - return ATTACHSQL_RETURN_ERROR; - } - return ATTACHSQL_RETURN_PROCESSING; -} - -bool attachsql_connect(attachsql_connect_t *con, attachsql_error_t **error) -{ - ascore_con_status_t status; - - status= ascore_connect(con->core_con); - - switch(status) - { - case ASCORE_CON_STATUS_PARAMETER_ERROR: - attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_PARAMETER, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", "Bad parameter"); - if (con->callback_fn != NULL) - { - con->callback_fn(con, ATTACHSQL_EVENT_ERROR, con->callback_context, *error); - } - return false; - break; - case ASCORE_CON_STATUS_NOT_CONNECTED: - /* Shouldn't happen */ - return true; - break; - case ASCORE_CON_STATUS_CONNECTING: - return true; - break; - case ASCORE_CON_STATUS_CONNECT_FAILED: - if (con->core_con->local_errcode == ASRET_DNS_ERROR) - { - attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_HOST_UNKNOWN, ATTACHSQL_ERROR_LEVEL_ERROR, "08000", con->core_con->errmsg); - } - else if (con->core_con->server_errno != 0) - { - attachsql_error_server_create(con, error); - } - else - { - if (con->core_con->errmsg[0] != '\0') - { - attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_CONNECT, ATTACHSQL_ERROR_LEVEL_ERROR, "08000", con->core_con->errmsg); - } - else - { - attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_CONNECT, ATTACHSQL_ERROR_LEVEL_ERROR, "08000", "Unknown connection failure"); - } - } - if (con->callback_fn != NULL) - { - con->callback_fn(con, ATTACHSQL_EVENT_ERROR, con->callback_context, *error); - } - return false; - break; - case ASCORE_CON_STATUS_BUSY: - /* Should never be hit */ - return false; - break; - case ASCORE_CON_STATUS_IDLE: - if ((con->core_con->command_status == ASCORE_COMMAND_STATUS_CONNECTED) and (con->callback_fn != NULL)) - { - con->callback_fn(con, ATTACHSQL_EVENT_CONNECTED, con->callback_context, NULL); - } - return true; - break; - case ASCORE_CON_STATUS_SSL_ERROR: - attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_SSL, ATTACHSQL_ERROR_LEVEL_ERROR, "08000", con->core_con->errmsg); - if (con->callback_fn != NULL) - { - con->callback_fn(con, ATTACHSQL_EVENT_ERROR, con->callback_context, *error); - } - - return false; - break; - - } - - return true; -} - -bool attachsql_connect_set_option(attachsql_connect_t *con, attachsql_options_t option, const void *arg) -{ - // arg option is for later - (void) arg; - if (con == NULL) - { - return false; - } - - switch (option) - { - case ATTACHSQL_OPTION_COMPRESS: -#ifdef HAVE_ZLIB - con->core_con->client_capabilities|= ASCORE_CAPABILITY_COMPRESS; -#else - return false; -#endif - break; - case ATTACHSQL_OPTION_FOUND_ROWS: - con->core_con->client_capabilities|= ASCORE_CAPABILITY_FOUND_ROWS; - break; - case ATTACHSQL_OPTION_IGNORE_SIGPIPE: - con->core_con->client_capabilities|= ASCORE_CAPABILITY_IGNORE_SIGPIPE; - break; - case ATTACHSQL_OPTION_INTERACTIVE: - con->core_con->client_capabilities|= ASCORE_CAPABILITY_INTERACTIVE; - break; - case ATTACHSQL_OPTION_LOCAL_FILES: - con->core_con->client_capabilities|= ASCORE_CAPABILITY_LOCAL_FILES; - break; - case ATTACHSQL_OPTION_MULTI_STATEMENTS: - con->core_con->client_capabilities|= ASCORE_CAPABILITY_MULTI_STATEMENTS; - break; - case ATTACHSQL_OPTION_NO_SCHEMA: - con->core_con->client_capabilities|= ASCORE_CAPABILITY_NO_SCHEMA; - break; - case ATTACHSQL_OPTION_SSL_NO_VERIFY: -#ifdef HAVE_OPENSSL - con->core_con->ssl.no_verify= true; -#else - return false; -#endif - break; - case ATTACHSQL_OPTION_SEMI_BLOCKING: - con->core_con->options.semi_block= true; - break; - case ATTACHSQL_OPTION_NONE: - return false; - break; - default: - return false; - } - return true; -} - -#ifdef HAVE_OPENSSL -bool attachsql_connect_set_ssl(attachsql_connect_t *con, const char *key, const char *cert, const char *ca, const char *capath, const char *cipher, bool verify, attachsql_error_t **error) -{ - if (con == NULL) - { - attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_PARAMETER, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", "Connection parameter not valid"); - return false; - } - - if (not ascore_con_set_ssl(con->core_con, key, cert, ca, capath, cipher, verify)) - { - attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_SSL, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", con->core_con->errmsg); - return false; - } - return true; -} -#else -bool attachsql_connect_set_ssl(attachsql_connect_t *con, const char *key, const char *cert, const char *ca, const char *capath, const char *cipher, bool verify, attachsql_error_t **error) -{ - (void) con; - (void) key; - (void) cert; - (void) ca; - (void) capath; - (void) cipher; - (void) verify; - - attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_NO_SSL, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", "SSL support has not been compiled in"); - return false; -} -#endif diff --git a/src/asql/group.cc b/src/asql/group.cc deleted file mode 100644 index be1b34c..0000000 --- a/src/asql/group.cc +++ /dev/null @@ -1,105 +0,0 @@ -/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab: - * Copyright 2014 Hewlett-Packard Development Company, L.P. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. You may obtain - * a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - * - */ - -#include "config.h" -#include "common.h" - -attachsql_group_t *attachsql_group_create(attachsql_error_t **error) -{ - attachsql_group_t *group= NULL; - - group= new (std::nothrow) attachsql_group_t; - - if (group == NULL) - { - attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_ALLOC, ATTACHSQL_ERROR_LEVEL_ERROR, "82100", "Allocation failure for group object"); - return NULL; - } - group->loop= uv_loop_new(); - if (group->loop == NULL) - { - attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_ALLOC, ATTACHSQL_ERROR_LEVEL_ERROR, "82100", "Allocation failure for group event loop"); - delete group; - return NULL; - } - return group; -} - -void attachsql_group_destroy(attachsql_group_t *group) -{ - size_t connection; - if (group == NULL) - { - return; - } - for (connection= 0; connection < group->connection_count; connection++) - { - attachsql_connect_destroy(group->connections[connection]); - } - uv_run(group->loop, UV_RUN_DEFAULT); - uv_loop_delete(group->loop); - for (connection= 0; connection < group->connection_count; connection++) - { - delete group->connections[connection]->core_con; - delete group->connections[connection]; - } - if (group->connections != NULL) - { - free(group->connections); - } - delete group; -} - -void attachsql_group_add_connection(attachsql_group_t *group, attachsql_connect_t *con, attachsql_error_t **error) -{ - attachsql_connect_t **tmp_cons; - - if ((group == NULL) || (con == NULL)) - { - attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_PARAMETER, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", "Bad parameter"); - return; - } - - tmp_cons= (attachsql_connect_t**)realloc(group->connections, sizeof(attachsql_connect_t*) * (group->connection_count + 1)); - if (tmp_cons != NULL) - { - group->connections= tmp_cons; - group->connections[group->connection_count]= con; - con->core_con->in_group= true; - con->core_con->uv_objects.loop= group->loop; - group->connection_count++; - } - else - { - attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_ALLOC, ATTACHSQL_ERROR_LEVEL_ERROR, "82100", "Allocation failure for group connection add"); - } -} - -void attachsql_group_run(attachsql_group_t *group) -{ - size_t connection; - attachsql_error_t *error= NULL; - if (group == NULL) - { - return; - } - uv_run(group->loop, UV_RUN_NOWAIT); - for (connection= 0; connection < group->connection_count; connection++) - { - attachsql_connect_poll(group->connections[connection], &error); - } -} diff --git a/src/asql/include.am b/src/asql/include.am deleted file mode 100644 index 3851035..0000000 --- a/src/asql/include.am +++ /dev/null @@ -1,45 +0,0 @@ -# vim:ft=automake -# included from Top Level Makefile.am -# All paths should be given relative to the root - -noinst_HEADERS+= src/asql/common.h -noinst_HEADERS+= src/asql/error_internal.h -noinst_HEADERS+= src/asql/connect_internal.h -noinst_HEADERS+= src/asql/query_internal.h -noinst_HEADERS+= src/asql/statement_internal.h -noinst_HEADERS+= src/asql/structs_internal.h - -lib_LTLIBRARIES+= src/asql/libattachsql.la -src_asql_libattachsql_la_SOURCES= -src_asql_libattachsql_la_LIBADD= -src_asql_libattachsql_la_LDFLAGS= -src_asql_libattachsql_la_CFLAGS= -DBUILDING_ASQL -src_asql_libattachsql_la_CXXFLAGS= -DBUILDING_ASQL - -if BUILD_WIN32 -src_asql_libattachsql_la_LIBADD+= -lmingw32 -src_asql_libattachsql_la_LIBADD+= -lws2_32 -src_asql_libattachsql_la_LIBADD+= -lpsapi -src_asql_libattachsql_la_LIBADD+= -liphlpapi -endif - -src_asql_libattachsql_la_SOURCES+= src/ascore/buffer.cc -src_asql_libattachsql_la_SOURCES+= src/ascore/command.cc -src_asql_libattachsql_la_SOURCES+= src/ascore/connect.cc -src_asql_libattachsql_la_SOURCES+= src/ascore/sha1.cc -src_asql_libattachsql_la_SOURCES+= src/ascore/net.cc -src_asql_libattachsql_la_SOURCES+= src/ascore/pack.cc -src_asql_libattachsql_la_SOURCES+= src/ascore/statement.cc - -src_asql_libattachsql_la_SOURCES+= src/asql/error.cc -src_asql_libattachsql_la_SOURCES+= src/asql/connect.cc -src_asql_libattachsql_la_SOURCES+= src/asql/group.cc -src_asql_libattachsql_la_SOURCES+= src/asql/query.cc -src_asql_libattachsql_la_SOURCES+= src/asql/statement.cc -src_asql_libattachsql_la_SOURCES+= src/asql/utility.cc - -src_asql_libattachsql_la_LDFLAGS+= -version-info ${LIBATTACHSQL_LIBRARY_VERSION} - -src_asql_libattachsql_la_LIBADD+= @LIBUV_LIB@ -src_asql_libattachsql_la_LIBADD+= @ZLIB_LIB@ -src_asql_libattachsql_la_LIBADD+= @OPENSSL_LIBS@ diff --git a/src/asql/statement.cc b/src/asql/statement.cc deleted file mode 100644 index 1c65d5f..0000000 --- a/src/asql/statement.cc +++ /dev/null @@ -1,1101 +0,0 @@ -/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab: - * Copyright 2014 Hewlett-Packard Development Company, L.P. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. You may obtain - * a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - * - */ - -#include "config.h" -#include "src/asql/common.h" -#include "src/ascore/ascore.h" -#include "src/ascore/statement.h" -#include "src/asql/statement_internal.h" - -bool attachsql_statement_prepare(attachsql_connect_t *con, size_t length, const char *statement, attachsql_error_t **error) -{ - if (con->core_con->status == ASCORE_CON_STATUS_NOT_CONNECTED) - { - con->query_buffer= (char*)statement; - con->query_buffer_length= length; - con->query_buffer_alloc= false; - con->query_buffer_statement= true; - return attachsql_connect(con, error); - } - con->stmt= ascore_stmt_prepare(con->core_con, length, statement); - if (con->stmt == NULL) - { - attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_ALLOC, ATTACHSQL_ERROR_LEVEL_ERROR, "82100", "Allocation failure for statement object"); - return false; - } - return true; -} - -bool attachsql_statement_execute(attachsql_connect_t *con, attachsql_error_t **error) -{ - if (con == NULL) - { - attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_PARAMETER, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", "No connection provided"); - return false; - } - if (con->stmt == NULL) - { - attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_PARAMETER, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", "No statement prepared"); - return false; - } - /* Free anything left over from last exec */ - ascore_command_free(con->core_con); - if (not ascore_stmt_execute(con->stmt)) - { - if (con->core_con->local_errcode == ASRET_BAD_STMT_PARAMETER) - { - attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_PARAMETER, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", "Bad parameter bound to statement"); - return false; - } - else - { - attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_ALLOC, ATTACHSQL_ERROR_LEVEL_ERROR, "82100", "Allocation failure for statement object"); - return false; - } - } - return true; -} - -bool attachsql_statement_reset(attachsql_connect_t *con, attachsql_error_t **error) -{ - if (con == NULL) - { - attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_PARAMETER, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", "No connection provided"); - return false; - } - if (con->stmt == NULL) - { - attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_PARAMETER, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", "No statement prepared"); - return false; - } - - if (ascore_stmt_reset(con->stmt) == ASCORE_COMMAND_STATUS_SEND_FAILED) - { - attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_SERVER_GONE, ATTACHSQL_ERROR_LEVEL_ERROR, "08006", con->core_con->errmsg); - return false; - } - - return true; -} - -bool attachsql_statement_send_long_data(attachsql_connect_t *con, uint16_t param, size_t length, char *data, attachsql_error_t **error) -{ - if (con == NULL) - { - attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_PARAMETER, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", "No statement provided"); - return false; - } - if (con->stmt == NULL) - { - attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_PARAMETER, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", "No statement prepared"); - return false; - } - - if (ascore_stmt_send_long_data(con->stmt, param, length, data) == ASCORE_COMMAND_STATUS_SEND_FAILED) - { - attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_SERVER_GONE, ATTACHSQL_ERROR_LEVEL_ERROR, "08006", con->core_con->errmsg); - return false; - } - - return true; -} - -uint16_t attachsql_statement_get_param_count(attachsql_connect_t *con) -{ - if ((con == NULL) || (con->stmt == NULL)) - { - return 0; - } - return con->stmt->param_count; -} - -bool attachsql_statement_set_int(attachsql_connect_t *con, uint16_t param, int32_t value, attachsql_error_t **error) -{ - return attachsql_statement_set_param(con, ASCORE_COLUMN_TYPE_LONG, param, 0, &value, false, error); -} - -bool attachsql_statement_set_unsigned_int(attachsql_connect_t *con, uint16_t param, uint32_t value, attachsql_error_t **error) -{ - return attachsql_statement_set_param(con, ASCORE_COLUMN_TYPE_LONG, param, 0, &value, true, error); -} - -bool attachsql_statement_set_bigint(attachsql_connect_t *con, uint16_t param, int64_t value, attachsql_error_t **error) -{ - return attachsql_statement_set_param(con, ASCORE_COLUMN_TYPE_LONGLONG, param, 0, &value, false, error); -} - -bool attachsql_statement_set_unsigned_bigint(attachsql_connect_t *con, uint16_t param, uint64_t value, attachsql_error_t **error) -{ - return attachsql_statement_set_param(con, ASCORE_COLUMN_TYPE_LONGLONG, param, 0, &value, true, error); -} - -bool attachsql_statement_set_float(attachsql_connect_t *con, uint16_t param, float value, attachsql_error_t **error) -{ - return attachsql_statement_set_param(con, ASCORE_COLUMN_TYPE_FLOAT, param, 0, &value, false, error); -} - -bool attachsql_statement_set_double(attachsql_connect_t *con, uint16_t param, double value, attachsql_error_t **error) -{ - return attachsql_statement_set_param(con, ASCORE_COLUMN_TYPE_DOUBLE, param, 0, &value, false, error); -} - -bool attachsql_statement_set_string(attachsql_connect_t *con, uint16_t param, size_t length, const char *value, attachsql_error_t **error) -{ - return attachsql_statement_set_param(con, ASCORE_COLUMN_TYPE_STRING, param, length, value, false, error); -} - -bool attachsql_statement_set_binary(attachsql_connect_t *con, uint16_t param, size_t length, const char *value, attachsql_error_t **error) -{ - return attachsql_statement_set_param(con, ASCORE_COLUMN_TYPE_BLOB, param, length, value, false, error); -} - -bool attachsql_statement_set_null(attachsql_connect_t *con, uint16_t param, attachsql_error_t **error) -{ - return attachsql_statement_set_param(con, ASCORE_COLUMN_TYPE_NULL, param, 0, NULL, false, error); -} - -bool attachsql_statement_set_datetime(attachsql_connect_t *con, uint16_t param, uint16_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t minute, uint8_t second, uint32_t microsecond, attachsql_error_t **error) -{ - if ((con == NULL) || (con->stmt == NULL)) - { - attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_PARAMETER, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", "Connection parameter not valid"); - return false; - } - - if (param >= con->stmt->param_count) - { - attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_PARAMETER, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", "Param %d does not exist", param); - return false; - } - con->stmt->param_data[param].data.datetime_data= new ascore_datetime_st; - con->stmt->param_data[param].datetime_alloc= true; - con->stmt->param_data[param].data.datetime_data->year= year; - con->stmt->param_data[param].data.datetime_data->month= month; - con->stmt->param_data[param].data.datetime_data->day= day; - con->stmt->param_data[param].data.datetime_data->hour= hour; - con->stmt->param_data[param].data.datetime_data->minute= minute; - con->stmt->param_data[param].data.datetime_data->second= second; - con->stmt->param_data[param].data.datetime_data->microsecond= microsecond; - con->stmt->param_data[param].type= ASCORE_COLUMN_TYPE_DATETIME; - - return true; -} - -bool attachsql_statement_set_time(attachsql_connect_t *con, uint16_t param, uint8_t hour, uint8_t minute, uint8_t second, uint32_t microsecond, bool is_negative, attachsql_error_t **error) -{ - if ((con == NULL) || (con->stmt == NULL)) - { - attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_PARAMETER, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", "Connection parameter not valid"); - return false; - } - - if (param >= con->stmt->param_count) - { - attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_PARAMETER, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", "Param %d does not exist", param); - return false; - } - con->stmt->param_data[param].data.datetime_data= new ascore_datetime_st; - con->stmt->param_data[param].datetime_alloc= false; - con->stmt->param_data[param].data.datetime_data->hour= hour; - con->stmt->param_data[param].data.datetime_data->minute= minute; - con->stmt->param_data[param].data.datetime_data->second= second; - con->stmt->param_data[param].data.datetime_data->microsecond= microsecond; - con->stmt->param_data[param].data.datetime_data->is_negative= is_negative; - con->stmt->param_data[param].type= ASCORE_COLUMN_TYPE_TIME; - - return true; -} - -bool attachsql_statement_set_param(attachsql_connect_t *con, ascore_column_type_t type, uint16_t param, size_t length, const void *value, bool is_unsigned, attachsql_error_t **error) -{ - if ((con == NULL) || (con->stmt == NULL)) - { - attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_PARAMETER, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", "Connection parameter not valid"); - return false; - } - - if (param >= con->stmt->param_count) - { - attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_PARAMETER, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", "Param %d does not exist", param); - return false; - } - - switch (type) - { - case ASCORE_COLUMN_TYPE_LONG: - con->stmt->param_data[param].data.int_data= *(uint32_t*)value; - con->stmt->param_data[param].is_unsigned= is_unsigned; - con->stmt->param_data[param].type= type; - break; - case ASCORE_COLUMN_TYPE_LONGLONG: - con->stmt->param_data[param].data.bigint_data= *(uint64_t*)value; - con->stmt->param_data[param].is_unsigned= is_unsigned; - con->stmt->param_data[param].type= type; - break; - case ASCORE_COLUMN_TYPE_FLOAT: - con->stmt->param_data[param].data.float_data= *(float*)value; - con->stmt->param_data[param].is_unsigned= false; - con->stmt->param_data[param].type= type; - break; - case ASCORE_COLUMN_TYPE_DOUBLE: - con->stmt->param_data[param].data.double_data= *(double*)value; - con->stmt->param_data[param].is_unsigned= false; - con->stmt->param_data[param].type= type; - break; - case ASCORE_COLUMN_TYPE_STRING: - case ASCORE_COLUMN_TYPE_BLOB: - con->stmt->param_data[param].data.string_data= (char*)value; - con->stmt->param_data[param].length= length; - con->stmt->param_data[param].type= type; - break; - case ASCORE_COLUMN_TYPE_NULL: - con->stmt->param_data[param].type= type;; - break; - /* the following won't happen, but this will keep the compiler happy */ - case ASCORE_COLUMN_TYPE_DECIMAL: - case ASCORE_COLUMN_TYPE_TINY: - case ASCORE_COLUMN_TYPE_SHORT: - case ASCORE_COLUMN_TYPE_TIMESTAMP: - case ASCORE_COLUMN_TYPE_INT24: - case ASCORE_COLUMN_TYPE_DATE: - case ASCORE_COLUMN_TYPE_TIME: - case ASCORE_COLUMN_TYPE_DATETIME: - case ASCORE_COLUMN_TYPE_YEAR: - case ASCORE_COLUMN_TYPE_NEWDATE: - case ASCORE_COLUMN_TYPE_VARCHAR: - case ASCORE_COLUMN_TYPE_BIT: - case ASCORE_COLUMN_TYPE_TIMESTAMP2: - case ASCORE_COLUMN_TYPE_DATETIME2: - case ASCORE_COLUMN_TYPE_TIME2: - case ASCORE_COLUMN_TYPE_NEWDECIMAL: - case ASCORE_COLUMN_TYPE_ENUM: - case ASCORE_COLUMN_TYPE_SET: - case ASCORE_COLUMN_TYPE_TINY_BLOB: - case ASCORE_COLUMN_TYPE_MEDIUM_BLOB: - case ASCORE_COLUMN_TYPE_LONG_BLOB: - case ASCORE_COLUMN_TYPE_VARSTRING: - case ASCORE_COLUMN_TYPE_GEOMETRY: - break; - } - - return true; -} - -bool attachsql_statement_row_get(attachsql_connect_t *con, attachsql_error_t **error) -{ - char *raw_row; - uint16_t column; - uint16_t total_columns; - uint8_t bytes= 0; - uint64_t length; - - if (con == NULL) - { - attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_PARAMETER, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", "Connection parameter not valid"); - return false; - } - - total_columns= con->core_con->result.column_count; - if (con->stmt_row == NULL) - { - con->stmt_row= new (std::nothrow) attachsql_stmt_row_st[total_columns]; - } - - if (con->stmt_row == NULL) - { - attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_ALLOC, ATTACHSQL_ERROR_LEVEL_ERROR, "82100", "Allocation failure for row"); - return false; - } - - raw_row= con->core_con->result.row_data; - /* packet header */ - raw_row++; - con->stmt_null_bitmap_length= ((total_columns+7+2)/8); - con->stmt_null_bitmap= raw_row; - raw_row+= con->stmt_null_bitmap_length; - - for (column= 0; column < total_columns; column++) - { - ascore_column_type_t type= con->core_con->result.columns[column].type; - /* Really complex way of saying "if this is in the NULL bitmap */ - if (con->stmt_null_bitmap[(column+2)/8] & (1 << ((column+2) % 8))) - { - type= ASCORE_COLUMN_TYPE_NULL; - } - switch(type) - { - case ASCORE_COLUMN_TYPE_STRING: - case ASCORE_COLUMN_TYPE_VARCHAR: - case ASCORE_COLUMN_TYPE_VARSTRING: - case ASCORE_COLUMN_TYPE_ENUM: - case ASCORE_COLUMN_TYPE_SET: - case ASCORE_COLUMN_TYPE_LONG_BLOB: - case ASCORE_COLUMN_TYPE_MEDIUM_BLOB: - case ASCORE_COLUMN_TYPE_TINY_BLOB: - case ASCORE_COLUMN_TYPE_BLOB: - case ASCORE_COLUMN_TYPE_GEOMETRY: - case ASCORE_COLUMN_TYPE_BIT: - case ASCORE_COLUMN_TYPE_DECIMAL: - case ASCORE_COLUMN_TYPE_NEWDECIMAL: - length= ascore_unpack_length(raw_row, &bytes, NULL); - raw_row+= bytes; - break; - case ASCORE_COLUMN_TYPE_DATE: - case ASCORE_COLUMN_TYPE_DATETIME: - case ASCORE_COLUMN_TYPE_TIMESTAMP: - case ASCORE_COLUMN_TYPE_TIME: - length= raw_row[0]; - raw_row++; - break; - case ASCORE_COLUMN_TYPE_LONGLONG: - case ASCORE_COLUMN_TYPE_DOUBLE: - length= 8; - break; - case ASCORE_COLUMN_TYPE_LONG: - case ASCORE_COLUMN_TYPE_INT24: - case ASCORE_COLUMN_TYPE_FLOAT: - length= 4; - break; - case ASCORE_COLUMN_TYPE_SHORT: - case ASCORE_COLUMN_TYPE_YEAR: - length= 2; - break; - case ASCORE_COLUMN_TYPE_TINY: - length= 1; - break; - case ASCORE_COLUMN_TYPE_NULL: - /* in NULL bitmask only */ - length= 0; - break; - case ASCORE_COLUMN_TYPE_NEWDATE: - case ASCORE_COLUMN_TYPE_TIMESTAMP2: - case ASCORE_COLUMN_TYPE_DATETIME2: - case ASCORE_COLUMN_TYPE_TIME2: - default: - /* According to MySQL protocol specs, this shouldn't happen */ - attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_UNKNOWN, ATTACHSQL_ERROR_LEVEL_ERROR, "60000", "Bad data in statement result"); - return false; - } - con->stmt_row[column].data= raw_row; - con->stmt_row[column].length= (size_t)length; - con->stmt_row[column].type= type; - raw_row+= length; - } - return true; -} - -int32_t attachsql_statement_get_int(attachsql_connect_t *con, uint16_t column, attachsql_error_t **error) -{ - if (con == NULL) - { - attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_PARAMETER, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", "Connection parameter not valid"); - return 0; - } - - if (con->stmt_row == NULL) - { - attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_PARAMETER, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", "Statement row has not been processed"); - return 0; - } - - if (column >= con->stmt->column_count) - { - attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_PARAMETER, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", "Column %d does not exist", column); - return 0; - } - - attachsql_stmt_row_st *column_data= &con->stmt_row[column]; - switch (column_data->type) - { - case ASCORE_COLUMN_TYPE_TINY: - return (int8_t)column_data->data[0]; - break; - case ASCORE_COLUMN_TYPE_YEAR: - case ASCORE_COLUMN_TYPE_SHORT: - return (int16_t)ascore_unpack_int2(column_data->data); - break; - case ASCORE_COLUMN_TYPE_LONG: - return (int32_t)ascore_unpack_int4(column_data->data); - break; - case ASCORE_COLUMN_TYPE_LONGLONG: - return (int32_t)ascore_unpack_int8(column_data->data); - break; - case ASCORE_COLUMN_TYPE_FLOAT: - float f; - memcpy(&f, column_data->data, 4); - return (int32_t)f; - break; - case ASCORE_COLUMN_TYPE_DOUBLE: - double d; - memcpy(&d, column_data->data, 8); - return (int32_t)d; - break; - case ASCORE_COLUMN_TYPE_NULL: - return 0; - break; - case ASCORE_COLUMN_TYPE_INT24: - return (int32_t)ascore_unpack_int3(column_data->data); - break; - - case ASCORE_COLUMN_TYPE_DECIMAL: - case ASCORE_COLUMN_TYPE_TIMESTAMP: - case ASCORE_COLUMN_TYPE_DATE: - case ASCORE_COLUMN_TYPE_TIME: - case ASCORE_COLUMN_TYPE_DATETIME: - case ASCORE_COLUMN_TYPE_NEWDATE: - case ASCORE_COLUMN_TYPE_VARCHAR: - case ASCORE_COLUMN_TYPE_BIT: - case ASCORE_COLUMN_TYPE_TIMESTAMP2: - case ASCORE_COLUMN_TYPE_DATETIME2: - case ASCORE_COLUMN_TYPE_TIME2: - case ASCORE_COLUMN_TYPE_NEWDECIMAL: - case ASCORE_COLUMN_TYPE_ENUM: - case ASCORE_COLUMN_TYPE_SET: - case ASCORE_COLUMN_TYPE_TINY_BLOB: - case ASCORE_COLUMN_TYPE_MEDIUM_BLOB: - case ASCORE_COLUMN_TYPE_LONG_BLOB: - case ASCORE_COLUMN_TYPE_BLOB: - case ASCORE_COLUMN_TYPE_VARSTRING: - case ASCORE_COLUMN_TYPE_STRING: - case ASCORE_COLUMN_TYPE_GEOMETRY: - attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_PARAMETER, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", "Cannot convert to int"); - return 0; - break; - } - /* Should never hit here, but lets make compilers happy */ - return 0; -} - - -uint32_t attachsql_statement_get_int_unsigned(attachsql_connect_t *con, uint16_t column, attachsql_error_t **error) -{ - if (con == NULL) - { - attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_PARAMETER, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", "Connection parameter not valid"); - return 0; - } - - if (con->stmt_row == NULL) - { - attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_PARAMETER, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", "Statement row has not been processed"); - return 0; - } - - if (column >= con->stmt->column_count) - { - attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_PARAMETER, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", "Column %d does not exist", column); - return 0; - } - - attachsql_stmt_row_st *column_data= &con->stmt_row[column]; - switch (column_data->type) - { - case ASCORE_COLUMN_TYPE_TINY: - return (uint8_t)column_data->data[0]; - break; - case ASCORE_COLUMN_TYPE_YEAR: - case ASCORE_COLUMN_TYPE_SHORT: - return (uint16_t)ascore_unpack_int2(column_data->data); - break; - case ASCORE_COLUMN_TYPE_LONG: - return (uint32_t)ascore_unpack_int4(column_data->data); - break; - case ASCORE_COLUMN_TYPE_LONGLONG: - return (uint32_t)ascore_unpack_int8(column_data->data); - break; - case ASCORE_COLUMN_TYPE_FLOAT: - float f; - memcpy(&f, column_data->data, 4); - return (uint32_t)f; - break; - case ASCORE_COLUMN_TYPE_DOUBLE: - double d; - memcpy(&d, column_data->data, 8); - return (uint32_t)d; - break; - case ASCORE_COLUMN_TYPE_NULL: - return 0; - break; - case ASCORE_COLUMN_TYPE_INT24: - return (uint32_t)ascore_unpack_int3(column_data->data); - break; - - case ASCORE_COLUMN_TYPE_DECIMAL: - case ASCORE_COLUMN_TYPE_TIMESTAMP: - case ASCORE_COLUMN_TYPE_DATE: - case ASCORE_COLUMN_TYPE_TIME: - case ASCORE_COLUMN_TYPE_DATETIME: - case ASCORE_COLUMN_TYPE_NEWDATE: - case ASCORE_COLUMN_TYPE_VARCHAR: - case ASCORE_COLUMN_TYPE_BIT: - case ASCORE_COLUMN_TYPE_TIMESTAMP2: - case ASCORE_COLUMN_TYPE_DATETIME2: - case ASCORE_COLUMN_TYPE_TIME2: - case ASCORE_COLUMN_TYPE_NEWDECIMAL: - case ASCORE_COLUMN_TYPE_ENUM: - case ASCORE_COLUMN_TYPE_SET: - case ASCORE_COLUMN_TYPE_TINY_BLOB: - case ASCORE_COLUMN_TYPE_MEDIUM_BLOB: - case ASCORE_COLUMN_TYPE_LONG_BLOB: - case ASCORE_COLUMN_TYPE_BLOB: - case ASCORE_COLUMN_TYPE_VARSTRING: - case ASCORE_COLUMN_TYPE_STRING: - case ASCORE_COLUMN_TYPE_GEOMETRY: - attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_PARAMETER, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", "Cannot convert to int"); - return 0; - break; - } - /* Should never hit here, but lets make compilers happy */ - return 0; -} - - -int64_t attachsql_statement_get_bigint(attachsql_connect_t *con, uint16_t column, attachsql_error_t **error) -{ - if (con == NULL) - { - attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_PARAMETER, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", "Connection parameter not valid"); - return 0; - } - - if (con->stmt_row == NULL) - { - attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_PARAMETER, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", "Statement row has not been processed"); - return 0; - } - - if (column >= con->stmt->column_count) - { - attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_PARAMETER, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", "Column %d does not exist", column); - return 0; - } - - attachsql_stmt_row_st *column_data= &con->stmt_row[column]; - switch (column_data->type) - { - case ASCORE_COLUMN_TYPE_TINY: - return (int8_t)column_data->data[0]; - break; - case ASCORE_COLUMN_TYPE_YEAR: - case ASCORE_COLUMN_TYPE_SHORT: - return (int16_t)ascore_unpack_int2(column_data->data); - break; - case ASCORE_COLUMN_TYPE_LONG: - return (int32_t)ascore_unpack_int4(column_data->data); - break; - case ASCORE_COLUMN_TYPE_LONGLONG: - return (int64_t)ascore_unpack_int8(column_data->data); - break; - case ASCORE_COLUMN_TYPE_FLOAT: - float f; - memcpy(&f, column_data->data, 4); - return (int64_t)f; - break; - case ASCORE_COLUMN_TYPE_DOUBLE: - double d; - memcpy(&d, column_data->data, 8); - return (int64_t)d; - break; - case ASCORE_COLUMN_TYPE_NULL: - return 0; - break; - case ASCORE_COLUMN_TYPE_INT24: - return (int32_t)ascore_unpack_int3(column_data->data); - break; - - case ASCORE_COLUMN_TYPE_DECIMAL: - case ASCORE_COLUMN_TYPE_TIMESTAMP: - case ASCORE_COLUMN_TYPE_DATE: - case ASCORE_COLUMN_TYPE_TIME: - case ASCORE_COLUMN_TYPE_DATETIME: - case ASCORE_COLUMN_TYPE_NEWDATE: - case ASCORE_COLUMN_TYPE_VARCHAR: - case ASCORE_COLUMN_TYPE_BIT: - case ASCORE_COLUMN_TYPE_TIMESTAMP2: - case ASCORE_COLUMN_TYPE_DATETIME2: - case ASCORE_COLUMN_TYPE_TIME2: - case ASCORE_COLUMN_TYPE_NEWDECIMAL: - case ASCORE_COLUMN_TYPE_ENUM: - case ASCORE_COLUMN_TYPE_SET: - case ASCORE_COLUMN_TYPE_TINY_BLOB: - case ASCORE_COLUMN_TYPE_MEDIUM_BLOB: - case ASCORE_COLUMN_TYPE_LONG_BLOB: - case ASCORE_COLUMN_TYPE_BLOB: - case ASCORE_COLUMN_TYPE_VARSTRING: - case ASCORE_COLUMN_TYPE_STRING: - case ASCORE_COLUMN_TYPE_GEOMETRY: - attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_PARAMETER, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", "Cannot convert to int"); - return 0; - break; - } - /* Should never hit here, but lets make compilers happy */ - return 0; -} - -uint64_t attachsql_statement_get_bigint_unsigned(attachsql_connect_t *con, uint16_t column, attachsql_error_t **error) -{ - if (con == NULL) - { - attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_PARAMETER, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", "Connection parameter not valid"); - return 0; - } - - if (con->stmt_row == NULL) - { - attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_PARAMETER, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", "Statement row has not been processed"); - return 0; - } - - if (column >= con->stmt->column_count) - { - attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_PARAMETER, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", "Column %d does not exist", column); - return 0; - } - - attachsql_stmt_row_st *column_data= &con->stmt_row[column]; - switch (column_data->type) - { - case ASCORE_COLUMN_TYPE_TINY: - return (uint8_t)column_data->data[0]; - break; - case ASCORE_COLUMN_TYPE_YEAR: - case ASCORE_COLUMN_TYPE_SHORT: - return (uint16_t)ascore_unpack_int2(column_data->data); - break; - case ASCORE_COLUMN_TYPE_LONG: - return (uint32_t)ascore_unpack_int4(column_data->data); - break; - case ASCORE_COLUMN_TYPE_LONGLONG: - return (uint64_t)ascore_unpack_int8(column_data->data); - break; - case ASCORE_COLUMN_TYPE_FLOAT: - float f; - memcpy(&f, column_data->data, 4); - return (uint32_t)f; - break; - case ASCORE_COLUMN_TYPE_DOUBLE: - double d; - memcpy(&d, column_data->data, 8); - return (uint32_t)d; - break; - case ASCORE_COLUMN_TYPE_NULL: - return 0; - break; - case ASCORE_COLUMN_TYPE_INT24: - return (uint32_t)ascore_unpack_int3(column_data->data); - break; - - case ASCORE_COLUMN_TYPE_DECIMAL: - case ASCORE_COLUMN_TYPE_TIMESTAMP: - case ASCORE_COLUMN_TYPE_DATE: - case ASCORE_COLUMN_TYPE_TIME: - case ASCORE_COLUMN_TYPE_DATETIME: - case ASCORE_COLUMN_TYPE_NEWDATE: - case ASCORE_COLUMN_TYPE_VARCHAR: - case ASCORE_COLUMN_TYPE_BIT: - case ASCORE_COLUMN_TYPE_TIMESTAMP2: - case ASCORE_COLUMN_TYPE_DATETIME2: - case ASCORE_COLUMN_TYPE_TIME2: - case ASCORE_COLUMN_TYPE_NEWDECIMAL: - case ASCORE_COLUMN_TYPE_ENUM: - case ASCORE_COLUMN_TYPE_SET: - case ASCORE_COLUMN_TYPE_TINY_BLOB: - case ASCORE_COLUMN_TYPE_MEDIUM_BLOB: - case ASCORE_COLUMN_TYPE_LONG_BLOB: - case ASCORE_COLUMN_TYPE_BLOB: - case ASCORE_COLUMN_TYPE_VARSTRING: - case ASCORE_COLUMN_TYPE_STRING: - case ASCORE_COLUMN_TYPE_GEOMETRY: - attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_PARAMETER, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", "Cannot convert to int"); - return 0; - break; - } - /* Should never hit here, but lets make compilers happy */ - return 0; -} - -double attachsql_statement_get_double(attachsql_connect_t *con, uint16_t column, attachsql_error_t **error) -{ - if (con == NULL) - { - attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_PARAMETER, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", "Connection parameter not valid"); - return 0; - } - - if (con->stmt_row == NULL) - { - attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_PARAMETER, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", "Statement row has not been processed"); - return 0; - } - - if (column >= con->stmt->column_count) - { - attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_PARAMETER, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", "Column %d does not exist", column); - return 0; - } - - attachsql_stmt_row_st *column_data= &con->stmt_row[column]; - switch (column_data->type) - { - case ASCORE_COLUMN_TYPE_TINY: - return (double)column_data->data[0]; - break; - case ASCORE_COLUMN_TYPE_YEAR: - case ASCORE_COLUMN_TYPE_SHORT: - return (double)ascore_unpack_int2(column_data->data); - break; - case ASCORE_COLUMN_TYPE_LONG: - return (double)ascore_unpack_int4(column_data->data); - break; - case ASCORE_COLUMN_TYPE_LONGLONG: - return (double)ascore_unpack_int8(column_data->data); - break; - case ASCORE_COLUMN_TYPE_FLOAT: - float f; - memcpy(&f, column_data->data, 4); - return (double)f; - break; - case ASCORE_COLUMN_TYPE_DOUBLE: - double d; - memcpy(&d, column_data->data, 8); - return d; - break; - case ASCORE_COLUMN_TYPE_NULL: - return 0; - break; - case ASCORE_COLUMN_TYPE_INT24: - return (double)ascore_unpack_int3(column_data->data); - break; - - case ASCORE_COLUMN_TYPE_DECIMAL: - case ASCORE_COLUMN_TYPE_TIMESTAMP: - case ASCORE_COLUMN_TYPE_DATE: - case ASCORE_COLUMN_TYPE_TIME: - case ASCORE_COLUMN_TYPE_DATETIME: - case ASCORE_COLUMN_TYPE_NEWDATE: - case ASCORE_COLUMN_TYPE_VARCHAR: - case ASCORE_COLUMN_TYPE_BIT: - case ASCORE_COLUMN_TYPE_TIMESTAMP2: - case ASCORE_COLUMN_TYPE_DATETIME2: - case ASCORE_COLUMN_TYPE_TIME2: - case ASCORE_COLUMN_TYPE_NEWDECIMAL: - case ASCORE_COLUMN_TYPE_ENUM: - case ASCORE_COLUMN_TYPE_SET: - case ASCORE_COLUMN_TYPE_TINY_BLOB: - case ASCORE_COLUMN_TYPE_MEDIUM_BLOB: - case ASCORE_COLUMN_TYPE_LONG_BLOB: - case ASCORE_COLUMN_TYPE_BLOB: - case ASCORE_COLUMN_TYPE_VARSTRING: - case ASCORE_COLUMN_TYPE_STRING: - case ASCORE_COLUMN_TYPE_GEOMETRY: - attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_PARAMETER, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", "Cannot convert to int"); - return 0; - break; - } - /* Should never hit here, but lets make compilers happy */ - return 0; -} - -float attachsql_statement_get_float(attachsql_connect_t *con, uint16_t column, attachsql_error_t **error) -{ - if (con == NULL) - { - attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_PARAMETER, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", "Connection parameter not valid"); - return 0; - } - - if (con->stmt_row == NULL) - { - attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_PARAMETER, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", "Statement row has not been processed"); - return 0; - } - - if (column >= con->stmt->column_count) - { - attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_PARAMETER, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", "Column %d does not exist", column); - return 0; - } - - attachsql_stmt_row_st *column_data= &con->stmt_row[column]; - switch (column_data->type) - { - case ASCORE_COLUMN_TYPE_TINY: - return (float)column_data->data[0]; - break; - case ASCORE_COLUMN_TYPE_YEAR: - case ASCORE_COLUMN_TYPE_SHORT: - return (float)ascore_unpack_int2(column_data->data); - break; - case ASCORE_COLUMN_TYPE_LONG: - return (float)ascore_unpack_int4(column_data->data); - break; - case ASCORE_COLUMN_TYPE_LONGLONG: - return (float)ascore_unpack_int8(column_data->data); - break; - case ASCORE_COLUMN_TYPE_FLOAT: - float f; - memcpy(&f, column_data->data, 4); - return f; - break; - case ASCORE_COLUMN_TYPE_DOUBLE: - double d; - memcpy(&d, column_data->data, 8); - return (float)d; - break; - case ASCORE_COLUMN_TYPE_NULL: - return 0; - break; - case ASCORE_COLUMN_TYPE_INT24: - return (float)ascore_unpack_int3(column_data->data); - break; - - case ASCORE_COLUMN_TYPE_DECIMAL: - case ASCORE_COLUMN_TYPE_TIMESTAMP: - case ASCORE_COLUMN_TYPE_DATE: - case ASCORE_COLUMN_TYPE_TIME: - case ASCORE_COLUMN_TYPE_DATETIME: - case ASCORE_COLUMN_TYPE_NEWDATE: - case ASCORE_COLUMN_TYPE_VARCHAR: - case ASCORE_COLUMN_TYPE_BIT: - case ASCORE_COLUMN_TYPE_TIMESTAMP2: - case ASCORE_COLUMN_TYPE_DATETIME2: - case ASCORE_COLUMN_TYPE_TIME2: - case ASCORE_COLUMN_TYPE_NEWDECIMAL: - case ASCORE_COLUMN_TYPE_ENUM: - case ASCORE_COLUMN_TYPE_SET: - case ASCORE_COLUMN_TYPE_TINY_BLOB: - case ASCORE_COLUMN_TYPE_MEDIUM_BLOB: - case ASCORE_COLUMN_TYPE_LONG_BLOB: - case ASCORE_COLUMN_TYPE_BLOB: - case ASCORE_COLUMN_TYPE_VARSTRING: - case ASCORE_COLUMN_TYPE_STRING: - case ASCORE_COLUMN_TYPE_GEOMETRY: - attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_PARAMETER, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", "Cannot convert to int"); - return 0; - break; - } - /* Should never hit here, but lets make compilers happy */ - return 0; -} - - -char *attachsql_statement_get_char(attachsql_connect_t *con, uint16_t column, size_t *length, attachsql_error_t **error) -{ - if (con == NULL) - { - attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_PARAMETER, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", "Connection parameter not valid"); - return NULL; - } - - if (con->stmt_row == NULL) - { - attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_PARAMETER, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", "Statement row has not been processed"); - return NULL; - } - - if (column >= con->stmt->column_count) - { - attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_PARAMETER, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", "Column %d does not exist", column); - return NULL; - } - - if (length == NULL) - { - attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_PARAMETER, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", "Length parameter not valid"); - return NULL; - } - - attachsql_stmt_row_st *column_data= &con->stmt_row[column]; - ascore_datetime_st datetime; - switch (column_data->type) - { - case ASCORE_COLUMN_TYPE_TINY: - if (con->core_con->result.columns[column].flags & ASCORE_COLUMN_FLAGS_UNSIGNED) - { - *length= snprintf(con->stmt_tmp_buffer, ATTACHSQL_STMT_CHAR_BUFFER_SIZE, "%" PRIu8, column_data->data[0]); - } - else - { - *length= snprintf(con->stmt_tmp_buffer, ATTACHSQL_STMT_CHAR_BUFFER_SIZE, "%" PRId8, column_data->data[0]); - } - return con->stmt_tmp_buffer; - break; - case ASCORE_COLUMN_TYPE_YEAR: - case ASCORE_COLUMN_TYPE_SHORT: - if (con->core_con->result.columns[column].flags & ASCORE_COLUMN_FLAGS_UNSIGNED) - { - *length= snprintf(con->stmt_tmp_buffer, ATTACHSQL_STMT_CHAR_BUFFER_SIZE, "%" PRIu16, ascore_unpack_int2(column_data->data)); - } - else - { - *length= snprintf(con->stmt_tmp_buffer, ATTACHSQL_STMT_CHAR_BUFFER_SIZE, "%" PRId16, ascore_unpack_int2(column_data->data)); - } - return con->stmt_tmp_buffer; - break; - case ASCORE_COLUMN_TYPE_LONG: - if (con->core_con->result.columns[column].flags & ASCORE_COLUMN_FLAGS_UNSIGNED) - { - *length= snprintf(con->stmt_tmp_buffer, ATTACHSQL_STMT_CHAR_BUFFER_SIZE, "%" PRIu32, ascore_unpack_int4(column_data->data)); - } - else - { - *length= snprintf(con->stmt_tmp_buffer, ATTACHSQL_STMT_CHAR_BUFFER_SIZE, "%" PRId32, ascore_unpack_int4(column_data->data)); - } - return con->stmt_tmp_buffer; - break; - case ASCORE_COLUMN_TYPE_LONGLONG: - if (con->core_con->result.columns[column].flags & ASCORE_COLUMN_FLAGS_UNSIGNED) - { - *length= snprintf(con->stmt_tmp_buffer, ATTACHSQL_STMT_CHAR_BUFFER_SIZE, "%" PRIu64, ascore_unpack_int8(column_data->data)); - } - else - { - *length= snprintf(con->stmt_tmp_buffer, ATTACHSQL_STMT_CHAR_BUFFER_SIZE, "%" PRId64, ascore_unpack_int8(column_data->data)); - } - return con->stmt_tmp_buffer; - break; - case ASCORE_COLUMN_TYPE_FLOAT: - float f; - memcpy(&f, column_data->data, 4); - *length= snprintf(con->stmt_tmp_buffer, ATTACHSQL_STMT_CHAR_BUFFER_SIZE, "%f", f); - return con->stmt_tmp_buffer; - break; - case ASCORE_COLUMN_TYPE_DOUBLE: - double d; - memcpy(&d, column_data->data, 8); - *length= snprintf(con->stmt_tmp_buffer, ATTACHSQL_STMT_CHAR_BUFFER_SIZE, "%f", d); - return con->stmt_tmp_buffer; - break; - case ASCORE_COLUMN_TYPE_NULL: - return NULL; - break; - case ASCORE_COLUMN_TYPE_INT24: - if (con->core_con->result.columns[column].flags & ASCORE_COLUMN_FLAGS_UNSIGNED) - { - *length= snprintf(con->stmt_tmp_buffer, ATTACHSQL_STMT_CHAR_BUFFER_SIZE, "%" PRIu32, ascore_unpack_int3(column_data->data)); - } - else - { - *length= snprintf(con->stmt_tmp_buffer, ATTACHSQL_STMT_CHAR_BUFFER_SIZE, "%" PRId32, ascore_unpack_int3(column_data->data)); - } - return con->stmt_tmp_buffer; - break; - - case ASCORE_COLUMN_TYPE_DECIMAL: - case ASCORE_COLUMN_TYPE_VARCHAR: - case ASCORE_COLUMN_TYPE_BIT: - case ASCORE_COLUMN_TYPE_NEWDECIMAL: - case ASCORE_COLUMN_TYPE_ENUM: - case ASCORE_COLUMN_TYPE_SET: - case ASCORE_COLUMN_TYPE_TINY_BLOB: - case ASCORE_COLUMN_TYPE_MEDIUM_BLOB: - case ASCORE_COLUMN_TYPE_LONG_BLOB: - case ASCORE_COLUMN_TYPE_BLOB: - case ASCORE_COLUMN_TYPE_VARSTRING: - case ASCORE_COLUMN_TYPE_STRING: - case ASCORE_COLUMN_TYPE_GEOMETRY: - *length= column_data->length; - return column_data->data; - break; - case ASCORE_COLUMN_TYPE_TIME: - ascore_unpack_time(column_data->data, column_data->length, &datetime); - *length= snprintf(con->stmt_tmp_buffer, ATTACHSQL_STMT_CHAR_BUFFER_SIZE, "%s%02u:%02" PRIu8 ":%02" PRIu8, (datetime.is_negative) ? "-" : "", datetime.hour + 24 * datetime.day, datetime.minute, datetime.second); - if (datetime.microsecond) - { - *length+= snprintf(con->stmt_tmp_buffer+(*length), ATTACHSQL_STMT_CHAR_BUFFER_SIZE-(*length), ".%06" PRIu32, datetime.microsecond); - } - return con->stmt_tmp_buffer; - break; - case ASCORE_COLUMN_TYPE_TIMESTAMP: - case ASCORE_COLUMN_TYPE_DATE: - case ASCORE_COLUMN_TYPE_DATETIME: - ascore_unpack_datetime(column_data->data, column_data->length, &datetime); - *length= snprintf(con->stmt_tmp_buffer, ATTACHSQL_STMT_CHAR_BUFFER_SIZE, "%04" PRIu16 "-%02" PRIu8 "-%02" PRIu32, datetime.year, datetime.month, datetime.day); - if (column_data->type == ASCORE_COLUMN_TYPE_DATE) - { - return con->stmt_tmp_buffer; - } - *length+= snprintf(con->stmt_tmp_buffer+(*length), ATTACHSQL_STMT_CHAR_BUFFER_SIZE-(*length), " %02" PRIu16 ":%02" PRIu8 ":%02" PRIu8, datetime.hour, datetime.minute, datetime.second); - - if (datetime.microsecond) - { - *length+= snprintf(con->stmt_tmp_buffer+(*length), ATTACHSQL_STMT_CHAR_BUFFER_SIZE-(*length), ".%06" PRIu32, datetime.microsecond); - } - return con->stmt_tmp_buffer; - break; - case ASCORE_COLUMN_TYPE_NEWDATE: - case ASCORE_COLUMN_TYPE_TIMESTAMP2: - case ASCORE_COLUMN_TYPE_DATETIME2: - case ASCORE_COLUMN_TYPE_TIME2: - attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_PARAMETER, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", "Cannot convert to int"); - return NULL; - break; - } - /* Should never hit here, but lets make compilers happy */ - return NULL; -} - -void attachsql_statement_close(attachsql_connect_t *con) -{ - if (con == NULL) - { - return; - } - - if (con->stmt_row != NULL) - { - delete[] con->stmt_row; - } - con->stmt_row= NULL; - ascore_stmt_destroy(con->stmt); - con->stmt= NULL; -} - -attachsql_column_type_t attachsql_statement_get_column_type(attachsql_connect_t *con, uint16_t column) -{ - if (con == NULL) - { - return ATTACHSQL_COLUMN_TYPE_ERROR; - } - - if (column >= con->core_con->result.column_count) - { - return ATTACHSQL_COLUMN_TYPE_ERROR; - } - - return (attachsql_column_type_t)con->core_con->result.columns[column].type; -} - -void attachsql_statement_row_next(attachsql_connect_t *con) -{ - if (con == NULL) - { - return; - } - ascore_get_next_row(con->core_con); -} - -uint16_t attachsql_statement_get_column_count(attachsql_connect_t *con) -{ - if (con == NULL) - { - return 0; - } - - return con->core_con->result.column_count; -} - diff --git a/src/asql/statement_internal.h b/src/asql/statement_internal.h deleted file mode 100644 index 32e8fce..0000000 --- a/src/asql/statement_internal.h +++ /dev/null @@ -1,31 +0,0 @@ -/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab: - * Copyright 2014 Hewlett-Packard Development Company, L.P. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. You may obtain - * a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - * - */ - -#pragma once - -#include "src/ascore/ascore.h" - -#ifdef __cplusplus -extern "C" { -#endif - -bool attachsql_statement_set_param(attachsql_connect_t *con, ascore_column_type_t type, uint16_t param, size_t length, const void *value, bool is_unsigned, attachsql_error_t **error); - -#ifdef __cplusplus -} -#endif - diff --git a/src/asql/structs_internal.h b/src/asql/structs_internal.h deleted file mode 100644 index a7c53a1..0000000 --- a/src/asql/structs_internal.h +++ /dev/null @@ -1,125 +0,0 @@ -/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab: - * Copyright 2014 Hewlett-Packard Development Company, L.P. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. You may obtain - * a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - * - */ - -#pragma once - -#include "src/ascore/ascore.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define ATTACHSQL_BUFFER_ROW_ALLOC_SIZE 100 -#define ATTACHSQL_STMT_CHAR_BUFFER_SIZE 40 - -struct attachsql_stmt_row_st -{ - char *data; - size_t length; - ascore_column_type_t type; - - attachsql_stmt_row_st() : - data(NULL), - length(0), - type(ASCORE_COLUMN_TYPE_NULL) - { } -}; - -struct attachsql_connect_t -{ - ascon_st *core_con; - attachsql_callback_fn *callback_fn; - void *callback_context; - char *query_buffer; - size_t query_buffer_length; - bool query_buffer_alloc; - bool query_buffer_statement; - bool in_query; - bool buffer_rows; - attachsql_query_column_st *columns; - attachsql_query_row_st *row; - attachsql_query_row_st **row_buffer; - uint64_t row_buffer_alloc_size; - uint64_t row_buffer_count; - uint64_t row_buffer_position; - bool all_rows_buffered; - ascore_stmt_st *stmt; - attachsql_stmt_row_st *stmt_row; - char *stmt_null_bitmap; - uint16_t stmt_null_bitmap_length; - char stmt_tmp_buffer[ATTACHSQL_STMT_CHAR_BUFFER_SIZE]; - - attachsql_connect_t(): - core_con(NULL), - callback_fn(NULL), - callback_context(NULL), - query_buffer(NULL), - query_buffer_length(0), - query_buffer_alloc(false), - query_buffer_statement(false), - in_query(false), - buffer_rows(false), - columns(NULL), - row(NULL), - row_buffer(NULL), - row_buffer_alloc_size(0), - row_buffer_count(0), - row_buffer_position(0), - all_rows_buffered(false), - stmt(NULL), - stmt_row(NULL), - stmt_null_bitmap(NULL), - stmt_null_bitmap_length(0) - { - stmt_tmp_buffer[0]= '\0'; - } -}; - -struct attachsql_error_t -{ - int code; - char msg[ATTACHSQL_MESSAGE_SIZE]; - char sqlstate[ATTACHSQL_SQLSTATE_SIZE]; - attachsql_error_level_t level; - - attachsql_error_t() : - code(0), - level(ATTACHSQL_ERROR_LEVEL_NOTICE) - { - msg[0]= '\0'; - sqlstate[0]= '\0'; - } -}; - -struct attachsql_group_t -{ - attachsql_connect_t **connections; - size_t connection_count; - uv_loop_t *loop; - - attachsql_group_t() : - connections(NULL), - connection_count(0), - loop(NULL) - { } - -}; - -#ifdef __cplusplus -} -#endif - diff --git a/src/ascore/buffer.cc b/src/buffer.cc similarity index 82% rename from src/ascore/buffer.cc rename to src/buffer.cc index 0dc9fae..ac6f2ae 100644 --- a/src/ascore/buffer.cc +++ b/src/buffer.cc @@ -23,7 +23,7 @@ #include #include -buffer_st *ascore_buffer_create() +buffer_st *attachsql_buffer_create() { buffer_st *buffer; @@ -33,7 +33,7 @@ buffer_st *ascore_buffer_create() return NULL; } - buffer->buffer= (char*)malloc(ASCORE_DEFAULT_BUFFER_SIZE); + buffer->buffer= (char*)malloc(ATTACHSQL_DEFAULT_BUFFER_SIZE); if (buffer->buffer == NULL) { delete buffer; @@ -42,18 +42,18 @@ buffer_st *ascore_buffer_create() buffer->buffer_read_ptr= buffer->buffer; buffer->buffer_write_ptr= buffer->buffer; - buffer->buffer_size= ASCORE_DEFAULT_BUFFER_SIZE; + buffer->buffer_size= ATTACHSQL_DEFAULT_BUFFER_SIZE; return buffer; } -void ascore_buffer_free(buffer_st *buffer) +void attachsql_buffer_free(buffer_st *buffer) { free(buffer->buffer); delete buffer; } -size_t ascore_buffer_get_available(buffer_st *buffer) +size_t attachsql_buffer_get_available(buffer_st *buffer) { if (buffer == NULL) { @@ -62,14 +62,14 @@ size_t ascore_buffer_get_available(buffer_st *buffer) return buffer->buffer_size - ((size_t)(buffer->buffer_read_ptr - buffer->buffer) + buffer->buffer_used); } -asret_t ascore_buffer_increase(buffer_st *buffer) +attachsql_ret_t attachsql_buffer_increase(buffer_st *buffer) { if (buffer == NULL) { - return ASRET_PARAMETER_ERROR; + return ATTACHSQL_RET_PARAMETER_ERROR; } - size_t buffer_available= ascore_buffer_get_available(buffer); + size_t buffer_available= attachsql_buffer_get_available(buffer); /* if the we have lots of stale data just shift * algorithm for this at the moment is if only half the buffer is available @@ -97,7 +97,7 @@ asret_t ascore_buffer_increase(buffer_st *buffer) char *realloc_buffer= (char*)realloc(buffer->buffer, new_size); if (realloc_buffer == NULL) { - return ASRET_OUT_OF_MEMORY_ERROR; + return ATTACHSQL_RET_OUT_OF_MEMORY_ERROR; } buffer->buffer_size= new_size; buffer->buffer= realloc_buffer; @@ -107,22 +107,22 @@ asret_t ascore_buffer_increase(buffer_st *buffer) buffer->packet_end_ptr= realloc_buffer + packet_end_size; } - return ASRET_OK; + return ATTACHSQL_RET_OK; } /* Moves the write pointer and returns the amount of unread data in the buffer */ -void ascore_buffer_move_write_ptr(buffer_st *buffer, size_t len) +void attachsql_buffer_move_write_ptr(buffer_st *buffer, size_t len) { buffer->buffer_write_ptr+= len; buffer->buffer_used+= len; } -size_t ascore_buffer_unread_data(buffer_st *buffer) +size_t attachsql_buffer_unread_data(buffer_st *buffer) { return (size_t)(buffer->buffer_write_ptr - buffer->buffer_read_ptr); } -void ascore_buffer_packet_read_end(buffer_st *buffer) +void attachsql_buffer_packet_read_end(buffer_st *buffer) { // If the buffer is now empty, reset it. Otherwise make sure the read ptr // points to the end of the packet. Should maybe move this to buffer.cc diff --git a/src/ascore/buffer.h b/src/buffer.h similarity index 72% rename from src/ascore/buffer.h rename to src/buffer.h index 5b053e0..2914189 100644 --- a/src/ascore/buffer.h +++ b/src/buffer.h @@ -26,7 +26,7 @@ extern "C" { #endif -#define ASCORE_DEFAULT_BUFFER_SIZE 1024*1024 +#define ATTACHSQL_DEFAULT_BUFFER_SIZE 1024*1024 struct buffer_st { @@ -47,13 +47,13 @@ struct buffer_st { } }; -buffer_st *ascore_buffer_create(); -void ascore_buffer_free(buffer_st *buffer); -size_t ascore_buffer_get_available(buffer_st *buffer); -asret_t ascore_buffer_increase(buffer_st *buffer); -void ascore_buffer_move_write_ptr(buffer_st *buffer, size_t len); -size_t ascore_buffer_unread_data(buffer_st *buffer); -void ascore_buffer_packet_read_end(buffer_st *buffer); +buffer_st *attachsql_buffer_create(); +void attachsql_buffer_free(buffer_st *buffer); +size_t attachsql_buffer_get_available(buffer_st *buffer); +attachsql_ret_t attachsql_buffer_increase(buffer_st *buffer); +void attachsql_buffer_move_write_ptr(buffer_st *buffer, size_t len); +size_t attachsql_buffer_unread_data(buffer_st *buffer); +void attachsql_buffer_packet_read_end(buffer_st *buffer); #ifdef __cplusplus } diff --git a/src/command.cc b/src/command.cc new file mode 100644 index 0000000..52610b2 --- /dev/null +++ b/src/command.cc @@ -0,0 +1,177 @@ +/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab: + * Copyright 2014 Hewlett-Packard Development Company, L.P. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. You may obtain + * a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + */ + +#include "command.h" +#include "net.h" + +#ifdef HAVE_ZLIB +attachsql_command_status_t attachsql_command_send_compressed(attachsql_connect_t *con, attachsql_command_t command, char *data, size_t length) +{ + attachsql_send_compressed_packet(con, data, length, command); + if (con->status == ATTACHSQL_CON_STATUS_IDLE) + { + if (command == ATTACHSQL_COMMAND_STMT_PREPARE) + { + attachsql_packet_queue_push(con, ATTACHSQL_PACKET_TYPE_PREPARE_RESPONSE); + } + else + { + attachsql_packet_queue_push(con, ATTACHSQL_PACKET_TYPE_RESPONSE); + } + con->command_status= ATTACHSQL_COMMAND_STATUS_SEND; + con->status= ATTACHSQL_CON_STATUS_BUSY; + return ATTACHSQL_COMMAND_STATUS_SEND; + } + return con->command_status; +} +#endif + +attachsql_command_status_t attachsql_command_send(attachsql_connect_t *con, attachsql_command_t command, char *data, size_t length) +{ + uv_buf_t send_buffer[3]; + int ret; + + /* Reset a bunch of internals */ + con->result.current_column= 0; + con->affected_rows= 0; + con->insert_id= 0; + con->server_status= 0; + con->warning_count= 0; + con->server_errno= 0; + + asdebug("Sending command 0x%02X to server", command); + con->local_errcode= ATTACHSQL_RET_OK; + con->errmsg[0]= '\0'; + + attachsql_pack_int3(con->packet_header, length + 1 + con->write_buffer_extra); + con->packet_number= 0; + con->packet_header[3] = con->packet_number; + +#ifdef HAVE_ZLIB + if (con->client_capabilities & ATTACHSQL_CAPABILITY_COMPRESS) + { + return attachsql_command_send_compressed(con, command, data, length); + } +#endif + + con->write_buffer[0]= command; + send_buffer[0].base= con->packet_header; + send_buffer[0].len= 4; + send_buffer[1].base= con->write_buffer; + send_buffer[1].len= 1 + con->write_buffer_extra; + con->write_buffer_extra= 0; + if (length > 0) + { + send_buffer[2].base= data; + send_buffer[2].len= length; + asdebug("Sending %zd bytes with %zd command bytes to server", length, send_buffer[1].len); + asdebug_hex(data, length); +#ifdef HAVE_OPENSSL + if (con->ssl.handshake_done) + { + ret= attachsql_ssl_buffer_write(con, send_buffer, 3); + } + else +#endif + { + uv_write_t *req= new (std::nothrow) uv_write_t; + ret= uv_write(req, con->uv_objects.stream, send_buffer, 3, on_write); + } + } + else + { + asdebug("Sending %zd command bytes with no data", send_buffer[1].len); +#ifdef HAVE_OPENSSL + if (con->ssl.handshake_done) + { + ret= attachsql_ssl_buffer_write(con, send_buffer, 2); + } + else +#endif + { + uv_write_t *req= new (std::nothrow) uv_write_t; + ret= uv_write(req, con->uv_objects.stream, send_buffer, 2, on_write); + } + } + if (ret < 0) + { + con->local_errcode= ATTACHSQL_RET_NET_WRITE_ERROR; + asdebug("Write fail: %s", uv_err_name(ret)); + con->command_status= ATTACHSQL_COMMAND_STATUS_SEND_FAILED; + con->next_packet_queue_used= 0; + con->local_errcode= ATTACHSQL_RET_NET_WRITE_ERROR; + snprintf(con->errmsg, ATTACHSQL_ERROR_BUFFER_SIZE, "Query send failed: %s", uv_err_name(ret)); + return con->command_status; + } + + if (command == ATTACHSQL_COMMAND_STMT_PREPARE) + { + attachsql_packet_queue_push(con, ATTACHSQL_PACKET_TYPE_PREPARE_RESPONSE); + } + else if ((command == ATTACHSQL_COMMAND_STMT_RESET) || (command == ATTACHSQL_COMMAND_STMT_CLOSE)) + { + /*DO NOTHING*/ + } + else + { + attachsql_packet_queue_push(con, ATTACHSQL_PACKET_TYPE_RESPONSE); + } + con->command_status= ATTACHSQL_COMMAND_STATUS_SEND; + con->status= ATTACHSQL_CON_STATUS_BUSY; + return ATTACHSQL_COMMAND_STATUS_SEND; +} + +attachsql_command_status_t attachsql_get_next_row(attachsql_connect_t *con) +{ + attachsql_buffer_packet_read_end(con->read_buffer); + attachsql_packet_queue_push(con, ATTACHSQL_PACKET_TYPE_ROW); + con->command_status= ATTACHSQL_COMMAND_STATUS_READ_ROW; + attachsql_con_process_packets(con); + return con->command_status; +} + +bool attachsql_command_next_result(attachsql_connect_t *con) +{ + if (con == NULL) + { + return false; + } + if (con->server_status & ATTACHSQL_SERVER_STATUS_MORE_RESULTS) + { + /* Reset a bunch of internals */ + con->result.current_column= 0; + con->affected_rows= 0; + con->insert_id= 0; + con->server_status= 0; + con->warning_count= 0; + con->server_errno= 0; + attachsql_packet_queue_push(con, ATTACHSQL_PACKET_TYPE_RESPONSE); + con->command_status= ATTACHSQL_COMMAND_STATUS_READ_RESPONSE; + con->status= ATTACHSQL_CON_STATUS_BUSY; + return true; + } + return false; +} + +void attachsql_command_free(attachsql_connect_t *con) +{ + if (con->result.columns != NULL) + { + delete[] con->result.columns; + } + con->result.columns= NULL; +} diff --git a/src/ascore/command.h b/src/command.h similarity index 64% rename from src/ascore/command.h rename to src/command.h index 182ae63..64b6550 100644 --- a/src/ascore/command.h +++ b/src/command.h @@ -26,16 +26,16 @@ extern "C" { #endif #ifdef HAVE_ZLIB -ascore_command_status_t ascore_command_send_compressed(ascon_st *con, ascore_command_t command, char *data, size_t length); +attachsql_command_status_t attachsql_command_send_compressed(attachsql_connect_t *con, attachsql_command_t command, char *data, size_t length); #endif -ascore_command_status_t ascore_command_send(ascon_st *con, ascore_command_t command, char *data, size_t length); +attachsql_command_status_t attachsql_command_send(attachsql_connect_t *con, attachsql_command_t command, char *data, size_t length); -ascore_command_status_t ascore_get_next_row(ascon_st *con); +attachsql_command_status_t attachsql_get_next_row(attachsql_connect_t *con); -bool ascore_command_next_result(ascon_st *con); +bool attachsql_command_next_result(attachsql_connect_t *con); -void ascore_command_free(ascon_st *con); +void attachsql_command_free(attachsql_connect_t *con); #ifdef __cplusplus } diff --git a/src/ascore/common.h b/src/common.h similarity index 87% rename from src/ascore/common.h rename to src/common.h index 1e808e4..9a8fbf0 100644 --- a/src/ascore/common.h +++ b/src/common.h @@ -17,14 +17,21 @@ #pragma once +#ifdef __cplusplus +#include +#endif + #include "debug.h" #include "return.h" #include "pack_macros.h" #include "pack.h" #include "constants.h" #include "structs.h" +#include +#include "error_internal.h" #include #include #include #include #include +#include diff --git a/src/connect.cc b/src/connect.cc new file mode 100644 index 0000000..43ef690 --- /dev/null +++ b/src/connect.cc @@ -0,0 +1,973 @@ +/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab: + * Copyright 2014 Hewlett-Packard Development Company, L.P. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. You may obtain + * a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + */ + +#include "config.h" +#include "common.h" +#include "connect.h" +#include "sha1.h" +#include "net.h" +#include "query_internal.h" +#include +#include +#ifdef HAVE_OPENSSL +# include +#endif + +attachsql_connect_t *attachsql_connect_create(const char *host, in_port_t port, const char *user, const char *pass, const char *schema, attachsql_error_t **error) +{ + attachsql_connect_t *con; + + con = new (std::nothrow) attachsql_connect_t; + if (con == NULL) + { + attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_ALLOC, ATTACHSQL_ERROR_LEVEL_ERROR, "82100", "Allocation failure for connection object"); + return NULL; + } + + con->host= host; + con->port= port; + if ((user == NULL) or (strlen(user) > ATTACHSQL_MAX_USER_SIZE)) + { + con->local_errcode= ATTACHSQL_RET_USER_TOO_LONG; + con->status= ATTACHSQL_CON_STATUS_PARAMETER_ERROR; + attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_PARAMETER, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", "User name too long"); + attachsql_connect_destroy(con); + return NULL; + } + con->user= user; + // We don't really care how long pass is since we itterate though it during + // SHA1 passes. Needs to be nul terminated. NULL is also acceptable. + con->pass= pass; + if ((schema == NULL) or (strlen(schema) > ATTACHSQL_MAX_SCHEMA_SIZE)) + { + con->local_errcode= ATTACHSQL_RET_SCHEMA_TOO_LONG; + con->status= ATTACHSQL_CON_STATUS_PARAMETER_ERROR; + attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_PARAMETER, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", "Schema too long"); + attachsql_connect_destroy(con); + return NULL; + } + con->schema= schema; + + return con; +} + +void attachsql_connect_destroy(attachsql_connect_t *con) +{ + if (con == NULL) + { + return; + } + + if (con->in_query) + { + attachsql_query_close(con); + } + + if (con->read_buffer != NULL) + { + attachsql_buffer_free(con->read_buffer); + } + + if (con->read_buffer_compress != NULL) + { + attachsql_buffer_free(con->read_buffer_compress); + } + + if (con->uncompressed_buffer != NULL) + { + free(con->uncompressed_buffer); + } + + if (con->compressed_buffer != NULL) + { + free(con->compressed_buffer); + } + + if (con->next_packet_queue != NULL) + { + free(con->next_packet_queue); + } + +#ifdef HAVE_OPENSSL + if (con->ssl.bio_buffer != NULL) + { + free(con->ssl.bio_buffer); + } + if (con->ssl.write_buffer != NULL) + { + attachsql_buffer_free(con->ssl.write_buffer); + } + /* This frees BIOs as well */ + if (con->ssl.ssl != NULL) + { + SSL_free(con->ssl.ssl); + } + if (con->ssl.context != NULL) + { + SSL_CTX_free(con->ssl.context); + } +#endif + // On a net error we already closed the connection + if ((con->uv_objects.stream != NULL) and (con->status != ATTACHSQL_CON_STATUS_NET_ERROR)) + { + uv_check_stop(&con->uv_objects.check); + if (con->pool == NULL) + { + uv_walk(con->uv_objects.loop, loop_walk_cb, NULL); + uv_run(con->uv_objects.loop, UV_RUN_DEFAULT); + } + } + if (con->pool == NULL) + { + int ret= uv_loop_close(con->uv_objects.loop); + assert(ret == 0); + delete con->uv_objects.loop; + delete con; + } +} + +void loop_walk_cb(uv_handle_t *handle, void *arg) +{ + (void) arg; + uv_close(handle, NULL); +} + +void on_resolved(uv_getaddrinfo_t *resolver, int status, struct addrinfo *res) +{ + attachsql_connect_t *con= (attachsql_connect_t *)resolver->data; + + asdebug("Resolver callback"); + if (status < 0) + { + asdebug("DNS lookup failure: %s", uv_err_name(status)); + con->status= ATTACHSQL_CON_STATUS_CONNECT_FAILED; + con->local_errcode= ATTACHSQL_RET_DNS_ERROR; + snprintf(con->errmsg, ATTACHSQL_ERROR_BUFFER_SIZE, "DNS lookup failure: %s", uv_err_name(status)); + return; + } + char addr[17] = {'\0'}; + + uv_ip4_name((struct sockaddr_in*) res->ai_addr, addr, 16); + asdebug("DNS lookup success: %s", addr); + uv_tcp_init(resolver->loop, &con->uv_objects.socket.tcp); + con->uv_objects.socket.tcp.data= con; + con->uv_objects.connect_req.data= (void*) &con->uv_objects.socket.tcp; + uv_tcp_connect(&con->uv_objects.connect_req, &con->uv_objects.socket.tcp, (const struct sockaddr*) res->ai_addr, on_connect); + + uv_freeaddrinfo(res); +} + +attachsql_con_status_t attachsql_do_poll(attachsql_connect_t *con) +{ + //asdebug("Connection poll"); + if (con == NULL) + { + return ATTACHSQL_CON_STATUS_PARAMETER_ERROR; + } + + if ((con->status == ATTACHSQL_CON_STATUS_NOT_CONNECTED) or (con->status == ATTACHSQL_CON_STATUS_CONNECT_FAILED) or (con->status == ATTACHSQL_CON_STATUS_IDLE) or (con->status == ATTACHSQL_CON_STATUS_SSL_ERROR)) + { + return con->status; + } +#ifdef HAVE_OPENSSL + if (con->ssl.handshake_done) + { + attachsql_ssl_run(con); + } +#endif + attachsql_run_uv_loop(con); + + return con->status; +} + +void attachsql_send_callback(attachsql_connect_t *con, attachsql_events_t event, attachsql_error_t *error) +{ + if (event == con->last_callback) + { + /* We already sent this event */ + asdebug("Duplicate event %d for connection %u", event, con->connection_id); + return; + } + if ((con->pool != NULL) and (con->pool->callback_fn != NULL)) + { + asdebug("Callback event: %d for connection %u", event, con->connection_id); + con->last_callback= event; + con->pool->callback_fn(con, con->connection_id, event, con->pool->callback_context, error); + } +} + +attachsql_return_t attachsql_connect_poll(attachsql_connect_t *con, attachsql_error_t **error) +{ + attachsql_con_status_t status; + + if (con == NULL) + { + attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_PARAMETER, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", "Invalid connection object"); + return ATTACHSQL_RETURN_ERROR; + } + if (con->pool == NULL) + { + status= attachsql_do_poll(con); + } + else + { + status= con->status; + } + + switch (status) + { + case ATTACHSQL_CON_STATUS_PARAMETER_ERROR: + attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_PARAMETER, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", "Bad parameter"); + attachsql_send_callback(con, ATTACHSQL_EVENT_ERROR, *error); + return ATTACHSQL_RETURN_ERROR; + break; + case ATTACHSQL_CON_STATUS_NOT_CONNECTED: + return ATTACHSQL_RETURN_NOT_CONNECTED; + break; + case ATTACHSQL_CON_STATUS_CONNECTING: + return ATTACHSQL_RETURN_CONNECTING; + break; + case ATTACHSQL_CON_STATUS_CONNECT_FAILED: + if (con->local_errcode == ATTACHSQL_RET_DNS_ERROR) + { + attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_HOST_UNKNOWN, ATTACHSQL_ERROR_LEVEL_ERROR, "08000", con->errmsg); + } + else if (con->server_errno != 0) + { + attachsql_error_server_create(con, error); + } + else + { + if (con->errmsg[0] != '\0') + { + attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_CONNECT, ATTACHSQL_ERROR_LEVEL_ERROR, "08000", con->errmsg); + } + else + { + attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_CONNECT, ATTACHSQL_ERROR_LEVEL_ERROR, "08000", "Unknown connection failure"); + } + } + attachsql_send_callback(con, ATTACHSQL_EVENT_ERROR, *error); + return ATTACHSQL_RETURN_ERROR; + break; + case ATTACHSQL_CON_STATUS_BUSY: + return ATTACHSQL_RETURN_PROCESSING; + break; + case ATTACHSQL_CON_STATUS_SSL_ERROR: + attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_SSL, ATTACHSQL_ERROR_LEVEL_ERROR, "08000", con->errmsg); + attachsql_send_callback(con, ATTACHSQL_EVENT_ERROR, *error); + return ATTACHSQL_RETURN_ERROR; + break; + case ATTACHSQL_CON_STATUS_IDLE: + if (con->server_errno != 0) + { + // Server error during query + attachsql_error_server_create(con, error); + attachsql_send_callback(con, ATTACHSQL_EVENT_ERROR, *error); + return ATTACHSQL_RETURN_ERROR; + } + else if (con->command_status == ATTACHSQL_COMMAND_STATUS_EOF) + { + attachsql_send_callback(con, ATTACHSQL_EVENT_EOF, *error); + con->all_rows_buffered= true; + con->command_status= ATTACHSQL_COMMAND_STATUS_EOF; + return ATTACHSQL_RETURN_EOF; + } + else if (con->command_status == ATTACHSQL_COMMAND_STATUS_ROW_IN_BUFFER) + { + if (con->buffer_rows) + { + return attachsql_query_row_buffer(con, error); + } + else + { + attachsql_send_callback(con, ATTACHSQL_EVENT_ROW_READY, *error); + return ATTACHSQL_RETURN_ROW_READY; + } + } + else if (con->command_status == ATTACHSQL_COMMAND_STATUS_CONNECTED) + { + attachsql_send_callback(con, ATTACHSQL_EVENT_CONNECTED, *error); + if (con->query_buffer_length > 0) + { + return attachsql_connect_query(con, error); + } + else + { + return ATTACHSQL_RETURN_EOF; + } + } + /* If we hit here something went wrong */ + assert(0); + return ATTACHSQL_RETURN_EOF; + break; + case ATTACHSQL_CON_STATUS_NET_ERROR: + attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_SERVER_LOST, ATTACHSQL_ERROR_LEVEL_ERROR, "08006", con->errmsg); + attachsql_send_callback(con, ATTACHSQL_EVENT_ERROR, *error); + return ATTACHSQL_RETURN_ERROR; + break; + } + /* If we get this far 1. our compiler needs shooting for not catching a + * missing case statement and 2. something bad probably happened anyway */ + attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_UNKNOWN, ATTACHSQL_ERROR_LEVEL_ERROR, "99999", "Unkown error occurred"); + return ATTACHSQL_RETURN_ERROR; +} + +void attachsql_check_for_data_cb(uv_check_t *handle) +{ + asdebug("Check called"); + struct attachsql_connect_t *con= (struct attachsql_connect_t*)handle->data; + attachsql_con_process_packets(con); +} + +attachsql_con_status_t attachsql_do_connect(attachsql_connect_t *con) +{ + int ret; + + if (con == NULL) + { + return ATTACHSQL_CON_STATUS_PARAMETER_ERROR; + } + + con->uv_objects.hints.ai_family = PF_INET; + con->uv_objects.hints.ai_socktype = SOCK_STREAM; + con->uv_objects.hints.ai_protocol = IPPROTO_TCP; + con->uv_objects.hints.ai_flags = 0; + + if (con->status != ATTACHSQL_CON_STATUS_NOT_CONNECTED) + { + return con->status; + } + + if (con->pool == NULL) + { + con->uv_objects.loop= new (std::nothrow) uv_loop_t; + ret= uv_loop_init(con->uv_objects.loop); + if (ret < 0) + { + asdebug("Loop initalize failure"); + con->local_errcode= ATTACHSQL_RET_OUT_OF_MEMORY_ERROR; + snprintf(con->errmsg, ATTACHSQL_ERROR_BUFFER_SIZE, "Loop initialization failure, either out of memory or out of file descripitors (usually the latter)"); + con->status= ATTACHSQL_CON_STATUS_CONNECT_FAILED; + return con->status; + } + } + + snprintf(con->str_port, 6, "%d", con->port); + // If port is 0 and no explicit option set then assume we mean UDS + // instead of TCP + if (con->options.protocol == ATTACHSQL_CON_PROTOCOL_UNKNOWN) + { + if (con->port == 0) + { + con->options.protocol= ATTACHSQL_CON_PROTOCOL_UDS; + } + else + { + con->options.protocol= ATTACHSQL_CON_PROTOCOL_TCP; + } + } + switch(con->options.protocol) + { + case ATTACHSQL_CON_PROTOCOL_TCP: + asdebug("TCP connection"); + asdebug("Async DNS lookup: %s", con->host); + con->uv_objects.resolver.data= con; + ret= uv_getaddrinfo(con->uv_objects.loop, &con->uv_objects.resolver, on_resolved, con->host, con->str_port, &con->uv_objects.hints); + if (ret < 0) + { + asdebug("DNS lookup fail: %s", uv_err_name(ret)); + con->local_errcode= ATTACHSQL_RET_DNS_ERROR; + snprintf(con->errmsg, ATTACHSQL_ERROR_BUFFER_SIZE, "DNS lookup failure: %s", uv_err_name(ret)); + con->status= ATTACHSQL_CON_STATUS_CONNECT_FAILED; + return con->status; + } + con->status= ATTACHSQL_CON_STATUS_CONNECTING; + attachsql_run_uv_loop(con); + break; + case ATTACHSQL_CON_PROTOCOL_UDS: + asdebug("UDS connection"); + uv_pipe_init(con->uv_objects.loop, &con->uv_objects.socket.uds, 1); + con->uv_objects.socket.uds.data= con; + con->uv_objects.connect_req.data= (void*) &con->uv_objects.socket.uds; + con->status= ATTACHSQL_CON_STATUS_CONNECTING; + uv_pipe_connect(&con->uv_objects.connect_req, &con->uv_objects.socket.uds, con->host, on_connect); + attachsql_run_uv_loop(con); + break; + case ATTACHSQL_CON_PROTOCOL_UNKNOWN: + asdebug("Unknown protocol, this shouldn't happen"); + con->status= ATTACHSQL_CON_STATUS_CONNECT_FAILED; + } + + return con->status; +} + +attachsql_return_t attachsql_connect_query(attachsql_connect_t *con, attachsql_error_t **error) +{ + attachsql_command_status_t ret; + + if (con->query_buffer_statement) + { + attachsql_statement_prepare(con, con->query_buffer_length, con->query_buffer, NULL); + ret= con->command_status; + } + else + { + ret= attachsql_command_send(con, ATTACHSQL_COMMAND_QUERY, con->query_buffer, con->query_buffer_length); + } + if (ret == ATTACHSQL_COMMAND_STATUS_SEND_FAILED) + { + attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_SERVER_GONE, ATTACHSQL_ERROR_LEVEL_ERROR, "08006", con->errmsg); + return ATTACHSQL_RETURN_ERROR; + } + return ATTACHSQL_RETURN_PROCESSING; +} + +bool attachsql_connect(attachsql_connect_t *con, attachsql_error_t **error) +{ + attachsql_con_status_t status; + + /* TODO: Merge this in? */ + status= attachsql_do_connect(con); + + switch(status) + { + case ATTACHSQL_CON_STATUS_PARAMETER_ERROR: + attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_PARAMETER, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", "Bad parameter"); + attachsql_send_callback(con, ATTACHSQL_EVENT_ERROR, *error); + return false; + break; + case ATTACHSQL_CON_STATUS_NOT_CONNECTED: + /* Shouldn't happen */ + return true; + break; + case ATTACHSQL_CON_STATUS_CONNECTING: + return true; + break; + case ATTACHSQL_CON_STATUS_CONNECT_FAILED: + if (con->local_errcode == ATTACHSQL_RET_DNS_ERROR) + { + attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_HOST_UNKNOWN, ATTACHSQL_ERROR_LEVEL_ERROR, "08000", con->errmsg); + } + else if (con->server_errno != 0) + { + attachsql_error_server_create(con, error); + } + else + { + if (con->errmsg[0] != '\0') + { + attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_CONNECT, ATTACHSQL_ERROR_LEVEL_ERROR, "08000", con->errmsg); + } + else + { + attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_CONNECT, ATTACHSQL_ERROR_LEVEL_ERROR, "08000", "Unknown connection failure"); + } + } + attachsql_send_callback(con, ATTACHSQL_EVENT_ERROR, *error); + return false; + break; + case ATTACHSQL_CON_STATUS_BUSY: + /* Should never be hit */ + return false; + break; + case ATTACHSQL_CON_STATUS_IDLE: + if (con->command_status == ATTACHSQL_COMMAND_STATUS_CONNECTED) + { + attachsql_send_callback(con, ATTACHSQL_EVENT_CONNECTED, *error); + } + return true; + break; + case ATTACHSQL_CON_STATUS_SSL_ERROR: + attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_SSL, ATTACHSQL_ERROR_LEVEL_ERROR, "08000", con->errmsg); + attachsql_send_callback(con, ATTACHSQL_EVENT_ERROR, *error); + return false; + break; + case ATTACHSQL_CON_STATUS_NET_ERROR: + attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_SERVER_LOST, ATTACHSQL_ERROR_LEVEL_ERROR, "08006", con->errmsg); + attachsql_send_callback(con, ATTACHSQL_EVENT_ERROR, *error); + return false; + break; + } + + return true; +} + +bool attachsql_connect_set_option(attachsql_connect_t *con, attachsql_options_t option, const void *arg) +{ + // arg option is for later + (void) arg; + if (con == NULL) + { + return false; + } + + switch (option) + { + case ATTACHSQL_OPTION_COMPRESS: +#ifdef HAVE_ZLIB + con->client_capabilities|= ATTACHSQL_CAPABILITY_COMPRESS; +#else + return false; +#endif + break; + case ATTACHSQL_OPTION_FOUND_ROWS: + con->client_capabilities|= ATTACHSQL_CAPABILITY_FOUND_ROWS; + break; + case ATTACHSQL_OPTION_IGNORE_SIGPIPE: + con->client_capabilities|= ATTACHSQL_CAPABILITY_IGNORE_SIGPIPE; + break; + case ATTACHSQL_OPTION_INTERACTIVE: + con->client_capabilities|= ATTACHSQL_CAPABILITY_INTERACTIVE; + break; + case ATTACHSQL_OPTION_LOCAL_FILES: + con->client_capabilities|= ATTACHSQL_CAPABILITY_LOCAL_FILES; + break; + case ATTACHSQL_OPTION_MULTI_STATEMENTS: + con->client_capabilities|= ATTACHSQL_CAPABILITY_MULTI_STATEMENTS; + break; + case ATTACHSQL_OPTION_NO_SCHEMA: + con->client_capabilities|= ATTACHSQL_CAPABILITY_NO_SCHEMA; + break; + case ATTACHSQL_OPTION_SSL_NO_VERIFY: +#ifdef HAVE_OPENSSL + con->ssl.no_verify= true; +#else + return false; +#endif + break; + case ATTACHSQL_OPTION_SEMI_BLOCKING: + con->options.semi_block= true; + break; + case ATTACHSQL_OPTION_NONE: + return false; + break; + default: + return false; + } + return true; +} + +void on_connect(uv_connect_t *req, int status) +{ + attachsql_connect_t *con= (attachsql_connect_t*)req->handle->data; + asdebug("Connect event callback"); + if (status < 0) + { + asdebug("Connect fail: %s", uv_err_name(status)); + con->local_errcode= ATTACHSQL_RET_CONNECT_ERROR; + con->status= ATTACHSQL_CON_STATUS_CONNECT_FAILED; + snprintf(con->errmsg, ATTACHSQL_ERROR_BUFFER_SIZE, "Connection failed: %s", uv_err_name(status)); + return; + } + asdebug("Connection succeeded!"); + attachsql_packet_queue_push(con, ATTACHSQL_PACKET_TYPE_HANDSHAKE); + // maybe move the set con->stream to connect function + con->uv_objects.stream= (uv_stream_t*)req->data; + uv_check_init(con->uv_objects.loop, &con->uv_objects.check); + con->uv_objects.check.data= con; + uv_check_start(&con->uv_objects.check, attachsql_check_for_data_cb); + uv_read_start((uv_stream_t*)req->data, on_alloc, attachsql_read_data_cb); +} + +void on_alloc(uv_handle_t *client, size_t suggested_size, uv_buf_t *buf) +{ + size_t buffer_free; + attachsql_connect_t *con= (attachsql_connect_t*) client->data; + +#ifdef HAVE_OPENSSL + if (con->ssl.handshake_done && (con->ssl.bio_buffer_size < suggested_size)) + { + asdebug("Increasing SSL read buffer to %zd", suggested_size); + char *realloc_buffer= (char*)realloc(con->ssl.bio_buffer, suggested_size); + if (realloc_buffer) + { + con->ssl.bio_buffer= realloc_buffer; + con->ssl.bio_buffer_size= suggested_size; + } + else + { + con->local_errcode= ATTACHSQL_RET_OUT_OF_MEMORY_ERROR; + asdebug("SSL buffer realloc failure"); + con->command_status= ATTACHSQL_COMMAND_STATUS_SEND_FAILED; + con->next_packet_queue_used= 0; + } + } +#endif + + if (not con->options.compression) + { + asdebug("%zd bytes requested for read buffer", suggested_size); + + if (con->read_buffer == NULL) + { + asdebug("Creating read buffer"); + con->read_buffer= attachsql_buffer_create(); + } + buffer_free= attachsql_buffer_get_available(con->read_buffer); + if (buffer_free < suggested_size) + { + asdebug("Enlarging buffer, free: %zd, requested: %zd", buffer_free, suggested_size); + attachsql_buffer_increase(con->read_buffer); + buffer_free= attachsql_buffer_get_available(con->read_buffer); + } + buf->base= con->read_buffer->buffer_write_ptr; + buf->len= buffer_free; + } + else + { + asdebug("%zd bytes requested for compressed read buffer", suggested_size); + + if (con->read_buffer_compress == NULL) + { + asdebug("Creating compressed read buffer"); + con->read_buffer_compress= attachsql_buffer_create(); + } + buffer_free= attachsql_buffer_get_available(con->read_buffer_compress); + if (buffer_free < suggested_size) + { + asdebug("Enlarging compress buffer, free: %zd, requested: %zd", buffer_free, suggested_size); + attachsql_buffer_increase(con->read_buffer_compress); + buffer_free= attachsql_buffer_get_available(con->read_buffer_compress); + } + buf->base= con->read_buffer_compress->buffer_write_ptr; + buf->len= buffer_free; + } + +#ifdef HAVE_OPENSSL + if (con->ssl.handshake_done) + { + buf->base= con->ssl.bio_buffer; + buf->len= con->ssl.bio_buffer_size; + } +#endif +} + +void attachsql_packet_read_handshake(attachsql_connect_t *con) +{ + asdebug("Connect handshake packet"); + buffer_st *buffer= con->read_buffer; + + // Rejection error before handshake + if ((unsigned char)buffer->buffer_read_ptr[0] == 0xff) + { + attachsql_packet_read_response(con); + } + + // Protocol version + if (buffer->buffer_read_ptr[0] != 10) + { + // Note that 255 is a special immediate auth fail case + asdebug("Bad protocol version"); + con->local_errcode= ATTACHSQL_RET_BAD_PROTOCOL; + snprintf(con->errmsg, ATTACHSQL_ERROR_BUFFER_SIZE, "Incompatible protocol version"); + return; + } + + // Server version (null-terminated string) + buffer->buffer_read_ptr++; + strncpy(con->server_version, buffer->buffer_read_ptr, ATTACHSQL_MAX_SERVER_VERSION_LEN); + con->server_version[ATTACHSQL_MAX_SERVER_VERSION_LEN - 1]= '\0'; + buffer->buffer_read_ptr+= strlen(con->server_version) + 1; + + // Thread ID + con->thread_id= attachsql_unpack_int4(buffer->buffer_read_ptr); + buffer->buffer_read_ptr+= 4; + + // Scramble buffer and 1 byte filler + memcpy(con->scramble_buffer, buffer->buffer_read_ptr, 8); + buffer->buffer_read_ptr+= 9; + + // Server capabilities + con->server_capabilities= (attachsql_capabilities_t)attachsql_unpack_int2(buffer->buffer_read_ptr); + buffer->buffer_read_ptr+= 2; + // Check MySQL 4.1 protocol capability is on, we won't support old auth + if (not (con->server_capabilities & ATTACHSQL_CAPABILITY_PROTOCOL_41)) + { + asdebug("MySQL <4.1 Auth not supported"); + con->local_errcode= ATTACHSQL_RET_NO_OLD_AUTH; + snprintf(con->errmsg, ATTACHSQL_ERROR_BUFFER_SIZE, "MySQL 4.1 protocol and higher required"); + } + + con->charset= buffer->buffer_read_ptr[0]; + buffer->buffer_read_ptr++; + + con->server_status= attachsql_unpack_int2(buffer->buffer_read_ptr); + // 13 byte filler and unrequired scramble length (until auth plugins) + buffer->buffer_read_ptr+= 15; + + memcpy(con->scramble_buffer + 8, buffer->buffer_read_ptr, 12); + // '\0' scramble terminator + buffer->buffer_read_ptr+= 13; + + // MySQL 5.5 onwards has more password plugin stuff here, ignore for now + attachsql_packet_read_end(con); + + // Create response packet + attachsql_handshake_response(con); +} + +void attachsql_handshake_response(attachsql_connect_t *con) +{ + unsigned char *buffer_ptr; + uint32_t capabilities; + + asdebug("Sending handshake response"); + buffer_ptr= (unsigned char*)con->write_buffer; + + capabilities= con->server_capabilities & ATTACHSQL_CAPABILITY_CLIENT; + capabilities|= ATTACHSQL_CAPABILITY_MULTI_RESULTS; + capabilities|= con->client_capabilities; + +#ifdef HAVE_OPENSSL + if (con->ssl.ssl != NULL) + { + if (not (con->server_capabilities & ATTACHSQL_CAPABILITY_SSL)) + { + asdebug("SSL disabled on server"); + con->local_errcode= ATTACHSQL_RET_NET_SSL_ERROR; + snprintf(con->errmsg, ATTACHSQL_ERROR_BUFFER_SIZE, "SSL auth not supported enabled on server"); + con->command_status= ATTACHSQL_COMMAND_STATUS_SEND_FAILED; + con->next_packet_queue_used= 0; + con->status= ATTACHSQL_CON_STATUS_CONNECT_FAILED; + return; + } + capabilities |= ATTACHSQL_CAPABILITY_SSL; + } +#endif + + attachsql_pack_int4(buffer_ptr, capabilities); + buffer_ptr+= 4; + + // Set max packet size to our buffer size for now + attachsql_pack_int4(buffer_ptr, ATTACHSQL_DEFAULT_BUFFER_SIZE); + buffer_ptr+= 4; + + // Change this when we support charsets + buffer_ptr[0]= 0; + buffer_ptr++; + + // 0x00 padding for 23 bytes + memset(buffer_ptr, 0, 23); + buffer_ptr+= 23; + +#ifdef HAVE_OPENSSL + if ((con->ssl.ssl != NULL) and (attachsql_packet_queue_peek(con) != ATTACHSQL_PACKET_TYPE_HANDSHAKE_SSL)) + { + /* for SSL we do a short handshake ending here in plain text, + * no user/password sent. + * The enablement of the SSL capability tells the server that OpenSSL + * handshake happens next followed by a full MySQL handshake packet with + * user/pass encrypted + */ + attachsql_send_data(con, con->write_buffer, (size_t)(buffer_ptr - (unsigned char*)con->write_buffer)); + attachsql_packet_queue_push(con, ATTACHSQL_PACKET_TYPE_HANDSHAKE_SSL); + attachsql_handshake_response(con); + return; + } + + if ((con->ssl.ssl != NULL) and (attachsql_packet_queue_peek(con) == ATTACHSQL_PACKET_TYPE_HANDSHAKE_SSL)) + { + /* second entry into handshake for SSL, this response and all other send / + * receives should be encrypted from now on + */ + con->ssl.enabled= true; + attachsql_packet_queue_pop(con); + } +#endif + + // User name + memcpy(buffer_ptr, con->user, strlen(con->user)); + buffer_ptr+= strlen(con->user); + buffer_ptr[0]= '\0'; + buffer_ptr++; + + // Password + // TODO: add support for password plugins + if (con->pass[0] != '\0') + { + attachsql_ret_t ret; + buffer_ptr[0]= SHA1_DIGEST_LENGTH; // probably should use char packing? + buffer_ptr++; + ret= scramble_password(con, (unsigned char*)buffer_ptr); + if (ret != ATTACHSQL_RET_OK) + { + asdebug("Scramble problem!"); + con->local_errcode= ATTACHSQL_RET_BAD_SCRAMBLE; + return; + } + buffer_ptr+= SHA1_DIGEST_LENGTH; + } + else + { + buffer_ptr[0]= '\0'; + buffer_ptr++; + } + + if (con->schema != NULL) + { + memcpy(buffer_ptr, con->schema, strlen(con->schema)); + buffer_ptr+= strlen(con->schema); + } + buffer_ptr[0]= '\0'; + buffer_ptr++; + attachsql_send_data(con, con->write_buffer, (size_t)(buffer_ptr - (unsigned char*)con->write_buffer)); + attachsql_packet_queue_push(con, ATTACHSQL_PACKET_TYPE_RESPONSE); +} + +attachsql_ret_t scramble_password(attachsql_connect_t *con, unsigned char *buffer) +{ + SHA1_CTX ctx; + unsigned char stage1[SHA1_DIGEST_LENGTH]; + unsigned char stage2[SHA1_DIGEST_LENGTH]; + uint8_t it; + + if (con->scramble_buffer[0] == '\0') + { + asdebug("No scramble supplied from server"); + return ATTACHSQL_RET_NO_SCRAMBLE; + } + + // Double hash the password + SHA1Init(&ctx); + SHA1Update(&ctx, (unsigned char*)con->pass, strlen(con->pass)); + SHA1Final(stage1, &ctx); + SHA1Init(&ctx); + SHA1Update(&ctx, stage1, SHA1_DIGEST_LENGTH); + SHA1Final(stage2, &ctx); + + // Hash the scramble with the double hash + SHA1Init(&ctx); + SHA1Update(&ctx, con->scramble_buffer, SHA1_DIGEST_LENGTH); + SHA1Update(&ctx, stage2, SHA1_DIGEST_LENGTH); + SHA1Final(buffer, &ctx); + + // XOR the hash with the stage1 hash + for (it= 0; it < SHA1_DIGEST_LENGTH; it++) + { + buffer[it]= buffer[it] ^ stage1[it]; + } + + return ATTACHSQL_RET_OK; +} + +const char *attachsql_connect_get_server_version(attachsql_connect_t *con) +{ + if (con == NULL) + { + return NULL; + } + + return con->server_version; +} + +uint32_t attachsql_connect_get_connection_id(attachsql_connect_t *con) +{ + if (con == NULL) + { + return 0; + } + return con->thread_id; +} + +#ifdef HAVE_OPENSSL +bool attachsql_connect_set_ssl(attachsql_connect_t *con, const char *key, const char *cert, const char *ca, const char *capath, const char *cipher, bool verify, attachsql_error_t **error) +{ + if (con == NULL) + { + attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_PARAMETER, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", "Connection parameter not valid"); + return false; + } + + con->ssl.context= SSL_CTX_new(TLSv1_client_method()); + + if (cipher != NULL) + { + if (SSL_CTX_set_cipher_list(con->ssl.context, cipher) != 1) + { + strncpy(con->errmsg, "Error setting SSL cipher list", ATTACHSQL_ERROR_BUFFER_SIZE - 1); + con->errmsg[ATTACHSQL_ERROR_BUFFER_SIZE - 1]= '\0'; + attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_SSL, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", con->errmsg); + return false; + } + } + + if (SSL_CTX_load_verify_locations(con->ssl.context, ca, capath) != 1) + { + strncpy(con->errmsg, "Error loading the SSL certificate authority file", ATTACHSQL_ERROR_BUFFER_SIZE -1); + con->errmsg[ATTACHSQL_ERROR_BUFFER_SIZE - 1]= '\0'; + attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_SSL, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", con->errmsg); + return false; + } + + if (cert != NULL) + { + if (SSL_CTX_use_certificate_file(con->ssl.context, cert, SSL_FILETYPE_PEM) != 1) + { + strncpy(con->errmsg, "Error loading the SSL certificate file", ATTACHSQL_ERROR_BUFFER_SIZE - 1); + con->errmsg[ATTACHSQL_ERROR_BUFFER_SIZE - 1]= '\0'; + attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_SSL, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", con->errmsg); + return false; + } + + if (key == NULL) + { + key= cert; + } + + if (SSL_CTX_use_PrivateKey_file(con->ssl.context, key, SSL_FILETYPE_PEM) != 1) + { + strncpy(con->errmsg, "Cannot load the SSL key file", ATTACHSQL_ERROR_BUFFER_SIZE - 1); + con->errmsg[ATTACHSQL_ERROR_BUFFER_SIZE - 1]= '\0'; + attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_SSL, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", con->errmsg); + return false; + } + + if (SSL_CTX_check_private_key(con->ssl.context) != 1) + { + strncpy(con->errmsg, "Error validating the SSL private key", ATTACHSQL_ERROR_BUFFER_SIZE - 1); + con->errmsg[ATTACHSQL_ERROR_BUFFER_SIZE - 1]= '\0'; + attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_SSL, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", con->errmsg); + return false; + } + } + + if (verify) + { + SSL_CTX_set_verify(con->ssl.context, SSL_VERIFY_PEER, NULL); + } + con->ssl.ssl= SSL_new(con->ssl.context); + /* force client handshake mode to allow SSL_write before handshake complete */ + SSL_set_connect_state(con->ssl.ssl); + + return true; +} +#else +bool attachsql_connect_set_ssl(attachsql_connect_t *con, const char *key, const char *cert, const char *ca, const char *capath, const char *cipher, bool verify, attachsql_error_t **error) +{ + (void) con; + (void) key; + (void) cert; + (void) ca; + (void) capath; + (void) cipher; + (void) verify; + + attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_NO_SSL, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", "SSL support has not been compiled in"); + return false; +} +#endif diff --git a/src/ascore/connect.h b/src/connect.h similarity index 57% rename from src/ascore/connect.h rename to src/connect.h index 2db6064..da00a4c 100644 --- a/src/ascore/connect.h +++ b/src/connect.h @@ -31,35 +31,33 @@ extern "C" { #endif -ascon_st *ascore_con_create(const char *host, in_port_t port, const char *user, const char *pass, const char *schema); +attachsql_con_status_t attachsql_do_connect(attachsql_connect_t *con); -ascore_con_status_t ascore_connect(ascon_st *con); +attachsql_con_status_t attachsql_do_poll(attachsql_connect_t *con); -ascore_con_status_t ascore_con_poll(ascon_st *con); - -void ascore_con_destroy(ascon_st *con); +void loop_walk_cb(uv_handle_t *handle, void *arg); void on_resolved(uv_getaddrinfo_t *resolver, int status, struct addrinfo *res); void on_connect(uv_connect_t *req, int status); -void ascore_packet_read_handshake(ascon_st *con); +void attachsql_packet_read_handshake(attachsql_connect_t *con); -uv_buf_t on_alloc(uv_handle_t *client, size_t suggested_size); +void on_alloc(uv_handle_t *client, size_t suggested_size, uv_buf_t *buf); -asret_t scramble_password(ascon_st *con, unsigned char *buffer); +attachsql_ret_t scramble_password(attachsql_connect_t *con, unsigned char *buffer); -void ascore_handshake_response(ascon_st *con); +void attachsql_handshake_response(attachsql_connect_t *con); -void ascore_library_init(void); +attachsql_return_t attachsql_connect_query(attachsql_connect_t *con, attachsql_error_t **error); #ifdef HAVE_OPENSSL -bool ascore_con_set_ssl(ascon_st *con, const char *key, const char *cert, const char *ca, const char *capath, const char *cipher, bool verify); - -int ascore_ssl_buffer_write(ascon_st *con, uv_buf_t *buf, int buf_len); +int attachsql_ssl_buffer_write(attachsql_connect_t *con, uv_buf_t *buf, int buf_len); #endif -void ascore_check_for_data_cb(uv_check_t *handle, int status); +void attachsql_check_for_data_cb(uv_check_t *handle); + +void attachsql_send_callback(attachsql_connect_t *con, attachsql_events_t event, attachsql_error_t *error); #ifdef __cplusplus } diff --git a/src/constants.h b/src/constants.h new file mode 100644 index 0000000..6edb0f2 --- /dev/null +++ b/src/constants.h @@ -0,0 +1,208 @@ +/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab: + * Copyright 2014 Hewlett-Packard Development Company, L.P. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. You may obtain + * a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + */ + +#pragma once + +#include "config.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ATTACHSQL_DEFAULT_PORT 3306 +#define ATTACHSQL_ERROR_BUFFER_SIZE 255 +#define ATTACHSQL_MAX_SERVER_VERSION_LEN 32 +#define ATTACHSQL_MAX_USER_SIZE 16 +#define ATTACHSQL_MAX_SCHEMA_SIZE 64 +#define ATTACHSQL_MAX_TABLE_SIZE 64 +#define ATTACHSQL_MAX_COLUMN_SIZE 64 +#define ATTACHSQL_MAX_DEFAULT_VALUE_SIZE 2048 +#define ATTACHSQL_MAX_MESSAGE_LEN 2048 +#define ATTACHSQL_WRITE_BUFFER_SIZE 1024 +#define ATTACHSQL_MINIMUM_COMPRESS_SIZE 50 +#define ATTACHSQL_STMT_EXEC_DEFAULT_SIZE 16*1024 +#define ATTACHSQL_DEFAULT_PACKET_QUEUE_SIZE 64 + +#define ATTACHSQL_STMT_PARAM_UNSIGNED_BIT 0x8000 + +enum attachsql_con_protocol_t +{ + ATTACHSQL_CON_PROTOCOL_UNKNOWN, + ATTACHSQL_CON_PROTOCOL_UDS, + ATTACHSQL_CON_PROTOCOL_TCP +}; + +enum attachsql_con_options_t +{ + ATTACHSQL_CON_OPTION_POLLING, + ATTACHSQL_CON_OPTION_RAW_SCRAMBLE, + ATTACHSQL_CON_OPTION_FOUND_ROWS, + ATTACHSQL_CON_OPTION_INTERACTIVE, + ATTACHSQL_CON_OPTION_MULTI_STATEMENTS, + ATTACHSQL_CON_OPTION_AUTH_PLUGIN, + ATTACHSQL_CON_OPTION_PROTOCOL_TCP, + ATTACHSQL_CON_OPTION_PROTOCOL_UDS +}; + +enum attachsql_con_status_t +{ + ATTACHSQL_CON_STATUS_PARAMETER_ERROR, + ATTACHSQL_CON_STATUS_NOT_CONNECTED, + ATTACHSQL_CON_STATUS_CONNECTING, + ATTACHSQL_CON_STATUS_CONNECT_FAILED, + ATTACHSQL_CON_STATUS_BUSY, + ATTACHSQL_CON_STATUS_IDLE, + ATTACHSQL_CON_STATUS_SSL_ERROR, + ATTACHSQL_CON_STATUS_NET_ERROR +}; + +enum attachsql_packet_type_t +{ + ATTACHSQL_PACKET_TYPE_NONE, + ATTACHSQL_PACKET_TYPE_HANDSHAKE, + ATTACHSQL_PACKET_TYPE_HANDSHAKE_SSL, + ATTACHSQL_PACKET_TYPE_RESPONSE, + ATTACHSQL_PACKET_TYPE_PREPARE_RESPONSE, + ATTACHSQL_PACKET_TYPE_PREPARE_PARAMETER, + ATTACHSQL_PACKET_TYPE_PREPARE_COLUMN, + ATTACHSQL_PACKET_TYPE_COLUMN, + ATTACHSQL_PACKET_TYPE_ROW, + ATTACHSQL_PACKET_TYPE_STMT_ROW +}; + +enum attachsql_capabilities_t +{ + ATTACHSQL_CAPABILITY_NONE= 0, + ATTACHSQL_CAPABILITY_LONG_PASSWORD= (1 << 0), + ATTACHSQL_CAPABILITY_FOUND_ROWS= (1 << 1), + ATTACHSQL_CAPABILITY_LONG_FLAG= (1 << 2), + ATTACHSQL_CAPABILITY_CONNECT_WITH_DB= (1 << 3), + ATTACHSQL_CAPABILITY_NO_SCHEMA= (1 << 4), + ATTACHSQL_CAPABILITY_COMPRESS= (1 << 5), + ATTACHSQL_CAPABILITY_ODBC= (1 << 6), + ATTACHSQL_CAPABILITY_LOCAL_FILES= (1 << 7), + ATTACHSQL_CAPABILITY_IGNORE_SPACE= (1 << 8), + ATTACHSQL_CAPABILITY_PROTOCOL_41= (1 << 9), + ATTACHSQL_CAPABILITY_INTERACTIVE= (1 << 10), + ATTACHSQL_CAPABILITY_SSL= (1 << 11), + ATTACHSQL_CAPABILITY_IGNORE_SIGPIPE= (1 << 12), + ATTACHSQL_CAPABILITY_TRANSACTIONS= (1 << 13), + ATTACHSQL_CAPABILITY_RESERVED= (1 << 14), + ATTACHSQL_CAPABILITY_SERCURE_CONNECTION= (1 << 15), + ATTACHSQL_CAPABILITY_MULTI_STATEMENTS= (1 << 16), + ATTACHSQL_CAPABILITY_MULTI_RESULTS= (1 << 17), + ATTACHSQL_CAPABILITY_PLUGIN_AUTH= (1 << 19), + ATTACHSQL_CAPABILITY_CLIENT= (ATTACHSQL_CAPABILITY_LONG_PASSWORD | + ATTACHSQL_CAPABILITY_FOUND_ROWS | + ATTACHSQL_CAPABILITY_LONG_FLAG | + ATTACHSQL_CAPABILITY_CONNECT_WITH_DB | + ATTACHSQL_CAPABILITY_PLUGIN_AUTH | + ATTACHSQL_CAPABILITY_TRANSACTIONS | + ATTACHSQL_CAPABILITY_PROTOCOL_41 | + ATTACHSQL_CAPABILITY_SERCURE_CONNECTION) +}; + + +enum attachsql_command_status_t +{ + ATTACHSQL_COMMAND_STATUS_EOF, + ATTACHSQL_COMMAND_STATUS_CONNECTED, + ATTACHSQL_COMMAND_STATUS_SEND, + ATTACHSQL_COMMAND_STATUS_SEND_FAILED, + ATTACHSQL_COMMAND_STATUS_READ_RESPONSE, + ATTACHSQL_COMMAND_STATUS_READ_COLUMN, + ATTACHSQL_COMMAND_STATUS_READ_ROW, + ATTACHSQL_COMMAND_STATUS_READ_FAILED, + ATTACHSQL_COMMAND_STATUS_ROW_IN_BUFFER, + ATTACHSQL_COMMAND_STATUS_READ_STMT_PARAM, + ATTACHSQL_COMMAND_STATUS_READ_STMT_COLUMN, + ATTACHSQL_COMMAND_STATUS_READ_STMT_ROW +}; + +enum attachsql_command_t +{ + ATTACHSQL_COMMAND_SLEEP= 0x00, + ATTACHSQL_COMMAND_QUIT= 0x01, + ATTACHSQL_COMMAND_INITDB= 0x02, + ATTACHSQL_COMMAND_QUERY= 0x03, + ATTACHSQL_COMMAND_FIELD_LIST= 0x04, + ATTACHSQL_COMMAND_CREATE_DB= 0x05, + ATTACHSQL_COMMAND_DROP_DB= 0x06, + ATTACHSQL_COMMAND_REFRESH= 0x07, + ATTACHSQL_COMMAND_SHUTDOWN= 0x08, + ATTACHSQL_COMMAND_STATISTICS= 0x09, + ATTACHSQL_COMMAND_PROCESS_INFO= 0x0a, + ATTACHSQL_COMMAND_CONNECT= 0x0b, + ATTACHSQL_COMMAND_PROCESS_KILL= 0x0c, + ATTACHSQL_COMMAND_DEBUG= 0x0d, + ATTACHSQL_COMMAND_PING= 0x0e, + ATTACHSQL_COMMAND_TIME= 0x0f, + ATTACHSQL_COMMAND_DELAYED_INSERT= 0x10, + ATTACHSQL_COMMAND_CHANGE_USER= 0x11, + ATTACHSQL_COMMAND_BINLOG_DUMP= 0x12, + ATTACHSQL_COMMAND_TABLE_DUMP= 0x13, + ATTACHSQL_COMMAND_CONNECT_OUT= 0x14, /* Internal (unused) */ + ATTACHSQL_COMMAND_REGISTER_SLAVE= 0x15, + ATTACHSQL_COMMAND_STMT_PREPARE= 0x16, + ATTACHSQL_COMMAND_STMT_EXECUTE= 0x17, + ATTACHSQL_COMMAND_STMT_SEND_LONG_DATA= 0x18, + ATTACHSQL_COMMAND_STMT_CLOSE= 0x19, + ATTACHSQL_COMMAND_STMT_RESET= 0x1a, + ATTACHSQL_COMMAND_SET_OPTION= 0x1b, + ATTACHSQL_COMMAND_STMT_FETCH= 0x1c, + ATTACHSQL_COMMAND_DAEMON= 0x1d, + ATTACHSQL_COMMAND_BINLOG_DUMP_GTID= 0x1e, + ATTACHSQL_COMMAND_RESET_CONNECTION= 0x1f +}; + +enum attachsql_server_status_t +{ + ATTACHSQL_SERVER_STATUS_NONE= 0, + ATTACHSQL_SERVER_STATUS_IN_TRANSACTION= (1 << 0), + ATTACHSQL_SERVER_STATUS_AUTOCOMMIT= (1 << 1), + // (1 << 2) unusued + ATTACHSQL_SERVER_STATUS_MORE_RESULTS= (1 << 3), + ATTACHSQL_SERVER_STATUS_NO_GOOD_INDEX= (1 << 4), + ATTACHSQL_SERVER_STATUS_NO_INDEX= (1 << 5), + ATTACHSQL_SERVER_STATUS_CURSOR_EXISTS= (1 << 6), + ATTACHSQL_SERVER_STATUS_LAST_ROW_SENT= (1 << 7), + ATTACHSQL_SERVER_STATUS_DB_DROPPED= (1 << 8), + ATTACHSQL_SERVER_STATUS_NO_BACKSLASH_ESCAPES= (1 << 9), + ATTACHSQL_SERVER_STATUS_METADATA_CHANGED= (1 << 10), + ATTACHSQL_SERVER_STATUS_QUERY_WAS_SLOW= (1 << 11), + ATTACHSQL_SERVER_STATUS_PS_OUT_PARAMS= (1 << 12), + ATTACHSQL_SERVER_STATUS_IN_TRANSACTION_READ_ONLY= (1 << 13) +}; + +enum attachsql_stmt_state_t +{ + ATTACHSQL_STMT_STATE_NONE, + ATTACHSQL_STMT_STATE_PREPARED, + ATTACHSQL_STMT_STATE_EXECUTED +}; + +enum attachsql_stmt_cursor_t +{ + ATTACHSQL_STMT_CURSOR_NONE= 0x00, + ATTACHSQL_STMT_CURSOR_READ_ONLY= 0x01, + ATTACHSQL_STMT_CURSOR_FOR_UPDATE= 0x02, + ATTACHSQL_STMT_CURSOR_SCROLLABLE= 0x03 +}; +#ifdef __cplusplus +} +#endif + diff --git a/src/ascore/debug.h b/src/debug.h similarity index 83% rename from src/ascore/debug.h rename to src/debug.h index 45d03cb..ea1a695 100644 --- a/src/ascore/debug.h +++ b/src/debug.h @@ -24,16 +24,16 @@ extern "C" { #endif #if DEBUG -#define asdebug(MSG, ...) fprintf(stderr, "[libattachcore] %s:%d " MSG "\n", __FILE__, __LINE__, ##__VA_ARGS__) +#define asdebug(MSG, ...) fprintf(stderr, "[libattachsql] %s:%d " MSG "\n", __FILE__, __LINE__, ##__VA_ARGS__) #define asdebug_hex(DATA, LEN) do { \ size_t hex_it; \ - fprintf(stderr, "[libattachcore] %s:%d packet hex: ", __FILE__, __LINE__); \ + fprintf(stderr, "[libattachsql] %s:%d packet hex: ", __FILE__, __LINE__); \ for (hex_it = 0; hex_it < LEN ; hex_it++) \ { \ fprintf(stderr, "%02X ", (unsigned char)DATA[hex_it]); \ } \ fprintf(stderr, "\n"); \ - fprintf(stderr, "[libattachcore] %s:%d printable packet data: ", __FILE__, __LINE__); \ + fprintf(stderr, "[libattachsql] %s:%d printable packet data: ", __FILE__, __LINE__); \ for (hex_it = 0; hex_it < LEN ; hex_it++) \ { \ if (((unsigned char)DATA[hex_it] < 0x32) or (((unsigned char)DATA[hex_it] > 0x7e))) \ diff --git a/src/asql/error.cc b/src/error.cc similarity index 91% rename from src/asql/error.cc rename to src/error.cc index 8fb83f5..0b1008e 100644 --- a/src/asql/error.cc +++ b/src/error.cc @@ -16,7 +16,7 @@ */ #include "config.h" -#include "src/asql/common.h" +#include "common.h" #include #include @@ -84,10 +84,10 @@ void attachsql_error_server_create(attachsql_connect_t *con, attachsql_error_t * /* No good way of handling this scenario */ return; } - new_err->code= con->core_con->server_errno; - strncpy(new_err->msg, con->core_con->server_message, ATTACHSQL_MESSAGE_SIZE - 1); + new_err->code= con->server_errno; + strncpy(new_err->msg, con->server_message, ATTACHSQL_MESSAGE_SIZE - 1); new_err->msg[ATTACHSQL_MESSAGE_SIZE - 1]= '\0'; - memcpy(new_err->sqlstate, con->core_con->sqlstate, ATTACHSQL_SQLSTATE_SIZE - 1); + memcpy(new_err->sqlstate, con->sqlstate, ATTACHSQL_SQLSTATE_SIZE - 1); new_err->sqlstate[ATTACHSQL_SQLSTATE_SIZE - 1]= '\0'; *error= new_err; } diff --git a/src/asql/error_internal.h b/src/error_internal.h similarity index 96% rename from src/asql/error_internal.h rename to src/error_internal.h index 9813679..e40b3d4 100644 --- a/src/asql/error_internal.h +++ b/src/error_internal.h @@ -17,7 +17,7 @@ #pragma once -#include "src/ascore/ascore.h" +#include "ascore.h" #ifdef __cplusplus extern "C" { diff --git a/src/include.am b/src/include.am new file mode 100644 index 0000000..4e07c94 --- /dev/null +++ b/src/include.am @@ -0,0 +1,54 @@ +# vim:ft=automake +# included from Top Level Makefile.am +# All paths should be given relative to the root + +noinst_HEADERS+= src/ascore.h +noinst_HEADERS+= src/buffer.h +noinst_HEADERS+= src/connect.h +noinst_HEADERS+= src/constants.h +noinst_HEADERS+= src/command.h +noinst_HEADERS+= src/common.h +noinst_HEADERS+= src/debug.h +noinst_HEADERS+= src/error_internal.h +noinst_HEADERS+= src/net.h +noinst_HEADERS+= src/pack.h +noinst_HEADERS+= src/pack_macros.h +noinst_HEADERS+= src/query_internal.h +noinst_HEADERS+= src/return.h +noinst_HEADERS+= src/sha1.h +noinst_HEADERS+= src/structs.h +noinst_HEADERS+= src/statement.h + +lib_LTLIBRARIES+= src/libattachsql.la +src_libattachsql_la_SOURCES= +src_libattachsql_la_LIBADD= +src_libattachsql_la_LDFLAGS= +src_libattachsql_la_CFLAGS= -DBUILDING_ASQL +src_libattachsql_la_CXXFLAGS= -DBUILDING_ASQL + +if BUILD_WIN32 +src_libattachsql_la_LIBADD+= -lmingw32 +src_libattachsql_la_LIBADD+= -lws2_32 +src_libattachsql_la_LIBADD+= -lpsapi +src_libattachsql_la_LIBADD+= -liphlpapi +endif + +src_libattachsql_la_SOURCES+= src/buffer.cc +src_libattachsql_la_SOURCES+= src/command.cc +src_libattachsql_la_SOURCES+= src/connect.cc +src_libattachsql_la_SOURCES+= src/sha1.cc +src_libattachsql_la_SOURCES+= src/net.cc +src_libattachsql_la_SOURCES+= src/pack.cc +src_libattachsql_la_SOURCES+= src/statement.cc +src_libattachsql_la_SOURCES+= src/statement_getset.cc + +src_libattachsql_la_SOURCES+= src/error.cc +src_libattachsql_la_SOURCES+= src/pool.cc +src_libattachsql_la_SOURCES+= src/query.cc +src_libattachsql_la_SOURCES+= src/utility.cc + +src_libattachsql_la_LDFLAGS+= -version-info ${LIBATTACHSQL_LIBRARY_VERSION} + +src_libattachsql_la_LIBADD+= @LIBUV_LIBS@ +src_libattachsql_la_LIBADD+= @ZLIB_LIBS@ +src_libattachsql_la_LIBADD+= @OPENSSL_LIBS@ diff --git a/src/ascore/net.cc b/src/net.cc similarity index 50% rename from src/ascore/net.cc rename to src/net.cc index d03da4c..b21a036 100644 --- a/src/ascore/net.cc +++ b/src/net.cc @@ -31,7 +31,7 @@ #endif #ifdef HAVE_OPENSSL -void ascore_ssl_run(ascon_st *con) +void attachsql_ssl_run(attachsql_connect_t *con) { int r; @@ -41,9 +41,9 @@ void ascore_ssl_run(ascon_st *con) r= SSL_connect(con->ssl.ssl); if (r < 0) { - ascore_ssl_handle_error(con, r); + attachsql_ssl_handle_error(con, r); } - ascore_ssl_data_check(con); + attachsql_ssl_data_check(con); } else { @@ -51,21 +51,21 @@ void ascore_ssl_run(ascon_st *con) r= SSL_read(con->ssl.ssl, con->ssl.ssl_read_buffer, sizeof(con->ssl.ssl_read_buffer)); if (r < 0) { - ascore_ssl_handle_error(con, r); + attachsql_ssl_handle_error(con, r); } asdebug("Read %d encrypted bytes", r); - ascore_ssl_data_check(con); + attachsql_ssl_data_check(con); } } -void ascore_ssl_data_check(ascon_st *con) +void attachsql_ssl_data_check(attachsql_connect_t *con) { int bytes_read= 0; uv_buf_t send_buffer[1]; if (con->ssl.write_buffer) { - size_t write_buffer_len= ascore_buffer_unread_data(con->ssl.write_buffer); + size_t write_buffer_len= attachsql_buffer_unread_data(con->ssl.write_buffer); if (write_buffer_len > 0) { int r= SSL_write(con->ssl.ssl, con->ssl.write_buffer->buffer_read_ptr, (int)write_buffer_len); @@ -74,13 +74,13 @@ void ascore_ssl_data_check(ascon_st *con) int error= SSL_get_error(con->ssl.ssl, r); if (error != SSL_ERROR_WANT_READ) { - con->local_errcode= ASRET_NET_SSL_ERROR; + con->local_errcode= ATTACHSQL_RET_NET_SSL_ERROR; asdebug("SSL write fail: %d", error); - con->command_status= ASCORE_COMMAND_STATUS_SEND_FAILED; - con->next_packet_type= ASCORE_PACKET_TYPE_NONE; - con->status= ASCORE_CON_STATUS_SSL_ERROR; - snprintf(con->errmsg, ASCORE_ERROR_BUFFER_SIZE - 1, "SSL write fail: %s", ERR_reason_error_string(ERR_get_error())); - con->errmsg[ASCORE_ERROR_BUFFER_SIZE - 1]= '\0'; + con->command_status= ATTACHSQL_COMMAND_STATUS_SEND_FAILED; + con->next_packet_queue_used= 0; + con->status= ATTACHSQL_CON_STATUS_SSL_ERROR; + snprintf(con->errmsg, ATTACHSQL_ERROR_BUFFER_SIZE - 1, "SSL write fail: %s", ERR_reason_error_string(ERR_get_error())); + con->errmsg[ATTACHSQL_ERROR_BUFFER_SIZE - 1]= '\0'; } } else @@ -97,40 +97,40 @@ void ascore_ssl_data_check(ascon_st *con) send_buffer[0].base= con->ssl.ssl_write_buffer; send_buffer[0].len= bytes_read; uv_write_t *req= new (std::nothrow) uv_write_t; - if (uv_write(req, con->uv_objects.stream, send_buffer, 1, on_write) != 0) + int ret= uv_write(req, con->uv_objects.stream, send_buffer, 1, on_write); + if (ret < 0) { - con->local_errcode= ASRET_NET_WRITE_ERROR; - asdebug("Write fail: %s", uv_err_name(uv_last_error(con->uv_objects.loop))); - con->command_status= ASCORE_COMMAND_STATUS_SEND_FAILED; - con->next_packet_type= ASCORE_PACKET_TYPE_NONE; + con->local_errcode= ATTACHSQL_RET_NET_WRITE_ERROR; + asdebug("Write fail: %s", uv_err_name(ret)); + con->command_status= ATTACHSQL_COMMAND_STATUS_SEND_FAILED; + con->next_packet_queue_used= 0; } } } -void ascore_ssl_handle_error(ascon_st *con, int result) +void attachsql_ssl_handle_error(attachsql_connect_t *con, int result) { int error= SSL_get_error(con->ssl.ssl, result); if (error == SSL_ERROR_WANT_READ) { - ascore_ssl_data_check(con); + attachsql_ssl_data_check(con); } else { - con->local_errcode= ASRET_NET_SSL_ERROR; + con->local_errcode= ATTACHSQL_RET_NET_SSL_ERROR; unsigned long errcode= ERR_get_error(); asdebug("SSL fail: %d, %s", error, ERR_error_string(errcode, NULL)); - con->status= ASCORE_CON_STATUS_SSL_ERROR; - con->command_status= ASCORE_COMMAND_STATUS_SEND_FAILED; - con->next_packet_type= ASCORE_PACKET_TYPE_NONE; - snprintf(con->errmsg, ASCORE_ERROR_BUFFER_SIZE - 1, "SSL read/write fail: %s", ERR_reason_error_string(errcode)); - con->errmsg[ASCORE_ERROR_BUFFER_SIZE - 1]= '\0'; + con->status= ATTACHSQL_CON_STATUS_SSL_ERROR; + con->command_status= ATTACHSQL_COMMAND_STATUS_SEND_FAILED; + con->next_packet_queue_used= 0; + snprintf(con->errmsg, ATTACHSQL_ERROR_BUFFER_SIZE - 1, "SSL read/write fail: %s", ERR_reason_error_string(errcode)); + con->errmsg[ATTACHSQL_ERROR_BUFFER_SIZE - 1]= '\0'; } } -int ascore_ssl_buffer_write(ascon_st *con, uv_buf_t *buf, int buf_len) +int attachsql_ssl_buffer_write(attachsql_connect_t *con, uv_buf_t *buf, int buf_len) { size_t required_size= 0; - size_t buffer_free= 0; int current_buf; for (current_buf= 0; current_buf < buf_len; current_buf++) { @@ -139,27 +139,25 @@ int ascore_ssl_buffer_write(ascon_st *con, uv_buf_t *buf, int buf_len) if (con->ssl.write_buffer == NULL) { asdebug("Creating SSL write buffer"); - con->ssl.write_buffer= ascore_buffer_create(); + con->ssl.write_buffer= attachsql_buffer_create(); } - buffer_free= ascore_buffer_get_available(con->ssl.write_buffer); - if (buffer_free < required_size) + if (attachsql_buffer_get_available(con->ssl.write_buffer) < required_size) { asdebug("Enlarging SSL write buffer"); - ascore_buffer_increase(con->ssl.write_buffer); - buffer_free= ascore_buffer_get_available(con->ssl.write_buffer); + attachsql_buffer_increase(con->ssl.write_buffer); } for (current_buf= 0; current_buf < buf_len; current_buf++) { memcpy(con->ssl.write_buffer->buffer_write_ptr, buf[current_buf].base, buf[current_buf].len); - ascore_buffer_move_write_ptr(con->ssl.write_buffer, buf[current_buf].len); + attachsql_buffer_move_write_ptr(con->ssl.write_buffer, buf[current_buf].len); } - ascore_ssl_run(con); + attachsql_ssl_run(con); return 0; } #endif -void ascore_send_data(ascon_st *con, char *data, size_t length) +void attachsql_send_data(attachsql_connect_t *con, char *data, size_t length) { uv_buf_t send_buffer[2]; @@ -171,21 +169,21 @@ void ascore_send_data(ascon_st *con, char *data, size_t length) SSL_set_bio(con->ssl.ssl, con->ssl.read_bio, con->ssl.write_bio); SSL_set_connect_state(con->ssl.ssl); SSL_do_handshake(con->ssl.ssl); - ascore_ssl_run(con); + attachsql_ssl_run(con); con->ssl.handshake_done= true; } #endif asdebug("Sending %zd bytes to server", length); - ascore_pack_int3(con->packet_header, length); + attachsql_pack_int3(con->packet_header, length); con->packet_number++; con->packet_header[3]= con->packet_number; #ifdef HAVE_ZLIB /* Can't use con->options.compression because at this point we haven't even connected so the flag isn't set */ - if ((con->client_capabilities & ASCORE_CAPABILITY_COMPRESS) && (con->status != ASCORE_CON_STATUS_CONNECTING)) + if ((con->client_capabilities & ATTACHSQL_CAPABILITY_COMPRESS) && (con->status != ATTACHSQL_CON_STATUS_CONNECTING)) { - ascore_send_compressed_packet(con, data, length, 0); + attachsql_send_compressed_packet(con, data, length, 0); return; } #endif @@ -195,13 +193,13 @@ void ascore_send_data(ascon_st *con, char *data, size_t length) send_buffer[1].base= data; send_buffer[1].len= length; asdebug_hex(data, length); - con->command_status= ASCORE_COMMAND_STATUS_READ_RESPONSE; + con->command_status= ATTACHSQL_COMMAND_STATUS_READ_RESPONSE; int r; #ifdef HAVE_OPENSSL if (con->ssl.handshake_done) { - r= ascore_ssl_buffer_write(con, send_buffer, 2); + r= attachsql_ssl_buffer_write(con, send_buffer, 2); } else #endif @@ -209,17 +207,17 @@ void ascore_send_data(ascon_st *con, char *data, size_t length) uv_write_t *req= new (std::nothrow) uv_write_t; r= uv_write(req, con->uv_objects.stream, send_buffer, 2, on_write); } - if (r != 0) + if (r < 0) { - con->local_errcode= ASRET_NET_WRITE_ERROR; - asdebug("Write fail: %s", uv_err_name(uv_last_error(con->uv_objects.loop))); - con->command_status= ASCORE_COMMAND_STATUS_SEND_FAILED; - con->next_packet_type= ASCORE_PACKET_TYPE_NONE; + con->local_errcode= ATTACHSQL_RET_NET_WRITE_ERROR; + asdebug("Write fail: %s", uv_err_name(r)); + con->command_status= ATTACHSQL_COMMAND_STATUS_SEND_FAILED; + con->next_packet_queue_used= 0; } } #ifdef HAVE_ZLIB -void ascore_send_compressed_packet(ascon_st *con, char *data, size_t length, uint8_t command) +void attachsql_send_compressed_packet(attachsql_connect_t *con, char *data, size_t length, uint8_t command) { uv_buf_t send_buffer[2]; char *realloc_buffer; @@ -236,17 +234,17 @@ void ascore_send_compressed_packet(ascon_st *con, char *data, size_t length, uin } if (con->uncompressed_buffer_len < required_uncompressed) { - /* Enlarge to a multiple of ASCORE_WRITE_BUFFER_SIZE */ - size_t rounding= required_uncompressed % ASCORE_WRITE_BUFFER_SIZE; - new_size= required_uncompressed + ASCORE_WRITE_BUFFER_SIZE - rounding; + /* Enlarge to a multiple of ATTACHSQL_WRITE_BUFFER_SIZE */ + size_t rounding= required_uncompressed % ATTACHSQL_WRITE_BUFFER_SIZE; + new_size= required_uncompressed + ATTACHSQL_WRITE_BUFFER_SIZE - rounding; asdebug("Enlarging uncompressed buffer to %zu bytes", new_size); realloc_buffer= (char*)realloc(con->uncompressed_buffer, new_size); if (realloc_buffer == NULL) { - con->local_errcode= ASRET_OUT_OF_MEMORY_ERROR; + con->local_errcode= ATTACHSQL_RET_OUT_OF_MEMORY_ERROR; asdebug("Uncompressed buffer realloc failure"); - con->command_status= ASCORE_COMMAND_STATUS_SEND_FAILED; - con->next_packet_type= ASCORE_PACKET_TYPE_NONE; + con->command_status= ATTACHSQL_COMMAND_STATUS_SEND_FAILED; + con->next_packet_queue_used= 0; return; } con->uncompressed_buffer= realloc_buffer; @@ -268,7 +266,7 @@ void ascore_send_compressed_packet(ascon_st *con, char *data, size_t length, uin memcpy(&con->uncompressed_buffer[4], data, length); } - if (length > ASCORE_MINIMUM_COMPRESS_SIZE) + if (length > ATTACHSQL_MINIMUM_COMPRESS_SIZE) { size_t required_compressed; /* compress the packet */ @@ -276,17 +274,17 @@ void ascore_send_compressed_packet(ascon_st *con, char *data, size_t length, uin required_compressed= (size_t)compressBound((uLong) required_uncompressed); if (con->compressed_buffer_len < required_compressed) { - /* Enlarge to a multiple of ASCORE_WRITE_BUFFER_SIZE */ - size_t rounding= required_compressed % ASCORE_WRITE_BUFFER_SIZE; - new_size= required_compressed + ASCORE_WRITE_BUFFER_SIZE - rounding; + /* Enlarge to a multiple of ATTACHSQL_WRITE_BUFFER_SIZE */ + size_t rounding= required_compressed % ATTACHSQL_WRITE_BUFFER_SIZE; + new_size= required_compressed + ATTACHSQL_WRITE_BUFFER_SIZE - rounding; asdebug("Enlarging compressed buffer to %zu bytes", new_size); realloc_buffer= (char*)realloc(con->compressed_buffer, new_size); if (realloc_buffer == NULL) { - con->local_errcode= ASRET_OUT_OF_MEMORY_ERROR; + con->local_errcode= ATTACHSQL_RET_OUT_OF_MEMORY_ERROR; asdebug("Compressed buffer realloc failure"); - con->command_status= ASCORE_COMMAND_STATUS_SEND_FAILED; - con->next_packet_type= ASCORE_PACKET_TYPE_NONE; + con->command_status= ATTACHSQL_COMMAND_STATUS_SEND_FAILED; + con->next_packet_queue_used= 0; return; } con->compressed_buffer= realloc_buffer; @@ -296,15 +294,15 @@ void ascore_send_compressed_packet(ascon_st *con, char *data, size_t length, uin int res= compress((Bytef*)con->compressed_buffer, (uLongf*)&compressed_length, (Bytef*)con->uncompressed_buffer, (uLong)required_uncompressed); if ((res != Z_OK) || (con->uncompressed_buffer_len < compressed_length)) { - con->local_errcode= ASRET_COMPRESSION_FAILURE; + con->local_errcode= ATTACHSQL_RET_COMPRESSION_FAILURE; asdebug("Compression failure"); - con->command_status= ASCORE_COMMAND_STATUS_SEND_FAILED; - con->next_packet_type= ASCORE_PACKET_TYPE_NONE; + con->command_status= ATTACHSQL_COMMAND_STATUS_SEND_FAILED; + con->next_packet_queue_used= 0; return; } - ascore_pack_int3(con->compressed_packet_header, compressed_length); + attachsql_pack_int3(con->compressed_packet_header, compressed_length); con->compressed_packet_header[3]= con->compressed_packet_number; - ascore_pack_int3(con->compressed_packet_header+4, required_uncompressed); + attachsql_pack_int3(con->compressed_packet_header+4, required_uncompressed); send_buffer[0].base= con->compressed_packet_header; send_buffer[0].len= 7; send_buffer[1].base= con->compressed_buffer; @@ -313,9 +311,9 @@ void ascore_send_compressed_packet(ascon_st *con, char *data, size_t length, uin } else { - ascore_pack_int3(con->compressed_packet_header, required_uncompressed); + attachsql_pack_int3(con->compressed_packet_header, required_uncompressed); con->compressed_packet_header[3]= con->compressed_packet_number; - ascore_pack_int3(con->compressed_packet_header+4, 0); + attachsql_pack_int3(con->compressed_packet_header+4, 0); asdebug_hex(con->compressed_packet_header, 7); send_buffer[0].base= con->compressed_packet_header; send_buffer[0].len= 7; @@ -325,49 +323,78 @@ void ascore_send_compressed_packet(ascon_st *con, char *data, size_t length, uin asdebug_hex(con->uncompressed_buffer, required_uncompressed); } asdebug_hex(data, length); - con->command_status= ASCORE_COMMAND_STATUS_READ_RESPONSE; + con->command_status= ATTACHSQL_COMMAND_STATUS_READ_RESPONSE; - uv_write_t *req= new (std::nothrow) uv_write_t; - if (uv_write(req, con->uv_objects.stream, send_buffer, 2, on_write) != 0) + int r; +#ifdef HAVE_OPENSSL + if (con->ssl.handshake_done) { - con->local_errcode= ASRET_NET_WRITE_ERROR; - asdebug("Write fail: %s", uv_err_name(uv_last_error(con->uv_objects.loop))); - con->command_status= ASCORE_COMMAND_STATUS_SEND_FAILED; - con->next_packet_type= ASCORE_PACKET_TYPE_NONE; + r= attachsql_ssl_buffer_write(con, send_buffer, 2); + } + else +#endif + { + uv_write_t *req= new (std::nothrow) uv_write_t; + r= uv_write(req, con->uv_objects.stream, send_buffer, 2, on_write); + } + if (r < 0) + { + con->local_errcode= ATTACHSQL_RET_NET_WRITE_ERROR; + asdebug("Write fail: %s", uv_err_name(r)); + con->command_status= ATTACHSQL_COMMAND_STATUS_SEND_FAILED; + con->next_packet_queue_used= 0; } } #endif void on_write(uv_write_t *req, int status) { - ascon_st *con= (ascon_st*)req->handle->data; + attachsql_connect_t *con= (attachsql_connect_t*)req->handle->data; asdebug("Write callback, status: %d", status); - if (con->next_packet_type == ASCORE_PACKET_TYPE_NONE) + if (attachsql_packet_queue_peek(con) == ATTACHSQL_PACKET_TYPE_NONE) { - con->status= ASCORE_CON_STATUS_IDLE; - con->command_status= ASCORE_COMMAND_STATUS_EOF; + con->status= ATTACHSQL_CON_STATUS_IDLE; + con->command_status= ATTACHSQL_COMMAND_STATUS_EOF; } - if (status != 0) + if (status < 0) { - con->local_errcode= ASRET_NET_WRITE_ERROR; - asdebug("Write fail: %s", uv_err_name(uv_last_error(con->uv_objects.loop))); - con->command_status= ASCORE_COMMAND_STATUS_SEND_FAILED; - con->next_packet_type= ASCORE_PACKET_TYPE_NONE; + con->local_errcode= ATTACHSQL_RET_NET_WRITE_ERROR; + asdebug("Write fail: %s", uv_err_name(status)); + con->command_status= ATTACHSQL_COMMAND_STATUS_SEND_FAILED; + con->next_packet_queue_used= 0; + con->status= ATTACHSQL_CON_STATUS_NET_ERROR; + snprintf(con->errmsg, ATTACHSQL_ERROR_BUFFER_SIZE, "Net write failure: %s", uv_err_name(status)); + uv_check_stop(&con->uv_objects.check); + uv_close((uv_handle_t*)con->uv_objects.stream, NULL); } delete req; } -void ascore_read_data_cb(uv_stream_t* tcp, ssize_t read_size, const uv_buf_t buf) +void attachsql_read_data_cb(uv_stream_t* tcp, ssize_t read_size, const uv_buf_t *buf) { - (void) buf; - struct ascon_st *con= (struct ascon_st*)tcp->data; + (void) buf; // If we enter this with HAVE_OPENSSL undefined buf is unused + + struct attachsql_connect_t *con= (struct attachsql_connect_t*)tcp->data; + + if (read_size < 0) + { + con->local_errcode= ATTACHSQL_RET_NET_READ_ERROR; + asdebug("Read fail: %s", uv_err_name((int)read_size)); + con->command_status= ATTACHSQL_COMMAND_STATUS_READ_FAILED; + con->next_packet_queue_used= 0; + con->status= ATTACHSQL_CON_STATUS_NET_ERROR; + snprintf(con->errmsg, ATTACHSQL_ERROR_BUFFER_SIZE, "Net read failure: %s", uv_err_name((int)read_size)); + uv_check_stop(&con->uv_objects.check); + uv_close((uv_handle_t*)con->uv_objects.stream, NULL); + return; + } #ifdef HAVE_OPENSSL if (con->ssl.handshake_done) { asdebug("Got encrypted data, %zd bytes", read_size); - BIO_write(con->ssl.read_bio, buf.base, (int)read_size); + BIO_write(con->ssl.read_bio, buf->base, (int)read_size); buffer_st *buffer= NULL; if (con->options.compression) { @@ -377,43 +404,35 @@ void ascore_read_data_cb(uv_stream_t* tcp, ssize_t read_size, const uv_buf_t buf { buffer= con->read_buffer; } - size_t available_buffer= ascore_buffer_get_available(buffer); + size_t available_buffer= attachsql_buffer_get_available(buffer); int r= SSL_read(con->ssl.ssl, buffer->buffer_write_ptr, (int)available_buffer); if (r < 0) { - ascore_ssl_handle_error(con, r); + attachsql_ssl_handle_error(con, r); } else if (r > 0) { asdebug("Got unencrypted data, %d bytes", r); - ascore_buffer_move_write_ptr(buffer, r); + attachsql_buffer_move_write_ptr(buffer, r); } return; } #endif - if (read_size < 0) - { - con->local_errcode= ASRET_NET_READ_ERROR; - asdebug("Read fail: %s", uv_err_name(uv_last_error(con->uv_objects.loop))); - con->command_status= ASCORE_COMMAND_STATUS_READ_FAILED; - con->next_packet_type= ASCORE_PACKET_TYPE_NONE; - return; - } asdebug("Got data, %zd bytes", read_size); if (con->options.compression) { - ascore_buffer_move_write_ptr(con->read_buffer_compress, read_size); + attachsql_buffer_move_write_ptr(con->read_buffer_compress, read_size); } else { - ascore_buffer_move_write_ptr(con->read_buffer, read_size); + attachsql_buffer_move_write_ptr(con->read_buffer, read_size); } - ascore_con_process_packets(con); + attachsql_con_process_packets(con); } #ifdef HAVE_ZLIB -bool ascore_con_decompress_read_buffer(ascon_st *con) +bool attachsql_con_decompress_read_buffer(attachsql_connect_t *con) { size_t data_size; size_t buffer_free; @@ -421,13 +440,13 @@ bool ascore_con_decompress_read_buffer(ascon_st *con) uint32_t uncompressed_packet_size; /* compress packet header is 7 bytes */ - data_size= ascore_buffer_unread_data(con->read_buffer_compress); + data_size= attachsql_buffer_unread_data(con->read_buffer_compress); if (data_size < 7) { return false; } // First 3 bytes are packet size - compressed_packet_size= ascore_unpack_int3(con->read_buffer_compress->buffer_read_ptr); + compressed_packet_size= attachsql_unpack_int3(con->read_buffer_compress->buffer_read_ptr); //con->packet_size= packet_len; if ((compressed_packet_size + 7) > data_size) @@ -444,26 +463,26 @@ bool ascore_con_decompress_read_buffer(ascon_st *con) if (con->compressed_packet_number != con->read_buffer_compress->buffer_read_ptr[3]) { asdebug("Compressed packet out of sequence!"); - con->local_errcode= ASRET_PACKET_OUT_OF_SEQUENCE; - con->command_status= ASCORE_COMMAND_STATUS_READ_FAILED; - con->next_packet_type= ASCORE_PACKET_TYPE_NONE; + con->local_errcode= ATTACHSQL_RET_PACKET_OUT_OF_SEQUENCE; + con->command_status= ATTACHSQL_COMMAND_STATUS_READ_FAILED; + con->next_packet_queue_used= 0; return true; } - uncompressed_packet_size= ascore_unpack_int3(con->read_buffer_compress->buffer_read_ptr+4); + uncompressed_packet_size= attachsql_unpack_int3(con->read_buffer_compress->buffer_read_ptr+4); asdebug("%u bytes requested for read buffer", uncompressed_packet_size); con->read_buffer_compress->buffer_read_ptr+= 7; if (con->read_buffer == NULL) { asdebug("Creating read buffer"); - con->read_buffer= ascore_buffer_create(); + con->read_buffer= attachsql_buffer_create(); } - buffer_free= ascore_buffer_get_available(con->read_buffer); + buffer_free= attachsql_buffer_get_available(con->read_buffer); if (buffer_free < uncompressed_packet_size) { asdebug("Enlarging buffer, free: %zu, requested: %u", buffer_free, uncompressed_packet_size); - ascore_buffer_increase(con->read_buffer); - buffer_free= ascore_buffer_get_available(con->read_buffer); + attachsql_buffer_increase(con->read_buffer); + buffer_free= attachsql_buffer_get_available(con->read_buffer); } con->read_buffer_compress->packet_end_ptr= con->read_buffer_compress->buffer_read_ptr + compressed_packet_size; @@ -472,7 +491,7 @@ bool ascore_con_decompress_read_buffer(ascon_st *con) asdebug("Compression packet with no compression"); memcpy(con->read_buffer->buffer_write_ptr, con->read_buffer_compress->buffer_read_ptr, compressed_packet_size); con->read_buffer_compress->buffer_read_ptr+= compressed_packet_size; - ascore_buffer_move_write_ptr(con->read_buffer, compressed_packet_size); + attachsql_buffer_move_write_ptr(con->read_buffer, compressed_packet_size); return true; } else @@ -482,19 +501,19 @@ bool ascore_con_decompress_read_buffer(ascon_st *con) if (res != Z_OK) { asdebug("Decompression error: %d", res); - con->local_errcode= ASRET_COMPRESSION_FAILURE; - con->command_status= ASCORE_COMMAND_STATUS_READ_FAILED; - con->next_packet_type= ASCORE_PACKET_TYPE_NONE; + con->local_errcode= ATTACHSQL_RET_COMPRESSION_FAILURE; + con->command_status= ATTACHSQL_COMMAND_STATUS_READ_FAILED; + con->next_packet_queue_used= 0; return true; } con->read_buffer_compress->buffer_read_ptr+= compressed_packet_size; - ascore_buffer_move_write_ptr(con->read_buffer, buffer_free); + attachsql_buffer_move_write_ptr(con->read_buffer, buffer_free); return true; } } #endif -bool ascore_con_process_packets(ascon_st *con) +bool attachsql_con_process_packets(attachsql_connect_t *con) { uint32_t packet_len; size_t data_size; @@ -510,17 +529,18 @@ bool ascore_con_process_packets(ascon_st *con) { return false; } - if (not ascore_con_decompress_read_buffer(con) and (con->read_buffer == NULL)) + if (not attachsql_con_decompress_read_buffer(con) and (con->read_buffer == NULL)) { return false; } } #endif - while (con->next_packet_type != ASCORE_PACKET_TYPE_NONE) + attachsql_packet_type_t next_packet_type; + while ((next_packet_type= attachsql_packet_queue_peek(con)) != ATTACHSQL_PACKET_TYPE_NONE) { // Packet header is 4 bytes, if we don't have that, then we don't have enough - data_size= ascore_buffer_unread_data(con->read_buffer); + data_size= attachsql_buffer_unread_data(con->read_buffer); if (data_size < 4) { asdebug("Read less than 4 bytes (%zu bytes), waiting for more", data_size); @@ -528,7 +548,7 @@ bool ascore_con_process_packets(ascon_st *con) } // First 3 bytes are packet size - packet_len= ascore_unpack_int3(con->read_buffer->buffer_read_ptr); + packet_len= attachsql_unpack_int3(con->read_buffer->buffer_read_ptr); con->packet_size= packet_len; if ((packet_len + 4) > data_size) @@ -538,52 +558,53 @@ bool ascore_con_process_packets(ascon_st *con) } // If initial read handshake packet_number is 0, so don't increment - if (con->next_packet_type != ASCORE_PACKET_TYPE_HANDSHAKE) + if (next_packet_type != ATTACHSQL_PACKET_TYPE_HANDSHAKE) { con->packet_number++; } + attachsql_packet_queue_pop(con); // Fourth byte is packet number asdebug("Got packet %d, expected %d", con->read_buffer->buffer_read_ptr[3], con->packet_number); if (con->packet_number != con->read_buffer->buffer_read_ptr[3]) { asdebug("Packet out of sequence!"); - con->local_errcode= ASRET_PACKET_OUT_OF_SEQUENCE; - con->command_status= ASCORE_COMMAND_STATUS_READ_FAILED; - con->next_packet_type= ASCORE_PACKET_TYPE_NONE; + con->local_errcode= ATTACHSQL_RET_PACKET_OUT_OF_SEQUENCE; + con->command_status= ATTACHSQL_COMMAND_STATUS_READ_FAILED; + con->next_packet_queue_used= 0; return true; } con->read_buffer->buffer_read_ptr+= 4; con->read_buffer->packet_end_ptr= con->read_buffer->buffer_read_ptr + packet_len; asdebug_hex(con->read_buffer->buffer_read_ptr, packet_len); - switch(con->next_packet_type) + switch(next_packet_type) { - case ASCORE_PACKET_TYPE_NONE: + case ATTACHSQL_PACKET_TYPE_NONE: // Shoudn't happen return true; - case ASCORE_PACKET_TYPE_HANDSHAKE: - ascore_packet_read_handshake(con); + case ATTACHSQL_PACKET_TYPE_HANDSHAKE: + attachsql_packet_read_handshake(con); break; - case ASCORE_PACKET_TYPE_HANDSHAKE_SSL: - ascore_handshake_response(con); + case ATTACHSQL_PACKET_TYPE_HANDSHAKE_SSL: + attachsql_handshake_response(con); break; - case ASCORE_PACKET_TYPE_RESPONSE: - ascore_packet_read_response(con); + case ATTACHSQL_PACKET_TYPE_RESPONSE: + attachsql_packet_read_response(con); break; - case ASCORE_PACKET_TYPE_PREPARE_RESPONSE: - ascore_packet_read_prepare_response(con); + case ATTACHSQL_PACKET_TYPE_PREPARE_RESPONSE: + attachsql_packet_read_prepare_response(con); break; - case ASCORE_PACKET_TYPE_PREPARE_PARAMETER: - ascore_packet_read_prepare_parameter(con); + case ATTACHSQL_PACKET_TYPE_PREPARE_PARAMETER: + attachsql_packet_read_prepare_parameter(con); break; - case ASCORE_PACKET_TYPE_PREPARE_COLUMN: - ascore_packet_read_prepare_column(con); + case ATTACHSQL_PACKET_TYPE_PREPARE_COLUMN: + attachsql_packet_read_prepare_column(con); break; - case ASCORE_PACKET_TYPE_COLUMN: - ascore_packet_read_column(con); + case ATTACHSQL_PACKET_TYPE_COLUMN: + attachsql_packet_read_column(con); break; - case ASCORE_PACKET_TYPE_STMT_ROW: - case ASCORE_PACKET_TYPE_ROW: - ascore_packet_read_row(con); + case ATTACHSQL_PACKET_TYPE_STMT_ROW: + case ATTACHSQL_PACKET_TYPE_ROW: + attachsql_packet_read_row(con); return true; break; } @@ -592,34 +613,31 @@ bool ascore_con_process_packets(ascon_st *con) return false; } -void ascore_packet_read_row(ascon_st *con) +void attachsql_packet_read_row(attachsql_connect_t *con) { // If we hit an EOF instead if ((unsigned char)con->read_buffer->buffer_read_ptr[0] == 0xfe) { con->result.row_data= NULL; con->result.row_length= 0; - ascore_packet_read_response(con); + attachsql_packet_read_response(con); return; } asdebug("Row read"); con->result.row_data= con->read_buffer->buffer_read_ptr; con->result.row_length= con->packet_size; - con->next_packet_type= ASCORE_PACKET_TYPE_NONE; - con->command_status= ASCORE_COMMAND_STATUS_ROW_IN_BUFFER; - con->status= ASCORE_CON_STATUS_IDLE; - uv_read_stop(con->uv_objects.stream); + con->command_status= ATTACHSQL_COMMAND_STATUS_ROW_IN_BUFFER; + con->status= ATTACHSQL_CON_STATUS_IDLE; } -void ascore_packet_read_end(ascon_st *con) +void attachsql_packet_read_end(attachsql_connect_t *con) { asdebug("Packet end"); - uv_read_stop(con->uv_objects.stream); - ascore_buffer_packet_read_end(con->read_buffer); + attachsql_buffer_packet_read_end(con->read_buffer); } -void ascore_packet_read_prepare_response(ascon_st *con) +void attachsql_packet_read_prepare_response(attachsql_connect_t *con) { asdebug("Prepare response packet"); buffer_st *buffer= con->read_buffer; @@ -627,7 +645,7 @@ void ascore_packet_read_prepare_response(ascon_st *con) if (buffer->buffer_read_ptr[0] != 0x00) { /* Stmt error packets are the same as normal ones */ - ascore_packet_read_response(con); + attachsql_packet_read_response(con); } else { @@ -635,52 +653,47 @@ void ascore_packet_read_prepare_response(ascon_st *con) asdebug("Got PREPARE_OK packet"); buffer->buffer_read_ptr++; data_read++; - con->stmt->id= ascore_unpack_int4(buffer->buffer_read_ptr); + con->stmt->id= attachsql_unpack_int4(buffer->buffer_read_ptr); buffer->buffer_read_ptr+= 4; data_read+= 4; - con->stmt->column_count= ascore_unpack_int2(buffer->buffer_read_ptr); + con->stmt->column_count= attachsql_unpack_int2(buffer->buffer_read_ptr); buffer->buffer_read_ptr+= 2; data_read+= 2; - con->stmt->param_count= ascore_unpack_int2(buffer->buffer_read_ptr); + con->stmt->param_count= attachsql_unpack_int2(buffer->buffer_read_ptr); /* one byte filler */ buffer->buffer_read_ptr+= 3; data_read+= 3; - con->warning_count= ascore_unpack_int2(buffer->buffer_read_ptr); + con->warning_count= attachsql_unpack_int2(buffer->buffer_read_ptr); buffer->buffer_read_ptr+= 2; data_read+= 2; if (con->stmt->param_count) { con->stmt->params= new (std::nothrow) column_t[con->stmt->param_count]; - con->stmt->param_data= new (std::nothrow) ascore_stmt_param_st[con->stmt->param_count]; - } - if (con->stmt->column_count) - { - con->stmt->columns= new (std::nothrow) column_t[con->stmt->column_count]; + con->stmt->param_data= new (std::nothrow) attachsql_stmt_param_st[con->stmt->param_count]; } if (con->stmt->param_count > 0) { - con->next_packet_type= ASCORE_PACKET_TYPE_PREPARE_PARAMETER; - con->command_status= ASCORE_COMMAND_STATUS_READ_STMT_PARAM; + attachsql_packet_queue_push(con, ATTACHSQL_PACKET_TYPE_PREPARE_PARAMETER); + con->command_status= ATTACHSQL_COMMAND_STATUS_READ_STMT_PARAM; } else if (con->stmt->column_count > 0) { - con->next_packet_type= ASCORE_PACKET_TYPE_PREPARE_COLUMN; - con->command_status= ASCORE_COMMAND_STATUS_READ_STMT_COLUMN; + attachsql_packet_queue_push(con, ATTACHSQL_PACKET_TYPE_PREPARE_COLUMN); + con->command_status= ATTACHSQL_COMMAND_STATUS_READ_STMT_COLUMN; } else { - con->command_status= ASCORE_COMMAND_STATUS_EOF; - con->status= ASCORE_CON_STATUS_IDLE; - con->next_packet_type= ASCORE_PACKET_TYPE_NONE; - ascore_packet_read_end(con); + con->command_status= ATTACHSQL_COMMAND_STATUS_EOF; + con->status= ATTACHSQL_CON_STATUS_IDLE; + attachsql_packet_read_end(con); } buffer->buffer_read_ptr+= (con->packet_size - data_read); - con->stmt->state= ASCORE_STMT_STATE_PREPARED; - ascore_packet_read_end(con); + con->stmt->state= ATTACHSQL_STMT_STATE_PREPARED; + attachsql_packet_read_end(con); } } -void ascore_packet_read_response(ascon_st *con) +void attachsql_packet_read_response(attachsql_connect_t *con) { asdebug("Response packet"); uint8_t bytes; @@ -693,36 +706,35 @@ void ascore_packet_read_response(ascon_st *con) asdebug("Got OK packet"); buffer->buffer_read_ptr++; data_read++; - con->affected_rows= ascore_unpack_length(buffer->buffer_read_ptr, &bytes, NULL); + con->affected_rows= attachsql_unpack_length(buffer->buffer_read_ptr, &bytes, NULL); buffer->buffer_read_ptr+= bytes; data_read+= bytes; - con->insert_id= ascore_unpack_length(buffer->buffer_read_ptr, &bytes, NULL); + con->insert_id= attachsql_unpack_length(buffer->buffer_read_ptr, &bytes, NULL); buffer->buffer_read_ptr+= bytes; data_read+= bytes; - con->server_status= ascore_unpack_int2(buffer->buffer_read_ptr); + con->server_status= attachsql_unpack_int2(buffer->buffer_read_ptr); buffer->buffer_read_ptr+= 2; data_read+= 2; - con->warning_count= ascore_unpack_int2(buffer->buffer_read_ptr); + con->warning_count= attachsql_unpack_int2(buffer->buffer_read_ptr); buffer->buffer_read_ptr+= 2; data_read+= 2; - snprintf(con->server_message, ASCORE_MAX_MESSAGE_LEN, "%.*s", (con->packet_size - data_read), buffer->buffer_read_ptr); - con->server_message[ASCORE_MAX_MESSAGE_LEN - 1]= '\0'; + snprintf(con->server_message, ATTACHSQL_MAX_MESSAGE_LEN, "%.*s", (con->packet_size - data_read), buffer->buffer_read_ptr); + con->server_message[ATTACHSQL_MAX_MESSAGE_LEN - 1]= '\0'; buffer->buffer_read_ptr+= (con->packet_size - data_read); - if (con->status == ASCORE_CON_STATUS_CONNECTING) + if (con->status == ATTACHSQL_CON_STATUS_CONNECTING) { - con->command_status= ASCORE_COMMAND_STATUS_CONNECTED; - if (con->client_capabilities & ASCORE_CAPABILITY_COMPRESS) + con->command_status= ATTACHSQL_COMMAND_STATUS_CONNECTED; + if (con->client_capabilities & ATTACHSQL_CAPABILITY_COMPRESS) { con->options.compression= true; } } else { - con->command_status= ASCORE_COMMAND_STATUS_EOF; + con->command_status= ATTACHSQL_COMMAND_STATUS_EOF; } - con->status= ASCORE_CON_STATUS_IDLE; - con->next_packet_type= ASCORE_PACKET_TYPE_NONE; - ascore_packet_read_end(con); + con->status= ATTACHSQL_CON_STATUS_IDLE; + attachsql_packet_read_end(con); } else if ((unsigned char)buffer->buffer_read_ptr[0] == 0xff) { @@ -730,123 +742,131 @@ void ascore_packet_read_response(ascon_st *con) asdebug("Got Error packet"); buffer->buffer_read_ptr++; data_read++; - con->server_errno= ascore_unpack_int2(buffer->buffer_read_ptr); + con->server_errno= attachsql_unpack_int2(buffer->buffer_read_ptr); // Also skip the SQLSTATE marker, always a '#' buffer->buffer_read_ptr+= 3; data_read+= 3; memcpy(con->sqlstate, buffer->buffer_read_ptr, 5); buffer->buffer_read_ptr+= 5; data_read+= 5; - snprintf(con->server_message, ASCORE_MAX_MESSAGE_LEN, "%.*s", (con->packet_size - data_read), buffer->buffer_read_ptr); - con->server_message[ASCORE_MAX_MESSAGE_LEN - 1]= '\0'; + snprintf(con->server_message, ATTACHSQL_MAX_MESSAGE_LEN, "%.*s", (con->packet_size - data_read), buffer->buffer_read_ptr); + con->server_message[ATTACHSQL_MAX_MESSAGE_LEN - 1]= '\0'; buffer->buffer_read_ptr+= (con->packet_size - data_read); - if (con->command_status == ASCORE_COMMAND_STATUS_READ_RESPONSE) + if (con->command_status == ATTACHSQL_COMMAND_STATUS_READ_RESPONSE) { - con->status= ASCORE_CON_STATUS_CONNECT_FAILED; + con->status= ATTACHSQL_CON_STATUS_CONNECT_FAILED; } else { - con->status= ASCORE_CON_STATUS_IDLE; + con->status= ATTACHSQL_CON_STATUS_IDLE; } - con->next_packet_type= ASCORE_PACKET_TYPE_NONE; - con->command_status= ASCORE_COMMAND_STATUS_NONE; - ascore_packet_read_end(con); + con->next_packet_queue_used= 0; + con->command_status= ATTACHSQL_COMMAND_STATUS_EOF; + attachsql_packet_read_end(con); } else if ((unsigned char)buffer->buffer_read_ptr[0] == 0xfe) { // This is an EOF packet asdebug("Got EOF packet"); buffer->buffer_read_ptr++; - con->warning_count= ascore_unpack_int2(buffer->buffer_read_ptr); + con->warning_count= attachsql_unpack_int2(buffer->buffer_read_ptr); buffer->buffer_read_ptr+= 2; - con->server_status= ascore_unpack_int2(buffer->buffer_read_ptr); + con->server_status= attachsql_unpack_int2(buffer->buffer_read_ptr); buffer->buffer_read_ptr+= 2; - if (con->command_status == ASCORE_COMMAND_STATUS_READ_COLUMN) + if (con->command_status == ATTACHSQL_COMMAND_STATUS_READ_COLUMN) { - con->command_status= ASCORE_COMMAND_STATUS_READ_ROW; - con->next_packet_type= ASCORE_PACKET_TYPE_ROW; - ascore_buffer_packet_read_end(con->read_buffer); + con->command_status= ATTACHSQL_COMMAND_STATUS_READ_ROW; + attachsql_packet_queue_push(con, ATTACHSQL_PACKET_TYPE_ROW); + attachsql_buffer_packet_read_end(con->read_buffer); } - else if (con->command_status == ASCORE_COMMAND_STATUS_READ_STMT_PARAM) + else if (con->command_status == ATTACHSQL_COMMAND_STATUS_READ_STMT_PARAM) { if (con->stmt->column_count > 0) { - con->command_status= ASCORE_COMMAND_STATUS_READ_STMT_COLUMN; - con->next_packet_type= ASCORE_PACKET_TYPE_PREPARE_COLUMN; - ascore_buffer_packet_read_end(con->read_buffer); + con->command_status= ATTACHSQL_COMMAND_STATUS_READ_STMT_COLUMN; + attachsql_packet_queue_push(con, ATTACHSQL_PACKET_TYPE_PREPARE_COLUMN); + attachsql_buffer_packet_read_end(con->read_buffer); } else { - con->next_packet_type= ASCORE_PACKET_TYPE_NONE; - con->command_status= ASCORE_COMMAND_STATUS_EOF; - con->status= ASCORE_CON_STATUS_IDLE; - ascore_packet_read_end(con); + con->command_status= ATTACHSQL_COMMAND_STATUS_EOF; + con->status= ATTACHSQL_CON_STATUS_IDLE; + attachsql_packet_read_end(con); } } else { - con->next_packet_type= ASCORE_PACKET_TYPE_NONE; - con->command_status= ASCORE_COMMAND_STATUS_EOF; - con->status= ASCORE_CON_STATUS_IDLE; - ascore_packet_read_end(con); + con->command_status= ATTACHSQL_COMMAND_STATUS_EOF; + con->status= ATTACHSQL_CON_STATUS_IDLE; + attachsql_packet_read_end(con); } } else { // This is a result packet asdebug("Got result packet"); - con->result.column_count= ascore_unpack_length(buffer->buffer_read_ptr, &bytes, NULL); + con->result.column_count= attachsql_unpack_length(buffer->buffer_read_ptr, &bytes, NULL); buffer->buffer_read_ptr+= bytes; con->result.columns= new (std::nothrow) column_t[con->result.column_count]; - ascore_buffer_packet_read_end(con->read_buffer); - con->next_packet_type= ASCORE_PACKET_TYPE_COLUMN; - con->command_status= ASCORE_COMMAND_STATUS_READ_COLUMN; + attachsql_buffer_packet_read_end(con->read_buffer); + attachsql_packet_queue_push(con, ATTACHSQL_PACKET_TYPE_COLUMN); + con->command_status= ATTACHSQL_COMMAND_STATUS_READ_COLUMN; } } -void ascore_packet_read_prepare_parameter(ascon_st *con) +void attachsql_packet_read_prepare_parameter(attachsql_connect_t *con) { asdebug("Prepare parameter packet read"); column_t *column; column= &con->stmt->params[con->stmt->current_param]; - ascore_packet_get_column(con, column); + attachsql_packet_get_column(con, column); con->stmt->current_param++; if (con->stmt->current_param == con->stmt->param_count) { - con->next_packet_type= ASCORE_PACKET_TYPE_RESPONSE; + attachsql_packet_queue_push(con, ATTACHSQL_PACKET_TYPE_RESPONSE); + } + else + { + attachsql_packet_queue_push(con, ATTACHSQL_PACKET_TYPE_PREPARE_PARAMETER); } } -void ascore_packet_read_prepare_column(ascon_st *con) +void attachsql_packet_read_prepare_column(attachsql_connect_t *con) { - asdebug("Prepare column packet callback"); - column_t *column; - column= &con->stmt->columns[con->stmt->current_column]; - ascore_packet_get_column(con, column); + /* Skipping these packets as they are useless */ + asdebug("Prepare column packet callback (skipped)"); + attachsql_buffer_packet_read_end(con->read_buffer); con->stmt->current_column++; if (con->stmt->current_column == con->stmt->column_count) { - con->next_packet_type= ASCORE_PACKET_TYPE_RESPONSE; + attachsql_packet_queue_push(con, ATTACHSQL_PACKET_TYPE_RESPONSE); + } + else + { + attachsql_packet_queue_push(con, ATTACHSQL_PACKET_TYPE_PREPARE_COLUMN); } } -void ascore_packet_read_column(ascon_st *con) +void attachsql_packet_read_column(attachsql_connect_t *con) { asdebug("Column packet callback"); column_t *column; column= &con->result.columns[con->result.current_column]; - ascore_packet_get_column(con, column); + attachsql_packet_get_column(con, column); con->result.current_column++; if (con->result.current_column == con->result.column_count) { - con->next_packet_type= ASCORE_PACKET_TYPE_RESPONSE; + attachsql_packet_queue_push(con, ATTACHSQL_PACKET_TYPE_RESPONSE); + } + else + { + attachsql_packet_queue_push(con, ATTACHSQL_PACKET_TYPE_COLUMN); } } - -void ascore_packet_get_column(ascon_st *con, column_t *column) +void attachsql_packet_get_column(attachsql_connect_t *con, column_t *column) { uint8_t bytes; uint64_t str_len; @@ -854,16 +874,16 @@ void ascore_packet_get_column(ascon_st *con, column_t *column) buffer_st *buffer= con->read_buffer; // Skip catalog since no MySQL version actually uses this yet - str_len= ascore_unpack_length(buffer->buffer_read_ptr, &bytes, NULL); + str_len= attachsql_unpack_length(buffer->buffer_read_ptr, &bytes, NULL); buffer->buffer_read_ptr+= bytes; buffer->buffer_read_ptr+= str_len; // Schema - str_len= ascore_unpack_length(buffer->buffer_read_ptr, &bytes, NULL); + str_len= attachsql_unpack_length(buffer->buffer_read_ptr, &bytes, NULL); buffer->buffer_read_ptr+= bytes; - if (str_len >= ASCORE_MAX_SCHEMA_SIZE) + if (str_len >= ATTACHSQL_MAX_SCHEMA_SIZE) { - str_read= ASCORE_MAX_SCHEMA_SIZE - 1; + str_read= ATTACHSQL_MAX_SCHEMA_SIZE - 1; } else { @@ -877,11 +897,11 @@ void ascore_packet_get_column(ascon_st *con, column_t *column) buffer->buffer_read_ptr+= str_len; // Table - str_len= ascore_unpack_length(buffer->buffer_read_ptr, &bytes, NULL); + str_len= attachsql_unpack_length(buffer->buffer_read_ptr, &bytes, NULL); buffer->buffer_read_ptr+= bytes; - if (str_len >= ASCORE_MAX_TABLE_SIZE) + if (str_len >= ATTACHSQL_MAX_TABLE_SIZE) { - str_read= ASCORE_MAX_TABLE_SIZE -1; + str_read= ATTACHSQL_MAX_TABLE_SIZE -1; } else { @@ -895,11 +915,11 @@ void ascore_packet_get_column(ascon_st *con, column_t *column) buffer->buffer_read_ptr+= str_len; // Origin table - str_len= ascore_unpack_length(buffer->buffer_read_ptr, &bytes, NULL); + str_len= attachsql_unpack_length(buffer->buffer_read_ptr, &bytes, NULL); buffer->buffer_read_ptr+= bytes; - if (str_len >= ASCORE_MAX_TABLE_SIZE) + if (str_len >= ATTACHSQL_MAX_TABLE_SIZE) { - str_read= ASCORE_MAX_TABLE_SIZE -1; + str_read= ATTACHSQL_MAX_TABLE_SIZE -1; } else { @@ -913,11 +933,11 @@ void ascore_packet_get_column(ascon_st *con, column_t *column) buffer->buffer_read_ptr+= str_len; // Column - str_len= ascore_unpack_length(buffer->buffer_read_ptr, &bytes, NULL); + str_len= attachsql_unpack_length(buffer->buffer_read_ptr, &bytes, NULL); buffer->buffer_read_ptr+= bytes; - if (str_len >= ASCORE_MAX_COLUMN_SIZE) + if (str_len >= ATTACHSQL_MAX_COLUMN_SIZE) { - str_read= ASCORE_MAX_COLUMN_SIZE -1; + str_read= ATTACHSQL_MAX_COLUMN_SIZE -1; } else { @@ -931,11 +951,11 @@ void ascore_packet_get_column(ascon_st *con, column_t *column) buffer->buffer_read_ptr+= str_len; // Origin column - str_len= ascore_unpack_length(buffer->buffer_read_ptr, &bytes, NULL); + str_len= attachsql_unpack_length(buffer->buffer_read_ptr, &bytes, NULL); buffer->buffer_read_ptr+= bytes; - if (str_len >= ASCORE_MAX_COLUMN_SIZE) + if (str_len >= ATTACHSQL_MAX_COLUMN_SIZE) { - str_read= ASCORE_MAX_COLUMN_SIZE -1; + str_read= ATTACHSQL_MAX_COLUMN_SIZE -1; } else { @@ -952,21 +972,21 @@ void ascore_packet_get_column(ascon_st *con, column_t *column) buffer->buffer_read_ptr++; // Charset - column->charset= ascore_unpack_int2(buffer->buffer_read_ptr); + column->charset= attachsql_unpack_int2(buffer->buffer_read_ptr); buffer->buffer_read_ptr+= 2; // Length - column->length= ascore_unpack_int4(buffer->buffer_read_ptr); + column->length= attachsql_unpack_int4(buffer->buffer_read_ptr); buffer->buffer_read_ptr+= 4; // Type /* direct char -> enum seems to cause signed -> unsigned conversion issues */ uint8_t type= (uint8_t)buffer->buffer_read_ptr[0]; - column->type= (ascore_column_type_t)type; + column->type= (attachsql_column_type_t)type; buffer->buffer_read_ptr++; // Flags - column->flags= (ascore_column_flags_t)ascore_unpack_int2(buffer->buffer_read_ptr); + column->flags= (attachsql_column_flags_t)attachsql_unpack_int2(buffer->buffer_read_ptr); buffer->buffer_read_ptr+= 2; // Decimals @@ -977,11 +997,11 @@ void ascore_packet_get_column(ascon_st *con, column_t *column) buffer->buffer_read_ptr+= 2; // Default value - str_len= ascore_unpack_length(buffer->buffer_read_ptr, &bytes, NULL); + str_len= attachsql_unpack_length(buffer->buffer_read_ptr, &bytes, NULL); buffer->buffer_read_ptr+= bytes; - if (str_len >= ASCORE_MAX_DEFAULT_VALUE_SIZE) + if (str_len >= ATTACHSQL_MAX_DEFAULT_VALUE_SIZE) { - str_read= ASCORE_MAX_DEFAULT_VALUE_SIZE -1; + str_read= ATTACHSQL_MAX_DEFAULT_VALUE_SIZE -1; } else { @@ -994,5 +1014,70 @@ void ascore_packet_get_column(ascon_st *con, column_t *column) column->default_size= str_read; buffer->buffer_read_ptr+= str_len; asdebug("Got column %s.%s.%s", column->schema, column->table, column->column); - ascore_buffer_packet_read_end(con->read_buffer); + attachsql_buffer_packet_read_end(con->read_buffer); +} + +void attachsql_run_uv_loop(attachsql_connect_t *con) +{ + if (con->pool == NULL) + { + if (con->options.semi_block) + { + uv_run(con->uv_objects.loop, UV_RUN_ONCE); + } + else + { + uv_run(con->uv_objects.loop, UV_RUN_NOWAIT); + } + } +} + +bool attachsql_packet_queue_push(attachsql_connect_t *con, attachsql_packet_type_t packet_type) +{ + asdebug("Push packet type: %d, count: %zu", packet_type, con->next_packet_queue_used+1); + attachsql_packet_type_t *new_queue= NULL; + if (con->next_packet_queue_size == 0) + { + con->next_packet_queue= (attachsql_packet_type_t*)malloc(sizeof(attachsql_packet_type_t) * ATTACHSQL_DEFAULT_PACKET_QUEUE_SIZE); + con->next_packet_queue_size= ATTACHSQL_DEFAULT_PACKET_QUEUE_SIZE; + if (con->next_packet_queue == NULL) + { + return false; + } + } + + if (con->next_packet_queue_used >= con->next_packet_queue_size) + { + new_queue= (attachsql_packet_type_t*)realloc(con->next_packet_queue, con->next_packet_queue_size * 2); + if (new_queue == NULL) + { + return false; + } + con->next_packet_queue= new_queue; + con->next_packet_queue_size= con->next_packet_queue_size * 2; + } + con->next_packet_queue[con->next_packet_queue_used]= packet_type; + con->next_packet_queue_used++; + return true; +} + +attachsql_packet_type_t attachsql_packet_queue_pop(attachsql_connect_t *con) +{ + if (con->next_packet_queue_used == 0) + { + return ATTACHSQL_PACKET_TYPE_NONE; + } + con->next_packet_queue_used--; + asdebug("Pop packet type: %d, count: %zu", con->next_packet_queue[con->next_packet_queue_used], con->next_packet_queue_used); + return con->next_packet_queue[con->next_packet_queue_used]; +} + +attachsql_packet_type_t attachsql_packet_queue_peek(attachsql_connect_t *con) +{ + asdebug("Peek packet type"); + if (con->next_packet_queue_used == 0) + { + return ATTACHSQL_PACKET_TYPE_NONE; + } + return con->next_packet_queue[con->next_packet_queue_used-1]; } diff --git a/src/net.h b/src/net.h new file mode 100644 index 0000000..2a90084 --- /dev/null +++ b/src/net.h @@ -0,0 +1,74 @@ +/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab: + * Copyright 2014 Hewlett-Packard Development Company, L.P. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. You may obtain + * a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + */ + +#pragma once + +#include "common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void attachsql_send_data(attachsql_connect_t *con, char *data, size_t length); + +void on_write(uv_write_t *req, int status); + +void attachsql_read_data_cb(uv_stream_t* tcp, ssize_t read_size, const uv_buf_t *buf); + +bool attachsql_con_process_packets(attachsql_connect_t *con); + +void attachsql_packet_read_end(attachsql_connect_t *con); + +void attachsql_packet_read_response(attachsql_connect_t *con); + +void attachsql_packet_read_prepare_response(attachsql_connect_t *con); + +void attachsql_packet_read_prepare_parameter(attachsql_connect_t *con); + +void attachsql_packet_read_prepare_column(attachsql_connect_t *con); + +void attachsql_packet_get_column(attachsql_connect_t *con, column_t *column); + +void attachsql_packet_read_column(attachsql_connect_t *con); + +void attachsql_packet_stmt_read_row(attachsql_connect_t *con); + +void attachsql_packet_read_row(attachsql_connect_t *con); + +void attachsql_run_uv_loop(attachsql_connect_t *con); + +bool attachsql_packet_queue_push(attachsql_connect_t *con, attachsql_packet_type_t packet_type); + +attachsql_packet_type_t attachsql_packet_queue_pop(attachsql_connect_t *con); + +attachsql_packet_type_t attachsql_packet_queue_peek(attachsql_connect_t *con); + +#ifdef HAVE_ZLIB +void attachsql_send_compressed_packet(attachsql_connect_t *con, char *data, size_t length, uint8_t command); +#endif + +#ifdef HAVE_OPENSSL +void attachsql_ssl_run(attachsql_connect_t *con); + +void attachsql_ssl_data_check(attachsql_connect_t *con); + +void attachsql_ssl_handle_error(attachsql_connect_t *con, int result); +#endif + +#ifdef __cplusplus +} +#endif diff --git a/src/ascore/pack.cc b/src/pack.cc similarity index 71% rename from src/ascore/pack.cc rename to src/pack.cc index 1d3c56f..44790e9 100644 --- a/src/ascore/pack.cc +++ b/src/pack.cc @@ -25,19 +25,19 @@ * error or NULL it is reflected in 'status'. * Requires 'bytes' to be pre-allocated (status can be NULL to not use it). */ -uint64_t ascore_unpack_length(char *buffer, uint8_t *bytes, ascore_pack_status_t *status) +uint64_t attachsql_unpack_length(char *buffer, uint8_t *bytes, attachsql_pack_status_t *status) { - ascore_pack_status_t unused_status; + attachsql_pack_status_t unused_status; if (status == NULL) { status= &unused_status; } if ((bytes == NULL) || (buffer == NULL)) { - *status= ASCORE_PACK_INVALID_ARGUMENT; + *status= ATTACHSQL_PACK_INVALID_ARGUMENT; return 0; } - *status= ASCORE_PACK_OK; + *status= ATTACHSQL_PACK_OK; if ((unsigned char)buffer[0] < 0xfb) { @@ -47,30 +47,30 @@ uint64_t ascore_unpack_length(char *buffer, uint8_t *bytes, ascore_pack_status_t else if ((unsigned char)buffer[0] == 0xfb) { *bytes= 1; - *status= ASCORE_PACK_NULL; + *status= ATTACHSQL_PACK_NULL; return 0; } else if ((unsigned char)buffer[0] == 0xfc) { *bytes= 3; - return ascore_unpack_int2(buffer + 1); + return attachsql_unpack_int2(buffer + 1); } else if ((unsigned char)buffer[0] == 0xfd) { *bytes= 4; - return ascore_unpack_int3(buffer + 1); + return attachsql_unpack_int3(buffer + 1); } else { *bytes= 9; - return ascore_unpack_int8(buffer + 1); + return attachsql_unpack_int8(buffer + 1); } // If you get here, your compiler doesn't love you } -char *ascore_pack_data(char *buffer, size_t length, char *data) +char *attachsql_pack_data(char *buffer, size_t length, char *data) { - buffer= ascore_pack_length(buffer, length); + buffer= attachsql_pack_length(buffer, length); if (length > 0) { memcpy(buffer, data, length); @@ -80,7 +80,7 @@ char *ascore_pack_data(char *buffer, size_t length, char *data) return buffer; } -char *ascore_pack_length(char *buffer, size_t length) +char *attachsql_pack_length(char *buffer, size_t length) { if (length <= 0xfa) { @@ -91,28 +91,28 @@ char *ascore_pack_length(char *buffer, size_t length) { buffer[0]= 0xfc; buffer++; - ascore_pack_int2(buffer, length); + attachsql_pack_int2(buffer, length); buffer+= 2; } else if (length <= 0xffffff) { buffer[0]= 0xfd; buffer++; - ascore_pack_int3(buffer, length); + attachsql_pack_int3(buffer, length); buffer+= 3; } else { buffer[0]= 0xfe; buffer++; - ascore_pack_int8(buffer, (uint64_t)length); + attachsql_pack_int8(buffer, (uint64_t)length); buffer+= 8; } return buffer; } -char *ascore_pack_datetime(char *buffer, ascore_datetime_st *datetime, bool date_only) +char *attachsql_pack_datetime(char *buffer, attachsql_datetime_st *datetime, bool date_only) { uint8_t length= 0; @@ -120,7 +120,7 @@ char *ascore_pack_datetime(char *buffer, ascore_datetime_st *datetime, bool date { if (datetime->microsecond > 0) { - ascore_pack_int4(buffer+8, datetime->microsecond); + attachsql_pack_int4(buffer+8, datetime->microsecond); length= 11; } @@ -144,7 +144,7 @@ char *ascore_pack_datetime(char *buffer, ascore_datetime_st *datetime, bool date (datetime->month > 0) or (datetime->day > 0)) { - ascore_pack_int2(buffer+1, datetime->year); + attachsql_pack_int2(buffer+1, datetime->year); buffer[3]= (char) datetime->month; buffer[4]= (char) datetime->day; if (length == 0) @@ -158,12 +158,12 @@ char *ascore_pack_datetime(char *buffer, ascore_datetime_st *datetime, bool date return (buffer + length + 1); } -void ascore_unpack_datetime(char *buffer, size_t length, ascore_datetime_st *datetime) +void attachsql_unpack_datetime(char *buffer, size_t length, attachsql_datetime_st *datetime) { if (length) { datetime->is_negative= false; - datetime->year= ascore_unpack_int2(buffer); + datetime->year= attachsql_unpack_int2(buffer); datetime->month= buffer[2]; datetime->day= buffer[3]; if (length > 4) @@ -173,35 +173,35 @@ void ascore_unpack_datetime(char *buffer, size_t length, ascore_datetime_st *dat datetime->second= buffer[6]; if (length > 7) { - datetime->microsecond= ascore_unpack_int4(&buffer[7]); + datetime->microsecond= attachsql_unpack_int4(&buffer[7]); } } } } -void ascore_unpack_time(char *buffer, size_t length, ascore_datetime_st *datetime) +void attachsql_unpack_time(char *buffer, size_t length, attachsql_datetime_st *datetime) { if (length) { datetime->is_negative= buffer[0]; - datetime->day= ascore_unpack_int4(&buffer[1]); + datetime->day= attachsql_unpack_int4(&buffer[1]); datetime->hour= buffer[5]; datetime->minute= buffer[6]; datetime->second= buffer[7]; if (length > 8) { - datetime->microsecond= ascore_unpack_int4(&buffer[8]); + datetime->microsecond= attachsql_unpack_int4(&buffer[8]); } } } -char *ascore_pack_time(char *buffer, ascore_datetime_st *time) +char *attachsql_pack_time(char *buffer, attachsql_datetime_st *time) { uint8_t length= 0; if (time->microsecond > 0) { - ascore_pack_int4(buffer+9, time->microsecond); + attachsql_pack_int4(buffer+9, time->microsecond); length= 12; } @@ -211,7 +211,7 @@ char *ascore_pack_time(char *buffer, ascore_datetime_st *time) (time->second > 0)) { buffer[1]= time->is_negative; - ascore_pack_int4(buffer+2, time->day); + attachsql_pack_int4(buffer+2, time->day); buffer[6]= (char) time->hour; buffer[7]= (char) time->minute; buffer[8]= (char) time->second; diff --git a/src/ascore/pack.h b/src/pack.h similarity index 55% rename from src/ascore/pack.h rename to src/pack.h index c8ef1cd..7938335 100644 --- a/src/ascore/pack.h +++ b/src/pack.h @@ -26,26 +26,26 @@ extern "C" { #endif -enum ascore_pack_status_t +enum attachsql_pack_status_t { - ASCORE_PACK_OK, - ASCORE_PACK_INVALID_ARGUMENT, - ASCORE_PACK_NULL + ATTACHSQL_PACK_OK, + ATTACHSQL_PACK_INVALID_ARGUMENT, + ATTACHSQL_PACK_NULL }; -uint64_t ascore_unpack_length(char *buffer, uint8_t *bytes, ascore_pack_status_t *status); +uint64_t attachsql_unpack_length(char *buffer, uint8_t *bytes, attachsql_pack_status_t *status); -char *ascore_pack_data(char *buffer, size_t length, char *data); +char *attachsql_pack_data(char *buffer, size_t length, char *data); -char *ascore_pack_length(char *buffer, size_t length); +char *attachsql_pack_length(char *buffer, size_t length); -char *ascore_pack_datetime(char *buffer, ascore_datetime_st *datetime, bool date_only); +char *attachsql_pack_datetime(char *buffer, attachsql_datetime_st *datetime, bool date_only); -char *ascore_pack_time(char *buffer, ascore_datetime_st *datetime); +char *attachsql_pack_time(char *buffer, attachsql_datetime_st *datetime); -void ascore_unpack_time(char *buffer, size_t length, ascore_datetime_st *datetime); +void attachsql_unpack_time(char *buffer, size_t length, attachsql_datetime_st *datetime); -void ascore_unpack_datetime(char *buffer, size_t length, ascore_datetime_st *datetime); +void attachsql_unpack_datetime(char *buffer, size_t length, attachsql_datetime_st *datetime); #ifdef __cplusplus } diff --git a/src/ascore/pack_macros.h b/src/pack_macros.h similarity index 83% rename from src/ascore/pack_macros.h rename to src/pack_macros.h index 98f3b6d..245df44 100644 --- a/src/ascore/pack_macros.h +++ b/src/pack_macros.h @@ -46,19 +46,19 @@ extern "C" { #endif -#define ascore_pack_int2(__buffer, __int) do { \ +#define attachsql_pack_int2(__buffer, __int) do { \ (__buffer)[0]= (uint8_t)((__int) & 0xFF); \ (__buffer)[1]= (uint8_t)(((__int) >> 8) & 0xFF); } while (0) -#define ascore_pack_int3(__buffer, __int) do { \ +#define attachsql_pack_int3(__buffer, __int) do { \ (__buffer)[0]= (uint8_t)((__int) & 0xFF); \ (__buffer)[1]= (uint8_t)(((__int) >> 8) & 0xFF); \ (__buffer)[2]= (uint8_t)(((__int) >> 16) & 0xFF); } while (0) -#define ascore_pack_int4(__buffer, __int) do { \ +#define attachsql_pack_int4(__buffer, __int) do { \ (__buffer)[0]= (uint8_t)((__int) & 0xFF); \ (__buffer)[1]= (uint8_t)(((__int) >> 8) & 0xFF); \ (__buffer)[2]= (uint8_t)(((__int) >> 16) & 0xFF); \ (__buffer)[3]= (uint8_t)(((__int) >> 24) & 0xFF); } while (0) -#define ascore_pack_int8(__buffer, __int) do { \ +#define attachsql_pack_int8(__buffer, __int) do { \ (__buffer)[0]= (uint8_t)((__int) & 0xFF); \ (__buffer)[1]= (uint8_t)(((__int) >> 8) & 0xFF); \ (__buffer)[2]= (uint8_t)(((__int) >> 16) & 0xFF); \ @@ -68,24 +68,24 @@ extern "C" { (__buffer)[6]= (uint8_t)(((__int) >> 48) & 0xFF); \ (__buffer)[7]= (uint8_t)(((__int) >> 56) & 0xFF); } while (0) -#define ascore_unpack_int2(__buffer) \ - ((((uint8_t *)__buffer)[0]) | \ +#define attachsql_unpack_int2(__buffer) \ + (uint16_t)((((uint8_t *)__buffer)[0]) | \ ((uint16_t)(((uint8_t *)__buffer)[1]) << 8)) -#define ascore_unpack_int3(__buffer) \ +#define attachsql_unpack_int3(__buffer) \ (((uint8_t *)__buffer)[0] | \ ((uint32_t)(((uint8_t *)__buffer)[1]) << 8) | \ ((uint32_t)(((uint8_t *)__buffer)[2]) << 16)) -#define ascore_unpack_int4(__buffer) \ +#define attachsql_unpack_int4(__buffer) \ (((uint8_t *)__buffer)[0] | \ ((uint32_t)(((uint8_t *)__buffer)[1]) << 8) | \ ((uint32_t)(((uint8_t *)__buffer)[2]) << 16) | \ ((uint32_t)(((uint8_t *)__buffer)[3]) << 24)) -#define ascore_unpack_int8(__buffer) \ - (ascore_unpack_int4(__buffer) | \ - ((uint64_t)ascore_unpack_int4(((uint8_t *)__buffer)+4) << 32)) +#define attachsql_unpack_int8(__buffer) \ + (attachsql_unpack_int4(__buffer) | \ + ((uint64_t)attachsql_unpack_int4(((uint8_t *)__buffer)+4) << 32)) -#define ascore_mb_char(__c) (((__c) & 0x80) != 0) -#define ascore_mb_length(__c) \ +#define attachsql_mb_char(__c) (((__c) & 0x80) != 0) +#define attachsql_mb_length(__c) \ ((uint32_t)(__c) <= 0x7f ? 1 : \ ((uint32_t)(__c) <= 0x7ff ? 2 : \ ((uint32_t)(__c) <= 0xd7ff ? 3 : \ diff --git a/src/pool.cc b/src/pool.cc new file mode 100644 index 0000000..9b2bbda --- /dev/null +++ b/src/pool.cc @@ -0,0 +1,111 @@ +/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab: + * Copyright 2014 Hewlett-Packard Development Company, L.P. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. You may obtain + * a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + */ + +#include "config.h" +#include "common.h" + +attachsql_pool_t *attachsql_pool_create(attachsql_callback_fn *function, void *context, attachsql_error_t **error) +{ + attachsql_pool_t *pool= NULL; + + pool= new (std::nothrow) attachsql_pool_t; + + if (pool == NULL) + { + attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_ALLOC, ATTACHSQL_ERROR_LEVEL_ERROR, "82100", "Allocation failure for pool object"); + return NULL; + } + pool->loop= new (std::nothrow) uv_loop_t; + uv_loop_init(pool->loop); + if (pool->loop == NULL) + { + attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_ALLOC, ATTACHSQL_ERROR_LEVEL_ERROR, "82100", "Allocation failure for pool event loop"); + delete pool; + return NULL; + } + pool->callback_fn= function; + pool->callback_context= context; + return pool; +} + +void attachsql_pool_destroy(attachsql_pool_t *pool) +{ + size_t connection; + if (pool == NULL) + { + return; + } + for (connection= 0; connection < pool->connection_count; connection++) + { + attachsql_connect_destroy(pool->connections[connection]); + } + uv_walk(pool->loop, loop_walk_cb, NULL); + uv_run(pool->loop, UV_RUN_DEFAULT); + int ret= uv_loop_close(pool->loop); + assert(ret == 0); + delete pool->loop; + for (connection= 0; connection < pool->connection_count; connection++) + { + delete pool->connections[connection]; + } + if (pool->connections != NULL) + { + free(pool->connections); + } + delete pool; +} + +void attachsql_pool_add_connection(attachsql_pool_t *pool, attachsql_connect_t *con, attachsql_error_t **error) +{ + attachsql_connect_t **tmp_cons; + + if ((pool == NULL) || (con == NULL)) + { + attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_PARAMETER, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", "Bad parameter"); + return; + } + + tmp_cons= (attachsql_connect_t**)realloc(pool->connections, sizeof(attachsql_connect_t*) * (pool->connection_count + 1)); + if (tmp_cons != NULL) + { + pool->connections= tmp_cons; + pool->connections[pool->connection_count]= con; + con->pool= pool; + con->uv_objects.loop= pool->loop; + pool->connection_count++; + con->connection_id= pool->connection_count; + } + else + { + attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_ALLOC, ATTACHSQL_ERROR_LEVEL_ERROR, "82100", "Allocation failure for pool connection add"); + } +} + +void attachsql_pool_run(attachsql_pool_t *pool) +{ + size_t connection; + attachsql_error_t *error= NULL; + if (pool == NULL) + { + return; + } + uv_run(pool->loop, UV_RUN_NOWAIT); + for (connection= 0; connection < pool->connection_count; connection++) + { + attachsql_connect_poll(pool->connections[connection], &error); + } +} diff --git a/src/asql/query.cc b/src/query.cc similarity index 87% rename from src/asql/query.cc rename to src/query.cc index a13fa25..a06db4c 100644 --- a/src/asql/query.cc +++ b/src/query.cc @@ -16,9 +16,9 @@ */ #include "config.h" -#include "src/asql/common.h" -#include "src/asql/query_internal.h" -#include "src/ascore/ascore.h" +#include "common.h" +#include "query_internal.h" +#include "ascore.h" bool attachsql_query(attachsql_connect_t *con, size_t length, const char *statement, uint16_t parameter_count, attachsql_query_parameter_st *parameters, attachsql_error_t **error) { @@ -26,7 +26,7 @@ bool attachsql_query(attachsql_connect_t *con, size_t length, const char *statem size_t buffer_pos= 0; size_t out_len; uint16_t param; - ascore_command_status_t ret; + attachsql_command_status_t ret; if (con == NULL) { @@ -44,7 +44,7 @@ bool attachsql_query(attachsql_connect_t *con, size_t length, const char *statem /* No parameters so we can send now */ if (parameter_count == 0) { - if (con->core_con->status == ASCORE_CON_STATUS_NOT_CONNECTED) + if (con->status == ATTACHSQL_CON_STATUS_NOT_CONNECTED) { con->query_buffer= (char*)statement; con->query_buffer_length= length; @@ -52,10 +52,10 @@ bool attachsql_query(attachsql_connect_t *con, size_t length, const char *statem con->query_buffer_statement= false; return attachsql_connect(con, error); } - ret= ascore_command_send(con->core_con, ASCORE_COMMAND_QUERY, (char*)statement, length); - if (ret == ASCORE_COMMAND_STATUS_SEND_FAILED) + ret= attachsql_command_send(con, ATTACHSQL_COMMAND_QUERY, (char*)statement, length); + if (ret == ATTACHSQL_COMMAND_STATUS_SEND_FAILED) { - attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_SERVER_GONE, ATTACHSQL_ERROR_LEVEL_ERROR, "08006", con->core_con->errmsg); + attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_SERVER_GONE, ATTACHSQL_ERROR_LEVEL_ERROR, "08006", con->errmsg); return false; } return true; @@ -114,7 +114,7 @@ bool attachsql_query(attachsql_connect_t *con, size_t length, const char *statem case ATTACHSQL_ESCAPE_TYPE_CHAR: con->query_buffer[buffer_pos] = '\''; buffer_pos++; - if (con->core_con->server_status & ASCORE_SERVER_STATUS_NO_BACKSLASH_ESCAPES) + if (con->server_status & ATTACHSQL_SERVER_STATUS_NO_BACKSLASH_ESCAPES) { buffer_pos+= attachsql_query_no_backslash_escape_data(&con->query_buffer[buffer_pos], (char*)parameters[param].data, parameters[param].length); } @@ -126,7 +126,7 @@ bool attachsql_query(attachsql_connect_t *con, size_t length, const char *statem buffer_pos++; break; case ATTACHSQL_ESCAPE_TYPE_CHAR_LIKE: - if (con->core_con->server_status & ASCORE_SERVER_STATUS_NO_BACKSLASH_ESCAPES) + if (con->server_status & ATTACHSQL_SERVER_STATUS_NO_BACKSLASH_ESCAPES) { buffer_pos+= attachsql_query_no_backslash_escape_data(&con->query_buffer[buffer_pos], (char*)parameters[param].data, parameters[param].length); } @@ -169,14 +169,14 @@ bool attachsql_query(attachsql_connect_t *con, size_t length, const char *statem con->query_buffer_length= buffer_pos; con->query_buffer_statement= false; - if (con->core_con->status == ASCORE_CON_STATUS_NOT_CONNECTED) + if (con->status == ATTACHSQL_CON_STATUS_NOT_CONNECTED) { return attachsql_connect(con, error); } - ret= ascore_command_send(con->core_con, ASCORE_COMMAND_QUERY, con->query_buffer, con->query_buffer_length); - if (ret == ASCORE_COMMAND_STATUS_SEND_FAILED) + ret= attachsql_command_send(con, ATTACHSQL_COMMAND_QUERY, con->query_buffer, con->query_buffer_length); + if (ret == ATTACHSQL_COMMAND_STATUS_SEND_FAILED) { - attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_SERVER_GONE, ATTACHSQL_ERROR_LEVEL_ERROR, "08006", con->core_con->errmsg); + attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_SERVER_GONE, ATTACHSQL_ERROR_LEVEL_ERROR, "08006", con->errmsg); return false; } return true; @@ -281,12 +281,12 @@ void attachsql_query_close(attachsql_connect_t *con) } con->row= NULL; /* We are still in query if there are more results */ - if (not (con->core_con->server_status & ASCORE_SERVER_STATUS_MORE_RESULTS)) + if (not (con->server_status & ATTACHSQL_SERVER_STATUS_MORE_RESULTS)) { con->in_query= false; } - ascore_command_free(con->core_con); + attachsql_command_free(con); if (con->row_buffer_alloc_size > 0) { for (uint64_t row_pos= 0; row_pos < con->row_buffer_count; row_pos++) @@ -308,7 +308,7 @@ uint16_t attachsql_query_column_count(attachsql_connect_t *con) return 0; } - return con->core_con->result.column_count; + return con->result.column_count; } attachsql_query_column_st *attachsql_query_column_get(attachsql_connect_t *con, uint16_t column) @@ -320,7 +320,7 @@ attachsql_query_column_st *attachsql_query_column_get(attachsql_connect_t *con, { return 0; } - column_count= con->core_con->result.column_count; + column_count= con->result.column_count; if ((column > column_count) or (column < 1)) { @@ -332,7 +332,7 @@ attachsql_query_column_st *attachsql_query_column_get(attachsql_connect_t *con, con->columns= new attachsql_query_column_st[column_count]; for (current_col= 0; current_col < column_count; current_col++) { - core_column= &con->core_con->result.columns[current_col]; + core_column= &con->result.columns[current_col]; con->columns[current_col].schema= core_column->schema; con->columns[current_col].table= core_column->table; con->columns[current_col].origin_table= core_column->origin_table; @@ -368,13 +368,13 @@ attachsql_query_row_st *attachsql_query_row_get(attachsql_connect_t *con, attach return NULL; } - if (con->core_con->command_status != ASCORE_COMMAND_STATUS_ROW_IN_BUFFER) + if (con->command_status != ATTACHSQL_COMMAND_STATUS_ROW_IN_BUFFER) { attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_NO_DATA, ATTACHSQL_ERROR_LEVEL_ERROR, "02000", "No more data to retreive"); return NULL; } - total_columns= con->core_con->result.column_count; + total_columns= con->result.column_count; if (con->row == NULL) { con->row= new (std::nothrow) attachsql_query_row_st[total_columns]; @@ -386,10 +386,10 @@ attachsql_query_row_st *attachsql_query_row_get(attachsql_connect_t *con, attach return NULL; } - raw_row= con->core_con->result.row_data; + raw_row= con->result.row_data; for (column= 0; column < total_columns; column++) { - length= ascore_unpack_length(raw_row, &bytes, NULL); + length= attachsql_unpack_length(raw_row, &bytes, NULL); raw_row+= bytes; con->row[column].length= (size_t)length; con->row[column].data= raw_row; @@ -400,16 +400,19 @@ attachsql_query_row_st *attachsql_query_row_get(attachsql_connect_t *con, attach void attachsql_query_row_next(attachsql_connect_t *con) { + asdebug("Row next called"); if (con == NULL) { return; } + con->last_callback= ATTACHSQL_EVENT_NONE; + if (con->buffer_rows) { return; } - ascore_get_next_row(con->core_con); + attachsql_get_next_row(con); } uint64_t attachsql_connection_last_insert_id(attachsql_connect_t *con) @@ -419,7 +422,7 @@ uint64_t attachsql_connection_last_insert_id(attachsql_connect_t *con) return 0; } - return con->core_con->insert_id; + return con->insert_id; } uint64_t attachsql_query_affected_rows(attachsql_connect_t *con) @@ -429,7 +432,7 @@ uint64_t attachsql_query_affected_rows(attachsql_connect_t *con) return 0; } - return con->core_con->affected_rows; + return con->affected_rows; } const char *attachsql_query_info(attachsql_connect_t *con) @@ -439,7 +442,7 @@ const char *attachsql_query_info(attachsql_connect_t *con) return NULL; } - return con->core_con->server_message; + return con->server_message; } uint32_t attachsql_query_warning_count(attachsql_connect_t *con) @@ -449,7 +452,7 @@ uint32_t attachsql_query_warning_count(attachsql_connect_t *con) return 0; } - return con->core_con->warning_count; + return con->warning_count; } attachsql_return_t attachsql_query_next_result(attachsql_connect_t *con) @@ -459,7 +462,7 @@ attachsql_return_t attachsql_query_next_result(attachsql_connect_t *con) return ATTACHSQL_RETURN_ERROR; } - if (ascore_command_next_result(con->core_con)) + if (attachsql_command_next_result(con)) { return ATTACHSQL_RETURN_PROCESSING; } @@ -524,7 +527,7 @@ attachsql_return_t attachsql_query_row_buffer(attachsql_connect_t *con, attachsq con->row_buffer= realloc_buffer; } - total_columns= con->core_con->result.column_count; + total_columns= con->result.column_count; row= new (std::nothrow) attachsql_query_row_st[total_columns]; if (row == NULL) @@ -533,10 +536,10 @@ attachsql_return_t attachsql_query_row_buffer(attachsql_connect_t *con, attachsq return ATTACHSQL_RETURN_ERROR; } - raw_row= con->core_con->result.row_data; + raw_row= con->result.row_data; for (column= 0; column < total_columns; column++) { - length= ascore_unpack_length(raw_row, &bytes, NULL); + length= attachsql_unpack_length(raw_row, &bytes, NULL); raw_row+= bytes; row[column].length= (size_t)length; row[column].data= raw_row; @@ -545,8 +548,8 @@ attachsql_return_t attachsql_query_row_buffer(attachsql_connect_t *con, attachsq con->row_buffer[con->row_buffer_count]= row; con->row_buffer_count++; - ascore_get_next_row(con->core_con); - } while (ascore_con_process_packets(con->core_con) and (con->core_con->status != ASCORE_CON_STATUS_IDLE)); + attachsql_get_next_row(con); + } while (attachsql_con_process_packets(con) and (con->status != ATTACHSQL_CON_STATUS_IDLE)); return ATTACHSQL_RETURN_PROCESSING; } diff --git a/src/asql/query_internal.h b/src/query_internal.h similarity index 97% rename from src/asql/query_internal.h rename to src/query_internal.h index 4f605ed..e87b840 100644 --- a/src/asql/query_internal.h +++ b/src/query_internal.h @@ -18,7 +18,7 @@ #pragma once #include -#include "src/ascore/ascore.h" +#include "ascore.h" #ifdef __cplusplus extern "C" { diff --git a/src/ascore/return.h b/src/return.h similarity index 56% rename from src/ascore/return.h rename to src/return.h index ef6df67..e7b8d77 100644 --- a/src/ascore/return.h +++ b/src/return.h @@ -21,25 +21,25 @@ extern "C" { #endif -enum asret_t { - ASRET_OK, - ASRET_PARAMETER_ERROR, - ASRET_CONNECTING, - ASRET_DNS_ERROR, - ASRET_CONNECT_ERROR, - ASRET_OUT_OF_MEMORY_ERROR, - ASRET_NO_SCRAMBLE, - ASRET_USER_TOO_LONG, - ASRET_SCHEMA_TOO_LONG, - ASRET_NET_READ_ERROR, - ASRET_NET_SSL_ERROR, - ASRET_NET_WRITE_ERROR, - ASRET_PACKET_OUT_OF_SEQUENCE, - ASRET_BAD_PROTOCOL, - ASRET_NO_OLD_AUTH, - ASRET_BAD_SCRAMBLE, - ASRET_COMPRESSION_FAILURE, - ASRET_BAD_STMT_PARAMETER +enum attachsql_ret_t { + ATTACHSQL_RET_OK, + ATTACHSQL_RET_PARAMETER_ERROR, + ATTACHSQL_RET_CONNECTING, + ATTACHSQL_RET_DNS_ERROR, + ATTACHSQL_RET_CONNECT_ERROR, + ATTACHSQL_RET_OUT_OF_MEMORY_ERROR, + ATTACHSQL_RET_NO_SCRAMBLE, + ATTACHSQL_RET_USER_TOO_LONG, + ATTACHSQL_RET_SCHEMA_TOO_LONG, + ATTACHSQL_RET_NET_READ_ERROR, + ATTACHSQL_RET_NET_SSL_ERROR, + ATTACHSQL_RET_NET_WRITE_ERROR, + ATTACHSQL_RET_PACKET_OUT_OF_SEQUENCE, + ATTACHSQL_RET_BAD_PROTOCOL, + ATTACHSQL_RET_NO_OLD_AUTH, + ATTACHSQL_RET_BAD_SCRAMBLE, + ATTACHSQL_RET_COMPRESSION_FAILURE, + ATTACHSQL_RET_BAD_STMT_PARAMETER }; #ifdef __cplusplus diff --git a/src/ascore/sha1.cc b/src/sha1.cc similarity index 98% rename from src/ascore/sha1.cc rename to src/sha1.cc index 6718605..f44de67 100644 --- a/src/ascore/sha1.cc +++ b/src/sha1.cc @@ -103,6 +103,11 @@ SHA1Transform(uint32_t state[5], const uint8_t buffer[SHA1_BLOCK_LENGTH]) /* Wipe variables */ a = b = c = d = e = 0; + (void) a; + (void) b; + (void) c; + (void) d; + (void) e; } diff --git a/src/ascore/sha1.h b/src/sha1.h similarity index 100% rename from src/ascore/sha1.h rename to src/sha1.h diff --git a/src/statement.cc b/src/statement.cc new file mode 100644 index 0000000..a66938b --- /dev/null +++ b/src/statement.cc @@ -0,0 +1,358 @@ +/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab: + * Copyright 2014 Hewlett-Packard Development Company, L.P. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. You may obtain + * a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + */ + +#include "config.h" +#include "common.h" +#include "statement.h" +#include "command.h" +#include "net.h" + +bool attachsql_statement_prepare(attachsql_connect_t *con, size_t length, const char *statement, attachsql_error_t **error) +{ + if (con->status == ATTACHSQL_CON_STATUS_NOT_CONNECTED) + { + con->query_buffer= (char*)statement; + con->query_buffer_length= length; + con->query_buffer_alloc= false; + con->query_buffer_statement= true; + return attachsql_connect(con, error); + } + con->stmt= new (std::nothrow) attachsql_stmt_st; + + if (con->stmt == NULL) + { + con->local_errcode= ATTACHSQL_RET_OUT_OF_MEMORY_ERROR; + con->command_status= ATTACHSQL_COMMAND_STATUS_SEND_FAILED; + attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_ALLOC, ATTACHSQL_ERROR_LEVEL_ERROR, "82100", "Allocation failure for statement object"); + return false; + } + + con->stmt->con= con; + asdebug("Sending MySQL prepare"); + attachsql_command_send(con, ATTACHSQL_COMMAND_STMT_PREPARE, (char*)statement, length); + + return true; +} + +bool attachsql_statement_execute(attachsql_connect_t *con, attachsql_error_t **error) +{ + if (con == NULL) + { + attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_PARAMETER, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", "No connection provided"); + return false; + } + if (con->stmt == NULL) + { + attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_PARAMETER, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", "No statement prepared"); + return false; + } + /* Free anything left over from last exec */ + attachsql_command_free(con); + if (not attachsql_stmt_execute(con->stmt)) + { + if (con->local_errcode == ATTACHSQL_RET_BAD_STMT_PARAMETER) + { + attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_PARAMETER, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", "Bad parameter bound to statement"); + return false; + } + else + { + attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_ALLOC, ATTACHSQL_ERROR_LEVEL_ERROR, "82100", "Allocation failure for statement object"); + return false; + } + } + return true; +} + +bool attachsql_stmt_execute(attachsql_stmt_st *stmt) +{ + char *buffer_pos= NULL; + uint16_t param_count= 0; + + /* Need minimum of 2K plus a bit extra for packet header */ + if (not attachsql_stmt_check_buffer_size(stmt, 2060)) + { + return false; + } + buffer_pos= stmt->exec_buffer; + + /* statement ID */ + attachsql_pack_int4(buffer_pos, stmt->id); + buffer_pos+= 4; + /* cursor flags */ + buffer_pos[0]= ATTACHSQL_STMT_CURSOR_NONE; + buffer_pos++; + /* iteration count (always 1) */ + attachsql_pack_int4(buffer_pos, 1); + buffer_pos+= 4; + /* NULL bitmask */ + if (stmt->param_count > 0) + { + uint16_t null_bytes= (stmt->param_count + 7) / 8; + memset(buffer_pos, 0, null_bytes); + param_count= stmt->param_count; + for (uint16_t param= 0; param < stmt->param_count; param++) + { + if (stmt->param_data[param].type == ATTACHSQL_COLUMN_TYPE_NULL) + { + buffer_pos[param/8] |= (1 << (param % 8)); + param_count--; + } + } + buffer_pos+= null_bytes; + } + /* New bind? */ + buffer_pos[0]= stmt->new_bind; + buffer_pos++; + /* Bind params + * First part is type of each parameter, 2 bytes per type + * Second part is the parameters themselves + * param_count is the number of params without NULL since they don't store type data + */ + char *param_type_pos= buffer_pos; + size_t param_bytes= 0; + size_t buffer_bytes= 0; + buffer_pos+= (param_count * 2); + for (uint16_t param= 0; param < stmt->param_count; param++) + { + attachsql_stmt_param_st *param_data= &stmt->param_data[param]; + + uint16_t type= (uint16_t)param_data->type; + if (type == ATTACHSQL_COLUMN_TYPE_NULL) + { + continue; + } + if (param_data->is_unsigned) + { + type|= ATTACHSQL_STMT_PARAM_UNSIGNED_BIT; + } + attachsql_pack_int2(¶m_type_pos[param * 2], type); + + /* Long data skipped */ + if (param_data->is_long_data) + { + continue; + } + + /* Check buffer for at least attachsql_datetime_st bytes + * restore pointers too + */ + param_bytes= param_type_pos - stmt->exec_buffer; + buffer_bytes= buffer_pos - stmt->exec_buffer; + if (not attachsql_stmt_check_buffer_size(stmt, sizeof(attachsql_datetime_st))) + { + return false; + } + param_type_pos= stmt->exec_buffer + param_bytes; + buffer_pos= stmt->exec_buffer + buffer_bytes; + + switch (param_data->type) + { + case ATTACHSQL_COLUMN_TYPE_TINY: + buffer_pos[0]= param_data->data.tinyint_data; + buffer_pos++; + break; + case ATTACHSQL_COLUMN_TYPE_SHORT: + attachsql_pack_int2(buffer_pos, param_data->data.smallint_data); + buffer_pos+= 2; + break; + case ATTACHSQL_COLUMN_TYPE_LONG: + attachsql_pack_int4(buffer_pos, param_data->data.int_data); + buffer_pos+= 4; + break; + case ATTACHSQL_COLUMN_TYPE_LONGLONG: + attachsql_pack_int8(buffer_pos, param_data->data.bigint_data); + buffer_pos+= 8; + break; + case ATTACHSQL_COLUMN_TYPE_FLOAT: + memcpy(buffer_pos, ¶m_data->data.float_data, 4); + buffer_pos+= 4; + break; + case ATTACHSQL_COLUMN_TYPE_DOUBLE: + memcpy(buffer_pos, ¶m_data->data.double_data, 8); + buffer_pos+= 8; + break; + case ATTACHSQL_COLUMN_TYPE_TIME: + buffer_pos= attachsql_pack_time(buffer_pos, param_data->data.datetime_data); + break; + case ATTACHSQL_COLUMN_TYPE_DATE: + buffer_pos= attachsql_pack_datetime(buffer_pos, param_data->data.datetime_data, true); + break; + case ATTACHSQL_COLUMN_TYPE_DATETIME: + case ATTACHSQL_COLUMN_TYPE_TIMESTAMP: + buffer_pos= attachsql_pack_datetime(buffer_pos, param_data->data.datetime_data, false); + break; + case ATTACHSQL_COLUMN_TYPE_STRING: + case ATTACHSQL_COLUMN_TYPE_BLOB: + /* check buffer for size */ + param_bytes= param_type_pos - stmt->exec_buffer; + buffer_bytes= buffer_pos - stmt->exec_buffer; + if (not attachsql_stmt_check_buffer_size(stmt, param_data->length)) + { + return false; + } + param_type_pos= stmt->exec_buffer + param_bytes; + buffer_pos= stmt->exec_buffer + buffer_bytes; + buffer_pos= attachsql_pack_data(buffer_pos, param_data->length, param_data->data.string_data); + break; + case ATTACHSQL_COLUMN_TYPE_NULL: + /* Already handled in the NULL bitmask we should not get here */ + /* The following should never happen, but are listed to make compilers happy bunnies */ + case ATTACHSQL_COLUMN_TYPE_INT24: + case ATTACHSQL_COLUMN_TYPE_YEAR: + case ATTACHSQL_COLUMN_TYPE_VARCHAR: + case ATTACHSQL_COLUMN_TYPE_BIT: + case ATTACHSQL_COLUMN_TYPE_NEWDECIMAL: + case ATTACHSQL_COLUMN_TYPE_ENUM: + case ATTACHSQL_COLUMN_TYPE_SET: + case ATTACHSQL_COLUMN_TYPE_TINY_BLOB: + case ATTACHSQL_COLUMN_TYPE_MEDIUM_BLOB: + case ATTACHSQL_COLUMN_TYPE_LONG_BLOB: + case ATTACHSQL_COLUMN_TYPE_VARSTRING: + case ATTACHSQL_COLUMN_TYPE_GEOMETRY: + case ATTACHSQL_COLUMN_TYPE_DECIMAL: + case ATTACHSQL_COLUMN_TYPE_ERROR: + default: + stmt->con->local_errcode= ATTACHSQL_RET_BAD_STMT_PARAMETER; + asdebug("Bad stmt parameter type provided: %d", param_data->type); + stmt->con->command_status= ATTACHSQL_COMMAND_STATUS_SEND_FAILED; + stmt->con->next_packet_queue_used= 0; + return false; + break; + } + } + if (attachsql_command_send(stmt->con, ATTACHSQL_COMMAND_STMT_EXECUTE, stmt->exec_buffer, buffer_pos - stmt->exec_buffer) != ATTACHSQL_COMMAND_STATUS_SEND) + { + return false; + } + return true; +} + +bool attachsql_stmt_check_buffer_size(attachsql_stmt_st *stmt, size_t required) +{ + char *realloc_buffer= NULL; + + if (stmt->exec_buffer_length < required) + { + size_t new_size= 0; + if (stmt->exec_buffer_length == 0) + { + new_size= ATTACHSQL_STMT_EXEC_DEFAULT_SIZE; + } + else + { + new_size= stmt->exec_buffer_length * 2; + } + realloc_buffer= (char*)realloc(stmt->exec_buffer, new_size); + if (realloc_buffer == NULL) + { + stmt->con->local_errcode= ATTACHSQL_RET_OUT_OF_MEMORY_ERROR; + asdebug("Exec buffer realloc failure"); + stmt->con->command_status= ATTACHSQL_COMMAND_STATUS_SEND_FAILED; + stmt->con->next_packet_queue_used= 0; + return false; + } + stmt->exec_buffer= realloc_buffer; + stmt->exec_buffer_length= new_size; + } + return true; +} + +attachsql_command_status_t attachsql_stmt_fetch(attachsql_stmt_st *stmt) +{ + attachsql_buffer_packet_read_end(stmt->con->read_buffer); + attachsql_packet_queue_push(stmt->con, ATTACHSQL_PACKET_TYPE_STMT_ROW); + stmt->con->command_status= ATTACHSQL_COMMAND_STATUS_READ_STMT_ROW; + attachsql_con_process_packets(stmt->con); + return stmt->con->command_status; +} + +void attachsql_statement_close(attachsql_connect_t *con) +{ + if (con == NULL) + { + return; + } + + attachsql_stmt_st *stmt= con->stmt; + + if (con->stmt_row != NULL) + { + delete[] con->stmt_row; + } + con->stmt_row= NULL; + + if (stmt == NULL) + { + return; + } + + if (stmt->param_count > 0) + { + delete[] stmt->params; + } + + if (stmt->exec_buffer_length > 0) + { + free(stmt->exec_buffer); + } + + if (stmt->param_data != NULL) + { + for (uint16_t param= 0; param < stmt->param_count; param++) + { + if (stmt->param_data[param].datetime_alloc) + { + delete stmt->param_data[param].data.datetime_data; + } + } + delete[] stmt->param_data; + } + + con->stmt= NULL; + con->write_buffer_extra= 4; + attachsql_command_free(con); + attachsql_pack_int4(&con->write_buffer[1], stmt->id); + attachsql_command_send(con, ATTACHSQL_COMMAND_STMT_CLOSE, NULL, 0); + delete stmt; +} + +bool attachsql_statement_reset(attachsql_connect_t *con, attachsql_error_t **error) +{ + if (con == NULL) + { + attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_PARAMETER, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", "No connection provided"); + return false; + } + if (con->stmt == NULL) + { + attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_PARAMETER, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", "No statement prepared"); + return false; + } + + con->write_buffer_extra= 4; + attachsql_pack_int4(&con->write_buffer[1], con->stmt->id); + + if (attachsql_command_send(con, ATTACHSQL_COMMAND_STMT_RESET, NULL, 0) == ATTACHSQL_COMMAND_STATUS_SEND_FAILED) + { + attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_SERVER_GONE, ATTACHSQL_ERROR_LEVEL_ERROR, "08006", con->errmsg); + return false; + } + + return true; +} + diff --git a/src/asql/connect_internal.h b/src/statement.h similarity index 62% rename from src/asql/connect_internal.h rename to src/statement.h index 627a2aa..6bc08ef 100644 --- a/src/asql/connect_internal.h +++ b/src/statement.h @@ -2,7 +2,7 @@ * Copyright 2014 Hewlett-Packard Development Company, L.P. * * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. You may obtain + * not use this file except in compliance with the License. You may obtain * a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 @@ -17,15 +17,21 @@ #pragma once -#include "src/ascore/ascore.h" +#include "config.h" +#include "common.h" #ifdef __cplusplus extern "C" { #endif -attachsql_return_t attachsql_connect_query(attachsql_connect_t *con, attachsql_error_t **error); +bool attachsql_stmt_execute(attachsql_stmt_st *stmt); + +bool attachsql_stmt_check_buffer_size(attachsql_stmt_st *stmt, size_t required); + +attachsql_command_status_t attachsql_stmt_fetch(attachsql_stmt_st *stmt); + +bool attachsql_statement_set_param(attachsql_connect_t *con, attachsql_column_type_t type, uint16_t param, size_t length, const void *value, bool is_unsigned, attachsql_error_t **error); #ifdef __cplusplus } #endif - diff --git a/src/statement_getset.cc b/src/statement_getset.cc new file mode 100644 index 0000000..d962ffc --- /dev/null +++ b/src/statement_getset.cc @@ -0,0 +1,903 @@ +/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab: + * Copyright 2014 Hewlett-Packard Development Company, L.P. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. You may obtain + * a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + */ + +#include "config.h" +#include "common.h" +#include "ascore.h" +#include "statement.h" + +bool attachsql_statement_send_long_data(attachsql_connect_t *con, uint16_t param, size_t length, char *data, attachsql_error_t **error) +{ + if (con == NULL) + { + attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_PARAMETER, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", "No statement provided"); + return false; + } + if (con->stmt == NULL) + { + attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_PARAMETER, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", "No statement prepared"); + return false; + } + con->write_buffer_extra= 6; + attachsql_pack_int4(&con->write_buffer[1], con->stmt->id); + attachsql_pack_int2(&con->write_buffer[5], param); + + if (attachsql_command_send(con, ATTACHSQL_COMMAND_STMT_SEND_LONG_DATA, data, length) == ATTACHSQL_COMMAND_STATUS_SEND_FAILED) + { + attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_SERVER_GONE, ATTACHSQL_ERROR_LEVEL_ERROR, "08006", con->errmsg); + return false; + } + + return true; +} + +uint16_t attachsql_statement_get_param_count(attachsql_connect_t *con) +{ + if ((con == NULL) || (con->stmt == NULL)) + { + return 0; + } + return con->stmt->param_count; +} + +bool attachsql_statement_set_int(attachsql_connect_t *con, uint16_t param, int32_t value, attachsql_error_t **error) +{ + return attachsql_statement_set_param(con, ATTACHSQL_COLUMN_TYPE_LONG, param, 0, &value, false, error); +} + +bool attachsql_statement_set_unsigned_int(attachsql_connect_t *con, uint16_t param, uint32_t value, attachsql_error_t **error) +{ + return attachsql_statement_set_param(con, ATTACHSQL_COLUMN_TYPE_LONG, param, 0, &value, true, error); +} + +bool attachsql_statement_set_bigint(attachsql_connect_t *con, uint16_t param, int64_t value, attachsql_error_t **error) +{ + return attachsql_statement_set_param(con, ATTACHSQL_COLUMN_TYPE_LONGLONG, param, 0, &value, false, error); +} + +bool attachsql_statement_set_unsigned_bigint(attachsql_connect_t *con, uint16_t param, uint64_t value, attachsql_error_t **error) +{ + return attachsql_statement_set_param(con, ATTACHSQL_COLUMN_TYPE_LONGLONG, param, 0, &value, true, error); +} + +bool attachsql_statement_set_double(attachsql_connect_t *con, uint16_t param, double value, attachsql_error_t **error) +{ + return attachsql_statement_set_param(con, ATTACHSQL_COLUMN_TYPE_DOUBLE, param, 0, &value, false, error); +} + +bool attachsql_statement_set_string(attachsql_connect_t *con, uint16_t param, size_t length, const char *value, attachsql_error_t **error) +{ + return attachsql_statement_set_param(con, ATTACHSQL_COLUMN_TYPE_STRING, param, length, value, false, error); +} + +bool attachsql_statement_set_binary(attachsql_connect_t *con, uint16_t param, size_t length, const char *value, attachsql_error_t **error) +{ + return attachsql_statement_set_param(con, ATTACHSQL_COLUMN_TYPE_BLOB, param, length, value, false, error); +} + +bool attachsql_statement_set_null(attachsql_connect_t *con, uint16_t param, attachsql_error_t **error) +{ + return attachsql_statement_set_param(con, ATTACHSQL_COLUMN_TYPE_NULL, param, 0, NULL, false, error); +} + +bool attachsql_statement_set_datetime(attachsql_connect_t *con, uint16_t param, uint16_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t minute, uint8_t second, uint32_t microsecond, attachsql_error_t **error) +{ + if ((con == NULL) || (con->stmt == NULL)) + { + attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_PARAMETER, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", "Connection parameter not valid"); + return false; + } + + if (param >= con->stmt->param_count) + { + attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_PARAMETER, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", "Param %d does not exist", param); + return false; + } + con->stmt->param_data[param].data.datetime_data= new attachsql_datetime_st; + con->stmt->param_data[param].datetime_alloc= true; + con->stmt->param_data[param].data.datetime_data->year= year; + con->stmt->param_data[param].data.datetime_data->month= month; + con->stmt->param_data[param].data.datetime_data->day= day; + con->stmt->param_data[param].data.datetime_data->hour= hour; + con->stmt->param_data[param].data.datetime_data->minute= minute; + con->stmt->param_data[param].data.datetime_data->second= second; + con->stmt->param_data[param].data.datetime_data->microsecond= microsecond; + con->stmt->param_data[param].type= ATTACHSQL_COLUMN_TYPE_DATETIME; + + return true; +} + +bool attachsql_statement_set_time(attachsql_connect_t *con, uint16_t param, uint8_t hour, uint8_t minute, uint8_t second, uint32_t microsecond, bool is_negative, attachsql_error_t **error) +{ + if ((con == NULL) || (con->stmt == NULL)) + { + attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_PARAMETER, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", "Connection parameter not valid"); + return false; + } + + if (param >= con->stmt->param_count) + { + attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_PARAMETER, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", "Param %d does not exist", param); + return false; + } + con->stmt->param_data[param].data.datetime_data= new attachsql_datetime_st; + con->stmt->param_data[param].datetime_alloc= false; + con->stmt->param_data[param].data.datetime_data->hour= hour; + con->stmt->param_data[param].data.datetime_data->minute= minute; + con->stmt->param_data[param].data.datetime_data->second= second; + con->stmt->param_data[param].data.datetime_data->microsecond= microsecond; + con->stmt->param_data[param].data.datetime_data->is_negative= is_negative; + con->stmt->param_data[param].type= ATTACHSQL_COLUMN_TYPE_TIME; + + return true; +} + +bool attachsql_statement_set_param(attachsql_connect_t *con, attachsql_column_type_t type, uint16_t param, size_t length, const void *value, bool is_unsigned, attachsql_error_t **error) +{ + if ((con == NULL) || (con->stmt == NULL)) + { + attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_PARAMETER, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", "Connection parameter not valid"); + return false; + } + + if (param >= con->stmt->param_count) + { + attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_PARAMETER, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", "Param %d does not exist", param); + return false; + } + + switch (type) + { + case ATTACHSQL_COLUMN_TYPE_LONG: + con->stmt->param_data[param].data.int_data= *(uint32_t*)value; + con->stmt->param_data[param].is_unsigned= is_unsigned; + con->stmt->param_data[param].type= type; + break; + case ATTACHSQL_COLUMN_TYPE_LONGLONG: + con->stmt->param_data[param].data.bigint_data= *(uint64_t*)value; + con->stmt->param_data[param].is_unsigned= is_unsigned; + con->stmt->param_data[param].type= type; + break; + case ATTACHSQL_COLUMN_TYPE_FLOAT: + con->stmt->param_data[param].data.float_data= *(float*)value; + con->stmt->param_data[param].is_unsigned= false; + con->stmt->param_data[param].type= type; + break; + case ATTACHSQL_COLUMN_TYPE_DOUBLE: + con->stmt->param_data[param].data.double_data= *(double*)value; + con->stmt->param_data[param].is_unsigned= false; + con->stmt->param_data[param].type= type; + break; + case ATTACHSQL_COLUMN_TYPE_STRING: + case ATTACHSQL_COLUMN_TYPE_BLOB: + con->stmt->param_data[param].data.string_data= (char*)value; + con->stmt->param_data[param].length= length; + con->stmt->param_data[param].type= type; + break; + case ATTACHSQL_COLUMN_TYPE_NULL: + con->stmt->param_data[param].type= type;; + break; + /* the following won't happen, but this will keep the compiler happy */ + case ATTACHSQL_COLUMN_TYPE_DECIMAL: + case ATTACHSQL_COLUMN_TYPE_TINY: + case ATTACHSQL_COLUMN_TYPE_SHORT: + case ATTACHSQL_COLUMN_TYPE_TIMESTAMP: + case ATTACHSQL_COLUMN_TYPE_INT24: + case ATTACHSQL_COLUMN_TYPE_DATE: + case ATTACHSQL_COLUMN_TYPE_TIME: + case ATTACHSQL_COLUMN_TYPE_DATETIME: + case ATTACHSQL_COLUMN_TYPE_YEAR: + case ATTACHSQL_COLUMN_TYPE_VARCHAR: + case ATTACHSQL_COLUMN_TYPE_BIT: + case ATTACHSQL_COLUMN_TYPE_NEWDECIMAL: + case ATTACHSQL_COLUMN_TYPE_ENUM: + case ATTACHSQL_COLUMN_TYPE_SET: + case ATTACHSQL_COLUMN_TYPE_TINY_BLOB: + case ATTACHSQL_COLUMN_TYPE_MEDIUM_BLOB: + case ATTACHSQL_COLUMN_TYPE_LONG_BLOB: + case ATTACHSQL_COLUMN_TYPE_VARSTRING: + case ATTACHSQL_COLUMN_TYPE_GEOMETRY: + case ATTACHSQL_COLUMN_TYPE_ERROR: + break; + } + + return true; +} + +bool attachsql_statement_row_get(attachsql_connect_t *con, attachsql_error_t **error) +{ + char *raw_row; + uint16_t column; + uint16_t total_columns; + uint8_t bytes= 0; + uint64_t length; + + if (con == NULL) + { + attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_PARAMETER, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", "Connection parameter not valid"); + return false; + } + + total_columns= con->result.column_count; + if (con->stmt_row == NULL) + { + con->stmt_row= new (std::nothrow) attachsql_stmt_row_st[total_columns]; + } + + if (con->stmt_row == NULL) + { + attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_ALLOC, ATTACHSQL_ERROR_LEVEL_ERROR, "82100", "Allocation failure for row"); + return false; + } + + raw_row= con->result.row_data; + /* packet header */ + raw_row++; + con->stmt_null_bitmap_length= ((total_columns+7+2)/8); + con->stmt_null_bitmap= raw_row; + raw_row+= con->stmt_null_bitmap_length; + + for (column= 0; column < total_columns; column++) + { + attachsql_column_type_t type= con->result.columns[column].type; + /* Really complex way of saying "if this is in the NULL bitmap */ + if (con->stmt_null_bitmap[(column+2)/8] & (1 << ((column+2) % 8))) + { + type= ATTACHSQL_COLUMN_TYPE_NULL; + } + switch(type) + { + case ATTACHSQL_COLUMN_TYPE_STRING: + case ATTACHSQL_COLUMN_TYPE_VARCHAR: + case ATTACHSQL_COLUMN_TYPE_VARSTRING: + case ATTACHSQL_COLUMN_TYPE_ENUM: + case ATTACHSQL_COLUMN_TYPE_SET: + case ATTACHSQL_COLUMN_TYPE_LONG_BLOB: + case ATTACHSQL_COLUMN_TYPE_MEDIUM_BLOB: + case ATTACHSQL_COLUMN_TYPE_TINY_BLOB: + case ATTACHSQL_COLUMN_TYPE_BLOB: + case ATTACHSQL_COLUMN_TYPE_GEOMETRY: + case ATTACHSQL_COLUMN_TYPE_BIT: + case ATTACHSQL_COLUMN_TYPE_DECIMAL: + case ATTACHSQL_COLUMN_TYPE_NEWDECIMAL: + length= attachsql_unpack_length(raw_row, &bytes, NULL); + raw_row+= bytes; + break; + case ATTACHSQL_COLUMN_TYPE_DATE: + case ATTACHSQL_COLUMN_TYPE_DATETIME: + case ATTACHSQL_COLUMN_TYPE_TIMESTAMP: + case ATTACHSQL_COLUMN_TYPE_TIME: + length= raw_row[0]; + raw_row++; + break; + case ATTACHSQL_COLUMN_TYPE_LONGLONG: + case ATTACHSQL_COLUMN_TYPE_DOUBLE: + length= 8; + break; + case ATTACHSQL_COLUMN_TYPE_LONG: + case ATTACHSQL_COLUMN_TYPE_INT24: + case ATTACHSQL_COLUMN_TYPE_FLOAT: + length= 4; + break; + case ATTACHSQL_COLUMN_TYPE_SHORT: + case ATTACHSQL_COLUMN_TYPE_YEAR: + length= 2; + break; + case ATTACHSQL_COLUMN_TYPE_TINY: + length= 1; + break; + case ATTACHSQL_COLUMN_TYPE_NULL: + /* in NULL bitmask only */ + length= 0; + break; + case ATTACHSQL_COLUMN_TYPE_ERROR: + default: + attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_UNKNOWN, ATTACHSQL_ERROR_LEVEL_ERROR, "60000", "Bad data in statement result"); + return false; + } + con->stmt_row[column].data= raw_row; + con->stmt_row[column].length= (size_t)length; + con->stmt_row[column].type= type; + raw_row+= length; + } + return true; +} + +int32_t attachsql_statement_get_int(attachsql_connect_t *con, uint16_t column, attachsql_error_t **error) +{ + if (con == NULL) + { + attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_PARAMETER, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", "Connection parameter not valid"); + return 0; + } + + if (con->stmt_row == NULL) + { + attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_PARAMETER, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", "Statement row has not been processed"); + return 0; + } + + if (column >= con->result.column_count) + { + attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_PARAMETER, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", "Column %d does not exist", column); + return 0; + } + + attachsql_stmt_row_st *column_data= &con->stmt_row[column]; + switch (column_data->type) + { + case ATTACHSQL_COLUMN_TYPE_TINY: + return (int8_t)column_data->data[0]; + break; + case ATTACHSQL_COLUMN_TYPE_YEAR: + case ATTACHSQL_COLUMN_TYPE_SHORT: + return (int16_t)attachsql_unpack_int2(column_data->data); + break; + case ATTACHSQL_COLUMN_TYPE_LONG: + return (int32_t)attachsql_unpack_int4(column_data->data); + break; + case ATTACHSQL_COLUMN_TYPE_LONGLONG: + return (int32_t)attachsql_unpack_int8(column_data->data); + break; + case ATTACHSQL_COLUMN_TYPE_FLOAT: + float f; + memcpy(&f, column_data->data, 4); + return (int32_t)f; + break; + case ATTACHSQL_COLUMN_TYPE_DOUBLE: + double d; + memcpy(&d, column_data->data, 8); + return (int32_t)d; + break; + case ATTACHSQL_COLUMN_TYPE_NULL: + return 0; + break; + case ATTACHSQL_COLUMN_TYPE_INT24: + return (int32_t)attachsql_unpack_int3(column_data->data); + break; + + case ATTACHSQL_COLUMN_TYPE_DECIMAL: + case ATTACHSQL_COLUMN_TYPE_TIMESTAMP: + case ATTACHSQL_COLUMN_TYPE_DATE: + case ATTACHSQL_COLUMN_TYPE_TIME: + case ATTACHSQL_COLUMN_TYPE_DATETIME: + case ATTACHSQL_COLUMN_TYPE_VARCHAR: + case ATTACHSQL_COLUMN_TYPE_BIT: + case ATTACHSQL_COLUMN_TYPE_NEWDECIMAL: + case ATTACHSQL_COLUMN_TYPE_ENUM: + case ATTACHSQL_COLUMN_TYPE_SET: + case ATTACHSQL_COLUMN_TYPE_TINY_BLOB: + case ATTACHSQL_COLUMN_TYPE_MEDIUM_BLOB: + case ATTACHSQL_COLUMN_TYPE_LONG_BLOB: + case ATTACHSQL_COLUMN_TYPE_BLOB: + case ATTACHSQL_COLUMN_TYPE_VARSTRING: + case ATTACHSQL_COLUMN_TYPE_STRING: + case ATTACHSQL_COLUMN_TYPE_GEOMETRY: + case ATTACHSQL_COLUMN_TYPE_ERROR: + attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_PARAMETER, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", "Cannot convert to int"); + return 0; + break; + } + /* Should never hit here, but lets make compilers happy */ + return 0; +} + + +uint32_t attachsql_statement_get_int_unsigned(attachsql_connect_t *con, uint16_t column, attachsql_error_t **error) +{ + if (con == NULL) + { + attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_PARAMETER, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", "Connection parameter not valid"); + return 0; + } + + if (con->stmt_row == NULL) + { + attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_PARAMETER, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", "Statement row has not been processed"); + return 0; + } + + if (column >= con->result.column_count) + { + attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_PARAMETER, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", "Column %d does not exist", column); + return 0; + } + + attachsql_stmt_row_st *column_data= &con->stmt_row[column]; + switch (column_data->type) + { + case ATTACHSQL_COLUMN_TYPE_TINY: + return (uint8_t)column_data->data[0]; + break; + case ATTACHSQL_COLUMN_TYPE_YEAR: + case ATTACHSQL_COLUMN_TYPE_SHORT: + return (uint16_t)attachsql_unpack_int2(column_data->data); + break; + case ATTACHSQL_COLUMN_TYPE_LONG: + return (uint32_t)attachsql_unpack_int4(column_data->data); + break; + case ATTACHSQL_COLUMN_TYPE_LONGLONG: + return (uint32_t)attachsql_unpack_int8(column_data->data); + break; + case ATTACHSQL_COLUMN_TYPE_FLOAT: + float f; + memcpy(&f, column_data->data, 4); + return (uint32_t)f; + break; + case ATTACHSQL_COLUMN_TYPE_DOUBLE: + double d; + memcpy(&d, column_data->data, 8); + return (uint32_t)d; + break; + case ATTACHSQL_COLUMN_TYPE_NULL: + return 0; + break; + case ATTACHSQL_COLUMN_TYPE_INT24: + return (uint32_t)attachsql_unpack_int3(column_data->data); + break; + + case ATTACHSQL_COLUMN_TYPE_DECIMAL: + case ATTACHSQL_COLUMN_TYPE_TIMESTAMP: + case ATTACHSQL_COLUMN_TYPE_DATE: + case ATTACHSQL_COLUMN_TYPE_TIME: + case ATTACHSQL_COLUMN_TYPE_DATETIME: + case ATTACHSQL_COLUMN_TYPE_VARCHAR: + case ATTACHSQL_COLUMN_TYPE_BIT: + case ATTACHSQL_COLUMN_TYPE_NEWDECIMAL: + case ATTACHSQL_COLUMN_TYPE_ENUM: + case ATTACHSQL_COLUMN_TYPE_SET: + case ATTACHSQL_COLUMN_TYPE_TINY_BLOB: + case ATTACHSQL_COLUMN_TYPE_MEDIUM_BLOB: + case ATTACHSQL_COLUMN_TYPE_LONG_BLOB: + case ATTACHSQL_COLUMN_TYPE_BLOB: + case ATTACHSQL_COLUMN_TYPE_VARSTRING: + case ATTACHSQL_COLUMN_TYPE_STRING: + case ATTACHSQL_COLUMN_TYPE_GEOMETRY: + case ATTACHSQL_COLUMN_TYPE_ERROR: + attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_PARAMETER, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", "Cannot convert to int"); + return 0; + break; + } + /* Should never hit here, but lets make compilers happy */ + return 0; +} + + +int64_t attachsql_statement_get_bigint(attachsql_connect_t *con, uint16_t column, attachsql_error_t **error) +{ + if (con == NULL) + { + attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_PARAMETER, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", "Connection parameter not valid"); + return 0; + } + + if (con->stmt_row == NULL) + { + attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_PARAMETER, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", "Statement row has not been processed"); + return 0; + } + + if (column >= con->result.column_count) + { + attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_PARAMETER, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", "Column %d does not exist", column); + return 0; + } + + attachsql_stmt_row_st *column_data= &con->stmt_row[column]; + switch (column_data->type) + { + case ATTACHSQL_COLUMN_TYPE_TINY: + return (int8_t)column_data->data[0]; + break; + case ATTACHSQL_COLUMN_TYPE_YEAR: + case ATTACHSQL_COLUMN_TYPE_SHORT: + return (int16_t)attachsql_unpack_int2(column_data->data); + break; + case ATTACHSQL_COLUMN_TYPE_LONG: + return (int32_t)attachsql_unpack_int4(column_data->data); + break; + case ATTACHSQL_COLUMN_TYPE_LONGLONG: + return (int64_t)attachsql_unpack_int8(column_data->data); + break; + case ATTACHSQL_COLUMN_TYPE_FLOAT: + float f; + memcpy(&f, column_data->data, 4); + return (int64_t)f; + break; + case ATTACHSQL_COLUMN_TYPE_DOUBLE: + double d; + memcpy(&d, column_data->data, 8); + return (int64_t)d; + break; + case ATTACHSQL_COLUMN_TYPE_NULL: + return 0; + break; + case ATTACHSQL_COLUMN_TYPE_INT24: + return (int32_t)attachsql_unpack_int3(column_data->data); + break; + + case ATTACHSQL_COLUMN_TYPE_DECIMAL: + case ATTACHSQL_COLUMN_TYPE_TIMESTAMP: + case ATTACHSQL_COLUMN_TYPE_DATE: + case ATTACHSQL_COLUMN_TYPE_TIME: + case ATTACHSQL_COLUMN_TYPE_DATETIME: + case ATTACHSQL_COLUMN_TYPE_VARCHAR: + case ATTACHSQL_COLUMN_TYPE_BIT: + case ATTACHSQL_COLUMN_TYPE_NEWDECIMAL: + case ATTACHSQL_COLUMN_TYPE_ENUM: + case ATTACHSQL_COLUMN_TYPE_SET: + case ATTACHSQL_COLUMN_TYPE_TINY_BLOB: + case ATTACHSQL_COLUMN_TYPE_MEDIUM_BLOB: + case ATTACHSQL_COLUMN_TYPE_LONG_BLOB: + case ATTACHSQL_COLUMN_TYPE_BLOB: + case ATTACHSQL_COLUMN_TYPE_VARSTRING: + case ATTACHSQL_COLUMN_TYPE_STRING: + case ATTACHSQL_COLUMN_TYPE_GEOMETRY: + case ATTACHSQL_COLUMN_TYPE_ERROR: + attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_PARAMETER, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", "Cannot convert to int"); + return 0; + break; + } + /* Should never hit here, but lets make compilers happy */ + return 0; +} + +uint64_t attachsql_statement_get_bigint_unsigned(attachsql_connect_t *con, uint16_t column, attachsql_error_t **error) +{ + if (con == NULL) + { + attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_PARAMETER, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", "Connection parameter not valid"); + return 0; + } + + if (con->stmt_row == NULL) + { + attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_PARAMETER, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", "Statement row has not been processed"); + return 0; + } + + if (column >= con->result.column_count) + { + attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_PARAMETER, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", "Column %d does not exist", column); + return 0; + } + + attachsql_stmt_row_st *column_data= &con->stmt_row[column]; + switch (column_data->type) + { + case ATTACHSQL_COLUMN_TYPE_TINY: + return (uint8_t)column_data->data[0]; + break; + case ATTACHSQL_COLUMN_TYPE_YEAR: + case ATTACHSQL_COLUMN_TYPE_SHORT: + return (uint16_t)attachsql_unpack_int2(column_data->data); + break; + case ATTACHSQL_COLUMN_TYPE_LONG: + return (uint32_t)attachsql_unpack_int4(column_data->data); + break; + case ATTACHSQL_COLUMN_TYPE_LONGLONG: + return (uint64_t)attachsql_unpack_int8(column_data->data); + break; + case ATTACHSQL_COLUMN_TYPE_FLOAT: + float f; + memcpy(&f, column_data->data, 4); + return (uint32_t)f; + break; + case ATTACHSQL_COLUMN_TYPE_DOUBLE: + double d; + memcpy(&d, column_data->data, 8); + return (uint32_t)d; + break; + case ATTACHSQL_COLUMN_TYPE_NULL: + return 0; + break; + case ATTACHSQL_COLUMN_TYPE_INT24: + return (uint32_t)attachsql_unpack_int3(column_data->data); + break; + + case ATTACHSQL_COLUMN_TYPE_DECIMAL: + case ATTACHSQL_COLUMN_TYPE_TIMESTAMP: + case ATTACHSQL_COLUMN_TYPE_DATE: + case ATTACHSQL_COLUMN_TYPE_TIME: + case ATTACHSQL_COLUMN_TYPE_DATETIME: + case ATTACHSQL_COLUMN_TYPE_VARCHAR: + case ATTACHSQL_COLUMN_TYPE_BIT: + case ATTACHSQL_COLUMN_TYPE_NEWDECIMAL: + case ATTACHSQL_COLUMN_TYPE_ENUM: + case ATTACHSQL_COLUMN_TYPE_SET: + case ATTACHSQL_COLUMN_TYPE_TINY_BLOB: + case ATTACHSQL_COLUMN_TYPE_MEDIUM_BLOB: + case ATTACHSQL_COLUMN_TYPE_LONG_BLOB: + case ATTACHSQL_COLUMN_TYPE_BLOB: + case ATTACHSQL_COLUMN_TYPE_VARSTRING: + case ATTACHSQL_COLUMN_TYPE_STRING: + case ATTACHSQL_COLUMN_TYPE_GEOMETRY: + case ATTACHSQL_COLUMN_TYPE_ERROR: + attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_PARAMETER, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", "Cannot convert to int"); + return 0; + break; + } + /* Should never hit here, but lets make compilers happy */ + return 0; +} + +double attachsql_statement_get_double(attachsql_connect_t *con, uint16_t column, attachsql_error_t **error) +{ + if (con == NULL) + { + attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_PARAMETER, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", "Connection parameter not valid"); + return 0; + } + + if (con->stmt_row == NULL) + { + attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_PARAMETER, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", "Statement row has not been processed"); + return 0; + } + + if (column >= con->result.column_count) + { + attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_PARAMETER, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", "Column %d does not exist", column); + return 0; + } + + attachsql_stmt_row_st *column_data= &con->stmt_row[column]; + switch (column_data->type) + { + case ATTACHSQL_COLUMN_TYPE_TINY: + return (double)column_data->data[0]; + break; + case ATTACHSQL_COLUMN_TYPE_YEAR: + case ATTACHSQL_COLUMN_TYPE_SHORT: + return (double)attachsql_unpack_int2(column_data->data); + break; + case ATTACHSQL_COLUMN_TYPE_LONG: + return (double)attachsql_unpack_int4(column_data->data); + break; + case ATTACHSQL_COLUMN_TYPE_LONGLONG: + return (double)attachsql_unpack_int8(column_data->data); + break; + case ATTACHSQL_COLUMN_TYPE_FLOAT: + float f; + memcpy(&f, column_data->data, 4); + return (double)f; + break; + case ATTACHSQL_COLUMN_TYPE_DOUBLE: + double d; + memcpy(&d, column_data->data, 8); + return d; + break; + case ATTACHSQL_COLUMN_TYPE_NULL: + return 0; + break; + case ATTACHSQL_COLUMN_TYPE_INT24: + return (double)attachsql_unpack_int3(column_data->data); + break; + + case ATTACHSQL_COLUMN_TYPE_DECIMAL: + case ATTACHSQL_COLUMN_TYPE_TIMESTAMP: + case ATTACHSQL_COLUMN_TYPE_DATE: + case ATTACHSQL_COLUMN_TYPE_TIME: + case ATTACHSQL_COLUMN_TYPE_DATETIME: + case ATTACHSQL_COLUMN_TYPE_VARCHAR: + case ATTACHSQL_COLUMN_TYPE_BIT: + case ATTACHSQL_COLUMN_TYPE_NEWDECIMAL: + case ATTACHSQL_COLUMN_TYPE_ENUM: + case ATTACHSQL_COLUMN_TYPE_SET: + case ATTACHSQL_COLUMN_TYPE_TINY_BLOB: + case ATTACHSQL_COLUMN_TYPE_MEDIUM_BLOB: + case ATTACHSQL_COLUMN_TYPE_LONG_BLOB: + case ATTACHSQL_COLUMN_TYPE_BLOB: + case ATTACHSQL_COLUMN_TYPE_VARSTRING: + case ATTACHSQL_COLUMN_TYPE_STRING: + case ATTACHSQL_COLUMN_TYPE_GEOMETRY: + case ATTACHSQL_COLUMN_TYPE_ERROR: + attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_PARAMETER, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", "Cannot convert to int"); + return 0; + break; + } + /* Should never hit here, but lets make compilers happy */ + return 0; +} + +char *attachsql_statement_get_char(attachsql_connect_t *con, uint16_t column, size_t *length, attachsql_error_t **error) +{ + if (con == NULL) + { + attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_PARAMETER, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", "Connection parameter not valid"); + return NULL; + } + + if (con->stmt_row == NULL) + { + attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_PARAMETER, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", "Statement row has not been processed"); + return NULL; + } + + if (column >= con->result.column_count) + { + attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_PARAMETER, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", "Column %d does not exist", column); + return NULL; + } + + if (length == NULL) + { + attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_PARAMETER, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", "Length parameter not valid"); + return NULL; + } + + attachsql_stmt_row_st *column_data= &con->stmt_row[column]; + attachsql_datetime_st datetime; + switch (column_data->type) + { + case ATTACHSQL_COLUMN_TYPE_TINY: + if (con->result.columns[column].flags & ATTACHSQL_COLUMN_FLAGS_UNSIGNED) + { + *length= snprintf(con->stmt_tmp_buffer, ATTACHSQL_STMT_CHAR_BUFFER_SIZE, "%" PRIu8, column_data->data[0]); + } + else + { + *length= snprintf(con->stmt_tmp_buffer, ATTACHSQL_STMT_CHAR_BUFFER_SIZE, "%" PRId8, column_data->data[0]); + } + return con->stmt_tmp_buffer; + break; + case ATTACHSQL_COLUMN_TYPE_YEAR: + case ATTACHSQL_COLUMN_TYPE_SHORT: + if (con->result.columns[column].flags & ATTACHSQL_COLUMN_FLAGS_UNSIGNED) + { + *length= snprintf(con->stmt_tmp_buffer, ATTACHSQL_STMT_CHAR_BUFFER_SIZE, "%" PRIu16, attachsql_unpack_int2(column_data->data)); + } + else + { + *length= snprintf(con->stmt_tmp_buffer, ATTACHSQL_STMT_CHAR_BUFFER_SIZE, "%" PRId16, attachsql_unpack_int2(column_data->data)); + } + return con->stmt_tmp_buffer; + break; + case ATTACHSQL_COLUMN_TYPE_LONG: + if (con->result.columns[column].flags & ATTACHSQL_COLUMN_FLAGS_UNSIGNED) + { + *length= snprintf(con->stmt_tmp_buffer, ATTACHSQL_STMT_CHAR_BUFFER_SIZE, "%" PRIu32, attachsql_unpack_int4(column_data->data)); + } + else + { + *length= snprintf(con->stmt_tmp_buffer, ATTACHSQL_STMT_CHAR_BUFFER_SIZE, "%" PRId32, attachsql_unpack_int4(column_data->data)); + } + return con->stmt_tmp_buffer; + break; + case ATTACHSQL_COLUMN_TYPE_LONGLONG: + if (con->result.columns[column].flags & ATTACHSQL_COLUMN_FLAGS_UNSIGNED) + { + *length= snprintf(con->stmt_tmp_buffer, ATTACHSQL_STMT_CHAR_BUFFER_SIZE, "%" PRIu64, attachsql_unpack_int8(column_data->data)); + } + else + { + *length= snprintf(con->stmt_tmp_buffer, ATTACHSQL_STMT_CHAR_BUFFER_SIZE, "%" PRId64, attachsql_unpack_int8(column_data->data)); + } + return con->stmt_tmp_buffer; + break; + case ATTACHSQL_COLUMN_TYPE_FLOAT: + float f; + memcpy(&f, column_data->data, 4); + *length= snprintf(con->stmt_tmp_buffer, ATTACHSQL_STMT_CHAR_BUFFER_SIZE, "%f", f); + return con->stmt_tmp_buffer; + break; + case ATTACHSQL_COLUMN_TYPE_DOUBLE: + double d; + memcpy(&d, column_data->data, 8); + *length= snprintf(con->stmt_tmp_buffer, ATTACHSQL_STMT_CHAR_BUFFER_SIZE, "%f", d); + return con->stmt_tmp_buffer; + break; + case ATTACHSQL_COLUMN_TYPE_NULL: + return NULL; + break; + case ATTACHSQL_COLUMN_TYPE_INT24: + if (con->result.columns[column].flags & ATTACHSQL_COLUMN_FLAGS_UNSIGNED) + { + *length= snprintf(con->stmt_tmp_buffer, ATTACHSQL_STMT_CHAR_BUFFER_SIZE, "%" PRIu32, attachsql_unpack_int3(column_data->data)); + } + else + { + *length= snprintf(con->stmt_tmp_buffer, ATTACHSQL_STMT_CHAR_BUFFER_SIZE, "%" PRId32, attachsql_unpack_int3(column_data->data)); + } + return con->stmt_tmp_buffer; + break; + + case ATTACHSQL_COLUMN_TYPE_DECIMAL: + case ATTACHSQL_COLUMN_TYPE_VARCHAR: + case ATTACHSQL_COLUMN_TYPE_BIT: + case ATTACHSQL_COLUMN_TYPE_NEWDECIMAL: + case ATTACHSQL_COLUMN_TYPE_ENUM: + case ATTACHSQL_COLUMN_TYPE_SET: + case ATTACHSQL_COLUMN_TYPE_TINY_BLOB: + case ATTACHSQL_COLUMN_TYPE_MEDIUM_BLOB: + case ATTACHSQL_COLUMN_TYPE_LONG_BLOB: + case ATTACHSQL_COLUMN_TYPE_BLOB: + case ATTACHSQL_COLUMN_TYPE_VARSTRING: + case ATTACHSQL_COLUMN_TYPE_STRING: + case ATTACHSQL_COLUMN_TYPE_GEOMETRY: + *length= column_data->length; + return column_data->data; + break; + case ATTACHSQL_COLUMN_TYPE_TIME: + attachsql_unpack_time(column_data->data, column_data->length, &datetime); + *length= snprintf(con->stmt_tmp_buffer, ATTACHSQL_STMT_CHAR_BUFFER_SIZE, "%s%02u:%02" PRIu8 ":%02" PRIu8, (datetime.is_negative) ? "-" : "", datetime.hour + 24 * datetime.day, datetime.minute, datetime.second); + if (datetime.microsecond) + { + *length+= snprintf(con->stmt_tmp_buffer+(*length), ATTACHSQL_STMT_CHAR_BUFFER_SIZE-(*length), ".%06" PRIu32, datetime.microsecond); + } + return con->stmt_tmp_buffer; + break; + case ATTACHSQL_COLUMN_TYPE_TIMESTAMP: + case ATTACHSQL_COLUMN_TYPE_DATE: + case ATTACHSQL_COLUMN_TYPE_DATETIME: + attachsql_unpack_datetime(column_data->data, column_data->length, &datetime); + *length= snprintf(con->stmt_tmp_buffer, ATTACHSQL_STMT_CHAR_BUFFER_SIZE, "%04" PRIu16 "-%02" PRIu8 "-%02" PRIu32, datetime.year, datetime.month, datetime.day); + if (column_data->type == ATTACHSQL_COLUMN_TYPE_DATE) + { + return con->stmt_tmp_buffer; + } + *length+= snprintf(con->stmt_tmp_buffer+(*length), ATTACHSQL_STMT_CHAR_BUFFER_SIZE-(*length), " %02" PRIu8 ":%02" PRIu8 ":%02" PRIu8, datetime.hour, datetime.minute, datetime.second); + + if (datetime.microsecond) + { + *length+= snprintf(con->stmt_tmp_buffer+(*length), ATTACHSQL_STMT_CHAR_BUFFER_SIZE-(*length), ".%06" PRIu32, datetime.microsecond); + } + return con->stmt_tmp_buffer; + break; + case ATTACHSQL_COLUMN_TYPE_ERROR: + attachsql_error_client_create(error, ATTACHSQL_ERROR_CODE_PARAMETER, ATTACHSQL_ERROR_LEVEL_ERROR, "22023", "Cannot convert to int"); + return NULL; + break; + } + /* Should never hit here, but lets make compilers happy */ + return NULL; +} + +attachsql_column_type_t attachsql_statement_get_column_type(attachsql_connect_t *con, uint16_t column) +{ + if (con == NULL) + { + return ATTACHSQL_COLUMN_TYPE_ERROR; + } + + if (column >= con->result.column_count) + { + return ATTACHSQL_COLUMN_TYPE_ERROR; + } + + return (attachsql_column_type_t)con->result.columns[column].type; +} + +void attachsql_statement_row_next(attachsql_connect_t *con) +{ + if (con == NULL) + { + return; + } + attachsql_get_next_row(con); +} + +uint16_t attachsql_statement_get_column_count(attachsql_connect_t *con) +{ + if (con == NULL) + { + return 0; + } + + return con->result.column_count; +} + diff --git a/src/ascore/structs.h b/src/structs.h similarity index 58% rename from src/ascore/structs.h rename to src/structs.h index fd76365..90ea163 100644 --- a/src/ascore/structs.h +++ b/src/structs.h @@ -2,7 +2,7 @@ * Copyright 2014 Hewlett-Packard Development Company, L.P. * * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. You may obtain + * not use this file except in compliance with the License. You may obtain * a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 @@ -32,6 +32,7 @@ typedef uint16_t in_port_t; #endif #include +#include #ifdef HAVE_OPENSSL # include @@ -42,21 +43,38 @@ typedef uint16_t in_port_t; extern "C" { #endif -typedef struct ascon_st ascon_st; +typedef struct attachsql_connect_t attachsql_connect_t; +typedef struct attachsql_pool_t attachsql_pool_t; + +#define ATTACHSQL_BUFFER_ROW_ALLOC_SIZE 100 +#define ATTACHSQL_STMT_CHAR_BUFFER_SIZE 40 + +struct attachsql_stmt_row_st +{ + char *data; + size_t length; + attachsql_column_type_t type; + + attachsql_stmt_row_st() : + data(NULL), + length(0), + type(ATTACHSQL_COLUMN_TYPE_NULL) + { } +}; struct column_t { - char schema[ASCORE_MAX_SCHEMA_SIZE]; - char table[ASCORE_MAX_TABLE_SIZE]; - char origin_table[ASCORE_MAX_TABLE_SIZE]; - char column[ASCORE_MAX_COLUMN_SIZE]; - char origin_column[ASCORE_MAX_COLUMN_SIZE]; + char schema[ATTACHSQL_MAX_SCHEMA_SIZE]; + char table[ATTACHSQL_MAX_TABLE_SIZE]; + char origin_table[ATTACHSQL_MAX_TABLE_SIZE]; + char column[ATTACHSQL_MAX_COLUMN_SIZE]; + char origin_column[ATTACHSQL_MAX_COLUMN_SIZE]; uint16_t charset; uint32_t length; - ascore_column_type_t type; - ascore_column_flags_t flags; + attachsql_column_type_t type; + attachsql_column_flags_t flags; uint8_t decimals; - char default_value[ASCORE_MAX_DEFAULT_VALUE_SIZE]; + char default_value[ATTACHSQL_MAX_DEFAULT_VALUE_SIZE]; size_t default_size; }; @@ -79,7 +97,7 @@ struct result_t { } }; -struct ascore_datetime_st +struct attachsql_datetime_st { uint16_t year; uint8_t month; @@ -90,7 +108,7 @@ struct ascore_datetime_st uint32_t microsecond; bool is_negative; - ascore_datetime_st (): + attachsql_datetime_st (): year(0), month(0), day(0), @@ -102,9 +120,9 @@ struct ascore_datetime_st { } }; -struct ascore_stmt_param_st +struct attachsql_stmt_param_st { - ascore_column_type_t type; + attachsql_column_type_t type; size_t length; bool is_long_data; bool is_unsigned; @@ -117,12 +135,12 @@ struct ascore_stmt_param_st uint64_t bigint_data; float float_data; double double_data; - ascore_datetime_st *datetime_data; + attachsql_datetime_st *datetime_data; char *string_data; } data; - ascore_stmt_param_st() : - type(ASCORE_COLUMN_TYPE_NULL), + attachsql_stmt_param_st() : + type(ATTACHSQL_COLUMN_TYPE_NULL), length(0), is_long_data(false), is_unsigned(false), @@ -130,32 +148,30 @@ struct ascore_stmt_param_st { } }; -struct ascore_stmt_st +struct attachsql_stmt_st { - ascon_st *con; + attachsql_connect_t *con; uint32_t id; uint16_t column_count; - column_t *columns; uint16_t current_column; uint16_t param_count; column_t *params; uint16_t current_param; - ascore_stmt_state_t state; + attachsql_stmt_state_t state; char *exec_buffer; size_t exec_buffer_length; - ascore_stmt_param_st *param_data; + attachsql_stmt_param_st *param_data; bool new_bind; - ascore_stmt_st(): + attachsql_stmt_st(): con(NULL), id(0), column_count(0), - columns(NULL), current_column(0), param_count(0), params(NULL), current_param(0), - state(ASCORE_STMT_STATE_NONE), + state(ATTACHSQL_STMT_STATE_NONE), exec_buffer(NULL), exec_buffer_length(0), param_data(NULL), @@ -163,7 +179,7 @@ struct ascore_stmt_st { } }; -struct ascon_st +struct attachsql_connect_t { const char *host; in_port_t port; @@ -174,29 +190,30 @@ struct ascon_st struct options_t { bool compression; - ascore_con_protocol_t protocol; + attachsql_con_protocol_t protocol; bool semi_block; options_t() : compression(false), - protocol(ASCORE_CON_PROTOCOL_UNKNOWN), + protocol(ATTACHSQL_CON_PROTOCOL_UNKNOWN), semi_block(false) { } } options; - ascore_con_status_t status; - char errmsg[ASCORE_ERROR_BUFFER_SIZE]; - asret_t local_errcode; + attachsql_con_status_t status; + char errmsg[ATTACHSQL_ERROR_BUFFER_SIZE]; + attachsql_ret_t local_errcode; buffer_st *read_buffer; buffer_st *read_buffer_compress; - char write_buffer[ASCORE_WRITE_BUFFER_SIZE]; + char write_buffer[ATTACHSQL_WRITE_BUFFER_SIZE]; uint8_t write_buffer_extra; /* for extra bytes in packet header due to prepared statement */ uint8_t packet_number; uint32_t thread_id; - char server_version[ASCORE_MAX_SERVER_VERSION_LEN]; + uint32_t connection_id; /* the pool ID */ + char server_version[ATTACHSQL_MAX_SERVER_VERSION_LEN]; unsigned char scramble_buffer[20]; char packet_header[4]; - ascore_capabilities_t server_capabilities; + attachsql_capabilities_t server_capabilities; int client_capabilities; uint32_t packet_size; uint64_t affected_rows; @@ -204,12 +221,14 @@ struct ascon_st uint16_t server_status; uint16_t warning_count; uint16_t server_errno; - char server_message[ASCORE_MAX_MESSAGE_LEN]; - char sqlstate[ASCORE_SQLSTATE_SIZE]; + char server_message[ATTACHSQL_MAX_MESSAGE_LEN]; + char sqlstate[ATTACHSQL_SQLSTATE_SIZE]; uint8_t charset; struct result_t result; - ascore_command_status_t command_status; - ascore_packet_type_t next_packet_type; + attachsql_command_status_t command_status; + attachsql_packet_type_t *next_packet_queue; + size_t next_packet_queue_size; + size_t next_packet_queue_used; char *uncompressed_buffer; size_t uncompressed_buffer_len; char *compressed_buffer; @@ -269,23 +288,43 @@ struct ascon_st } ssl; #endif bool in_statement; - ascore_stmt_st *stmt; - bool in_group; + attachsql_stmt_st *stmt; + /* the following has been migrated during struct merge */ + attachsql_pool_t *pool; + char *query_buffer; + size_t query_buffer_length; + bool query_buffer_alloc; + bool query_buffer_statement; + bool in_query; + bool buffer_rows; + attachsql_query_column_st *columns; + attachsql_query_row_st *row; + attachsql_query_row_st **row_buffer; + uint64_t row_buffer_alloc_size; + uint64_t row_buffer_count; + uint64_t row_buffer_position; + bool all_rows_buffered; + attachsql_stmt_row_st *stmt_row; + char *stmt_null_bitmap; + uint16_t stmt_null_bitmap_length; + char stmt_tmp_buffer[ATTACHSQL_STMT_CHAR_BUFFER_SIZE]; + attachsql_events_t last_callback; - ascon_st() : + attachsql_connect_t() : host(NULL), port(0), user(NULL), pass(NULL), schema(NULL), - status(ASCORE_CON_STATUS_NOT_CONNECTED), - local_errcode(ASRET_OK), + status(ATTACHSQL_CON_STATUS_NOT_CONNECTED), + local_errcode(ATTACHSQL_RET_OK), read_buffer(NULL), read_buffer_compress(NULL), write_buffer_extra(0), packet_number(0), thread_id(0), - server_capabilities(ASCORE_CAPABILITY_NONE), + connection_id(0), + server_capabilities(ATTACHSQL_CAPABILITY_NONE), client_capabilities(0), packet_size(0), affected_rows(0), @@ -294,8 +333,10 @@ struct ascon_st warning_count(0), server_errno(0), charset(0), - command_status(ASCORE_COMMAND_STATUS_NONE), - next_packet_type(ASCORE_PACKET_TYPE_NONE), + command_status(ATTACHSQL_COMMAND_STATUS_EOF), + next_packet_queue(NULL), + next_packet_queue_size(0), + next_packet_queue_used(0), uncompressed_buffer(NULL), uncompressed_buffer_len(0), compressed_buffer(NULL), @@ -303,7 +344,24 @@ struct ascon_st compressed_packet_number(0), in_statement(false), stmt(NULL), - in_group(false) + pool(NULL), + query_buffer(NULL), + query_buffer_length(0), + query_buffer_alloc(false), + query_buffer_statement(false), + in_query(false), + buffer_rows(false), + columns(NULL), + row(NULL), + row_buffer(NULL), + row_buffer_alloc_size(0), + row_buffer_count(0), + row_buffer_position(0), + all_rows_buffered(false), + stmt_row(NULL), + stmt_null_bitmap(NULL), + stmt_null_bitmap_length(0), + last_callback(ATTACHSQL_EVENT_NONE) { str_port[0]= '\0'; errmsg[0]= '\0'; @@ -314,9 +372,44 @@ struct ascon_st sqlstate[0]= '\0'; write_buffer[0]= '\0'; compressed_packet_header[0]= '\0'; + stmt_tmp_buffer[0]= '\0'; + } +}; + +struct attachsql_error_t +{ + int code; + char msg[ATTACHSQL_MESSAGE_SIZE]; + char sqlstate[ATTACHSQL_SQLSTATE_SIZE]; + attachsql_error_level_t level; + + attachsql_error_t() : + code(0), + level(ATTACHSQL_ERROR_LEVEL_NOTICE) + { + msg[0]= '\0'; + sqlstate[0]= '\0'; } }; +struct attachsql_pool_t +{ + attachsql_connect_t **connections; + uint32_t connection_count; + attachsql_callback_fn *callback_fn; + void *callback_context; + uv_loop_t *loop; + + attachsql_pool_t() : + connections(NULL), + connection_count(0), + callback_fn(NULL), + callback_context(NULL), + loop(NULL) + { } + +}; + #ifdef __cplusplus } #endif diff --git a/src/asql/utility.cc b/src/utility.cc similarity index 92% rename from src/asql/utility.cc rename to src/utility.cc index e8b8da6..e41bfba 100644 --- a/src/asql/utility.cc +++ b/src/utility.cc @@ -17,7 +17,7 @@ #include "config.h" #include "version.h" -#include "src/asql/common.h" +#include "common.h" const char *attachsql_get_library_version(void) { @@ -41,5 +41,8 @@ uint8_t attachsql_get_library_version_patch(void) void attachsql_library_init(void) { - ascore_library_init(); +#ifdef HAVE_OPENSSL + SSL_load_error_strings(); + SSL_library_init(); +#endif } diff --git a/tests/asql/include.am b/tests/asql/include.am deleted file mode 100644 index 1357c12..0000000 --- a/tests/asql/include.am +++ /dev/null @@ -1,171 +0,0 @@ -# vim:ft=automake -# Copyright (C) 2012 Data Differential -# All rights reserved. -# -# Use and distribution licensed under the BSD license. See -# the COPYING file in the parent directory for full text. -# -# included from Top Level Makefile.am -# All paths should be given relative to the root - -t_asql_version_SOURCES= tests/asql/version.cc -t_asql_version_LDADD= src/asql/libattachsql.la -if BUILD_WIN32 -t_asql_version_LDADD+= -lws2_32 -t_asql_version_LDADD+= -lpsapi -t_asql_version_LDADD+= -liphlpapi -endif -check_PROGRAMS+= t/asql/version -noinst_PROGRAMS+= t/asql/version - -t_asql_query_SOURCES= tests/asql/query.cc -t_asql_query_LDADD= src/asql/libattachsql.la -if BUILD_WIN32 -t_asql_query_LDADD+= -lws2_32 -t_asql_query_LDADD+= -lpsapi -t_asql_query_LDADD+= -liphlpapi -endif -check_PROGRAMS+= t/asql/query -noinst_PROGRAMS+= t/asql/query - -t_asql_query_ssl_SOURCES= tests/asql/query_ssl.cc -t_asql_query_ssl_LDADD= src/asql/libattachsql.la -if BUILD_WIN32 -t_asql_query_ssl_LDADD+= -lws2_32 -t_asql_query_ssl_LDADD+= -lpsapi -t_asql_query_ssl_LDADD+= -liphlpapi -endif -check_PROGRAMS+= t/asql/query_ssl -noinst_PROGRAMS+= t/asql/query_ssl - -t_asql_query_compress_SOURCES= tests/asql/query_compress.cc -t_asql_query_compress_LDADD= src/asql/libattachsql.la -if BUILD_WIN32 -t_asql_query_compress_LDADD+= -lws2_32 -t_asql_query_compress_LDADD+= -lpsapi -t_asql_query_compress_LDADD+= -liphlpapi -endif -check_PROGRAMS+= t/asql/query_compress -noinst_PROGRAMS+= t/asql/query_compress - -t_asql_query_uds_SOURCES= tests/asql/query_uds.cc -t_asql_query_uds_LDADD= src/asql/libattachsql.la -if BUILD_WIN32 -t_asql_query_uds_LDADD+= -lws2_32 -t_asql_query_uds_LDADD+= -lpsapi -t_asql_query_uds_LDADD+= -liphlpapi -endif -check_PROGRAMS+= t/asql/query_uds -noinst_PROGRAMS+= t/asql/query_uds - -t_asql_query_buffer_SOURCES= tests/asql/query_buffer.cc -t_asql_query_buffer_LDADD= src/asql/libattachsql.la -if BUILD_WIN32 -t_asql_query_buffer_LDADD+= -lws2_32 -t_asql_query_buffer_LDADD+= -lpsapi -t_asql_query_buffer_LDADD+= -liphlpapi -endif -check_PROGRAMS+= t/asql/query_buffer -noinst_PROGRAMS+= t/asql/query_buffer - -t_asql_multi_query_SOURCES= tests/asql/multi_query.cc -t_asql_multi_query_LDADD= src/asql/libattachsql.la -if BUILD_WIN32 -t_asql_multi_query_LDADD+= -lws2_32 -t_asql_multi_query_LDADD+= -lpsapi -t_asql_multi_query_LDADD+= -liphlpapi -endif -check_PROGRAMS+= t/asql/multi_query -noinst_PROGRAMS+= t/asql/multi_query - -t_asql_query_error_SOURCES= tests/asql/query_error.cc -t_asql_query_error_LDADD= src/asql/libattachsql.la -if BUILD_WIN32 -t_asql_query_error_LDADD+= -lws2_32 -t_asql_query_error_LDADD+= -lpsapi -t_asql_query_error_LDADD+= -liphlpapi -endif -check_PROGRAMS+= t/asql/query_error -noinst_PROGRAMS+= t/asql/query_error - -t_asql_connect_error_SOURCES= tests/asql/connect_error.cc -t_asql_connect_error_LDADD= src/asql/libattachsql.la -if BUILD_WIN32 -t_asql_connect_error_LDADD+= -lws2_32 -t_asql_connect_error_LDADD+= -lpsapi -t_asql_connect_error_LDADD+= -liphlpapi -endif -check_PROGRAMS+= t/asql/connect_error -noinst_PROGRAMS+= t/asql/connect_error - -t_asql_statement_SOURCES= tests/asql/statement.cc -t_asql_statement_LDADD= src/asql/libattachsql.la -if BUILD_WIN32 -t_asql_statement_LDADD+= -lws2_32 -t_asql_statement_LDADD+= -lpsapi -t_asql_statement_LDADD+= -liphlpapi -endif -check_PROGRAMS+= t/asql/statement -noinst_PROGRAMS+= t/asql/statement - -t_asql_statement_param_SOURCES= tests/asql/statement_param.cc -t_asql_statement_param_LDADD= src/asql/libattachsql.la -if BUILD_WIN32 -t_asql_statement_param_LDADD+= -lws2_32 -t_asql_statement_param_LDADD+= -lpsapi -t_asql_statement_param_LDADD+= -liphlpapi -endif -check_PROGRAMS+= t/asql/statement_param -noinst_PROGRAMS+= t/asql/statement_param - -t_asql_statement_reuse_SOURCES= tests/asql/statement_reuse.cc -t_asql_statement_reuse_LDADD= src/asql/libattachsql.la -if BUILD_WIN32 -t_asql_statement_reuse_LDADD+= -lws2_32 -t_asql_statement_reuse_LDADD+= -lpsapi -t_asql_statement_reuse_LDADD+= -liphlpapi -endif -check_PROGRAMS+= t/asql/statement_reuse -noinst_PROGRAMS+= t/asql/statement_reuse - -t_asql_statement_twice_SOURCES= tests/asql/statement_twice.cc -t_asql_statement_twice_LDADD= src/asql/libattachsql.la -if BUILD_WIN32 -t_asql_statement_twice_LDADD+= -lws2_32 -t_asql_statement_twice_LDADD+= -lpsapi -t_asql_statement_twice_LDADD+= -liphlpapi -endif -check_PROGRAMS+= t/asql/statement_twice -noinst_PROGRAMS+= t/asql/statement_twice - -t_asql_no_backslash_SOURCES= tests/asql/no_backslash.cc -t_asql_no_backslash_LDADD= src/asql/libattachsql.la -if BUILD_WIN32 -t_asql_no_backslash_LDADD+= -lws2_32 -t_asql_no_backslash_LDADD+= -lpsapi -t_asql_no_backslash_LDADD+= -liphlpapi -endif -check_PROGRAMS+= t/asql/no_backslash -noinst_PROGRAMS+= t/asql/no_backslash - -t_asql_query_semi_block_SOURCES= tests/asql/query_semi_block.cc -t_asql_query_semi_block_LDADD= src/asql/libattachsql.la -if BUILD_WIN32 -t_asql_query_semi_block_LDADD+= -lws2_32 -t_asql_query_semi_block_LDADD+= -lpsapi -t_asql_query_semi_block_LDADD+= -liphlpapi -endif -check_PROGRAMS+= t/asql/query_semi_block -noinst_PROGRAMS+= t/asql/query_semi_block - -t_asql_group_SOURCES= tests/asql/group.cc -t_asql_group_LDADD= src/asql/libattachsql.la -if BUILD_WIN32 -t_asql_group_LDADD+= -lws2_32 -t_asql_group_LDADD+= -lpsapi -t_asql_group_LDADD+= -liphlpapi -endif -check_PROGRAMS+= t/asql/group -noinst_PROGRAMS+= t/asql/group - - diff --git a/tests/connect.cc b/tests/connect.cc new file mode 100644 index 0000000..263959b --- /dev/null +++ b/tests/connect.cc @@ -0,0 +1,46 @@ +/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab: + * Copyright 2014 Hewlett-Packard Development Company, L.P. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. You may obtain + * a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + */ + +#include +#include "version.h" +#include + +int main(int argc, char *argv[]) +{ + (void) argc; + (void) argv; + attachsql_connect_t *con; + attachsql_error_t *error= NULL; + attachsql_return_t aret= ATTACHSQL_RETURN_NONE; + + con= attachsql_connect_create("localhost", 3306, "test", "test", "", NULL); + attachsql_connect(con, &error); + while (aret != ATTACHSQL_RETURN_EOF) + { + aret= attachsql_connect_poll(con, &error); + if (error && (attachsql_error_code(error) == 2002)) + { + SKIP_IF_(true, "No MYSQL server"); + } + else if (error != NULL) + { + ASSERT_FALSE_(true, "Error exists: %s", attachsql_error_message(error)); + } + } + attachsql_query_close(con); + attachsql_connect_destroy(con); +} diff --git a/tests/asql/connect_error.cc b/tests/connect_error.cc similarity index 97% rename from tests/asql/connect_error.cc rename to tests/connect_error.cc index e3e5f3a..ade721e 100644 --- a/tests/asql/connect_error.cc +++ b/tests/connect_error.cc @@ -17,7 +17,7 @@ #include #include "version.h" -#include +#include int main(int argc, char *argv[]) { diff --git a/tests/include.am b/tests/include.am index 9a1cb98..216f963 100644 --- a/tests/include.am +++ b/tests/include.am @@ -11,4 +11,222 @@ LIBTOOL_COMMAND= ${abs_top_builddir}/libtool --mode=execute GDB_COMMAND= $(LIBTOOL_COMMAND) gdb -f -x support/run.gdb -include tests/asql/include.am +t_version_SOURCES= tests/version.cc +t_version_LDADD= src/libattachsql.la +if BUILD_WIN32 +t_version_LDADD+= -lws2_32 +t_version_LDADD+= -lpsapi +t_version_LDADD+= -liphlpapi +endif +check_PROGRAMS+= t/version +noinst_PROGRAMS+= t/version + +t_query_SOURCES= tests/query.cc +t_query_LDADD= src/libattachsql.la +if BUILD_WIN32 +t_query_LDADD+= -lws2_32 +t_query_LDADD+= -lpsapi +t_query_LDADD+= -liphlpapi +endif +check_PROGRAMS+= t/query +noinst_PROGRAMS+= t/query + +t_query_ssl_SOURCES= tests/query_ssl.cc +t_query_ssl_LDADD= src/libattachsql.la +if BUILD_WIN32 +t_query_ssl_LDADD+= -lws2_32 +t_query_ssl_LDADD+= -lpsapi +t_query_ssl_LDADD+= -liphlpapi +endif +check_PROGRAMS+= t/query_ssl +noinst_PROGRAMS+= t/query_ssl + +t_query_compress_SOURCES= tests/query_compress.cc +t_query_compress_LDADD= src/libattachsql.la +if BUILD_WIN32 +t_query_compress_LDADD+= -lws2_32 +t_query_compress_LDADD+= -lpsapi +t_query_compress_LDADD+= -liphlpapi +endif +check_PROGRAMS+= t/query_compress +noinst_PROGRAMS+= t/query_compress + +t_query_uds_SOURCES= tests/query_uds.cc +t_query_uds_LDADD= src/libattachsql.la +if BUILD_WIN32 +t_query_uds_LDADD+= -lws2_32 +t_query_uds_LDADD+= -lpsapi +t_query_uds_LDADD+= -liphlpapi +endif +check_PROGRAMS+= t/query_uds +noinst_PROGRAMS+= t/query_uds + +t_query_buffer_SOURCES= tests/query_buffer.cc +t_query_buffer_LDADD= src/libattachsql.la +if BUILD_WIN32 +t_query_buffer_LDADD+= -lws2_32 +t_query_buffer_LDADD+= -lpsapi +t_query_buffer_LDADD+= -liphlpapi +endif +check_PROGRAMS+= t/query_buffer +noinst_PROGRAMS+= t/query_buffer + +t_multi_query_SOURCES= tests/multi_query.cc +t_multi_query_LDADD= src/libattachsql.la +if BUILD_WIN32 +t_multi_query_LDADD+= -lws2_32 +t_multi_query_LDADD+= -lpsapi +t_multi_query_LDADD+= -liphlpapi +endif +check_PROGRAMS+= t/multi_query +noinst_PROGRAMS+= t/multi_query + +t_query_error_SOURCES= tests/query_error.cc +t_query_error_LDADD= src/libattachsql.la +if BUILD_WIN32 +t_query_error_LDADD+= -lws2_32 +t_query_error_LDADD+= -lpsapi +t_query_error_LDADD+= -liphlpapi +endif +check_PROGRAMS+= t/query_error +noinst_PROGRAMS+= t/query_error + +t_connect_error_SOURCES= tests/connect_error.cc +t_connect_error_LDADD= src/libattachsql.la +if BUILD_WIN32 +t_connect_error_LDADD+= -lws2_32 +t_connect_error_LDADD+= -lpsapi +t_connect_error_LDADD+= -liphlpapi +endif +check_PROGRAMS+= t/connect_error +noinst_PROGRAMS+= t/connect_error + +t_connect_SOURCES= tests/connect.cc +t_connect_LDADD= src/libattachsql.la +if BUILD_WIN32 +t_connect_LDADD+= -lws2_32 +t_connect_LDADD+= -lpsapi +t_connect_LDADD+= -liphlpapi +endif +check_PROGRAMS+= t/connect +noinst_PROGRAMS+= t/connect + +t_statement_SOURCES= tests/statement.cc +t_statement_LDADD= src/libattachsql.la +if BUILD_WIN32 +t_statement_LDADD+= -lws2_32 +t_statement_LDADD+= -lpsapi +t_statement_LDADD+= -liphlpapi +endif +check_PROGRAMS+= t/statement +noinst_PROGRAMS+= t/statement + +t_statement_param_SOURCES= tests/statement_param.cc +t_statement_param_LDADD= src/libattachsql.la +if BUILD_WIN32 +t_statement_param_LDADD+= -lws2_32 +t_statement_param_LDADD+= -lpsapi +t_statement_param_LDADD+= -liphlpapi +endif +check_PROGRAMS+= t/statement_param +noinst_PROGRAMS+= t/statement_param + +t_statement_reuse_SOURCES= tests/statement_reuse.cc +t_statement_reuse_LDADD= src/libattachsql.la +if BUILD_WIN32 +t_statement_reuse_LDADD+= -lws2_32 +t_statement_reuse_LDADD+= -lpsapi +t_statement_reuse_LDADD+= -liphlpapi +endif +check_PROGRAMS+= t/statement_reuse +noinst_PROGRAMS+= t/statement_reuse + +t_statement_twice_SOURCES= tests/statement_twice.cc +t_statement_twice_LDADD= src/libattachsql.la +if BUILD_WIN32 +t_statement_twice_LDADD+= -lws2_32 +t_statement_twice_LDADD+= -lpsapi +t_statement_twice_LDADD+= -liphlpapi +endif +check_PROGRAMS+= t/statement_twice +noinst_PROGRAMS+= t/statement_twice + +t_no_backslash_SOURCES= tests/no_backslash.cc +t_no_backslash_LDADD= src/libattachsql.la +if BUILD_WIN32 +t_no_backslash_LDADD+= -lws2_32 +t_no_backslash_LDADD+= -lpsapi +t_no_backslash_LDADD+= -liphlpapi +endif +check_PROGRAMS+= t/no_backslash +noinst_PROGRAMS+= t/no_backslash + +t_query_semi_block_SOURCES= tests/query_semi_block.cc +t_query_semi_block_LDADD= src/libattachsql.la +if BUILD_WIN32 +t_query_semi_block_LDADD+= -lws2_32 +t_query_semi_block_LDADD+= -lpsapi +t_query_semi_block_LDADD+= -liphlpapi +endif +check_PROGRAMS+= t/query_semi_block +noinst_PROGRAMS+= t/query_semi_block + +t_pool_SOURCES= tests/pool.cc +t_pool_LDADD= src/libattachsql.la +if BUILD_WIN32 +t_pool_LDADD+= -lws2_32 +t_pool_LDADD+= -lpsapi +t_pool_LDADD+= -liphlpapi +endif +check_PROGRAMS+= t/pool +noinst_PROGRAMS+= t/pool + +t_statement_semi_block_SOURCES= tests/statement_semi_block.cc +t_statement_semi_block_LDADD= src/libattachsql.la +if BUILD_WIN32 +t_statement_semi_block_LDADD+= -lws2_32 +t_statement_semi_block_LDADD+= -lpsapi +t_statement_semi_block_LDADD+= -liphlpapi +endif +check_PROGRAMS+= t/statement_semi_block +noinst_PROGRAMS+= t/statement_semi_block + +t_query_compress_semi_block_SOURCES= tests/query_compress_semi_block.cc +t_query_compress_semi_block_LDADD= src/libattachsql.la +if BUILD_WIN32 +t_query_compress_semi_block_LDADD+= -lws2_32 +t_query_compress_semi_block_LDADD+= -lpsapi +t_query_compress_semi_block_LDADD+= -liphlpapi +endif +check_PROGRAMS+= t/query_compress_semi_block +noinst_PROGRAMS+= t/query_compress_semi_block + +t_pool_compress_SOURCES= tests/pool_compress.cc +t_pool_compress_LDADD= src/libattachsql.la +if BUILD_WIN32 +t_pool_compress_LDADD+= -lws2_32 +t_pool_compress_LDADD+= -lpsapi +t_pool_compress_LDADD+= -liphlpapi +endif +check_PROGRAMS+= t/pool_compress +noinst_PROGRAMS+= t/pool_compress + +t_query_ssl_compress_SOURCES= tests/query_ssl_compress.cc +t_query_ssl_compress_LDADD= src/libattachsql.la +if BUILD_WIN32 +t_query_ssl_compress_LDADD+= -lws2_32 +t_query_ssl_compress_LDADD+= -lpsapi +t_query_ssl_compress_LDADD+= -liphlpapi +endif +check_PROGRAMS+= t/query_ssl_compress +noinst_PROGRAMS+= t/query_ssl_compress + +t_transaction_SOURCES= tests/transaction.cc +t_transaction_LDADD= src/libattachsql.la +if BUILD_WIN32 +t_transaction_LDADD+= -lws2_32 +t_transaction_LDADD+= -lpsapi +t_transaction_LDADD+= -liphlpapi +endif +check_PROGRAMS+= t/transaction +noinst_PROGRAMS+= t/transaction diff --git a/tests/asql/multi_query.cc b/tests/multi_query.cc similarity index 98% rename from tests/asql/multi_query.cc rename to tests/multi_query.cc index a50a353..89a4ca6 100644 --- a/tests/asql/multi_query.cc +++ b/tests/multi_query.cc @@ -17,7 +17,7 @@ #include #include "version.h" -#include +#include int main(int argc, char *argv[]) { diff --git a/tests/asql/no_backslash.cc b/tests/no_backslash.cc similarity index 98% rename from tests/asql/no_backslash.cc rename to tests/no_backslash.cc index 6fd6837..ae22fc6 100644 --- a/tests/asql/no_backslash.cc +++ b/tests/no_backslash.cc @@ -17,7 +17,7 @@ #include #include "version.h" -#include +#include int main(int argc, char *argv[]) { diff --git a/tests/pool.cc b/tests/pool.cc new file mode 100644 index 0000000..85982a1 --- /dev/null +++ b/tests/pool.cc @@ -0,0 +1,89 @@ +/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab: + * Copyright 2014 Hewlett-Packard Development Company, L.P. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. You may obtain + * a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + */ + +#include +#include "version.h" +#include + +static int done= 0; + +void callbk(attachsql_connect_t *current_con, uint32_t connection_id, attachsql_events_t events, void *context, attachsql_error_t *error) +{ + (void) context; + attachsql_query_row_st *row; + uint16_t columns, col; + switch(events) + { + case ATTACHSQL_EVENT_CONNECTED: + printf("Connected event on con %d\n", connection_id); + break; + case ATTACHSQL_EVENT_ERROR: + if (error && (attachsql_error_code(error) == 2002)) + { + SKIP_IF_(true, "No MYSQL server"); + } + else + { + ASSERT_FALSE_(true, "Error exists on con %d: %d", connection_id, attachsql_error_code(error)); + } + // Normally we would attachsql_error_free() here + break; + case ATTACHSQL_EVENT_EOF: + printf("Connection %d finished\n", connection_id); + done++; + attachsql_query_close(current_con); + break; + case ATTACHSQL_EVENT_ROW_READY: + row= attachsql_query_row_get(current_con, &error); + columns= attachsql_query_column_count(current_con); + for (col=0; col < columns; col++) + { + printf("Con: %d, Column: %d, Length: %zu, Data: %.*s \n", connection_id, col, row[col].length, (int)row[col].length, row[col].data); + } + attachsql_query_row_next(current_con); + break; + case ATTACHSQL_EVENT_NONE: + break; + } +} + +int main(int argc, char *argv[]) +{ + (void) argc; + (void) argv; + attachsql_connect_t *con[3]; + attachsql_pool_t *pool; + attachsql_error_t *error= NULL; + const char *data= "SHOW PROCESSLIST"; + + pool= attachsql_pool_create(callbk, NULL, NULL); + con[0]= attachsql_connect_create("localhost", 3306, "test", "test", "", NULL); + attachsql_pool_add_connection(pool, con[0], &error); + con[1]= attachsql_connect_create("localhost", 3306, "test", "test", "", NULL); + attachsql_pool_add_connection(pool, con[1], &error); + con[2]= attachsql_connect_create("localhost", 3306, "test", "test", "", NULL); + attachsql_pool_add_connection(pool, con[2], &error); + attachsql_query(con[0], strlen(data), data, 0, NULL, &error); + attachsql_query(con[1], strlen(data), data, 0, NULL, &error); + attachsql_query(con[2], strlen(data), data, 0, NULL, &error); + + while(done < 3) + { + attachsql_pool_run(pool); + } + attachsql_pool_destroy(pool); +} diff --git a/tests/asql/group.cc b/tests/pool_compress.cc similarity index 66% rename from tests/asql/group.cc rename to tests/pool_compress.cc index 7c71de8..7f39dc3 100644 --- a/tests/asql/group.cc +++ b/tests/pool_compress.cc @@ -17,19 +17,19 @@ #include #include "version.h" -#include +#include -bool done[3]= {false, false, false}; +static int done= 0; -void callbk(attachsql_connect_t *current_con, attachsql_events_t events, void *context, attachsql_error_t *error) +void callbk(attachsql_connect_t *current_con, uint32_t connection_id, attachsql_events_t events, void *context, attachsql_error_t *error) { - uint8_t *con_no= (uint8_t*)context; + (void) context; attachsql_query_row_st *row; uint16_t columns, col; switch(events) { case ATTACHSQL_EVENT_CONNECTED: - printf("Connected event on con %d\n", *con_no); + printf("Connected event on con %d\n", connection_id); break; case ATTACHSQL_EVENT_ERROR: if (error && (attachsql_error_code(error) == 2002)) @@ -38,13 +38,13 @@ void callbk(attachsql_connect_t *current_con, attachsql_events_t events, void *c } else { - ASSERT_FALSE_(true, "Error exists on con %d: %d", *con_no, attachsql_error_code(error)); + ASSERT_FALSE_(true, "Error exists on con %d: %d", connection_id, attachsql_error_code(error)); } // Normally we would attachsql_error_free() here break; case ATTACHSQL_EVENT_EOF: - printf("Connection %d finished\n", *con_no); - done[*con_no]= true; + printf("Connection %d finished\n", connection_id); + done++; attachsql_query_close(current_con); break; case ATTACHSQL_EVENT_ROW_READY: @@ -52,7 +52,7 @@ void callbk(attachsql_connect_t *current_con, attachsql_events_t events, void *c columns= attachsql_query_column_count(current_con); for (col=0; col < columns; col++) { - printf("Con: %d, Column: %d, Length: %zu, Data: %.*s ", *con_no, col, row[col].length, (int)row[col].length, row[col].data); + printf("Con: %d, Column: %d, Length: %zu, Data: %.*s ", connection_id, col, row[col].length, (int)row[col].length, row[col].data); } attachsql_query_row_next(current_con); printf("\n"); @@ -67,28 +67,28 @@ int main(int argc, char *argv[]) (void) argc; (void) argv; attachsql_connect_t *con[3]; - attachsql_group_t *group; + attachsql_pool_t *pool; attachsql_error_t *error= NULL; const char *data= "SHOW PROCESSLIST"; - uint8_t con_no[3]= {0, 1, 2}; - group= attachsql_group_create(NULL); + pool= attachsql_pool_create(callbk, NULL, NULL); con[0]= attachsql_connect_create("localhost", 3306, "test", "test", "", NULL); - attachsql_group_add_connection(group, con[0], &error); - attachsql_connect_set_callback(con[0], callbk, &con_no[0]); + bool compress= attachsql_connect_set_option(con[0], ATTACHSQL_OPTION_COMPRESS, NULL); + SKIP_IF_(!compress, "Not compiled with ZLib"); + attachsql_pool_add_connection(pool, con[0], &error); con[1]= attachsql_connect_create("localhost", 3306, "test", "test", "", NULL); - attachsql_group_add_connection(group, con[1], &error); - attachsql_connect_set_callback(con[1], callbk, &con_no[1]); + attachsql_connect_set_option(con[1], ATTACHSQL_OPTION_COMPRESS, NULL); + attachsql_pool_add_connection(pool, con[1], &error); con[2]= attachsql_connect_create("localhost", 3306, "test", "test", "", NULL); - attachsql_group_add_connection(group, con[2], &error); - attachsql_connect_set_callback(con[2], callbk, &con_no[2]); + attachsql_connect_set_option(con[2], ATTACHSQL_OPTION_COMPRESS, NULL); + attachsql_pool_add_connection(pool, con[2], &error); attachsql_query(con[0], strlen(data), data, 0, NULL, &error); attachsql_query(con[1], strlen(data), data, 0, NULL, &error); attachsql_query(con[2], strlen(data), data, 0, NULL, &error); - while((not done[0]) || (not done[1]) || (not done[2])) + while(done < 3) { - attachsql_group_run(group); + attachsql_pool_run(pool); } - attachsql_group_destroy(group); + attachsql_pool_destroy(pool); } diff --git a/tests/asql/query.cc b/tests/query.cc similarity index 98% rename from tests/asql/query.cc rename to tests/query.cc index 43014cd..3696622 100644 --- a/tests/asql/query.cc +++ b/tests/query.cc @@ -17,7 +17,7 @@ #include #include "version.h" -#include +#include int main(int argc, char *argv[]) { diff --git a/tests/asql/query_buffer.cc b/tests/query_buffer.cc similarity index 97% rename from tests/asql/query_buffer.cc rename to tests/query_buffer.cc index 3ef69ee..ccb8d4a 100644 --- a/tests/asql/query_buffer.cc +++ b/tests/query_buffer.cc @@ -17,7 +17,7 @@ #include #include "version.h" -#include +#include int main(int argc, char *argv[]) { diff --git a/tests/asql/query_compress.cc b/tests/query_compress.cc similarity index 98% rename from tests/asql/query_compress.cc rename to tests/query_compress.cc index 3327f9c..5f25cca 100644 --- a/tests/asql/query_compress.cc +++ b/tests/query_compress.cc @@ -17,7 +17,7 @@ #include #include "version.h" -#include +#include int main(int argc, char *argv[]) { diff --git a/tests/query_compress_semi_block.cc b/tests/query_compress_semi_block.cc new file mode 100644 index 0000000..d363e1a --- /dev/null +++ b/tests/query_compress_semi_block.cc @@ -0,0 +1,103 @@ +/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab: + * Copyright 2014 Hewlett-Packard Development Company, L.P. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. You may obtain + * a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + */ + +#include +#include "version.h" +#include + +int main(int argc, char *argv[]) +{ + (void) argc; + (void) argv; + attachsql_connect_t *con; + attachsql_error_t *error= NULL; + const char *data= "SHOW PROCESSLIST"; + const char *data2= "SELECT ? as a, '?' as b, ? as c, ? as d, ? as e"; + attachsql_return_t aret= ATTACHSQL_RETURN_NONE; + attachsql_query_row_st *row; + attachsql_query_parameter_st param[5]; + uint16_t columns, col; + + con= attachsql_connect_create("localhost", 3306, "test", "test", "", NULL); + bool compress= attachsql_connect_set_option(con, ATTACHSQL_OPTION_COMPRESS, NULL); + SKIP_IF_(!compress, "Not compiled with ZLib"); + attachsql_connect_set_option(con, ATTACHSQL_OPTION_SEMI_BLOCKING, NULL); + attachsql_query(con, strlen(data), data, 0, NULL, &error); + while(aret != ATTACHSQL_RETURN_EOF) + { + aret= attachsql_connect_poll(con, &error); + if (aret == ATTACHSQL_RETURN_ROW_READY) + { + row= attachsql_query_row_get(con, &error); + columns= attachsql_query_column_count(con); + for (col=0; col < columns; col++) + { + printf("Column: %d, Length: %zu, Data: %.*s ", col, row[col].length, (int)row[col].length, row[col].data); + } + attachsql_query_row_next(con); + printf("\n"); + } + if (error && (attachsql_error_code(error) == 2002)) + { + SKIP_IF_(true, "No MYSQL server"); + } + else if (error) + { + ASSERT_FALSE_(true, "Error exists: %d", attachsql_error_code(error)); + } + } + attachsql_query_close(con); + const char *td= "test"; + uint32_t tn= 45768; + float tf= 3.14159; + double tlf= 3.1415926; + param[0].type= ATTACHSQL_ESCAPE_TYPE_CHAR; + param[0].data= (char*)td; + param[0].length= strlen(td); + param[1].type= ATTACHSQL_ESCAPE_TYPE_CHAR_LIKE; + param[1].data= (char*)td; + param[1].length= strlen(td); + param[2].type= ATTACHSQL_ESCAPE_TYPE_INT; + param[2].data= &tn; + param[2].is_unsigned= true; + param[3].type= ATTACHSQL_ESCAPE_TYPE_FLOAT; + param[3].data= &tf; + param[4].type= ATTACHSQL_ESCAPE_TYPE_DOUBLE; + param[4].data= &tlf; + attachsql_query(con, strlen(data2), data2, 5, param, &error); + ASSERT_NULL_(error, "Error not NULL"); + aret= ATTACHSQL_RETURN_NONE; + while(aret != ATTACHSQL_RETURN_EOF) + { + aret= attachsql_connect_poll(con, &error); + if (aret == ATTACHSQL_RETURN_ROW_READY) + { + row= attachsql_query_row_get(con, &error); + columns= attachsql_query_column_count(con); + ASSERT_EQ_(5, columns, "Column count unexpected"); + ASSERT_STREQL_("test", row[0].data, 4, "Bad row data"); + ASSERT_STREQL_("test", row[1].data, 4, "Bad row data"); + ASSERT_STREQL_("45768", row[2].data, 5, "Bad row data"); + ASSERT_STREQL_("3.14159", row[3].data, 7, "Bad float data"); + ASSERT_STREQL_("3.1415926", row[4].data, 9, "Bad double data"); + attachsql_query_row_next(con); + printf("\n"); + } + } + attachsql_query_close(con); + attachsql_connect_destroy(con); +} diff --git a/tests/asql/query_error.cc b/tests/query_error.cc similarity index 98% rename from tests/asql/query_error.cc rename to tests/query_error.cc index a6102af..3e34152 100644 --- a/tests/asql/query_error.cc +++ b/tests/query_error.cc @@ -17,7 +17,7 @@ #include #include "version.h" -#include +#include int main(int argc, char *argv[]) { diff --git a/tests/asql/query_semi_block.cc b/tests/query_semi_block.cc similarity index 98% rename from tests/asql/query_semi_block.cc rename to tests/query_semi_block.cc index 4df9591..f571891 100644 --- a/tests/asql/query_semi_block.cc +++ b/tests/query_semi_block.cc @@ -17,7 +17,7 @@ #include #include "version.h" -#include +#include int main(int argc, char *argv[]) { diff --git a/tests/asql/query_ssl.cc b/tests/query_ssl.cc similarity index 97% rename from tests/asql/query_ssl.cc rename to tests/query_ssl.cc index 13c3dbf..6733889 100644 --- a/tests/asql/query_ssl.cc +++ b/tests/query_ssl.cc @@ -17,7 +17,7 @@ #include #include "version.h" -#include +#include int main(int argc, char *argv[]) { @@ -39,7 +39,7 @@ int main(int argc, char *argv[]) { SKIP_IF_(true, "SSL not supported"); } - ASSERT_NULL_(error, "SSL setup error"); + SKIP_IF_(error, "SSL certs missing"); attachsql_query(con, strlen(data), data, 0, NULL, &error); while(aret != ATTACHSQL_RETURN_EOF) { diff --git a/tests/query_ssl_compress.cc b/tests/query_ssl_compress.cc new file mode 100644 index 0000000..d4c1fbf --- /dev/null +++ b/tests/query_ssl_compress.cc @@ -0,0 +1,109 @@ +/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab: + * Copyright 2014 Hewlett-Packard Development Company, L.P. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. You may obtain + * a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + */ + +#include +#include "version.h" +#include + +int main(int argc, char *argv[]) +{ + (void) argc; + (void) argv; + attachsql_connect_t *con; + attachsql_error_t *error= NULL; + const char *data= "SHOW PROCESSLIST"; + const char *data2= "SELECT ? as a, '?' as b, ? as c, ? as d, ? as e"; + attachsql_return_t aret= ATTACHSQL_RETURN_NONE; + attachsql_query_row_st *row; + attachsql_query_parameter_st param[5]; + uint16_t columns, col; + + attachsql_library_init(); + con= attachsql_connect_create("localhost", 3306, "test", "test", "", NULL); + attachsql_connect_set_ssl(con, "tests/ssl/client-key.pem", "tests/ssl/client-cert.pem", "tests/ssl/ca-cert.pem", NULL, NULL, false, &error); + bool compress= attachsql_connect_set_option(con, ATTACHSQL_OPTION_COMPRESS, NULL); + SKIP_IF_(!compress, "Not compiled with ZLib"); + if (error and (attachsql_error_code(error) == 3002)) + { + SKIP_IF_(true, "SSL not supported"); + } + SKIP_IF_(error, "SSL certs missing"); + attachsql_query(con, strlen(data), data, 0, NULL, &error); + while(aret != ATTACHSQL_RETURN_EOF) + { + aret= attachsql_connect_poll(con, &error); + if (aret == ATTACHSQL_RETURN_ROW_READY) + { + row= attachsql_query_row_get(con, &error); + columns= attachsql_query_column_count(con); + for (col=0; col < columns; col++) + { + printf("Column: %d, Length: %zu, Data: %.*s ", col, row[col].length, (int)row[col].length, row[col].data); + } + attachsql_query_row_next(con); + printf("\n"); + } + if (error && (attachsql_error_code(error) == 2002)) + { + SKIP_IF_(true, "No MYSQL server, or MySQL doesn't support SSL"); + } + else if (error) + { + ASSERT_FALSE_(true, "Error exists: %d, %s", attachsql_error_code(error), attachsql_error_message(error)); + } + } + attachsql_query_close(con); + const char *td= "test"; + uint32_t tn= 45768; + float tf= 3.14159; + double tlf= 3.1415926; + param[0].type= ATTACHSQL_ESCAPE_TYPE_CHAR; + param[0].data= (char*)td; + param[0].length= strlen(td); + param[1].type= ATTACHSQL_ESCAPE_TYPE_CHAR_LIKE; + param[1].data= (char*)td; + param[1].length= strlen(td); + param[2].type= ATTACHSQL_ESCAPE_TYPE_INT; + param[2].data= &tn; + param[2].is_unsigned= true; + param[3].type= ATTACHSQL_ESCAPE_TYPE_FLOAT; + param[3].data= &tf; + param[4].type= ATTACHSQL_ESCAPE_TYPE_DOUBLE; + param[4].data= &tlf; + attachsql_query(con, strlen(data2), data2, 5, param, &error); + ASSERT_NULL_(error, "Error not NULL"); + aret= ATTACHSQL_RETURN_NONE; + while(aret != ATTACHSQL_RETURN_EOF) + { + aret= attachsql_connect_poll(con, &error); + if (aret == ATTACHSQL_RETURN_ROW_READY) + { + row= attachsql_query_row_get(con, &error); + columns= attachsql_query_column_count(con); + ASSERT_EQ_(5, columns, "Column count unexpected"); + ASSERT_STREQL_("test", row[0].data, 4, "Bad row data"); + ASSERT_STREQL_("test", row[1].data, 4, "Bad row data"); + ASSERT_STREQL_("45768", row[2].data, 5, "Bad row data"); + ASSERT_STREQL_("3.14159", row[3].data, 7, "Bad float data"); + ASSERT_STREQL_("3.1415926", row[4].data, 9, "Bad double data"); + attachsql_query_row_next(con); + printf("\n"); + } + } + attachsql_query_close(con); + attachsql_connect_destroy(con); +} diff --git a/tests/asql/query_uds.cc b/tests/query_uds.cc similarity index 98% rename from tests/asql/query_uds.cc rename to tests/query_uds.cc index 4d3c993..11779c5 100644 --- a/tests/asql/query_uds.cc +++ b/tests/query_uds.cc @@ -17,7 +17,7 @@ #include #include "version.h" -#include +#include int main(int argc, char *argv[]) { diff --git a/tests/ssl/ca-cert.pem b/tests/ssl/ca-cert.pem index 20e20f3..16c87e4 100644 --- a/tests/ssl/ca-cert.pem +++ b/tests/ssl/ca-cert.pem @@ -1,20 +1,22 @@ -----BEGIN CERTIFICATE----- -MIIDVzCCAj+gAwIBAgIJAPE9z0nXWqb/MA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNV -BAYTAlhYMRUwEwYDVQQHDAxEZWZhdWx0IENpdHkxHDAaBgNVBAoME0RlZmF1bHQg -Q29tcGFueSBMdGQwHhcNMTQwODMwMTEwMzU1WhcNMjQwNzA4MTEwMzU1WjBCMQsw -CQYDVQQGEwJYWDEVMBMGA1UEBwwMRGVmYXVsdCBDaXR5MRwwGgYDVQQKDBNEZWZh -dWx0IENvbXBhbnkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA -tzyD2ZwWbWxceqNaMK9JENg1bGmh8ZOu3SGREyt13JW32+FzpOz2T28GLC+lUGex -8VbliMbvZsTW7qyU8ZSd2Dem1i8Gh+V99viE4mjD/ziycoi90ucxD58ER9m9c70a -qmJip+mHSNL7aA1Vo4FRbwNxeOf40Kz8miONFu5AJcE/E4iYsz3yhYaLMEe/CWfB -It1tC22chJsOz4mNl4CGIXta8BDR+3kvjeBfIscB1QKHtZSk8pzd2kVw4ilpKICN -d4tPdD0zLvXedRqOb5UewocHzAlpHmox/vzk4I8R4PiWi/ApzDqGF9N037o/dx4+ -zmcylr7v7lDccxqmXwDuUwIDAQABo1AwTjAdBgNVHQ4EFgQUaUuuR0FOwOnnLC1N -7iWVHeQQsdEwHwYDVR0jBBgwFoAUaUuuR0FOwOnnLC1N7iWVHeQQsdEwDAYDVR0T -BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAA9WgYMDq+01SaVIV+7iH+OiB0bDa -UChcCsZ42z3lt8Q5IaD3uMkEnBsR3PRQaUkuf80p96pAY6W2iTKSgLWYwBGqzmJL -uJFg/z1Zglo/jy+JezoHR5NlTRwv4NUoSqBnfV2ty5LJwYFZOza+u10bsp/PJw6h -M0vIWi/VQBrE8W5WBEIr5L/2CotuSxHlDe3bGK+qlhIzcIa3RDO1woVxfEF/fQu3 -ffCC5WH7wpPeGF8nv26Hcnbe+jYrhvfIRBs433peLUIK1lvKwxeQfB0AFY1q+Jm/ -FHwjMRZOB4lb49rgfzfoicBJN+1UOce/nsKy29eU+NxvrKGaV5RK3VLd9g== +MIIDkTCCAnmgAwIBAgIJAPuxDSp4KrE0MA0GCSqGSIb3DQEBBQUAMF8xCzAJBgNV +BAYTAlVLMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX +aWRnaXRzIFB0eSBMdGQxGDAWBgNVBAMMD2xpYmF0dGFjaHNxbC1jYTAeFw0xNTAy +MTgxNjAyMThaFw0yNDEyMjcxNjAyMThaMF8xCzAJBgNVBAYTAlVLMRMwEQYDVQQI +DApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQx +GDAWBgNVBAMMD2xpYmF0dGFjaHNxbC1jYTCCASIwDQYJKoZIhvcNAQEBBQADggEP +ADCCAQoCggEBANT7kq1Z/hbxw/VuR+ARqYZMcUsDNU5e/Bd6NmG6tFDXQBOokIq5 +oNXoLfosWu5pyNg9wgiJJRyWH1TC1oKKyDhzLpAWi8KzHmVN92PXEZ2UDz/XqI9l +xci2qPt7zyv9MXPqOhHWbNNlgLrk40Dw3gCUSNPZ2RcEGkvWdn4BPUwdcynCEpAa +2YVzRZT7jrYmw5+FJU6pq2cJjdPRYdqOiDt3i1vZZWfMGubadoOoAW9wazyBKcJW +U/U1FBDDafmoqxuMj/suuiytwJZ9Vq1qEX48R0F0kDiyxZmzsQUgVwy5OCtn32Gc +VIINMHonDaYCuUXIMscq0WNw1LrbsNNBnwUCAwEAAaNQME4wHQYDVR0OBBYEFJAS +I91ChedKF9vUbztP0CvvwYxIMB8GA1UdIwQYMBaAFJASI91ChedKF9vUbztP0Cvv +wYxIMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBANH9iY79aQfdVLix ++JHaYmgC2Iw7Zl6bGH/ejHJf5dXZ2E/0vMlLqf+XeZFhyhNfz09ZLZH5Ztx4ur0Q ++qbVGPHlfpenknnxNJjGI9+91lYquSb0Gm6vPKdG4PyabzvPziFFW+84vaTuDODq +1EmJSNlzhSQ6vlFt9AyMgrN5WFcuJmATzcZLskpnZIasOLfPtpce+8DlGocKFpNh +qkRTGhQ+LWT/7hc29FmAWWGUc4QsllQ204lpgxQjr8aQywzv1DhB6ZX7ch3IshrZ +9sozCnN3tDbsmjmzeiSFaZRz1M6dAOLjIC6Y2aVGNDSciTXC53Oxn8wtrApOkc8i +RP2l+Jg= -----END CERTIFICATE----- diff --git a/tests/ssl/ca-key.pem b/tests/ssl/ca-key.pem index 4293bfe..c6e485d 100644 --- a/tests/ssl/ca-key.pem +++ b/tests/ssl/ca-key.pem @@ -1,27 +1,27 @@ -----BEGIN RSA PRIVATE KEY----- -MIIEogIBAAKCAQEAtzyD2ZwWbWxceqNaMK9JENg1bGmh8ZOu3SGREyt13JW32+Fz -pOz2T28GLC+lUGex8VbliMbvZsTW7qyU8ZSd2Dem1i8Gh+V99viE4mjD/ziycoi9 -0ucxD58ER9m9c70aqmJip+mHSNL7aA1Vo4FRbwNxeOf40Kz8miONFu5AJcE/E4iY -sz3yhYaLMEe/CWfBIt1tC22chJsOz4mNl4CGIXta8BDR+3kvjeBfIscB1QKHtZSk -8pzd2kVw4ilpKICNd4tPdD0zLvXedRqOb5UewocHzAlpHmox/vzk4I8R4PiWi/Ap -zDqGF9N037o/dx4+zmcylr7v7lDccxqmXwDuUwIDAQABAoIBAEEl1ecX1O2Aunyr -+ZQXrk274XqzL+3ZSTG8Dn2XVSdhX+ZgiSJZUdW6LqKlKgylYaHh+Ggh+to6IATp -/WbLJTfLyZibTaIhmSCnCXAKOa1Tdja8oWkL4+ie7AGzy+ULliCALH1wzTW6NcKw -AwPIJbDns39+Unu3FXSkMTS27r29Fmb+bsYSXzpKSszByZuonQ9AIFCihF2Vzhki -lFo7Gk6Fje+wBEI6mYywDxlelC4mKJoAba5r7H78sV+aA8fxhEoEEwkfZSKn7HWn -QjPjgI9C6Dtt5XhYic8a0RNQv4PshgM48YRFbTjleMm6iz5vliSvoeE/3/6bPIFP -hfKdF0ECgYEA3dqFhiJ0ema2oxrhkHMMOA5qRg7jzBfCUhSE0qJYDs6w/eKxHBXP -MxuQ96ww/sbkLLpbhCfpwcX2DroL5BuAbE4T+qE7VqRlyjUWH7z7PMaBVQqTlSy4 -E0sg3LqrwDVI144xlCu6+5e62BP1TfBq263YngOxz7iqgQVnYppccCECgYEA03Bl -xKdXSun7i2kfOeYQM/1gNICwCWadhcxFZHNpZC2DqMqkNoESX2wQJTWBLNnzQetF -LEZFV8rzPAH/k696lY9JVGTDMNdero0f7v+Ia4dqcMFTtygL8fJmTtANGmaAzQCA -qqRdustNmsWwpsMhElQNyeIJeb7ZPwACWtPen/MCgYAXOqAscUMc5dBNt6zSgRlQ -bUH3X+u+HOa9zWQy4ciylDW3/5pnxGjTgxlktWTT6GNPw5t9dOhm36Fp3VUNZ0vF -C0/QOD2MTt5Rk8ljPVhY/rff/aGCRxJnAsDIG8uL7ohX+Y17ZDDJ0xM/OKfAp2Go -6sT5lo1xoHZJ2BUBIAR5wQKBgHImvmq7RZ+GT23mpRsnIBxRcP0ndOK+adDwhY5D -2ORixi/8p0ddy8OEnfrYthK24GP4VvIeRhWt1j/RfGAJXw8buqU7eT4HKHDodBMe -FlKnW0ngtgeuMTTAf4eRP2G/cU48NTrrXkcYt58Vl9eQhWxVwNP7ms4FwVgH8z2C -ITENAoGAFbz27P7GWNdT9Yz4uE9mQnJI9ESNlhImPRop+HkhaZHBDNXZx4+o4eTO -cuwdWfWCXz2fzQFKpDRprHh0avFc7NHD41gn1epRNqFEljvUrIQ81YtTpnaBG1ie -MXmVJqO4fZz3z+7uW9idCVwhKN2nswYoMVoP673QiDkWc6CH1h8= +MIIEpAIBAAKCAQEA1PuSrVn+FvHD9W5H4BGphkxxSwM1Tl78F3o2Ybq0UNdAE6iQ +irmg1egt+ixa7mnI2D3CCIklHJYfVMLWgorIOHMukBaLwrMeZU33Y9cRnZQPP9eo +j2XFyLao+3vPK/0xc+o6EdZs02WAuuTjQPDeAJRI09nZFwQaS9Z2fgE9TB1zKcIS +kBrZhXNFlPuOtibDn4UlTqmrZwmN09Fh2o6IO3eLW9llZ8wa5tp2g6gBb3BrPIEp +wlZT9TUUEMNp+airG4yP+y66LK3Aln1WrWoRfjxHQXSQOLLFmbOxBSBXDLk4K2ff +YZxUgg0weicNpgK5RcgyxyrRY3DUutuw00GfBQIDAQABAoIBAQCASUQRPJqK0Xc6 +NwH+GkVlSlgXWcha+2WW8psdBKul4fGLpcXieWtCTQacoOjooDlE3vYn1AvRiy82 +C+HPYa62KdLLIXlvfhp55Jt1vM60fsEssEaskR2wBy4DxJCGK40FB/mQUvrb3lDK +wiGMNUlTSf4P9TEI5wS712MqBK8aT62IWVlnIbUEsD+kAZHs74JTNpV4PpmgQR1G +FIYb8yBJeAB4X2E62fY6ZJAXIW8GK+M3k+Uv6K3ifovvvMYAsoWUwEAjRHc/xRdy +KertTF+QZkZfCFLv2aoAL/VOnwpvWdRaLo4C3wfJqxsFBO5sgS8u3mYg1LlVIKQB +TceEmCYBAoGBAOrQGmtzKsy0Ax4xtkdG59Or+dPdiKWMUP1g10Byrj12xcj3vag8 +31cuIlXymv9YCbkXV34IgDURubs4Hp/vkzLmSJWRuR4QnU8etEWpKernHLJ00V2g +sIhQyKodP1g7D4bbbe5539BNW1zVgj8p6bmh5BF429PR9JnKeUsrstyFAoGBAOgz +N+chiPE1WkIKOoVK9XPn5BuhKEYpaBSdU4HUdHZldwzK2LfDmkydFL6ZEcsOBjUx +gnxrE1XDuK41QMiuUpIOVHoeuJQIvILuQNBGNxrajoER1EVNXh1xocSUJ11ygUkp +TmHrKQcSKyb+28qABGdlLslrCDeku7f6mY3dxoCBAoGABUJ8FQQTZVpy5249owMX +lko34mMH+I1YExTkPXFULdRHQeUqvmX+qrlB06MHjcivDxJSx2PxWz72ZhcvuG1p +Yq592bvV5bKBk5AggZ70bWqX3fd36Rz8V1FX7VeSX6uTAXZQ1BKuzL+u2DmAHWIW +9i2GKk4Gvovparh6VxC3hPECgYEAk8w+MhVraDVQjSabl0peL/eTf262BurGQBDg +HYyQ0OfGvlLDXTzZExkNIkCmTbxQgT1RVEaHmRiqjeCBqvsivar3ZH/3duqUqzZh +9PAslSA2grtJhQ84777rfAfdgqKm3l23caZQiBqtcvXYCu4vX2zNOhGxulFV10Zg +xSc7+YECgYBVl7xDwtIrBx7rG4MsLArW7yjm37g0RBCJVFUdhuaI7f8cRbf9pgtb +hRvbUcs4Cwr/m+d01u36rkw9NIxnAtqgSQETAwVJqQ4INuFAiPbN+l5epW4VRLP7 +Umme/A7s/4tBUjGlYPqpStffSUF1hkRuFylqLpcwBFFwWzCsCnqvBw== -----END RSA PRIVATE KEY----- diff --git a/tests/ssl/client-cert.pem b/tests/ssl/client-cert.pem index c5d9c0d..50cf432 100644 --- a/tests/ssl/client-cert.pem +++ b/tests/ssl/client-cert.pem @@ -1,18 +1,20 @@ -----BEGIN CERTIFICATE----- -MIIC+DCCAeACAQEwDQYJKoZIhvcNAQEFBQAwQjELMAkGA1UEBhMCWFgxFTATBgNV -BAcMDERlZmF1bHQgQ2l0eTEcMBoGA1UECgwTRGVmYXVsdCBDb21wYW55IEx0ZDAe -Fw0xNDA4MzAxMTA3NTdaFw0yNDA3MDgxMTA3NTdaMEIxCzAJBgNVBAYTAlhYMRUw -EwYDVQQHDAxEZWZhdWx0IENpdHkxHDAaBgNVBAoME0RlZmF1bHQgQ29tcGFueSBM -dGQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDHMRTqNtivI074Gb7/ -eCjYlKViIcoTtQdmK910owOSmbz8mKc5DGgNgcKDirYLkqI3wGpYYCOr16DKJv4f -pbLktkdICk8kb9040J7a3oAlJ+T813StLPiwYhtZMUz+oMMWpJ1nS8muutwatZIs -YL1SFSIVVxl7YfT8pIOFJzTiyh0Jg1qnkjYVAKG7C6HnQxjl2JcAOP6k41J5T5ST -yMZUfO+vZqWw8lZNLgXMrR/6qHFQNgFxfNw99C4XsNUf1vPpKRo2MU18adXA1xP9 -IqZiUXtEvV0TheIzTZlSICRhJPhXK9D9IS7G+Krjuj1p8PUKII7Uai0Sa6gKEzEF -SVnVAgMBAAEwDQYJKoZIhvcNAQEFBQADggEBAGPUwMCdHdABR946eOwn09Fe//X2 -Ot+I6Hoq/5AlSUR1nKfTZstmCPpir7zI00lqZX7NyshTDKc2hOYA9u06/X5VQ8F/ -UTKLFw1qr6RXrSu+aKCdRwyztS02HAuqLOvj4ftGoUe3TjIWFfK9JjiuSaio24QW -IYL2en8hF0gO1a2yeCqjmBXELewpCl8KwqFmSIet1hxkNNlXBhKRSjECGFC/4VKG -FqlQJu12O37mhEyGR9wgELx+Xz6x/r+ZvTkr1QS31YTA8AIUm/dYcJyuA+QPinh8 -t4oJ9EpCGfRsaeKdJHsotu88HUSY5ZWS6OBEIp/CB0JAlQqd4Vtr2A8Gn14= +MIIDNjCCAh4CAQEwDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCVUsxEzARBgNV +BAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0 +ZDEYMBYGA1UEAwwPbGliYXR0YWNoc3FsLWNhMB4XDTE1MDIxODE2MDQyNVoXDTI0 +MTIyNzE2MDQyNVowYzELMAkGA1UEBhMCVUsxEzARBgNVBAgMClNvbWUtU3RhdGUx +ITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDEcMBoGA1UEAwwTbGli +YXR0YWNoc3FsLWNsaWVudDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +AMgr1doaczeuqmtJZ+93phJ5n+U/NpvgZ5YRhNH7Sn7DaDeRf2oSg1/+htrOYiUJ +DtqNSp6Z0wgYWDyKREGQaBFYqZ4OFZNGDnfG972SX0dFKcXDBlSvQH8b9+W3alf9 +/b9VZ6MMN0hMj4BVFujvq97hwj6KyuYCe6PmIzRa76eELOryAjU51QJGdlRr9/C5 +fYSTiUPfNJ+1hAl2GX0vzNZYbvyPFw6tAHWkwCCMFhBiGwyLpXn5+DZgzHnrVcrE +7Uq92sT2V2rxfNxjFm4XfTODJVdyDeBlKFrzEM4aGhCiv+0DpSeM0MNDvhhnozuy +1g/gH36XUWkLunUymYjSBycCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAKzS4j46a +DmnVXv4vWIW7KioU08i08Snv98UPUPg99f9fMtJZw99gEXder5QLIUkyRudzs3kb +OH+fARoO2rTxGI4ujggocTyf0REruLxKnAQCMH1MmBw0iCafw3TMDs/GD2Te5gBf ++h242q1sNcY3x8mlAMj1nNgjSrj6C4eyMgGyBEQxj7p0HaZCuSD0Mp0xzx+9nA0j +2QVAImws1M8Y5PO4o312nRuCNDsYCBkm2sNAqBeFlQR/vzA/2I99VZF/Ogp8PccW +zE+kZFDqoXm8eQxIqkHoh40MCvLZfS1Q7MYCxsnm6u9yBXBotMOYleb9l8p6LrPm +RYpuRQjexmcnIw== -----END CERTIFICATE----- diff --git a/tests/ssl/client-key.pem b/tests/ssl/client-key.pem index 515949a..289e4e5 100644 --- a/tests/ssl/client-key.pem +++ b/tests/ssl/client-key.pem @@ -1,27 +1,27 @@ -----BEGIN RSA PRIVATE KEY----- -MIIEowIBAAKCAQEAxzEU6jbYryNO+Bm+/3go2JSlYiHKE7UHZivddKMDkpm8/Jin -OQxoDYHCg4q2C5KiN8BqWGAjq9egyib+H6Wy5LZHSApPJG/dONCe2t6AJSfk/Nd0 -rSz4sGIbWTFM/qDDFqSdZ0vJrrrcGrWSLGC9UhUiFVcZe2H0/KSDhSc04sodCYNa -p5I2FQChuwuh50MY5diXADj+pONSeU+Uk8jGVHzvr2alsPJWTS4FzK0f+qhxUDYB -cXzcPfQuF7DVH9bz6SkaNjFNfGnVwNcT/SKmYlF7RL1dE4XiM02ZUiAkYST4VyvQ -/SEuxviq47o9afD1CiCO1GotEmuoChMxBUlZ1QIDAQABAoIBAH71NpptqMBAJfYW -GtmjkY0xeRPJ642SBYxGixjrSbynxn/NIFBJKwzo1ryWrZ9Er6YPOvjnFfVSM0aF -gdVT/GiwEVDGWVkk/4BV39oqlMyZ1+abwN8b2co6TaoUtTlZ595Hv5d2A68dpGpV -rjwg0Ko/lAC8Ch7M+aQJi1ZT/e5JujghCW89v3EF3AZsr3uDvfG5P+8ZI5+yRouF -ku7z9nb8pcNMKPurFK6Cp8op9wbv7dkwJseltrtBsCh6g0qsLucdWgPjtMd0bW5Q -K3oaOGl96SoeuILA0KMhtsDD9Q2ce1g9URaCZhDIMY5jekCQwspomj1N2ZOxL+Eu -zA3a5yECgYEA5t6bm+35dK2IfbW8m5x3pZ1BhrJ66pC5afxNiQawAhwUoUwFKhbq -zcP5D+d9NNdIwfxu5EOCI5/otbu9Z346tZ/YpO/Qj62P4e1cAojqfghuV9DdzmEa -qFrjdtx/kLhctfMcRWtcqp81wmEJI3yWSQ+jYt2XPSBoeqb7rsmi5IkCgYEA3N+9 -62z5o6Hw4Yqe9g/wnJZ77ZhQxPu928danRdY+U0JKqC6pZo2gE7EofoJ0lYLthxn -yHCgHnOFicN3Q1xfPDNorxKhFpSgvf5b92+pWDYnvRXlrqSJE4RgV3tN3ZeG3etf -CCXKP8bdohtq6wruVVlSQtSrHsJCZzJHchLpz+0CgYBzQqnvhDSpYsWk9SmPiuNV -BJilNdAV8WEQH81Z3sPamchW6swdQknBptheb1TcH6sMZgm63lVHkdstd+hMlgGb -kY0ocy3tvVn7EnSAM3jWqUDliLpkAai8anvraJQrXU+z6wavRbWC3W+KdsWIOPgS -y8LnZffOpbJjoaA/mB1B+QKBgQDAe7fN6B0xzdnXI+/d7gw42ifL6hZRZDWTx4qf -Jg6iy9C2NnYSBW+Dp6FSq01N4TC5ls2W7xeLEg+I/C/+IwzXsNGE6M47mHDwwi8x -Vj0VI7TD4sZTyQ2wVYeEFW/JMdkVop4hwpUbuVnCgPRPOypydLHsjdtGpfIqbrW2 -oubiDQKBgEYwQRmOlFkNOZrRZ6RTJdKj8ccmvD7/d4OqXkvAkHNc9kbcUq4IFWte -qBJmi5fQRvXmugkI9LWW+3scRWcHPVIe61LtYjQz1UmgfQhbibJ8q7l9zLGOlsOi -jpnqQXYUGv0N8aZBaI6Gh5EYpHkV8eLGJKD34bKxW/+0vEOj+Cg2 +MIIEpgIBAAKCAQEAyCvV2hpzN66qa0ln73emEnmf5T82m+BnlhGE0ftKfsNoN5F/ +ahKDX/6G2s5iJQkO2o1KnpnTCBhYPIpEQZBoEVipng4Vk0YOd8b3vZJfR0UpxcMG +VK9Afxv35bdqV/39v1Vnoww3SEyPgFUW6O+r3uHCPorK5gJ7o+YjNFrvp4Qs6vIC +NTnVAkZ2VGv38Ll9hJOJQ980n7WECXYZfS/M1lhu/I8XDq0AdaTAIIwWEGIbDIul +efn4NmDMeetVysTtSr3axPZXavF83GMWbhd9M4MlV3IN4GUoWvMQzhoaEKK/7QOl +J4zQw0O+GGejO7LWD+AffpdRaQu6dTKZiNIHJwIDAQABAoIBAQCg+mfMNBNOx4A0 +Md+NPLrpBrjpYzHmn8yOal5XhHD/iuSoM7G1O1g9/fKzyuAxCpzQdGp7LBgD3Zgw +b72+wISA1r3p50fAncmK2A9qfGl1ZpDWgyX3Os1yq6psKloyk4fatLNY870Nvsx1 +F3kKMZ0V7JcLNxE/cuW+BJlxRGSRYRPPlePIfgDk1t7SN0czQ0ecEP8pWFt928tS +jYWaBsQfAlilSakt+kRNsSNh8y9fXW/3g/KmebWYZusnYE7jM8VG11I+LngWIDx2 +C9uAAo/uTeml7Hb6jIFM2xf2NRsFvsK1cACFe4kWYK9puKSpWM3mZAiFzwhaapI1 +HGeq4DYRAoGBAPpaEzmjGB5ffOgJmjFEV/uyyAsNkJ/IvNOH+5EYfaonTf5rHZ4k +ruTEwb565sd8mYYaJ/WDXNQ7LV8JRfTbwqWta0lX+BeJ3YLIYNBiFqTM6Ac3IrD1 +QGR6wYDFROyS4bckjOLkfaEQxlNj9hRwQqPpJmM1ZGg4UqBIf4qIrgmfAoGBAMyv +8EILFRyl6CS3GKBaItNDhhtBFmTR9lZzftXlvGXoqOYL9xoczAifJ93vsjr+wU3Y +1gGVAtJDRRcsnkuoEOISQKAE7vKuMnGBl1bUSSjy5J4PuhYcHxtx5NMBI3hdtkS8 +HQbUO1SzMf/tMLUGpAVzBK2S/LQYBQNE/MmYJKV5AoGBAOoRMYxf+nrbWFMyNyH8 +/i3sN7Bt3FwoOLOlngVI2qUt3nQS/jwPnB10AJjxG7hDvN5ushGP4kjjk0YZy3hl +x5VTkM2gG+sWES7n3ey26OjoU7/7QsokYzIOu8CDsC9oHPU4jSjN7M+ceXEaMsdl +Nkk+AZAcKWZv0oDdh7GknOONAoGBAJJvlG1LTHFQaEJME3w0wBFwj3LUH9dFNv0m +Z6lTUHN//cWG7eNqkrXgVz86CsKWG2k8Je6/0mLm6Xjo3N63gEycTkus+932rfPy +iHkAKs725oQGMFU9DSwvUUt71wp30Lxf8ExAbantAWpdIKmB9LpJTSF4tP2K6Zsr +McZv6FfRAoGBAJGbZ+6cprYe1xHp3T7MPVXu7AFfEmv7QoCRTu4mKI02PSS19n7b +zcV6N1idXyvFPz1FMxoQTSiKk1WLjXkOvg+yOXUKARQcYAJb7QiWAHpdLeb29TYP +UGEgOFlO3NTbZu6FP1U6vsBGA9cdpee33KfltnRqhsEfAM0NFyL7pWTR -----END RSA PRIVATE KEY----- diff --git a/tests/ssl/client-req.pem b/tests/ssl/client-req.pem index 9c4d956..26cc18e 100644 --- a/tests/ssl/client-req.pem +++ b/tests/ssl/client-req.pem @@ -1,16 +1,17 @@ -----BEGIN CERTIFICATE REQUEST----- -MIIChzCCAW8CAQAwQjELMAkGA1UEBhMCWFgxFTATBgNVBAcMDERlZmF1bHQgQ2l0 -eTEcMBoGA1UECgwTRGVmYXVsdCBDb21wYW55IEx0ZDCCASIwDQYJKoZIhvcNAQEB -BQADggEPADCCAQoCggEBAMcxFOo22K8jTvgZvv94KNiUpWIhyhO1B2Yr3XSjA5KZ -vPyYpzkMaA2BwoOKtguSojfAalhgI6vXoMom/h+lsuS2R0gKTyRv3TjQntregCUn -5PzXdK0s+LBiG1kxTP6gwxaknWdLya663Bq1kixgvVIVIhVXGXth9Pykg4UnNOLK -HQmDWqeSNhUAobsLoedDGOXYlwA4/qTjUnlPlJPIxlR8769mpbDyVk0uBcytH/qo -cVA2AXF83D30Lhew1R/W8+kpGjYxTXxp1cDXE/0ipmJRe0S9XROF4jNNmVIgJGEk -+Fcr0P0hLsb4quO6PWnw9QogjtRqLRJrqAoTMQVJWdUCAwEAAaAAMA0GCSqGSIb3 -DQEBBQUAA4IBAQBhugl3VwEG0zxlkozgACsnj38rsQe5uZaGTqiu9Fl6WnFKmOnR -7lwnjkEt2k7lo0tgb7L/JPQZi0tdorsXZqPkaDG5J5npO+2ZWTEyE+7M4VpiqSQy -ypP3W6f+ccBnadAmitIdKRE6Ey1jNKxbgyaASJdL2ghk3zrm6kbFccjBUwzZClHy -Ce6pirg1DxIwbsfkflhxjajp70LcwwzSWk2p0EKQARlVVBQCIYW79FdMneT9jXYn -vnGgNvfaBnFuDrk3lsnAdCOtJazfyE88XJj762kDwvqs8ux87qCF9T3oIfNWJ0vD -5TcOBSdBR6AVpCaV7Xq9yh5fnHzr6EnIJJi5 +MIICqDCCAZACAQAwYzELMAkGA1UEBhMCVUsxEzARBgNVBAgMClNvbWUtU3RhdGUx +ITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDEcMBoGA1UEAwwTbGli +YXR0YWNoc3FsLWNsaWVudDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +AMgr1doaczeuqmtJZ+93phJ5n+U/NpvgZ5YRhNH7Sn7DaDeRf2oSg1/+htrOYiUJ +DtqNSp6Z0wgYWDyKREGQaBFYqZ4OFZNGDnfG972SX0dFKcXDBlSvQH8b9+W3alf9 +/b9VZ6MMN0hMj4BVFujvq97hwj6KyuYCe6PmIzRa76eELOryAjU51QJGdlRr9/C5 +fYSTiUPfNJ+1hAl2GX0vzNZYbvyPFw6tAHWkwCCMFhBiGwyLpXn5+DZgzHnrVcrE +7Uq92sT2V2rxfNxjFm4XfTODJVdyDeBlKFrzEM4aGhCiv+0DpSeM0MNDvhhnozuy +1g/gH36XUWkLunUymYjSBycCAwEAAaAAMA0GCSqGSIb3DQEBBQUAA4IBAQCS5/A7 +ty+bwvtQvuIeQdqKox1E0msw1rnJmIxHJp1QNIJ/yXV+FUHQbZU7LLPwLjwhEUAy +eZNG/Va6sGoyrSnu9blKczL65E1qPZDHpi8gRbeZdZyMhgorF5xSCcVhU5h6XQxf +BhhQ01df3gEuAksKE4LE9v/9WTPTnqd3znE2Sp9XLLSJY8wVcYNoBbq+WyRwvpBo +lw3WE8vcy5Jd9EeqAfVyZAsdBa0i5GMnLw+uqCq6ipHXcU2lNyNVAkmzfGJKKR7q +pDOK9ZqbJhi7SiIHEUwU1Aanc2kQdpa6tMK3/zLwKDh0XDm8BZi8fwl08Fjc25et +GfMsg+gklw6vjYPz -----END CERTIFICATE REQUEST----- diff --git a/tests/ssl/server-cert.pem b/tests/ssl/server-cert.pem index cbf003e..dd2c062 100644 --- a/tests/ssl/server-cert.pem +++ b/tests/ssl/server-cert.pem @@ -1,18 +1,20 @@ -----BEGIN CERTIFICATE----- -MIIC+DCCAeACAQEwDQYJKoZIhvcNAQEFBQAwQjELMAkGA1UEBhMCWFgxFTATBgNV -BAcMDERlZmF1bHQgQ2l0eTEcMBoGA1UECgwTRGVmYXVsdCBDb21wYW55IEx0ZDAe -Fw0xNDA4MzAxMTA2MDhaFw0yNDA3MDgxMTA2MDhaMEIxCzAJBgNVBAYTAlhYMRUw -EwYDVQQHDAxEZWZhdWx0IENpdHkxHDAaBgNVBAoME0RlZmF1bHQgQ29tcGFueSBM -dGQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCrEtHj5AFagE3x5E5j -WRqHqZVhoSWY8oK2vlw33tpq4udFqzUfCkMY6CqZwKylUhZR0GZGFMGqDO+FP4B6 -ypo3fdG8Nevn3tq5WaZl82Sq/j9f/mfxmg9oE3D5Z5i8xoBjaJNNMnTUZjKeWHnY -maF7IHFu9v+JuXUbsvWke6r08Za9IADxcKEs6Ulmped4jPfXZ44jmGofARnXiuY/ -AddNx2h//dEogJy2dtb4b0fjOzY5UQ3zc054Vh2tJAHcWgsKvXOesiEoxBZQYAX2 -mY+V3sOvZl30dJNzSyhpV7LaqQY0biOGwDg3L9xSc1dlqXUGPFCmt5IKx8kQ55Tb -+WipAgMBAAEwDQYJKoZIhvcNAQEFBQADggEBACtXv6tMCP9UZ15Si45s4Lt27xOo -LVHBrmwMOviuOiCoc/iolFaxKVmaaWTXU9oGYMfkCC9miH5PzjeKOZWJk1uYD+LR -6L35r8UlHfj7q61PaPWpl4057Rrfj57YlrljvrC4c3DO56dnsHMJfkJWaYIPHTX+ -o8NZ/GpxmOivEzGTzQkJ4fJX/NFFifPRG40+LLf5GS2vX/EqxOn/a7+ybRQ7iKCc -p5/1dlIZa9gc5oPvxL9s+4iZptjUgDx1cr76loDdsIjSKcr7o0W+X9MdsU/k7XML -ern28SyiyP0QAYihkhZGDzYL2nru9sSNvTP7Ev/lID6x3PeNn63T3Bm0Eps= +MIIDNjCCAh4CAQEwDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCVUsxEzARBgNV +BAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0 +ZDEYMBYGA1UEAwwPbGliYXR0YWNoc3FsLWNhMB4XDTE1MDIxODE2MDMzMVoXDTI0 +MTIyNzE2MDMzMVowYzELMAkGA1UEBhMCVUsxEzARBgNVBAgMClNvbWUtU3RhdGUx +ITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDEcMBoGA1UEAwwTbGli +YXR0YWNoc3FsLXNlcnZlcjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +ALdqaxM34/IillhtX37HrYKY2uQVcdYW/7jbi6MriGyx3pJwXvceOxWp93tWauvW +hZ7VY5qTkNvhHBJfumWRmnhxh9jMHYx+fDBZk490KyZnuSuN1Ax3waM4MnIF8RHs +rypAiRO2MFrrZirsZ+mA8HD0cwpt/oROpXTlS6cl4hyzvTQ5SwPR+l1Mi81qba4M +hKEIfc+H1VM4fJKbOoHydczGLo/RmBZX5N9ml/mknSzk78ZUCNNLdY5p4a92gAqu +0+iIeQOtpR46VTrqrNZPEpUvUJ5QguJdZhrGcBRpqAv6kdQUzYYovOtvHBuUk8t9 +flMar5FKzY7kSYnyZ7IIv+sCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAgt32zBO2 +gUiJTM7MlOfqs2WVboiZqOITAcg9aEG4+ETai4dD9BgnSPv4taF52FWgTUR+xg8d +2XwMEzMBrx7WsgSYzLN4+OEIvQjNwS+/Fr8C1If9N6qlmY2Zf7r4CSHyeFEn9+hk +SdBSEpqd+Q2jK/tQnMFOdXwhTEpPgEsfvC93892S/cmdiAY3dK5FRdM4N2Yzz21X +SMegaVsufHrWpIqrm54ICcLnQQiopCKasg4SDSdgnzzKvV8RKVcgdBFauYBURuVG +N81m9RbW+W6caL93OrPmXJNPdpZL2L7z1mML9Xwb+pvCfowZTPsb4BVlbOQZwErf +m9fZ6R/P2Gn0iQ== -----END CERTIFICATE----- diff --git a/tests/ssl/server-key.pem b/tests/ssl/server-key.pem index a382b95..4376676 100644 --- a/tests/ssl/server-key.pem +++ b/tests/ssl/server-key.pem @@ -1,27 +1,27 @@ -----BEGIN RSA PRIVATE KEY----- -MIIEpAIBAAKCAQEAqxLR4+QBWoBN8eROY1kah6mVYaElmPKCtr5cN97aauLnRas1 -HwpDGOgqmcCspVIWUdBmRhTBqgzvhT+AesqaN33RvDXr597auVmmZfNkqv4/X/5n -8ZoPaBNw+WeYvMaAY2iTTTJ01GYynlh52JmheyBxbvb/ibl1G7L1pHuq9PGWvSAA -8XChLOlJZqXneIz312eOI5hqHwEZ14rmPwHXTcdof/3RKICctnbW+G9H4zs2OVEN -83NOeFYdrSQB3FoLCr1znrIhKMQWUGAF9pmPld7Dr2Zd9HSTc0soaVey2qkGNG4j -hsA4Ny/cUnNXZal1BjxQpreSCsfJEOeU2/loqQIDAQABAoIBAHkpSx5sTckbNhkr -6ZjTcsbChNowl8BLgeiLyiSH4YnySno9V9I0InFxfTqIC77K9KPdRZI9ASy/HKTy -5LwS4kaLBhCW4A3I+IBtzjxGtfWlPJ1wQY4L3v2HR2xcwwBwVl4RosH6CmSkPRWI -9ENEC+p4f95ncXTJtPd5OCDWta3kg/2apnmoFc3PzdCh1dnSzLYCysmlhktFeoQu -EGev29V7KPbbjRlGBMMR47WSod/edOksbUoxEZ88NyvSggu1u7CIx3Y28iCF0dZT -IQgHWxCdVDyBhscDPMh1x2maJPFMYjVFvD+SlPqlNL94Sa0djibsYm+ux1Dy0r2n -VaJMfkECgYEA4MF01pBsijwUHhOwzbMoRKYWvbsMY33t9J5DbEBjREqVdLNrdFju -gCzBPHzJgCgFGP9/8cjdjVPvLfqB3oDuOTsNlwKaLxya0LR4k7IB8V8ZH7AljAU2 -0dirX2gFDzkEMmKRgNKxzmyStDBRuDHZUSLHRI9PASVtHb27qQyE0HcCgYEAwtrv -4uBcsOWBn/trfYMpXO2iWTVc5zWde3l5fIWiLEPtv0gtva19pj0p9jeTS7uQAoic -1UTNjHU/MMdRUSqUG1+XMnpkfxxaw7ulIir0b2Zg1mtSc3b+55LBlXkmygsW/2dk -4MyBuZSjx01jUHUpvEN/lcaoPZf+yQ+btcBD998CgYEApVVqb5RaY+4CFoYBn6/V -RXqwa+23FVFDxJjPnEhZPZloDCsYNsRc3ikOFULur7nA1jzNj71lTVubLMWE13sc -wzjvrFCbv2BZeoHn2S4vQ7HjN25KkJAdXYz3s/0/C42zyqS7yHo1llZELQ0GcGsr -JAZjc8nAImW3uRMjgx3Ubc0CgYEAimu1VdpEfnXLa7bTWUo/rAA0AGNkJ+tygDB/ -GPJljkSDNAs2UzRXuixhDsPUI0yOtP4PS4Gg81KnHSO6pIo2xGtXoUhI8/NUlw9J -88fH9QspZ6i93cB+vEsIsgJqh8TxBWaRxxAAZ7Er130mPBW/HDpm/CMviPHc0UAB -QU/f+MkCgYBOokk2+WxX0JhjIf14yT6AlxJ4NVSZMr9Lze//zqsKTDE0F2ZAmrWu -HoaQqQMbXXW1ocYB7C6kpE3z0TAvU8PQYhZQEUT4YMnCcnuaCeYzOt0ooO42sApW -ze0uh7ByqeTVFtYswtG/bW7FmDBwSjParURhle9EJlUbrjlM3+fZQQ== +MIIEpAIBAAKCAQEAt2prEzfj8iKWWG1ffsetgpja5BVx1hb/uNuLoyuIbLHeknBe +9x47Fan3e1Zq69aFntVjmpOQ2+EcEl+6ZZGaeHGH2MwdjH58MFmTj3QrJme5K43U +DHfBozgycgXxEeyvKkCJE7YwWutmKuxn6YDwcPRzCm3+hE6ldOVLpyXiHLO9NDlL +A9H6XUyLzWptrgyEoQh9z4fVUzh8kps6gfJ1zMYuj9GYFlfk32aX+aSdLOTvxlQI +00t1jmnhr3aACq7T6Ih5A62lHjpVOuqs1k8SlS9QnlCC4l1mGsZwFGmoC/qR1BTN +hii8628cG5STy31+UxqvkUrNjuRJifJnsgi/6wIDAQABAoIBAQCtm/RIF6ISYjyu +7K/0X+rTb/3Y4JeEzvY0stLEmwMh52bGc8jf3eSNR/lx7EV+f+qwgkkqWj1GcxhQ +J/5V/3EYSlYMln/tqRfB6DftFEd3rbwvBqtNNdm6tgnBtfAOSFsxAi790niIxsJJ +JMXi1uI/+JIfsCe2cn7YW+W1C/2vrbOPr+QLJ6BZ5jqXiziHzl9lpnd9P6YBzc9Z +RIiFie3G0JeGymDz+xZ2Ql2zx8PtfEIx2CCRSEzthjt2YZgga3f+SZbpqfe64PU1 +LYbK5l4jPP/9dovlcvJn9amwB6O1Lxp5Xz+ZN9+YGbGGt3JyvIdspXi7XXERrd5y +E8131R6ZAoGBAOC+BOeynxOxIhzcLV7BGuZKUVpN0RyX7jt24HnBTCaGxKMV64rD +Jgz5Cihn/HTUNgInwrUHbvxwSlY1VLGEnuQK+0cvvkH6bxnPB/uS3rseOkvSS9j8 +nxmtdD+yswQKNMgzhtajpZ01Xkfx7Ud8jT5vMK/7niof/Lyx4ViUwCsfAoGBANDs +9fInsDf19I9DwFDuGHnYU9WF5uSimIgRpevqMVES5dTrfXzCrDkMWnrXxzNr+9dj +QWa1Ou5vosUfUANH9YxcNLKsxZ0ihznDCo/ZzsSDiP5mACjouTxKn1EfA6C7Hzi/ +nk6JcNWidTx4jfmie3OCDglWSROjI1sTGIr5gF21AoGBAJ5iC77lyOntyWahXHAM +ktJ8yXxkntwRzlil3Gix6uKz01xDlG2EPgqib6AuOGJ1M2KtdrBxfqv0zs6WYwt/ +tSJtAs0WPnTs8uMzXiLTTJh+IwNQPxe6YL2N2gESBMryDmSQu5QEXDDAbaMyQdBB +XKEFZ0B+iOaTCGBK087DdfJtAoGAWsnOKreidP71klgPt1tv2WrvK0dvyYT6oY6B +up3fZmq+4yKeOlviOTwsCVvBHZBcNQHVxssUW865Pc3YmERp6N+cqtQ3X4xElQ4z +hcVRe8Xo/xvWD/DppdCLoNXIXs1RyPhD078YAE4Dgg6lK4i2+r/WV6peQSFQWOBY +dvPrG00CgYAui4hmJRrpFiD5uqfI5s9ZUZ4Tx8MU5lpvwQpW9bdnqr3Ff+5nxXuu +t3E1P6nUzduxXrgjL9xOxBbpJiR8vpl1jvlQj2B+xzZ/kTznWZLlLW4SuI00kTwy +yH8L8vND64Vadkvh4Q3gr3Cz1pyD+zz8xTmgCXje+BEtCsqCGSHQmQ== -----END RSA PRIVATE KEY----- diff --git a/tests/ssl/server-req.pem b/tests/ssl/server-req.pem index d519b3d..80f7b07 100644 --- a/tests/ssl/server-req.pem +++ b/tests/ssl/server-req.pem @@ -1,16 +1,17 @@ -----BEGIN CERTIFICATE REQUEST----- -MIIChzCCAW8CAQAwQjELMAkGA1UEBhMCWFgxFTATBgNVBAcMDERlZmF1bHQgQ2l0 -eTEcMBoGA1UECgwTRGVmYXVsdCBDb21wYW55IEx0ZDCCASIwDQYJKoZIhvcNAQEB -BQADggEPADCCAQoCggEBAKsS0ePkAVqATfHkTmNZGoeplWGhJZjygra+XDfe2mri -50WrNR8KQxjoKpnArKVSFlHQZkYUwaoM74U/gHrKmjd90bw16+fe2rlZpmXzZKr+ -P1/+Z/GaD2gTcPlnmLzGgGNok00ydNRmMp5YediZoXsgcW72/4m5dRuy9aR7qvTx -lr0gAPFwoSzpSWal53iM99dnjiOYah8BGdeK5j8B103HaH/90SiAnLZ21vhvR+M7 -NjlRDfNzTnhWHa0kAdxaCwq9c56yISjEFlBgBfaZj5Xew69mXfR0k3NLKGlXstqp -BjRuI4bAODcv3FJzV2WpdQY8UKa3kgrHyRDnlNv5aKkCAwEAAaAAMA0GCSqGSIb3 -DQEBBQUAA4IBAQBTrrnuR8Co7CC0bwFFXx5mRedCQa++7REOXWJhhBcII81RYu96 -aO/2s8H/5KLmdSNP8TgdZ3Sd+ySHixD1vPV85MHixywBIDAjvUCW4t3yyWTWVB70 -fThHnABJpiaQa5dZ/PMZkIER1ZPb20GtYUEtbuLhlFltxkAw9jCvnxoRZMe9IDj0 -R21veV7ca3AwKAZALeAEVBIqZQub4EVTyV9gj+FDcWfMtLoW8Q/uxczYLtvIHh9a -ixqQi82mMRhIA8NRkk260llvu3Mv6toCN6kr3X78LENo+Jt/W8268XA7fIzVnXlu -ZgXHADzrdM8Uy3pF5APbFAk03S/qgjSBB6C6 +MIICqDCCAZACAQAwYzELMAkGA1UEBhMCVUsxEzARBgNVBAgMClNvbWUtU3RhdGUx +ITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDEcMBoGA1UEAwwTbGli +YXR0YWNoc3FsLXNlcnZlcjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +ALdqaxM34/IillhtX37HrYKY2uQVcdYW/7jbi6MriGyx3pJwXvceOxWp93tWauvW +hZ7VY5qTkNvhHBJfumWRmnhxh9jMHYx+fDBZk490KyZnuSuN1Ax3waM4MnIF8RHs +rypAiRO2MFrrZirsZ+mA8HD0cwpt/oROpXTlS6cl4hyzvTQ5SwPR+l1Mi81qba4M +hKEIfc+H1VM4fJKbOoHydczGLo/RmBZX5N9ml/mknSzk78ZUCNNLdY5p4a92gAqu +0+iIeQOtpR46VTrqrNZPEpUvUJ5QguJdZhrGcBRpqAv6kdQUzYYovOtvHBuUk8t9 +flMar5FKzY7kSYnyZ7IIv+sCAwEAAaAAMA0GCSqGSIb3DQEBBQUAA4IBAQA30wIw +ELoJoObFxBCTDLTBScqwn7SwPw7wO+qI/u6rEav5pZBSfp8gBz5aYmlil7dbl7yM +Q1MlBlksrn++/9Qwlqt26Qgu6Ox3RNToIjKafoccPDlht7aZ9cSNfj6t52jsaNrU +/OJwpkNqarMDw74M0QKWX1G9+xsUopbKxuBfqxesEbOL9wLqlhLouyFaMG35TSbk +NLqm5nuxpgD96whpG1tc7eBZqocP8ahGRUqfPXHh8wMJw93DYdJ+qha1kgcvey46 +hTeWvDSZztfxnXsfG/JQmbyWWtN4vKQXZxU1Y1eNBW5f1xEOdEB9XqIAB9dpGboa +JmFtqRl44O2eTx1Z -----END CERTIFICATE REQUEST----- diff --git a/tests/asql/statement.cc b/tests/statement.cc similarity index 98% rename from tests/asql/statement.cc rename to tests/statement.cc index f2b2709..0e415f9 100644 --- a/tests/asql/statement.cc +++ b/tests/statement.cc @@ -17,7 +17,7 @@ #include #include "version.h" -#include +#include int main(int argc, char *argv[]) { diff --git a/tests/asql/statement_param.cc b/tests/statement_param.cc similarity index 95% rename from tests/asql/statement_param.cc rename to tests/statement_param.cc index 3b13b52..071d85f 100644 --- a/tests/asql/statement_param.cc +++ b/tests/statement_param.cc @@ -17,7 +17,7 @@ #include #include "version.h" -#include +#include int main(int argc, char *argv[]) { @@ -25,7 +25,7 @@ int main(int argc, char *argv[]) (void) argv; attachsql_connect_t *con; attachsql_error_t *error= NULL; - const char *data= "SELECT ? as a, ? as b, FROM_UNIXTIME(1196440219) as c"; + const char *data= "SELECT ? as a, ? as b, CONVERT_TZ(FROM_UNIXTIME(1196440219),@@session.time_zone,'+00:00') as c"; const char *data2= "hello world"; attachsql_return_t aret= ATTACHSQL_RETURN_NONE; uint16_t columns; diff --git a/tests/asql/statement_reuse.cc b/tests/statement_reuse.cc similarity index 96% rename from tests/asql/statement_reuse.cc rename to tests/statement_reuse.cc index dfc4792..65673b1 100644 --- a/tests/asql/statement_reuse.cc +++ b/tests/statement_reuse.cc @@ -17,7 +17,7 @@ #include #include "version.h" -#include +#include int main(int argc, char *argv[]) { @@ -25,7 +25,7 @@ int main(int argc, char *argv[]) (void) argv; attachsql_connect_t *con; attachsql_error_t *error= NULL; - const char *data= "SELECT ? as a, ? as b, FROM_UNIXTIME(1196440219) as c"; + const char *data= "SELECT ? as a, ? as b, CONVERT_TZ(FROM_UNIXTIME(1196440219),@@session.time_zone,'+00:00') as c"; const char *data2= "hello world"; const char *data3= "dlrow olleh"; attachsql_return_t aret= ATTACHSQL_RETURN_NONE; diff --git a/tests/statement_semi_block.cc b/tests/statement_semi_block.cc new file mode 100644 index 0000000..15b5621 --- /dev/null +++ b/tests/statement_semi_block.cc @@ -0,0 +1,83 @@ +/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab: + * Copyright 2014 Hewlett-Packard Development Company, L.P. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. You may obtain + * a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + */ + +#include +#include "version.h" +#include + +int main(int argc, char *argv[]) +{ + (void) argc; + (void) argv; + attachsql_connect_t *con; + attachsql_error_t *error= NULL; + const char *data= "SELECT ? as a, ? as b, CONVERT_TZ(FROM_UNIXTIME(1196440219),@@session.time_zone,'+00:00') as c"; + const char *data2= "hello world"; + attachsql_return_t aret= ATTACHSQL_RETURN_NONE; + uint16_t columns; + + con= attachsql_connect_create("localhost", 3306, "test", "test", "", NULL); + attachsql_connect_set_option(con, ATTACHSQL_OPTION_SEMI_BLOCKING, NULL); + attachsql_statement_prepare(con, strlen(data), data, &error); + ASSERT_FALSE_(error, "Statement creation error"); + while(aret != ATTACHSQL_RETURN_EOF) + { + aret= attachsql_connect_poll(con, &error); + if (error && (attachsql_error_code(error) == 2002)) + { + SKIP_IF_(true, "No MYSQL server"); + } + else if (error) + { + ASSERT_FALSE_(true, "Error exists: %d", attachsql_error_code(error)); + } + } + ASSERT_EQ_(2, attachsql_statement_get_param_count(con), "Wrong number of params"); + attachsql_statement_set_string(con, 0, 11, data2, NULL); + attachsql_statement_set_int(con, 1, 123456, NULL); + attachsql_statement_execute(con, &error); + aret= ATTACHSQL_RETURN_NONE; + while(aret != ATTACHSQL_RETURN_EOF) + { + aret= attachsql_connect_poll(con, &error); + if (aret == ATTACHSQL_RETURN_ROW_READY) + { + columns= attachsql_statement_get_column_count(con); + attachsql_statement_row_get(con, &error); + printf("Got %d columns\n", columns); + size_t len; + char *col_data= attachsql_statement_get_char(con, 0, &len, &error); + printf("Column 0: %.*s\n", (int)len, col_data); + printf("Column 1: %d\n", attachsql_statement_get_int(con, 1, &error)); + ASSERT_EQ_(123456, attachsql_statement_get_int(con, 1, &error), "Column 1 result match fail"); + ASSERT_EQ_(ATTACHSQL_COLUMN_TYPE_LONG, attachsql_statement_get_column_type(con, 1), "Column 1 type match fail"); + ASSERT_STREQL_("hello world", col_data, len, "Column 0 result match fail"); + col_data= attachsql_statement_get_char(con, 1, &len, &error); + ASSERT_STREQL_("123456", col_data, len, "Column 0 str conversion fail"); + col_data= attachsql_statement_get_char(con, 2, &len, &error); + printf("Column 2: %.*s\n", (int)len, col_data); + ASSERT_STREQL_("2007-11-30 16:30:19", col_data, len, "Column 2 str conversion fail"); + attachsql_statement_row_next(con); + } + if (error) + { + ASSERT_FALSE_(true, "Error exists: %d", attachsql_error_code(error)); + } + } + attachsql_statement_close(con); + attachsql_connect_destroy(con); +} diff --git a/tests/asql/statement_twice.cc b/tests/statement_twice.cc similarity index 94% rename from tests/asql/statement_twice.cc rename to tests/statement_twice.cc index 7919fb5..23ec5cd 100644 --- a/tests/asql/statement_twice.cc +++ b/tests/statement_twice.cc @@ -17,7 +17,7 @@ #include #include "version.h" -#include +#include int main(int argc, char *argv[]) { @@ -25,7 +25,7 @@ int main(int argc, char *argv[]) (void) argv; attachsql_connect_t *con; attachsql_error_t *error= NULL; - const char *data= "SELECT ? as a, ? as b, FROM_UNIXTIME(1196440219) as c"; + const char *data= "SELECT ? as a, ? as b, CONVERT_TZ(FROM_UNIXTIME(1196440219),@@session.time_zone,'+00:00') as c"; const char *data2= "hello world"; attachsql_return_t aret= ATTACHSQL_RETURN_NONE; uint16_t columns; @@ -91,7 +91,7 @@ int main(int argc, char *argv[]) ASSERT_FALSE_(true, "Error exists: %d", attachsql_error_code(error)); } } - attachsql_statement_set_float(con, 0, 3.14159, NULL); + attachsql_statement_set_double(con, 0, 3.14159, NULL); attachsql_statement_set_datetime(con, 1, 2014, 10, 6, 21, 50, 20, 324560, NULL); attachsql_statement_execute(con, &error); aret= ATTACHSQL_RETURN_NONE; @@ -106,7 +106,7 @@ int main(int argc, char *argv[]) size_t len; char *col_data= attachsql_statement_get_char(con, 1, &len, &error); printf("Column 0: %.*s\n", (int)len, col_data); - printf("Column 1: %f\n", attachsql_statement_get_float(con, 0, &error)); + printf("Column 1: %f\n", attachsql_statement_get_double(con, 0, &error)); ASSERT_STREQL_("2014-10-06 21:50:20.324560", col_data, len, "Column 0 result match fail"); col_data= attachsql_statement_get_char(con, 0, &len, &error); ASSERT_STREQL_("3.14159", col_data, 7, "Column 0 str conversion fail"); diff --git a/tests/transaction.cc b/tests/transaction.cc new file mode 100644 index 0000000..8ee5d40 --- /dev/null +++ b/tests/transaction.cc @@ -0,0 +1,118 @@ +/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab: + * Copyright 2014 Hewlett-Packard Development Company, L.P. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. You may obtain + * a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + */ + +#include +#include "version.h" +#include + +void cycle_query(attachsql_connect_t *con) +{ + attachsql_error_t *error= NULL; + attachsql_return_t aret= ATTACHSQL_RETURN_NONE; + while (aret != ATTACHSQL_RETURN_EOF) + { + aret= attachsql_connect_poll(con, &error); + if (aret == ATTACHSQL_RETURN_ROW_READY) + { + attachsql_query_row_next(con); + } + if (error && (attachsql_error_code(error) == 2002)) + { + SKIP_IF_(true, "No MYSQL server"); + } + else if (error != NULL) + { + ASSERT_FALSE_(true, "Error exists: %s", attachsql_error_message(error)); + } + } +} + +int main(int argc, char *argv[]) +{ + (void) argc; + (void) argv; + attachsql_connect_t *con; + attachsql_error_t *error= NULL; + const char data[]= "CREATE DATABASE IF NOT EXISTS testdb"; + const char data2[]= "CREATE TABLE IF NOT EXISTS testdb.trans_test (a int, b int)"; + const char data3[]= "START TRANSACTION"; + const char data4[]= "INSERT INTO testdb.trans_test VALUES (1,2),(2,3),(3,4)"; + const char data5[]= "COMMIT"; + const char data6[]= "SELECT * FROM testdb.trans_test"; + attachsql_return_t aret= ATTACHSQL_RETURN_NONE; + attachsql_query_row_st *row; + + con= attachsql_connect_create("localhost", 3306, "test", "test", "", NULL); + attachsql_query(con, strlen(data), data, 0, NULL, &error); + cycle_query(con); + attachsql_query_close(con); + + attachsql_query(con, strlen(data2), data2, 0, NULL, &error); + cycle_query(con); + attachsql_query_close(con); + + attachsql_query(con, strlen(data3), data3, 0, NULL, &error); + cycle_query(con); + attachsql_query_close(con); + + attachsql_query(con, strlen(data4), data4, 0, NULL, &error); + cycle_query(con); + attachsql_query_close(con); + + attachsql_query(con, strlen(data5), data5, 0, NULL, &error); + cycle_query(con); + attachsql_query_close(con); + + attachsql_query(con, strlen(data6), data6, 0, NULL, &error); + + uint8_t current_row= 0; + while(aret != ATTACHSQL_RETURN_EOF) + { + aret= attachsql_connect_poll(con, &error); + if (aret == ATTACHSQL_RETURN_ROW_READY) + { + row= attachsql_query_row_get(con, &error); + if (current_row == 0) + { + ASSERT_STREQL_("1", row[0].data, 1, "Bad row data"); + ASSERT_STREQL_("2", row[1].data, 1, "Bad row data"); + } + if (current_row == 1) + { + ASSERT_STREQL_("2", row[0].data, 1, "Bad row data"); + ASSERT_STREQL_("3", row[1].data, 1, "Bad row data"); + } + if (current_row == 2) + { + ASSERT_STREQL_("3", row[0].data, 1, "Bad row data"); + ASSERT_STREQL_("4", row[1].data, 1, "Bad row data"); + } + current_row++; + attachsql_query_row_next(con); + } + if (error && (attachsql_error_code(error) == 2002)) + { + SKIP_IF_(true, "No MYSQL server"); + } + else if (error) + { + ASSERT_FALSE_(true, "Error exists: %d", attachsql_error_code(error)); + } + } + attachsql_query_close(con); + attachsql_connect_destroy(con); +} diff --git a/tests/asql/version.cc b/tests/version.cc similarity index 95% rename from tests/asql/version.cc rename to tests/version.cc index 6c40801..7ec0373 100644 --- a/tests/asql/version.cc +++ b/tests/version.cc @@ -17,7 +17,7 @@ #include #include "version.h" -#include +#include int main(int argc, char *argv[]) {