support protocol ob20 and full link trace
This commit is contained in:
113
.secignore
Normal file
113
.secignore
Normal file
@ -0,0 +1,113 @@
|
||||
##########################################################
|
||||
# OBFlow Secret Scan Ignore List #
|
||||
##########################################################
|
||||
# Above the segmentation lines there are suspected privacy information #
|
||||
# Please use the file name as the first line and the igored information #
|
||||
# should be started with tab. #
|
||||
# Under the segmentation lines there are the folders which you need to ignore #
|
||||
##########################################################
|
||||
**
|
||||
http://www.gnu.org/licenses/
|
||||
http://www.gnu.org/licenses
|
||||
http://license.coscl.org.cn/MulanPubL-2.0
|
||||
https://open.oceanbase.com/
|
||||
https://open.oceanbase.com
|
||||
https://github.com/oceanbase/oceanbase
|
||||
https://github.com/oceanbase/oceanbase/issues
|
||||
http://www.mysql.com/downloads
|
||||
http://dev.mysql.com/doc/refman/5.7/en/source-installation.html
|
||||
http://dev.mysql.com/doc/refman/5.7/en/
|
||||
http://www.gnu.org/licenses/
|
||||
http://oceanbase.com/
|
||||
https://gw.alipayobjects.com/zos/bmw-prod/d6c1a0b7-c714-4429-8a33-2b394a5c1bf1.svg
|
||||
https://www.oceanbase.com/)
|
||||
https://www.oceanbase.com/docs)
|
||||
http://tools.ietf.org/html/rfc1950
|
||||
http://zlib.net/
|
||||
http://zlib.net/zlib_faq.html
|
||||
http://marknelson.us/1997/01/01/zlib-engine/
|
||||
http://java.sun.com/developer/technicalArticles/Programming/compression/
|
||||
http://search.cpan.org/~pmqs/IO-Compress-Zlib/
|
||||
http://docs.python.org/library/zlib.html
|
||||
http://wiki.tcl.tk/4610
|
||||
http://palmzlib.sourceforge.net/
|
||||
http://tools.ietf.org/html/...
|
||||
http://treebuild.metux.de/)
|
||||
http://www.zlib.org/advisory-2002-03-11.txt
|
||||
http://www.muppetlabs.com/~breadbox/software/assembly.html
|
||||
http://www.winimage.com/zLibDll/unzip.html
|
||||
http://marknelson.us/1997/01/01/zlib-engine/
|
||||
http://zlib.net/zlib_how.html
|
||||
http://www.pdflib.com/
|
||||
http://sourceforge.net/projects/acroformtool/
|
||||
http://www.sunfreeware.com
|
||||
http://www.gzip.org/#faq11
|
||||
http://www.ijs.si/software/snprintf/
|
||||
http://www.gnupg.org/
|
||||
http://www.info-zip.org/
|
||||
http://tools.ietf.org/html/rfc1951
|
||||
http://mariadb.mirrors.ovh.net/MariaDB/mariadb-%DB%/winx64-packages/mariadb-%DB%-winx64.msi
|
||||
http://timestamp.verisign.com/scripts/timstamp.dll)
|
||||
http://tools.ietf.org/html/rfc1950
|
||||
http://msdn2.microsoft.com/en-us/library/ms776446.aspx
|
||||
http://www.faqs.org/rfcs/rfc2781.html
|
||||
http://forums.belution.com/ja/vc/000/234/78s.shtml
|
||||
http://nienie.com/~masapico/api_ImageDirectoryEntryToData.html
|
||||
http://msdn.microsoft.com/en-us/library/windows/desktop/ms738586(v=vs.85).aspx
|
||||
https://mariadb.com/kb/en/library/eof_packet/
|
||||
https://mariadb.com/kb/en/library/2-binlog-event-header/
|
||||
http://www.php.net
|
||||
http://www.php.net/software
|
||||
http://www.netlib.org/fp/dtoa.c
|
||||
http://www.php.net/license/3_01.txt
|
||||
https://mariadb.com/kb/en/mariadb/configuring-mariadb-with-mycnf/
|
||||
https://dev.mysql.com/doc/refman/8.0/en/datetime.html
|
||||
https://jira.mariadb.org
|
||||
http://schemas.microsoft.com/wix/2006/wi
|
||||
https://facebook.github.io/watchman/)
|
||||
http://www.freedesktop.org/wiki/Software/pkg-config/)
|
||||
http://schemas.microsoft.com/office/word/2003/wordml
|
||||
http://www.php.net/software/
|
||||
jloup@gzip.org
|
||||
zlib@gzip.org
|
||||
info@winimage.com
|
||||
markn@ieee.org
|
||||
pmqs@cpan.org
|
||||
amk@amk.ca
|
||||
madler@alumni.caltech.edu
|
||||
rbrown64@csc.com.au
|
||||
kevin@rodin.wustl.edu
|
||||
Tyge.Lovset@cmr.no
|
||||
paag@tid.es
|
||||
c_rios@sonda.cl
|
||||
michael.bell@web.de
|
||||
toscano.pino@tiscali.it
|
||||
malbrech@eso.org
|
||||
vince@kyllikki.org
|
||||
georg@mariadb.com
|
||||
martinsc@uol.com.br
|
||||
sinisa@coresinc.com
|
||||
license@php.net
|
||||
georg@mysql.com
|
||||
andrey@mysql.com
|
||||
uwendel@mysql.com
|
||||
kpv@research.att.com
|
||||
gsf@research.att.com
|
||||
chongo@toad.com
|
||||
andrey@php.net
|
||||
someUser
|
||||
**/*.c
|
||||
http://www.gnu.org/licenses/
|
||||
http://www.gnu.org/licenses
|
||||
http://www.php.net
|
||||
http://www.php.net/software
|
||||
--------------------------------------------------------
|
||||
# Should use GLOB wildcard to config and analysis the ignored folder
|
||||
# The root patch shold start with '/'
|
||||
/BUILD/**
|
||||
/.secignore
|
||||
--------------------------------------------------------
|
||||
# Config the ignored fold to escape the Chinese scan by GLOB wildcard
|
||||
**/*.md
|
||||
/tools/**
|
||||
/test/test.conf
|
||||
@ -16,7 +16,7 @@ IF(COMMAND CMAKE_POLICY)
|
||||
ENDIF()
|
||||
|
||||
|
||||
PROJECT(mariadb-connector-c C)
|
||||
PROJECT(ob-connector-c C)
|
||||
|
||||
# Is C/C built as subproject?
|
||||
get_directory_property(IS_SUBPROJECT PARENT_DIRECTORY)
|
||||
@ -52,8 +52,8 @@ ENDMACRO()
|
||||
|
||||
### Options ###
|
||||
IF(NOT WIN32)
|
||||
#ADD_OPTION(WITH_MYSQLCOMPAT "creates libmysql* symbolic links" OFF)
|
||||
ADD_OPTION(WITH_MYSQLCOMPAT "creates libmysql* symbolic links" ON)
|
||||
ADD_OPTION(WITH_MYSQLCOMPAT "creates libmysql* symbolic links" OFF)
|
||||
#ADD_OPTION(WITH_MYSQLCOMPAT "creates libmysql* symbolic links" ON)
|
||||
ELSE()
|
||||
ADD_OPTION(WITH_MSI "Build MSI installation package" OFF)
|
||||
ADD_OPTION(WITH_SIGNCODE "digitally sign files" OFF)
|
||||
@ -409,33 +409,68 @@ IF(CLIENT_DOCS)
|
||||
COMPONENT SharedLibraries)
|
||||
ENDIF()
|
||||
|
||||
|
||||
IF(WIN32 AND WITH_MSI AND CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo")
|
||||
ADD_SUBDIRECTORY(win/packaging)
|
||||
ENDIF()
|
||||
MESSAGE1(SYSTEM_PROCESSOR "SYSTEM processor: ${CMAKE_SYSTEM_PROCESSOR}")
|
||||
SET(CPACK_PACKAGE_VENDOR "MariaDB Corporation Ab")
|
||||
SET(CPACK_PACKAGE_DESCRIPTION "MariaDB Connector/C. A library for connecting to MariaDB and MySQL servers")
|
||||
SET(CPACK_PACKAGE_NAME "mariadb_connector_c")
|
||||
SET(CPACK_PACKAGE_NAME "ob_connector_c")
|
||||
STRING(TOLOWER ${CMAKE_SYSTEM_NAME} system_name)
|
||||
SET(CPACK_RESOURCE_FILE_LICENSE "${CC_SOURCE_DIR}/COPYING.LIB")
|
||||
SET(CPACK_PACKAGE_DESCRIPTION_FILE "${CC_SOURCE_DIR}/README")
|
||||
INCLUDE(cmake/ConnectorName.cmake)
|
||||
IF(NOT PACKAGE_STATUS_SUFFIX)
|
||||
SET(CPACK_SOURCE_PACKAGE_FILE_NAME "mariadb-connector-c-${CPACK_PACKAGE_VERSION}-src")
|
||||
IF(PACKAGE_PLATFORM_SUFFIX)
|
||||
SET(CPACK_PACKAGE_FILE_NAME "mariadb-connector-c-${CPACK_PACKAGE_VERSION}-${PACKAGE_PLATFORM_SUFFIX}")
|
||||
|
||||
IF(NOT WIN32)
|
||||
IF(NOT PACKAGE_STATUS_SUFFIX)
|
||||
SET(CPACK_SOURCE_PACKAGE_FILE_NAME "ob-connector-c-${CPACK_PACKAGE_VERSION}-src")
|
||||
IF(PACKAGE_PLATFORM_SUFFIX)
|
||||
SET(CPACK_PACKAGE_FILE_NAME "ob-connector-c-${CPACK_PACKAGE_VERSION}-${PACKAGE_PLATFORM_SUFFIX}")
|
||||
ELSE()
|
||||
SET(CPACK_PACKAGE_FILE_NAME "ob-connector-c-${CPACK_PACKAGE_VERSION}-${system_name}-${CMAKE_SYSTEM_PROCESSOR}")
|
||||
ENDIF()
|
||||
ELSE()
|
||||
SET(CPACK_PACKAGE_FILE_NAME "mariadb-connector-c-${CPACK_PACKAGE_VERSION}-${system_name}-${CMAKE_SYSTEM_PROCESSOR}")
|
||||
SET(CPACK_SOURCE_PACKAGE_FILE_NAME "ob-connector-c-${CPACK_PACKAGE_VERSION}-${PACKAGE_STATUS_SUFFIX}-src")
|
||||
IF(PACKAGE_PLATFORM_SUFFIX)
|
||||
SET(CPACK_PACKAGE_FILE_NAME "ob-connector-c-${CPACK_PACKAGE_VERSION}-${PACKAGE_STATUS_SUFFIX}-${PACKAGE_PLATFORM_SUFFIX}")
|
||||
ELSE()
|
||||
SET(CPACK_PACKAGE_FILE_NAME "ob-connector-c-${CPACK_PACKAGE_VERSION}-${PACKAGE_STATUS_SUFFIX}-${system_name}-${CMAKE_SYSTEM_PROCESSOR}")
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
ELSE()
|
||||
SET(CPACK_SOURCE_PACKAGE_FILE_NAME "mariadb-connector-c-${CPACK_PACKAGE_VERSION}-${PACKAGE_STATUS_SUFFIX}-src")
|
||||
IF(PACKAGE_PLATFORM_SUFFIX)
|
||||
SET(CPACK_PACKAGE_FILE_NAME "mariadb-connector-c-${CPACK_PACKAGE_VERSION}-${PACKAGE_STATUS_SUFFIX}-${PACKAGE_PLATFORM_SUFFIX}")
|
||||
IF(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
SET(PLATFORM "win64")
|
||||
ELSE()
|
||||
SET(CPACK_PACKAGE_FILE_NAME "mariadb-connector-c-${CPACK_PACKAGE_VERSION}-${PACKAGE_STATUS_SUFFIX}-${system_name}-${CMAKE_SYSTEM_PROCESSOR}")
|
||||
SET(PLATFORM "win32")
|
||||
ENDIF()
|
||||
|
||||
string(TIMESTAMP COMPILE_TIME %Y%m%d%H%M%S)
|
||||
MESSAGE(STATUS ${COMPILE_TIME})
|
||||
|
||||
SET(CPACK_PACKAGE_VERSION_RPM ${CPACK_PACKAGE_VERSION})
|
||||
file(STRINGS ./rpm/libobclient-VER.txt STRLIST LIMIT_COUNT 1)
|
||||
foreach(STR IN LISTS STRLIST)
|
||||
SET(CPACK_PACKAGE_VERSION_RPM ${STR})
|
||||
endforeach(STR)
|
||||
|
||||
IF(NOT PACKAGE_STATUS_SUFFIX)
|
||||
SET(CPACK_SOURCE_PACKAGE_FILE_NAME "ob-connector-c-${CPACK_PACKAGE_VERSION_RPM}-src")
|
||||
IF(PACKAGE_PLATFORM_SUFFIX)
|
||||
SET(CPACK_PACKAGE_FILE_NAME "ob-connector-c-${CPACK_PACKAGE_VERSION_RPM}-${PACKAGE_PLATFORM_SUFFIX}")
|
||||
ELSE()
|
||||
SET(CPACK_PACKAGE_FILE_NAME "ob-connector-c-${CPACK_PACKAGE_VERSION_RPM}-${system_name}-${PLATFORM}-${COMPILE_TIME}")
|
||||
ENDIF()
|
||||
ELSE()
|
||||
SET(CPACK_SOURCE_PACKAGE_FILE_NAME "ob-connector-c-${CPACK_PACKAGE_VERSION_RPM}-${PACKAGE_STATUS_SUFFIX}-src")
|
||||
IF(PACKAGE_PLATFORM_SUFFIX)
|
||||
SET(CPACK_PACKAGE_FILE_NAME "ob-connector-c-${CPACK_PACKAGE_VERSION_RPM}-${PACKAGE_STATUS_SUFFIX}-${PACKAGE_PLATFORM_SUFFIX}")
|
||||
ELSE()
|
||||
SET(CPACK_PACKAGE_FILE_NAME "ob-connector-c-${CPACK_PACKAGE_VERSION_RPM}-${PACKAGE_STATUS_SUFFIX}-${system_name}-${PLATFORM}-${COMPILE_TIME}")
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
|
||||
|
||||
# Build source packages
|
||||
IF(GIT_BUILD_SRCPKG)
|
||||
# get branch name
|
||||
|
||||
4
build.sh
4
build.sh
@ -26,4 +26,8 @@ cmake . \
|
||||
-DDEFAULT_COLLATION=utf8_general_ci \
|
||||
-DWITHOUT_TOKUDB=1
|
||||
|
||||
#-DCMAKE_BUILD_TYPE=DEBUG \
|
||||
#-DCMAKE_C_FLAGS_DEBUG="-g -O0" \
|
||||
#-DCMAKE_CXX_FLAGS_DEBUG="-g -O0" \
|
||||
|
||||
make -j `cat /proc/cpuinfo | grep processor| wc -l`
|
||||
@ -61,12 +61,12 @@ ENDIF()
|
||||
#
|
||||
|
||||
SET(INSTALL_BINDIR_DEFAULT "bin")
|
||||
SET(INSTALL_LIBDIR_DEFAULT "lib/mariadb")
|
||||
SET(INSTALL_LIBDIR_DEFAULT "lib")
|
||||
SET(INSTALL_PCDIR_DEFAULT "lib/pkgconfig")
|
||||
SET(INSTALL_INCLUDEDIR_DEFAULT "include/mariadb")
|
||||
SET(INSTALL_INCLUDEDIR_DEFAULT "include")
|
||||
SET(INSTALL_DOCDIR_DEFAULT "docs")
|
||||
IF(NOT IS_SUBPROJECT)
|
||||
SET(INSTALL_PLUGINDIR_DEFAULT "lib/mariadb/plugin")
|
||||
SET(INSTALL_PLUGINDIR_DEFAULT "lib/plugin")
|
||||
ELSE()
|
||||
ENDIF()
|
||||
SET(LIBMARIADB_STATIC_DEFAULT "obclnt")
|
||||
@ -75,13 +75,13 @@ SET(LIBMARIADB_STATIC_DEFAULT "obclnt")
|
||||
#
|
||||
SET(INSTALL_BINDIR_RPM "bin")
|
||||
IF((CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64" OR CMAKE_SYSTEM_PROCESSOR MATCHES "ppc64" OR CMAKE_SYSTEM_PROCESSOR MATCHES "ppc64le" OR CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64" OR CMAKE_SYSTEM_PROCESSOR MATCHES "s390x") AND CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
SET(INSTALL_LIBDIR_RPM "lib64/mariadb")
|
||||
SET(INSTALL_LIBDIR_RPM "lib64")
|
||||
SET(INSTALL_PCDIR_RPM "lib64/pkgconfig")
|
||||
SET(INSTALL_PLUGINDIR_RPM "lib64/mariadb/plugin")
|
||||
SET(INSTALL_PLUGINDIR_RPM "lib64/plugin")
|
||||
ELSE()
|
||||
SET(INSTALL_LIBDIR_RPM "lib/mariadb")
|
||||
SET(INSTALL_LIBDIR_RPM "lib")
|
||||
SET(INSTALL_PCDIR_RPM "lib/pkgconfig")
|
||||
SET(INSTALL_PLUGINDIR_RPM "lib/mariadb/plugin")
|
||||
SET(INSTALL_PLUGINDIR_RPM "lib/plugin")
|
||||
ENDIF()
|
||||
SET(INSTALL_INCLUDEDIR_RPM "include")
|
||||
SET(INSTALL_DOCDIR_RPM "docs")
|
||||
@ -94,8 +94,8 @@ SET(INSTALL_BINDIR_DEB "bin")
|
||||
SET(INSTALL_LIBDIR_DEB "lib/${CMAKE_LIBRARY_ARCHITECTURE}")
|
||||
SET(INSTALL_PCDIR_DEB "lib/${CMAKE_LIBRARY_ARCHITECTURE}/pkgconfig")
|
||||
SET(INSTALL_PLUGINDIR_DEB "${INSTALL_LIBDIR_DEB}/libmariadb${CPACK_PACKAGE_VERSION_MAJOR}/plugin")
|
||||
SET(INSTALL_INCLUDEDIR_DEB "include/mariadb")
|
||||
SET(LIBMARIADB_STATIC_DEB "mariadb")
|
||||
SET(INSTALL_INCLUDEDIR_DEB "include")
|
||||
SET(LIBMARIADB_STATIC_DEB "obclnt")
|
||||
|
||||
IF(INSTALL_LAYOUT MATCHES "DEB")
|
||||
SET(INSTALL_PLUGINDIR_CLIENT ${INSTALL_PLUGINDIR_DEB})
|
||||
|
||||
@ -5,9 +5,23 @@ SET(MARIADB_CLIENT_INCLUDES ${CC_SOURCE_DIR}/include/mariadb_com.h
|
||||
${CC_SOURCE_DIR}/include/ma_tls.h
|
||||
${CC_BINARY_DIR}/include/mariadb_version.h
|
||||
${CC_SOURCE_DIR}/include/ma_list.h
|
||||
${CC_SOURCE_DIR}/include/ma_hash.h
|
||||
${CC_SOURCE_DIR}/include/ma_global.h
|
||||
${CC_SOURCE_DIR}/include/ma_string.h
|
||||
${CC_SOURCE_DIR}/include/ma_config.h
|
||||
${CC_SOURCE_DIR}/include/ma_sys.h
|
||||
${CC_SOURCE_DIR}/include/errmsg.h
|
||||
${CC_SOURCE_DIR}/include/mariadb_dyncol.h
|
||||
${CC_SOURCE_DIR}/include/mariadb_ctype.h
|
||||
${CC_SOURCE_DIR}/include/ob_oralce_format_models.h
|
||||
${CC_SOURCE_DIR}/include/ob_complex.h
|
||||
${CC_SOURCE_DIR}/include/ob_thread.h
|
||||
${CC_SOURCE_DIR}/include/ob_rwlock.h
|
||||
${CC_SOURCE_DIR}/include/ob_cond.h
|
||||
${CC_SOURCE_DIR}/include/ob_thread_key.h
|
||||
${CC_SOURCE_DIR}/include/ob_protocol20.h
|
||||
${CC_SOURCE_DIR}/include/ob_object.h
|
||||
${CC_SOURCE_DIR}/include/ob_full_link_trace.h
|
||||
${CC_SOURCE_DIR}/include/mariadb_rpl.h
|
||||
)
|
||||
IF(NOT IS_SUBPROJECT)
|
||||
|
||||
@ -64,6 +64,7 @@ extern const char *mariadb_client_errors[]; /* Error messages */
|
||||
#define CR_NET_PACKET_TOO_LARGE 2020
|
||||
#define CR_SSL_CONNECTION_ERROR 2026
|
||||
#define CR_MALFORMED_PACKET 2027
|
||||
#define CR_NULL_POINTER 2029
|
||||
#define CR_NO_PREPARE_STMT 2030
|
||||
#define CR_PARAMS_NOT_BOUND 2031
|
||||
#define CR_INVALID_PARAMETER_NO 2034
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/* Copyright (C) 2013 by MontyProgram AB
|
||||
|
||||
Copyright (c) 2021 OceanBase.
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
@ -54,7 +54,7 @@ struct st_mysql_options_extension {
|
||||
char *ssl_crlpath;
|
||||
char *server_public_key_path;
|
||||
struct mysql_async_context *async_context;
|
||||
HASH connect_attrs;
|
||||
OB_HASH connect_attrs;
|
||||
size_t connect_attrs_len;
|
||||
void (*report_progress)(const MYSQL *mysql,
|
||||
unsigned int stage,
|
||||
@ -74,7 +74,7 @@ struct st_mysql_options_extension {
|
||||
my_bool read_only;
|
||||
char *connection_handler;
|
||||
my_bool (*set_option)(MYSQL *mysql, const char *config_option, const char *config_value);
|
||||
HASH userdata;
|
||||
OB_HASH userdata;
|
||||
char *server_public_key;
|
||||
char *proxy_header;
|
||||
size_t proxy_header_len;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
|
||||
|
||||
Copyright (c) 2021 OceanBase.
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
@ -25,7 +25,12 @@
|
||||
#include <winsock2.h>
|
||||
#include <windows.h>
|
||||
#include <stdlib.h>
|
||||
#ifndef strcasecmp
|
||||
#define strcasecmp _stricmp
|
||||
#endif
|
||||
#ifndef strncasecmp
|
||||
#define strncasecmp _strnicmp
|
||||
#endif
|
||||
#define sleep(x) Sleep(1000*(x))
|
||||
#ifdef _MSC_VER
|
||||
#define inline __inline
|
||||
@ -550,7 +555,7 @@ extern double my_atof(const char*);
|
||||
Max size that must be added to a so that we know Size to make
|
||||
addressable obj.
|
||||
*/
|
||||
typedef long my_ptrdiff_t;
|
||||
typedef long ma_ptrdiff_t;
|
||||
#define MY_ALIGN(A,L) (((A) + (L) - 1) & ~((L) - 1))
|
||||
#define ALIGN_SIZE(A) MY_ALIGN((A),sizeof(double))
|
||||
/* Size to make addressable obj. */
|
||||
@ -558,7 +563,7 @@ typedef long my_ptrdiff_t;
|
||||
/* Offset of filed f in structure t */
|
||||
#define OFFSET(t, f) ((size_t)(char *)&((t *)0)->f)
|
||||
#define ADD_TO_PTR(ptr,size,type) (type) ((unsigned char*) (ptr)+size)
|
||||
#define PTR_BYTE_DIFF(A,B) (my_ptrdiff_t) ((unsigned char*) (A) - (unsigned char*) (B))
|
||||
#define PTR_BYTE_DIFF(A,B) (ma_ptrdiff_t) ((unsigned char*) (A) - (unsigned char*) (B))
|
||||
|
||||
#define NullS (char *) 0
|
||||
/* Nowadays we do not support MessyDos */
|
||||
@ -682,8 +687,16 @@ typedef short int15; /* Most effective integer 0 <= x <= 32767 */
|
||||
typedef char *my_string; /* String of characters */
|
||||
typedef unsigned long size_s; /* Size of strings (In string-funcs) */
|
||||
typedef int myf; /* Type of MyFlags in my_funcs */
|
||||
typedef char my_bool; /* Small bool */
|
||||
#ifndef TYPEDEF_MY_BOOL
|
||||
#define TYPEDEF_MY_BOOL
|
||||
typedef char my_bool; /* Small bool */
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef TYPEDEF_MY_ULONGLONG
|
||||
#define TYPEDEF_MY_ULONGLONG
|
||||
typedef unsigned long long my_ulonglong;
|
||||
#endif
|
||||
#if !defined(bool) && !defined(bool_defined) && (!defined(HAVE_BOOL) || !defined(__cplusplus))
|
||||
typedef char bool; /* Ordinary boolean values 0 1 */
|
||||
#endif
|
||||
@ -1091,4 +1104,62 @@ typedef unsigned long long intptr;
|
||||
#define RTLD_NOW 1
|
||||
#endif
|
||||
|
||||
#ifndef OB_MACRO
|
||||
#define OB_MACRO
|
||||
|
||||
#define OB_SUCCESS 0
|
||||
#define OB_ERROR -4000
|
||||
#define UNUSED(x) (void)x
|
||||
|
||||
#define OB_LIKELY(x) __builtin_expect(!!(x),1)
|
||||
#define OB_UNLIKELY(x) __builtin_expect(!!(x),0)
|
||||
#define OB_ISNULL(statement) (OB_UNLIKELY(NULL == (statement)))
|
||||
#define OB_NOT_NULL(statement) (OB_LIKELY(NULL != (statement)))
|
||||
|
||||
|
||||
#define OB_SUCC(statement) (OB_LIKELY(OB_SUCCESS == (ret = (statement))))
|
||||
#define OB_FAIL(statement) (OB_UNLIKELY(OB_SUCCESS != (ret = (statement))))
|
||||
#define OB_INLINE inline __attribute__((always_inline))
|
||||
|
||||
#define OB_SIZE_OVERFLOW -4019
|
||||
#define OB_DESERIALIZE_ERROR -4034
|
||||
|
||||
#define OB_MAX_V1B (__UINT64_C(1) << 7) - 1
|
||||
#define OB_MAX_V2B (__UINT64_C(1) << 14) - 1
|
||||
#define OB_MAX_V3B (__UINT64_C(1) << 21) - 1
|
||||
#define OB_MAX_V4B (__UINT64_C(1) << 28) - 1
|
||||
#define OB_MAX_V5B (__UINT64_C(1) << 35) - 1
|
||||
#define OB_MAX_V6B (__UINT64_C(1) << 42) - 1
|
||||
#define OB_MAX_V7B (__UINT64_C(1) << 49) - 1
|
||||
#define OB_MAX_V8B (__UINT64_C(1) << 56) - 1
|
||||
#define OB_MAX_V9B (__UINT64_C(1) << 63) - 1
|
||||
|
||||
|
||||
#define OB_MAX_1B (__UINT64_C(1) << 8) - 1
|
||||
#define OB_MAX_2B (__UINT64_C(1) << 16) - 1
|
||||
#define OB_MAX_3B (__UINT64_C(1) << 24) - 1
|
||||
#define OB_MAX_4B (__UINT64_C(1) << 32) - 1
|
||||
#define OB_MAX_5B (__UINT64_C(1) << 40) - 1
|
||||
#define OB_MAX_6B (__UINT64_C(1) << 48) - 1
|
||||
#define OB_MAX_7B (__UINT64_C(1) << 56) - 1
|
||||
#define OB_MAX_8B UINT64_MAX;
|
||||
|
||||
|
||||
|
||||
#define OB_MAX_INT_1B (__UINT64_C(23))
|
||||
#define OB_MAX_INT_2B (__UINT64_C(1) << 8) - 1
|
||||
#define OB_MAX_INT_3B (__UINT64_C(1) << 16) - 1
|
||||
#define OB_MAX_INT_4B (__UINT64_C(1) << 24) - 1
|
||||
#define OB_MAX_INT_5B (__UINT64_C(1) << 32) - 1
|
||||
#define OB_MAX_INT_7B (__UINT64_C(1) << 48) - 1
|
||||
#define OB_MAX_INT_9B UINT64_MAX
|
||||
|
||||
|
||||
#define OB_MAX_1B_STR_LEN (__INT64_C(55))
|
||||
#define OB_MAX_2B_STR_LEN (__INT64_C(1) << 8) - 1
|
||||
#define OB_MAX_3B_STR_LEN (__INT64_C(1) << 16) - 1
|
||||
#define OB_MAX_4B_STR_LEN (__INT64_C(1) << 24) - 1
|
||||
#define OB_MAX_5B_STR_LEN (__INT64_C(1) << 32) - 1
|
||||
|
||||
#endif
|
||||
#endif /* _global_h */
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/************************************************************************************
|
||||
Copyright (C) 2000, 2012 MySQL AB & MySQL Finland AB & TCX DataKonsult AB,
|
||||
Monty Program AB
|
||||
|
||||
Copyright (c) 2021 OceanBase.
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
@ -26,19 +26,20 @@
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "ma_global.h"
|
||||
#include "ma_sys.h"
|
||||
typedef uchar *(*hash_get_key)(const uchar *,uint*,my_bool);
|
||||
typedef void (*hash_free_key)(void *);
|
||||
|
||||
/* flags for hash_init */
|
||||
#define HASH_CASE_INSENSITIVE 1
|
||||
|
||||
typedef struct st_hash_info {
|
||||
typedef struct ob_st_hash_info {
|
||||
uint next; /* index to next key */
|
||||
uchar *data; /* data for current entry */
|
||||
} HASH_LINK;
|
||||
} OB_HASH_LINK;
|
||||
|
||||
typedef struct st_hash {
|
||||
struct ob_st_hash {
|
||||
uint key_offset,key_length; /* Length of key if const length */
|
||||
uint records,blength,current_record;
|
||||
uint flags;
|
||||
@ -46,20 +47,23 @@ typedef struct st_hash {
|
||||
hash_get_key get_key;
|
||||
void (*free)(void *);
|
||||
uint (*calc_hashnr)(const uchar *key,uint length);
|
||||
} HASH;
|
||||
|
||||
} ;
|
||||
#ifndef TYPE_DEFINE_OB_HASH
|
||||
#define TYPE_DEFINE_OB_HASH
|
||||
typedef struct ob_st_hash OB_HASH;
|
||||
#endif
|
||||
#define hash_init(A,B,C,D,E,F,G) _hash_init(A,B,C,D,E,F,G CALLER_INFO)
|
||||
my_bool _hash_init(HASH *hash,uint default_array_elements, uint key_offset,
|
||||
my_bool _hash_init(OB_HASH *hash,uint default_array_elements, uint key_offset,
|
||||
uint key_length, hash_get_key get_key,
|
||||
void (*free_element)(void*), uint flags CALLER_INFO_PROTO);
|
||||
void hash_free(HASH *tree);
|
||||
uchar *hash_element(HASH *hash,uint idx);
|
||||
void * hash_search(HASH *info,const uchar *key,uint length);
|
||||
void * hash_next(HASH *info,const uchar *key,uint length);
|
||||
my_bool hash_insert(HASH *info,const uchar *data);
|
||||
my_bool hash_delete(HASH *hash,uchar *record);
|
||||
my_bool hash_update(HASH *hash,uchar *record,uchar *old_key,uint old_key_length);
|
||||
my_bool hash_check(HASH *hash); /* Only in debug library */
|
||||
void (*free_element)(void*), uint flags);
|
||||
void hash_free(OB_HASH *tree);
|
||||
uchar *hash_element(OB_HASH *hash,uint idx);
|
||||
void * hash_search(OB_HASH *info,const uchar *key,uint length);
|
||||
void * hash_next(OB_HASH *info,const uchar *key,uint length);
|
||||
my_bool hash_insert(OB_HASH *info,const uchar *data);
|
||||
my_bool hash_delete(OB_HASH *hash,uchar *record);
|
||||
my_bool hash_update(OB_HASH *hash,uchar *record,uchar *old_key,uint old_key_length);
|
||||
my_bool hash_check(OB_HASH *hash); /* Only in debug library */
|
||||
|
||||
#define hash_clear(H) memset((char*) (H), 0,sizeof(*(H)))
|
||||
#define hash_inited(H) ((H)->array.buffer != 0)
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
|
||||
2012 by MontyProgram AB
|
||||
|
||||
Copyright (c) 2021 OceanBase.
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
@ -22,7 +22,7 @@
|
||||
#define _ma_string_h_
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "ma_global.h"
|
||||
typedef enum {
|
||||
MY_GCVT_ARG_FLOAT,
|
||||
MY_GCVT_ARG_DOUBLE
|
||||
|
||||
@ -28,7 +28,6 @@
|
||||
#ifndef _mysql_com_h
|
||||
#define _mysql_com_h
|
||||
|
||||
|
||||
#define NAME_CHAR_LEN 64
|
||||
#define NAME_LEN 256 /* Field/table name length */
|
||||
#define HOSTNAME_LENGTH 60
|
||||
@ -93,11 +92,29 @@ enum enum_server_command
|
||||
COM_DAEMON= 29,
|
||||
COM_UNSUPPORTED= 30,
|
||||
COM_RESET_CONNECTION = 31,
|
||||
COM_STMT_PREPARE_EXECUTE = 0xa1,
|
||||
COM_STMT_SEND_PIECE_DATA = 0xa2,
|
||||
COM_STMT_GET_PIECE_DATA = 0xa3,
|
||||
COM_STMT_BULK_EXECUTE = 250,
|
||||
COM_RESERVED_1 = 254, /* former COM_MULTI, now removed */
|
||||
COM_END
|
||||
};
|
||||
|
||||
enum enum_nls_time_type
|
||||
{
|
||||
NLS_DATE_FORMAT,
|
||||
NLS_TIMESTAMP_FORMAT,
|
||||
NLS_TIMESTAMP_TZ_FORMAT,
|
||||
NLS_TIME_MAX
|
||||
};
|
||||
|
||||
enum enum_prepare_execute_extend_flag
|
||||
{
|
||||
PRE_EXE_EXTEND_FLAG_RETURNING= 1,
|
||||
PRE_EXE_EXTEND_FLAG_ADD_USER_FIELD= 1<<1,
|
||||
PRE_EXE_EXTEND_FLAG_PLOUT= 1<<2,
|
||||
PRE_EXE_EXTEND_END=1<<31
|
||||
};
|
||||
|
||||
#define NOT_NULL_FLAG 1 /* Field can't be NULL */
|
||||
#define PRI_KEY_FLAG 2 /* Field is part of a primary key */
|
||||
@ -162,10 +179,15 @@ enum enum_server_command
|
||||
#define CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS (1UL << 22)
|
||||
#define CLIENT_SESSION_TRACKING (1UL << 23)
|
||||
|
||||
/* Client no longer needs EOF packet */
|
||||
#define CLIENT_DEPRECATE_EOF (1UL << 24)
|
||||
|
||||
#define CLIENT_SUPPORT_ORACLE_MODE (1UL << 27)
|
||||
#define CLIENT_RETURN_HIDDEN_ROWID (1UL << 28)
|
||||
|
||||
#define CLIENT_PROGRESS (1UL << 29) /* client supports progress indicator */
|
||||
#define CLIENT_USE_LOB_LOCATOR (1UL << 29)
|
||||
// #define CLIENT_PROGRESS (1UL << 29) /* client supports progress indicator */
|
||||
#define CLIENT_PROGRESS (1UL << 32) /* client supports progress indicator */
|
||||
#define CLIENT_PROGRESS_OBSOLETE CLIENT_PROGRESS
|
||||
#define CLIENT_SSL_VERIFY_SERVER_CERT (1UL << 30)
|
||||
#define CLIENT_REMEMBER_OPTIONS (1UL << 31)
|
||||
@ -273,7 +295,7 @@ typedef struct st_ma_pvio MARIADB_PVIO;
|
||||
#define MAX_BIGINT_WIDTH 20
|
||||
|
||||
struct st_ma_connection_plugin;
|
||||
|
||||
struct st_ob20protocol;
|
||||
|
||||
typedef struct st_net {
|
||||
MARIADB_PVIO *pvio;
|
||||
@ -292,7 +314,7 @@ typedef struct st_net {
|
||||
char unused_1;
|
||||
my_bool unused_2;
|
||||
my_bool compress;
|
||||
my_bool unused_3;
|
||||
my_bool use_ob20protocol;
|
||||
void *unused_4;
|
||||
unsigned int last_errno;
|
||||
unsigned char error;
|
||||
@ -301,6 +323,7 @@ typedef struct st_net {
|
||||
char last_error[MYSQL_ERRMSG_SIZE];
|
||||
char sqlstate[SQLSTATE_LENGTH+1];
|
||||
struct st_mariadb_net_extension *extension;
|
||||
struct st_ob20protocol *ob20protocol;
|
||||
} NET;
|
||||
|
||||
#define packet_error ((unsigned int) -1)
|
||||
@ -312,6 +335,9 @@ enum enum_mysql_set_option
|
||||
MYSQL_OPTION_MULTI_STATEMENTS_OFF
|
||||
};
|
||||
|
||||
#define CURSOR_TYPE_ARRAY_BIND 8
|
||||
#define CURSOR_TYPE_SAVE_EXCEPTION 16
|
||||
|
||||
enum enum_session_state_type
|
||||
{
|
||||
SESSION_TRACK_SYSTEM_VARIABLES= 0,
|
||||
@ -334,6 +360,70 @@ enum enum_session_state_type
|
||||
TODO: Remove this after server fixes */
|
||||
#define SESSION_TRACK_TRANSACTION_TYPE SESSION_TRACK_TRANSACTION_STATE
|
||||
|
||||
// for obproxy and observer compatibility
|
||||
enum ObCapabilityFlagShift
|
||||
{
|
||||
OB_CAP_PARTITION_TABLE_SHIFT = 0,
|
||||
OB_CAP_CHANGE_USER_SHIFT,
|
||||
OB_CAP_READ_WEAK_SHIFT,
|
||||
OB_CAP_CHECKSUM_SHIFT,
|
||||
OB_CAP_SAFE_WEAK_READ_SHIFT,
|
||||
OB_CAP_PRIORITY_HIT_SHIFT,
|
||||
OB_CAP_CHECKSUM_SWITCH_SHIFT,
|
||||
OB_CAP_OCJ_ENABLE_EXTRA_OK_PACKET_SHIFT,
|
||||
OB_CAP_OB_PROTOCOL_V2_SHIFT,
|
||||
OB_CAP_EXTRA_OK_PACKET_FOR_STATISTICS_SHIFT,
|
||||
OB_CAP_ABUNDANT_FEEDBACK,
|
||||
OB_CAP_PL_ROUTE_SHIFT,
|
||||
OB_CAP_PROXY_REROUTE_SHIFT,
|
||||
OB_CAP_PROXY_SESSION_SYNC_SHIFT,
|
||||
OB_CAP_FULL_LINK_TRACE_SHIFT,
|
||||
OB_CAP_PROXY_NEW_EXTRA_INFO_SHIFT
|
||||
};
|
||||
|
||||
#define OB_TEST_CAPABILITY(cap, tg_cap) (((cap) & (tg_cap)) == (tg_cap))
|
||||
#define OB_CAP_GET_TYPE(i) (1LL << i)
|
||||
#define OB_CAP_PARTITION_TABLE OB_CAP_GET_TYPE(OB_CAP_PARTITION_TABLE_SHIFT)
|
||||
#define OB_CAP_CHANGE_USER OB_CAP_GET_TYPE(OB_CAP_CHANGE_USER_SHIFT)
|
||||
#define OB_CAP_READ_WEAK OB_CAP_GET_TYPE(OB_CAP_READ_WEAK_SHIFT)
|
||||
#define OB_CAP_CHECKSUM OB_CAP_GET_TYPE(OB_CAP_CHECKSUM_SHIFT)
|
||||
#define OB_CAP_SAFE_WEAK_READ OB_CAP_GET_TYPE(OB_CAP_SAFE_WEAK_READ_SHIFT)
|
||||
#define OB_CAP_PRIORITY_HIT OB_CAP_GET_TYPE(OB_CAP_PRIORITY_HIT_SHIFT)
|
||||
#define OB_CAP_CHECKSUM_SWITCH OB_CAP_GET_TYPE(OB_CAP_CHECKSUM_SWITCH_SHIFT)
|
||||
#define OB_CAP_OB_PROTOCOL_V2 OB_CAP_GET_TYPE(OB_CAP_OB_PROTOCOL_V2_SHIFT)
|
||||
#define OB_CAP_EXTRA_OK_PACKET_FOR_STATISTICS OB_CAP_GET_TYPE(OB_CAP_EXTRA_OK_PACKET_FOR_STATISTICS_SHIFT)
|
||||
#define OB_CAP_PL_ROUTE OB_CAP_GET_TYPE(OB_CAP_PL_ROUTE_SHIFT)
|
||||
#define OB_CAP_PROXY_REROUTE OB_CAP_GET_TYPE(OB_CAP_PROXY_REROUTE_SHIFT)
|
||||
#define OB_CAP_PROXY_SESSION_SYNC OB_CAP_GET_TYPE(OB_CAP_PROXY_SESSION_SYNC_SHIFT)
|
||||
#define OB_CAP_FULL_LINK_TRACE OB_CAP_GET_TYPE(OB_CAP_FULL_LINK_TRACE_SHIFT)
|
||||
#define OB_CAP_PROXY_NEW_EXTRA_INFO OB_CAP_GET_TYPE(OB_CAP_PROXY_NEW_EXTRA_INFO_SHIFT)
|
||||
|
||||
static const unsigned long OBPROXY_DEFAULT_CAPABILITY_FLAG =
|
||||
(OB_CAP_PARTITION_TABLE
|
||||
| OB_CAP_CHANGE_USER
|
||||
| OB_CAP_READ_WEAK
|
||||
| OB_CAP_CHECKSUM
|
||||
| OB_CAP_SAFE_WEAK_READ
|
||||
| OB_CAP_CHECKSUM_SWITCH
|
||||
| OB_CAP_OB_PROTOCOL_V2
|
||||
| OB_CAP_EXTRA_OK_PACKET_FOR_STATISTICS
|
||||
| OB_CAP_PL_ROUTE
|
||||
| OB_CAP_PROXY_REROUTE
|
||||
| OB_CAP_FULL_LINK_TRACE
|
||||
| OB_CAP_PROXY_NEW_EXTRA_INFO);
|
||||
|
||||
static const long OB_MAX_UINT32_BUF_LEN = 11; // string length of max uint32_t(2**32 - 1)
|
||||
static const long OB_MAX_UINT64_BUF_LEN = 22; // string length of max uint64_t(2**64 - 1)
|
||||
static const long OB_MAX_VERSION_BUF_LEN = 22; // string length of (xxx.xxx.xxx.xxx.xxx)
|
||||
static const long OB_MAX_IP_BUF_LEN = 20; // string length of (xxx.xxx.xxx.xxx.xxx)
|
||||
|
||||
static const char *const OB_MYSQL_CAPABILITY_FLAG = "__proxy_capability_flag";
|
||||
static const char *const OB_MYSQL_CLIENT_MODE = "__mysql_client_type";
|
||||
static const char *const OB_MYSQL_CLIENT_OBPROXY_MODE = "__ob_proxy";
|
||||
static const char *const OB_MYSQL_CONNECTION_ID = "__connection_id";
|
||||
static const char *const OB_MYSQL_PROXY_CONNECTION_ID = "__proxy_connection_id";
|
||||
static const char *const OB_MYSQL_GLOBAL_VARS_VERSION = "__global_vars_version";
|
||||
|
||||
typedef enum enum_field_types { MYSQL_TYPE_DECIMAL, MYSQL_TYPE_TINY,
|
||||
MYSQL_TYPE_SHORT, MYSQL_TYPE_LONG,
|
||||
MYSQL_TYPE_FLOAT, MYSQL_TYPE_DOUBLE,
|
||||
@ -356,6 +446,7 @@ typedef enum enum_field_types { MYSQL_TYPE_DECIMAL, MYSQL_TYPE_TINY,
|
||||
MYSQL_TYPE_ARRAY = 161, //0xa1
|
||||
MYSQL_TYPE_STRUCT = 162, //0xa2
|
||||
MYSQL_TYPE_CURSOR = 163, //0xa3
|
||||
MYSQL_TYPE_PLARRAY = 164, //0xa4
|
||||
MYSQL_TYPE_OB_TIMESTAMP_WITH_TIME_ZONE = 200,
|
||||
MYSQL_TYPE_OB_TIMESTAMP_WITH_LOCAL_TIME_ZONE = 201,
|
||||
MYSQL_TYPE_OB_TIMESTAMP_NANO = 202,
|
||||
@ -464,6 +555,12 @@ typedef struct st_udf_init
|
||||
/* Constants when using compression */
|
||||
#define NET_HEADER_SIZE 4 /* standard header size */
|
||||
#define COMP_HEADER_SIZE 3 /* compression header extra size */
|
||||
#define PIECE_HEADER_SIZE 16 /* COM_STMT_SEND_PIECE_DATA header size */
|
||||
#define OB20_HEADER_SIZE 24 /* ob 20 protocol header size */
|
||||
#define OB20_TAILER_SIZE 4 /* ob 20 protocol tailer size */
|
||||
#define OB20_PROTOCOL_MAGIC_NUM 0x20AB /* ob 20 protocol header magic num */
|
||||
#define OB20_PROTOCOL_VERSION_VALUE 20 /* ob 20 protocol header version */
|
||||
#define OB20_EXTRAINFO_LENGTH_SIZE 4 /* ob 20 protocol extra_info size */
|
||||
|
||||
/* Prototypes to password functions */
|
||||
#define native_password_plugin_name "mysql_native_password"
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/************************************************************************
|
||||
|
||||
Copyright (c) 2021 OceanBase.
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
@ -22,6 +22,11 @@
|
||||
*************************************************************************/
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
typedef unsigned int uint;
|
||||
typedef unsigned long ulong;
|
||||
#endif
|
||||
|
||||
#define MYSQL_NO_DATA 100
|
||||
#define MYSQL_DATA_TRUNCATED 101
|
||||
#define MYSQL_DEFAULT_PREFETCH_ROWS (unsigned long) 1
|
||||
@ -55,7 +60,6 @@ do { \
|
||||
#define MYSQL_PS_SKIP_RESULT_STR -2
|
||||
#define STMT_ID_LENGTH 4
|
||||
|
||||
|
||||
typedef struct st_mysql_stmt MYSQL_STMT;
|
||||
|
||||
typedef MYSQL_RES* (*mysql_stmt_use_or_store_func)(MYSQL_STMT *);
|
||||
@ -65,6 +69,7 @@ enum enum_stmt_attr_type
|
||||
STMT_ATTR_UPDATE_MAX_LENGTH,
|
||||
STMT_ATTR_CURSOR_TYPE,
|
||||
STMT_ATTR_PREFETCH_ROWS,
|
||||
STMT_ATTR_ARRAY_BIND,
|
||||
|
||||
/* MariaDB only */
|
||||
STMT_ATTR_PREBIND_PARAMS=200,
|
||||
@ -84,6 +89,9 @@ enum enum_cursor_type
|
||||
CURSOR_TYPE_SCROLLABLE= 4
|
||||
};
|
||||
|
||||
#define CURSOR_TYPE_ARRAY_BIND 8
|
||||
#define CURSOR_TYPE_SAVE_EXCEPTION 16
|
||||
|
||||
enum enum_indicator_type
|
||||
{
|
||||
STMT_INDICATOR_NTS=-1,
|
||||
@ -94,6 +102,12 @@ enum enum_indicator_type
|
||||
STMT_INDICATOR_IGNORE_ROW=4
|
||||
};
|
||||
|
||||
enum enum_prepare_execute_request_ext_flag
|
||||
{
|
||||
STMT_PRE_EXE_EFLAG_DEFAULT=0,
|
||||
STMT_PRE_EXE_EFLAG_NEED_ARRAYBIND_RES= 2 //need resultset for arraybinding for all types(dml/pl etc.)
|
||||
};
|
||||
|
||||
/*
|
||||
bulk PS flags
|
||||
*/
|
||||
@ -137,8 +151,14 @@ typedef struct st_mysql_bind
|
||||
my_bool error_value; /* used if error is 0 */
|
||||
my_bool is_unsigned; /* set if integer type is unsigned */
|
||||
my_bool long_data_used; /* If used with mysql_send_long_data */
|
||||
my_bool piece_data_used; /* If used with mysql_send_piece_data */
|
||||
my_bool is_null_value; /* Used if is_null is 0 */
|
||||
my_bool is_handle_returning_into; /* is handling the result of returning into*/
|
||||
my_bool no_need_to_parser_result; /* skip to parse the column for this result */
|
||||
unsigned long last_offset;
|
||||
void *extension;
|
||||
MYSQL *mysql;
|
||||
MA_MEM_ROOT bind_alloc; /* use for complex type */
|
||||
} MYSQL_BIND;
|
||||
|
||||
//add for oboracle complex type
|
||||
@ -173,6 +193,14 @@ typedef struct st_mysql_complex_bind_object
|
||||
COMPLEX_OBJECT_HEADER;
|
||||
} MYSQL_COMPLEX_BIND_OBJECT;
|
||||
|
||||
// add for support send pl array maxrarr_len
|
||||
typedef struct st_mysql_complex_bind_plarray
|
||||
{
|
||||
COMPLEX_OBJECT_HEADER;
|
||||
unsigned long maxrarr_len;
|
||||
enum enum_field_types elem_type;
|
||||
} MYSQL_COMPLEX_BIND_PLARRAY;
|
||||
|
||||
typedef struct st_mysql_complex_bind_object MYSQL_COMPLEX_BIND_ARRAY;
|
||||
//end add for oboracle complex type
|
||||
#define MAX_OB_LOB_LOCATOR_HEADER_LENGTH 40
|
||||
@ -269,6 +297,7 @@ struct st_mysql_stmt
|
||||
unsigned char send_types_to_server;
|
||||
MYSQL_BIND *params;
|
||||
MYSQL_BIND *bind;
|
||||
MYSQL_FIELD *param_fields; /* result set metadata */
|
||||
MYSQL_DATA result; /* we don't use mysqlnd's result set logic */
|
||||
MYSQL_ROWS *result_cursor;
|
||||
my_bool bind_result_done;
|
||||
@ -297,7 +326,131 @@ struct st_mysql_stmt
|
||||
void *user_data;
|
||||
ps_result_callback result_callback;
|
||||
ps_param_callback param_callback;
|
||||
/*add for support prepare_execute protocol*/
|
||||
unsigned int bind_size;
|
||||
unsigned int iteration_count;
|
||||
unsigned int execute_mode;
|
||||
unsigned int check_sum;
|
||||
my_bool use_prepare_execute;
|
||||
/*
|
||||
* Added for RETURNING...INTO to handle the resultset
|
||||
**/
|
||||
my_bool is_handle_returning_into; /* is handling the result of returning into */
|
||||
my_bool has_added_user_fields; /* will be set if user's field info has added */
|
||||
my_bool is_pl_out_resultset; /* will be set for resultset of PL out parameters. OBServer will be set since 3.2.2 */
|
||||
/*end add for support prepare_execute protocol*/
|
||||
unsigned short orientation; /* i.e. OCI_FETCH_ABSOLUTE - Fetches the row number (specified by fetch_offset parameter) in the result set using absolute positioning.*/
|
||||
int fetch_offset; /* The offset to be used with the orientation parameter for changing the current row position */
|
||||
unsigned long ext_flag; /* prepare_execute extend flag which need to be send to OBServer */
|
||||
MA_MEM_ROOT param_fields_mem_root; /* param root allocations */
|
||||
};
|
||||
/*add for support send PLArray maxrarr_len*/
|
||||
enum enum_mysql_send_plarray_maxrarrlen_flag
|
||||
{
|
||||
SEND_PLARRAY_MAXRARRLEN_FORCE_CLOSE = 0,
|
||||
SEND_PLARRAY_MAXRARRLEN_AUTO_OPEN,
|
||||
SEND_PLARRAY_MAXRARRLEN_FORCE_OPEN,
|
||||
SEND_PLARRAY_MAXRARRLEN_FLAG_MAX,
|
||||
};
|
||||
my_bool determine_send_plarray_maxrarr_len(MYSQL *mysql);
|
||||
my_bool get_support_send_plarray_maxrarr_len(MYSQL *mysql);
|
||||
/*end for support send PLArray maxrarr_len*/
|
||||
|
||||
/*add for support plarray bindbyname */
|
||||
enum enum_mysql_plarray_bindbyname
|
||||
{
|
||||
PLARRAY_BINDBYNAME_FORCE_CLOSE = 0,
|
||||
PLARRAY_BINDBYNAME_AUTO_OPEN,
|
||||
PLARRAY_BINDBYNAME_FORCE_OPEN,
|
||||
PLARRAY_BINDBYNAME_FLAG_MAX,
|
||||
};
|
||||
my_bool determine_plarray_bindbyname(MYSQL *mysql);
|
||||
my_bool get_support_plarray_bindbyname(MYSQL *mysql);
|
||||
/*end for support plarray bindbyname */
|
||||
|
||||
/*add for support protocol ob20*/
|
||||
enum enum_ob20_protocol
|
||||
{
|
||||
PROTOCOL_OB20_FORCE_CLOSE = 0,
|
||||
PROTOCOL_OB20_AUTO_OPEN,
|
||||
PROTOCOL_OB20_FORCE_OPEN,
|
||||
PROTOCOL_OB20_FLAY_MAX
|
||||
};
|
||||
my_bool determine_protocol_ob20(MYSQL *mysql);
|
||||
my_bool get_use_protocol_ob20(MYSQL *mysql);
|
||||
|
||||
enum enum_full_link_trace
|
||||
{
|
||||
PROTOCOL_FLT_FORCE_CLOSE = 0,
|
||||
PROTOCOL_FLT_AUTO_OPEN,
|
||||
PROTOCOL_FLT_FORCE_OPEN,
|
||||
PROTOCOL_FLT_FLAY_MAX
|
||||
};
|
||||
my_bool determine_full_link_trace(MYSQL *mysql);
|
||||
my_bool get_use_full_link_trace(MYSQL *mysql);
|
||||
|
||||
uint32_t ob_crc32(uint64_t crc, const char *buf, int64_t len);
|
||||
uint64_t ob_crc64(uint64_t crc, const char *buf, int64_t len);
|
||||
/*end for support protocol ob20*/
|
||||
|
||||
/* add for support bindbyname for plarray */
|
||||
struct prepare_extend_args_t
|
||||
{
|
||||
unsigned int params_count; // pass params_ount from caller
|
||||
};
|
||||
typedef struct prepare_extend_args_t PREPARE_EXTEND_ARGS;
|
||||
// todo: add a switch to accept args
|
||||
/* end for support bindbyname for plarray */
|
||||
|
||||
enum enum_mysql_prepare_execute_flag
|
||||
{
|
||||
PREPARE_EXECUTE_FORCE_CLOSE = 0,
|
||||
PREPARE_EXECUTE_AUTO_OPEN,
|
||||
PREPARE_EXECUTE_FORCE_OPEN,
|
||||
PREPARE_EXECUTE_FLAG_MAX
|
||||
};
|
||||
/*add for support prepare_execute protocol*/
|
||||
my_bool determine_use_prepare_execute(MYSQL *mysql);
|
||||
my_bool get_support_send_fetch_flag(MYSQL *mysql);
|
||||
my_bool get_use_prepare_execute(MYSQL* msyql);
|
||||
my_bool get_use_preapre_execute(MYSQL* msyql);
|
||||
/*end add for support prepare_execute protocol*/
|
||||
/*add for support new prepare_execute mode*/
|
||||
//same value as OCI
|
||||
#define EXECUTE_BATCH_MODE 0x00000001 /* batch the oci stmt for exec */
|
||||
#define EXECUTE_EXACT_FETCH 0x00000002 /* fetch exact rows specified */
|
||||
/* #define 0x00000004 available */
|
||||
#define EXECUTE_STMT_SCROLLABLE_READONLY \
|
||||
0x00000008 /* if result set is scrollable */
|
||||
#define EXECUTE_DESCRIBE_ONLY 0x00000010 /* only describe the statement */
|
||||
#define EXECUTE_COMMIT_ON_SUCCESS 0x00000020 /* commit, if successful exec */
|
||||
#define EXECUTE_NON_BLOCKING 0x00000040 /* non-blocking */
|
||||
#define EXECUTE_BATCH_ERRORS 0x00000080 /* batch errors in array dmls */
|
||||
#define EXECUTE_PARSE_ONLY 0x00000100 /* only parse the statement */
|
||||
#define EXECUTE_EXACT_FETCH_RESERVED_1 0x00000200 /* reserved */
|
||||
/*add for support new prepare_execute mode*/
|
||||
|
||||
/*add for support fetch flag*/
|
||||
#define FETCH_RETURN_EXTRA_OK 0x00000001L
|
||||
#define FETCH_HAS_PIECE_COLUMN 0x00000002L
|
||||
//same as oci fetch orientation
|
||||
#define CURSOR_FETCH_DEFAULT 0x00000000
|
||||
#define CURSOR_FETCH_CURRENT 0x00000001 /* refetching current position */
|
||||
#define CURSOR_FETCH_NEXT 0x00000002 /* next row */
|
||||
#define CURSOR_FETCH_FIRST 0x00000004 /* first row of the result set */
|
||||
#define CURSOR_FETCH_LAST 0x00000008 /* the last row of the result set */
|
||||
#define CURSOR_FETCH_PRIOR 0x00000010 /* previous row relative to current */
|
||||
#define CURSOR_FETCH_ABSOLUTE 0x00000020 /* absolute offset from first */
|
||||
#define CURSOR__FETCH_RELATIVE 0x00000040 /* offset relative to current */
|
||||
#define CURSOR__FETCH_RESERVED_1 0x00000080 /* reserved */
|
||||
#define CURSOR__FETCH_RESERVED_2 0x00000100 /* reserved */
|
||||
#define CURSOR__FETCH_RESERVED_3 0x00000200 /* reserved */
|
||||
#define CURSOR__FETCH_RESERVED_4 0x00000400 /* reserved */
|
||||
#define CURSOR__FETCH_RESERVED_5 0x00000800 /* reserved */
|
||||
#define CURSOR__FETCH_RESERVED_6 0x00001000 /* reserved */
|
||||
/*end add for support fetch flag*/
|
||||
|
||||
#define NEED_DATA_AT_EXEC_FLAG 0x00000001
|
||||
|
||||
typedef void (*ps_field_fetch_func)(MYSQL_BIND *r_param, const MYSQL_FIELD * field, unsigned char **row);
|
||||
typedef struct st_mysql_perm_bind {
|
||||
@ -307,7 +460,7 @@ typedef struct st_mysql_perm_bind {
|
||||
unsigned long max_len;
|
||||
} MYSQL_PS_CONVERSION;
|
||||
|
||||
extern MYSQL_PS_CONVERSION mysql_ps_fetch_functions[MYSQL_TYPE_GEOMETRY + 1];
|
||||
extern MYSQL_PS_CONVERSION mysql_ps_fetch_functions[MYSQL_TYPE_GEOMETRY + 2];
|
||||
unsigned long ma_net_safe_read(MYSQL *mysql);
|
||||
void mysql_init_ps_subsystem(void);
|
||||
unsigned long net_field_length(unsigned char **packet);
|
||||
@ -319,9 +472,38 @@ int ma_simple_command(MYSQL *mysql,enum enum_server_command command, const char
|
||||
MYSQL_STMT * STDCALL mysql_stmt_init(MYSQL *mysql);
|
||||
int STDCALL mysql_stmt_prepare(MYSQL_STMT *stmt, const char *query, unsigned long length);
|
||||
int STDCALL mysql_stmt_execute(MYSQL_STMT *stmt);
|
||||
int STDCALL mysql_stmt_prepare_v2(MYSQL_STMT *stmt, const char *query, unsigned long length, void* extend_arg);
|
||||
int STDCALL mysql_stmt_execute_v2(MYSQL_STMT *stmt, const char *query, unsigned long length, unsigned int iteration_count, int execute_mode, void* extend_arg);
|
||||
int STDCALL mysql_stmt_fetch(MYSQL_STMT *stmt);
|
||||
int STDCALL mysql_stmt_fetch_column(MYSQL_STMT *stmt, MYSQL_BIND *bind_arg, unsigned int column, unsigned long offset);
|
||||
int STDCALL mysql_stmt_store_result(MYSQL_STMT *stmt);
|
||||
|
||||
my_bool STDCALL mysql_stmt_send_piece_data(MYSQL_STMT *stmt, unsigned int param_number,
|
||||
const char *data, unsigned long length,
|
||||
char piece_type, char is_null);
|
||||
my_bool STDCALL mysql_stmt_read_piece_data(MYSQL_STMT *stmt, unsigned int param_number,
|
||||
unsigned short orientation, int scroll_offset,
|
||||
unsigned long data_len, unsigned char *piece_type, unsigned long *ret_data_len);
|
||||
/*
|
||||
* add for RETURNING INTO resultset's flag
|
||||
**/
|
||||
my_bool STDCALL is_returning_result(MYSQL_STMT *stmt);
|
||||
my_bool STDCALL has_added_user_fields(MYSQL_STMT *stmt);
|
||||
/* add pl out resultset flag, observer since 3.2.2 */
|
||||
my_bool STDCALL is_pl_out_result(MYSQL_STMT *stmt);
|
||||
|
||||
unsigned long STDCALL stmt_pre_exe_req_ext_flag_get(MYSQL_STMT *stmt);
|
||||
void STDCALL stmt_pre_exe_req_ext_flag_set(MYSQL_STMT *stmt, unsigned long flag);
|
||||
|
||||
/*
|
||||
* add oracle_mode fetch method
|
||||
*/
|
||||
int STDCALL mysql_stmt_fetch_oracle_cursor(MYSQL_STMT *stmt);
|
||||
int STDCALL mysql_stmt_fetch_oracle_implicit_cursor(MYSQL_STMT *stmt, my_bool is_need_fetch_from_server);
|
||||
int STDCALL mysql_stmt_fetch_oracle_buffered_result(MYSQL_STMT *stmt);
|
||||
/*
|
||||
* end add oracle_mode fetch method
|
||||
*/
|
||||
unsigned long STDCALL mysql_stmt_param_count(MYSQL_STMT * stmt);
|
||||
my_bool STDCALL mysql_stmt_attr_set(MYSQL_STMT *stmt, enum enum_stmt_attr_type attr_type, const void *attr);
|
||||
my_bool STDCALL mysql_stmt_attr_get(MYSQL_STMT *stmt, enum enum_stmt_attr_type attr_type, void *attr);
|
||||
@ -347,3 +529,5 @@ int STDCALL mysql_stmt_next_result(MYSQL_STMT *stmt);
|
||||
my_bool STDCALL mysql_stmt_more_results(MYSQL_STMT *stmt);
|
||||
int STDCALL mariadb_stmt_execute_direct(MYSQL_STMT *stmt, const char *stmt_str, size_t length);
|
||||
MYSQL_FIELD * STDCALL mariadb_stmt_fetch_fields(MYSQL_STMT *stmt);
|
||||
void end_server(MYSQL *mysql);
|
||||
void free_old_query(MYSQL *mysql);
|
||||
|
||||
@ -11,7 +11,9 @@
|
||||
#else
|
||||
#define PROTOCOL_VERSION @PROTOCOL_VERSION@
|
||||
#define MARIADB_CLIENT_VERSION_STR "@MARIADB_CLIENT_VERSION@"
|
||||
#ifndef MARIADB_BASE_VERSION
|
||||
#define MARIADB_BASE_VERSION "@MARIADB_BASE_VERSION@"
|
||||
#endif
|
||||
#define MARIADB_VERSION_ID @MARIADB_VERSION_ID@
|
||||
#define MARIADB_PORT @MARIADB_PORT@
|
||||
#define MARIADB_UNIX_ADDR "@MARIADB_UNIX_ADDR@"
|
||||
@ -24,7 +26,9 @@
|
||||
|
||||
#define MYSQL_CONFIG_NAME "my"
|
||||
#define MYSQL_VERSION_ID @MARIADB_VERSION_ID@
|
||||
#ifndef MYSQL_SERVER_VERSION
|
||||
#define MYSQL_SERVER_VERSION "@MARIADB_CLIENT_VERSION@-MariaDB"
|
||||
#endif
|
||||
|
||||
#define MARIADB_PACKAGE_VERSION "@CPACK_PACKAGE_VERSION@"
|
||||
#define MARIADB_PACKAGE_VERSION_ID @MARIADB_PACKAGE_VERSION_ID@
|
||||
|
||||
@ -36,8 +36,17 @@ extern "C" {
|
||||
|
||||
#if !defined (_global_h) && !defined (MY_GLOBAL_INCLUDED) /* If not standard header */
|
||||
#include <sys/types.h>
|
||||
typedef char my_bool;
|
||||
|
||||
#ifndef TYPEDEF_MY_BOOL
|
||||
#define TYPEDEF_MY_BOOL
|
||||
typedef char my_bool; /* Small bool */
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef TYPEDEF_MY_ULONGLONG
|
||||
#define TYPEDEF_MY_ULONGLONG
|
||||
typedef unsigned long long my_ulonglong;
|
||||
#endif
|
||||
|
||||
#if !defined(_WIN32)
|
||||
#define STDCALL
|
||||
@ -60,6 +69,7 @@ typedef int my_socket;
|
||||
#include "mariadb_version.h"
|
||||
#include "ma_list.h"
|
||||
#include "mariadb_ctype.h"
|
||||
// #include "ma_hash.h"
|
||||
|
||||
|
||||
typedef struct st_ma_const_string
|
||||
@ -96,10 +106,19 @@ extern unsigned int mariadb_deinitialize_ssl;
|
||||
#define IS_PRI_KEY(n) ((n) & PRI_KEY_FLAG)
|
||||
#define IS_NOT_NULL(n) ((n) & NOT_NULL_FLAG)
|
||||
#define IS_BLOB(n) ((n) & BLOB_FLAG)
|
||||
#define IS_NUM(t) (((t) <= MYSQL_TYPE_INT24 && (t) != MYSQL_TYPE_TIMESTAMP) || (t) == MYSQL_TYPE_YEAR || (t) == MYSQL_TYPE_NEWDECIMAL)
|
||||
#define IS_NUM(t) (((t) <= MYSQL_TYPE_INT24 && (t) != MYSQL_TYPE_TIMESTAMP) || (t) == MYSQL_TYPE_YEAR || (t) == MYSQL_TYPE_NEWDECIMAL || (t) == MYSQL_TYPE_OB_NUMBER_FLOAT)
|
||||
#define IS_LONGDATA(t) (((t) >= MYSQL_TYPE_TINY_BLOB && (t) <= MYSQL_TYPE_STRING) || ((t) == MYSQL_TYPE_OB_NVARCHAR2 || (t) == MYSQL_TYPE_OB_NCHAR))
|
||||
#define IS_NUM_FIELD(f) ((f)->flags & NUM_FLAG)
|
||||
#define INTERNAL_NUM_FIELD(f) (((f)->type <= MYSQL_TYPE_INT24 && ((f)->type != MYSQL_TYPE_TIMESTAMP || (f)->length == 14 || (f)->length == 8)) || (f)->type == MYSQL_TYPE_YEAR || (f)->type == MYSQL_TYPE_NEWDECIMAL || (f)->type == MYSQL_TYPE_DECIMAL)
|
||||
|
||||
#define IS_NUM_TERMINAL(t) (((t) <= MYSQL_TYPE_INT24 && (t) != MYSQL_TYPE_TIMESTAMP) || (t) == MYSQL_TYPE_YEAR || (t) == MYSQL_TYPE_NEWDECIMAL || (t) == MYSQL_TYPE_OB_NUMBER_FLOAT)
|
||||
#define IS_NUM_BINARY_TERMINAL(t) ((t) == MYSQL_TYPE_FLOAT || (t) == MYSQL_TYPE_DOUBLE)
|
||||
enum ObRoutineParamInOut
|
||||
{
|
||||
SP_PARAM_IN = 1,
|
||||
SP_PARAM_OUT = 2,
|
||||
SP_PARAM_INOUT = 3,
|
||||
};
|
||||
typedef struct st_mysql_field {
|
||||
char *name; /* Name of column */
|
||||
char *org_name; /* Name of original column (added after 3.23.58) */
|
||||
@ -121,8 +140,22 @@ extern unsigned int mariadb_deinitialize_ssl;
|
||||
/***********************/
|
||||
unsigned int flags; /* Div flags */
|
||||
unsigned int decimals; /* Number of decimals in field */
|
||||
unsigned int precision;
|
||||
enum ObRoutineParamInOut ob_routine_param_inout;
|
||||
my_bool is_implicit_rowid;
|
||||
unsigned int charsetnr; /* char set number (added in 4.1) */
|
||||
unsigned char *owner_name;
|
||||
unsigned char *type_name;
|
||||
unsigned long version;
|
||||
unsigned int owner_name_length;
|
||||
unsigned int type_name_length;
|
||||
enum enum_field_types type; /* Type of field. Se mysql_com.h for types */
|
||||
unsigned char *elem_owner_name;
|
||||
unsigned char *elem_type_name;
|
||||
unsigned long elem_version;
|
||||
unsigned int elem_owner_name_length;
|
||||
unsigned int elem_type_name_length;
|
||||
enum enum_field_types elem_type; /* Type of array elem. Se mysql_com.h for types */
|
||||
void *extension; /* added in 4.1 */
|
||||
} MYSQL_FIELD;
|
||||
|
||||
@ -369,7 +402,47 @@ struct st_mysql_options {
|
||||
my_bool *unbuffered_fetch_owner;
|
||||
char *info_buffer;
|
||||
struct st_mariadb_extension *extension;
|
||||
void * ob_extension;
|
||||
my_bool can_use_prepare_execute;
|
||||
my_bool can_send_plarray_maxrarr_len;
|
||||
my_bool can_plarray_bindbyname;
|
||||
my_bool can_use_protocol_ob20;
|
||||
my_bool can_use_full_link_trace;
|
||||
unsigned long ob_server_version;
|
||||
unsigned long ob_proxy_version;
|
||||
unsigned long capability; // system varaiable
|
||||
} MYSQL;
|
||||
struct st_mysql_trace_info;
|
||||
struct ob_st_hash;
|
||||
#ifndef TYPE_DEFINE_OB_HASH
|
||||
#define TYPE_DEFINE_OB_HASH
|
||||
typedef struct ob_st_hash OB_HASH;
|
||||
#endif
|
||||
typedef struct st_mysql_extension {
|
||||
MYSQL *mysql;
|
||||
OB_HASH *complex_type_hash;
|
||||
#define MAX_NLS_FORMAT_STR_LEN 256
|
||||
unsigned char nls_date_format[MAX_NLS_FORMAT_STR_LEN];
|
||||
unsigned char nls_timestamp_format[MAX_NLS_FORMAT_STR_LEN];
|
||||
unsigned char nls_timestamp_tz_format[MAX_NLS_FORMAT_STR_LEN];
|
||||
// struct st_mysql_trace_info *trace_data;
|
||||
// struct st_session_track_info state_change;
|
||||
} MYSQL_EXTENSION;
|
||||
/* "Constructor/destructor" for MYSQL extension structure. */
|
||||
struct st_mysql_extension* mysql_extension_init(struct st_mysql*);
|
||||
void mysql_extension_free(struct st_mysql_extension*);
|
||||
|
||||
/*
|
||||
Note: Allocated extension structure is freed in mysql_close_free()
|
||||
called by mysql_close().
|
||||
*/
|
||||
#define MYSQL_EXTENSION_PTR(H) \
|
||||
( \
|
||||
(struct st_mysql_extension*) \
|
||||
( (H)->ob_extension ? \
|
||||
(H)->ob_extension : ((H)->ob_extension= mysql_extension_init(H)) \
|
||||
) \
|
||||
)
|
||||
|
||||
typedef struct st_mysql_res {
|
||||
unsigned long long row_count;
|
||||
@ -384,6 +457,8 @@ typedef struct st_mysql_res {
|
||||
MYSQL *handle; /* for unbuffered reads */
|
||||
my_bool eof; /* Used my mysql_fetch_row */
|
||||
my_bool is_ps;
|
||||
MYSQL_FIELD *param_fields;
|
||||
unsigned int param_count;
|
||||
} MYSQL_RES;
|
||||
|
||||
typedef struct
|
||||
@ -512,6 +587,7 @@ my_bool STDCALL mysql_eof(MYSQL_RES *res);
|
||||
MYSQL_FIELD *STDCALL mysql_fetch_field_direct(MYSQL_RES *res,
|
||||
unsigned int fieldnr);
|
||||
MYSQL_FIELD * STDCALL mysql_fetch_fields(MYSQL_RES *res);
|
||||
MYSQL_FIELD * STDCALL mysql_fetch_params(MYSQL_RES *res);
|
||||
MYSQL_ROWS * STDCALL mysql_row_tell(MYSQL_RES *res);
|
||||
unsigned int STDCALL mysql_field_tell(MYSQL_RES *res);
|
||||
|
||||
@ -742,6 +818,7 @@ int STDCALL mysql_stmt_send_long_data_start(my_bool *ret, MYSQL_STMT *stmt,
|
||||
int STDCALL mysql_stmt_send_long_data_cont(my_bool *ret, MYSQL_STMT *stmt,
|
||||
int status);
|
||||
int STDCALL mysql_reset_connection(MYSQL *mysql);
|
||||
my_bool get_local_ip_port(my_socket fd, char *ip, int iplen, int *port);
|
||||
|
||||
/* API function calls (used by dynamic plugins) */
|
||||
struct st_mariadb_api {
|
||||
|
||||
50
include/ob_bitmap.h
Normal file
50
include/ob_bitmap.h
Normal file
@ -0,0 +1,50 @@
|
||||
/************************************************************************************
|
||||
Copyright (c) 2021 OceanBase.
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not see <http://www.gnu.org/licenses>
|
||||
or write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St., Fifth Floor, Boston, MA 02110, USA
|
||||
|
||||
Part of this code includes code from the PHP project which
|
||||
is freely available from http://www.php.net
|
||||
*************************************************************************************/
|
||||
|
||||
#ifndef _ob_bitmap_h_
|
||||
#define _ob_bitmap_h_
|
||||
|
||||
#include <ma_global.h>
|
||||
|
||||
typedef uint32 ob_bitmap_map;
|
||||
|
||||
typedef struct st_bitmap
|
||||
{
|
||||
ob_bitmap_map *bitmap;
|
||||
uint n_bits;
|
||||
} OB_BITMAP;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
my_bool ob_bitmap_init(OB_BITMAP *map, uint n_bits);
|
||||
void ob_bitmap_free(OB_BITMAP *map);
|
||||
void ob_bitmap_set_bit(OB_BITMAP *map, uint bit);
|
||||
void ob_bitmap_clear_bit(OB_BITMAP *map, uint bit);
|
||||
my_bool ob_bitmap_is_set(const OB_BITMAP *map, uint bit);
|
||||
void ob_bitmap_clear_all(OB_BITMAP *map);
|
||||
void ob_bitmap_set_all(OB_BITMAP *map);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _ob_bitmap_h_ */
|
||||
83
include/ob_complex.h
Normal file
83
include/ob_complex.h
Normal file
@ -0,0 +1,83 @@
|
||||
/************************************************************************
|
||||
Copyright (c) 2021 OceanBase.
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
MA 02111-1301, USA
|
||||
|
||||
Part of this code includes code from PHP's mysqlnd extension
|
||||
(written by Andrey Hristov, Georg Richter and Ulf Wendel), freely
|
||||
available from http://www.php.net/software
|
||||
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef _OB_COMPLEX_H
|
||||
#define _OB_COMPLEX_H
|
||||
|
||||
#include "mysql.h"
|
||||
#include "ma_hash.h"
|
||||
#include "ob_rwlock.h"
|
||||
|
||||
typedef struct st_complex_hash {
|
||||
unsigned char *hash_key;
|
||||
OB_HASH *hash;
|
||||
ob_rw_lock_t rwlock;
|
||||
} COMPLEX_HASH;
|
||||
|
||||
typedef enum enum_types {
|
||||
TYPE_NUMBER,
|
||||
TYPE_VARCHAR2,
|
||||
TYPE_CHAR,
|
||||
TYPE_DATE,
|
||||
TYPE_OBJECT,
|
||||
TYPE_COLLECTION,
|
||||
TYPE_RAW,
|
||||
TYPE_LONG,
|
||||
TYPE_LONGLONG,
|
||||
TYPE_TINY,
|
||||
TYPE_SHORT,
|
||||
TYPE_FLOAT,
|
||||
TYPE_DOUBLE,
|
||||
TYPE_UNKNOW,
|
||||
TYPE_MAX
|
||||
} enum_types;
|
||||
|
||||
typedef struct st_complex_type {
|
||||
enum_types type;
|
||||
unsigned char owner_name[128];
|
||||
unsigned char type_name[128];
|
||||
unsigned int version;
|
||||
my_bool is_valid;
|
||||
} COMPLEX_TYPE;
|
||||
|
||||
typedef struct st_child_type {
|
||||
enum_types type;
|
||||
COMPLEX_TYPE *object;
|
||||
} CHILD_TYPE;
|
||||
|
||||
typedef struct st_complex_type_object {
|
||||
COMPLEX_TYPE header;
|
||||
unsigned int attr_no;
|
||||
unsigned int init_attr_no;
|
||||
CHILD_TYPE *child;
|
||||
} COMPLEX_TYPE_OBJECT;
|
||||
|
||||
typedef struct st_complex_type_collection {
|
||||
COMPLEX_TYPE header;
|
||||
CHILD_TYPE child;
|
||||
} COMPLEX_TYPE_COLLECTION;
|
||||
|
||||
COMPLEX_TYPE* STDCALL get_complex_type(MYSQL *mysql, unsigned char *owner_name, unsigned char *type_name);
|
||||
COMPLEX_TYPE* STDCALL get_complex_type_with_local(MYSQL *mysql, unsigned char *type_name);
|
||||
|
||||
#endif /* _OB_COMPLEX_H */
|
||||
51
include/ob_cond.h
Normal file
51
include/ob_cond.h
Normal file
@ -0,0 +1,51 @@
|
||||
/************************************************************************
|
||||
Copyright (c) 2021 OceanBase.
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
MA 02111-1301, USA
|
||||
|
||||
Part of this code includes code from PHP's mysqlnd extension
|
||||
(written by Andrey Hristov, Georg Richter and Ulf Wendel), freely
|
||||
available from http://www.php.net/software
|
||||
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef _OB_COND_H
|
||||
#define _OB_COND_H
|
||||
|
||||
#include "ob_thread.h"
|
||||
#include "ob_rwlock.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
typedef CONDITION_VARIABLE ob_cond_t;
|
||||
#else
|
||||
typedef pthread_cond_t ob_cond_t;
|
||||
#endif
|
||||
|
||||
int ob_cond_init(ob_cond_t *cond);
|
||||
int ob_cond_destroy(ob_cond_t *cond);
|
||||
int ob_cond_timedwait(ob_cond_t *cond, ob_mutex_t *mutex, const struct timespec *abstime);
|
||||
int ob_cond_wait(ob_cond_t *cond, ob_mutex_t *mutex);
|
||||
int ob_cond_signal(ob_cond_t *cond);
|
||||
int ob_cond_broadcast(ob_cond_t *cond);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _OB_COND_H */
|
||||
439
include/ob_full_link_trace.h
Normal file
439
include/ob_full_link_trace.h
Normal file
@ -0,0 +1,439 @@
|
||||
/*
|
||||
Copyright (c) 2000, 2018, Oracle and/or its affiliates.
|
||||
Copyright (c) 2009, 2019, MariaDB Corporation.
|
||||
Copyright (c) 2021 OceanBase.
|
||||
|
||||
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; version 2 of the License.
|
||||
|
||||
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, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */
|
||||
|
||||
#ifndef _ob_full_link_trace_h
|
||||
#define _ob_full_link_trace_h
|
||||
|
||||
#include <stdint.h>
|
||||
#include "ob_object.h"
|
||||
#include "ma_list.h"
|
||||
#include "ob_thread_key.h"
|
||||
|
||||
// #define DEBUG_OB20
|
||||
|
||||
#define UUID4_LEN 37
|
||||
#define UUID4_SERIALIZE_LEN 16
|
||||
|
||||
#define FLT_DECLARE \
|
||||
Ob20Protocol *ob20protocol = mysql->net.ob20protocol; \
|
||||
FLTInfo *flt = NULL; \
|
||||
ObSpanCtx *span; \
|
||||
ObTrace *trace; \
|
||||
char ip_buffer[50] = {0}; \
|
||||
char host_buffer[50] = {0}; \
|
||||
int port = 0
|
||||
|
||||
#define FLT_BEFORE_COMMAND(span_level, tag_level, tag_str) \
|
||||
do \
|
||||
{ \
|
||||
if (get_use_full_link_trace(mysql) && OB_NOT_NULL(ob20protocol)) { \
|
||||
flt = ob20protocol->flt; \
|
||||
if (OB_NOT_NULL(flt)) { \
|
||||
if (mysql->server_status & SERVER_STATUS_IN_TRANS) { \
|
||||
/* 当前事务中每次 begin 之前需要 reset,防止 span 不够用*/ \
|
||||
reset_span(flt->trace_); \
|
||||
} else { \
|
||||
/* 不在事务中再重新 begin trace */ \
|
||||
BEGIN_TRACE(flt); \
|
||||
} \
|
||||
span = BEGIN_SPAN(flt, span_level); \
|
||||
SET_TAG(flt, tag_level, tag_str); \
|
||||
if (NULL != mysql && get_local_ip_port(mysql->net.fd, ip_buffer, 50, &port)) { \
|
||||
snprintf(host_buffer, 50, "\"%s:%d\"", ip_buffer, port); \
|
||||
SET_TAG(flt, FLT_TAG_CLIENT_HOST, host_buffer); \
|
||||
} \
|
||||
if (flt_build_request(mysql, flt)) { \
|
||||
/* error , but do nothing */ \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define FLT_AFTER_COMMAND \
|
||||
do \
|
||||
{ \
|
||||
ob20protocol = mysql->net.ob20protocol; \
|
||||
if (get_use_full_link_trace(mysql) && OB_NOT_NULL(ob20protocol)) { \
|
||||
flt = ob20protocol->flt; \
|
||||
trace = OBTRACE(flt); \
|
||||
if (NULL != trace) { \
|
||||
END_SPAN(flt, span); \
|
||||
if (TRUE == trace->force_print_) { \
|
||||
FLUSH_TRACE(flt); \
|
||||
} else if (TRUE == trace->slow_query_print_) { \
|
||||
trace->slow_query_print_ = FALSE; /* 每次请求就slow query置为FALSE */ \
|
||||
flush_first_span(trace); \
|
||||
} \
|
||||
if (mysql->server_status & SERVER_STATUS_IN_TRANS) { \
|
||||
/* do nothing */ \
|
||||
} else { \
|
||||
/* 不在事务中需要结束trace */ \
|
||||
END_TRACE(flt); \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define DEFINE_FLT_SERIALIZE_FUNC(type) \
|
||||
int flt_serialize_##type(char *buf, const int64_t len, int64_t *pos, void *flt_info); \
|
||||
int flt_get_serialize_size_##type(int32_t *size, void *flt_info); \
|
||||
int flt_deserialize_field_##type(FullLinkTraceExtraInfoId extra_id, const int64_t v_len, \
|
||||
const char *buf, const int64_t len, int64_t *pos, void *flt_info)
|
||||
|
||||
#define FLT_SERIALIZE_FUNC(type) \
|
||||
{ \
|
||||
flt_deserialize_field_##type, \
|
||||
flt_serialize_##type, \
|
||||
flt_get_serialize_size_##type \
|
||||
}
|
||||
|
||||
#define DEFINE_TO_STRING_FUNC_FOR(type) \
|
||||
int tostring_##type(char *buf, const int64_t buf_len, int64_t *pos, type *src)
|
||||
|
||||
// 当前维护每个trace大小为4k, 这个大小是整个trace期间分配的所有空间大小
|
||||
#define OBTRACE_DEFAULT_BUFFER_SIZE (1L << 12)
|
||||
// 当前驱动free span为4个
|
||||
#define SPAN_CACHE_COUNT (1L << 2)
|
||||
// 由于当前最多就一个SPAN,最大的LOG buffer为 1k
|
||||
#define MAX_TRACE_LOG_SIZE (1L << 10)
|
||||
// 当前全链路部分序列化后最大大小为 2k
|
||||
#define MAX_FLT_SERIALIZE_SIZE (1L << 11)
|
||||
#define INIT_OFFSET (MAX_TRACE_LOG_SIZE + MAX_FLT_SERIALIZE_SIZE + SPAN_CACHE_COUNT * (sizeof(LIST) + sizeof(ObSpanCtx)))
|
||||
|
||||
#define OBTRACE(flt) get_trace_instance(flt)
|
||||
#define BEGIN_TRACE(flt) (begin_trace(OBTRACE(flt)))
|
||||
#define END_TRACE(flt) \
|
||||
do \
|
||||
{ \
|
||||
end_trace(OBTRACE(flt)); \
|
||||
} while (0)
|
||||
#define BEGIN_SPAN(flt, span_type) BEGIN_CHILD_SPAN(flt, span_type)
|
||||
#define BEGIN_CHILD_SPAN(flt, span_type) (begin_span(OBTRACE(flt), span_type, 1, FALSE))
|
||||
#define BEGIN_FOLLOW_SPAN(flt, span_type) (begin_span(OBTRACE(flt), span_type, 1, TRUE))
|
||||
#define END_SPAN(flt, span_id) \
|
||||
do \
|
||||
{ \
|
||||
ObTrace *trace = OBTRACE(flt); \
|
||||
(end_span(trace, span_id)); \
|
||||
} while (0)
|
||||
#define SET_TAG(flt, tag_type, value) \
|
||||
do \
|
||||
{ \
|
||||
ObSpanCtx *span = OBTRACE(flt)->last_active_span_; \
|
||||
if (OB_NOT_NULL(span)) { \
|
||||
append_tag(OBTRACE(flt), span, tag_type, value); \
|
||||
} \
|
||||
} while (0)
|
||||
#define SET_TRACE_LEVEL(trace, level) (trace->level_ = level)
|
||||
#define SET_AUTO_FLUSH(trace, value) (trace->auto_flush_ = value)
|
||||
#define FLUSH_TRACE(flt) \
|
||||
do \
|
||||
{ \
|
||||
flush_trace(OBTRACE(flt)); \
|
||||
} while (0)
|
||||
|
||||
|
||||
typedef struct st_obtrace ObTrace;
|
||||
/*
|
||||
0 ~ 999用于ob client 私有
|
||||
1000~1999用于ob proxy私有
|
||||
2000~65535用于全链路共有
|
||||
*/
|
||||
typedef enum enum_fulllinktraceextrainfoid
|
||||
{
|
||||
FLT_DRIVER_SPAN = 1,
|
||||
FLT_DRIVER_END = 1000,
|
||||
// APP_INFO
|
||||
FLT_CLIENT_IDENTIFIER = 2001,
|
||||
FLT_MODULE,
|
||||
FLT_ACTION,
|
||||
FLT_CLIENT_INFO,
|
||||
FLT_APPINFO_TYPE,
|
||||
// QUERY_INFO
|
||||
FLT_QUERY_START_TIMESTAMP = 2010,
|
||||
FLT_QUERY_END_TIMESTAMP,
|
||||
// CONTROL_INFO
|
||||
FLT_LEVEL = 2020,
|
||||
FLT_SAMPLE_PERCENTAGE,
|
||||
FLT_RECORD_POLICY,
|
||||
FLT_PRINT_SAMPLE_PCT,
|
||||
FLT_SLOW_QUERY_THRES,
|
||||
// SPAN_INFO
|
||||
FLT_TRACE_ENABLE = 2030,
|
||||
FLT_FORCE_PRINT,
|
||||
FLT_TRACE_ID,
|
||||
FLT_REF_TYPE,
|
||||
FLT_SPAN_ID,
|
||||
FLT_EXTRA_INFO_ID_END
|
||||
} FullLinkTraceExtraInfoId;
|
||||
|
||||
/*
|
||||
0 ~ 999用于ob client 私有
|
||||
1000~1999用于ob proxy私有
|
||||
2000~65535用于全链路共有
|
||||
*/
|
||||
typedef enum enum_fulllinktraceextrainfotype
|
||||
{
|
||||
FLT_DRIVER_SPAN_INFO = 1,
|
||||
FLT_EXTRA_INFO_DRIVE_END = 1000,
|
||||
|
||||
FLT_APP_INFO = 2001,
|
||||
FLT_QUERY_INFO,
|
||||
FLT_CONTROL_INFO,
|
||||
FLT_SPAN_INFO,
|
||||
FLT_EXTRA_INFO_TYPE_END
|
||||
} FullLinkTraceExtraInfoType;
|
||||
|
||||
typedef enum enum_recordpolicy {
|
||||
RP_ALL = 1,
|
||||
RP_ONLY_SLOW_QUERY,
|
||||
RP_SAMPLE_AND_SLOW_QUERY,
|
||||
MAX_RECORD_POLICY
|
||||
} RecordPolicy;
|
||||
|
||||
typedef struct st_fltinfobase
|
||||
{
|
||||
FullLinkTraceExtraInfoType type_;
|
||||
} FLTInfoBase;
|
||||
|
||||
typedef struct st_fltcontrolinfo
|
||||
{
|
||||
FullLinkTraceExtraInfoType type_;
|
||||
int8_t level_;
|
||||
double sample_pct_;
|
||||
RecordPolicy rp_;
|
||||
double print_sample_pct_;
|
||||
int64_t slow_query_threshold_;
|
||||
} FLTControlInfo;
|
||||
|
||||
typedef struct st_fltappinfo
|
||||
{
|
||||
FullLinkTraceExtraInfoType type_;
|
||||
const char *identifier_;
|
||||
const char *module_;
|
||||
const char *action_;
|
||||
const char *client_info_;
|
||||
} FLTAppInfo;
|
||||
|
||||
typedef struct st_fltqueryinfo
|
||||
{
|
||||
FullLinkTraceExtraInfoType type_;
|
||||
int64_t query_start_timestamp_;
|
||||
int64_t query_end_timestamp_;
|
||||
} FLTQueryInfo;
|
||||
|
||||
typedef struct st_fltspaninfo
|
||||
{
|
||||
FullLinkTraceExtraInfoType type_;
|
||||
int8_t trace_enable_;
|
||||
int8_t force_print_;
|
||||
const char *trace_id_;
|
||||
int8_t ref_type_;
|
||||
const char *span_id_;
|
||||
} FLTSpanInfo;
|
||||
|
||||
typedef struct st_fltdriverspaninfo
|
||||
{
|
||||
FullLinkTraceExtraInfoType type_;
|
||||
const char *client_span_;
|
||||
} FLTDriverSpanInfo;
|
||||
|
||||
typedef struct st_fltvaluedata
|
||||
{
|
||||
void *value_data_;
|
||||
size_t length;
|
||||
} FLTValueData;
|
||||
|
||||
typedef struct st_fltinfo
|
||||
{
|
||||
FLTDriverSpanInfo client_span_;
|
||||
FLTControlInfo control_info_;
|
||||
FLTAppInfo app_info_;
|
||||
FLTQueryInfo query_info_;
|
||||
FLTSpanInfo span_info_;
|
||||
|
||||
FLTValueData flt_value_data_; // for set extra info
|
||||
|
||||
my_bool in_trans_;
|
||||
char trace_id_[UUID4_SERIALIZE_LEN];
|
||||
char span_id_[UUID4_SERIALIZE_LEN];
|
||||
ObTrace *trace_;
|
||||
} FLTInfo;
|
||||
|
||||
typedef int (*flt_deserialize_field_func)(FullLinkTraceExtraInfoId extra_id, const int64_t v_len,
|
||||
const char *buf, const int64_t len, int64_t *pos, void *flt_info);
|
||||
typedef int (*flt_serialize_func)(char *buf, const int64_t len, int64_t *pos, void *flt_info);
|
||||
typedef int (*flt_get_serialize_size_func)(int32_t *size, void *flt_info);
|
||||
|
||||
typedef struct st_fltfunc
|
||||
{
|
||||
flt_deserialize_field_func deserialize_field_func;
|
||||
flt_serialize_func serialize_func;
|
||||
flt_get_serialize_size_func get_serialize_size_func;
|
||||
} FLTFunc;
|
||||
|
||||
typedef struct st_uuid
|
||||
{
|
||||
union {
|
||||
struct {
|
||||
uint64_t low_;
|
||||
uint64_t high_;
|
||||
};
|
||||
struct {
|
||||
uint32_t time_low;
|
||||
uint16_t time_mid;
|
||||
uint16_t time_hi_and_version;
|
||||
uint8_t clock_seq_hi_and_reserved;
|
||||
uint8_t clock_seq_low;
|
||||
uint8_t node[6];
|
||||
};
|
||||
};
|
||||
} UUID;
|
||||
DEFINE_TO_STRING_FUNC_FOR(UUID);
|
||||
|
||||
enum enum_flt_tagtype{
|
||||
FLT_TAG_COMMAND_NAME = 0,
|
||||
FLT_TAG_CLIENT_HOST = 1,
|
||||
FLT_TAG_MAX_TYPE
|
||||
};
|
||||
|
||||
typedef struct st_obtagctx ObTagCtx;
|
||||
struct st_obtagctx
|
||||
{
|
||||
ObTagCtx *next_;
|
||||
uint16_t tag_type_;
|
||||
const char *data_;
|
||||
};
|
||||
DEFINE_TO_STRING_FUNC_FOR(ObTagCtx);
|
||||
|
||||
typedef struct st_obspanctx
|
||||
{
|
||||
uint16_t span_type_;
|
||||
UUID span_id_;
|
||||
struct st_obspanctx *source_span_;
|
||||
my_bool is_follow_;
|
||||
int64_t start_ts_;
|
||||
int64_t end_ts_;
|
||||
ObTagCtx *tags_;
|
||||
} ObSpanCtx;
|
||||
DEFINE_TO_STRING_FUNC_FOR(ObSpanCtx);
|
||||
|
||||
struct st_obtrace
|
||||
{
|
||||
uint64_t buffer_size_;
|
||||
uint64_t offset_;
|
||||
uint64_t seq_;
|
||||
my_bool in_trans_;
|
||||
my_bool trace_enable_;
|
||||
my_bool force_print_;
|
||||
my_bool slow_query_print_;
|
||||
FLTInfo *flt; // point to flt struct
|
||||
uint64_t uuid_random_seed[2];
|
||||
UUID trace_id_;
|
||||
UUID root_span_id_;
|
||||
LIST *current_span_list_;
|
||||
LIST *free_span_list_;
|
||||
ObSpanCtx *last_active_span_;
|
||||
union {
|
||||
uint8_t policy_;
|
||||
struct {
|
||||
uint8_t level_ : 7;
|
||||
uint8_t auto_flush_ : 1;
|
||||
};
|
||||
};
|
||||
uint64_t log_buf_offset_;
|
||||
char *log_buf_; // 大小为:MAX_TRACE_LOG_SIZE
|
||||
char *flt_serialize_buf_; // 大小为:MAX_FLT_SERIALIZE_SIZE
|
||||
char data_[0]; // 多分配的空间存储free span以及方便后续打tag时使用
|
||||
};
|
||||
|
||||
int trace_init();
|
||||
void trace_end();
|
||||
void begin_trace(ObTrace *trace);
|
||||
void end_trace(ObTrace *trace);
|
||||
ObSpanCtx* begin_span(ObTrace *trace, uint32_t span_type, uint8_t level, my_bool is_follow);
|
||||
void end_span(ObTrace *trace, ObSpanCtx *span);
|
||||
// 当前在sql开始的时候需要调用reset接口将span清空, 防止事务中span过多
|
||||
void reset_span(ObTrace *trace);
|
||||
void append_tag(ObTrace *trace, ObSpanCtx *span, uint16_t tag_type, const char *str);
|
||||
ObTrace *get_trace_instance(FLTInfo *flt);
|
||||
void flush_first_span(ObTrace *trace);
|
||||
void flush_trace(ObTrace *trace);
|
||||
|
||||
DEFINE_FLT_SERIALIZE_FUNC(appinfo); // FLT_APP_INFO
|
||||
DEFINE_FLT_SERIALIZE_FUNC(queryinfo); // FLT_QUERY_INFO
|
||||
DEFINE_FLT_SERIALIZE_FUNC(controlinfo); // FLT_CONTROL_INFO
|
||||
DEFINE_FLT_SERIALIZE_FUNC(spaninfo); // FLT_SPAN_INFO
|
||||
DEFINE_FLT_SERIALIZE_FUNC(driverspaninfo); // FLT_DRIVER_SPAN_INFO
|
||||
DEFINE_FLT_SERIALIZE_FUNC(nosupport); // FLT_EXTRA_INFO_TYPE_END
|
||||
|
||||
// 判断是否是合法的控制信息,如果不合法,不发送extra info
|
||||
my_bool flt_is_vaild(FLTInfo *flt);
|
||||
|
||||
int serialize_UUID(char *buf, const int64_t buf_len, int64_t* pos, UUID *uuid);
|
||||
int deserialize_UUID(const char *buf, const int64_t buf_len, int64_t *pos, UUID *uuid);
|
||||
|
||||
int uuid4_init(uint64_t *seed, size_t seed_size);
|
||||
UUID uuid4_generate(uint64_t *seed);
|
||||
|
||||
int flt_init(FLTInfo *flt);
|
||||
void flt_end(FLTInfo *flt);
|
||||
int flt_build_request(MYSQL *mysql, FLTInfo *flt);
|
||||
void flt_set_send_trans_flag(FLTInfo *flt, my_bool send_flag);
|
||||
|
||||
int flt_deserialize_extra_info(const char *buf, const int64_t len, int64_t *pos, FullLinkTraceExtraInfoType type, void *flt_info);
|
||||
int flt_serialize_extra_info(char *buf, const int64_t len, int64_t *pos, void *flt_info);
|
||||
int flt_get_serialize_size_extra_info(int32_t *size, void *flt_info);
|
||||
|
||||
// for encode
|
||||
int flt_store_type_and_len(char *buf, int64_t len, int64_t *pos, int16_t type, int32_t v_len);
|
||||
int flt_store_str(char *buf, int64_t len, int64_t *pos, const char *str, const uint64_t str_len, int16_t type);
|
||||
//@{Serialize integer data, save the data in v to the position of buf+pos, and update pos
|
||||
int flt_store_int1(char *buf, int64_t len, int64_t *pos, int8_t v, int16_t type);
|
||||
int flt_store_int2(char *buf, int64_t len, int64_t *pos, int16_t v, int16_t type);
|
||||
int flt_store_int3(char *buf, int64_t len, int64_t *pos, int32_t v, int16_t type);
|
||||
int flt_store_int4(char *buf, int64_t len, int64_t *pos, int32_t v, int16_t type);
|
||||
int flt_store_int5(char *buf, int64_t len, int64_t *pos, int64_t v, int16_t type);
|
||||
int flt_store_int6(char *buf, int64_t len, int64_t *pos, int64_t v, int16_t type);
|
||||
int flt_store_int8(char *buf, int64_t len, int64_t *pos, int64_t v, int16_t type);
|
||||
int flt_store_double(char *buf, const int64_t len, int64_t *pos, double val, int16_t type);
|
||||
int flt_store_float(char *buf, const int64_t len, int64_t *pos, float val, int16_t type);
|
||||
|
||||
int flt_get_store_str_size(const uint64_t str_len);
|
||||
int flt_get_store_int1_size();
|
||||
int flt_get_store_int2_size();
|
||||
int flt_get_store_int3_size();
|
||||
int flt_get_store_int4_size();
|
||||
int flt_get_store_int5_size();
|
||||
int flt_get_store_int6_size();
|
||||
int flt_get_store_int8_size();
|
||||
int flt_get_store_double_size();
|
||||
int flt_get_store_float_size();
|
||||
|
||||
// for decode
|
||||
int flt_resolve_type_and_len(const char *buf, int64_t len, int64_t *pos, int16_t *type, int32_t *v_len);
|
||||
int flt_get_str(const char *buf, int64_t len, int64_t *pos, int64_t str_len, char **str);
|
||||
//@{ Signed integer in reverse sequence, write the result to v, and update pos
|
||||
int flt_get_int1(const char *buf, int64_t len, int64_t *pos, int64_t v_len, int8_t *val);
|
||||
int flt_get_int2(const char *buf, int64_t len, int64_t *pos, int64_t v_len, int16_t *val);
|
||||
int flt_get_int3(const char *buf, int64_t len, int64_t *pos, int64_t v_len, int32_t *val);
|
||||
int flt_get_int4(const char *buf, int64_t len, int64_t *pos, int64_t v_len, int32_t *val);
|
||||
int flt_get_int8(const char *buf, int64_t len, int64_t *pos, int64_t v_len, int64_t *val);
|
||||
int flt_get_double(const char *buf, int64_t len, int64_t *pos, int64_t v_len, double *val);
|
||||
int flt_get_float(const char *buf, int64_t len, int64_t *pos, int64_t v_len, float *val);
|
||||
#endif
|
||||
285
include/ob_object.h
Normal file
285
include/ob_object.h
Normal file
@ -0,0 +1,285 @@
|
||||
/*
|
||||
Copyright (c) 2000, 2018, Oracle and/or its affiliates.
|
||||
Copyright (c) 2009, 2019, MariaDB Corporation.
|
||||
Copyright (c) 2021 OceanBase.
|
||||
|
||||
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; version 2 of the License.
|
||||
|
||||
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, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */
|
||||
|
||||
#ifndef _ob_object_h
|
||||
#define _ob_object_h
|
||||
|
||||
#include <mysql.h>
|
||||
#include <stdint.h>
|
||||
|
||||
typedef enum enum_obobjtype
|
||||
{
|
||||
ObNullType = 0, // 空类型
|
||||
|
||||
ObTinyIntType=1, // int8, aka mysql boolean type
|
||||
ObSmallIntType=2, // int16
|
||||
ObMediumIntType=3, // int24
|
||||
ObInt32Type=4, // int32
|
||||
ObIntType=5, // int64, aka bigint
|
||||
|
||||
ObUTinyIntType=6, // uint8
|
||||
ObUSmallIntType=7, // uint16
|
||||
ObUMediumIntType=8, // uint24
|
||||
ObUInt32Type=9, // uint32
|
||||
ObUInt64Type=10, // uint64
|
||||
|
||||
ObFloatType=11, // single-precision floating point
|
||||
ObDoubleType=12, // double-precision floating point
|
||||
|
||||
ObUFloatType=13, // unsigned single-precision floating point
|
||||
ObUDoubleType=14, // unsigned double-precision floating point
|
||||
|
||||
ObNumberType=15, // aka decimal/numeric
|
||||
ObUNumberType=16,
|
||||
|
||||
ObDateTimeType=17,
|
||||
ObTimestampType=18,
|
||||
ObDateType=19,
|
||||
ObTimeType=20,
|
||||
ObYearType=21,
|
||||
|
||||
ObVarcharType=22, // charset: utf8mb4 or binary
|
||||
ObCharType=23, // charset: utf8mb4 or binary
|
||||
|
||||
ObHexStringType = 24, // hexadecimal literal, e.g. X'42', 0x42, b'1001', 0b1001
|
||||
|
||||
ObExtendType = 25, // Min, Max, NOP etc.
|
||||
ObUnknownType = 26, // For question mark(?) in prepared statement, no need to serialize
|
||||
// @note future new types to be defined here !!!
|
||||
|
||||
ObTinyTextType = 27,
|
||||
ObTextType = 28,
|
||||
ObMediumTextType = 29,
|
||||
ObLongTextType = 30,
|
||||
|
||||
ObBitType = 31,
|
||||
ObEnumType = 32,
|
||||
ObSetType = 33,
|
||||
ObEnumInnerType = 34,
|
||||
ObSetInnerType = 35,
|
||||
|
||||
ObTimestampTZType = 36, // timestamp with time zone for oracle
|
||||
ObTimestampLTZType = 37, // timestamp with local time zone for oracle
|
||||
ObTimestampNanoType = 38, // timestamp nanosecond for oracle
|
||||
ObRawType = 39, // raw type for oracle
|
||||
ObIntervalYMType = 40, // interval year to month
|
||||
ObIntervalDSType = 41, // interval day to second
|
||||
ObNumberFloatType = 42, // oracle float, subtype of NUMBER
|
||||
ObNVarchar2Type = 43, // nvarchar2
|
||||
ObNCharType = 44, // nchar
|
||||
ObURowIDType = 45, // UROWID
|
||||
ObLobType = 46, // Oracle Lob
|
||||
ObMaxType // invalid type, or count of obj type
|
||||
} ObObjType;
|
||||
|
||||
enum enum_obcollationtype
|
||||
{
|
||||
CS_TYPE_INVALID = 0,
|
||||
CS_TYPE_GBK_CHINESE_CI = 28,
|
||||
CS_TYPE_UTF8MB4_GENERAL_CI = 45,
|
||||
CS_TYPE_UTF8MB4_BIN = 46,
|
||||
CS_TYPE_UTF16_GENERAL_CI = 54,
|
||||
CS_TYPE_UTF16_BIN = 55,
|
||||
CS_TYPE_BINARY = 63,
|
||||
CS_TYPE_GBK_BIN = 87,
|
||||
CS_TYPE_UTF16_UNICODE_CI = 101,
|
||||
CS_TYPE_UTF8MB4_UNICODE_CI = 224,
|
||||
CS_TYPE_GB18030_CHINESE_CI = 248,
|
||||
CS_TYPE_GB18030_BIN = 249,
|
||||
CS_TYPE_MAX,
|
||||
} ObCollationType;
|
||||
|
||||
enum enum_obcollationlevel
|
||||
{
|
||||
CS_LEVEL_EXPLICIT = 0,
|
||||
CS_LEVEL_NONE = 1,
|
||||
CS_LEVEL_IMPLICIT = 2,
|
||||
CS_LEVEL_SYSCONST = 3,
|
||||
CS_LEVEL_COERCIBLE = 4,
|
||||
CS_LEVEL_NUMERIC = 5,
|
||||
CS_LEVEL_IGNORABLE = 6,
|
||||
CS_LEVEL_INVALID, // here we didn't define CS_LEVEL_INVALID as 0,
|
||||
// since 0 is a valid value for CS_LEVEL_EXPLICIT in mysql 5.6.
|
||||
// fortunately we didn't need to use it to define array like charset_arr,
|
||||
// and we didn't persist it on storage.
|
||||
} ObCollationLevel;
|
||||
|
||||
typedef struct st_obmysqltypemap
|
||||
{
|
||||
/* oceanbase::common::ObObjType ob_type; */
|
||||
enum_field_types mysql_type;
|
||||
uint16_t flags; /* flags if Field */
|
||||
uint64_t length; /* other than varchar type */
|
||||
} ObMySQLTypeMap;
|
||||
|
||||
static const ObMySQLTypeMap type_maps_[ObMaxType] =
|
||||
{
|
||||
/* ObMinType */
|
||||
{MYSQL_TYPE_NULL, BINARY_FLAG, 0}, /* ObNullType */
|
||||
{MYSQL_TYPE_TINY, BINARY_FLAG, 0}, /* ObTinyIntType */
|
||||
{MYSQL_TYPE_SHORT, BINARY_FLAG, 0}, /* ObSmallIntType */
|
||||
{MYSQL_TYPE_INT24, BINARY_FLAG, 0}, /* ObMediumIntType */
|
||||
{MYSQL_TYPE_LONG, BINARY_FLAG, 0}, /* ObInt32Type */
|
||||
{MYSQL_TYPE_LONGLONG, BINARY_FLAG, 0}, /* ObIntType */
|
||||
{MYSQL_TYPE_TINY, BINARY_FLAG | UNSIGNED_FLAG, 0}, /* ObUTinyIntType */
|
||||
{MYSQL_TYPE_SHORT, BINARY_FLAG | UNSIGNED_FLAG, 0}, /* ObUSmallIntType */
|
||||
{MYSQL_TYPE_INT24, BINARY_FLAG | UNSIGNED_FLAG, 0}, /* ObUMediumIntType */
|
||||
{MYSQL_TYPE_LONG, BINARY_FLAG | UNSIGNED_FLAG, 0}, /* ObUInt32Type */
|
||||
{MYSQL_TYPE_LONGLONG, BINARY_FLAG | UNSIGNED_FLAG, 0}, /* ObUInt64Type */
|
||||
{MYSQL_TYPE_FLOAT, BINARY_FLAG, 0}, /* ObFloatType */
|
||||
{MYSQL_TYPE_DOUBLE, BINARY_FLAG, 0}, /* ObDoubleType */
|
||||
{MYSQL_TYPE_FLOAT, BINARY_FLAG | UNSIGNED_FLAG, 0}, /* ObUFloatType */
|
||||
{MYSQL_TYPE_DOUBLE, BINARY_FLAG | UNSIGNED_FLAG, 0}, /* ObUDoubleType */
|
||||
{MYSQL_TYPE_NEWDECIMAL,BINARY_FLAG, 0}, /* ObNumberType */
|
||||
{MYSQL_TYPE_NEWDECIMAL,BINARY_FLAG | UNSIGNED_FLAG, 0}, /* ObUNumberType */
|
||||
{MYSQL_TYPE_DATETIME, BINARY_FLAG, 0}, /* ObDateTimeType */
|
||||
{MYSQL_TYPE_TIMESTAMP, BINARY_FLAG | TIMESTAMP_FLAG, 0}, /* ObTimestampType */
|
||||
{MYSQL_TYPE_DATE, BINARY_FLAG, 0}, /* ObDateType */
|
||||
{MYSQL_TYPE_TIME, BINARY_FLAG, 0}, /* ObTimeType */
|
||||
{MYSQL_TYPE_YEAR, UNSIGNED_FLAG | ZEROFILL_FLAG, 0}, /* ObYearType */
|
||||
{MYSQL_TYPE_VAR_STRING, 0, 0}, /* ObVarcharType */
|
||||
{MYSQL_TYPE_STRING, 0, 0}, /* ObCharType */
|
||||
{MYSQL_TYPE_VAR_STRING,BINARY_FLAG, 0}, /* ObHexStringType */
|
||||
{MAX_NO_FIELD_TYPES, 0, 0}, /* ObExtendType */
|
||||
{MAX_NO_FIELD_TYPES, 0, 0}, /* ObUnknownType */
|
||||
/* ObMaxType */
|
||||
};
|
||||
|
||||
int get_mysql_type(ObObjType ob_type, enum_field_types *mysql_type);
|
||||
|
||||
int get_ob_type(ObObjType *ob_type, enum_field_types mysql_type);
|
||||
|
||||
typedef struct st_obobjmeta
|
||||
{
|
||||
uint8_t type_;
|
||||
uint8_t cs_level_; // collation level
|
||||
uint8_t cs_type_; // collation type
|
||||
int8_t scale_; // scale
|
||||
} ObObjMeta;
|
||||
|
||||
typedef union un_obobjvalue
|
||||
{
|
||||
int64_t int64_;
|
||||
uint64_t uint64_;
|
||||
|
||||
float float_;
|
||||
double double_;
|
||||
|
||||
const char *string_;
|
||||
|
||||
uint32_t *nmb_digits_;
|
||||
|
||||
int64_t datetime_;
|
||||
int32_t date_;
|
||||
int64_t time_;
|
||||
uint8_t year_;
|
||||
|
||||
int64_t ext_;
|
||||
int64_t unknown_;
|
||||
} ObObjValue;
|
||||
|
||||
typedef struct st_obobj
|
||||
{
|
||||
ObObjMeta meta_; // sizeof = 4
|
||||
// union
|
||||
// {
|
||||
// int32_t val_len_;
|
||||
// number::ObNumber::Desc nmb_desc_;
|
||||
// ObOTimestampData::UnionTZCtx time_ctx_;
|
||||
// };
|
||||
int32_t val_len_; // sizeof = 4
|
||||
ObObjValue v_; // sizeof = 8
|
||||
|
||||
} ObObj;
|
||||
|
||||
/* obj serialize/deserialize function */
|
||||
typedef int (*ob_obj_value_serialize)(const ObObj *obj, char *buf, const int64_t buf_len, int64_t *pos);
|
||||
typedef int (*ob_obj_value_deserialize)(ObObj *obj, const char *buf, const int64_t data_len, int64_t *pos);
|
||||
typedef int64_t (*ob_obj_value_get_serialize_size)(const ObObj *obj);
|
||||
|
||||
typedef struct obobjtypefuncs
|
||||
{
|
||||
ob_obj_value_serialize serialize;
|
||||
ob_obj_value_deserialize deserialize;
|
||||
ob_obj_value_get_serialize_size get_serialize_size;
|
||||
} ObObjTypeFuncs;
|
||||
|
||||
|
||||
#define DECLAR_SERIALIZE_FUNCS(OBJTYPE) \
|
||||
int obj_val_serialize_##OBJTYPE(const ObObj *obj, char *buf, const int64_t buf_len, int64_t *pos); \
|
||||
int obj_val_deserialize_##OBJTYPE(ObObj *obj, const char *buf, const int64_t data_len, int64_t *pos); \
|
||||
int64_t obj_val_get_serialize_size_##OBJTYPE(const ObObj *obj); \
|
||||
|
||||
DECLAR_SERIALIZE_FUNCS(ObNullType);
|
||||
// ObTinyIntType=1, // int8, aka mysql boolean type
|
||||
DECLAR_SERIALIZE_FUNCS(ObTinyIntType);
|
||||
// ObSmallIntType=2, // int16
|
||||
DECLAR_SERIALIZE_FUNCS(ObSmallIntType);
|
||||
// ObMediumIntType=3, // int24
|
||||
DECLAR_SERIALIZE_FUNCS(ObMediumIntType);
|
||||
// ObInt32Type=4, // int32
|
||||
DECLAR_SERIALIZE_FUNCS(ObInt32Type);
|
||||
// ObIntType=5, // int64, aka bigint
|
||||
DECLAR_SERIALIZE_FUNCS(ObIntType);
|
||||
// ObUTinyIntType=6, // uint8
|
||||
DECLAR_SERIALIZE_FUNCS(ObUTinyIntType);
|
||||
// ObUSmallIntType=7, // uint16
|
||||
DECLAR_SERIALIZE_FUNCS(ObUSmallIntType);
|
||||
// ObUMediumIntType=8, // uint24
|
||||
DECLAR_SERIALIZE_FUNCS(ObUMediumIntType);
|
||||
// ObUInt32Type=9, // uint32
|
||||
DECLAR_SERIALIZE_FUNCS(ObUInt32Type);
|
||||
// ObUInt64Type=10, // uint64
|
||||
DECLAR_SERIALIZE_FUNCS(ObUInt64Type);
|
||||
// ObFloatType=11, // single-precision floating point
|
||||
DECLAR_SERIALIZE_FUNCS(ObFloatType);
|
||||
// ObDoubleType=12, // double-precision floating point
|
||||
DECLAR_SERIALIZE_FUNCS(ObDoubleType);
|
||||
// ObUFloatType=13, // unsigned single-precision floating point
|
||||
DECLAR_SERIALIZE_FUNCS(ObUFloatType);
|
||||
// ObUDoubleType=14, // unsigned double-precision floating point
|
||||
DECLAR_SERIALIZE_FUNCS(ObUDoubleType);
|
||||
// ObVarcharType=22 // charset: utf8mb4 or binary
|
||||
DECLAR_SERIALIZE_FUNCS(ObVarcharType)
|
||||
|
||||
void set_tinyint(ObObj *obj, const int8_t value);
|
||||
void set_tinyint_value(ObObj *obj, const int8_t value);
|
||||
void set_smallint(ObObj *obj, const int16_t value);
|
||||
void set_smallint_value(ObObj *obj, const int16_t value);
|
||||
void set_mediumint(ObObj *obj, const int32_t value);
|
||||
void set_int32(ObObj *obj, const int32_t value);
|
||||
void set_int32_value(ObObj *obj, const int32_t value);
|
||||
void set_int(ObObj *obj, const int64_t value);
|
||||
void set_int_value(ObObj *obj, const int64_t value);
|
||||
void set_utinyint(ObObj *obj, const uint8_t value);
|
||||
void set_usmallint(ObObj *obj, const uint16_t value);
|
||||
void set_umediumint(ObObj *obj, const uint32_t value);
|
||||
void set_uint32(ObObj *obj, const uint32_t value);
|
||||
void set_uint64(ObObj *obj, const uint64_t value);
|
||||
void set_float(ObObj *obj, const float value);
|
||||
void set_float_value(ObObj *obj, const float value);
|
||||
void set_ufloat(ObObj *obj, const float value);
|
||||
void set_double(ObObj *obj, const double value);
|
||||
void set_double_value(ObObj *obj, const double value);
|
||||
void set_udouble(ObObj *obj, const double value);
|
||||
void set_varchar(ObObj *obj, const char *ptr, int32_t size);
|
||||
|
||||
int serialize_ObObj(const ObObj *obj, char *buf, const int64_t buf_len, int64_t *pos);
|
||||
int deserialize_ObObj(ObObj *obj, const char *buf, const int64_t data_len, int64_t *pos);
|
||||
int64_t get_serialize_size_ObObj(const ObObj *obj);
|
||||
#endif
|
||||
244
include/ob_oralce_format_models.h
Normal file
244
include/ob_oralce_format_models.h
Normal file
@ -0,0 +1,244 @@
|
||||
/************************************************************************
|
||||
Copyright (c) 2021 OceanBase.
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
MA 02111-1301, USA
|
||||
|
||||
Part of this code includes code from PHP's mysqlnd extension
|
||||
(written by Andrey Hristov, Georg Richter and Ulf Wendel), freely
|
||||
available from http://www.php.net/software
|
||||
|
||||
*************************************************************************/
|
||||
#include "mysql.h"
|
||||
#include <stdint.h>
|
||||
|
||||
#define DATE_PART_CNT 3
|
||||
#define TIME_PART_CNT 4
|
||||
#define OTHER_PART_CNT 4
|
||||
#define DATETIME_PART_CNT (DATE_PART_CNT + TIME_PART_CNT)
|
||||
#define ORACLE_DATE_PART_CNT (DATE_PART_CNT + TIME_PART_CNT - 1)
|
||||
#define TOTAL_PART_CNT (DATETIME_PART_CNT + OTHER_PART_CNT)
|
||||
#define DT_YEAR 0
|
||||
#define DT_MON 1
|
||||
#define DT_MDAY 2
|
||||
|
||||
#define DT_HOUR 3
|
||||
#define DT_MIN 4
|
||||
#define DT_SEC 5
|
||||
#define DT_USEC 6
|
||||
|
||||
#define DT_DATE 7
|
||||
#define DT_YDAY 8
|
||||
#define DT_WDAY 9
|
||||
#define DT_OFFSET_MIN 10
|
||||
|
||||
#define OB_MAX_TZ_ABBR_LEN 32
|
||||
#define OB_MAX_TZ_NAME_LEN 64
|
||||
|
||||
//18446744073709551615
|
||||
#define MAX_UINT64_STR_LEN 20
|
||||
#define MAX_DIGITS10_STR_SIZE MAX_UINT64_STR_LEN + 3
|
||||
|
||||
#define DT_TYPE_DATE (1UL << 0)
|
||||
#define DT_TYPE_TIME (1UL << 1)
|
||||
#define DT_WEEK_SUN_BEGIN (1UL << 5) // sunday is the first day of week, otherwise monday.
|
||||
#define DT_WEEK_ZERO_BEGIN (1UL << 6) // week num will begin with 0, otherwise 1.
|
||||
#define DT_WEEK_GE_4_BEGIN (1UL << 7) // week which has 4 or more days is week 1, otherwise has
|
||||
#define DT_TYPE_ORACLE (1UL << 8) //oracle timestamp to nanosecond (nano, tz, ltz)
|
||||
// the first sunday of monday.
|
||||
#define DT_TYPE_TIMEZONE (1UL << 10) //oracle timestamp with time zone (tz)
|
||||
|
||||
#define DT_TYPE_DATETIME (DT_TYPE_DATE | DT_TYPE_TIME)
|
||||
|
||||
#define IS_SUN_BEGIN(mode) ((DT_WEEK_SUN_BEGIN & (mode)) ? 1 : 0)
|
||||
#define IS_ZERO_BEGIN(mode) ((DT_WEEK_ZERO_BEGIN & (mode)) ? 1 : 0)
|
||||
#define IS_GE_4_BEGIN(mode) ((DT_WEEK_GE_4_BEGIN & (mode)) ? 1 : 0)
|
||||
#define HAS_TYPE_ORACLE(mode) ((DT_TYPE_ORACLE & (mode)) ? 1 : 0)
|
||||
#define HAS_TYPE_TIMEZONE(mode) ((DT_TYPE_TIMEZONE & (mode)) ? 1 : 0)
|
||||
|
||||
#define DAYS_PER_WEEK 7
|
||||
#define MONS_PER_YEAR 12
|
||||
#define SECS_PER_MIN 60
|
||||
#define MINS_PER_HOUR 60
|
||||
|
||||
typedef uint64_t ObDTMode;
|
||||
|
||||
enum ElementFlag
|
||||
{
|
||||
INVALID_FLAG = -1,
|
||||
AD = 0,
|
||||
AD2, //A.D.
|
||||
BC,
|
||||
BC2, //B.C.
|
||||
CC,
|
||||
SCC,
|
||||
D,
|
||||
DAY,
|
||||
DD,
|
||||
DDD,
|
||||
DY,
|
||||
FF1,
|
||||
FF2,
|
||||
FF3,
|
||||
FF4,
|
||||
FF5,
|
||||
FF6,
|
||||
FF7,
|
||||
FF8,
|
||||
FF9,
|
||||
FF,
|
||||
HH,
|
||||
HH24,
|
||||
HH12,
|
||||
IW,
|
||||
I,
|
||||
IY,
|
||||
IYY,
|
||||
IYYY,
|
||||
MI,
|
||||
MM,
|
||||
MONTH,
|
||||
MON,
|
||||
AM,
|
||||
AM2, //A.M.
|
||||
PM,
|
||||
PM2, //P.M.
|
||||
Q,
|
||||
RR,
|
||||
RRRR,
|
||||
SS,
|
||||
SSSSS,
|
||||
WW,
|
||||
W,
|
||||
YGYYY,
|
||||
YEAR,
|
||||
SYEAR,
|
||||
YYYY,
|
||||
SYYYY,
|
||||
YYY,
|
||||
YY,
|
||||
Y,
|
||||
DS,
|
||||
DL,
|
||||
TZH,
|
||||
TZM,
|
||||
TZD,
|
||||
TZR,
|
||||
X,
|
||||
J,
|
||||
///<<< !!!add any flag before this line!!!
|
||||
MAX_FLAG_NUMBER
|
||||
};
|
||||
|
||||
enum ElementGroup
|
||||
{
|
||||
RUNTIME_CONFLICT_SOLVE_GROUP = -2,
|
||||
NON_CONFLICT_GROUP = -1,
|
||||
///<<< conflict in group, before this line, will be ignored
|
||||
NEVER_APPEAR_GROUP = 0, //the element should never appear
|
||||
YEAR_GROUP, //include : SYYYY YYYY YYY YY Y YGYYY RR RRRR
|
||||
MERIDIAN_INDICATOR_GROUP, //include : AM PM
|
||||
WEEK_OF_DAY_GROUP, //include : D Day Dy
|
||||
ERA_GROUP, //include : AD BC
|
||||
HOUR_GROUP, //include : HH HH12 HH24
|
||||
MONTH_GROUP, //include : MONTH MON MM
|
||||
DAY_OF_YEAR_GROUP, //include : DDD, J
|
||||
///<<< !!!add any flag before this line!!!
|
||||
MAX_CONFLICT_GROUP_NUMBER
|
||||
};
|
||||
|
||||
struct ObTimeConstStr {
|
||||
const char *ptr_;
|
||||
int32_t len_;
|
||||
};
|
||||
|
||||
struct ObDFMParseCtx
|
||||
{
|
||||
const char* fmt_str_;
|
||||
const char* cur_ch_;
|
||||
int64_t remain_len_;
|
||||
|
||||
//the following values are only used in function str_to_ob_time_oracle_dfm
|
||||
int64_t expected_elem_flag_;
|
||||
my_bool is_matching_by_expected_len_; //only used for match_int_value
|
||||
};
|
||||
|
||||
enum UpperCaseMode {
|
||||
NON_CHARACTER,
|
||||
ONLY_FIRST_CHARACTER,
|
||||
ALL_CHARACTER
|
||||
};
|
||||
|
||||
struct ObDFMElem
|
||||
{
|
||||
int64_t elem_flag_; //flag from enum ObDFMFlag
|
||||
int64_t offset_; //offset in origin format string
|
||||
my_bool is_single_dot_before_; //for the dot before FF
|
||||
enum UpperCaseMode upper_case_mode_;
|
||||
};
|
||||
|
||||
struct ObTime
|
||||
{
|
||||
uint64_t mode_;
|
||||
int32_t parts_[TOTAL_PART_CNT];
|
||||
// year: [1000, 9999].
|
||||
// month: [1, 12].
|
||||
// day: [1, 31].
|
||||
// hour: [0, 23] or [0, 838] if it is a time.
|
||||
// minute: [0, 59].
|
||||
// second: [0, 59].
|
||||
// usecond: [0, 1000000], 1000000 can only valid after str_to_ob_time, for round.
|
||||
// nanosecond: [0, 1000000000], when HAS_TYPE_ORACLE(mode_)
|
||||
// date: date value, day count since 1970-1-1.
|
||||
// year day: [1, 366].
|
||||
// week day: [1, 7], 1 means monday, 7 means sunday.
|
||||
// offset minute: [-12*60, 14*60].
|
||||
|
||||
char tz_name_[OB_MAX_TZ_NAME_LEN];
|
||||
char tzd_abbr_[OB_MAX_TZ_ABBR_LEN];//the abbr of time zone region with Daylight Saving Time
|
||||
int32_t time_zone_id_;
|
||||
uint8_t nano_scale_;
|
||||
my_bool is_tz_name_valid_;
|
||||
};
|
||||
|
||||
struct ObFastFormatInt
|
||||
{
|
||||
char buf_[MAX_DIGITS10_STR_SIZE];
|
||||
char *ptr_;
|
||||
int64_t len_;
|
||||
};
|
||||
|
||||
struct ObOracleTimeLimiter
|
||||
{
|
||||
int32_t MIN;
|
||||
int32_t MAX;
|
||||
int ERROR_CODE;
|
||||
};
|
||||
longlong strtoll10(const char *nptr, char **endptr, int *error);
|
||||
int calculate_str_oracle_dfm_length(const struct ObTime *ob_time,
|
||||
const char *fmt_str, const int64_t fmt_len,
|
||||
int16_t scale, int64_t *len);
|
||||
|
||||
int ob_time_to_str_oracle_dfm(const struct ObTime *ob_time,
|
||||
const char *fmt_str, const int64_t fmt_len,
|
||||
int16_t scale,
|
||||
char *buf, int64_t buf_len,
|
||||
int64_t *pos);
|
||||
|
||||
int32_t ob_time_to_date(struct ObTime *ob_time);
|
||||
|
||||
int str_to_ob_time_oracle_dfm(const char *str, const int64_t str_len,
|
||||
const char *fmt_str, const int64_t fmt_len,
|
||||
struct ObTime *ob_time,
|
||||
int16_t scale);
|
||||
155
include/ob_protocol20.h
Normal file
155
include/ob_protocol20.h
Normal file
@ -0,0 +1,155 @@
|
||||
/*
|
||||
Copyright (c) 2000, 2018, Oracle and/or its affiliates.
|
||||
Copyright (c) 2009, 2019, MariaDB Corporation.
|
||||
Copyright (c) 2021 OceanBase.
|
||||
|
||||
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; version 2 of the License.
|
||||
|
||||
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, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */
|
||||
#ifndef _OB_PROTOCOL20_H
|
||||
#define _OB_PROTOCOL20_H
|
||||
|
||||
#include <ma_global.h>
|
||||
#include <mysql.h>
|
||||
#include <mariadb_ctype.h>
|
||||
#include <mariadb_dyncol.h>
|
||||
#include <stdint.h>
|
||||
#include <ma_list.h>
|
||||
#include <ob_object.h>
|
||||
#include <ob_full_link_trace.h>
|
||||
|
||||
|
||||
#define DEFINE_OB20_EXTRAINFO_SERIALIZE_FUNC(type) \
|
||||
int extrainfo_serialize_##type(char *buf, const int64_t len, int64_t *pos, void *data); \
|
||||
int extrainfo_deserialize_##type(const char *buf, const int64_t len, int64_t *pos, void *data, const int64_t v_len);\
|
||||
int64_t extrainfo_get_serialize_size_##type(void *data)
|
||||
|
||||
#define OB20_EXTRAINFO_SERIALIZE_FUNC(type) \
|
||||
{ \
|
||||
extrainfo_serialize_##type, \
|
||||
extrainfo_deserialize_##type, \
|
||||
extrainfo_get_serialize_size_##type \
|
||||
}
|
||||
|
||||
typedef union st_ob20protocol_flags
|
||||
{
|
||||
uint32_t flags;
|
||||
struct Protocol20Flags
|
||||
{
|
||||
uint32_t OB_EXTRA_INFO_EXIST: 1;
|
||||
uint32_t OB_IS_LAST_PACKET: 1;
|
||||
uint32_t OB_IS_PROXY_REROUTE: 1;
|
||||
uint32_t OB_IS_NEW_EXTRA_INFO: 1;
|
||||
uint32_t OB_FLAG_RESERVED_NOT_USE: 28;
|
||||
} st_flags;
|
||||
} Ob20ProtocolFlags;
|
||||
|
||||
typedef struct st_ob20protocol_header
|
||||
{
|
||||
uint16_t magic_num;
|
||||
uint16_t version;
|
||||
uint32_t connection_id;
|
||||
uint32_t request_id;
|
||||
uint8_t pkt_seq;
|
||||
uint32_t payload_len;
|
||||
Ob20ProtocolFlags flag;
|
||||
uint16_t reserved;
|
||||
uint16_t header_checksum;
|
||||
} Ob20ProtocolHeader;
|
||||
|
||||
typedef struct st_ob20protocol_extra_info_list
|
||||
{
|
||||
LIST *list,
|
||||
*current;
|
||||
} Ob20ProtocolExtraInfoList;
|
||||
|
||||
/**
|
||||
0 ~ 999用于ob driver 私有
|
||||
1001~1999用于ob proxy私有
|
||||
2001~65535用于server, driver, proxy共有
|
||||
*/
|
||||
typedef enum em_extrainfokeytype {
|
||||
OB20_DRIVER_END = 1000,
|
||||
OB20_PROXY_END = 2000,
|
||||
TRACE_INFO = 2001,
|
||||
SESS_INFO = 2002,
|
||||
FULL_TRC = 2003,
|
||||
OB20_SVR_END,
|
||||
} ExtraInfoKeyType;
|
||||
|
||||
typedef struct st_ob20protocol_extra_info
|
||||
{
|
||||
ExtraInfoKeyType key;
|
||||
void *value;
|
||||
} Ob20ProtocolExtraInfo;
|
||||
|
||||
typedef struct st_ob20protocol
|
||||
{
|
||||
Ob20ProtocolHeader header;
|
||||
Ob20ProtocolExtraInfoList extra_info_list;
|
||||
unsigned int checksum;
|
||||
|
||||
// ma_net write buffer
|
||||
uchar *real_write_buffer;
|
||||
uint32_t real_write_buffer_length;
|
||||
|
||||
// extra info
|
||||
FLTInfo *flt; // full link trace
|
||||
} Ob20Protocol;
|
||||
|
||||
typedef int (*extrainfo_serialize_func)(char *buf, const int64_t len, int64_t *pos, void *data);
|
||||
typedef int (*extrainfo_deserialize_func)(const char *buf, const int64_t len, int64_t *pos, void *data, const int64_t v_len);
|
||||
typedef int64_t (*extrainfo_get_serialize_size_func)(void *data);
|
||||
|
||||
typedef struct st_extrainfo_serialize_func
|
||||
{
|
||||
extrainfo_serialize_func serialize_func;
|
||||
extrainfo_deserialize_func deserialize_func;
|
||||
extrainfo_get_serialize_size_func get_serialize_size_func;
|
||||
} ExtraInfoSerializeFunc;
|
||||
|
||||
DEFINE_OB20_EXTRAINFO_SERIALIZE_FUNC(flt); // full link trace
|
||||
|
||||
void update_request_id(uint32_t *request_id);
|
||||
|
||||
int ob20_init(Ob20Protocol *ob20protocol, unsigned long conid, my_bool use_flt);
|
||||
void ob20_end(Ob20Protocol *ob20protocol);
|
||||
|
||||
void clear_extra_info(Ob20Protocol *ob20protocol);
|
||||
|
||||
size_t get_protocol20_extra_info_length(Ob20Protocol *ob20protocol);
|
||||
|
||||
uchar *fill_protocol20_extra_info(Ob20Protocol *ob20protocol, uchar *buffer, size_t buffer_len);
|
||||
|
||||
void init_protocol20_header(Ob20Protocol *ob20protocol);
|
||||
|
||||
void update_protocol20_header(Ob20Protocol *ob20protocol);
|
||||
|
||||
uchar *fill_protocol20_header(Ob20Protocol *ob20protocol, size_t len, size_t pkt_nr, size_t complen,uchar *buffer);
|
||||
|
||||
int decode_protocol20_header(Ob20Protocol *ob20protocol, uchar *buffer, uint32_t pkt_len, uint32_t pkt_nr, uint32_t complen);
|
||||
|
||||
int decode_protocol20_extra_info(Ob20Protocol *ob20protocol, uchar *buffer);
|
||||
|
||||
int ob20_set_extra_info(MYSQL *mysql, ExtraInfoKeyType key, void *value);
|
||||
|
||||
int flt_set_module(MYSQL *mysql, const char *module_name);
|
||||
int flt_set_action(MYSQL *mysql, const char *action_name);
|
||||
int flt_set_client_info(MYSQL *mysql, const char *client_info);
|
||||
int flt_set_identifier(MYSQL *mysql, const char *identifier);
|
||||
|
||||
int flt_get_control_level(MYSQL *mysql, int *level);
|
||||
int flt_get_control_sample_pct(MYSQL *mysql, double *sample_pct);
|
||||
int flt_get_control_record_policy(MYSQL *mysql, int *rp);
|
||||
int flt_get_control_print_spct(MYSQL *mysql, double *sample_pct);
|
||||
int flt_get_control_slow_threshold(MYSQL *mysql, long int *slow_threshold);
|
||||
#endif
|
||||
87
include/ob_rwlock.h
Normal file
87
include/ob_rwlock.h
Normal file
@ -0,0 +1,87 @@
|
||||
/************************************************************************
|
||||
Copyright (c) 2021 OceanBase.
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
MA 02111-1301, USA
|
||||
|
||||
Part of this code includes code from PHP's mysqlnd extension
|
||||
(written by Andrey Hristov, Georg Richter and Ulf Wendel), freely
|
||||
available from http://www.php.net/software
|
||||
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef _OB_RWLOCK_H
|
||||
#define _OB_RWLOCK_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
|
||||
typedef CRITICAL_SECTION ob_mutex_t;
|
||||
typedef int ob_mutexattr_t;
|
||||
typedef struct st_my_rw_lock_t
|
||||
{
|
||||
SRWLOCK ob_srwlock;
|
||||
BOOL is_exclusive;
|
||||
} ob_rw_lock_t;
|
||||
#define OB_RW_INITIALIZER {SRWLOCK_INIT, FALSE}
|
||||
#else
|
||||
#include <pthread.h>
|
||||
typedef pthread_mutexattr_t ob_mutexattr_t;
|
||||
typedef pthread_mutex_t ob_mutex_t;
|
||||
typedef pthread_rwlock_t ob_rw_lock_t;
|
||||
#define OB_RW_INITIALIZER PTHREAD_RWLOCK_INITIALIZER
|
||||
#endif
|
||||
typedef ob_mutex_t native_mutex_t;
|
||||
typedef ob_mutexattr_t native_mutexattr_t;
|
||||
typedef ob_rw_lock_t native_rw_lock_t;
|
||||
|
||||
#ifndef NATIVE_RW_INITIALIZER
|
||||
#define NATIVE_RW_INITIALIZER OB_RW_INITIALIZER
|
||||
#endif
|
||||
/* Compatible with previous functions */
|
||||
#define native_mutex_init ob_mutex_init
|
||||
#define native_mutex_lock ob_mutex_lock
|
||||
#define native_mutex_trylock ob_mutex_trylock
|
||||
#define native_mutex_unlock ob_mutex_unlock
|
||||
#define native_mutex_destroy ob_mutex_destroy
|
||||
#define native_rw_init ob_rw_init
|
||||
#define native_rw_rdlock ob_rw_rdlock
|
||||
#define native_rw_tryrdlock ob_rw_tryrdlock
|
||||
#define native_rw_wrlock ob_rw_wrlock
|
||||
#define native_rw_trywrlock ob_rw_trywrlock
|
||||
#define native_rw_destroy ob_rw_destroy
|
||||
#define native_rw_unlock ob_rw_unlock
|
||||
|
||||
int ob_mutex_init(ob_mutex_t *mutex, const ob_mutexattr_t *attr);
|
||||
int ob_mutex_lock(ob_mutex_t *mutex);
|
||||
int ob_mutex_trylock(ob_mutex_t *mutex);
|
||||
int ob_mutex_unlock(ob_mutex_t *mutex);
|
||||
int ob_mutex_destroy(ob_mutex_t *mutex);
|
||||
int ob_rw_init(ob_rw_lock_t *rwp);
|
||||
int ob_rw_destroy(ob_rw_lock_t *rwp);
|
||||
int ob_rw_rdlock(ob_rw_lock_t *rwp);
|
||||
int ob_rw_tryrdlock(ob_rw_lock_t *rwp);
|
||||
int ob_rw_wrlock(ob_rw_lock_t *rwp);
|
||||
int ob_rw_trywrlock(ob_rw_lock_t *rwp);
|
||||
int ob_rw_unlock(ob_rw_lock_t *rwp);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
151
include/ob_serialize.h
Normal file
151
include/ob_serialize.h
Normal file
@ -0,0 +1,151 @@
|
||||
/*
|
||||
Copyright (c) 2000, 2018, Oracle and/or its affiliates.
|
||||
Copyright (c) 2009, 2019, MariaDB Corporation.
|
||||
Copyright (c) 2021 OceanBase.
|
||||
|
||||
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; version 2 of the License.
|
||||
|
||||
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, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */
|
||||
|
||||
#ifndef _ob_serialize_h
|
||||
#define _ob_serialize_h
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "ma_global.h"
|
||||
|
||||
|
||||
inline int encode_i64(char *buf, const int64_t buf_len, int64_t *ppos, int64_t val);
|
||||
inline int decode_i64(const char *buf, const int64_t data_len, int64_t *ppos, int64_t *val);
|
||||
|
||||
inline int64_t encoded_length_vi64(int64_t val);
|
||||
|
||||
/**
|
||||
* @brief Encode a integer (up to 64bit) in variable length encoding
|
||||
*
|
||||
* @param buf pointer to the destination buffer
|
||||
* @param end the end pointer to the destination buffer
|
||||
* @param val value to encode
|
||||
*
|
||||
* @return true - success, false - failed
|
||||
*/
|
||||
inline int encode_vi64(char *buf, const int64_t buf_len, int64_t *ppos, int64_t val);
|
||||
|
||||
inline int decode_vi64(const char *buf, const int64_t data_len, int64_t *ppos, int64_t *val);
|
||||
|
||||
inline int64_t encoded_length_vi32(int32_t val);
|
||||
|
||||
/**
|
||||
* @brief Encode a integer (up to 32bit) in variable length encoding
|
||||
*
|
||||
* @param buf pointer to the destination buffer
|
||||
* @param end the end pointer to the destination buffer
|
||||
* @param val value to encode
|
||||
*
|
||||
* @return true - success, false - failed
|
||||
*/
|
||||
|
||||
inline int encode_vi32(char *buf, const int64_t buf_len, int64_t *ppos, int32_t val);
|
||||
|
||||
inline int decode_vi32(const char *buf, const int64_t data_len, int64_t *ppos, int32_t *val);
|
||||
|
||||
inline int encode_i8(char *buf, const int64_t buf_len, int64_t *ppos, int8_t val);
|
||||
|
||||
inline int decode_i8(const char *buf, const int64_t data_len, int64_t *ppos, int8_t *val);
|
||||
|
||||
inline int encode_int64_t(char *buf, const int64_t buf_len, int64_t *pos, int64_t val);
|
||||
inline int encode_uint64_t(char *buf, const int64_t buf_len, int64_t *pos, uint64_t val);
|
||||
inline int encode_int32_t(char *buf, const int64_t buf_len, int64_t *pos, int32_t val);
|
||||
inline int encode_uint32_t(char *buf, const int64_t buf_len, int64_t *pos, uint32_t val);
|
||||
inline int encode_int16_t(char *buf, const int64_t buf_len, int64_t *pos, int16_t val);
|
||||
inline int encode_uint16_t(char *buf, const int64_t buf_len, int64_t *pos, uint16_t val);
|
||||
inline int encode_int8_t(char *buf, const int64_t buf_len, int64_t *pos, int8_t val);
|
||||
inline int encode_uint8_t(char *buf, const int64_t buf_len, int64_t *pos, uint8_t val);
|
||||
|
||||
inline int decode_int8_t(const char *buf, const int64_t data_len, int64_t *pos, int8_t *val);
|
||||
inline int decode_uint8_t(const char *buf, const int64_t data_len, int64_t *pos, uint8_t *val);
|
||||
inline int decode_int16_t(const char *buf, const int64_t data_len, int64_t *pos, int16_t *val);
|
||||
inline int decode_uint16_t(const char *buf, const int64_t data_len, int64_t *pos, uint16_t *val);
|
||||
inline int decode_int32_t(const char *buf, const int64_t data_len, int64_t *pos, int32_t *val);
|
||||
inline int decode_uint32_t(const char *buf, const int64_t data_len, int64_t *pos, uint32_t *val);
|
||||
inline int decode_int64_t(const char *buf, const int64_t data_len, int64_t *pos, int64_t *val);
|
||||
inline int decode_uint64_t(const char *buf, const int64_t data_len, int64_t *pos, uint64_t *val);
|
||||
|
||||
inline int64_t encoded_length_int64_t(int64_t val);
|
||||
inline int64_t encoded_length_uint64_t(uint64_t val);
|
||||
inline int64_t encoded_length_int32_t(int32_t val);
|
||||
inline int64_t encoded_length_uint32_t(uint32_t val);
|
||||
inline int64_t encoded_length_int16_t(int16_t val);
|
||||
inline int64_t encoded_length_uint16_t(uint16_t val);
|
||||
inline int64_t encoded_length_int8_t(int8_t unused);
|
||||
inline int64_t encoded_length_uint8_t(uint8_t unused);
|
||||
|
||||
inline int64_t encoded_length_float(float val);
|
||||
inline int encode_float(char *buf, const int64_t buf_len, int64_t *pos, float val);
|
||||
inline int decode_float(const char *buf, const int64_t data_len, int64_t *pos, float *val);
|
||||
inline int64_t encoded_length_double(double val);
|
||||
inline int encode_double(char *buf, const int64_t buf_len, int64_t *pos, double val);
|
||||
inline int decode_double(const char *buf, const int64_t data_len, int64_t *pos, double *val);
|
||||
|
||||
/**
|
||||
* @brief Computes the encoded length of vstr(int64,data,null)
|
||||
*
|
||||
* @param len string length
|
||||
*
|
||||
* @return the encoded length of str
|
||||
*/
|
||||
inline int64_t encoded_length_vstr_with_len(int64_t len);
|
||||
inline int64_t encoded_length_vstr(const char *str);
|
||||
|
||||
/**
|
||||
* @brief get the decoded length of data len of vstr
|
||||
* won't change the pos
|
||||
* @return the length of data
|
||||
*/
|
||||
inline int64_t decoded_length_vstr(const char *buf, const int64_t data_len, int64_t pos);
|
||||
|
||||
/**
|
||||
* @brief Encode a buf as vstr(int64,data,null)
|
||||
*
|
||||
* @param buf pointer to the destination buffer
|
||||
* @param vbuf pointer to the start of the input buffer
|
||||
* @param len length of the input buffer
|
||||
*/
|
||||
inline int encode_vstr_with_len(char *buf, const int64_t buf_len, int64_t *ppos, const void *vbuf,
|
||||
int64_t len);
|
||||
|
||||
inline int encode_vstr(char *buf, const int64_t buf_len, int64_t *ppos, const char *s);
|
||||
|
||||
inline const char *decode_vstr_nocopy(const char *buf, const int64_t data_len, int64_t *ppos, int64_t *lenp);
|
||||
|
||||
inline const char *decode_vstr(const char *buf, const int64_t data_len, int64_t *ppos,
|
||||
char *dest, int64_t buf_len, int64_t *lenp);
|
||||
|
||||
#define OB_UNIS_ENCODE(obj, type) \
|
||||
if (OB_SUCC(ret)) { \
|
||||
if (OB_FAIL(encode_##type(buf, buf_len, pos, obj))) { \
|
||||
} \
|
||||
}
|
||||
|
||||
#define OB_UNIS_DECODE(obj, type) \
|
||||
if (OB_SUCC(ret) && *pos < data_len) { \
|
||||
if (OB_FAIL(decode_##type(buf, data_len, pos, &obj))) { \
|
||||
} \
|
||||
}
|
||||
|
||||
#define OB_UNIS_ADD_LEN(obj, type) \
|
||||
len += encoded_length_##type(obj)
|
||||
|
||||
#endif
|
||||
115
include/ob_thread.h
Normal file
115
include/ob_thread.h
Normal file
@ -0,0 +1,115 @@
|
||||
/************************************************************************
|
||||
Copyright (c) 2021 OceanBase.
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
MA 02111-1301, USA
|
||||
|
||||
Part of this code includes code from PHP's mysqlnd extension
|
||||
(written by Andrey Hristov, Georg Richter and Ulf Wendel), freely
|
||||
available from http://www.php.net/software
|
||||
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef _OB_THREAD_H
|
||||
#define _OB_THREAD_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#define NATIVE_RW_INITIALIZER {SRWLOCK_INIT, FALSE}
|
||||
#include <windows.h>
|
||||
//#include <WinSock2.h>
|
||||
//#include <shlwapi.h>
|
||||
#else
|
||||
#include <pthread.h>
|
||||
#ifndef NATIVE_RW_INITIALIZER
|
||||
#define NATIVE_RW_INITIALIZER PTHREAD_RWLOCK_INITIALIZER
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Compatible with previous thread defines*/
|
||||
#define MY_THREAD_CREATE_JOINABLE OB_THREAD_CREATE_JOINABLE
|
||||
#define MY_THREAD_CREATE_DETACHED OB_THREAD_CREATE_DETACHED
|
||||
#define MY_THREAD_ONCE_INIT OB_THREAD_ONCE_INIT
|
||||
#define MY_THREAD_ONCE_INPREGRESS OB_THREAD_ONCE_INPROGRESS
|
||||
#define MY_THREAD_ONCE_DONE OB_THREAD_ONCE_DONE
|
||||
#define my_thread_self ob_thread_self
|
||||
|
||||
#ifdef _WIN32
|
||||
typedef DWORD ob_thread_t;
|
||||
typedef volatile LONG ob_thread_once_t;
|
||||
typedef struct thread_attr
|
||||
{
|
||||
DWORD ob_thread_stack_size;
|
||||
int ob_thead_state;
|
||||
} ob_thread_attr_t;
|
||||
|
||||
typedef void * (__cdecl *ob_start_routine)(void *);
|
||||
|
||||
struct ob_thread_start_param
|
||||
{
|
||||
ob_start_routine func;
|
||||
void *arg;
|
||||
};
|
||||
|
||||
unsigned int __stdcall ob_win_thread_start(void *p);
|
||||
#define OB_THREAD_CREATE_JOINABLE 0
|
||||
#define OB_THREAD_CREATE_DETACHED 1
|
||||
#define OB_THREAD_ONCE_INIT 0
|
||||
#define OB_THREAD_ONCE_INPROGRESS 1
|
||||
#define OB_THREAD_ONCE_DONE 2
|
||||
#else
|
||||
typedef pthread_once_t ob_thread_once_t;
|
||||
typedef pthread_t ob_thread_t;
|
||||
typedef pthread_attr_t ob_thread_attr_t;
|
||||
#define OB_THREAD_CREATE_JOINABLE PTHREAD_CREATE_JOINABLE
|
||||
#define OB_THREAD_CREATE_DETACHED PTHREAD_CREATE_DETACHED
|
||||
typedef void *(*ob_start_routine)(void *);
|
||||
#define OB_THREAD_ONCE_INIT PTHREAD_ONCE_INIT
|
||||
#endif
|
||||
|
||||
typedef ob_thread_once_t my_thread_once_t;
|
||||
typedef ob_thread_t my_thread_t;
|
||||
typedef ob_thread_attr_t my_thread_attr_t;
|
||||
|
||||
typedef struct st_ob_thread_handle
|
||||
{
|
||||
#ifdef _WIN32
|
||||
HANDLE handle;
|
||||
#endif
|
||||
ob_thread_t thread;
|
||||
} ob_thread_handle;
|
||||
|
||||
ob_thread_t ob_thread_self();
|
||||
|
||||
int ob_thread_equal(ob_thread_t ob_thread1, ob_thread_t ob_thread2);
|
||||
int ob_thread_attr_init(ob_thread_attr_t *ob_thread_attr);
|
||||
int ob_thread_attr_destroy(ob_thread_attr_t *ob_thread_attr);
|
||||
int ob_thread_attr_setstacksize(ob_thread_attr_t *ob_thread_attr, size_t ob_stacksize);
|
||||
int ob_thread_attr_setdetachstate(ob_thread_attr_t *ob_thread_attr, int ob_detachstate);
|
||||
int ob_thread_attr_getstacksize(ob_thread_attr_t *ob_thread_attr, size_t *ob_stacksize);
|
||||
void ob_thread_yield();
|
||||
|
||||
int ob_thread_once(ob_thread_once_t *ob_once_control, void (*ob_routine)(void));
|
||||
int ob_thread_create(ob_thread_handle *ob_thread, const ob_thread_attr_t *ob_thread_attr, ob_start_routine ob_thread_func, void *ob_thread_arg);
|
||||
int ob_thread_join(ob_thread_handle *ob_thread, void **ob_join_ptr);
|
||||
int ob_thread_cancel(ob_thread_handle *ob_thread);
|
||||
void ob_thread_exit(void *ob_thread_exit_ptr);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
48
include/ob_thread_key.h
Normal file
48
include/ob_thread_key.h
Normal file
@ -0,0 +1,48 @@
|
||||
/************************************************************************
|
||||
Copyright (c) 2021 OceanBase.
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
MA 02111-1301, USA
|
||||
|
||||
Part of this code includes code from PHP's mysqlnd extension
|
||||
(written by Andrey Hristov, Georg Richter and Ulf Wendel), freely
|
||||
available from http://www.php.net/software
|
||||
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef _OB_THREAD_KEY_H
|
||||
#define _OB_THREAD_KEY_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
typedef DWORD ob_thread_key_t;
|
||||
#else
|
||||
#include <pthread.h>
|
||||
typedef pthread_key_t ob_thread_key_t;
|
||||
#endif
|
||||
|
||||
int ob_create_thread_key(ob_thread_key_t *ob_key, void (*ob_destructor)(void *));
|
||||
int ob_delete_thread_key(ob_thread_key_t ob_key);
|
||||
void *ob_get_thread_key(ob_thread_key_t ob_key);
|
||||
int ob_set_thread_key(ob_thread_key_t ob_key, void *value);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@ -56,6 +56,7 @@ SET(MYSQL_LIB_SYMBOLS
|
||||
mysql_fetch_field
|
||||
mysql_fetch_field_direct
|
||||
mysql_fetch_fields
|
||||
mysql_fetch_params
|
||||
mysql_fetch_lengths
|
||||
mysql_fetch_row
|
||||
mysql_field_count
|
||||
@ -131,8 +132,22 @@ SET(MYSQL_LIB_SYMBOLS
|
||||
mysql_stmt_errno
|
||||
mysql_stmt_error
|
||||
mysql_stmt_execute
|
||||
get_support_send_fetch_flag
|
||||
get_support_plarray_bindbyname
|
||||
get_use_prepare_execute
|
||||
get_use_preapre_execute
|
||||
mysql_stmt_prepare_v2
|
||||
mysql_stmt_execute_v2
|
||||
has_added_user_fields
|
||||
is_returning_result
|
||||
stmt_pre_exe_req_ext_flag_set
|
||||
is_pl_out_result
|
||||
ob_time_to_date
|
||||
mysql_stmt_fetch
|
||||
mysql_stmt_fetch_column
|
||||
mysql_stmt_fetch_oracle_cursor
|
||||
mysql_stmt_fetch_oracle_implicit_cursor
|
||||
mysql_stmt_fetch_oracle_buffered_result
|
||||
mysql_stmt_field_count
|
||||
mysql_stmt_free_result
|
||||
mysql_stmt_init
|
||||
@ -148,6 +163,8 @@ SET(MYSQL_LIB_SYMBOLS
|
||||
mysql_stmt_row_seek
|
||||
mysql_stmt_row_tell
|
||||
mysql_stmt_send_long_data
|
||||
mysql_stmt_send_piece_data
|
||||
mysql_stmt_read_piece_data
|
||||
mysql_stmt_sqlstate
|
||||
mysql_stmt_store_result
|
||||
mysql_store_result
|
||||
@ -255,6 +272,71 @@ SET(MARIADB_NONBLOCK_SYMBOLS
|
||||
mysql_stmt_store_result_start
|
||||
mysql_store_result_cont
|
||||
mysql_store_result_start
|
||||
#oci use
|
||||
skip_param_complex
|
||||
convert_type_to_complex
|
||||
ob_time_to_date
|
||||
ob_time_to_str_oracle_dfm
|
||||
str_to_ob_time_oracle_dfm
|
||||
hash_delete
|
||||
hash_insert
|
||||
hash_search
|
||||
hash_element
|
||||
hash_free
|
||||
mysql_extension_init
|
||||
_hash_init
|
||||
# thread
|
||||
ob_thread_self
|
||||
ob_thread_equal
|
||||
ob_thread_attr_init
|
||||
ob_thread_attr_destroy
|
||||
ob_thread_attr_setstacksize
|
||||
ob_thread_attr_setdetachstate
|
||||
ob_thread_attr_getstacksize
|
||||
ob_thread_yield
|
||||
ob_thread_create
|
||||
ob_thread_join
|
||||
ob_thread_once
|
||||
ob_thread_cancel
|
||||
ob_thread_exit
|
||||
# ob20
|
||||
ob20_set_extra_info
|
||||
# full_link_trace
|
||||
flt_set_module
|
||||
flt_set_action
|
||||
flt_set_client_info
|
||||
flt_set_identifier
|
||||
flt_get_control_level
|
||||
flt_get_control_sample_pct
|
||||
flt_get_control_record_policy
|
||||
flt_get_control_print_spct
|
||||
flt_get_control_slow_threshold
|
||||
|
||||
flt_deserialize_extra_info
|
||||
flt_serialize_extra_info
|
||||
flt_get_serialize_size_extra_info
|
||||
ob_cond_init
|
||||
ob_cond_destroy
|
||||
ob_cond_timedwait
|
||||
ob_cond_wait
|
||||
ob_cond_signal
|
||||
ob_cond_broadcast
|
||||
ob_mutex_init
|
||||
ob_mutex_lock
|
||||
ob_mutex_trylock
|
||||
ob_mutex_unlock
|
||||
ob_mutex_destroy
|
||||
ob_rw_init
|
||||
ob_rw_destroy
|
||||
ob_rw_rdlock
|
||||
ob_rw_tryrdlock
|
||||
ob_rw_wrlock
|
||||
ob_rw_trywrlock
|
||||
ob_rw_unlock
|
||||
ob_create_thread_key
|
||||
ob_delete_thread_key
|
||||
ob_get_thread_key
|
||||
ob_set_thread_key
|
||||
)
|
||||
|
||||
# handle static plugins
|
||||
@ -294,6 +376,18 @@ ma_stmt_codec.c
|
||||
ma_string.c
|
||||
ma_dtoa.c
|
||||
mariadb_rpl.c
|
||||
ob_protocol20.c
|
||||
ob_bitmap.c
|
||||
ob_complex.c
|
||||
ob_strtoll10.c
|
||||
ob_oracle_format_models.c
|
||||
ob_thread.c
|
||||
ob_object.c
|
||||
ob_full_link_trace.c
|
||||
ob_serialize.c
|
||||
ob_rwlock.c
|
||||
ob_cond.c
|
||||
ob_thread_key.c
|
||||
${CC_BINARY_DIR}/libmariadb/ma_client_plugin.c
|
||||
ma_io.c
|
||||
${SSL_SOURCES}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/************************************************************************************
|
||||
Copyright (C) 2000, 2012 MySQL AB & MySQL Finland AB & TCX DataKonsult AB,
|
||||
Monty Program AB, 2016 MariaDB Corporation AB
|
||||
|
||||
Copyright (c) 2021 OceanBase.
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
@ -38,18 +38,18 @@
|
||||
#define HIGHUSED 8
|
||||
|
||||
static uint hash_mask(uint hashnr,uint buffmax,uint maxlength);
|
||||
static void movelink(HASH_LINK *array,uint pos,uint next_link,uint newlink);
|
||||
static void movelink(OB_HASH_LINK *array,uint pos,uint next_link,uint newlink);
|
||||
static uint calc_hashnr(const uchar *key,uint length);
|
||||
static uint calc_hashnr_caseup(const uchar *key,uint length);
|
||||
static int hashcmp(HASH *hash,HASH_LINK *pos,const uchar *key,uint length);
|
||||
static int hashcmp(OB_HASH *hash, OB_HASH_LINK *pos,const uchar *key,uint length);
|
||||
|
||||
|
||||
my_bool _hash_init(HASH *hash,uint size,uint key_offset,uint key_length,
|
||||
my_bool _hash_init(OB_HASH *hash,uint size,uint key_offset,uint key_length,
|
||||
hash_get_key get_key,
|
||||
void (*free_element)(void*),uint flags CALLER_INFO_PROTO)
|
||||
{
|
||||
hash->records=0;
|
||||
if (ma_init_dynamic_array_ci(&hash->array,sizeof(HASH_LINK),size,0))
|
||||
if (ma_init_dynamic_array_ci(&hash->array,sizeof(OB_HASH_LINK),size,0))
|
||||
{
|
||||
hash->free=0; /* Allow call to hash_free */
|
||||
return(TRUE);
|
||||
@ -69,12 +69,12 @@ my_bool _hash_init(HASH *hash,uint size,uint key_offset,uint key_length,
|
||||
}
|
||||
|
||||
|
||||
void hash_free(HASH *hash)
|
||||
void hash_free(OB_HASH *hash)
|
||||
{
|
||||
if (hash->free)
|
||||
{
|
||||
uint i,records;
|
||||
HASH_LINK *data=dynamic_element(&hash->array,0,HASH_LINK*);
|
||||
OB_HASH_LINK *data=dynamic_element(&hash->array,0, OB_HASH_LINK*);
|
||||
for (i=0,records=hash->records ; i < records ; i++)
|
||||
(*hash->free)(data[i].data);
|
||||
hash->free=0;
|
||||
@ -92,7 +92,7 @@ void hash_free(HASH *hash)
|
||||
*/
|
||||
|
||||
static inline char*
|
||||
hash_key(HASH *hash,const uchar *record,uint *length,my_bool first)
|
||||
hash_key(OB_HASH *hash,const uchar *record,uint *length,my_bool first)
|
||||
{
|
||||
if (hash->get_key)
|
||||
return (char *)(*hash->get_key)(record,(uint *)length,first);
|
||||
@ -108,7 +108,7 @@ static uint hash_mask(uint hashnr,uint buffmax,uint maxlength)
|
||||
return (hashnr & ((buffmax >> 1) -1));
|
||||
}
|
||||
|
||||
static uint hash_rec_mask(HASH *hash,HASH_LINK *pos,uint buffmax,
|
||||
static uint hash_rec_mask(OB_HASH *hash,OB_HASH_LINK *pos,uint buffmax,
|
||||
uint maxlength)
|
||||
{
|
||||
uint length;
|
||||
@ -191,7 +191,7 @@ uint calc_hashnr_caseup(const uchar *key, uint len)
|
||||
#ifndef __SUNPRO_C /* SUNPRO can't handle this */
|
||||
static inline
|
||||
#endif
|
||||
unsigned int rec_hashnr(HASH *hash,const uchar *record)
|
||||
unsigned int rec_hashnr(OB_HASH *hash,const uchar *record)
|
||||
{
|
||||
uint length;
|
||||
uchar *key= (uchar*) hash_key(hash,record,&length,0);
|
||||
@ -202,9 +202,9 @@ unsigned int rec_hashnr(HASH *hash,const uchar *record)
|
||||
/* Search after a record based on a key */
|
||||
/* Sets info->current_ptr to found record */
|
||||
|
||||
void* hash_search(HASH *hash,const uchar *key,uint length)
|
||||
void* hash_search(OB_HASH *hash,const uchar *key,uint length)
|
||||
{
|
||||
HASH_LINK *pos;
|
||||
OB_HASH_LINK *pos;
|
||||
uint flag,idx;
|
||||
|
||||
flag=1;
|
||||
@ -215,7 +215,7 @@ void* hash_search(HASH *hash,const uchar *key,uint length)
|
||||
hash->blength,hash->records);
|
||||
do
|
||||
{
|
||||
pos= dynamic_element(&hash->array,idx,HASH_LINK*);
|
||||
pos= dynamic_element(&hash->array,idx,OB_HASH_LINK*);
|
||||
if (!hashcmp(hash,pos,key,length))
|
||||
{
|
||||
hash->current_record= idx;
|
||||
@ -237,14 +237,14 @@ void* hash_search(HASH *hash,const uchar *key,uint length)
|
||||
/* Get next record with identical key */
|
||||
/* Can only be called if previous calls was hash_search */
|
||||
|
||||
void *hash_next(HASH *hash,const uchar *key,uint length)
|
||||
void *hash_next(OB_HASH *hash,const uchar *key,uint length)
|
||||
{
|
||||
HASH_LINK *pos;
|
||||
OB_HASH_LINK *pos;
|
||||
uint idx;
|
||||
|
||||
if (hash->current_record != NO_RECORD)
|
||||
{
|
||||
HASH_LINK *data=dynamic_element(&hash->array,0,HASH_LINK*);
|
||||
OB_HASH_LINK *data=dynamic_element(&hash->array,0, OB_HASH_LINK*);
|
||||
for (idx=data[hash->current_record].next; idx != NO_RECORD ; idx=pos->next)
|
||||
{
|
||||
pos=data+idx;
|
||||
@ -262,9 +262,9 @@ void *hash_next(HASH *hash,const uchar *key,uint length)
|
||||
|
||||
/* Change link from pos to new_link */
|
||||
|
||||
static void movelink(HASH_LINK *array,uint find,uint next_link,uint newlink)
|
||||
static void movelink(OB_HASH_LINK *array,uint find,uint next_link,uint newlink)
|
||||
{
|
||||
HASH_LINK *old_link;
|
||||
OB_HASH_LINK *old_link;
|
||||
do
|
||||
{
|
||||
old_link=array+next_link;
|
||||
@ -276,7 +276,7 @@ static void movelink(HASH_LINK *array,uint find,uint next_link,uint newlink)
|
||||
|
||||
/* Compare a key in a record to a whole key. Return 0 if identical */
|
||||
|
||||
static int hashcmp(HASH *hash,HASH_LINK *pos,const uchar *key,uint length)
|
||||
static int hashcmp(OB_HASH *hash, OB_HASH_LINK *pos,const uchar *key,uint length)
|
||||
{
|
||||
uint rec_keylength;
|
||||
uchar *rec_key= (uchar*) hash_key(hash,pos->data,&rec_keylength,1);
|
||||
@ -287,22 +287,22 @@ static int hashcmp(HASH *hash,HASH_LINK *pos,const uchar *key,uint length)
|
||||
|
||||
/* Write a hash-key to the hash-index */
|
||||
|
||||
my_bool hash_insert(HASH *info,const uchar *record)
|
||||
my_bool hash_insert(OB_HASH *info,const uchar *record)
|
||||
{
|
||||
int flag;
|
||||
uint halfbuff,hash_nr,first_index,idx;
|
||||
uchar *ptr_to_rec= NULL,*ptr_to_rec2= NULL;
|
||||
HASH_LINK *data,*empty,*gpos= NULL,*gpos2 = NULL,*pos;
|
||||
OB_HASH_LINK *data,*empty,*gpos= NULL,*gpos2 = NULL,*pos;
|
||||
|
||||
LINT_INIT(gpos); LINT_INIT(gpos2);
|
||||
LINT_INIT(ptr_to_rec); LINT_INIT(ptr_to_rec2);
|
||||
|
||||
flag=0;
|
||||
if (!(empty=(HASH_LINK*) ma_alloc_dynamic(&info->array)))
|
||||
if (!(empty=(OB_HASH_LINK*) ma_alloc_dynamic(&info->array)))
|
||||
return(TRUE); /* No more memory */
|
||||
|
||||
info->current_record= NO_RECORD;
|
||||
data=dynamic_element(&info->array,0,HASH_LINK*);
|
||||
data=dynamic_element(&info->array,0, OB_HASH_LINK*);
|
||||
halfbuff= info->blength >> 1;
|
||||
|
||||
idx=first_index=info->records-halfbuff;
|
||||
@ -421,15 +421,15 @@ my_bool hash_insert(HASH *info,const uchar *record)
|
||||
** if there is a free-function it's called for record if found
|
||||
******************************************************************************/
|
||||
|
||||
my_bool hash_delete(HASH *hash,uchar *record)
|
||||
my_bool hash_delete(OB_HASH *hash,uchar *record)
|
||||
{
|
||||
uint blength,pos2,pos_hashnr,lastpos_hashnr,idx,empty_index;
|
||||
HASH_LINK *data,*lastpos,*gpos,*pos,*pos3,*empty;
|
||||
OB_HASH_LINK *data,*lastpos,*gpos,*pos,*pos3,*empty;
|
||||
if (!hash->records)
|
||||
return(1);
|
||||
|
||||
blength=hash->blength;
|
||||
data=dynamic_element(&hash->array,0,HASH_LINK*);
|
||||
data=dynamic_element(&hash->array,0, OB_HASH_LINK*);
|
||||
/* Search after record with key */
|
||||
pos=data+ hash_mask(rec_hashnr(hash,record),blength,hash->records);
|
||||
gpos = 0;
|
||||
@ -508,12 +508,12 @@ exit:
|
||||
This is much more efficient than using a delete & insert.
|
||||
*/
|
||||
|
||||
my_bool hash_update(HASH *hash,uchar *record,uchar *old_key,uint old_key_length)
|
||||
my_bool hash_update(OB_HASH *hash,uchar *record,uchar *old_key,uint old_key_length)
|
||||
{
|
||||
uint idx,new_index,new_pos_index,blength,records,empty;
|
||||
HASH_LINK org_link,*data,*previous,*pos;
|
||||
OB_HASH_LINK org_link,*data,*previous,*pos;
|
||||
|
||||
data=dynamic_element(&hash->array,0,HASH_LINK*);
|
||||
data=dynamic_element(&hash->array,0,OB_HASH_LINK*);
|
||||
blength=hash->blength; records=hash->records;
|
||||
|
||||
/* Search after record with key */
|
||||
@ -572,10 +572,10 @@ my_bool hash_update(HASH *hash,uchar *record,uchar *old_key,uint old_key_length)
|
||||
}
|
||||
|
||||
|
||||
uchar *hash_element(HASH *hash,uint idx)
|
||||
uchar *hash_element(OB_HASH *hash,uint idx)
|
||||
{
|
||||
if (idx < hash->records)
|
||||
return dynamic_element(&hash->array,idx,HASH_LINK*)->data;
|
||||
return dynamic_element(&hash->array,idx,OB_HASH_LINK*)->data;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@ -38,8 +38,14 @@
|
||||
#ifndef _WIN32
|
||||
#include <poll.h>
|
||||
#endif
|
||||
#include <ob_protocol20.h>
|
||||
|
||||
#define MAX_PACKET_LENGTH (256L*256L*256L-1)
|
||||
#define MAX_PACKET_LENGTH_WITH_OB20 (MAX_PACKET_LENGTH - OB20_HEADER_SIZE - OB20_TAILER_SIZE - OB20_EXTRAINFO_LENGTH_SIZE)
|
||||
|
||||
#ifndef HAVE_COMPRESS
|
||||
#define HAVE_COMPRESS
|
||||
#endif
|
||||
|
||||
/* net_buffer_length and max_allowed_packet are defined in mysql.h
|
||||
See bug conc-57
|
||||
@ -51,6 +57,7 @@ ulong max_allowed_packet=1024L * 1024L * 1024L;
|
||||
ulong net_read_timeout= NET_READ_TIMEOUT;
|
||||
ulong net_write_timeout= NET_WRITE_TIMEOUT;
|
||||
ulong net_buffer_length= 8192; /* Default length. Enlarged if necessary */
|
||||
// ulong net_buffer_length= 10L * 1024L * 1024L; /* 10M:change for ob20 */
|
||||
|
||||
#if !defined(_WIN32)
|
||||
#include <sys/socket.h>
|
||||
@ -66,7 +73,6 @@ ulong net_buffer_length= 8192; /* Default length. Enlarged if necessary */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
** Give error if a too big packet is found
|
||||
** The server can change this with the -O switch, but because the client
|
||||
@ -100,6 +106,8 @@ int ma_net_init(NET *net, MARIADB_PVIO* pvio)
|
||||
net->where_b = net->remain_in_buf=0;
|
||||
net->last_errno=0;
|
||||
|
||||
net->use_ob20protocol = 0;
|
||||
|
||||
if (pvio != 0) /* If real connection */
|
||||
{
|
||||
ma_pvio_get_handle(pvio, &net->fd);
|
||||
@ -113,6 +121,13 @@ void ma_net_end(NET *net)
|
||||
{
|
||||
free(net->buff);
|
||||
net->buff=0;
|
||||
if (net->ob20protocol) {
|
||||
ob20_end(net->ob20protocol);
|
||||
free(net->ob20protocol);
|
||||
net->ob20protocol = 0;
|
||||
net->use_ob20protocol = 0;
|
||||
net->compress = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Realloc the packet buffer */
|
||||
@ -186,6 +201,10 @@ int ma_net_flush(NET *net)
|
||||
int ma_net_write(NET *net, const uchar *packet, size_t len)
|
||||
{
|
||||
uchar buff[NET_HEADER_SIZE];
|
||||
// update ob20 request id
|
||||
if (net->use_ob20protocol && OB_NOT_NULL(net->ob20protocol)) {
|
||||
update_request_id(&net->ob20protocol->header.request_id);
|
||||
}
|
||||
while (len >= MAX_PACKET_LENGTH)
|
||||
{
|
||||
const ulong max_len= MAX_PACKET_LENGTH;
|
||||
@ -218,6 +237,11 @@ int ma_net_write_command(NET *net, uchar command,
|
||||
buff[NET_HEADER_SIZE]= 0;
|
||||
buff[4]=command;
|
||||
|
||||
// update ob20 request id
|
||||
if (net->use_ob20protocol && OB_NOT_NULL(net->ob20protocol)) {
|
||||
update_request_id(&net->ob20protocol->header.request_id);
|
||||
}
|
||||
|
||||
if (length >= MAX_PACKET_LENGTH)
|
||||
{
|
||||
len= MAX_PACKET_LENGTH - 1;
|
||||
@ -249,15 +273,45 @@ int ma_net_write_command(NET *net, uchar command,
|
||||
static int ma_net_write_buff(NET *net,const char *packet, size_t len)
|
||||
{
|
||||
size_t left_length;
|
||||
size_t extra_info_length = 0;
|
||||
|
||||
if (!len)
|
||||
return 0;
|
||||
|
||||
if (net->max_packet > MAX_PACKET_LENGTH &&
|
||||
net->compress)
|
||||
left_length= (size_t)(MAX_PACKET_LENGTH - (net->write_pos - net->buff));
|
||||
else
|
||||
// 传入ma_net_real_write的buffer必须为MAX_PACKET_LENGTH - extra_info_length
|
||||
if (net->use_ob20protocol) {
|
||||
extra_info_length = get_protocol20_extra_info_length(net->ob20protocol);
|
||||
// 1.如果extra info length大于能存放的最大长度, 直接报错
|
||||
// 2.如果extra info length + 当前buffer里存放的packet大于最大长度,单独发一个extra info包
|
||||
// 3.如果extra info length + 当前buffer里存放的packet + 参数传入的packet length大于最大长度,
|
||||
// 将当前buffer中的buffer和extra info发送出去
|
||||
// 4.如果所有的都能放下,直接走到下面的流程
|
||||
if (extra_info_length > MAX_PACKET_LENGTH_WITH_OB20) {
|
||||
return 1; //error
|
||||
} else if (extra_info_length + (size_t)(net->write_pos - net->buff) > MAX_PACKET_LENGTH_WITH_OB20) {
|
||||
if (ma_net_real_write(net,(char*) net->buff, 0)) { // buffer为0,只写20头和extra info
|
||||
return 1; // error
|
||||
}
|
||||
} else if (extra_info_length + (size_t)(net->write_pos - net->buff) + len > MAX_PACKET_LENGTH_WITH_OB20) {
|
||||
// 将当前的buffer和extra info写入到网络包中
|
||||
if (ma_net_real_write(net,(char*) net->buff, (size_t)(net->write_pos - net->buff))) {
|
||||
return 1;
|
||||
}
|
||||
net->write_pos= net->buff;
|
||||
} else {
|
||||
// 当前所有都能放入一个包中, 这个分支会走到最后memcpy,然后结束
|
||||
}
|
||||
}
|
||||
|
||||
if (net->max_packet > MAX_PACKET_LENGTH && net->compress) {
|
||||
if (net->use_ob20protocol) {
|
||||
left_length= (size_t)(MAX_PACKET_LENGTH_WITH_OB20 - (net->write_pos - net->buff));
|
||||
} else {
|
||||
left_length= (size_t)(MAX_PACKET_LENGTH - (net->write_pos - net->buff));
|
||||
}
|
||||
} else {
|
||||
left_length=(size_t) (net->buff_end - net->write_pos);
|
||||
}
|
||||
|
||||
if (len > left_length)
|
||||
{
|
||||
@ -273,9 +327,13 @@ static int ma_net_write_buff(NET *net,const char *packet, size_t len)
|
||||
}
|
||||
if (net->compress)
|
||||
{
|
||||
/* uncompressed length is stored in 3 bytes,so
|
||||
packet can't be > 0xFFFFFF */
|
||||
left_length= MAX_PACKET_LENGTH;
|
||||
if (net->use_ob20protocol) {
|
||||
left_length= MAX_PACKET_LENGTH_WITH_OB20;
|
||||
} else {
|
||||
/* uncompressed length is stored in 3 bytes,so
|
||||
packet can't be > 0xFFFFFF */
|
||||
left_length= MAX_PACKET_LENGTH;
|
||||
}
|
||||
while (len > left_length)
|
||||
{
|
||||
if (ma_net_real_write(net, packet, left_length))
|
||||
@ -310,25 +368,97 @@ int ma_net_real_write(NET *net, const char *packet, size_t len)
|
||||
{
|
||||
size_t complen;
|
||||
uchar *b;
|
||||
uchar *check_result;
|
||||
uint header_length=NET_HEADER_SIZE+COMP_HEADER_SIZE;
|
||||
if (!(b=(uchar*) malloc(len + NET_HEADER_SIZE + COMP_HEADER_SIZE + 1)))
|
||||
{
|
||||
net->last_errno=ER_OUT_OF_RESOURCES;
|
||||
net->error=2;
|
||||
net->reading_or_writing=0;
|
||||
return(1);
|
||||
}
|
||||
memcpy(b+header_length,packet,len);
|
||||
|
||||
if (_mariadb_compress((unsigned char*) b+header_length,&len,&complen))
|
||||
if (net->use_ob20protocol)
|
||||
{
|
||||
complen=0;
|
||||
// use ob20 protocol
|
||||
uint32_t ob20_header_length = header_length + OB20_HEADER_SIZE;
|
||||
uint32_t extra_info_length = 0;
|
||||
uint32_t ob20_packet_len = 0;
|
||||
uint32_t real_write_buffer_length = 0;
|
||||
uint32_t crc32 = 0;
|
||||
|
||||
extra_info_length = get_protocol20_extra_info_length(net->ob20protocol);
|
||||
if (0 != extra_info_length) {
|
||||
ob20_packet_len = len + extra_info_length + OB20_HEADER_SIZE + OB20_TAILER_SIZE + OB20_EXTRAINFO_LENGTH_SIZE;
|
||||
} else {
|
||||
ob20_packet_len = len + extra_info_length + OB20_HEADER_SIZE + OB20_TAILER_SIZE;
|
||||
}
|
||||
|
||||
real_write_buffer_length = ob20_packet_len + NET_HEADER_SIZE + COMP_HEADER_SIZE + 1;
|
||||
if (net->ob20protocol->real_write_buffer_length < real_write_buffer_length) {
|
||||
net->ob20protocol->real_write_buffer = realloc(net->ob20protocol->real_write_buffer, real_write_buffer_length);
|
||||
if (OB_ISNULL(net->ob20protocol->real_write_buffer)) {
|
||||
net->last_errno=ER_OUT_OF_RESOURCES;
|
||||
net->error=2;
|
||||
net->reading_or_writing=0;
|
||||
return(1);
|
||||
} else {
|
||||
net->ob20protocol->real_write_buffer_length = real_write_buffer_length;
|
||||
}
|
||||
}
|
||||
b = net->ob20protocol->real_write_buffer;
|
||||
|
||||
// store extra info
|
||||
if (0 != extra_info_length) {
|
||||
int4store(b + ob20_header_length, extra_info_length);
|
||||
|
||||
check_result = fill_protocol20_extra_info(net->ob20protocol, b + ob20_header_length + OB20_EXTRAINFO_LENGTH_SIZE, extra_info_length);
|
||||
net->ob20protocol->header.flag.st_flags.OB_IS_NEW_EXTRA_INFO = 1;
|
||||
net->ob20protocol->header.flag.st_flags.OB_EXTRA_INFO_EXIST = 1;
|
||||
net->ob20protocol->header.flag.st_flags.OB_IS_LAST_PACKET = 0;
|
||||
if (check_result != b + ob20_header_length + OB20_EXTRAINFO_LENGTH_SIZE + extra_info_length) {
|
||||
return 1;
|
||||
} else {
|
||||
extra_info_length += OB20_EXTRAINFO_LENGTH_SIZE; // storing extra_info_length use 4 bytes
|
||||
}
|
||||
// clear extra info
|
||||
clear_extra_info(net->ob20protocol);
|
||||
} else {
|
||||
net->ob20protocol->header.flag.st_flags.OB_EXTRA_INFO_EXIST = 0;
|
||||
net->ob20protocol->header.flag.st_flags.OB_IS_NEW_EXTRA_INFO = 0;
|
||||
}
|
||||
|
||||
// store basic info
|
||||
memcpy(b + ob20_header_length + extra_info_length, packet, len);
|
||||
|
||||
// store crc64 checksum
|
||||
crc32 = ob_crc32(crc32, (char *)b + ob20_header_length, len + extra_info_length);
|
||||
int4store(b + ob20_header_length + extra_info_length + len, crc32);
|
||||
|
||||
net->ob20protocol->header.payload_len = len + extra_info_length;
|
||||
check_result = fill_protocol20_header(net->ob20protocol, ob20_packet_len, net->compress_pkt_nr++, 0, b);
|
||||
if (check_result != b + ob20_header_length) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
len = ob20_packet_len + NET_HEADER_SIZE + COMP_HEADER_SIZE;
|
||||
packet = (char *)b;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!(b=(uchar*) malloc(len + NET_HEADER_SIZE + COMP_HEADER_SIZE + 1)))
|
||||
{
|
||||
net->last_errno=ER_OUT_OF_RESOURCES;
|
||||
net->error=2;
|
||||
net->reading_or_writing=0;
|
||||
return(1);
|
||||
}
|
||||
memcpy(b+header_length,packet,len);
|
||||
|
||||
if (_mariadb_compress((unsigned char*) b+header_length,&len,&complen))
|
||||
{
|
||||
complen=0;
|
||||
}
|
||||
|
||||
int3store(&b[NET_HEADER_SIZE],complen);
|
||||
int3store(b,len);
|
||||
b[3]=(uchar) (net->compress_pkt_nr++);
|
||||
len+= header_length;
|
||||
packet= (char*) b;
|
||||
}
|
||||
int3store(&b[NET_HEADER_SIZE],complen);
|
||||
int3store(b,len);
|
||||
b[3]=(uchar) (net->compress_pkt_nr++);
|
||||
len+= header_length;
|
||||
packet= (char*) b;
|
||||
}
|
||||
#endif /* HAVE_COMPRESS */
|
||||
|
||||
@ -349,8 +479,8 @@ int ma_net_real_write(NET *net, const char *packet, size_t len)
|
||||
pos+=length;
|
||||
}
|
||||
#ifdef HAVE_COMPRESS
|
||||
if (net->compress)
|
||||
free((char*) packet);
|
||||
if (net->compress && !net->use_ob20protocol)
|
||||
free((char*) packet); // 2.0协议buffer自管理
|
||||
#endif
|
||||
net->reading_or_writing=0;
|
||||
return(((int) (pos != end)));
|
||||
@ -554,7 +684,93 @@ ulong ma_net_read(NET *net)
|
||||
|
||||
if ((packet_length = ma_real_read(net,(size_t *)&complen)) == packet_error)
|
||||
return packet_error;
|
||||
if (_mariadb_uncompress((unsigned char*) net->buff + net->where_b, &packet_length, &complen))
|
||||
if (net->use_ob20protocol)
|
||||
{
|
||||
/*
|
||||
OceanBase 2.0 Protocol Format:
|
||||
|
||||
0 1 2 3 4 Byte
|
||||
+-----------------+----------------------+
|
||||
| Magic Num | Version |
|
||||
+-----------------+----------------------+
|
||||
| Connection Id |
|
||||
+-----------------------------+----------+
|
||||
| Request Id | Seq |
|
||||
+-----------------------------+----------+
|
||||
| PayLoad Length |
|
||||
+----------------------------------------+
|
||||
| Flag |
|
||||
+-----------------+----------------------+
|
||||
| Reserved |Header Checksum(CRC16)|
|
||||
+-----------------+----------------------+
|
||||
| ... PayLoad Data ... |----------+
|
||||
+----------------------------------------+ |
|
||||
| Tailer PayLoad Checksum (CRC32) | |
|
||||
+----------------------------------------+ |
|
||||
|
|
||||
|
|
||||
+--------------------------+
|
||||
|
|
||||
|
|
||||
v
|
||||
+-------------------+-------------------+-------------------------------------+
|
||||
| Extra Len(4Byte) | Extra Info(K/V) | Basic Info(Standard MySQL Packet) |
|
||||
+-------------------+-------------------+-------------------------------------+
|
||||
*/
|
||||
|
||||
unsigned char *ob20_current = 0;
|
||||
unsigned char *ob20_start = 0;
|
||||
size_t ob20_extra_info_size = 0;
|
||||
uint32_t crc32 = 0;
|
||||
uint32_t packet_crc32;
|
||||
ob20_current = net->buff + net->where_b;
|
||||
ob20_start = ob20_current;
|
||||
|
||||
if (decode_protocol20_header(net->ob20protocol, ob20_current, packet_length, net->pkt_nr - 1, 0)) {
|
||||
net->error=2; /* caller will close socket */
|
||||
// 这里考虑定义一个新的错误码
|
||||
net->last_errno=ER_NET_READ_ERROR;
|
||||
return packet_error;
|
||||
}
|
||||
|
||||
ob20_current += OB20_HEADER_SIZE;
|
||||
|
||||
// first check checksum
|
||||
packet_crc32 = uint4korr(&ob20_current[net->ob20protocol->header.payload_len]);
|
||||
if (packet_crc32) {
|
||||
crc32 = ob_crc32(crc32, (char *)ob20_current, net->ob20protocol->header.payload_len);
|
||||
if (crc32 != packet_crc32) {
|
||||
net->error=2; /* caller will close socket */
|
||||
net->last_errno=ER_NET_READ_ERROR;
|
||||
return packet_error;
|
||||
}
|
||||
} else {
|
||||
// 如果server回包的crc32是0,当前不检查crc,后续加上开关
|
||||
}
|
||||
// clear last extra info
|
||||
clear_extra_info(net->ob20protocol);
|
||||
|
||||
// for extra info
|
||||
if (1 == net->ob20protocol->header.flag.st_flags.OB_EXTRA_INFO_EXIST){
|
||||
// get extra info size
|
||||
ob20_extra_info_size = uint4korr(ob20_current);
|
||||
#ifdef DEBUG_OB20
|
||||
printf("get extra info and ob20_extra_info size is %lu\n", ob20_extra_info_size);
|
||||
#endif
|
||||
// decode extra info
|
||||
if (1 == net->ob20protocol->header.flag.st_flags.OB_IS_NEW_EXTRA_INFO
|
||||
&& decode_protocol20_extra_info(net->ob20protocol, ob20_current)) {
|
||||
}
|
||||
ob20_extra_info_size += OB20_EXTRAINFO_LENGTH_SIZE;
|
||||
ob20_current += ob20_extra_info_size;
|
||||
}
|
||||
|
||||
// change buffer to raw mysql packet, same as compress protocol
|
||||
memmove(ob20_start, ob20_current, net->ob20protocol->header.payload_len - ob20_extra_info_size);
|
||||
// update complen , length of raw mysql packet length
|
||||
complen = net->ob20protocol->header.payload_len - ob20_extra_info_size;
|
||||
}
|
||||
else if (_mariadb_uncompress((unsigned char*) net->buff + net->where_b, &packet_length, &complen))
|
||||
{
|
||||
net->error=2; /* caller will close socket */
|
||||
net->last_errno=ER_NET_UNCOMPRESS_ERROR;
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
/****************************************************************************
|
||||
Copyright (C) 2012 Monty Program AB
|
||||
Copyright (c) 2021 OceanBase.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
@ -51,7 +50,7 @@
|
||||
#include "mysql.h"
|
||||
#include <math.h> /* ceil() */
|
||||
#include <limits.h>
|
||||
|
||||
#include "ob_complex.h"
|
||||
#ifdef WIN32
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
@ -87,7 +86,7 @@
|
||||
|
||||
#define YY_PART_YEAR 70
|
||||
|
||||
MYSQL_PS_CONVERSION mysql_ps_fetch_functions[MYSQL_TYPE_GEOMETRY + 1];
|
||||
MYSQL_PS_CONVERSION mysql_ps_fetch_functions[MYSQL_TYPE_GEOMETRY + 2];
|
||||
my_bool mysql_ps_subsystem_initialized= 0;
|
||||
|
||||
|
||||
@ -531,6 +530,7 @@ static void convert_froma_string(MYSQL_BIND *r_param, char *buffer, size_t len)
|
||||
}
|
||||
break;
|
||||
case MYSQL_TYPE_LONG:
|
||||
case MYSQL_TYPE_CURSOR:
|
||||
{
|
||||
longlong val= my_atoll(buffer, buffer + len, &error);
|
||||
*r_param->error=error ? 1 : r_param->is_unsigned ? NUMERIC_TRUNCATION(val, 0, UINT_MAX32) : NUMERIC_TRUNCATION(val, INT_MIN32, INT_MAX32) || error > 0;
|
||||
@ -578,6 +578,7 @@ static void convert_froma_string(MYSQL_BIND *r_param, char *buffer, size_t len)
|
||||
case MYSQL_TYPE_BLOB:
|
||||
case MYSQL_TYPE_DECIMAL:
|
||||
case MYSQL_TYPE_NEWDECIMAL:
|
||||
case MYSQL_TYPE_OB_UROWID:
|
||||
default:
|
||||
{
|
||||
if (len >= r_param->offset)
|
||||
@ -618,6 +619,7 @@ static void convert_from_long(MYSQL_BIND *r_param, const MYSQL_FIELD *field, lon
|
||||
r_param->buffer_length= 2;
|
||||
break;
|
||||
case MYSQL_TYPE_LONG:
|
||||
case MYSQL_TYPE_CURSOR:
|
||||
longstore(r_param->buffer, (int32)val);
|
||||
*r_param->error= r_param->is_unsigned ? NUMERIC_TRUNCATION(val, 0, UINT_MAX32) : NUMERIC_TRUNCATION(val, INT_MIN32, INT_MAX32);
|
||||
r_param->buffer_length= 4;
|
||||
@ -757,6 +759,7 @@ void ps_fetch_int32(MYSQL_BIND *r_param, const MYSQL_FIELD * const field,
|
||||
break; */
|
||||
case MYSQL_TYPE_INT24:
|
||||
case MYSQL_TYPE_LONG:
|
||||
case MYSQL_TYPE_CURSOR:
|
||||
ps_fetch_from_1_to_8_bytes(r_param, field, row, 4);
|
||||
break;
|
||||
default:
|
||||
@ -834,6 +837,7 @@ static void convert_from_float(MYSQL_BIND *r_param, const MYSQL_FIELD *field, fl
|
||||
}
|
||||
break;
|
||||
case MYSQL_TYPE_LONG:
|
||||
case MYSQL_TYPE_CURSOR:
|
||||
{
|
||||
if (r_param->is_unsigned)
|
||||
{
|
||||
@ -933,6 +937,7 @@ static void convert_from_double(MYSQL_BIND *r_param, const MYSQL_FIELD *field, d
|
||||
}
|
||||
break;
|
||||
case MYSQL_TYPE_LONG:
|
||||
case MYSQL_TYPE_CURSOR:
|
||||
{
|
||||
if (r_param->is_unsigned)
|
||||
{
|
||||
@ -1117,6 +1122,8 @@ void ps_fetch_oracle_timestamp(MYSQL_BIND *param,
|
||||
uint buffer_length = 0;
|
||||
uint length = net_field_length(row);
|
||||
|
||||
UNUSED(field);
|
||||
|
||||
if (length > 16) {
|
||||
buffer_length = length - 16 + sizeof(ORACLE_TIME) + 2;
|
||||
} else {
|
||||
@ -1256,6 +1263,701 @@ void ps_fetch_datetime(MYSQL_BIND *r_param, const MYSQL_FIELD * field,
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/*fetch ob_lob*/
|
||||
static void fill_ob_lob_locator(OB_LOB_LOCATOR *ob_lob_locator, uchar *row)
|
||||
{
|
||||
ob_lob_locator->magic_code_ = uint4korr(row);
|
||||
ob_lob_locator->version_ = uint4korr(row + 4);
|
||||
ob_lob_locator->snapshot_version_ = sint8korr(row + 8);
|
||||
ob_lob_locator->table_id_ = uint8korr(row + 16);
|
||||
ob_lob_locator->column_id_ = uint4korr(row + 24);
|
||||
ob_lob_locator->mode_ = uint2korr(row + 28);
|
||||
ob_lob_locator->option_ = uint2korr(row + 30);
|
||||
ob_lob_locator->payload_offset_ = uint4korr(row + 32);
|
||||
ob_lob_locator->payload_size_ = uint4korr(row + 36);
|
||||
}
|
||||
|
||||
static void fetch_result_ob_lob(MYSQL_BIND *param,
|
||||
const MYSQL_FIELD *field __attribute__((unused)),
|
||||
uchar **row)
|
||||
{
|
||||
ulong length= net_field_length(row);
|
||||
|
||||
if (param->buffer_length <= 0
|
||||
|| param->buffer_length < MAX_OB_LOB_LOCATOR_HEADER_LENGTH
|
||||
|| length < MAX_OB_LOB_LOCATOR_HEADER_LENGTH) {
|
||||
*param->error= 1;
|
||||
} else {
|
||||
OB_LOB_LOCATOR *ob_lob_locator = (OB_LOB_LOCATOR *)param->buffer;
|
||||
ulong copy_length = MIN(param->buffer_length - MAX_OB_LOB_LOCATOR_HEADER_LENGTH, length - MAX_OB_LOB_LOCATOR_HEADER_LENGTH);
|
||||
fill_ob_lob_locator(ob_lob_locator, *row);
|
||||
memcpy(ob_lob_locator->data_, (*row) + MAX_OB_LOB_LOCATOR_HEADER_LENGTH, copy_length);
|
||||
*param->error= copy_length + MAX_OB_LOB_LOCATOR_HEADER_LENGTH < length;
|
||||
}
|
||||
|
||||
*param->length= length;
|
||||
*row += length;
|
||||
}
|
||||
|
||||
/*fetch_complex_type*/
|
||||
static void fetch_result_complex(MYSQL_BIND *param, void *buffer,
|
||||
CHILD_TYPE *child, uchar **row);
|
||||
static void *fetch_result_complex_alloc_space(MYSQL_COMPLEX_BIND_BASIC *header,
|
||||
MYSQL_BIND *param,
|
||||
ulong length);
|
||||
static void fill_complex_type(MYSQL_BIND *param, void *buffer,
|
||||
CHILD_TYPE *child);
|
||||
static ulong get_complex_header_length(enum_types type) {
|
||||
switch (type) {
|
||||
case TYPE_OBJECT:
|
||||
return sizeof(MYSQL_COMPLEX_BIND_OBJECT);
|
||||
case TYPE_COLLECTION:
|
||||
return sizeof(MYSQL_COMPLEX_BIND_ARRAY);
|
||||
case TYPE_VARCHAR2:
|
||||
case TYPE_CHAR:
|
||||
case TYPE_RAW:
|
||||
return sizeof(MYSQL_COMPLEX_BIND_STRING);
|
||||
case TYPE_NUMBER:
|
||||
return sizeof(MYSQL_COMPLEX_BIND_DECIMAL);
|
||||
case TYPE_LONG:
|
||||
case TYPE_LONGLONG:
|
||||
case TYPE_TINY:
|
||||
case TYPE_SHORT:
|
||||
case TYPE_FLOAT:
|
||||
case TYPE_DOUBLE:
|
||||
return sizeof(MYSQL_COMPLEX_BIND_BASIC);
|
||||
default:
|
||||
return sizeof(MYSQL_COMPLEX_BIND_BASIC);
|
||||
}
|
||||
}
|
||||
static void fetch_result_str_complex(MYSQL_COMPLEX_BIND_STRING *header,
|
||||
MYSQL_BIND *param,
|
||||
uchar **row)
|
||||
{
|
||||
void *buffer;
|
||||
ulong length;
|
||||
|
||||
length = net_field_length(row);
|
||||
|
||||
//include end '\0'
|
||||
buffer = fetch_result_complex_alloc_space((MYSQL_COMPLEX_BIND_HEADER *)header, param, length + 1);
|
||||
if (NULL == buffer) {
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(buffer, (char *)*row, length);
|
||||
((uchar *)buffer)[length]= '\0';
|
||||
header->length = length;
|
||||
*row+= length;
|
||||
return;
|
||||
}
|
||||
static void fetch_result_long_complex(MYSQL_COMPLEX_BIND_BASIC *header,
|
||||
MYSQL_BIND *param,
|
||||
uchar **row)
|
||||
{
|
||||
void *buffer;
|
||||
|
||||
buffer = fetch_result_complex_alloc_space((MYSQL_COMPLEX_BIND_HEADER *)header, param, 4);
|
||||
if (NULL == buffer) {
|
||||
return;
|
||||
}
|
||||
longstore(buffer, ((uint32)sint4korr(*row)));
|
||||
*row += 4;
|
||||
|
||||
return;
|
||||
}
|
||||
static void fetch_result_longlong_complex(MYSQL_COMPLEX_BIND_BASIC *header,
|
||||
MYSQL_BIND *param,
|
||||
uchar **row)
|
||||
{
|
||||
void *buffer;
|
||||
ulonglong val;
|
||||
|
||||
buffer = fetch_result_complex_alloc_space((MYSQL_COMPLEX_BIND_HEADER *)header, param, 8);
|
||||
if (NULL == buffer) {
|
||||
return;
|
||||
}
|
||||
|
||||
val= (ulonglong)sint8korr(*row);
|
||||
longlongstore(buffer, val);
|
||||
*row += 8;
|
||||
|
||||
return;
|
||||
}
|
||||
static void fetch_result_short_complex(MYSQL_COMPLEX_BIND_BASIC *header,
|
||||
MYSQL_BIND *param,
|
||||
uchar **row)
|
||||
{
|
||||
void *buffer;
|
||||
|
||||
buffer = fetch_result_complex_alloc_space((MYSQL_COMPLEX_BIND_HEADER *)header, param, 2);
|
||||
if (NULL == buffer) {
|
||||
return;
|
||||
}
|
||||
shortstore(buffer, ((ushort)sint2korr(*row)));
|
||||
*row += 2;
|
||||
|
||||
return;
|
||||
}
|
||||
static void fetch_result_tiny_complex(MYSQL_COMPLEX_BIND_BASIC *header,
|
||||
MYSQL_BIND *param,
|
||||
uchar **row)
|
||||
{
|
||||
void *buffer;
|
||||
|
||||
buffer = fetch_result_complex_alloc_space((MYSQL_COMPLEX_BIND_HEADER *)header, param, 1);
|
||||
if (NULL == buffer) {
|
||||
return;
|
||||
}
|
||||
*(uchar *)buffer= **row;
|
||||
*row += 1;
|
||||
|
||||
return;
|
||||
}
|
||||
static void fetch_result_float_complex(MYSQL_COMPLEX_BIND_BASIC *header,
|
||||
MYSQL_BIND *param,
|
||||
uchar **row)
|
||||
{
|
||||
void *buffer;
|
||||
float *value;
|
||||
|
||||
buffer = fetch_result_complex_alloc_space((MYSQL_COMPLEX_BIND_HEADER *)header, param, 4);
|
||||
if (NULL == buffer) {
|
||||
return;
|
||||
}
|
||||
value= (float *)buffer;
|
||||
float4get(*value, *row);
|
||||
|
||||
*row += 4;
|
||||
return;
|
||||
}
|
||||
static void fetch_result_double_complex(MYSQL_COMPLEX_BIND_BASIC *header,
|
||||
MYSQL_BIND *param,
|
||||
uchar **row)
|
||||
{
|
||||
void *buffer;
|
||||
double *value;
|
||||
|
||||
buffer = fetch_result_complex_alloc_space((MYSQL_COMPLEX_BIND_HEADER *)header, param, 8);
|
||||
if (NULL == buffer) {
|
||||
return;
|
||||
}
|
||||
value= (double *)buffer;
|
||||
float8get(*value, *row);
|
||||
|
||||
*row += 8;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
static void fetch_result_object_complex(MYSQL_COMPLEX_BIND_OBJECT *header,
|
||||
MYSQL_BIND *param,
|
||||
uchar **row)
|
||||
{
|
||||
void *buffer = NULL;
|
||||
ulong length = 0;
|
||||
uint i = 0;
|
||||
COMPLEX_TYPE_OBJECT *object = NULL;
|
||||
struct st_complex_type *complex_type = NULL;
|
||||
uchar *null_ptr, bit;
|
||||
|
||||
complex_type = get_complex_type(param->mysql, header->owner_name, header->type_name);
|
||||
|
||||
if (complex_type == NULL) {
|
||||
*param->error= 1;
|
||||
return;
|
||||
}
|
||||
|
||||
object = (COMPLEX_TYPE_OBJECT *)complex_type;
|
||||
|
||||
for (i = 0; i < object->attr_no; i++) {
|
||||
length += get_complex_header_length(object->child[i].type);
|
||||
}
|
||||
|
||||
buffer = fetch_result_complex_alloc_space((MYSQL_COMPLEX_BIND_BASIC *)header, param, length);
|
||||
if (NULL == buffer) {
|
||||
return;
|
||||
}
|
||||
|
||||
null_ptr = *row;
|
||||
*row += (object->attr_no + 9)/8; /* skip null bits */
|
||||
bit = 4; /* first 2 bits are reserved */
|
||||
|
||||
for (i = 0; i < object->attr_no; i++) {
|
||||
fill_complex_type(param, buffer, &(object->child[i]));
|
||||
|
||||
if (*null_ptr & bit) {
|
||||
((MYSQL_COMPLEX_BIND_BASIC *)buffer)->is_null = 1;
|
||||
} else {
|
||||
fetch_result_complex(param, buffer, &(object->child[i]), row);
|
||||
}
|
||||
|
||||
buffer = (char*)buffer + get_complex_header_length(object->child[i].type);
|
||||
|
||||
if (!((bit<<=1) & 255)) {
|
||||
bit= 1; /* To next uchar */
|
||||
null_ptr++;
|
||||
}
|
||||
}
|
||||
|
||||
header->length = (char*)buffer - (char*)header->buffer;
|
||||
return;
|
||||
}
|
||||
static void read_binary_datetime(MYSQL_TIME *tm, uchar **pos)
|
||||
{
|
||||
uint length= net_field_length(pos);
|
||||
|
||||
if (length)
|
||||
{
|
||||
uchar *to= *pos;
|
||||
|
||||
tm->neg= 0;
|
||||
tm->year= (uint) sint2korr(to);
|
||||
tm->month= (uint) to[2];
|
||||
tm->day= (uint) to[3];
|
||||
|
||||
if (length > 4)
|
||||
{
|
||||
tm->hour= (uint) to[4];
|
||||
tm->minute= (uint) to[5];
|
||||
tm->second= (uint) to[6];
|
||||
}
|
||||
else
|
||||
tm->hour= tm->minute= tm->second= 0;
|
||||
tm->second_part= (length > 7) ? (ulong) sint4korr(to+7) : 0;
|
||||
tm->time_type= MYSQL_TIMESTAMP_DATETIME;
|
||||
|
||||
*pos+= length;
|
||||
}
|
||||
else
|
||||
{
|
||||
memset(tm, 0, sizeof(*tm));
|
||||
tm->time_type= MYSQL_TIMESTAMP_DATETIME;
|
||||
}
|
||||
}
|
||||
static void fetch_result_datetime_complex(MYSQL_COMPLEX_BIND_BASIC *header,
|
||||
MYSQL_BIND *param,
|
||||
uchar **row)
|
||||
{
|
||||
MYSQL_TIME *tm = NULL;
|
||||
|
||||
tm = fetch_result_complex_alloc_space(header, param, sizeof(MYSQL_TIME));
|
||||
if (NULL == tm) {
|
||||
return;
|
||||
}
|
||||
|
||||
read_binary_datetime(tm, row);
|
||||
return;
|
||||
}
|
||||
|
||||
static void fetch_result_bin_complex(MYSQL_COMPLEX_BIND_STRING *header,
|
||||
MYSQL_BIND *param,
|
||||
uchar **row)
|
||||
{
|
||||
void *buffer;
|
||||
ulong length;
|
||||
|
||||
length = net_field_length(row);
|
||||
|
||||
buffer = fetch_result_complex_alloc_space((MYSQL_COMPLEX_BIND_HEADER *)header, param, length);
|
||||
if (NULL == buffer) {
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(buffer, (char *)*row, length);
|
||||
header->length = length;
|
||||
*row+= length;
|
||||
return;
|
||||
}
|
||||
static void fetch_result_array_complex(MYSQL_COMPLEX_BIND_ARRAY *header,
|
||||
MYSQL_BIND *param,
|
||||
uchar **row,
|
||||
COMPLEX_TYPE *complex_type)
|
||||
{
|
||||
void *buffer = NULL;
|
||||
ulong length = 0;
|
||||
uint num = 0;
|
||||
uint i = 0;
|
||||
COMPLEX_TYPE_COLLECTION *object = NULL;
|
||||
uchar *null_ptr, bit;
|
||||
|
||||
if (NULL == complex_type) {
|
||||
complex_type = get_complex_type(param->mysql, header->owner_name, header->type_name);
|
||||
|
||||
if (complex_type == NULL) {
|
||||
*param->error= 1;
|
||||
return;
|
||||
}
|
||||
} else {/* 匿名数组本地存储信息 */}
|
||||
|
||||
object = (COMPLEX_TYPE_COLLECTION *)complex_type;
|
||||
|
||||
num = net_field_length(row);
|
||||
length = num * get_complex_header_length(object->child.type);
|
||||
|
||||
buffer = fetch_result_complex_alloc_space((MYSQL_COMPLEX_BIND_BASIC *)header, param, length);
|
||||
if (NULL == buffer) {
|
||||
return;
|
||||
}
|
||||
|
||||
null_ptr = *row;
|
||||
*row += (num + 9)/8; /* skip null bits */
|
||||
bit = 4; /* first 2 bits are reserved */
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
fill_complex_type(param, buffer, &(object->child));
|
||||
|
||||
if (*null_ptr & bit) {
|
||||
((MYSQL_COMPLEX_BIND_BASIC *)buffer)->is_null = 1;
|
||||
} else {
|
||||
fetch_result_complex(param, buffer, &(object->child), row);
|
||||
}
|
||||
|
||||
buffer = (char*)buffer + get_complex_header_length(object->child.type);
|
||||
|
||||
if (!((bit<<=1) & 255)) {
|
||||
bit= 1; /* To next uchar */
|
||||
null_ptr++;
|
||||
}
|
||||
}
|
||||
|
||||
header->length = num;
|
||||
return;
|
||||
}
|
||||
static void fetch_result_complex(MYSQL_BIND *param, void *buffer,
|
||||
CHILD_TYPE *child, uchar **row)
|
||||
{
|
||||
switch (child->type) {
|
||||
case TYPE_NUMBER:
|
||||
{
|
||||
fetch_result_str_complex((MYSQL_COMPLEX_BIND_STRING *)buffer, param, row);
|
||||
break;
|
||||
}
|
||||
case TYPE_VARCHAR2:
|
||||
case TYPE_CHAR:
|
||||
{
|
||||
fetch_result_str_complex((MYSQL_COMPLEX_BIND_STRING *)buffer, param, row);
|
||||
break;
|
||||
}
|
||||
case TYPE_RAW:
|
||||
{
|
||||
fetch_result_bin_complex((MYSQL_COMPLEX_BIND_STRING *)buffer, param, row);
|
||||
break;
|
||||
}
|
||||
case TYPE_DATE:
|
||||
{
|
||||
fetch_result_datetime_complex((MYSQL_COMPLEX_BIND_BASIC *)buffer, param, row);
|
||||
break;
|
||||
}
|
||||
case TYPE_OBJECT:
|
||||
{
|
||||
fetch_result_object_complex((MYSQL_COMPLEX_BIND_OBJECT *)buffer, param, row);
|
||||
break;
|
||||
}
|
||||
case TYPE_COLLECTION:
|
||||
{
|
||||
fetch_result_array_complex((MYSQL_COMPLEX_BIND_ARRAY *)buffer, param, row, NULL);
|
||||
break;
|
||||
}
|
||||
case TYPE_LONG:
|
||||
{
|
||||
fetch_result_long_complex((MYSQL_COMPLEX_BIND_BASIC *)buffer, param, row);
|
||||
break;
|
||||
}
|
||||
case TYPE_LONGLONG:
|
||||
{
|
||||
fetch_result_longlong_complex((MYSQL_COMPLEX_BIND_BASIC *)buffer, param, row);
|
||||
break;
|
||||
}
|
||||
case TYPE_TINY:
|
||||
{
|
||||
fetch_result_tiny_complex((MYSQL_COMPLEX_BIND_BASIC *)buffer, param, row);
|
||||
break;
|
||||
}
|
||||
case TYPE_SHORT:
|
||||
{
|
||||
fetch_result_short_complex((MYSQL_COMPLEX_BIND_BASIC *)buffer, param, row);
|
||||
break;
|
||||
}
|
||||
case TYPE_FLOAT:
|
||||
{
|
||||
fetch_result_float_complex((MYSQL_COMPLEX_BIND_BASIC *)buffer, param, row);
|
||||
break;
|
||||
}
|
||||
case TYPE_DOUBLE:
|
||||
{
|
||||
fetch_result_double_complex((MYSQL_COMPLEX_BIND_BASIC *)buffer, param, row);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
*param->error= 1;
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
static void *fetch_result_complex_alloc_space(MYSQL_COMPLEX_BIND_BASIC *header,
|
||||
MYSQL_BIND *param,
|
||||
ulong length)
|
||||
{
|
||||
void *buffer = NULL;
|
||||
(*param->length) += length;
|
||||
if (1 == *param->error) {
|
||||
buffer = (void *)ma_alloc_root(¶m->bind_alloc, length);
|
||||
} else if (param->offset + length > param->buffer_length) {
|
||||
*param->error= 1;
|
||||
buffer = (void *)ma_alloc_root(¶m->bind_alloc, length);
|
||||
} else {
|
||||
buffer = (char*)param->buffer + param->offset;
|
||||
}
|
||||
|
||||
header->buffer = buffer;
|
||||
if (header->buffer) {
|
||||
memset(header->buffer, 0, length);
|
||||
param->offset += length;
|
||||
}
|
||||
|
||||
return (header->buffer);
|
||||
}
|
||||
static uint mysql_type_to_object_type(uint mysql_type)
|
||||
{
|
||||
enum_types object_type;
|
||||
switch ((enum_field_types)mysql_type) {
|
||||
case MYSQL_TYPE_LONG:
|
||||
case MYSQL_TYPE_CURSOR:
|
||||
{
|
||||
object_type = TYPE_LONG;
|
||||
break;
|
||||
}
|
||||
case MYSQL_TYPE_LONGLONG:
|
||||
{
|
||||
object_type = TYPE_LONGLONG;
|
||||
break;
|
||||
}
|
||||
case MYSQL_TYPE_TINY:
|
||||
{
|
||||
object_type = TYPE_TINY;
|
||||
break;
|
||||
}
|
||||
case MYSQL_TYPE_SHORT:
|
||||
{
|
||||
object_type = TYPE_SHORT;
|
||||
break;
|
||||
}
|
||||
case MYSQL_TYPE_FLOAT:
|
||||
{
|
||||
object_type = TYPE_FLOAT;
|
||||
break;
|
||||
}
|
||||
case MYSQL_TYPE_DOUBLE:
|
||||
{
|
||||
object_type = TYPE_DOUBLE;
|
||||
break;
|
||||
}
|
||||
case MYSQL_TYPE_NEWDECIMAL:
|
||||
{
|
||||
object_type = TYPE_NUMBER;
|
||||
break;
|
||||
}
|
||||
case MYSQL_TYPE_VARCHAR:
|
||||
case MYSQL_TYPE_VAR_STRING:
|
||||
case MYSQL_TYPE_STRING:
|
||||
{
|
||||
object_type = TYPE_VARCHAR2;
|
||||
break;
|
||||
}
|
||||
case MYSQL_TYPE_OB_RAW:
|
||||
{
|
||||
object_type = TYPE_RAW;
|
||||
break;
|
||||
}
|
||||
case MYSQL_TYPE_DATETIME:
|
||||
{
|
||||
object_type = TYPE_DATE;
|
||||
break;
|
||||
}
|
||||
case MYSQL_TYPE_OBJECT:
|
||||
{
|
||||
object_type = TYPE_OBJECT;
|
||||
break;
|
||||
}
|
||||
case MYSQL_TYPE_ARRAY:
|
||||
{
|
||||
object_type = TYPE_COLLECTION;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
object_type = TYPE_UNKNOW;
|
||||
break;
|
||||
}
|
||||
return object_type;
|
||||
}
|
||||
static void fill_complex_type(MYSQL_BIND *param, void *buffer,
|
||||
CHILD_TYPE *child)
|
||||
{
|
||||
|
||||
switch (child->type) {
|
||||
case TYPE_NUMBER:
|
||||
{
|
||||
MYSQL_COMPLEX_BIND_DECIMAL *header = (MYSQL_COMPLEX_BIND_DECIMAL *)buffer;
|
||||
header->buffer_type = MYSQL_TYPE_NEWDECIMAL;
|
||||
break;
|
||||
}
|
||||
case TYPE_VARCHAR2:
|
||||
case TYPE_CHAR:
|
||||
{
|
||||
MYSQL_COMPLEX_BIND_STRING *header = (MYSQL_COMPLEX_BIND_STRING *)buffer;
|
||||
header->buffer_type = MYSQL_TYPE_VARCHAR;
|
||||
break;
|
||||
}
|
||||
case TYPE_RAW:
|
||||
{
|
||||
MYSQL_COMPLEX_BIND_STRING *header = (MYSQL_COMPLEX_BIND_STRING *)buffer;
|
||||
header->buffer_type = MYSQL_TYPE_OB_RAW;
|
||||
break;
|
||||
}
|
||||
case TYPE_DATE:
|
||||
{
|
||||
MYSQL_COMPLEX_BIND_BASIC *header = (MYSQL_COMPLEX_BIND_BASIC *)buffer;
|
||||
header->buffer_type = MYSQL_TYPE_DATETIME;
|
||||
break;
|
||||
}
|
||||
case TYPE_LONG:
|
||||
{
|
||||
MYSQL_COMPLEX_BIND_BASIC *header = (MYSQL_COMPLEX_BIND_BASIC *)buffer;
|
||||
header->buffer_type = MYSQL_TYPE_LONG;
|
||||
break;
|
||||
}
|
||||
case TYPE_LONGLONG:
|
||||
{
|
||||
MYSQL_COMPLEX_BIND_BASIC *header = (MYSQL_COMPLEX_BIND_BASIC *)buffer;
|
||||
header->buffer_type = MYSQL_TYPE_LONGLONG;
|
||||
break;
|
||||
}
|
||||
case TYPE_TINY:
|
||||
{
|
||||
MYSQL_COMPLEX_BIND_BASIC *header = (MYSQL_COMPLEX_BIND_BASIC *)buffer;
|
||||
header->buffer_type = MYSQL_TYPE_TINY;
|
||||
break;
|
||||
}
|
||||
case TYPE_SHORT:
|
||||
{
|
||||
MYSQL_COMPLEX_BIND_BASIC *header = (MYSQL_COMPLEX_BIND_BASIC *)buffer;
|
||||
header->buffer_type = MYSQL_TYPE_SHORT;
|
||||
break;
|
||||
}
|
||||
case TYPE_FLOAT:
|
||||
{
|
||||
MYSQL_COMPLEX_BIND_BASIC *header = (MYSQL_COMPLEX_BIND_BASIC *)buffer;
|
||||
header->buffer_type = MYSQL_TYPE_FLOAT;
|
||||
break;
|
||||
}
|
||||
case TYPE_DOUBLE:
|
||||
{
|
||||
MYSQL_COMPLEX_BIND_BASIC *header = (MYSQL_COMPLEX_BIND_BASIC *)buffer;
|
||||
header->buffer_type = MYSQL_TYPE_DOUBLE;
|
||||
break;
|
||||
}
|
||||
case TYPE_OBJECT:
|
||||
{
|
||||
MYSQL_COMPLEX_BIND_OBJECT *header = (MYSQL_COMPLEX_BIND_OBJECT *)buffer;
|
||||
header->buffer_type = MYSQL_TYPE_OBJECT;
|
||||
header->type_name = child->object->type_name;
|
||||
header->owner_name = child->object->owner_name;
|
||||
break;
|
||||
}
|
||||
case TYPE_COLLECTION:
|
||||
{
|
||||
MYSQL_COMPLEX_BIND_ARRAY *header = (MYSQL_COMPLEX_BIND_ARRAY *)buffer;
|
||||
header->buffer_type = MYSQL_TYPE_ARRAY;
|
||||
header->type_name = child->object->type_name;
|
||||
header->owner_name = child->object->owner_name;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
*param->error= 1;
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
static void fetch_result_type_complex(MYSQL_COMPLEX_BIND_OBJECT *header,
|
||||
MYSQL_BIND *param,
|
||||
uchar **row,
|
||||
COMPLEX_TYPE *complex_type)
|
||||
{
|
||||
if (NULL == complex_type) {
|
||||
complex_type = get_complex_type(param->mysql, header->owner_name, header->type_name);
|
||||
if (NULL == complex_type) {
|
||||
*param->error= 1;
|
||||
return;
|
||||
}
|
||||
} else { /*匿名数组,meta信息不能通过server查询,本地传入 */ }
|
||||
|
||||
if (TYPE_OBJECT == complex_type->type) {
|
||||
MYSQL_COMPLEX_BIND_OBJECT *buffer = fetch_result_complex_alloc_space((MYSQL_COMPLEX_BIND_BASIC *)header,
|
||||
param, sizeof(MYSQL_COMPLEX_BIND_OBJECT));
|
||||
|
||||
if (NULL == buffer) {
|
||||
return;
|
||||
}
|
||||
|
||||
buffer->owner_name = header->owner_name;
|
||||
buffer->type_name = header->type_name;
|
||||
buffer->buffer_type = MYSQL_TYPE_OBJECT;
|
||||
|
||||
fetch_result_object_complex(buffer, param, row);
|
||||
} else if (TYPE_COLLECTION == complex_type->type) {
|
||||
MYSQL_COMPLEX_BIND_ARRAY *buffer = fetch_result_complex_alloc_space((MYSQL_COMPLEX_BIND_BASIC *)header,
|
||||
param, sizeof(MYSQL_COMPLEX_BIND_ARRAY));
|
||||
|
||||
if (NULL == buffer) {
|
||||
return;
|
||||
}
|
||||
|
||||
buffer->owner_name = header->owner_name;
|
||||
buffer->type_name = header->type_name;
|
||||
buffer->buffer_type = MYSQL_TYPE_ARRAY;
|
||||
|
||||
fetch_result_array_complex(buffer, param, row, complex_type);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void ps_fetch_result_type(MYSQL_BIND *param,
|
||||
const MYSQL_FIELD *field,
|
||||
uchar **row)
|
||||
{
|
||||
MYSQL_COMPLEX_BIND_OBJECT header;
|
||||
|
||||
(*param->length) = 0;
|
||||
param->offset = 0;
|
||||
ma_init_alloc_root(¶m->bind_alloc, 2048, 0);
|
||||
|
||||
header.owner_name = field->owner_name;
|
||||
header.type_name = field->type_name;
|
||||
|
||||
if (NULL == header.owner_name && NULL == header.type_name) {
|
||||
COMPLEX_TYPE_COLLECTION complex_type;
|
||||
complex_type.header.type = TYPE_COLLECTION;
|
||||
complex_type.header.owner_name[0] = '\0';
|
||||
complex_type.header.type_name[0] = '\0';
|
||||
complex_type.header.version = field->version;
|
||||
complex_type.header.is_valid = TRUE;
|
||||
complex_type.child.type = (enum_types)mysql_type_to_object_type(field->elem_type);
|
||||
|
||||
if (TYPE_UNKNOW == complex_type.child.type) {
|
||||
*param->error = 1;
|
||||
} else {
|
||||
fetch_result_type_complex(&header, param, row, (COMPLEX_TYPE *)&complex_type);
|
||||
}
|
||||
} else {
|
||||
fetch_result_type_complex(&header, param, row, NULL);
|
||||
}
|
||||
|
||||
ma_free_root(¶m->bind_alloc, MYF(0));
|
||||
return;
|
||||
}
|
||||
|
||||
/* {{{ ps_fetch_string */
|
||||
static
|
||||
void ps_fetch_string(MYSQL_BIND *r_param,
|
||||
@ -1304,6 +2006,19 @@ void ps_fetch_bin(MYSQL_BIND *r_param,
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ ps_fetch_result_skip_direct */
|
||||
static
|
||||
void ps_fetch_result_skip_direct(MYSQL_BIND *r_param,
|
||||
const MYSQL_FIELD *field,
|
||||
unsigned char **row)
|
||||
{
|
||||
if (NULL != r_param) {
|
||||
(*r_param->skip_result)(r_param, (MYSQL_FIELD *)field, row);
|
||||
*r_param->error= 0;
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ _mysqlnd_init_ps_subsystem */
|
||||
void mysql_init_ps_subsystem(void)
|
||||
{
|
||||
@ -1332,6 +2047,10 @@ void mysql_init_ps_subsystem(void)
|
||||
mysql_ps_fetch_functions[MYSQL_TYPE_LONG].pack_len = 4;
|
||||
mysql_ps_fetch_functions[MYSQL_TYPE_LONG].max_len = 11;
|
||||
|
||||
mysql_ps_fetch_functions[MYSQL_TYPE_CURSOR].func = ps_fetch_int32; /* parse cursor it with type of INT32 */
|
||||
mysql_ps_fetch_functions[MYSQL_TYPE_CURSOR].pack_len = 4;
|
||||
mysql_ps_fetch_functions[MYSQL_TYPE_CURSOR].max_len = 11;
|
||||
|
||||
mysql_ps_fetch_functions[MYSQL_TYPE_LONGLONG].func = ps_fetch_int64;
|
||||
mysql_ps_fetch_functions[MYSQL_TYPE_LONGLONG].pack_len= 8;
|
||||
mysql_ps_fetch_functions[MYSQL_TYPE_LONGLONG].max_len = 21;
|
||||
@ -1421,6 +2140,18 @@ void mysql_init_ps_subsystem(void)
|
||||
mysql_ps_fetch_functions[MYSQL_TYPE_NEWDECIMAL].pack_len = MYSQL_PS_SKIP_RESULT_STR;
|
||||
mysql_ps_fetch_functions[MYSQL_TYPE_NEWDECIMAL].max_len = -1;
|
||||
|
||||
mysql_ps_fetch_functions[MYSQL_TYPE_OB_NUMBER_FLOAT].func = ps_fetch_string;
|
||||
mysql_ps_fetch_functions[MYSQL_TYPE_OB_NUMBER_FLOAT].pack_len = MYSQL_PS_SKIP_RESULT_STR;
|
||||
mysql_ps_fetch_functions[MYSQL_TYPE_OB_NUMBER_FLOAT].max_len = -1;
|
||||
|
||||
mysql_ps_fetch_functions[MYSQL_TYPE_OB_NVARCHAR2].func = ps_fetch_string;
|
||||
mysql_ps_fetch_functions[MYSQL_TYPE_OB_NVARCHAR2].pack_len = MYSQL_PS_SKIP_RESULT_STR;
|
||||
mysql_ps_fetch_functions[MYSQL_TYPE_OB_NVARCHAR2].max_len = -1;
|
||||
|
||||
mysql_ps_fetch_functions[MYSQL_TYPE_OB_NCHAR].func = ps_fetch_string;
|
||||
mysql_ps_fetch_functions[MYSQL_TYPE_OB_NCHAR].pack_len = MYSQL_PS_SKIP_RESULT_STR;
|
||||
mysql_ps_fetch_functions[MYSQL_TYPE_OB_NCHAR].max_len = -1;
|
||||
|
||||
mysql_ps_fetch_functions[MYSQL_TYPE_ENUM].func = ps_fetch_string;
|
||||
mysql_ps_fetch_functions[MYSQL_TYPE_ENUM].pack_len = MYSQL_PS_SKIP_RESULT_STR;
|
||||
mysql_ps_fetch_functions[MYSQL_TYPE_ENUM].max_len = -1;
|
||||
@ -1429,10 +2160,36 @@ void mysql_init_ps_subsystem(void)
|
||||
mysql_ps_fetch_functions[MYSQL_TYPE_SET].pack_len = MYSQL_PS_SKIP_RESULT_STR;
|
||||
mysql_ps_fetch_functions[MYSQL_TYPE_SET].max_len = -1;
|
||||
|
||||
mysql_ps_fetch_functions[MYSQL_TYPE_OB_UROWID].func = ps_fetch_string;
|
||||
mysql_ps_fetch_functions[MYSQL_TYPE_OB_UROWID].pack_len = MYSQL_PS_SKIP_RESULT_STR;
|
||||
mysql_ps_fetch_functions[MYSQL_TYPE_OB_UROWID].max_len = -1;
|
||||
|
||||
mysql_ps_fetch_functions[MYSQL_TYPE_ORA_BLOB].func = fetch_result_ob_lob;
|
||||
mysql_ps_fetch_functions[MYSQL_TYPE_ORA_BLOB].pack_len = MYSQL_PS_SKIP_RESULT_STR;
|
||||
mysql_ps_fetch_functions[MYSQL_TYPE_ORA_BLOB].max_len = -1;
|
||||
|
||||
|
||||
mysql_ps_fetch_functions[MYSQL_TYPE_ORA_CLOB].func = fetch_result_ob_lob;
|
||||
mysql_ps_fetch_functions[MYSQL_TYPE_ORA_CLOB].pack_len = MYSQL_PS_SKIP_RESULT_STR;
|
||||
mysql_ps_fetch_functions[MYSQL_TYPE_ORA_CLOB].max_len = -1;
|
||||
|
||||
mysql_ps_fetch_functions[MYSQL_TYPE_OB_RAW].func = ps_fetch_string;
|
||||
mysql_ps_fetch_functions[MYSQL_TYPE_OB_RAW].pack_len = MYSQL_PS_SKIP_RESULT_STR;
|
||||
mysql_ps_fetch_functions[MYSQL_TYPE_OB_RAW].max_len = -1;
|
||||
|
||||
mysql_ps_fetch_functions[MYSQL_TYPE_OBJECT].func = ps_fetch_result_type;
|
||||
mysql_ps_fetch_functions[MYSQL_TYPE_OBJECT].pack_len = MYSQL_PS_SKIP_RESULT_STR;
|
||||
mysql_ps_fetch_functions[MYSQL_TYPE_OBJECT].max_len = -1;
|
||||
|
||||
mysql_ps_fetch_functions[MYSQL_TYPE_GEOMETRY].func = ps_fetch_string;
|
||||
mysql_ps_fetch_functions[MYSQL_TYPE_GEOMETRY].pack_len= MYSQL_PS_SKIP_RESULT_STR;
|
||||
mysql_ps_fetch_functions[MYSQL_TYPE_GEOMETRY].max_len = -1;
|
||||
|
||||
//It will be used in returning into
|
||||
mysql_ps_fetch_functions[MAX_NO_FIELD_TYPES].func = ps_fetch_result_skip_direct;
|
||||
mysql_ps_fetch_functions[MAX_NO_FIELD_TYPES].pack_len= MYSQL_PS_SKIP_RESULT_STR;
|
||||
mysql_ps_fetch_functions[MAX_NO_FIELD_TYPES].max_len = -1;
|
||||
|
||||
mysql_ps_subsystem_initialized= 1;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@ -3064,7 +3064,7 @@ dynamic_column_update_move_left(DYNAMIC_COLUMN *str, PLAN *plan,
|
||||
return ER_DYNCOL_OK;
|
||||
}
|
||||
|
||||
#ifdef UNUSED
|
||||
#if 0
|
||||
static enum enum_dyncol_func_result
|
||||
dynamic_column_update_move_right(DYNAMIC_COLUMN *str, PLAN *plan,
|
||||
size_t offset_size,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
80
libmariadb/ob_bitmap.c
Normal file
80
libmariadb/ob_bitmap.c
Normal file
@ -0,0 +1,80 @@
|
||||
/************************************************************************************
|
||||
Copyright (c) 2021 OceanBase.
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not see <http://www.gnu.org/licenses>
|
||||
or write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St., Fifth Floor, Boston, MA 02110, USA
|
||||
|
||||
Part of this code includes code from the PHP project which
|
||||
is freely available from http://www.php.net
|
||||
*************************************************************************************/
|
||||
|
||||
#include "ob_bitmap.h"
|
||||
#include "string.h"
|
||||
|
||||
#define n_bytes_in_map(map) (((map)->n_bits + 7)/8)
|
||||
|
||||
my_bool ob_bitmap_init(OB_BITMAP *map, uint n_bits)
|
||||
{
|
||||
uint size_in_bytes;
|
||||
|
||||
map->n_bits = n_bits;
|
||||
size_in_bytes = n_bytes_in_map(map);
|
||||
|
||||
if (!(map->bitmap = (ob_bitmap_map *)malloc(size_in_bytes))) {
|
||||
return (1);
|
||||
}
|
||||
|
||||
ob_bitmap_clear_all(map);
|
||||
return (0);
|
||||
}
|
||||
|
||||
void ob_bitmap_set_bit(OB_BITMAP *map, uint bit)
|
||||
{
|
||||
if (bit < map->n_bits) {
|
||||
((uchar*)map->bitmap)[bit / 8] |= (1 << (bit & 7));
|
||||
}
|
||||
}
|
||||
|
||||
void ob_bitmap_clear_bit(OB_BITMAP *map, uint bit)
|
||||
{
|
||||
if (bit < map->n_bits) {
|
||||
((uchar*)map->bitmap)[bit / 8] &= ~(1 << (bit & 7));
|
||||
}
|
||||
}
|
||||
|
||||
my_bool ob_bitmap_is_set(const OB_BITMAP *map, uint bit)
|
||||
{
|
||||
if (bit < map->n_bits) {
|
||||
return ((uchar*)map->bitmap)[bit / 8] & (1 << (bit & 7));
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void ob_bitmap_clear_all(OB_BITMAP *map)
|
||||
{
|
||||
memset(map->bitmap, 0, n_bytes_in_map(map));
|
||||
}
|
||||
|
||||
void ob_bitmap_set_all(OB_BITMAP *map)
|
||||
{
|
||||
memset(map->bitmap, 0xFF, n_bytes_in_map(map));
|
||||
}
|
||||
|
||||
void ob_bitmap_free(OB_BITMAP *map)
|
||||
{
|
||||
free(map->bitmap);
|
||||
map->bitmap = NULL;
|
||||
map->n_bits = 0;
|
||||
}
|
||||
636
libmariadb/ob_complex.c
Normal file
636
libmariadb/ob_complex.c
Normal file
@ -0,0 +1,636 @@
|
||||
/*
|
||||
Copyright (c) 2000, 2018, Oracle and/or its affiliates.
|
||||
Copyright (c) 2009, 2019, MariaDB Corporation.
|
||||
Copyright (c) 2021 OceanBase Technology Co.,Ltd.
|
||||
|
||||
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; version 2 of the License.
|
||||
|
||||
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, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */
|
||||
#include "ma_common.h"
|
||||
#include "errmsg.h"
|
||||
#include "ob_complex.h"
|
||||
#include "ma_string.h"
|
||||
|
||||
static OB_HASH *global_hash = NULL;
|
||||
static ob_rw_lock_t global_rwlock = OB_RW_INITIALIZER;
|
||||
static void global_hash_free(void *record);
|
||||
// #define UNUSED(x) ((void)x)
|
||||
#define COMPLEX_TYPE_MAX_SQL_LENGTH 32 * 1024
|
||||
#define COMPLEX_TYPE_MYSQL(M) (MYSQL_EXTENSION_PTR(M)->mysql)
|
||||
#define COMPLEX_TYPE_HASH(M) (MYSQL_EXTENSION_PTR(M)->complex_type_hash)
|
||||
#define COMPLEX_TYPE_USER_TYPES_SQL \
|
||||
"SELECT "\
|
||||
" 0 DEPTH, "\
|
||||
" NULL PARENT_OWNER, "\
|
||||
" NULL PARENT_TYPE, "\
|
||||
" TYPE_NAME CHILD_TYPE, "\
|
||||
" 0 ATTR_NO, "\
|
||||
" SYS_CONTEXT('USERENV', 'CURRENT_USER') CHILD_TYPE_OWNER, "\
|
||||
" A.TYPECODE ATTR_TYPE_CODE, "\
|
||||
" NULL LENGTH, "\
|
||||
" NULL NUMBER_PRECISION, "\
|
||||
" NULL SCALE, "\
|
||||
" NULL CHARACTER_SET_NAME "\
|
||||
"FROM "\
|
||||
" USER_TYPES A WHERE TYPE_NAME = '%s' "\
|
||||
"UNION "\
|
||||
"( "\
|
||||
" WITH "\
|
||||
" CTE_RESULT(PARENT_OWNER, PARENT_TYPE, CHILD_TYPE, ATTR_NO, CHILD_TYPE_OWNER, ATTR_TYPE_CODE, LENGTH, NUMBER_PRECISION, SCALE, CHARACTER_SET_NAME) "\
|
||||
" AS ( "\
|
||||
" SELECT "\
|
||||
" SYS_CONTEXT('USERENV','CURRENT_USER') PARENT_OWNER, "\
|
||||
" B.TYPE_NAME PARENT_TYPE, "\
|
||||
" B.ELEM_TYPE_NAME CHILD_TYPE, "\
|
||||
" 0 ATTR_NO, "\
|
||||
" B.ELEM_TYPE_OWNER CHILD_TYPE_OWNER, "\
|
||||
" NVL(A.TYPECODE, B.ELEM_TYPE_NAME) AS ATTR_TYPE_CODE, "\
|
||||
" B.LENGTH LENGTH, "\
|
||||
" B.NUMBER_PRECISION NUMBER_PRECISION, "\
|
||||
" B.SCALE SCALE, "\
|
||||
" B.CHARACTER_SET_NAME CHARACTER_SET_NAME "\
|
||||
" FROM "\
|
||||
" USER_COLL_TYPES B LEFT JOIN USER_TYPES A ON A.TYPE_NAME = B.ELEM_TYPE_NAME "\
|
||||
" UNION "\
|
||||
" SELECT "\
|
||||
" SYS_CONTEXT('USERENV','CURRENT_USER') PARENT_OWNER, "\
|
||||
" B.TYPE_NAME PARENT_TYPE, "\
|
||||
" B.ATTR_TYPE_NAME CHILD_TYPE, "\
|
||||
" B.ATTR_NO ATTR_NO, "\
|
||||
" B.ATTR_TYPE_OWNER CHILD_TYPE_OWNER, "\
|
||||
" NVL(A.TYPECODE, B.ATTR_TYPE_NAME) AS ATTR_TYPE_CODE, "\
|
||||
" B.LENGTH LENGTH, "\
|
||||
" B.NUMBER_PRECISION NUMBER_PRECISION, "\
|
||||
" B.SCALE SCALE, "\
|
||||
" B.CHARACTER_SET_NAME CHARACTER_SET_NAME "\
|
||||
" FROM USER_TYPE_ATTRS B LEFT JOIN USER_TYPES A ON B.ATTR_TYPE_NAME = A.TYPE_NAME ORDER BY ATTR_NO "\
|
||||
" ) , "\
|
||||
" CTE(DEPTH, PARENT_OWNER, PARENT_TYPE, CHILD_TYPE, ATTR_NO, CHILD_TYPE_OWNER, ATTR_TYPE_CODE, LENGTH, NUMBER_PRECISION, SCALE, CHARACTER_SET_NAME) "\
|
||||
" AS ( "\
|
||||
" SELECT "\
|
||||
" 1 DEPTH, "\
|
||||
" PARENT_OWNER, "\
|
||||
" PARENT_TYPE, "\
|
||||
" CHILD_TYPE, "\
|
||||
" ATTR_NO, "\
|
||||
" CHILD_TYPE_OWNER, "\
|
||||
" ATTR_TYPE_CODE, "\
|
||||
" LENGTH, "\
|
||||
" NUMBER_PRECISION, "\
|
||||
" SCALE, CHARACTER_SET_NAME "\
|
||||
" FROM CTE_RESULT WHERE PARENT_TYPE = '%s' "\
|
||||
" UNION ALL "\
|
||||
" SELECT "\
|
||||
" DEPTH + 1 DEPTH, "\
|
||||
" CTE_RESULT.PARENT_OWNER, "\
|
||||
" CTE_RESULT.PARENT_TYPE, "\
|
||||
" CTE_RESULT.CHILD_TYPE, "\
|
||||
" CTE_RESULT.ATTR_NO, "\
|
||||
" CTE_RESULT.CHILD_TYPE_OWNER, "\
|
||||
" CTE_RESULT.ATTR_TYPE_CODE, "\
|
||||
" CTE_RESULT.LENGTH, "\
|
||||
" CTE_RESULT.NUMBER_PRECISION, "\
|
||||
" CTE_RESULT.SCALE, "\
|
||||
" CTE_RESULT.CHARACTER_SET_NAME "\
|
||||
" FROM CTE_RESULT INNER JOIN CTE ON CTE_RESULT.PARENT_TYPE = CTE.CHILD_TYPE "\
|
||||
" ) "\
|
||||
" SELECT * FROM CTE "\
|
||||
"); "\
|
||||
|
||||
#define COMPLEX_TYPE_ALL_TYPES_SQL \
|
||||
"SELECT "\
|
||||
" 0 DEPTH, "\
|
||||
" NULL PRAENT_OWNER, "\
|
||||
" NULL PARENT_TYPE, "\
|
||||
" to_char(TYPE_NAME) CHILD_TYPE, "\
|
||||
" 0 ATTR_NO, "\
|
||||
" OWNER CHILD_TYPE_OWNER, "\
|
||||
" A.TYPECODE ATTR_TYPE_CODE, "\
|
||||
" NULL LENGTH, "\
|
||||
" NULL NUMBER_PRECISION, "\
|
||||
" NULL SCALE, "\
|
||||
" NULL CHARACTER_SET_NAME "\
|
||||
" FROM "\
|
||||
" ALL_TYPES A WHERE TYPE_NAME = '%s' AND OWNER = '%s' "\
|
||||
" UNION "\
|
||||
" ( "\
|
||||
" WITH "\
|
||||
" CTE_RESULT(PARENT_OWNER, PARENT_TYPE, CHILD_TYPE, ATTR_NO, CHILD_TYPE_OWNER, ATTR_TYPE_CODE, LENGTH, NUMBER_PRECISION, SCALE, CHARACTER_SET_NAME) "\
|
||||
" AS ( "\
|
||||
" SELECT "\
|
||||
" B.OWNER PARENT_OWNER, "\
|
||||
" B.TYPE_NAME PARENT_TYPE, "\
|
||||
" B.ELEM_TYPE_NAME CHILD_TYPE, "\
|
||||
" 0 ATTR_NO, "\
|
||||
" B.ELEM_TYPE_OWNER CHILD_TYPE_OWNER, "\
|
||||
" NVL(A.TYPECODE, B.ELEM_TYPE_NAME) AS ATTR_TYPE_CODE, "\
|
||||
" B.LENGTH LENGTH, "\
|
||||
" B.NUMBER_PRECISION NUMBER_PRECISION, "\
|
||||
" B.SCALE SCALE, "\
|
||||
" B.CHARACTER_SET_NAME CHARACTER_SET_NAME "\
|
||||
" FROM "\
|
||||
" ALL_COLL_TYPES B LEFT JOIN ALL_TYPES A ON A.TYPE_NAME = B.ELEM_TYPE_NAME AND A.OWNER = B.ELEM_TYPE_OWNER "\
|
||||
" UNION "\
|
||||
" SELECT "\
|
||||
" B.OWNER PARENT_OWNER, "\
|
||||
" B.TYPE_NAME PARENT_TYPE, "\
|
||||
" B.ATTR_TYPE_NAME CHILD_TYPE, "\
|
||||
" B.ATTR_NO ATTR_NO, "\
|
||||
" B.ATTR_TYPE_OWNER CHILD_TYPE_OWNER, "\
|
||||
" NVL(A.TYPECODE, B.ATTR_TYPE_NAME) AS ATTR_TYPE_CODE, "\
|
||||
" B.LENGTH LENGTH, "\
|
||||
" B.NUMBER_PRECISION NUMBER_PRECISION, "\
|
||||
" B.SCALE SCALE, "\
|
||||
" B.CHARACTER_SET_NAME CHARACTER_SET_NAME "\
|
||||
" FROM ALL_TYPE_ATTRS B LEFT JOIN ALL_TYPES A ON A.TYPE_NAME = B.ATTR_TYPE_NAME AND A.OWNER = B.ATTR_TYPE_OWNER ORDER BY ATTR_NO "\
|
||||
" ) , "\
|
||||
" CTE(DEPTH, PARENT_OWNER, PARENT_TYPE, CHILD_TYPE, ATTR_NO, CHILD_TYPE_OWNER, ATTR_TYPE_CODE, LENGTH, NUMBER_PRECISION, SCALE, CHARACTER_SET_NAME) "\
|
||||
" AS ( "\
|
||||
" SELECT "\
|
||||
" 1 DEPTH, "\
|
||||
" PARENT_OWNER, "\
|
||||
" PARENT_TYPE, "\
|
||||
" CHILD_TYPE, "\
|
||||
" ATTR_NO, "\
|
||||
" CHILD_TYPE_OWNER, "\
|
||||
" ATTR_TYPE_CODE, "\
|
||||
" LENGTH, "\
|
||||
" NUMBER_PRECISION, "\
|
||||
" SCALE, CHARACTER_SET_NAME "\
|
||||
" FROM CTE_RESULT WHERE PARENT_TYPE = '%s' AND PARENT_OWNER = '%s' "\
|
||||
" UNION ALL "\
|
||||
" SELECT "\
|
||||
" DEPTH + 1 DEPTH, "\
|
||||
" CTE_RESULT.PARENT_OWNER, "\
|
||||
" CTE_RESULT.PARENT_TYPE, "\
|
||||
" CTE_RESULT.CHILD_TYPE, "\
|
||||
" CTE_RESULT.ATTR_NO, "\
|
||||
" CTE_RESULT.CHILD_TYPE_OWNER, "\
|
||||
" CTE_RESULT.ATTR_TYPE_CODE, "\
|
||||
" CTE_RESULT.LENGTH, "\
|
||||
" CTE_RESULT.NUMBER_PRECISION, "\
|
||||
" CTE_RESULT.SCALE, "\
|
||||
" CTE_RESULT.CHARACTER_SET_NAME "\
|
||||
" FROM CTE_RESULT INNER JOIN CTE ON CTE_RESULT.PARENT_TYPE = CTE.CHILD_TYPE AND CTE_RESULT.PARENT_OWNER = CTE.CHILD_TYPE_OWNER "\
|
||||
" ) "\
|
||||
" SELECT * FROM CTE "\
|
||||
"); "\
|
||||
|
||||
#define DEPTH_INDEX 0
|
||||
#define PARENT_TYPE_INDEX 2
|
||||
#define CHILD_TYPE_INDEX 3
|
||||
#define ATTR_NO_INDEX 4
|
||||
#define CHILD_OWNER_INDEX 5
|
||||
#define ATTR_TYPE_INDEX 6
|
||||
|
||||
static enum_types convert_type(const char *type) {
|
||||
if (!strcmp(type, "COLLECTION")) {
|
||||
return TYPE_COLLECTION;
|
||||
} else if (!strcmp(type, "OBJECT")) {
|
||||
return TYPE_OBJECT;
|
||||
} else if (!strcmp(type, "NUMBER")) {
|
||||
return TYPE_NUMBER;
|
||||
} else if (!strcmp(type, "VARCHAR2")) {
|
||||
return TYPE_VARCHAR2;
|
||||
} else if (!strcmp(type, "CHAR")) {
|
||||
return TYPE_CHAR;
|
||||
} else if (!strcmp(type, "DATE")) {
|
||||
return TYPE_DATE;
|
||||
} else if (!strcmp(type, "RAW")) {
|
||||
return TYPE_RAW;
|
||||
} else {
|
||||
return TYPE_MAX;
|
||||
}
|
||||
}
|
||||
|
||||
static int STDCALL
|
||||
parser_complex(MYSQL_RES *result, OB_HASH *hash)
|
||||
{
|
||||
MYSQL_ROW cur;
|
||||
|
||||
COMPLEX_TYPE *complex_type;
|
||||
unsigned char *parent_name;
|
||||
COMPLEX_TYPE *parent;
|
||||
while ((cur = mysql_fetch_row(result))) {
|
||||
unsigned int type_size;
|
||||
enum_types type = convert_type(cur[ATTR_TYPE_INDEX]);
|
||||
|
||||
if (TYPE_OBJECT == type || TYPE_COLLECTION == type) {
|
||||
complex_type = (COMPLEX_TYPE *) hash_search(hash, (unsigned char*)cur[CHILD_TYPE_INDEX], strlen(cur[CHILD_TYPE_INDEX]));
|
||||
|
||||
if (!complex_type) {
|
||||
type_size = TYPE_COLLECTION == type ? sizeof(COMPLEX_TYPE_COLLECTION) : sizeof(COMPLEX_TYPE_OBJECT);
|
||||
complex_type = (COMPLEX_TYPE *) calloc(1, type_size);
|
||||
|
||||
if (!complex_type) {
|
||||
return (1);
|
||||
}
|
||||
|
||||
complex_type->is_valid = 0;
|
||||
complex_type->type = type;
|
||||
if (TYPE_OBJECT == complex_type->type) {
|
||||
((COMPLEX_TYPE_OBJECT *)complex_type)->attr_no = 0;
|
||||
}
|
||||
/* name 被初始化成了 0, 所以不需要拷贝最后的 NULL 结束符 */
|
||||
memcpy(complex_type->type_name, cur[CHILD_TYPE_INDEX], strlen(cur[CHILD_TYPE_INDEX]));
|
||||
memcpy(complex_type->owner_name, cur[CHILD_OWNER_INDEX], strlen(cur[CHILD_OWNER_INDEX]));
|
||||
|
||||
if (hash_insert(hash, (unsigned char *)complex_type)) {
|
||||
return (1);
|
||||
}
|
||||
} else {
|
||||
//ReInit node's info in the query
|
||||
complex_type->is_valid = 0;
|
||||
if (TYPE_OBJECT == complex_type->type) {
|
||||
((COMPLEX_TYPE_OBJECT *)complex_type)->attr_no = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (atoi(cur[DEPTH_INDEX]) != 0) {
|
||||
parent_name = (unsigned char *)cur[PARENT_TYPE_INDEX];
|
||||
parent = (COMPLEX_TYPE *) hash_search(hash, parent_name, strlen((char *)parent_name));
|
||||
|
||||
if (parent == NULL) {
|
||||
return (1);
|
||||
}
|
||||
|
||||
if (TYPE_OBJECT == parent->type &&
|
||||
((COMPLEX_TYPE_OBJECT *)parent)->attr_no < strtoul(cur[ATTR_NO_INDEX], NULL, 10)) {
|
||||
((COMPLEX_TYPE_OBJECT *)parent)->attr_no = strtoul(cur[ATTR_NO_INDEX], NULL, 10);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result->data_cursor = result->data->data;
|
||||
|
||||
while ((cur = mysql_fetch_row(result))) {
|
||||
enum_types child_type;
|
||||
COMPLEX_TYPE_OBJECT *parent_object;
|
||||
COMPLEX_TYPE_COLLECTION *parent_collection;
|
||||
|
||||
if (atoi(cur[DEPTH_INDEX]) != 0) {
|
||||
parent_name = (unsigned char *)cur[PARENT_TYPE_INDEX];
|
||||
parent = (COMPLEX_TYPE *) hash_search(hash, parent_name, strlen((char *)parent_name));
|
||||
|
||||
if (parent == NULL) {
|
||||
return (1);
|
||||
}
|
||||
|
||||
child_type = convert_type(cur[ATTR_TYPE_INDEX]);
|
||||
|
||||
if (TYPE_OBJECT == parent->type) {
|
||||
parent_object = (COMPLEX_TYPE_OBJECT *)parent;
|
||||
|
||||
if (parent_object->child == NULL) {
|
||||
parent_object->child = (CHILD_TYPE *) calloc(1, parent_object->attr_no * sizeof(CHILD_TYPE));
|
||||
|
||||
if (parent_object->child == NULL) {
|
||||
return (1);
|
||||
}
|
||||
}
|
||||
|
||||
parent_object->child[atoi(cur[ATTR_NO_INDEX]) - 1].type = child_type;
|
||||
|
||||
if (TYPE_COLLECTION == child_type || TYPE_OBJECT == child_type) {
|
||||
complex_type = (COMPLEX_TYPE *)hash_search(hash,
|
||||
(unsigned char *)cur[CHILD_TYPE_INDEX], strlen(cur[CHILD_TYPE_INDEX]));
|
||||
|
||||
if (complex_type == NULL) {
|
||||
return (1);
|
||||
}
|
||||
|
||||
parent_object->child[atoi(cur[ATTR_NO_INDEX]) - 1].object = complex_type;
|
||||
}
|
||||
|
||||
parent_object->init_attr_no++;
|
||||
|
||||
if (parent_object->init_attr_no == parent_object->attr_no) {
|
||||
parent->is_valid = 1;
|
||||
}
|
||||
|
||||
} else if (TYPE_COLLECTION == parent->type) {
|
||||
parent_collection = (COMPLEX_TYPE_COLLECTION *)parent;
|
||||
|
||||
parent_collection->child.type = child_type;
|
||||
|
||||
if (TYPE_COLLECTION == child_type || TYPE_OBJECT == child_type) {
|
||||
complex_type = (COMPLEX_TYPE *)hash_search(hash,
|
||||
(unsigned char *)cur[CHILD_TYPE_INDEX], strlen(cur[CHILD_TYPE_INDEX]));
|
||||
|
||||
if (complex_type == NULL) {
|
||||
return (1);
|
||||
}
|
||||
|
||||
parent_collection->child.object = complex_type;
|
||||
}
|
||||
|
||||
parent->is_valid = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int STDCALL
|
||||
get_type_from_server(MYSQL *mysql, unsigned char *owner_name, unsigned char *type_name, COMPLEX_HASH *complex_hash)
|
||||
{
|
||||
int retval;
|
||||
MYSQL_RES *result;
|
||||
char sql[COMPLEX_TYPE_MAX_SQL_LENGTH] = {'\0'};
|
||||
|
||||
if (NULL != owner_name) {
|
||||
snprintf(sql, COMPLEX_TYPE_MAX_SQL_LENGTH, COMPLEX_TYPE_ALL_TYPES_SQL, type_name, owner_name, type_name, owner_name);
|
||||
} else {
|
||||
/* 如果 owner 为空, 先从 user_types 视图中获取 */
|
||||
snprintf(sql, COMPLEX_TYPE_MAX_SQL_LENGTH, COMPLEX_TYPE_USER_TYPES_SQL, type_name, type_name);
|
||||
}
|
||||
|
||||
if (mysql_real_query(mysql, sql, strlen(sql))) {
|
||||
return (1);
|
||||
}
|
||||
|
||||
if (!(result = mysql_store_result(mysql))) {
|
||||
return (1);
|
||||
/* 如果 user_types 视图中没有该 type, 在再从 all_types 视图中获取 */
|
||||
} else if (0 == mysql_num_rows(result) && NULL == owner_name) {
|
||||
mysql_free_result(result);
|
||||
snprintf(sql, COMPLEX_TYPE_MAX_SQL_LENGTH, COMPLEX_TYPE_ALL_TYPES_SQL, type_name, "SYS", type_name, "SYS");
|
||||
|
||||
if (mysql_real_query(mysql, sql, strlen(sql))) {
|
||||
return (1);
|
||||
}
|
||||
|
||||
if (!(result = mysql_store_result(mysql))) {
|
||||
return (1);
|
||||
}
|
||||
}
|
||||
|
||||
ob_rw_wrlock(&(complex_hash->rwlock));
|
||||
retval = parser_complex(result, complex_hash->hash);
|
||||
ob_rw_unlock(&(complex_hash->rwlock));
|
||||
|
||||
mysql_free_result(result);
|
||||
|
||||
return (retval);
|
||||
}
|
||||
|
||||
static int STDCALL
|
||||
complex_mysql_init(MYSQL *mysql, MYSQL **complex_mysql)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
*complex_mysql = NULL;
|
||||
|
||||
if (!(*complex_mysql = mysql_init(*complex_mysql))) {
|
||||
ret = 1;
|
||||
} else if (!mysql_real_connect(*complex_mysql, mysql->host, mysql->user, mysql->passwd,
|
||||
mysql->db, mysql->port, mysql->unix_socket, 0))
|
||||
{
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
if (ret != 0 && *complex_mysql != NULL) {
|
||||
mysql_close(*complex_mysql);
|
||||
*complex_mysql = NULL;
|
||||
}
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static void complex_hash_free(void *record)
|
||||
{
|
||||
COMPLEX_TYPE *header = (COMPLEX_TYPE *)record;
|
||||
if (header->type == TYPE_OBJECT) {
|
||||
free(((COMPLEX_TYPE_OBJECT *)header)->child);
|
||||
}
|
||||
|
||||
free(header);
|
||||
}
|
||||
|
||||
static unsigned char *complex_get_hash_key(const unsigned char *record, uint *length,
|
||||
my_bool not_used)
|
||||
{
|
||||
COMPLEX_TYPE *type = (COMPLEX_TYPE *)record;
|
||||
*length= strlen((char *)type->type_name);
|
||||
UNUSED(not_used);
|
||||
return type->type_name;
|
||||
}
|
||||
|
||||
static int STDCALL
|
||||
complex_hash_init(MYSQL *mysql, unsigned char *hash_key, COMPLEX_HASH **complex_hash)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
*complex_hash = NULL;
|
||||
|
||||
if (!(*complex_hash = calloc(1, sizeof(COMPLEX_HASH)))) {
|
||||
SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
|
||||
ret = 1;
|
||||
} else if(ob_rw_init(&((*complex_hash)->rwlock))) {
|
||||
SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
|
||||
ret = 1;
|
||||
} else if (!((*complex_hash)->hash = calloc(1, sizeof(OB_HASH)))) {
|
||||
SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
|
||||
ret = 1;
|
||||
} else if (hash_init((*complex_hash)->hash, 0, 0, 0, (hash_get_key) complex_get_hash_key,
|
||||
complex_hash_free, HASH_CASE_INSENSITIVE)) {
|
||||
SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
|
||||
ret = 1;
|
||||
} else if (!((*complex_hash)->hash_key = calloc(1, strlen((char *)hash_key) + 1))) {
|
||||
SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
|
||||
ret = 1;
|
||||
} else {
|
||||
//memset((*complex_hash)->hash_key, 0, strlen((char *)hash_key) + 1);
|
||||
memcpy((*complex_hash)->hash_key, hash_key, strlen((char *)hash_key));
|
||||
(*complex_hash)->hash_key[strlen((char *)hash_key)] = '\0';
|
||||
if (hash_insert(global_hash, (unsigned char *)(*complex_hash))) {
|
||||
SET_CLIENT_ERROR(mysql, CR_UNKNOWN_ERROR, SQLSTATE_UNKNOWN, 0);
|
||||
ret = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (ret && *complex_hash != NULL) {
|
||||
global_hash_free((void *)(*complex_hash));
|
||||
*complex_hash = NULL;
|
||||
}
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static void global_hash_free(void *record)
|
||||
{
|
||||
COMPLEX_HASH *complex_hash = (COMPLEX_HASH *)record;
|
||||
if (NULL != complex_hash->hash_key) {
|
||||
free(complex_hash->hash_key);
|
||||
}
|
||||
|
||||
if (NULL != complex_hash->hash) {
|
||||
hash_free(complex_hash->hash);
|
||||
free(complex_hash->hash);
|
||||
}
|
||||
|
||||
ob_rw_destroy(&(complex_hash->rwlock));
|
||||
free(complex_hash);
|
||||
}
|
||||
|
||||
static unsigned char *global_get_hash_key(const unsigned char *record, uint *length,
|
||||
my_bool not_used)
|
||||
{
|
||||
COMPLEX_HASH *complex_hash = (COMPLEX_HASH *)record;
|
||||
*length= strlen((char *)complex_hash->hash_key);
|
||||
UNUSED(not_used);
|
||||
return complex_hash->hash_key;
|
||||
}
|
||||
|
||||
static int STDCALL
|
||||
global_hash_init(MYSQL *mysql)
|
||||
{
|
||||
if (!(global_hash = calloc(1, sizeof(OB_HASH)))) {
|
||||
SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
|
||||
return 1;
|
||||
} else if (hash_init(global_hash, 0, 0, 0, (hash_get_key) global_get_hash_key,
|
||||
global_hash_free, HASH_CASE_INSENSITIVE)) {
|
||||
hash_free(global_hash);
|
||||
free(global_hash);
|
||||
SET_CLIENT_ERROR(mysql, CR_UNKNOWN_ERROR, SQLSTATE_UNKNOWN, 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char digits[]= "0123456789abcdef";
|
||||
|
||||
char *ma_safe_utoa(int base, ulonglong val, char *buf)
|
||||
{
|
||||
*buf--= 0;
|
||||
do {
|
||||
*buf--= digits[val % base];
|
||||
} while ((val /= base) != 0);
|
||||
return buf + 1;
|
||||
}
|
||||
static int STDCALL
|
||||
get_complex_hash(MYSQL *mysql, unsigned char *hash_key, int buffer_len, COMPLEX_HASH **complex_hash)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
*complex_hash = NULL;
|
||||
|
||||
if (NULL == global_hash) {
|
||||
ob_rw_wrlock(&global_rwlock);
|
||||
if (NULL == global_hash && global_hash_init(mysql)) {
|
||||
ret = 1;
|
||||
}
|
||||
ob_rw_unlock(&global_rwlock);
|
||||
}
|
||||
if (ret == 0) {
|
||||
unsigned int hash_length = 0;
|
||||
char port[10] = {'\0'};
|
||||
char *port_ptr = NULL;
|
||||
port_ptr = ma_safe_utoa(10, mysql->port, &port[sizeof(port)-1]);
|
||||
if (strlen(mysql->host) + strlen(port_ptr) + strlen(mysql->user) + 1 >= (size_t)buffer_len) {
|
||||
ret = 1;
|
||||
} else if ((NULL != mysql->db) && (strlen(mysql->host) + strlen(port_ptr) + strlen(mysql->user) +
|
||||
strlen(mysql->db) + 1 >= (size_t)buffer_len)) {
|
||||
ret = 1;
|
||||
} else {
|
||||
memcpy(hash_key + hash_length, mysql->host, strlen(mysql->host));
|
||||
hash_length += strlen(mysql->host);
|
||||
|
||||
memcpy(hash_key + hash_length, port_ptr, strlen(port_ptr));
|
||||
hash_length += strlen(port_ptr);
|
||||
|
||||
memcpy(hash_key + hash_length, mysql->user, strlen(mysql->user));
|
||||
hash_length += strlen(mysql->user);
|
||||
if (NULL != mysql->db) {
|
||||
memcpy(hash_key + hash_length, mysql->db, strlen(mysql->db));
|
||||
hash_length += strlen(mysql->db);
|
||||
}
|
||||
hash_key[hash_length] = '\0';
|
||||
ob_rw_rdlock(&global_rwlock);
|
||||
*complex_hash = (COMPLEX_HASH *)hash_search(global_hash, hash_key, strlen((char *)hash_key));
|
||||
ob_rw_unlock(&global_rwlock);
|
||||
|
||||
if (NULL == *complex_hash) {
|
||||
ob_rw_wrlock(&global_rwlock);
|
||||
if (NULL == *complex_hash) {
|
||||
if (complex_hash_init(mysql, hash_key, complex_hash)) {
|
||||
ret = 1;
|
||||
}
|
||||
}
|
||||
ob_rw_unlock(&global_rwlock);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
COMPLEX_TYPE* STDCALL
|
||||
get_complex_type(MYSQL *mysql, unsigned char *owner_name, unsigned char *type_name)
|
||||
{
|
||||
COMPLEX_TYPE *type = NULL;
|
||||
COMPLEX_HASH *complex_hash = NULL;
|
||||
MYSQL *complex_mysql = NULL;
|
||||
unsigned char hash_key[200] = {'\0'};
|
||||
|
||||
if (get_complex_hash(mysql, hash_key, 200, &complex_hash)) {
|
||||
} else {
|
||||
ob_rw_rdlock(&(complex_hash->rwlock));
|
||||
type = (COMPLEX_TYPE *)hash_search(complex_hash->hash, type_name, strlen((char *)type_name));
|
||||
ob_rw_unlock(&(complex_hash->rwlock));
|
||||
|
||||
if (NULL == type || type->is_valid != 1) {
|
||||
if (complex_mysql_init(mysql, &complex_mysql)) {
|
||||
} else if (get_type_from_server(complex_mysql, owner_name, type_name, complex_hash)) {
|
||||
} else {
|
||||
ob_rw_rdlock(&(complex_hash->rwlock));
|
||||
type = (COMPLEX_TYPE *)hash_search(complex_hash->hash, type_name, strlen((char *)type_name));
|
||||
ob_rw_unlock(&(complex_hash->rwlock));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (complex_mysql != NULL) {
|
||||
mysql_close(complex_mysql);
|
||||
complex_mysql = NULL;
|
||||
}
|
||||
|
||||
if (type && type->is_valid != 1) {
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
return (type);
|
||||
}
|
||||
|
||||
COMPLEX_TYPE* STDCALL
|
||||
get_complex_type_with_local(MYSQL *mysql, unsigned char *type_name)
|
||||
{
|
||||
COMPLEX_TYPE *type = NULL;
|
||||
COMPLEX_HASH *complex_hash = NULL;
|
||||
unsigned char hash_key[200] = {'\0'};
|
||||
memset(hash_key, 0, 200);
|
||||
|
||||
if (get_complex_hash(mysql, hash_key, 200, &complex_hash)) {
|
||||
} else {
|
||||
ob_rw_rdlock(&(complex_hash->rwlock));
|
||||
type = (COMPLEX_TYPE *)hash_search(complex_hash->hash, type_name, strlen((char *)type_name));
|
||||
ob_rw_unlock(&(complex_hash->rwlock));
|
||||
}
|
||||
|
||||
if (type && type->is_valid != 1) {
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
return (type);
|
||||
}
|
||||
140
libmariadb/ob_cond.c
Normal file
140
libmariadb/ob_cond.c
Normal file
@ -0,0 +1,140 @@
|
||||
/************************************************************************
|
||||
Copyright (c) 2021 OceanBase.
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
MA 02111-1301, USA
|
||||
|
||||
Part of this code includes code from PHP's mysqlnd extension
|
||||
(written by Andrey Hristov, Georg Richter and Ulf Wendel), freely
|
||||
available from http://www.php.net/software
|
||||
|
||||
*************************************************************************/
|
||||
|
||||
#include "ob_cond.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <time.h>
|
||||
|
||||
union ft64 {
|
||||
FILETIME ft;
|
||||
__int64 i64;
|
||||
};
|
||||
|
||||
DWORD ob_get_milliseconds(const struct timespec *ob_timespec)
|
||||
{
|
||||
DWORD ret;
|
||||
union ft64 ob_now_time;
|
||||
long long ob_millis_time;
|
||||
unsigned __int64 obtime;
|
||||
static const unsigned __int64 EPOCH = ((unsigned __int64)116444736000000000ULL);
|
||||
|
||||
if (NULL == ob_timespec) {
|
||||
ret = INFINITE;
|
||||
} else {
|
||||
obtime = ob_timespec->tv_sec * 10000000L + EPOCH;
|
||||
GetSystemTimeAsFileTime(&ob_now_time.ft);
|
||||
ob_millis_time = (obtime - ob_now_time.i64) / 10000;
|
||||
if (ob_millis_time < 0) {
|
||||
ret = 0;
|
||||
} else {
|
||||
if (ob_millis_time > UINT_MAX) {
|
||||
ob_millis_time= UINT_MAX;
|
||||
}
|
||||
ret = ob_millis_time;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ob_cond_init(ob_cond_t *ob_cond)
|
||||
{
|
||||
InitializeConditionVariable(ob_cond);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ob_cond_destroy(ob_cond_t *ob_cond)
|
||||
{
|
||||
// do nothing
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ob_cond_timedwait(ob_cond_t *ob_cond, ob_mutex_t *ob_mutex, const struct timespec *ob_timespec)
|
||||
{
|
||||
int ret;
|
||||
DWORD timeout= ob_get_milliseconds(ob_timespec);
|
||||
if (!SleepConditionVariableCS(ob_cond, ob_mutex, timeout)) {
|
||||
ret = ETIMEDOUT;
|
||||
} else {
|
||||
ret = 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ob_cond_wait(ob_cond_t *ob_cond, ob_mutex_t *ob_mutex)
|
||||
{
|
||||
int ret;
|
||||
if (!SleepConditionVariableCS(ob_cond, ob_mutex, INFINITE)) {
|
||||
ret = ETIMEDOUT;
|
||||
} else {
|
||||
ret = 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ob_cond_signal(ob_cond_t *ob_cond)
|
||||
{
|
||||
WakeConditionVariable(ob_cond);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ob_cond_broadcast(ob_cond_t *ob_cond)
|
||||
{
|
||||
WakeAllConditionVariable(ob_cond);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
int ob_cond_init(ob_cond_t *ob_cond)
|
||||
{
|
||||
return pthread_cond_init(ob_cond, NULL);
|
||||
}
|
||||
|
||||
int ob_cond_destroy(ob_cond_t *ob_cond)
|
||||
{
|
||||
return pthread_cond_destroy(ob_cond);
|
||||
}
|
||||
|
||||
int ob_cond_timedwait(ob_cond_t *ob_cond, ob_mutex_t *ob_mutex, const struct timespec *ob_timespec)
|
||||
{
|
||||
return pthread_cond_timedwait(ob_cond, ob_mutex, ob_timespec);
|
||||
}
|
||||
|
||||
int ob_cond_wait(ob_cond_t *ob_cond, ob_mutex_t *ob_mutex)
|
||||
{
|
||||
return pthread_cond_wait(ob_cond, ob_mutex);
|
||||
}
|
||||
|
||||
int ob_cond_signal(ob_cond_t *ob_cond)
|
||||
{
|
||||
return pthread_cond_signal(ob_cond);
|
||||
}
|
||||
|
||||
int ob_cond_broadcast(ob_cond_t *ob_cond)
|
||||
{
|
||||
return pthread_cond_broadcast(ob_cond);
|
||||
}
|
||||
|
||||
#endif
|
||||
2002
libmariadb/ob_full_link_trace.c
Normal file
2002
libmariadb/ob_full_link_trace.c
Normal file
File diff suppressed because it is too large
Load Diff
524
libmariadb/ob_object.c
Normal file
524
libmariadb/ob_object.c
Normal file
@ -0,0 +1,524 @@
|
||||
#include <ob_object.h>
|
||||
#include <stddef.h>
|
||||
#include "ob_serialize.h"
|
||||
|
||||
static int get_map(ObObjType ob_type, const ObMySQLTypeMap **map)
|
||||
{
|
||||
int ret = 0;
|
||||
if (ob_type >= ObMaxType) {
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
if (OB_SUCC(ret)) {
|
||||
*map = type_maps_ + ob_type;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int get_mysql_type(ObObjType ob_type, enum_field_types *mysql_type)
|
||||
{
|
||||
const ObMySQLTypeMap *map = NULL;
|
||||
int ret = 0;
|
||||
|
||||
if ((ret = get_map(ob_type, &map)) == 0) {
|
||||
*mysql_type = map->mysql_type;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int get_ob_type(ObObjType *ob_type, enum_field_types mysql_type)
|
||||
{
|
||||
int ret = 0;
|
||||
switch (mysql_type) {
|
||||
case MYSQL_TYPE_NULL:
|
||||
*ob_type = ObNullType;
|
||||
break;
|
||||
case MYSQL_TYPE_TINY:
|
||||
*ob_type = ObTinyIntType;
|
||||
break;
|
||||
case MYSQL_TYPE_SHORT:
|
||||
*ob_type = ObSmallIntType;
|
||||
break;
|
||||
case MYSQL_TYPE_INT24:
|
||||
*ob_type = ObMediumIntType;
|
||||
break;
|
||||
case MYSQL_TYPE_LONG:
|
||||
*ob_type = ObInt32Type;
|
||||
break;
|
||||
case MYSQL_TYPE_LONGLONG:
|
||||
*ob_type = ObIntType;
|
||||
break;
|
||||
case MYSQL_TYPE_FLOAT:
|
||||
*ob_type = ObFloatType;
|
||||
break;
|
||||
case MYSQL_TYPE_DOUBLE:
|
||||
*ob_type = ObDoubleType;
|
||||
break;
|
||||
case MYSQL_TYPE_TIMESTAMP:
|
||||
*ob_type = ObTimestampType;
|
||||
break;
|
||||
case MYSQL_TYPE_DATETIME:
|
||||
*ob_type = ObDateTimeType;
|
||||
break;
|
||||
case MYSQL_TYPE_TIME:
|
||||
*ob_type = ObTimeType;
|
||||
break;
|
||||
case MYSQL_TYPE_DATE:
|
||||
*ob_type = ObDateType;
|
||||
break;
|
||||
case MYSQL_TYPE_YEAR:
|
||||
*ob_type = ObYearType;
|
||||
break;
|
||||
case MYSQL_TYPE_VARCHAR:
|
||||
case MYSQL_TYPE_STRING:
|
||||
case MYSQL_TYPE_VAR_STRING:
|
||||
*ob_type = ObVarcharType;
|
||||
break;
|
||||
case MYSQL_TYPE_TINY_BLOB:
|
||||
*ob_type = ObTinyTextType;
|
||||
break;
|
||||
case MYSQL_TYPE_BLOB:
|
||||
*ob_type = ObTextType;
|
||||
break;
|
||||
case MYSQL_TYPE_MEDIUM_BLOB:
|
||||
*ob_type = ObMediumTextType;
|
||||
break;
|
||||
case MYSQL_TYPE_LONG_BLOB:
|
||||
*ob_type = ObLongTextType;
|
||||
break;
|
||||
case MYSQL_TYPE_OB_TIMESTAMP_WITH_TIME_ZONE:
|
||||
*ob_type = ObTimestampTZType;
|
||||
break;
|
||||
case MYSQL_TYPE_OB_TIMESTAMP_WITH_LOCAL_TIME_ZONE:
|
||||
*ob_type = ObTimestampLTZType;
|
||||
break;
|
||||
case MYSQL_TYPE_OB_TIMESTAMP_NANO:
|
||||
*ob_type = ObTimestampNanoType;
|
||||
break;
|
||||
case MYSQL_TYPE_OB_RAW:
|
||||
*ob_type = ObRawType;
|
||||
break;
|
||||
case MYSQL_TYPE_DECIMAL:
|
||||
case MYSQL_TYPE_NEWDECIMAL:
|
||||
*ob_type = ObNumberType;
|
||||
break;
|
||||
case MYSQL_TYPE_BIT:
|
||||
*ob_type = ObBitType;
|
||||
break;
|
||||
case MYSQL_TYPE_ENUM:
|
||||
*ob_type = ObEnumType;
|
||||
break;
|
||||
case MYSQL_TYPE_SET:
|
||||
*ob_type = ObSetType;
|
||||
break;
|
||||
case MYSQL_TYPE_OBJECT:
|
||||
*ob_type = ObExtendType;
|
||||
break;
|
||||
default:
|
||||
ret = 1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* obj get/set function */
|
||||
OB_INLINE int8_t get_tinyint(const ObObj *obj) { return (int8_t)(obj->v_.int64_); }
|
||||
OB_INLINE int16_t get_smallint(const ObObj *obj) { return (int16_t)(obj->v_.int64_); }
|
||||
OB_INLINE int32_t get_mediumint(const ObObj *obj) { return (int32_t)(obj->v_.int64_); }
|
||||
OB_INLINE int32_t get_int32(const ObObj *obj) { return (int32_t)(obj->v_.int64_); }
|
||||
OB_INLINE int64_t get_int(const ObObj *obj) { return (int64_t)(obj->v_.int64_); }
|
||||
|
||||
OB_INLINE uint8_t get_utinyint(const ObObj *obj) { return (uint8_t)(obj->v_.uint64_); }
|
||||
OB_INLINE uint16_t get_usmallint(const ObObj *obj) { return (uint16_t)(obj->v_.uint64_); }
|
||||
OB_INLINE uint32_t get_umediumint(const ObObj *obj) { return (uint32_t)(obj->v_.uint64_); }
|
||||
OB_INLINE uint32_t get_uint32(const ObObj *obj) { return (uint32_t)(obj->v_.uint64_); }
|
||||
OB_INLINE uint64_t get_uint64(const ObObj *obj) { return (uint64_t)(obj->v_.uint64_); }
|
||||
|
||||
OB_INLINE float get_float(const ObObj *obj) { return obj->v_.float_; }
|
||||
OB_INLINE double get_double(const ObObj *obj) { return obj->v_.double_; }
|
||||
OB_INLINE float get_ufloat(const ObObj *obj) { return obj->v_.float_; }
|
||||
OB_INLINE double get_udouble(const ObObj *obj) { return obj->v_.double_; }
|
||||
|
||||
OB_INLINE ObObjType get_type(ObObjMeta *meta) { return (ObObjType)meta->type_; }
|
||||
|
||||
OB_INLINE void set_null_meta(ObObjMeta *meta) { meta->type_ = (uint8_t)(ObNullType); meta->cs_level_ = CS_LEVEL_IGNORABLE; meta->cs_type_ = CS_TYPE_BINARY; }
|
||||
OB_INLINE void set_tinyint_meta(ObObjMeta *meta) { meta->type_ = (uint8_t)(ObTinyIntType); meta->cs_level_ = CS_LEVEL_NUMERIC;meta->cs_type_ = CS_TYPE_BINARY; }
|
||||
OB_INLINE void set_smallint_meta(ObObjMeta *meta) { meta->type_ = (uint8_t)(ObSmallIntType); meta->cs_level_ = CS_LEVEL_NUMERIC;meta->cs_type_ = CS_TYPE_BINARY; }
|
||||
OB_INLINE void set_mediumint_meta(ObObjMeta *meta) { meta->type_ = (uint8_t)(ObMediumIntType); meta->cs_level_ = CS_LEVEL_NUMERIC;meta->cs_type_ = CS_TYPE_BINARY; }
|
||||
OB_INLINE void set_int32_meta(ObObjMeta *meta) { meta->type_ = (uint8_t)(ObInt32Type); meta->cs_level_ = CS_LEVEL_NUMERIC;meta->cs_type_ = CS_TYPE_BINARY; }
|
||||
OB_INLINE void set_int_meta(ObObjMeta *meta) { meta->type_ = (uint8_t)(ObIntType); meta->cs_level_ = CS_LEVEL_NUMERIC;meta->cs_type_ = CS_TYPE_BINARY; }
|
||||
OB_INLINE void set_utinyint_meta(ObObjMeta *meta) { meta->type_ = (uint8_t)(ObUTinyIntType); meta->cs_level_ = CS_LEVEL_NUMERIC;meta->cs_type_ = CS_TYPE_BINARY; }
|
||||
OB_INLINE void set_usmallint_meta(ObObjMeta *meta) { meta->type_ = (uint8_t)(ObUSmallIntType); meta->cs_level_ = CS_LEVEL_NUMERIC;meta->cs_type_ = CS_TYPE_BINARY; }
|
||||
OB_INLINE void set_umediumint_meta(ObObjMeta *meta) { meta->type_ = (uint8_t)(ObUMediumIntType); meta->cs_level_ = CS_LEVEL_NUMERIC;meta->cs_type_ = CS_TYPE_BINARY; }
|
||||
OB_INLINE void set_uint32_meta(ObObjMeta *meta) { meta->type_ = (uint8_t)(ObUInt32Type); meta->cs_level_ = CS_LEVEL_NUMERIC;meta->cs_type_ = CS_TYPE_BINARY; }
|
||||
OB_INLINE void set_uint64_meta(ObObjMeta *meta) { meta->type_ = (uint8_t)(ObUInt64Type); meta->cs_level_ = CS_LEVEL_NUMERIC;meta->cs_type_ = CS_TYPE_BINARY; }
|
||||
OB_INLINE void set_float_meta(ObObjMeta *meta) { meta->type_ = (uint8_t)(ObFloatType); meta->cs_level_ = CS_LEVEL_NUMERIC;meta->cs_type_ = CS_TYPE_BINARY; }
|
||||
OB_INLINE void set_double_meta(ObObjMeta *meta) { meta->type_ = (uint8_t)(ObDoubleType); meta->cs_level_ = CS_LEVEL_NUMERIC;meta->cs_type_ = CS_TYPE_BINARY; }
|
||||
OB_INLINE void set_ufloat_meta(ObObjMeta *meta) { meta->type_ = (uint8_t)(ObUFloatType); meta->cs_level_ = CS_LEVEL_NUMERIC;meta->cs_type_ = CS_TYPE_BINARY; }
|
||||
OB_INLINE void set_udouble_meta(ObObjMeta *meta) { meta->type_ = (uint8_t)(ObUDoubleType); meta->cs_level_ = CS_LEVEL_NUMERIC;meta->cs_type_ = CS_TYPE_BINARY; }
|
||||
OB_INLINE void set_varchar_meta(ObObjMeta *meta) { meta->type_ = (uint8_t)(ObVarcharType); }
|
||||
|
||||
inline void set_tinyint(ObObj *obj, const int8_t value)
|
||||
{
|
||||
set_tinyint_meta(&obj->meta_);
|
||||
obj->v_.int64_ = (int64_t)(value);
|
||||
}
|
||||
|
||||
inline void set_tinyint_value(ObObj *obj, const int8_t value)
|
||||
{
|
||||
obj->v_.int64_ = (int64_t)(value);
|
||||
}
|
||||
|
||||
inline void set_smallint(ObObj *obj, const int16_t value)
|
||||
{
|
||||
set_smallint_meta(&obj->meta_);
|
||||
obj->v_.int64_ = (int64_t)(value);
|
||||
}
|
||||
|
||||
inline void set_smallint_value(ObObj *obj, const int16_t value)
|
||||
{
|
||||
obj->v_.int64_ = (int64_t)(value);
|
||||
}
|
||||
|
||||
inline void set_mediumint(ObObj *obj, const int32_t value)
|
||||
{
|
||||
set_mediumint_meta(&obj->meta_);
|
||||
obj->v_.int64_ = (int64_t)(value);
|
||||
}
|
||||
|
||||
inline void set_int32(ObObj *obj, const int32_t value)
|
||||
{
|
||||
set_int32_meta(&obj->meta_);
|
||||
obj->v_.int64_ = (int64_t)(value);
|
||||
}
|
||||
|
||||
inline void set_int32_value(ObObj *obj, const int32_t value)
|
||||
{
|
||||
// meta_.set_int32();
|
||||
obj->v_.int64_ = (int64_t)(value);
|
||||
}
|
||||
|
||||
inline void set_int(ObObj *obj, const int64_t value)
|
||||
{
|
||||
set_int_meta(&obj->meta_);
|
||||
obj->v_.int64_ = value;
|
||||
}
|
||||
|
||||
inline void set_int_value(ObObj *obj, const int64_t value)
|
||||
{
|
||||
obj->v_.int64_ = value;
|
||||
}
|
||||
|
||||
inline void set_utinyint(ObObj *obj, const uint8_t value)
|
||||
{
|
||||
set_utinyint_meta(&obj->meta_);
|
||||
obj->v_.uint64_ = (uint64_t)(value);
|
||||
}
|
||||
|
||||
inline void set_usmallint(ObObj *obj, const uint16_t value)
|
||||
{
|
||||
set_usmallint_meta(&obj->meta_);
|
||||
obj->v_.uint64_ = (uint64_t)(value);
|
||||
}
|
||||
|
||||
inline void set_umediumint(ObObj *obj, const uint32_t value)
|
||||
{
|
||||
set_umediumint_meta(&obj->meta_);
|
||||
obj->v_.uint64_ = (uint64_t)(value);
|
||||
}
|
||||
|
||||
inline void set_uint32(ObObj *obj, const uint32_t value)
|
||||
{
|
||||
set_uint32_meta(&obj->meta_);
|
||||
obj->v_.uint64_ = (uint64_t)(value);
|
||||
}
|
||||
|
||||
inline void set_uint64(ObObj *obj, const uint64_t value)
|
||||
{
|
||||
set_uint64_meta(&obj->meta_);
|
||||
obj->v_.uint64_ = value;
|
||||
}
|
||||
|
||||
inline void set_float(ObObj *obj, const float value)
|
||||
{
|
||||
set_float_meta(&obj->meta_);
|
||||
obj->v_.float_ = value;
|
||||
}
|
||||
|
||||
inline void set_float_value(ObObj *obj, const float value)
|
||||
{
|
||||
// meta_.set_float();
|
||||
obj->v_.float_ = value;
|
||||
}
|
||||
|
||||
inline void set_ufloat(ObObj *obj, const float value)
|
||||
{
|
||||
set_ufloat_meta(&obj->meta_);
|
||||
obj->v_.float_ = value;
|
||||
}
|
||||
|
||||
inline void set_double(ObObj *obj, const double value)
|
||||
{
|
||||
set_double_meta(&obj->meta_);
|
||||
obj->v_.double_ = value;
|
||||
}
|
||||
|
||||
inline void set_double_value(ObObj *obj, const double value)
|
||||
{
|
||||
obj->v_.double_ = value;
|
||||
}
|
||||
|
||||
inline void set_udouble(ObObj *obj, const double value)
|
||||
{
|
||||
set_udouble_meta(&obj->meta_);
|
||||
obj->v_.double_ = value;
|
||||
}
|
||||
|
||||
inline void set_varchar(ObObj *obj, const char *ptr, int32_t size)
|
||||
{
|
||||
set_varchar_meta(&obj->meta_);
|
||||
obj->meta_.cs_level_ = CS_LEVEL_IMPLICIT;
|
||||
obj->v_.string_ = ptr;
|
||||
obj->val_len_ = size;
|
||||
}
|
||||
/* obj get/set function */
|
||||
|
||||
// general serialization functions generator
|
||||
#define DEF_SERIALIZE_FUNCS(OBJTYPE, TYPE, VTYPE) \
|
||||
int obj_val_serialize_##OBJTYPE(const ObObj *obj, char *buf, const int64_t buf_len, int64_t *pos) \
|
||||
{ \
|
||||
int ret = OB_SUCCESS; \
|
||||
OB_UNIS_ENCODE(get_##TYPE(obj), VTYPE); \
|
||||
return ret; \
|
||||
} \
|
||||
\
|
||||
int obj_val_deserialize_##OBJTYPE(ObObj *obj, const char *buf, const int64_t data_len, int64_t *pos) \
|
||||
{ \
|
||||
int ret = OB_SUCCESS; \
|
||||
VTYPE v; \
|
||||
OB_UNIS_DECODE(v, VTYPE); \
|
||||
if (OB_SUCC(ret)) { \
|
||||
set_##TYPE(obj, v); \
|
||||
} \
|
||||
return ret; \
|
||||
} \
|
||||
\
|
||||
int64_t obj_val_get_serialize_size_##OBJTYPE(const ObObj *obj) \
|
||||
{ \
|
||||
int64_t len = 0; \
|
||||
OB_UNIS_ADD_LEN(get_##TYPE(obj), VTYPE); \
|
||||
return len; \
|
||||
}
|
||||
|
||||
// general generator for numeric types
|
||||
#define DEF_NUMERIC_FUNCS(OBJTYPE, TYPE, VTYPE, SQL_FORMAT, STR_FORMAT, HTYPE) \
|
||||
DEF_SERIALIZE_FUNCS(OBJTYPE, TYPE, VTYPE)
|
||||
|
||||
// ObTinyIntType=1, // int8, aka mysql boolean type
|
||||
DEF_NUMERIC_FUNCS(ObTinyIntType, tinyint, int8_t, "%hhd", "'%hhd'", int64_t);
|
||||
// ObSmallIntType=2, // int16
|
||||
DEF_NUMERIC_FUNCS(ObSmallIntType, smallint, int16_t, "%hd", "'%hd'", int64_t);
|
||||
// ObMediumIntType=3, // int24
|
||||
DEF_NUMERIC_FUNCS(ObMediumIntType, mediumint, int32_t, "%d", "'%d'", int64_t);
|
||||
// ObInt32Type=4, // int32
|
||||
DEF_NUMERIC_FUNCS(ObInt32Type, int32, int32_t, "%d", "'%d'", int64_t);
|
||||
// ObIntType=5, // int64, aka bigint
|
||||
DEF_NUMERIC_FUNCS(ObIntType, int, int64_t, "%ld", "'%ld'", int64_t);
|
||||
// ObUTinyIntType=6, // uint8
|
||||
DEF_NUMERIC_FUNCS(ObUTinyIntType, utinyint, uint8_t, "%hhu", "'%hhu'", uint64_t);
|
||||
// ObUSmallIntType=7, // uint16
|
||||
DEF_NUMERIC_FUNCS(ObUSmallIntType, usmallint, uint16_t, "%hu", "'%hu'", uint64_t);
|
||||
// ObUMediumIntType=8, // uint24
|
||||
DEF_NUMERIC_FUNCS(ObUMediumIntType, umediumint, uint32_t, "%u", "'%u'", uint64_t);
|
||||
// ObUInt32Type=9, // uint32
|
||||
DEF_NUMERIC_FUNCS(ObUInt32Type, uint32, uint32_t, "%u", "'%u'", uint64_t);
|
||||
// ObUInt64Type=10, // uint64
|
||||
DEF_NUMERIC_FUNCS(ObUInt64Type, uint64, uint64_t, "%lu", "'%lu'", uint64_t);
|
||||
// ObFloatType=11, // single-precision floating point
|
||||
DEF_NUMERIC_FUNCS(ObFloatType, float, float, "%2f", "'%2f'", double);
|
||||
// ObDoubleType=12, // double-precision floating point
|
||||
DEF_NUMERIC_FUNCS(ObDoubleType, double, double, "%2lf", "'%2lf'", double);
|
||||
// ObUFloatType=13, // unsigned single-precision floating point
|
||||
DEF_NUMERIC_FUNCS(ObUFloatType, ufloat, float, "%2f", "'%2f'", double);
|
||||
// ObUDoubleType=14, // unsigned double-precision floating point
|
||||
DEF_NUMERIC_FUNCS(ObUDoubleType, udouble, double, "%2lf", "'%2lf'", double);
|
||||
|
||||
// for obstring
|
||||
int obj_val_serialize_ObVarcharType(const ObObj *obj, char *buf, const int64_t buf_len, int64_t *pos)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
encode_vstr_with_len(buf, buf_len, pos, obj->v_.string_, obj->val_len_);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int obj_val_deserialize_ObVarcharType(ObObj *obj, const char *buf, const int64_t data_len, int64_t *pos)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
int64_t len = 0;
|
||||
const int64_t MINIMAL_NEEDED_SIZE = 2; //at least need two bytes
|
||||
if (OB_ISNULL(buf) || OB_UNLIKELY((data_len - *pos) < MINIMAL_NEEDED_SIZE)) {
|
||||
ret = OB_ERROR;
|
||||
} else {
|
||||
obj->v_.string_ = (char *)(decode_vstr_nocopy(buf, data_len, pos, &len));
|
||||
if (OB_ISNULL(obj->v_.string_)) {
|
||||
ret = OB_ERROR;
|
||||
} else {
|
||||
obj->val_len_ = len;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int64_t obj_val_get_serialize_size_ObVarcharType(const ObObj *obj)
|
||||
{
|
||||
return encoded_length_vstr_with_len(obj->val_len_);
|
||||
}
|
||||
|
||||
// for null type
|
||||
int obj_val_serialize_ObNullType(const ObObj *obj, char *buf, const int64_t buf_len, int64_t *pos)
|
||||
{
|
||||
int ret = OB_ERROR;
|
||||
UNUSED(obj);
|
||||
UNUSED(buf);
|
||||
UNUSED(buf_len);
|
||||
UNUSED(pos);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int obj_val_deserialize_ObNullType(ObObj *obj, const char *buf, const int64_t data_len, int64_t *pos)
|
||||
{
|
||||
int ret = OB_ERROR;
|
||||
UNUSED(obj);
|
||||
UNUSED(buf);
|
||||
UNUSED(data_len);
|
||||
UNUSED(pos);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int64_t obj_val_get_serialize_size_ObNullType(const ObObj *obj)
|
||||
{
|
||||
UNUSED(obj);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int serialize_ObObjMeta(const ObObjMeta *objmeta, char *buf, const int64_t buf_len, int64_t *pos)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
encode_uint8_t(buf, buf_len, pos, objmeta->type_);
|
||||
encode_uint8_t(buf, buf_len, pos, objmeta->cs_level_);
|
||||
encode_uint8_t(buf, buf_len, pos, objmeta->cs_type_);
|
||||
encode_int8_t(buf, buf_len, pos, objmeta->scale_);
|
||||
return ret;
|
||||
}
|
||||
int deserialize_ObObjMeta(ObObjMeta *objmeta,const char *buf, const int64_t data_len, int64_t *pos)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
decode_uint8_t(buf, data_len, pos, &objmeta->type_);
|
||||
decode_uint8_t(buf, data_len, pos, &objmeta->cs_level_);
|
||||
decode_uint8_t(buf, data_len, pos, &objmeta->cs_type_);
|
||||
decode_int8_t(buf, data_len, pos, &objmeta->scale_);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int64_t get_serialize_size_ObObjMeta(const ObObjMeta *objmeta)
|
||||
{
|
||||
int64_t len = 0;
|
||||
len += encoded_length_uint8_t(objmeta->type_);
|
||||
len += encoded_length_uint8_t(objmeta->cs_level_);
|
||||
len += encoded_length_uint8_t(objmeta->cs_type_);
|
||||
len += encoded_length_int8_t(objmeta->scale_);
|
||||
return len;
|
||||
}
|
||||
|
||||
#define DEF_FUNC_ENTRY(OBJTYPE) \
|
||||
{ \
|
||||
obj_val_serialize_##OBJTYPE, \
|
||||
obj_val_deserialize_##OBJTYPE, \
|
||||
obj_val_get_serialize_size_##OBJTYPE, \
|
||||
}
|
||||
|
||||
ObObjTypeFuncs OBJ_FUNCS[ObMaxType] =
|
||||
{
|
||||
DEF_FUNC_ENTRY(ObNullType), // 0
|
||||
DEF_FUNC_ENTRY(ObTinyIntType), // 1
|
||||
DEF_FUNC_ENTRY(ObSmallIntType), // 2
|
||||
DEF_FUNC_ENTRY(ObMediumIntType), // 3
|
||||
DEF_FUNC_ENTRY(ObInt32Type), // 4
|
||||
DEF_FUNC_ENTRY(ObIntType), // 5
|
||||
DEF_FUNC_ENTRY(ObUTinyIntType), // 6
|
||||
DEF_FUNC_ENTRY(ObUSmallIntType), // 7
|
||||
DEF_FUNC_ENTRY(ObUMediumIntType), // 8
|
||||
DEF_FUNC_ENTRY(ObUInt32Type), // 9
|
||||
DEF_FUNC_ENTRY(ObUInt64Type), // 10
|
||||
DEF_FUNC_ENTRY(ObFloatType), // 11
|
||||
DEF_FUNC_ENTRY(ObDoubleType), // 12
|
||||
DEF_FUNC_ENTRY(ObUFloatType), // 13
|
||||
DEF_FUNC_ENTRY(ObUDoubleType), // 14
|
||||
DEF_FUNC_ENTRY(ObNullType), // 15
|
||||
DEF_FUNC_ENTRY(ObNullType), // 16: unumber is the same as number
|
||||
DEF_FUNC_ENTRY(ObNullType), // 17
|
||||
DEF_FUNC_ENTRY(ObNullType), // 18
|
||||
DEF_FUNC_ENTRY(ObNullType), // 19
|
||||
DEF_FUNC_ENTRY(ObNullType), // 20
|
||||
DEF_FUNC_ENTRY(ObNullType), // 21
|
||||
DEF_FUNC_ENTRY(ObVarcharType), // 22, varchar
|
||||
DEF_FUNC_ENTRY(ObNullType), // 23, char
|
||||
DEF_FUNC_ENTRY(ObNullType), // 24, hex_string
|
||||
DEF_FUNC_ENTRY(ObNullType), // 25, ext
|
||||
DEF_FUNC_ENTRY(ObNullType), // 26, unknown
|
||||
DEF_FUNC_ENTRY(ObNullType), // 27
|
||||
DEF_FUNC_ENTRY(ObNullType), // 28
|
||||
DEF_FUNC_ENTRY(ObNullType), // 29
|
||||
DEF_FUNC_ENTRY(ObNullType), // 30
|
||||
DEF_FUNC_ENTRY(ObNullType), // 31
|
||||
DEF_FUNC_ENTRY(ObNullType), // 32
|
||||
DEF_FUNC_ENTRY(ObNullType), // 33
|
||||
DEF_FUNC_ENTRY(ObNullType), // 34
|
||||
DEF_FUNC_ENTRY(ObNullType), // 35
|
||||
DEF_FUNC_ENTRY(ObNullType), // 36, timestamp with time zone
|
||||
DEF_FUNC_ENTRY(ObNullType), // 37, timestamp with local time zone
|
||||
DEF_FUNC_ENTRY(ObNullType), // 38, timestamp (9)
|
||||
DEF_FUNC_ENTRY(ObNullType), // 39, raw
|
||||
DEF_FUNC_ENTRY(ObNullType), // 40
|
||||
DEF_FUNC_ENTRY(ObNullType), // 41
|
||||
DEF_FUNC_ENTRY(ObNullType), // 42
|
||||
DEF_FUNC_ENTRY(ObNullType), // 43, nvarchar2
|
||||
DEF_FUNC_ENTRY(ObNullType), // 44, nchar
|
||||
};
|
||||
|
||||
int serialize_ObObj(const ObObj *obj, char *buf, const int64_t buf_len, int64_t *pos)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
serialize_ObObjMeta(&obj->meta_, buf, buf_len, pos);
|
||||
if (OB_SUCC(ret)) {
|
||||
if (obj->meta_.type_ <= ObMaxType) {
|
||||
ret = OBJ_FUNCS[get_type((ObObjMeta *)&obj->meta_)].serialize(obj, buf, buf_len, pos);
|
||||
} else {
|
||||
ret = OB_ERROR;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int deserialize_ObObj(ObObj *obj, const char *buf, const int64_t data_len, int64_t *pos)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
deserialize_ObObjMeta(&obj->meta_, buf, data_len, pos);
|
||||
if (OB_SUCC(ret)) {
|
||||
if (obj->meta_.type_ <= ObMaxType) {
|
||||
ret = OBJ_FUNCS[get_type((ObObjMeta *)&obj->meta_)].deserialize(obj, buf, data_len, pos);
|
||||
} else {
|
||||
ret = OB_ERROR;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int64_t get_serialize_size_ObObj(const ObObj *obj)
|
||||
{
|
||||
int64_t len = 0;
|
||||
len += get_serialize_size_ObObjMeta(&obj->meta_);
|
||||
len += OBJ_FUNCS[get_type((ObObjMeta *)&obj->meta_)].get_serialize_size(obj);
|
||||
return len;
|
||||
}
|
||||
/* obj serialize/deserialize function */
|
||||
2512
libmariadb/ob_oracle_format_models.c
Normal file
2512
libmariadb/ob_oracle_format_models.c
Normal file
File diff suppressed because it is too large
Load Diff
702
libmariadb/ob_protocol20.c
Normal file
702
libmariadb/ob_protocol20.c
Normal file
@ -0,0 +1,702 @@
|
||||
#include "ob_protocol20.h"
|
||||
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "mysql.h"
|
||||
#include "ma_global.h"
|
||||
#include "ob_object.h"
|
||||
#include "ob_full_link_trace.h"
|
||||
#include "ob_rwlock.h"
|
||||
|
||||
#define UINT24_MAX (16777215U)
|
||||
#define EXTRA_TYPE_LENGTH 2
|
||||
#define EXTRA_LEN_LENGTH 4
|
||||
|
||||
#define OB20_SERIALIZE_FUNC_SET(id, funcname) (extra_serialize_funcs[id] = (ExtraInfoSerializeFunc)OB20_EXTRAINFO_SERIALIZE_FUNC(funcname))
|
||||
#define OB20_SERIALIZE_FUNC_INIT() \
|
||||
do \
|
||||
{ \
|
||||
/* FULL_TRACE */ \
|
||||
OB20_SERIALIZE_FUNC_SET(FULL_TRC, flt); \
|
||||
} while (0)
|
||||
|
||||
extern void *ma_multi_malloc(myf MyFlags, ...);
|
||||
|
||||
static ob_mutex_t init_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
static int init_flag = 0;
|
||||
static ExtraInfoSerializeFunc extra_serialize_funcs[OB20_SVR_END + 1];
|
||||
|
||||
// CRC table for the CRC-16. The poly is 0x8005 (x^16 + x^15 + x^2 + 1)
|
||||
uint16_t const ob_crc16_table[256] = {0x0000,
|
||||
0xC0C1,
|
||||
0xC181,
|
||||
0x0140,
|
||||
0xC301,
|
||||
0x03C0,
|
||||
0x0280,
|
||||
0xC241,
|
||||
0xC601,
|
||||
0x06C0,
|
||||
0x0780,
|
||||
0xC741,
|
||||
0x0500,
|
||||
0xC5C1,
|
||||
0xC481,
|
||||
0x0440,
|
||||
0xCC01,
|
||||
0x0CC0,
|
||||
0x0D80,
|
||||
0xCD41,
|
||||
0x0F00,
|
||||
0xCFC1,
|
||||
0xCE81,
|
||||
0x0E40,
|
||||
0x0A00,
|
||||
0xCAC1,
|
||||
0xCB81,
|
||||
0x0B40,
|
||||
0xC901,
|
||||
0x09C0,
|
||||
0x0880,
|
||||
0xC841,
|
||||
0xD801,
|
||||
0x18C0,
|
||||
0x1980,
|
||||
0xD941,
|
||||
0x1B00,
|
||||
0xDBC1,
|
||||
0xDA81,
|
||||
0x1A40,
|
||||
0x1E00,
|
||||
0xDEC1,
|
||||
0xDF81,
|
||||
0x1F40,
|
||||
0xDD01,
|
||||
0x1DC0,
|
||||
0x1C80,
|
||||
0xDC41,
|
||||
0x1400,
|
||||
0xD4C1,
|
||||
0xD581,
|
||||
0x1540,
|
||||
0xD701,
|
||||
0x17C0,
|
||||
0x1680,
|
||||
0xD641,
|
||||
0xD201,
|
||||
0x12C0,
|
||||
0x1380,
|
||||
0xD341,
|
||||
0x1100,
|
||||
0xD1C1,
|
||||
0xD081,
|
||||
0x1040,
|
||||
0xF001,
|
||||
0x30C0,
|
||||
0x3180,
|
||||
0xF141,
|
||||
0x3300,
|
||||
0xF3C1,
|
||||
0xF281,
|
||||
0x3240,
|
||||
0x3600,
|
||||
0xF6C1,
|
||||
0xF781,
|
||||
0x3740,
|
||||
0xF501,
|
||||
0x35C0,
|
||||
0x3480,
|
||||
0xF441,
|
||||
0x3C00,
|
||||
0xFCC1,
|
||||
0xFD81,
|
||||
0x3D40,
|
||||
0xFF01,
|
||||
0x3FC0,
|
||||
0x3E80,
|
||||
0xFE41,
|
||||
0xFA01,
|
||||
0x3AC0,
|
||||
0x3B80,
|
||||
0xFB41,
|
||||
0x3900,
|
||||
0xF9C1,
|
||||
0xF881,
|
||||
0x3840,
|
||||
0x2800,
|
||||
0xE8C1,
|
||||
0xE981,
|
||||
0x2940,
|
||||
0xEB01,
|
||||
0x2BC0,
|
||||
0x2A80,
|
||||
0xEA41,
|
||||
0xEE01,
|
||||
0x2EC0,
|
||||
0x2F80,
|
||||
0xEF41,
|
||||
0x2D00,
|
||||
0xEDC1,
|
||||
0xEC81,
|
||||
0x2C40,
|
||||
0xE401,
|
||||
0x24C0,
|
||||
0x2580,
|
||||
0xE541,
|
||||
0x2700,
|
||||
0xE7C1,
|
||||
0xE681,
|
||||
0x2640,
|
||||
0x2200,
|
||||
0xE2C1,
|
||||
0xE381,
|
||||
0x2340,
|
||||
0xE101,
|
||||
0x21C0,
|
||||
0x2080,
|
||||
0xE041,
|
||||
0xA001,
|
||||
0x60C0,
|
||||
0x6180,
|
||||
0xA141,
|
||||
0x6300,
|
||||
0xA3C1,
|
||||
0xA281,
|
||||
0x6240,
|
||||
0x6600,
|
||||
0xA6C1,
|
||||
0xA781,
|
||||
0x6740,
|
||||
0xA501,
|
||||
0x65C0,
|
||||
0x6480,
|
||||
0xA441,
|
||||
0x6C00,
|
||||
0xACC1,
|
||||
0xAD81,
|
||||
0x6D40,
|
||||
0xAF01,
|
||||
0x6FC0,
|
||||
0x6E80,
|
||||
0xAE41,
|
||||
0xAA01,
|
||||
0x6AC0,
|
||||
0x6B80,
|
||||
0xAB41,
|
||||
0x6900,
|
||||
0xA9C1,
|
||||
0xA881,
|
||||
0x6840,
|
||||
0x7800,
|
||||
0xB8C1,
|
||||
0xB981,
|
||||
0x7940,
|
||||
0xBB01,
|
||||
0x7BC0,
|
||||
0x7A80,
|
||||
0xBA41,
|
||||
0xBE01,
|
||||
0x7EC0,
|
||||
0x7F80,
|
||||
0xBF41,
|
||||
0x7D00,
|
||||
0xBDC1,
|
||||
0xBC81,
|
||||
0x7C40,
|
||||
0xB401,
|
||||
0x74C0,
|
||||
0x7580,
|
||||
0xB541,
|
||||
0x7700,
|
||||
0xB7C1,
|
||||
0xB681,
|
||||
0x7640,
|
||||
0x7200,
|
||||
0xB2C1,
|
||||
0xB381,
|
||||
0x7340,
|
||||
0xB101,
|
||||
0x71C0,
|
||||
0x7080,
|
||||
0xB041,
|
||||
0x5000,
|
||||
0x90C1,
|
||||
0x9181,
|
||||
0x5140,
|
||||
0x9301,
|
||||
0x53C0,
|
||||
0x5280,
|
||||
0x9241,
|
||||
0x9601,
|
||||
0x56C0,
|
||||
0x5780,
|
||||
0x9741,
|
||||
0x5500,
|
||||
0x95C1,
|
||||
0x9481,
|
||||
0x5440,
|
||||
0x9C01,
|
||||
0x5CC0,
|
||||
0x5D80,
|
||||
0x9D41,
|
||||
0x5F00,
|
||||
0x9FC1,
|
||||
0x9E81,
|
||||
0x5E40,
|
||||
0x5A00,
|
||||
0x9AC1,
|
||||
0x9B81,
|
||||
0x5B40,
|
||||
0x9901,
|
||||
0x59C0,
|
||||
0x5880,
|
||||
0x9841,
|
||||
0x8801,
|
||||
0x48C0,
|
||||
0x4980,
|
||||
0x8941,
|
||||
0x4B00,
|
||||
0x8BC1,
|
||||
0x8A81,
|
||||
0x4A40,
|
||||
0x4E00,
|
||||
0x8EC1,
|
||||
0x8F81,
|
||||
0x4F40,
|
||||
0x8D01,
|
||||
0x4DC0,
|
||||
0x4C80,
|
||||
0x8C41,
|
||||
0x4400,
|
||||
0x84C1,
|
||||
0x8581,
|
||||
0x4540,
|
||||
0x8701,
|
||||
0x47C0,
|
||||
0x4680,
|
||||
0x8641,
|
||||
0x8201,
|
||||
0x42C0,
|
||||
0x4380,
|
||||
0x8341,
|
||||
0x4100,
|
||||
0x81C1,
|
||||
0x8081,
|
||||
0x4040};
|
||||
|
||||
inline uint16_t ob_crc16_byte(uint16_t crc, const uint8_t data)
|
||||
{
|
||||
return (uint16_t)((crc >> 8) ^ ob_crc16_table[(crc ^ data) & 0xff]);
|
||||
}
|
||||
|
||||
/**
|
||||
* ob_crc16 - compute the CRC-16 for the data buffer
|
||||
* @crc: previous CRC value
|
||||
* @buffer: data pointer
|
||||
* @len: number of bytes in the buffer
|
||||
*
|
||||
* Returns the updated CRC value.
|
||||
*/
|
||||
inline uint16_t ob_crc16(uint16_t crc, uint8_t const *buffer, int64_t len)
|
||||
{
|
||||
while (len--) {
|
||||
crc = ob_crc16_byte(crc, *buffer++);
|
||||
}
|
||||
return crc;
|
||||
}
|
||||
|
||||
|
||||
int ob20_init(Ob20Protocol *ob20protocol, unsigned long conid, my_bool use_flt)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
|
||||
if (OB_ISNULL(ob20protocol)) {
|
||||
ret = OB_ERROR;
|
||||
} else {
|
||||
if (!init_flag) {
|
||||
ob_mutex_lock(&init_mutex);
|
||||
if (!init_flag) {
|
||||
OB20_SERIALIZE_FUNC_INIT(); // init extra info serialize func
|
||||
init_flag = 1;
|
||||
}
|
||||
ob_mutex_unlock(&init_mutex);
|
||||
}
|
||||
memset(ob20protocol, 0, sizeof(*(ob20protocol)));
|
||||
|
||||
ob20protocol->header.magic_num = OB20_PROTOCOL_MAGIC_NUM;
|
||||
ob20protocol->header.version = OB20_PROTOCOL_VERSION_VALUE;
|
||||
ob20protocol->header.request_id = rand() % UINT_MAX24;
|
||||
ob20protocol->extra_info_list.list = NULL;
|
||||
ob20protocol->extra_info_list.current = NULL;
|
||||
ob20protocol->header.connection_id = conid;
|
||||
ob20protocol->flt = NULL;
|
||||
if (use_flt) {
|
||||
ob20protocol->flt = malloc(sizeof(FLTInfo));
|
||||
if (OB_ISNULL(ob20protocol->flt)) {
|
||||
// malloc error
|
||||
ret = OB_ERROR;
|
||||
} else if (OB_FAIL(flt_init(ob20protocol->flt))) {
|
||||
// error
|
||||
} else {
|
||||
// printf("connect with ob20 and full link trace, connection id is %lu\n", conid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ob20_end(Ob20Protocol *ob20protocol)
|
||||
{
|
||||
if (OB_NOT_NULL(ob20protocol)) {
|
||||
clear_extra_info(ob20protocol);
|
||||
if (OB_NOT_NULL(ob20protocol->real_write_buffer)) {
|
||||
free(ob20protocol->real_write_buffer);
|
||||
ob20protocol->real_write_buffer = NULL;
|
||||
ob20protocol->real_write_buffer_length = 0;
|
||||
}
|
||||
if (OB_NOT_NULL(ob20protocol->flt)) {
|
||||
flt_end(ob20protocol->flt);
|
||||
free(ob20protocol->flt);
|
||||
ob20protocol->flt = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void clear_extra_info(Ob20Protocol *ob20protocol)
|
||||
{
|
||||
if (OB_NOT_NULL(ob20protocol)) {
|
||||
ob20protocol->extra_info_list.current = ob20protocol->extra_info_list.list;
|
||||
while (OB_NOT_NULL(ob20protocol->extra_info_list.list)) {
|
||||
ob20protocol->extra_info_list.list = ob20protocol->extra_info_list.list->next;
|
||||
list_free(ob20protocol->extra_info_list.current, 0);
|
||||
ob20protocol->extra_info_list.current = ob20protocol->extra_info_list.list;
|
||||
}
|
||||
memset(&ob20protocol->extra_info_list, 0, sizeof(ob20protocol->extra_info_list));
|
||||
}
|
||||
}
|
||||
|
||||
void update_request_id(uint32_t *request_id)
|
||||
{
|
||||
*request_id = *request_id + 1;
|
||||
if (*request_id > UINT24_MAX) {
|
||||
*request_id = 0;
|
||||
}
|
||||
}
|
||||
|
||||
uchar *fill_protocol20_header(Ob20Protocol *ob20protocol, size_t len, size_t pkt_nr, size_t complen,uchar *buffer)
|
||||
{
|
||||
size_t pos = 0;
|
||||
|
||||
// printf("write request %u\n", ob20protocol->header.request_id);
|
||||
|
||||
int3store(&buffer[NET_HEADER_SIZE], complen);
|
||||
int3store(&buffer[pos], len);
|
||||
buffer[3]=(uchar) (pkt_nr);
|
||||
pos += NET_HEADER_SIZE + COMP_HEADER_SIZE;
|
||||
|
||||
int2store(&buffer[pos], ob20protocol->header.magic_num);
|
||||
pos += 2;
|
||||
int2store(&buffer[pos], ob20protocol->header.version);
|
||||
pos += 2;
|
||||
int4store(&buffer[pos], ob20protocol->header.connection_id);
|
||||
pos += 4;
|
||||
int3store(&buffer[pos], ob20protocol->header.request_id);
|
||||
pos += 3;
|
||||
ob20protocol->header.pkt_seq = pkt_nr;
|
||||
int1store(&buffer[pos], ob20protocol->header.pkt_seq);
|
||||
pos += 1;
|
||||
int4store(&buffer[pos], ob20protocol->header.payload_len);
|
||||
pos += 4;
|
||||
int4store(&buffer[pos], ob20protocol->header.flag.flags);
|
||||
pos += 4;
|
||||
int2store(&buffer[pos], ob20protocol->header.reserved);
|
||||
pos += 2;
|
||||
ob20protocol->header.header_checksum = ob_crc16(0, (uint8_t *)buffer, pos);
|
||||
int2store(&buffer[pos], ob20protocol->header.header_checksum);
|
||||
pos += 2;
|
||||
|
||||
return buffer + pos;
|
||||
}
|
||||
|
||||
|
||||
// decode protocol20 header, pass the params pkt_len , pktnr and complen for checksum
|
||||
int decode_protocol20_header(Ob20Protocol *ob20protocol, uchar *buffer, uint32_t pkt_len, uint32_t pkt_nr, uint32_t complen)
|
||||
{
|
||||
int ret = 0;
|
||||
size_t pos = 0;
|
||||
uint16_t magic_num;
|
||||
uint16_t version;
|
||||
uint32_t connection_id;
|
||||
uint32_t request_id;
|
||||
uint8_t pkt_seq;
|
||||
uint32_t payload_len;
|
||||
Ob20ProtocolFlags flag;
|
||||
uint16_t reserved;
|
||||
uint16_t header_checksum;
|
||||
uint16_t crc16 = 0;
|
||||
char header_buffer[NET_HEADER_SIZE + COMP_HEADER_SIZE];
|
||||
|
||||
// decode
|
||||
magic_num = uint2korr(&buffer[pos]);
|
||||
pos += 2;
|
||||
version = uint2korr(&buffer[pos]);
|
||||
pos += 2;
|
||||
connection_id = uint4korr(&buffer[pos]);
|
||||
pos += 4;
|
||||
request_id = uint3korr(&buffer[pos]);
|
||||
pos += 3;
|
||||
pkt_seq = uint1korr(&buffer[pos]);
|
||||
pos += 1;
|
||||
payload_len = uint4korr(&buffer[pos]);
|
||||
pos += 4;
|
||||
flag.flags = uint4korr(&buffer[pos]);
|
||||
pos += 4;
|
||||
reserved = uint2korr(&buffer[pos]);
|
||||
pos += 2;
|
||||
header_checksum = uint2korr(&buffer[pos]);
|
||||
|
||||
// checksum
|
||||
if (0 != header_checksum) {
|
||||
int3store(header_buffer, pkt_len);
|
||||
header_buffer[3] = pkt_nr;
|
||||
int3store(&header_buffer[NET_HEADER_SIZE], complen);
|
||||
crc16 = ob_crc16(crc16, (uint8_t *)header_buffer, NET_HEADER_SIZE + COMP_HEADER_SIZE);
|
||||
crc16 = ob_crc16(crc16, (uint8_t *)buffer, pos);
|
||||
} else {
|
||||
crc16 = 0;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_OB20
|
||||
printf("////////////////begin ob20 pkt [%u]//////////////////////////\n", pkt_nr);
|
||||
printf("mysql pkt_len is %u\n", pkt_len);
|
||||
printf("mysql pkt_nr is %u\n", pkt_nr);
|
||||
printf("complen is %u\n", complen);
|
||||
printf("magic_num is %u\n", magic_num);
|
||||
printf("version is %u\n", version);
|
||||
printf("connection_id is %u\n", connection_id);
|
||||
printf("request_id is %u\n", request_id);
|
||||
printf("ob20 pkt_seq is %u\n", pkt_seq);
|
||||
printf("ob20 payload_len is %u\n", payload_len);
|
||||
printf("flag is %u\n", flag.flags);
|
||||
printf("header checksum is %u\n", header_checksum);
|
||||
printf("////////////////end ob20 pkt [%u]//////////////////////////\n", pkt_nr);
|
||||
#endif
|
||||
|
||||
if (crc16 != header_checksum) {
|
||||
ret = 1; // error
|
||||
} else if (magic_num != ob20protocol->header.magic_num) {
|
||||
ret = 1; // error
|
||||
} else if (version != ob20protocol->header.version) {
|
||||
ret = 1; // error
|
||||
} else if (connection_id != ob20protocol->header.connection_id) {
|
||||
ret = 1; // error
|
||||
} else if (request_id != ob20protocol->header.request_id) {
|
||||
ret = 1; // error
|
||||
} else {
|
||||
//check request id and pkt_seq
|
||||
if (pkt_seq != ob20protocol->header.pkt_seq + 1) {
|
||||
// printf("pkt_seq check error, local is %u, header is %u\n", ob20protocol->header.pkt_seq, pkt_seq);
|
||||
ret = 1; // error
|
||||
} else {
|
||||
ob20protocol->header.flag = flag;
|
||||
ob20protocol->header.payload_len = payload_len;
|
||||
ob20protocol->header.pkt_seq = pkt_seq;
|
||||
ob20protocol->header.reserved = reserved;
|
||||
ob20protocol->header.header_checksum = header_checksum;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int extrainfo_serialize_flt(char *buf, const int64_t len, int64_t *ppos, void *data)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
int64_t pos = *ppos;
|
||||
FLTValueData *flt_data = (FLTValueData *)data;
|
||||
// data是flt_build_request中生成,函数中需要保证生成string类型
|
||||
int64_t v_len = flt_data->length;
|
||||
|
||||
if (OB_ISNULL(buf)) {
|
||||
ret = OB_ERROR;
|
||||
} else if (len < pos + EXTRA_TYPE_LENGTH + EXTRA_LEN_LENGTH + v_len) {
|
||||
ret = OB_ERROR;
|
||||
} else {
|
||||
int2store(buf + pos, FULL_TRC);
|
||||
pos += 2;
|
||||
int4store(buf + pos, v_len);
|
||||
pos += 4;
|
||||
|
||||
memcpy(buf + pos, flt_data->value_data_, v_len);
|
||||
pos += v_len;
|
||||
|
||||
*ppos = pos;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int extrainfo_deserialize_flt(const char *buf, const int64_t len, int64_t *ppos, void *data, const int64_t v_len)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
int64_t pos = *ppos;
|
||||
Ob20Protocol *ob20protocol = (Ob20Protocol *)data;
|
||||
UNUSED(ob20protocol);
|
||||
UNUSED(v_len);
|
||||
while (OB_SUCC(ret) && pos < len) {
|
||||
int32_t tmp_v_len = 0;
|
||||
int64_t tmp_v_pos = 0;
|
||||
int16_t type = FLT_EXTRA_INFO_ID_END;
|
||||
void *flt_info = NULL;
|
||||
|
||||
if (OB_FAIL(flt_resolve_type_and_len(buf, len, &pos, &type, &tmp_v_len))) {
|
||||
ret = OB_ERROR;
|
||||
} else {
|
||||
my_bool know_flt_info = TRUE;
|
||||
|
||||
if (FLT_CONTROL_INFO == type) {
|
||||
flt_info = &ob20protocol->flt->control_info_;
|
||||
} else if (FLT_APP_INFO == type) {
|
||||
flt_info = &ob20protocol->flt->app_info_;
|
||||
} else if (FLT_QUERY_INFO == type) {
|
||||
flt_info = &ob20protocol->flt->query_info_;
|
||||
} else if (FLT_SPAN_INFO == type) {
|
||||
flt_info = &ob20protocol->flt->control_info_;
|
||||
} else {
|
||||
know_flt_info = FALSE;
|
||||
}
|
||||
if (TRUE == know_flt_info) {
|
||||
if (OB_ISNULL(flt_info)) {
|
||||
ret = OB_ERROR;
|
||||
} else {
|
||||
((FLTInfoBase *)flt_info)->type_ = (FullLinkTraceExtraInfoType)type;
|
||||
if (OB_FAIL(flt_deserialize_extra_info(buf + pos, tmp_v_len, &tmp_v_pos, (FullLinkTraceExtraInfoType)type, flt_info))) {
|
||||
ret = OB_ERROR;
|
||||
} else {
|
||||
pos += tmp_v_len;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 对于不识别的key,需要跳过
|
||||
pos += tmp_v_len;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (OB_SUCC(ret)) {
|
||||
*ppos = pos; // 最后设置好pos
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int64_t extrainfo_get_serialize_size_flt(void *data)
|
||||
{
|
||||
int64_t ret = 0;
|
||||
FLTValueData *flt_data = (FLTValueData *)data;
|
||||
if (OB_NOT_NULL(flt_data)) {
|
||||
ret = EXTRA_TYPE_LENGTH + EXTRA_LEN_LENGTH + flt_data->length;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
uchar *fill_protocol20_extra_info(Ob20Protocol *ob20protocol, uchar *buffer, size_t buffer_len)
|
||||
{
|
||||
char *packet = (char *)buffer;
|
||||
int64_t pos = 0;
|
||||
int ret = OB_SUCCESS;
|
||||
|
||||
if (OB_ISNULL(ob20protocol) || OB_ISNULL(ob20protocol->extra_info_list.list)) {
|
||||
// do nothing
|
||||
} else {
|
||||
Ob20ProtocolExtraInfo *extra_info_item;
|
||||
|
||||
ob20protocol->extra_info_list.current = ob20protocol->extra_info_list.list;
|
||||
|
||||
while (NULL != ob20protocol->extra_info_list.current) {
|
||||
extra_info_item = ob20protocol->extra_info_list.current->data;
|
||||
if (OB_ISNULL(extra_serialize_funcs[extra_info_item->key].serialize_func)) {
|
||||
// 函数指针没有设置, do nothing, 跳到下一个key
|
||||
} if (OB_FAIL(extra_serialize_funcs[extra_info_item->key].serialize_func(packet + pos, buffer_len, &pos, extra_info_item->value))) {
|
||||
return buffer;
|
||||
}
|
||||
ob20protocol->extra_info_list.current = ob20protocol->extra_info_list.current->next;
|
||||
}
|
||||
}
|
||||
|
||||
return (uchar *)(packet + pos);
|
||||
}
|
||||
|
||||
size_t get_protocol20_extra_info_length(Ob20Protocol *ob20protocol)
|
||||
{
|
||||
size_t ret = 0;
|
||||
size_t item_size;
|
||||
Ob20ProtocolExtraInfo *extra_info_item;
|
||||
ob20protocol->extra_info_list.current = ob20protocol->extra_info_list.list;
|
||||
|
||||
while(NULL != ob20protocol->extra_info_list.current) {
|
||||
extra_info_item = (Ob20ProtocolExtraInfo *)ob20protocol->extra_info_list.current->data;
|
||||
if (OB_ISNULL(extra_serialize_funcs[extra_info_item->key].get_serialize_size_func)) {
|
||||
item_size = 0;
|
||||
} else {
|
||||
item_size = extra_serialize_funcs[extra_info_item->key].get_serialize_size_func(extra_info_item->value);
|
||||
}
|
||||
|
||||
ob20protocol->extra_info_list.current = ob20protocol->extra_info_list.current->next;
|
||||
ret += item_size;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int decode_protocol20_extra_info(Ob20Protocol *ob20protocol, uchar *buffer)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
int64_t extra_info_len = 0;
|
||||
int64_t pos = 0, check_pos;
|
||||
ExtraInfoKeyType key_type;
|
||||
const char *row = (char *)buffer;
|
||||
size_t value_len;
|
||||
|
||||
extra_info_len = uint4korr(row);
|
||||
row += 4;
|
||||
|
||||
while (OB_SUCC(ret) && pos < extra_info_len) {
|
||||
// key is 2 bytes
|
||||
key_type = uint2korr(row + pos);
|
||||
pos += 2;
|
||||
value_len = uint4korr(row + pos);
|
||||
pos += 4;
|
||||
|
||||
check_pos = pos;
|
||||
if (OB_ISNULL(extra_serialize_funcs[key_type].deserialize_func)) {
|
||||
// 如果函数指针没有设置,直接跳过value不解析
|
||||
pos += value_len;
|
||||
} else if (OB_FAIL(extra_serialize_funcs[key_type].deserialize_func(row, extra_info_len, &pos, ob20protocol, sizeof(*ob20protocol)))) {
|
||||
// error
|
||||
} else if (pos != check_pos + (int64_t)value_len) {
|
||||
// error
|
||||
ret = OB_ERROR;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ob20_set_extra_info(MYSQL *mysql, ExtraInfoKeyType key, void *value)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
Ob20Protocol *ob20protocol = mysql->net.ob20protocol;
|
||||
LIST *extra_info_list_item = NULL;
|
||||
Ob20ProtocolExtraInfo *extra_info_item = NULL;
|
||||
|
||||
if (!(extra_info_list_item = ma_multi_malloc(0,
|
||||
&extra_info_list_item, sizeof(LIST),
|
||||
&extra_info_item, sizeof(Ob20ProtocolExtraInfo),
|
||||
NULL))) {
|
||||
ret = OB_ERROR;
|
||||
} else {
|
||||
extra_info_item->key = key;
|
||||
extra_info_item->value = value;
|
||||
extra_info_list_item->data = extra_info_item;
|
||||
ob20protocol->extra_info_list.list = list_add(ob20protocol->extra_info_list.list, extra_info_list_item);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
189
libmariadb/ob_rwlock.c
Normal file
189
libmariadb/ob_rwlock.c
Normal file
@ -0,0 +1,189 @@
|
||||
/************************************************************************
|
||||
Copyright (c) 2021 OceanBase.
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
MA 02111-1301, USA
|
||||
|
||||
Part of this code includes code from PHP's mysqlnd extension
|
||||
(written by Andrey Hristov, Georg Richter and Ulf Wendel), freely
|
||||
available from http://www.php.net/software
|
||||
|
||||
*************************************************************************/
|
||||
|
||||
#include "ob_rwlock.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
int ob_mutex_init(ob_mutex_t *ob_mutex, const ob_mutexattr_t *attr)
|
||||
{
|
||||
InitializeCriticalSection(ob_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ob_mutex_lock(ob_mutex_t *ob_mutex)
|
||||
{
|
||||
EnterCriticalSection(ob_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ob_mutex_trylock(ob_mutex_t *ob_mutex)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (!TryEnterCriticalSection(ob_mutex)) {
|
||||
ret = EBUSY;
|
||||
} else if (ob_mutex->RecursionCount > 1) {
|
||||
LeaveCriticalSection(ob_mutex);
|
||||
ret = EBUSY;
|
||||
} else {
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ob_mutex_unlock(ob_mutex_t *ob_mutex)
|
||||
{
|
||||
LeaveCriticalSection(ob_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ob_mutex_destroy(ob_mutex_t *ob_mutex)
|
||||
{
|
||||
DeleteCriticalSection(ob_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ob_rw_init(ob_rw_lock_t *ob_rwp)
|
||||
{
|
||||
InitializeSRWLock(&ob_rwp->ob_srwlock);
|
||||
ob_rwp->is_exclusive = FALSE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ob_rw_destroy(ob_rw_lock_t *ob_rwp)
|
||||
{
|
||||
// do nothing
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ob_rw_rdlock(ob_rw_lock_t *ob_rwp)
|
||||
{
|
||||
AcquireSRWLockShared(&ob_rwp->ob_srwlock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ob_rw_tryrdlock(ob_rw_lock_t *ob_rwp)
|
||||
{
|
||||
int ret = 0;
|
||||
if (!TryAcquireSRWLockShared(&ob_rwp->ob_srwlock)) {
|
||||
ret = EBUSY;
|
||||
} else {
|
||||
ret = 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ob_rw_wrlock(ob_rw_lock_t *ob_rwp)
|
||||
{
|
||||
AcquireSRWLockExclusive(&ob_rwp->ob_srwlock);
|
||||
ob_rwp->is_exclusive= TRUE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ob_rw_trywrlock(ob_rw_lock_t *ob_rwp)
|
||||
{
|
||||
int ret = 0;;
|
||||
if (!TryAcquireSRWLockExclusive(&ob_rwp->ob_srwlock)) {
|
||||
ret = EBUSY;
|
||||
} else {
|
||||
ob_rwp->is_exclusive= TRUE;
|
||||
ret = 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ob_rw_unlock(ob_rw_lock_t *ob_rwp)
|
||||
{
|
||||
if (ob_rwp->is_exclusive) {
|
||||
ob_rwp->is_exclusive= FALSE;
|
||||
ReleaseSRWLockExclusive(&ob_rwp->ob_srwlock);
|
||||
} else {
|
||||
ReleaseSRWLockShared(&ob_rwp->ob_srwlock);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
|
||||
int ob_mutex_init(ob_mutex_t *ob_mutex, const ob_mutexattr_t *attr)
|
||||
{
|
||||
return pthread_mutex_init(ob_mutex, (pthread_mutexattr_t *)attr);
|
||||
}
|
||||
|
||||
int ob_mutex_lock(ob_mutex_t *ob_mutex)
|
||||
{
|
||||
return pthread_mutex_lock(ob_mutex);
|
||||
}
|
||||
|
||||
int ob_mutex_trylock(ob_mutex_t *ob_mutex)
|
||||
{
|
||||
return pthread_mutex_trylock(ob_mutex);
|
||||
}
|
||||
|
||||
int ob_mutex_unlock(ob_mutex_t *ob_mutex)
|
||||
{
|
||||
return pthread_mutex_unlock(ob_mutex);
|
||||
}
|
||||
|
||||
int ob_mutex_destroy(ob_mutex_t *ob_mutex)
|
||||
{
|
||||
return pthread_mutex_destroy(ob_mutex);
|
||||
}
|
||||
|
||||
int ob_rw_init(ob_rw_lock_t *ob_rwp)
|
||||
{
|
||||
return pthread_rwlock_init(ob_rwp, NULL);
|
||||
}
|
||||
|
||||
int ob_rw_destroy(ob_rw_lock_t *ob_rwp)
|
||||
{
|
||||
return pthread_rwlock_destroy(ob_rwp);
|
||||
}
|
||||
|
||||
int ob_rw_rdlock(ob_rw_lock_t *ob_rwp)
|
||||
{
|
||||
return pthread_rwlock_rdlock(ob_rwp);
|
||||
}
|
||||
|
||||
int ob_rw_tryrdlock(ob_rw_lock_t *ob_rwp)
|
||||
{
|
||||
return pthread_rwlock_tryrdlock(ob_rwp);
|
||||
}
|
||||
|
||||
int ob_rw_wrlock(ob_rw_lock_t *ob_rwp)
|
||||
{
|
||||
return pthread_rwlock_wrlock(ob_rwp);
|
||||
}
|
||||
|
||||
int ob_rw_trywrlock(ob_rw_lock_t *ob_rwp)
|
||||
{
|
||||
return pthread_rwlock_trywrlock(ob_rwp);
|
||||
}
|
||||
|
||||
int ob_rw_unlock(ob_rw_lock_t *ob_rwp)
|
||||
{
|
||||
return pthread_rwlock_unlock(ob_rwp);
|
||||
}
|
||||
#endif
|
||||
|
||||
510
libmariadb/ob_serialize.c
Normal file
510
libmariadb/ob_serialize.c
Normal file
@ -0,0 +1,510 @@
|
||||
#include "ob_serialize.h"
|
||||
|
||||
inline int64_t encoded_length_vi64(int64_t val)
|
||||
{
|
||||
uint64_t __v = (uint64_t)(val);
|
||||
int64_t need_bytes = 0;
|
||||
if (__v <= OB_MAX_V1B) {
|
||||
need_bytes = 1;
|
||||
} else if (__v <= OB_MAX_V2B) {
|
||||
need_bytes = 2;
|
||||
} else if (__v <= OB_MAX_V3B) {
|
||||
need_bytes = 3;
|
||||
} else if (__v <= OB_MAX_V4B) {
|
||||
need_bytes = 4;
|
||||
} else if (__v <= OB_MAX_V5B) {
|
||||
need_bytes = 5;
|
||||
} else if (__v <= OB_MAX_V6B) {
|
||||
need_bytes = 6;
|
||||
} else if (__v <= OB_MAX_V7B) {
|
||||
need_bytes = 7;
|
||||
} else if (__v <= OB_MAX_V8B) {
|
||||
need_bytes = 8;
|
||||
} else if (__v <= OB_MAX_V9B) {
|
||||
need_bytes = 9;
|
||||
} else {
|
||||
need_bytes = 10;
|
||||
}
|
||||
return need_bytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Encode a integer (up to 64bit) in variable length encoding
|
||||
*
|
||||
* @param buf pointer to the destination buffer
|
||||
* @param end the end pointer to the destination buffer
|
||||
* @param val value to encode
|
||||
*
|
||||
* @return true - success, false - failed
|
||||
*/
|
||||
inline int encode_vi64(char *buf, const int64_t buf_len, int64_t *ppos, int64_t val)
|
||||
{
|
||||
int64_t pos = *ppos;
|
||||
uint64_t __v = (uint64_t)(val);
|
||||
int ret = ((NULL != buf) &&
|
||||
((buf_len - pos) >= encoded_length_vi64(__v))) ? OB_SUCCESS : OB_SIZE_OVERFLOW;
|
||||
if (OB_SUCC(ret)) {
|
||||
while (__v > OB_MAX_V1B) {
|
||||
*(buf + pos++) = (int8_t)((__v) | 0x80);
|
||||
__v >>= 7;
|
||||
}
|
||||
if (__v <= OB_MAX_V1B) {
|
||||
*(buf + pos++) = (int8_t)((__v) & 0x7f);
|
||||
}
|
||||
*ppos = pos;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline int decode_vi64(const char *buf, const int64_t data_len, int64_t *ppos, int64_t *val)
|
||||
{
|
||||
uint64_t __v = 0;
|
||||
uint32_t shift = 0;
|
||||
int64_t pos = *ppos;
|
||||
int64_t tmp_pos = pos;
|
||||
int ret = OB_SUCCESS;
|
||||
while (OB_SUCC(ret) && ((*(buf + tmp_pos)) & 0x80)) {
|
||||
if (data_len - tmp_pos < 1) {
|
||||
ret = OB_DESERIALIZE_ERROR;
|
||||
break;
|
||||
}
|
||||
__v |= ((uint64_t)(*(buf + tmp_pos++)) & 0x7f) << shift;
|
||||
shift += 7;
|
||||
}
|
||||
if (OB_SUCC(ret)) {
|
||||
if (data_len - tmp_pos < 1) {
|
||||
ret = OB_DESERIALIZE_ERROR;
|
||||
} else {
|
||||
__v |= (((uint64_t)(*(buf + tmp_pos++)) & 0x7f) << shift);
|
||||
*val = (int64_t)(__v);
|
||||
pos = tmp_pos;
|
||||
}
|
||||
*ppos = pos;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline int64_t encoded_length_vi32(int32_t val)
|
||||
{
|
||||
uint32_t __v = (uint64_t)(val);
|
||||
int64_t need_bytes = 0;
|
||||
if (__v <= OB_MAX_V1B) {
|
||||
need_bytes = 1;
|
||||
} else if (__v <= OB_MAX_V2B) {
|
||||
need_bytes = 2;
|
||||
} else if (__v <= OB_MAX_V3B) {
|
||||
need_bytes = 3;
|
||||
} else if (__v <= OB_MAX_V4B) {
|
||||
need_bytes = 4;
|
||||
} else {
|
||||
need_bytes = 5;
|
||||
}
|
||||
return need_bytes;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Encode a integer (up to 32bit) in variable length encoding
|
||||
*
|
||||
* @param buf pointer to the destination buffer
|
||||
* @param end the end pointer to the destination buffer
|
||||
* @param val value to encode
|
||||
*
|
||||
* @return true - success, false - failed
|
||||
*/
|
||||
|
||||
inline int encode_vi32(char *buf, const int64_t buf_len, int64_t *ppos, int32_t val)
|
||||
{
|
||||
int64_t pos = *ppos;
|
||||
uint32_t __v = (uint32_t)(val);
|
||||
int ret = ((NULL != buf) &&
|
||||
((buf_len - pos) >= encoded_length_vi32(val))) ? OB_SUCCESS : OB_SIZE_OVERFLOW;
|
||||
if (OB_SUCC(ret)) {
|
||||
while (__v > OB_MAX_V1B) {
|
||||
*(buf + pos++) = (int8_t)((__v) | 0x80);
|
||||
__v >>= 7;
|
||||
}
|
||||
if (__v <= OB_MAX_V1B) {
|
||||
*(buf + pos++) = (int8_t)((__v) & 0x7f);
|
||||
}
|
||||
*ppos = pos;
|
||||
}
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
inline int decode_vi32(const char *buf, const int64_t data_len, int64_t *ppos, int32_t *val)
|
||||
{
|
||||
uint32_t __v = 0;
|
||||
uint32_t shift = 0;
|
||||
int ret = OB_SUCCESS;
|
||||
int64_t pos = *ppos;
|
||||
int64_t tmp_pos = pos;
|
||||
while (OB_SUCC(ret) && ((*(buf + tmp_pos)) & 0x80)) {
|
||||
if (data_len - tmp_pos < 1) {
|
||||
ret = OB_DESERIALIZE_ERROR;
|
||||
break;
|
||||
}
|
||||
__v |= ((uint32_t)(*(buf + tmp_pos++)) & 0x7f) << shift;
|
||||
shift += 7;
|
||||
}
|
||||
if (OB_SUCC(ret)) {
|
||||
if (data_len - tmp_pos < 1) {
|
||||
ret = OB_DESERIALIZE_ERROR;
|
||||
} else {
|
||||
__v |= ((uint32_t)(*(buf + tmp_pos++)) & 0x7f) << shift;
|
||||
*val = (int32_t)(__v);
|
||||
pos = tmp_pos;
|
||||
}
|
||||
*ppos = pos;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline int64_t encoded_length_i8(int8_t val)
|
||||
{
|
||||
return (int64_t)(sizeof(val));
|
||||
}
|
||||
|
||||
inline int encode_i8(char *buf, const int64_t buf_len, int64_t *ppos, int8_t val)
|
||||
{
|
||||
int64_t pos = *ppos;
|
||||
int ret = ((NULL != buf) &&
|
||||
((buf_len - pos) >= (int64_t)(sizeof(val)))) ? OB_SUCCESS : OB_SIZE_OVERFLOW;
|
||||
if (OB_SUCC(ret)) {
|
||||
*(buf + pos++) = val;
|
||||
*ppos = pos;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline int decode_i8(const char *buf, const int64_t data_len, int64_t *ppos, int8_t *val)
|
||||
{
|
||||
int pos = *ppos;
|
||||
int ret = (NULL != buf && data_len - pos >= 1) ? OB_SUCCESS : OB_DESERIALIZE_ERROR;
|
||||
if (OB_SUCC(ret)) {
|
||||
*val = *(buf + pos++);
|
||||
*ppos = pos;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline int encode_i64(char *buf, const int64_t buf_len, int64_t *ppos, int64_t val)
|
||||
{
|
||||
int pos = *ppos;
|
||||
int ret = ((NULL != buf) &&
|
||||
((buf_len - pos) >= (int64_t)(sizeof(val)))) ? OB_SUCCESS : OB_ERROR;
|
||||
if (OB_SUCC(ret)) {
|
||||
*(buf + pos++) = (char)(((val) >> 56) & 0xff);
|
||||
*(buf + pos++) = (char)(((val) >> 48) & 0xff);
|
||||
*(buf + pos++) = (char)(((val) >> 40) & 0xff);
|
||||
*(buf + pos++) = (char)(((val) >> 32) & 0xff);
|
||||
*(buf + pos++) = (char)(((val) >> 24) & 0xff);
|
||||
*(buf + pos++) = (char)(((val) >> 16) & 0xff);
|
||||
*(buf + pos++) = (char)(((val) >> 8) & 0xff);
|
||||
*(buf + pos++) = (char)((val) & 0xff);
|
||||
|
||||
*ppos = pos;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline int decode_i64(const char *buf, const int64_t data_len, int64_t *ppos, int64_t *val)
|
||||
{
|
||||
int pos = *ppos;
|
||||
int ret = (NULL != buf && data_len - pos >= 8) ? OB_SUCCESS : OB_ERROR;
|
||||
if (OB_SUCC(ret)) {
|
||||
*val = (((int64_t)((*(buf + pos++))) & 0xff)) << 56;
|
||||
*val |= (((int64_t)((*(buf + pos++))) & 0xff)) << 48;
|
||||
*val |= (((int64_t)((*(buf + pos++))) & 0xff)) << 40;
|
||||
*val |= (((int64_t)((*(buf + pos++))) & 0xff)) << 32;
|
||||
*val |= (((int64_t)((*(buf + pos++))) & 0xff)) << 24;
|
||||
*val |= (((int64_t)((*(buf + pos++))) & 0xff)) << 16;
|
||||
*val |= (((int64_t)((*(buf + pos++))) & 0xff)) << 8;
|
||||
*val |= (((int64_t)((*(buf + pos++))) & 0xff));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline int encode_int64_t(char *buf, const int64_t buf_len, int64_t *pos, int64_t val)
|
||||
{
|
||||
return encode_vi64(buf, buf_len, pos, val);
|
||||
}
|
||||
inline int encode_uint64_t(char *buf, const int64_t buf_len, int64_t *pos, uint64_t val)
|
||||
{
|
||||
return encode_vi64(buf, buf_len, pos, (int64_t)(val));
|
||||
}
|
||||
inline int encode_int32_t(char *buf, const int64_t buf_len, int64_t *pos, int32_t val)
|
||||
{
|
||||
return encode_vi32(buf, buf_len, pos, val);
|
||||
}
|
||||
inline int encode_uint32_t(char *buf, const int64_t buf_len, int64_t *pos, uint32_t val)
|
||||
{
|
||||
return encode_vi32(buf, buf_len, pos, (int32_t)(val));
|
||||
}
|
||||
inline int encode_int16_t(char *buf, const int64_t buf_len, int64_t *pos, int16_t val)
|
||||
{
|
||||
return encode_vi32(buf, buf_len, pos, (int32_t)(val));
|
||||
}
|
||||
inline int encode_uint16_t(char *buf, const int64_t buf_len, int64_t *pos, uint16_t val)
|
||||
{
|
||||
return encode_vi32(buf, buf_len, pos, (int32_t)(val));
|
||||
}
|
||||
inline int encode_int8_t(char *buf, const int64_t buf_len, int64_t *pos, int8_t val)
|
||||
{
|
||||
return encode_i8(buf, buf_len, pos, val);
|
||||
}
|
||||
inline int encode_uint8_t(char *buf, const int64_t buf_len, int64_t *pos, uint8_t val)
|
||||
{
|
||||
return encode_i8(buf, buf_len, pos, (int8_t)(val));
|
||||
}
|
||||
|
||||
|
||||
inline int decode_int8_t(const char *buf, const int64_t data_len, int64_t *pos, int8_t *val)
|
||||
{
|
||||
*val = 0;
|
||||
return decode_i8(buf, data_len, pos, val);
|
||||
}
|
||||
inline int decode_uint8_t(const char *buf, const int64_t data_len, int64_t *pos, uint8_t *val)
|
||||
{
|
||||
*val = 0;
|
||||
return decode_i8(buf, data_len, pos, (int8_t*)val);
|
||||
}
|
||||
inline int decode_int16_t(const char *buf, const int64_t data_len, int64_t *pos, int16_t *val)
|
||||
{
|
||||
int32_t v = 0;
|
||||
int ret = decode_vi32(buf, data_len, pos, &v);
|
||||
*val = (int16_t)(v);
|
||||
return ret;
|
||||
}
|
||||
inline int decode_uint16_t(const char *buf, const int64_t data_len, int64_t *pos, uint16_t *val)
|
||||
{
|
||||
int32_t v = 0;
|
||||
int ret = decode_vi32(buf, data_len, pos, &v);
|
||||
*val = (uint16_t)(v);
|
||||
return ret;
|
||||
}
|
||||
inline int decode_int32_t(const char *buf, const int64_t data_len, int64_t *pos, int32_t *val)
|
||||
{
|
||||
*val = 0;
|
||||
return decode_vi32(buf, data_len, pos, val);
|
||||
}
|
||||
inline int decode_uint32_t(const char *buf, const int64_t data_len, int64_t *pos, uint32_t *val)
|
||||
{
|
||||
*val = 0;
|
||||
return decode_vi32(buf, data_len, pos, (int32_t *)val);
|
||||
}
|
||||
inline int decode_int64_t(const char *buf, const int64_t data_len, int64_t *pos, int64_t *val)
|
||||
{
|
||||
*val = 0;
|
||||
return decode_vi64(buf, data_len, pos, val);
|
||||
}
|
||||
inline int decode_uint64_t(const char *buf, const int64_t data_len, int64_t *pos, uint64_t *val)
|
||||
{
|
||||
*val = 0;
|
||||
return decode_vi64(buf, data_len, pos, (int64_t *)val);
|
||||
}
|
||||
|
||||
inline int64_t encoded_length_int64_t(int64_t val)
|
||||
{
|
||||
return encoded_length_vi64(val);
|
||||
}
|
||||
inline int64_t encoded_length_uint64_t(uint64_t val)
|
||||
{
|
||||
return encoded_length_vi64((int64_t)val);
|
||||
}
|
||||
inline int64_t encoded_length_int32_t(int32_t val)
|
||||
{
|
||||
return encoded_length_vi32(val);
|
||||
}
|
||||
inline int64_t encoded_length_uint32_t(uint32_t val)
|
||||
{
|
||||
return encoded_length_vi32((int32_t)val);
|
||||
}
|
||||
inline int64_t encoded_length_int16_t(int16_t val)
|
||||
{
|
||||
return encoded_length_vi32(val);
|
||||
}
|
||||
inline int64_t encoded_length_uint16_t(uint16_t val)
|
||||
{
|
||||
return encoded_length_vi32((int32_t)val);
|
||||
}
|
||||
inline int64_t encoded_length_int8_t(int8_t unused)
|
||||
{
|
||||
UNUSED(unused);
|
||||
return 1;
|
||||
}
|
||||
inline int64_t encoded_length_uint8_t(uint8_t unused)
|
||||
{
|
||||
UNUSED(unused);
|
||||
return 1;
|
||||
}
|
||||
|
||||
inline int64_t encoded_length_float(float val)
|
||||
{
|
||||
int32_t tmp = 0;
|
||||
memcpy(&tmp, &val, sizeof(tmp));
|
||||
return encoded_length_vi32(tmp);
|
||||
}
|
||||
|
||||
inline int encode_float(char *buf, const int64_t buf_len, int64_t *pos, float val)
|
||||
{
|
||||
int32_t tmp = 0;
|
||||
memcpy(&tmp, &val, sizeof(tmp));
|
||||
return encode_vi32(buf, buf_len, pos, tmp);
|
||||
}
|
||||
|
||||
inline int decode_float(const char *buf, const int64_t data_len, int64_t *pos, float *val)
|
||||
{
|
||||
int32_t tmp = 0;
|
||||
int ret = OB_SUCCESS;
|
||||
if ((ret = decode_vi32(buf, data_len, pos, &tmp)) == 0) {
|
||||
memcpy(val, &tmp, sizeof(*val));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline int64_t encoded_length_double(double val)
|
||||
{
|
||||
int64_t tmp = 0;
|
||||
memcpy(&tmp, &val, sizeof(tmp));
|
||||
return encoded_length_vi64(tmp);
|
||||
}
|
||||
|
||||
inline int encode_double(char *buf, const int64_t buf_len, int64_t *pos, double val)
|
||||
{
|
||||
int64_t tmp = 0;
|
||||
memcpy(&tmp, &val, sizeof(tmp));
|
||||
return encode_vi64(buf, buf_len, pos, tmp);
|
||||
}
|
||||
|
||||
inline int decode_double(const char *buf, const int64_t data_len, int64_t *pos, double *val)
|
||||
{
|
||||
int64_t tmp = 0;
|
||||
int ret = OB_SUCCESS;
|
||||
if ((ret = decode_vi64(buf, data_len, pos, &tmp)) == 0) {
|
||||
memcpy(val, &tmp, sizeof(*val));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Computes the encoded length of vstr(int64,data,null)
|
||||
*
|
||||
* @param len string length
|
||||
*
|
||||
* @return the encoded length of str
|
||||
*/
|
||||
inline int64_t encoded_length_vstr_with_len(int64_t len)
|
||||
{
|
||||
return encoded_length_vi64(len) + len + 1;
|
||||
}
|
||||
|
||||
inline int64_t encoded_length_vstr(const char *str)
|
||||
{
|
||||
return encoded_length_vstr_with_len(str ? (int64_t)(strlen(str) + 1) : 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief get the decoded length of data len of vstr
|
||||
* won't change the pos
|
||||
* @return the length of data
|
||||
*/
|
||||
inline int64_t decoded_length_vstr(const char *buf, const int64_t data_len, int64_t pos)
|
||||
{
|
||||
int64_t len = -1;
|
||||
int64_t tmp_pos = pos;
|
||||
if (NULL == buf || data_len < 0 || pos < 0) {
|
||||
len = -1;
|
||||
} else if (decode_vi64(buf, data_len, &tmp_pos, &len) != 0) {
|
||||
len = -1;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Encode a buf as vstr(int64,data,null)
|
||||
*
|
||||
* @param buf pointer to the destination buffer
|
||||
* @param vbuf pointer to the start of the input buffer
|
||||
* @param len length of the input buffer
|
||||
*/
|
||||
inline int encode_vstr_with_len(char *buf, const int64_t buf_len, int64_t *ppos, const void *vbuf,
|
||||
int64_t len)
|
||||
{
|
||||
int64_t pos = *ppos;
|
||||
int ret = ((NULL != buf) && (len >= 0)
|
||||
&& ((buf_len - pos) >= (int32_t)(encoded_length_vstr_with_len(len))))
|
||||
? OB_SUCCESS : OB_SIZE_OVERFLOW;
|
||||
if (OB_SUCC(ret)) {
|
||||
/**
|
||||
* even through it's a null string, we can serialize it with
|
||||
* lenght 0, and following a '\0'
|
||||
*/
|
||||
ret = encode_vi64(buf, buf_len, &pos, len);
|
||||
if (OB_SUCCESS == ret && len > 0 && NULL != vbuf) {
|
||||
memcpy(buf + pos, vbuf, len);
|
||||
pos += len;
|
||||
}
|
||||
*(buf + pos++) = 0;
|
||||
*ppos = pos;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline int encode_vstr(char *buf, const int64_t buf_len, int64_t *ppos, const char *s)
|
||||
{
|
||||
return encode_vstr_with_len(buf, buf_len, ppos, s, s ? strlen(s) + 1 : 0);
|
||||
}
|
||||
|
||||
inline const char *decode_vstr_nocopy(const char *buf, const int64_t data_len, int64_t *ppos, int64_t *lenp)
|
||||
{
|
||||
int64_t pos = *ppos;
|
||||
const char *str = 0;
|
||||
int64_t tmp_len = 0;
|
||||
int64_t tmp_pos = pos;
|
||||
|
||||
if ((NULL == buf) || (data_len < 0) || (pos < 0) || (NULL == lenp)) {
|
||||
//just _return_;
|
||||
} else if (decode_vi64(buf, data_len, &tmp_pos, &tmp_len) != OB_SUCCESS) {
|
||||
*lenp = -1;
|
||||
} else if (tmp_len >= 0) {
|
||||
if (data_len - tmp_pos >= tmp_len) {
|
||||
str = buf + tmp_pos;
|
||||
*lenp = tmp_len++;
|
||||
tmp_pos += tmp_len;
|
||||
pos = tmp_pos;
|
||||
} else {
|
||||
*lenp = -1;
|
||||
}
|
||||
}
|
||||
*ppos = pos;
|
||||
return str;
|
||||
}
|
||||
|
||||
inline const char *decode_vstr(const char *buf, const int64_t data_len, int64_t *ppos,
|
||||
char *dest, int64_t buf_len, int64_t *lenp)
|
||||
{
|
||||
int64_t pos = *ppos;
|
||||
const char *str = 0;
|
||||
int64_t tmp_len = 0;
|
||||
int64_t tmp_pos = pos;
|
||||
if ((NULL == buf) || (data_len < 0) || (pos < 0) || (0 == dest) || buf_len < 0 || (NULL == lenp)) {
|
||||
//just _return_;
|
||||
} else if (decode_vi64(buf, data_len, &tmp_pos, &tmp_len) != 0 || tmp_len > buf_len) {
|
||||
*lenp = -1;
|
||||
} else if (tmp_len >= 0) {
|
||||
if (data_len - tmp_pos >= tmp_len) {
|
||||
str = buf + tmp_pos;
|
||||
*lenp = tmp_len++;
|
||||
memcpy(dest, str, *lenp);
|
||||
tmp_pos += tmp_len;
|
||||
pos = tmp_pos;
|
||||
} else {
|
||||
*lenp = -1;
|
||||
}
|
||||
}
|
||||
*ppos = pos;
|
||||
return str;
|
||||
}
|
||||
38
libmariadb/ob_strtoll10.c
Normal file
38
libmariadb/ob_strtoll10.c
Normal file
@ -0,0 +1,38 @@
|
||||
/************************************************************************
|
||||
Copyright (c) 2021 OceanBase.
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
MA 02111-1301, USA
|
||||
|
||||
Part of this code includes code from PHP's mysqlnd extension
|
||||
(written by Andrey Hristov, Georg Richter and Ulf Wendel), freely
|
||||
available from http://www.php.net/software
|
||||
|
||||
*************************************************************************/
|
||||
|
||||
#include <ma_global.h>
|
||||
#include <ma_sys.h> /* Needed for MY_ERRNO_ERANGE */
|
||||
#include <ma_string.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#define MY_ERRNO_EDOM 33
|
||||
#define MY_ERRNO_ERANGE 34
|
||||
|
||||
longlong strtoll10(const char *nptr, char **endptr, int *error)
|
||||
{
|
||||
longlong ret = 0;
|
||||
ret = strtoll(nptr, endptr, 10);
|
||||
*error = errno;
|
||||
return ret;
|
||||
}
|
||||
254
libmariadb/ob_thread.c
Normal file
254
libmariadb/ob_thread.c
Normal file
@ -0,0 +1,254 @@
|
||||
/************************************************************************
|
||||
Copyright (c) 2021 OceanBase.
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
MA 02111-1301, USA
|
||||
|
||||
Part of this code includes code from PHP's mysqlnd extension
|
||||
(written by Andrey Hristov, Georg Richter and Ulf Wendel), freely
|
||||
available from http://www.php.net/software
|
||||
|
||||
*************************************************************************/
|
||||
#include "ob_thread.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <process.h>
|
||||
#include <signal.h>
|
||||
|
||||
unsigned int __stdcall ob_win_thread_start(void *win_start_param)
|
||||
{
|
||||
struct ob_thread_start_param *ob_start_param= (struct ob_thread_start_param *)win_start_param;
|
||||
ob_start_routine ob_start_func= ob_start_param->func;
|
||||
void *ob_start_arg= ob_start_param->arg;
|
||||
free(win_start_param);
|
||||
(*ob_start_func)(ob_start_arg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ob_thread_t ob_thread_self()
|
||||
{
|
||||
return GetCurrentThreadId();
|
||||
}
|
||||
|
||||
int ob_thread_equal(ob_thread_t ob_thread1, ob_thread_t ob_thread2)
|
||||
{
|
||||
return (ob_thread1 == ob_thread2);
|
||||
}
|
||||
|
||||
int ob_thread_attr_init(ob_thread_attr_t *ob_thread_attr)
|
||||
{
|
||||
ob_thread_attr->ob_thead_state= OB_THREAD_CREATE_JOINABLE;
|
||||
ob_thread_attr->ob_thread_stack_size= 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ob_thread_attr_destroy(ob_thread_attr_t *ob_thread_attr)
|
||||
{
|
||||
ob_thread_attr->ob_thead_state= OB_THREAD_CREATE_JOINABLE;
|
||||
ob_thread_attr->ob_thread_stack_size= 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ob_thread_attr_setstacksize(ob_thread_attr_t *ob_thread_attr, size_t ob_stacksize)
|
||||
{
|
||||
ob_thread_attr->ob_thread_stack_size= (DWORD)ob_stacksize;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ob_thread_attr_setdetachstate(ob_thread_attr_t *ob_thread_attr, int ob_ob_thead_state)
|
||||
{
|
||||
ob_thread_attr->ob_thead_state= ob_ob_thead_state;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ob_thread_attr_getstacksize(ob_thread_attr_t *ob_thread_attr, size_t *ob_stacksize)
|
||||
{
|
||||
*ob_stacksize= (size_t)ob_thread_attr->ob_thread_stack_size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ob_thread_yield()
|
||||
{
|
||||
SwitchToThread();
|
||||
}
|
||||
|
||||
int ob_thread_once(ob_thread_once_t *ob_once_control, void (*ob_routine)(void))
|
||||
{
|
||||
int ret = 0;
|
||||
LONG ob_thread_state;
|
||||
|
||||
if (OB_THREAD_ONCE_DONE == *ob_once_control) {
|
||||
ret = 0;
|
||||
} else {
|
||||
ob_thread_state = InterlockedCompareExchange(ob_once_control, OB_THREAD_ONCE_INPROGRESS, OB_THREAD_ONCE_INIT);
|
||||
|
||||
switch(ob_thread_state)
|
||||
{
|
||||
case OB_THREAD_ONCE_DONE:
|
||||
{
|
||||
// do nothing
|
||||
break;
|
||||
}
|
||||
case OB_THREAD_ONCE_INPROGRESS:
|
||||
{
|
||||
while(OB_THREAD_ONCE_INPROGRESS == *ob_once_control) {
|
||||
Sleep(1); // sleep
|
||||
}
|
||||
break;
|
||||
}
|
||||
case OB_THREAD_ONCE_INIT:
|
||||
{
|
||||
(*ob_routine)();
|
||||
*ob_once_control = OB_THREAD_ONCE_DONE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ob_thread_create(ob_thread_handle *ob_thread, const ob_thread_attr_t *ob_thread_attr,
|
||||
ob_start_routine ob_thread_func, void *ob_thread_arg)
|
||||
{
|
||||
int ret = 0;
|
||||
unsigned int ob_thread_stack_size;
|
||||
struct ob_thread_start_param *ob_thread_param;
|
||||
|
||||
if (NULL == (ob_thread_param = (struct ob_thread_start_param *)malloc(sizeof(*ob_thread_param)))) {
|
||||
ret = 1; // error
|
||||
} else {
|
||||
ob_thread_param->arg = ob_thread_arg;
|
||||
ob_thread_param->func = ob_thread_func;
|
||||
ob_thread_stack_size = ob_thread_attr ? ob_thread_attr->ob_thread_stack_size : 0;
|
||||
ob_thread->handle= (HANDLE)_beginthreadex(NULL, ob_thread_stack_size, ob_win_thread_start, ob_thread_param, 0, &ob_thread->thread);
|
||||
if (NULL == ob_thread->handle) {
|
||||
// error, free param
|
||||
free(ob_thread_param);
|
||||
ret = 1;
|
||||
} else if (ob_thread_attr && OB_THREAD_CREATE_DETACHED == ob_thread_attr->ob_thead_state) {
|
||||
CloseHandle(ob_thread->handle);
|
||||
ob_thread->handle= NULL;
|
||||
}
|
||||
}
|
||||
if (0 != ret) {
|
||||
ob_thread->handle= NULL;
|
||||
ob_thread->thread= 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ob_thread_join(ob_thread_handle *ob_thread, void **ob_join_ptr)
|
||||
{
|
||||
int ret = 0;
|
||||
if (WAIT_OBJECT_0 != WaitForSingleObject(ob_thread->handle, INFINITE)) {
|
||||
ret = 1;
|
||||
} else if (ob_thread->handle) {
|
||||
CloseHandle(ob_thread->handle);
|
||||
}
|
||||
if (0 != ret) {
|
||||
ob_thread->thread= 0;
|
||||
ob_thread->handle= NULL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ob_thread_cancel(ob_thread_handle *ob_thread)
|
||||
{
|
||||
int ret = 0;
|
||||
BOOL terminate_ret = FALSE;
|
||||
if (ob_thread->handle) {
|
||||
if (FALSE == (terminate_ret = TerminateThread(ob_thread->handle, 0))) {
|
||||
errno= EINVAL;
|
||||
ret = -1;
|
||||
} else {
|
||||
CloseHandle(ob_thread->handle);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ob_thread_exit(void *ob_thread_exit_ptr)
|
||||
{
|
||||
_endthreadex(0);
|
||||
}
|
||||
#else
|
||||
// for unix
|
||||
|
||||
ob_thread_t ob_thread_self()
|
||||
{
|
||||
return pthread_self();
|
||||
}
|
||||
|
||||
int ob_thread_equal(ob_thread_t ob_thread1, ob_thread_t ob_thread2)
|
||||
{
|
||||
return pthread_equal(ob_thread1, ob_thread2);
|
||||
}
|
||||
|
||||
int ob_thread_attr_init(ob_thread_attr_t *ob_thread_attr)
|
||||
{
|
||||
return pthread_attr_init(ob_thread_attr);
|
||||
}
|
||||
|
||||
int ob_thread_attr_destroy(ob_thread_attr_t *ob_thread_attr)
|
||||
{
|
||||
return pthread_attr_destroy(ob_thread_attr);
|
||||
}
|
||||
|
||||
int ob_thread_attr_setstacksize(ob_thread_attr_t *ob_thread_attr, size_t ob_stacksize)
|
||||
{
|
||||
return pthread_attr_setstacksize(ob_thread_attr, ob_stacksize);
|
||||
}
|
||||
|
||||
int ob_thread_attr_setdetachstate(ob_thread_attr_t *ob_thread_attr, int ob_ob_thead_state)
|
||||
{
|
||||
return pthread_attr_setdetachstate(ob_thread_attr, ob_ob_thead_state);
|
||||
}
|
||||
|
||||
int ob_thread_attr_getstacksize(ob_thread_attr_t *ob_thread_attr, size_t *ob_stacksize)
|
||||
{
|
||||
return pthread_attr_getstacksize(ob_thread_attr, ob_stacksize);
|
||||
}
|
||||
|
||||
void ob_thread_yield()
|
||||
{
|
||||
sched_yield();
|
||||
}
|
||||
|
||||
int ob_thread_once(ob_thread_once_t *ob_once_control, void (*ob_routine)(void))
|
||||
{
|
||||
return pthread_once(ob_once_control, ob_routine);
|
||||
}
|
||||
|
||||
int ob_thread_create(ob_thread_handle *ob_thread, const ob_thread_attr_t *ob_thread_attr,
|
||||
ob_start_routine ob_thread_func, void *ob_thread_arg)
|
||||
{
|
||||
return pthread_create(&ob_thread->thread, ob_thread_attr, ob_thread_func, ob_thread_arg);
|
||||
}
|
||||
|
||||
int ob_thread_join(ob_thread_handle *ob_thread, void **ob_join_ptr)
|
||||
{
|
||||
return pthread_join(ob_thread->thread, ob_join_ptr);
|
||||
}
|
||||
|
||||
int ob_thread_cancel(ob_thread_handle *ob_thread)
|
||||
{
|
||||
return pthread_cancel(ob_thread->thread);
|
||||
}
|
||||
|
||||
void ob_thread_exit(void *ob_thread_exit_ptr)
|
||||
{
|
||||
pthread_exit(ob_thread_exit_ptr);
|
||||
}
|
||||
|
||||
#endif
|
||||
76
libmariadb/ob_thread_key.c
Normal file
76
libmariadb/ob_thread_key.c
Normal file
@ -0,0 +1,76 @@
|
||||
/************************************************************************
|
||||
Copyright (c) 2021 OceanBase.
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
MA 02111-1301, USA
|
||||
|
||||
Part of this code includes code from PHP's mysqlnd extension
|
||||
(written by Andrey Hristov, Georg Richter and Ulf Wendel), freely
|
||||
available from http://www.php.net/software
|
||||
|
||||
*************************************************************************/
|
||||
|
||||
#include "ob_thread_key.h"
|
||||
|
||||
#ifndef UNUSED
|
||||
#define UNUSED(x) ((void)(x))
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
int ob_create_thread_key(ob_thread_key_t *ob_key, void (*ob_destructor)(void *))
|
||||
{
|
||||
UNUSED(ob_destructor);
|
||||
*ob_key = TlsAlloc();
|
||||
return (TLS_OUT_OF_INDEXES == *ob_key);
|
||||
}
|
||||
|
||||
int ob_delete_thread_key(ob_thread_key_t ob_key)
|
||||
{
|
||||
return !TlsFree(ob_key);
|
||||
}
|
||||
|
||||
void *ob_get_thread_key(ob_thread_key_t ob_key)
|
||||
{
|
||||
return TlsGetValue(ob_key);
|
||||
}
|
||||
|
||||
int ob_set_thread_key(ob_thread_key_t ob_key, void *value)
|
||||
{
|
||||
return !TlsSetValue(ob_key, value);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
int ob_create_thread_key(ob_thread_key_t *ob_key, void (*ob_destructor)(void *))
|
||||
{
|
||||
return pthread_key_create(ob_key, ob_destructor);
|
||||
}
|
||||
|
||||
int ob_delete_thread_key(ob_thread_key_t ob_key)
|
||||
{
|
||||
return pthread_key_delete(ob_key);
|
||||
}
|
||||
|
||||
void *ob_get_thread_key(ob_thread_key_t ob_key)
|
||||
{
|
||||
return pthread_getspecific(ob_key);
|
||||
}
|
||||
|
||||
int ob_set_thread_key(ob_thread_key_t ob_key, void *value)
|
||||
{
|
||||
return pthread_setspecific(ob_key, value);
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -10,11 +10,11 @@ prefix=@CMAKE_INSTALL_PREFIX@
|
||||
includedir=${prefix}/@INSTALL_INCLUDEDIR@/@SUFFIX_INSTALL_DIR@
|
||||
libdir=${prefix}/@INSTALL_LIBDIR@/@SUFFIX_INSTALL_DIR@
|
||||
|
||||
Name: libmariadb
|
||||
Name: libobclnt
|
||||
Version: @CPACK_PACKAGE_VERSION@
|
||||
Description: MariaDB Connector/C dynamic library
|
||||
Cflags: -I${includedir}
|
||||
Libs: -L${libdir} -lmariadb
|
||||
Libs: -L${libdir} -lobclnt
|
||||
Libs.private: @extra_dynamic_LDFLAGS@
|
||||
|
||||
|
||||
|
||||
@ -28,7 +28,7 @@ static char *mariadb_progname;
|
||||
#endif
|
||||
|
||||
#define INCLUDE "-I%s/@INSTALL_INCLUDEDIR@ -I%s/@INSTALL_INCLUDEDIR@/mysql"
|
||||
#define LIBS "-L%s/@INSTALL_LIBDIR@/ -lmariadb"
|
||||
#define LIBS "-L%s/@INSTALL_LIBDIR@/ -lobclnt"
|
||||
#define LIBS_SYS "@extra_dynamic_LDFLAGS@"
|
||||
#define CFLAGS INCLUDE
|
||||
#define VERSION "@MARIADB_CLIENT_VERSION@"
|
||||
|
||||
@ -257,6 +257,10 @@ static int send_client_reply_packet(MCPVIO_EXT *mpvio,
|
||||
mysql->client_flag&= ~CLIENT_COMPRESS;
|
||||
#endif
|
||||
|
||||
if (FALSE == mysql->can_use_protocol_ob20) {
|
||||
mysql->client_flag&= ~CLIENT_COMPRESS;
|
||||
}
|
||||
|
||||
if (mysql->client_flag & CLIENT_PROTOCOL_41)
|
||||
{
|
||||
/* 4.1 server and 4.1 client has a 32 byte option flag */
|
||||
|
||||
@ -1 +1 @@
|
||||
2.0.2
|
||||
2.2.0
|
||||
|
||||
@ -3,10 +3,23 @@
|
||||
# Usage: obclient-build.sh <oceanbasepath> <package> <version> <release>
|
||||
# Usage: obclient-build.sh
|
||||
|
||||
TOP_DIR=$1
|
||||
PACKAGE=$2
|
||||
VERSION=$3
|
||||
RELEASE=$4
|
||||
REDHAT=`cat /etc/redhat-release|cut -d " " -f 7|cut -d "." -f 1`
|
||||
|
||||
if [ $# -ne 4 ]
|
||||
then
|
||||
TOP_DIR=`pwd`/../
|
||||
PACKAGE=$(basename $0 -build.sh)
|
||||
VERSION=`cat ${PACKAGE}-VER.txt`
|
||||
RELEASE="1"
|
||||
#RELEASE="dev.el${REDHAT}"
|
||||
else
|
||||
TOP_DIR=$1
|
||||
PACKAGE=$2
|
||||
VERSION=$3
|
||||
RELEASE="$4.el${REDHAT}"
|
||||
export AONE_BUILD_NUMBER=${4}
|
||||
fi
|
||||
echo "[BUILD] args: TOP_DIR=${TOP_DIR} PACKAGE=${PACKAGE} VERSION=${VERSION} RELEASE=${RELEASE} AONE_BUILD_NUMBER=${AONE_BUILD_NUMBER}"
|
||||
|
||||
TMP_DIR=${TOP_DIR}/${PACKAGE}-tmp.$$
|
||||
BOOST_DIR=${TMP_DIR}/BOOST
|
||||
|
||||
@ -37,11 +37,11 @@ do
|
||||
done
|
||||
mkdir -p $RPM_BUILD_ROOT%{prefix}
|
||||
mv $RPM_BUILD_ROOT%{file_dir}/* $RPM_BUILD_ROOT%{prefix}
|
||||
mv $RPM_BUILD_ROOT%{prefix}/include/mariadb $RPM_BUILD_ROOT%{prefix}/include/mariadb_bak
|
||||
mv $RPM_BUILD_ROOT%{prefix}/include/mariadb_bak/* $RPM_BUILD_ROOT%{prefix}/include/
|
||||
rm -rf $RPM_BUILD_ROOT%{prefix}/include/mariadb_bak
|
||||
mv $RPM_BUILD_ROOT%{prefix}/lib/mariadb/* $RPM_BUILD_ROOT%{prefix}/lib/
|
||||
rm -rf $RPM_BUILD_ROOT%{prefix}/lib/mariadb
|
||||
#mv $RPM_BUILD_ROOT%{prefix}/include/mariadb $RPM_BUILD_ROOT%{prefix}/include/mariadb_bak
|
||||
#mv $RPM_BUILD_ROOT%{prefix}/include/mariadb_bak/* $RPM_BUILD_ROOT%{prefix}/include/
|
||||
#rm -rf $RPM_BUILD_ROOT%{prefix}/include/mariadb_bak
|
||||
#mv $RPM_BUILD_ROOT%{prefix}/lib/mariadb/* $RPM_BUILD_ROOT%{prefix}/lib/
|
||||
#rm -rf $RPM_BUILD_ROOT%{prefix}/lib/mariadb
|
||||
|
||||
%clean
|
||||
rm -rf $RPM_BUILD_ROOT
|
||||
|
||||
@ -1,16 +1,35 @@
|
||||
CFLAGS= -I../../include
|
||||
CCFLAGS= -I../../include
|
||||
LDFLAGS= -g -L ../../libmariadb/ -lobclnt -lz -lpthread -lgtest
|
||||
BIN=ob_mysql_ps_test ob_mysql_text_test ob_oracle_ps_test
|
||||
BIN=ob_mysql_ps_test ob_mysql_ps_cursor_test ob_mysql_text_test ob_oracle_ps_test \
|
||||
ob_oracle_datetype_test ob_new_ps_test ob_new_ps_select_notable ob_new_ps_select_test \
|
||||
ob_mysql_ssl_test ob_oracle_fetch_cursor_test ob_oracle_array_binding_test \
|
||||
ob_oracle_pl_test
|
||||
EXEC=env LD_LIBRARY_PATH=../../libmariadb/
|
||||
all:${BIN} run
|
||||
.PHONY:clean
|
||||
ob_mysql_ps_cursor_test:ob_mysql_ps_cursor_test.c
|
||||
ob_mysql_ps_test:ob_mysql_ps_test.c
|
||||
ob_mysql_text_test:ob_mysql_text_test.c
|
||||
ob_oracle_ps_test:ob_oracle_ps_test.c
|
||||
ob_oracle_datetype_test:ob_oracle_datetype_test.c
|
||||
ob_new_ps_test:ob_new_ps_test.c
|
||||
ob_new_ps_select_notable:ob_new_ps_select_notable.c
|
||||
ob_new_ps_select_test:ob_new_ps_select_test.c
|
||||
ob_mysql_ssl_test:ob_mysql_ssl_test.c
|
||||
ob_oracle_fetch_cursor_test:ob_oracle_fetch_cursor_test.c
|
||||
ob_oracle_array_binding_test:ob_oracle_array_binding_test.c
|
||||
ob_oracle_pl_test:ob_oracle_pl_test.c
|
||||
run:
|
||||
$(EXEC) ./ob_mysql_ps_test
|
||||
$(EXEC) ./ob_mysql_ps_cursor_test
|
||||
$(EXEC) ./ob_mysql_text_test
|
||||
$(EXEC) ./ob_oracle_ps_test
|
||||
$(EXEC) ./ob_oracle_datetype_test
|
||||
$(EXEC) ./ob_new_ps_test
|
||||
$(EXEC) ./ob_new_ps_select_notable
|
||||
$(EXEC) ./ob_new_ps_select_test
|
||||
$(EXEC) ./ob_oracle_fetch_cursor_test
|
||||
$(EXEC) ./ob_oracle_array_binding_test
|
||||
clean:
|
||||
rm -rf ${BIN} *.o
|
||||
|
||||
129
unittest/my_test/ob_mysql_ps_cursor_test.c
Normal file
129
unittest/my_test/ob_mysql_ps_cursor_test.c
Normal file
@ -0,0 +1,129 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "mysql.h"
|
||||
#include "test_util.h"
|
||||
/*
|
||||
*
|
||||
*/
|
||||
int do_stmt_select_with_cursor(MYSQL* mysql) {
|
||||
my_log("=========do_stmt_select_with_cursor==========");
|
||||
const char* pStatement = "select * from person where id > ?";
|
||||
MYSQL_STMT *stmt;
|
||||
MYSQL_BIND bind[4];
|
||||
int param_count;
|
||||
int filed_count;
|
||||
//prepare data
|
||||
int i = 0;
|
||||
char insert_buf[100] = {0};
|
||||
for (i = 0; i < 10; i++)
|
||||
{
|
||||
snprintf(insert_buf, 100, "insert into person values('%d', '%d', 'test_%d', '2021-04-06 10:21:00');", i, i, i);
|
||||
// my_log("buf is %s", insert_buf);
|
||||
if (mysql_real_query(mysql, insert_buf, strlen(insert_buf))) {
|
||||
my_log("mysql_real_query failed:%s", mysql_error(mysql));
|
||||
}
|
||||
}
|
||||
my_ulonglong affected_rows;
|
||||
stmt = mysql_stmt_init(mysql);
|
||||
if (!stmt) {
|
||||
my_log("msyql_stmt_init failed: %s", mysql_error(mysql));
|
||||
return -1;
|
||||
}
|
||||
if (mysql_stmt_prepare(stmt, pStatement, strlen(pStatement))) {
|
||||
my_log("mysql_stmt_prepare failed:%s", mysql_error(mysql));
|
||||
return -1;
|
||||
}
|
||||
filed_count = mysql_stmt_field_count(stmt);
|
||||
param_count = mysql_stmt_param_count(stmt);
|
||||
ASSERT_EQ(param_count, 1, "mysql_stmt_param_count");
|
||||
int id, num;
|
||||
id = 0;
|
||||
memset(bind, 0, sizeof(bind));
|
||||
{
|
||||
//id
|
||||
bind[0].buffer_type = MYSQL_TYPE_LONG;
|
||||
bind[0].buffer = (char*)&id;
|
||||
bind[0].buffer_length = 0;
|
||||
bind[0].is_null = 0;
|
||||
bind[0].length = 0;
|
||||
// bind[0].is_unsigned = 0;
|
||||
}
|
||||
if (mysql_stmt_bind_param(stmt, bind)) {
|
||||
my_log("bind failed:%s", mysql_stmt_error(stmt));
|
||||
ASSERT_EQ(0, -1, "mysql_stmt_bind_param failed");
|
||||
return -1;
|
||||
}
|
||||
ulong cursor_type = CURSOR_TYPE_READ_ONLY;
|
||||
ASSERT_EQ(0, mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, &cursor_type), "mysql_stmt_attr_set");
|
||||
unsigned int iteration_count = 1;
|
||||
//stmt->iteration_count = 0;
|
||||
if (mysql_stmt_execute(stmt)) {
|
||||
my_log("mysql_stmt_execute select failed:%s", mysql_stmt_error(stmt));
|
||||
return -1;
|
||||
}
|
||||
// if (mysql_stmt_store_result(stmt)) {
|
||||
// my_log("mysql_stmt_store_result failed :%s", mysql_stmt_error(stmt));
|
||||
// return -1;
|
||||
// }
|
||||
filed_count = mysql_stmt_field_count(stmt);
|
||||
ASSERT_EQ(filed_count, 4, "mysql_stmt_field_count");
|
||||
my_ulonglong row_count = mysql_stmt_num_rows(stmt);
|
||||
// ASSERT_EQ(row_count, 9, "mysql_stmt_num_rows");
|
||||
memset(bind, 0, sizeof(bind));
|
||||
char name[20];
|
||||
char birthday[20];
|
||||
bind[0].buffer_type = MYSQL_TYPE_LONG;
|
||||
bind[0].buffer = &id;
|
||||
bind[1].buffer_type = MYSQL_TYPE_LONG;
|
||||
bind[1].buffer = #
|
||||
bind[2].buffer_type = MYSQL_TYPE_STRING;
|
||||
bind[2].buffer = name;
|
||||
bind[2].buffer_length = sizeof(name);
|
||||
bind[3].buffer_type = MYSQL_TYPE_STRING;
|
||||
bind[3].buffer = birthday;
|
||||
bind[3].buffer_length = sizeof(birthday);
|
||||
|
||||
if (mysql_stmt_bind_result(stmt, bind)) {
|
||||
my_log("mysql_stmt_bind_result failed:%s", mysql_stmt_error(stmt));
|
||||
return -1;
|
||||
}
|
||||
i = 1;
|
||||
while (mysql_stmt_fetch(stmt) == 0) {
|
||||
if (id != i) {
|
||||
ASSERT_EQ(id, i, "check value");
|
||||
}
|
||||
++i;
|
||||
// my_log("%d\t%d\t%s\t%s\n", id, num, name, birthday);
|
||||
}
|
||||
mysql_stmt_close(stmt);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
mysql_library_init(0, NULL, NULL);
|
||||
MYSQL *mysql = mysql_init(NULL);
|
||||
unsigned int timeout = 3000;
|
||||
init_conn_info(OB_MYSQL_MODE);
|
||||
mysql_options(mysql, MYSQL_OPT_CONNECT_TIMEOUT, &timeout);
|
||||
|
||||
if (mysql_real_connect(mysql, DBHOST, DBUSER, DBPASS, DBNAME, DBPORT, DBSOCK, DBPCNT) == NULL)
|
||||
{
|
||||
my_log("connect failed: %s, host:%s, port:%d, user:%s, pass:%s, dbname:%s",
|
||||
mysql_error(mysql),DBHOST, DBPORT, DBUSER, DBPASS, DBNAME);
|
||||
mysql_close(mysql);
|
||||
mysql_library_end();
|
||||
return 0;
|
||||
} else {
|
||||
my_log("connect %s:%d using %s succ", DBHOST, DBPORT, DBUSER);
|
||||
}
|
||||
int ret = 0;
|
||||
mysql_query(mysql, "drop table person");
|
||||
ret = mysql_query(mysql, "create table person(id int, num int, name varchar(20), birthday varchar(20))");
|
||||
if (ret != 0)
|
||||
{
|
||||
my_log("create table error, %s", mysql_error(mysql));
|
||||
return ret;
|
||||
}
|
||||
do_stmt_select_with_cursor(mysql);
|
||||
return 0;
|
||||
}
|
||||
@ -133,7 +133,7 @@ int do_stmt_insert(MYSQL* mysql) {
|
||||
}
|
||||
int do_stmt_select(MYSQL* mysql) {
|
||||
my_log("=========do_stmt_select==========");
|
||||
const char* pStatement = "select * from person";
|
||||
const char* pStatement = "select * from person where id > ?";
|
||||
MYSQL_STMT *stmt;
|
||||
MYSQL_BIND bind[4];
|
||||
int param_count;
|
||||
@ -150,6 +150,24 @@ int do_stmt_select(MYSQL* mysql) {
|
||||
}
|
||||
filed_count = mysql_stmt_field_count(stmt);
|
||||
param_count = mysql_stmt_param_count(stmt);
|
||||
ASSERT_EQ(param_count, 1, "mysql_stmt_param_count");
|
||||
int id, num;
|
||||
id = 0;
|
||||
memset(bind, 0, sizeof(bind));
|
||||
{
|
||||
//id
|
||||
bind[0].buffer_type = MYSQL_TYPE_LONG;
|
||||
bind[0].buffer = (char*)&id;
|
||||
bind[0].buffer_length = 0;
|
||||
bind[0].is_null = 0;
|
||||
bind[0].length = 0;
|
||||
// bind[0].is_unsigned = 0;
|
||||
}
|
||||
if (mysql_stmt_bind_param(stmt, bind)) {
|
||||
my_log("bind failed:%s", mysql_stmt_error(stmt));
|
||||
ASSERT_EQ(0, -1, "mysql_stmt_bind_param failed");
|
||||
return -1;
|
||||
}
|
||||
unsigned int iteration_count = 1;
|
||||
//stmt->iteration_count = 0;
|
||||
if (mysql_stmt_execute(stmt)) {
|
||||
@ -165,7 +183,6 @@ int do_stmt_select(MYSQL* mysql) {
|
||||
my_ulonglong row_count = mysql_stmt_num_rows(stmt);
|
||||
ASSERT_EQ(row_count, 9, "mysql_stmt_field_count");
|
||||
memset(bind, 0, sizeof(bind));
|
||||
int id, num;
|
||||
char name[20];
|
||||
char birthday[20];
|
||||
bind[0].buffer_type = MYSQL_TYPE_LONG;
|
||||
|
||||
97
unittest/my_test/ob_mysql_ssl_test.c
Normal file
97
unittest/my_test/ob_mysql_ssl_test.c
Normal file
@ -0,0 +1,97 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "mysql.h"
|
||||
#include "test_util.h"
|
||||
/*
|
||||
*
|
||||
*/
|
||||
inline long long get_cur_time()
|
||||
{
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, NULL);
|
||||
return tv.tv_sec * 1000000 + tv.tv_usec;
|
||||
}
|
||||
int do_stmt_select_query(MYSQL* mysql) {
|
||||
my_log("=========do_stmt_select_query==========");
|
||||
const char* select_query = "select * from test;";
|
||||
const char* insert_query = "insert into test values(1, 'test1')";
|
||||
int filed_count;
|
||||
my_ulonglong affected_rows;
|
||||
int64_t t_start, t_end;
|
||||
t_start = get_cur_time();
|
||||
if (mysql_real_query(mysql, insert_query, strlen(insert_query))) {
|
||||
my_log("mysql_real_query insert_query failed:%s", mysql_error(mysql));
|
||||
ASSERT_EQ(0, -1, "mysql_real_query");
|
||||
return -1;
|
||||
}
|
||||
if (mysql_real_query(mysql, select_query, strlen(select_query))) {
|
||||
my_log("mysql_real_query select failed:%s", mysql_error(mysql));
|
||||
ASSERT_EQ(0, -1, "mysql_real_query");
|
||||
return -1;
|
||||
}
|
||||
t_end = get_cur_time();
|
||||
// printf("mysql_real_query cost time %ld us\n", t_end - t_start);
|
||||
t_start = t_end;
|
||||
MYSQL_RES * result = mysql_use_result(mysql);
|
||||
t_end = get_cur_time();
|
||||
// printf("store result cost time %ld us\n", t_end - t_start);
|
||||
t_start = t_end;
|
||||
if (!result) {
|
||||
my_log("unexpect null result");
|
||||
ASSERT_EQ(0, -1, "mysql_use_result get null");
|
||||
return -1;
|
||||
}
|
||||
filed_count = mysql_num_fields(result);
|
||||
ASSERT_EQ(filed_count, 2, "mysql_num_fields");
|
||||
int i = 0;
|
||||
MYSQL_FIELD *fields = mysql_fetch_fields(result);
|
||||
for(i = 0; i < filed_count; i++)
|
||||
{
|
||||
printf("%s\t", fields[i].name);
|
||||
if (i == 0 && strcasecmp(fields[i].name, "ID") != 0) {
|
||||
ASSERT_EQ(0, -1, "invalid field");
|
||||
} else if (i == 1 && strcasecmp(fields[i].name, "NAME") != 0) {
|
||||
ASSERT_EQ(0, -1, "invalid field");
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
int result_count = 0;
|
||||
MYSQL_ROW sql_row;
|
||||
while (sql_row = mysql_fetch_row(result)) {
|
||||
result_count++;
|
||||
for (i = 0; i < filed_count; i++)
|
||||
{
|
||||
//
|
||||
}
|
||||
}
|
||||
t_end = get_cur_time();
|
||||
// printf("fetch %d cost time %ld us\n", result_count, t_end - t_start);
|
||||
mysql_free_result(result);
|
||||
return 0;
|
||||
}
|
||||
int main(int argc, char** argv) {
|
||||
mysql_library_init(0, NULL, NULL);
|
||||
MYSQL *mysql = mysql_init(NULL);
|
||||
unsigned int timeout = 3000;
|
||||
init_conn_info(OB_MYSQL_MODE);
|
||||
mysql_options(mysql, MYSQL_OPT_CONNECT_TIMEOUT, &timeout);
|
||||
if (mysql_real_connect(mysql, DBHOST, DBUSER, DBPASS, DBNAME, DBPORT, DBSOCK, DBPCNT) == NULL)
|
||||
{
|
||||
my_log("connect failed: %s, host:%s, port:%d, user:%s, pass:%s, dbname:%s",
|
||||
mysql_error(mysql),DBHOST, DBPORT, DBUSER, DBPASS, DBNAME);
|
||||
mysql_close(mysql);
|
||||
mysql_library_end();
|
||||
return 0;
|
||||
} else {
|
||||
my_log("connect %s:%d using %s succ", DBHOST, DBPORT, DBUSER);
|
||||
}
|
||||
int ret = 0;
|
||||
mysql_real_query(mysql, "drop table test", strlen("drop table test"));
|
||||
ret = mysql_query(mysql, "create table test(id int, name varchar(20))");
|
||||
if (ret != 0){
|
||||
printf("create table failed, %s\n", mysql_error(mysql));
|
||||
return ret;
|
||||
}
|
||||
do_stmt_select_query(mysql);
|
||||
return 0;
|
||||
}
|
||||
214
unittest/my_test/ob_new_ps_insert_test.c
Normal file
214
unittest/my_test/ob_new_ps_insert_test.c
Normal file
@ -0,0 +1,214 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "mysql.h"
|
||||
#include "test_util.h"
|
||||
|
||||
int stmt_insert_long_data_test(MYSQL* mysql) {
|
||||
my_log("stmt_insert_test");
|
||||
const char* pStatement = "insert into test_new_ps(id,name) values(?,?)";
|
||||
MYSQL_STMT *stmt;
|
||||
MYSQL_BIND bind[2];
|
||||
int param_count;
|
||||
int id = 8;
|
||||
int num = 10;
|
||||
int ret = 0;
|
||||
int i = 0;
|
||||
// char table[30] = "test.person";
|
||||
// char name[30] = "jh";
|
||||
// char birthday[20] = "2018-01-01";
|
||||
char name[20] = "data long than";
|
||||
my_ulonglong affected_rows;
|
||||
stmt = mysql_stmt_init(mysql);
|
||||
if (!stmt) {
|
||||
my_log("msyql_stmt_init failed: %s\n", mysql_error(mysql));
|
||||
return -1;
|
||||
}
|
||||
if (ret = mysql_stmt_prepare_v2(stmt, pStatement, strlen(pStatement), NULL)) {
|
||||
my_log("mysql_stmt_prepare_v2 failed:%s\n", mysql_error(mysql));
|
||||
return -1;
|
||||
} else {
|
||||
ASSERT_EQ(ret , 0, "mysql_stmt_prepare_v2");
|
||||
}
|
||||
|
||||
param_count = mysql_stmt_param_count(stmt);
|
||||
my_log("param_count is %d", param_count);
|
||||
ASSERT_EQ(param_count, 2, "mysql_stmt_param_count");
|
||||
memset(bind, 0, sizeof(bind));
|
||||
{
|
||||
//id
|
||||
bind[0].buffer_type = MYSQL_TYPE_LONG;
|
||||
bind[0].buffer = (char*)&id;
|
||||
bind[0].buffer_length = 0;
|
||||
bind[0].is_null = 0;
|
||||
bind[0].length = 0;
|
||||
// bind[0].is_unsigned = 0;
|
||||
}
|
||||
{
|
||||
//name
|
||||
unsigned long str_len = strlen(name);
|
||||
my_log("str_len for name is %d", str_len);
|
||||
bind[1].buffer_type = MYSQL_TYPE_STRING;
|
||||
bind[1].buffer = (char*)name;
|
||||
bind[1].buffer_length = str_len;
|
||||
bind[1].is_null = 0;
|
||||
bind[1].length = &str_len;
|
||||
// bind[2].is_unsigned = 0;
|
||||
}
|
||||
if (ret = mysql_stmt_bind_param(stmt, bind)) {
|
||||
my_log("bind failed:%s", mysql_stmt_error(stmt));
|
||||
return -1;
|
||||
} else {
|
||||
ASSERT_EQ(ret, 0, "mysql_stmt_bind_param");
|
||||
}
|
||||
unsigned int iteration_count = 1;
|
||||
// mysql_stmt_attr_set(stmt, STMT_ATTR_ITERRATION_COUNT, &iteration_count);
|
||||
//stmt->iteration_count = 1;
|
||||
for (i = 0; i < 2; i++) {
|
||||
if (mysql_stmt_execute_v2(stmt,pStatement, strlen(pStatement), iteration_count, 0, 0)) {
|
||||
my_log("mysql_stmt_execute_v2 insert failed:%s", mysql_stmt_error(stmt));
|
||||
return -1;
|
||||
}
|
||||
affected_rows = mysql_stmt_affected_rows(stmt);
|
||||
my_log("insert %d affected rows :%lu", iteration_count,affected_rows);
|
||||
ASSERT_EQ(affected_rows, 0, "mysql_stmt_affected_rows");
|
||||
snprintf(name, 20, "short");
|
||||
if (ret = mysql_stmt_execute_v2(stmt, pStatement, strlen(pStatement),iteration_count, 0, 0)) {
|
||||
my_log("mysql_stmt_execute_v2 insert failed:%s", mysql_stmt_error(stmt));
|
||||
return -1;
|
||||
} else {
|
||||
ASSERT_EQ(ret, 0, "mysql_stmt_execute_v2");
|
||||
}
|
||||
affected_rows = mysql_stmt_affected_rows(stmt);
|
||||
my_log("insert %d affected rows :%lu", iteration_count, affected_rows);
|
||||
ASSERT_EQ(affected_rows, 1, "mysql_stmt_affected_rows");
|
||||
}
|
||||
if (ret = mysql_stmt_close(stmt)) {
|
||||
my_log("mysql_stmt_close faield:%s", mysql_stmt_error(stmt));
|
||||
return -1;
|
||||
} else {
|
||||
ASSERT_EQ(ret, 0, "mysql_stmt_close");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
int stmt_insert_data_test(MYSQL* mysql) {
|
||||
my_log("stmt_insert_test");
|
||||
const char* pStatement = "insert into test_new_ps(id,name) values(?,?)";
|
||||
MYSQL_STMT *stmt;
|
||||
MYSQL_BIND bind[2];
|
||||
int param_count;
|
||||
int id = 8;
|
||||
int num = 10;
|
||||
int ret = 0;
|
||||
int i = 0;
|
||||
// char table[30] = "test.person";
|
||||
// char name[30] = "jh";
|
||||
// char birthday[20] = "2018-01-01";
|
||||
char name[20] = "data1";
|
||||
my_ulonglong affected_rows;
|
||||
stmt = mysql_stmt_init(mysql);
|
||||
if (!stmt) {
|
||||
my_log("msyql_stmt_init failed: %s\n", mysql_error(mysql));
|
||||
return -1;
|
||||
}
|
||||
if (ret = mysql_stmt_prepare_v2(stmt, pStatement, strlen(pStatement), NULL)) {
|
||||
my_log("mysql_stmt_prepare_v2 failed:%s\n", mysql_error(mysql));
|
||||
return -1;
|
||||
} else {
|
||||
ASSERT_EQ(ret , 0, "mysql_stmt_prepare_v2");
|
||||
}
|
||||
|
||||
param_count = mysql_stmt_param_count(stmt);
|
||||
my_log("param_count is %d", param_count);
|
||||
ASSERT_EQ(param_count, 2, "mysql_stmt_param_count");
|
||||
memset(bind, 0, sizeof(bind));
|
||||
{
|
||||
//id
|
||||
bind[0].buffer_type = MYSQL_TYPE_LONG;
|
||||
bind[0].buffer = (char*)&id;
|
||||
bind[0].buffer_length = 0;
|
||||
bind[0].is_null = 0;
|
||||
bind[0].length = 0;
|
||||
// bind[0].is_unsigned = 0;
|
||||
}
|
||||
{
|
||||
//name
|
||||
unsigned long str_len = strlen(name);
|
||||
my_log("str_len for name is %d", str_len);
|
||||
bind[1].buffer_type = MYSQL_TYPE_STRING;
|
||||
bind[1].buffer = (char*)name;
|
||||
bind[1].buffer_length = str_len;
|
||||
bind[1].is_null = 0;
|
||||
bind[1].length = &str_len;
|
||||
// bind[2].is_unsigned = 0;
|
||||
}
|
||||
if (ret = mysql_stmt_bind_param(stmt, bind)) {
|
||||
my_log("bind failed:%s", mysql_stmt_error(stmt));
|
||||
return -1;
|
||||
} else {
|
||||
ASSERT_EQ(ret, 0, "mysql_stmt_bind_param");
|
||||
}
|
||||
unsigned int iteration_count = 1;
|
||||
// mysql_stmt_attr_set(stmt, STMT_ATTR_ITERRATION_COUNT, &iteration_count);
|
||||
//stmt->iteration_count = 1;
|
||||
for (i = 0; i < 2; i++)
|
||||
{
|
||||
if (mysql_stmt_execute_v2(stmt, pStatement, strlen(pStatement), iteration_count, 0, 0)) {
|
||||
my_log("mysql_stmt_execute_v2 insert failed:%s", mysql_stmt_error(stmt));
|
||||
return -1;
|
||||
}
|
||||
affected_rows = mysql_stmt_affected_rows(stmt);
|
||||
my_log("insert %d affected rows :%lu", iteration_count,affected_rows);
|
||||
ASSERT_EQ(affected_rows, 1, "mysql_stmt_affected_rows");
|
||||
snprintf(name, 20, "short");
|
||||
if (ret = mysql_stmt_execute_v2(stmt, pStatement, strlen(pStatement),iteration_count, 0, 0)) {
|
||||
my_log("mysql_stmt_execute_v2 insert failed:%s", mysql_stmt_error(stmt));
|
||||
return -1;
|
||||
} else {
|
||||
ASSERT_EQ(ret, 0, "mysql_stmt_execute_v2");
|
||||
}
|
||||
affected_rows = mysql_stmt_affected_rows(stmt);
|
||||
my_log("insert %d affected rows :%lu", iteration_count, affected_rows);
|
||||
ASSERT_EQ(affected_rows, 1, "mysql_stmt_affected_rows");
|
||||
}
|
||||
|
||||
if (ret = mysql_stmt_close(stmt)) {
|
||||
my_log("mysql_stmt_close faield:%s", mysql_stmt_error(stmt));
|
||||
return -1;
|
||||
} else {
|
||||
ASSERT_EQ(ret, 0, "mysql_stmt_close");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
int main(int argc, char** argv) {
|
||||
mysql_library_init(0, NULL, NULL);
|
||||
MYSQL *mysql = mysql_init(NULL);
|
||||
unsigned int timeout = 3000;
|
||||
init_conn_info(OB_ORACLE_MODE);
|
||||
|
||||
mysql_options(mysql, MYSQL_OPT_CONNECT_TIMEOUT, &timeout);
|
||||
if (mysql_real_connect(mysql, DBHOST, DBUSER, DBPASS, DBNAME, DBPORT, DBSOCK, DBPCNT) == NULL)
|
||||
{
|
||||
my_log("connect failed: %s\n", mysql_error(mysql));
|
||||
mysql_close(mysql);
|
||||
mysql_library_end();
|
||||
return 0;
|
||||
} else {
|
||||
my_log("connect to %s:%d using %s success", DBHOST, DBPORT, DBUSER);
|
||||
}
|
||||
int ret = mysql_query(mysql, "SET NAMES utf8");
|
||||
if (ret != 0)
|
||||
{
|
||||
printf("set names error, %s\n", mysql_error(mysql));
|
||||
return ret;
|
||||
}
|
||||
mysql_query(mysql, "drop table test_new_ps");
|
||||
ret = mysql_query(mysql, "create table test_new_ps(id int, name varchar2(10))");
|
||||
if (ret != 0)
|
||||
{
|
||||
my_log("create table error, %s\n", mysql_error(mysql));
|
||||
return ret;
|
||||
}
|
||||
stmt_insert_long_data_test(mysql);
|
||||
stmt_insert_data_test(mysql);
|
||||
return 0;
|
||||
}
|
||||
101
unittest/my_test/ob_new_ps_select_notable.c
Normal file
101
unittest/my_test/ob_new_ps_select_notable.c
Normal file
@ -0,0 +1,101 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "mysql.h"
|
||||
#include "test_util.h"
|
||||
|
||||
|
||||
int stmt_select_test_not_exist_table(MYSQL* mysql) {
|
||||
my_log("stmt_select_test_not_exist_table");
|
||||
const char* pStatement = "select * from test_new_ps";
|
||||
MYSQL_STMT *stmt;
|
||||
MYSQL_BIND bind[4];
|
||||
int ret = 0;
|
||||
int param_count;
|
||||
int filed_count;
|
||||
my_ulonglong affected_rows;
|
||||
stmt = mysql_stmt_init(mysql);
|
||||
if (!stmt) {
|
||||
my_log("msyql_stmt_init failed: %s", mysql_error(mysql));
|
||||
ASSERT_EQ(-1, 0, "mysql_stmt_init");
|
||||
return -1;
|
||||
}
|
||||
if (ret = mysql_stmt_prepare_v2(stmt, pStatement, strlen(pStatement), 0)) {
|
||||
my_log("mysql_stmt_prepare_v2 failed:%s", mysql_error(mysql));
|
||||
ASSERT_EQ(ret, 0, "mysql_stmt_prepare_v2");
|
||||
}
|
||||
filed_count = mysql_stmt_field_count(stmt);
|
||||
my_log("filed_count is %u", filed_count);
|
||||
param_count = mysql_stmt_param_count(stmt);
|
||||
my_log("param_count is %d", param_count);
|
||||
unsigned int iteration_count = 1;
|
||||
// mysql_stmt_attr_set(stmt, STMT_ATTR_ITERRATION_COUNT, &iteration_count);
|
||||
//stmt->iteration_count = 0;
|
||||
if (ret = mysql_stmt_execute_v2(stmt, pStatement, strlen(pStatement), iteration_count, 0, 0)) {
|
||||
my_log("mysql_stmt_execute_v2 select failed:%s", mysql_stmt_error(stmt));
|
||||
ASSERT_EQ(1, ret, "mysql_stmt_execute_v2");
|
||||
} else {
|
||||
ASSERT_EQ(1, ret, "mysql_stmt_execute_v2");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
int stmt_select_test_no_table(MYSQL* mysql) {
|
||||
my_log("stmt_select_test_no_table");
|
||||
const char* pStatement = "select c1,c2,c3,c4";
|
||||
MYSQL_STMT *stmt;
|
||||
MYSQL_BIND bind[4];
|
||||
int ret = 0;
|
||||
int param_count;
|
||||
int filed_count;
|
||||
my_ulonglong affected_rows;
|
||||
stmt = mysql_stmt_init(mysql);
|
||||
if (!stmt) {
|
||||
my_log("msyql_stmt_init failed: %s", mysql_error(mysql));
|
||||
ASSERT_EQ(-1, 0, "mysql_stmt_init");
|
||||
return -1;
|
||||
}
|
||||
if (ret = mysql_stmt_prepare_v2(stmt, pStatement, strlen(pStatement), 0)) {
|
||||
my_log("mysql_stmt_prepare_v2 failed:%s", mysql_error(mysql));
|
||||
ASSERT_EQ(ret, 0, "mysql_stmt_prepare_v2");
|
||||
}
|
||||
filed_count = mysql_stmt_field_count(stmt);
|
||||
my_log("filed_count is %u", filed_count);
|
||||
param_count = mysql_stmt_param_count(stmt);
|
||||
my_log("param_count is %d", param_count);
|
||||
unsigned int iteration_count = 1;
|
||||
// mysql_stmt_attr_set(stmt, STMT_ATTR_ITERRATION_COUNT, &iteration_count);
|
||||
//stmt->iteration_count = 0;
|
||||
if (ret = mysql_stmt_execute_v2(stmt, pStatement, strlen(pStatement), iteration_count, 0, 0)) {
|
||||
my_log("mysql_stmt_execute_v2 select failed:%s", mysql_stmt_error(stmt));
|
||||
ASSERT_EQ(1, ret, "mysql_stmt_execute_v2");
|
||||
} else {
|
||||
ASSERT_EQ(1, ret, "mysql_stmt_init");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
int main(int argc, char** argv) {
|
||||
mysql_library_init(0, NULL, NULL);
|
||||
MYSQL *mysql = mysql_init(NULL);
|
||||
unsigned int timeout = 3000;
|
||||
init_conn_info(OB_ORACLE_MODE);
|
||||
mysql_options(mysql, MYSQL_OPT_CONNECT_TIMEOUT, &timeout);
|
||||
|
||||
if (mysql_real_connect(mysql, DBHOST, DBUSER, DBPASS, DBNAME, DBPORT, DBSOCK, DBPCNT) == NULL)
|
||||
{
|
||||
my_log("connect failed: %s\n", mysql_error(mysql));
|
||||
mysql_close(mysql);
|
||||
mysql_library_end();
|
||||
return 0;
|
||||
} else {
|
||||
my_log("connect to %s:%d using %s success", DBHOST, DBPORT, DBUSER);
|
||||
}
|
||||
int ret = mysql_query(mysql, "SET NAMES utf8");
|
||||
if (ret != 0)
|
||||
{
|
||||
printf("set names failed, %s\n", mysql_error(mysql));
|
||||
return ret;
|
||||
}
|
||||
mysql_query(mysql, "drop table test_new_ps");
|
||||
stmt_select_test_not_exist_table(mysql);
|
||||
stmt_select_test_no_table(mysql);
|
||||
return 0;
|
||||
}
|
||||
605
unittest/my_test/ob_new_ps_select_test.c
Normal file
605
unittest/my_test/ob_new_ps_select_test.c
Normal file
@ -0,0 +1,605 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "mysql.h"
|
||||
#include "test_util.h"
|
||||
|
||||
int stmt_select_test_no_param_no_result(MYSQL* mysql) {
|
||||
my_log("stmt_select_test_no_param_no_result");
|
||||
const char* pStatement = "select * from test_new_ps";
|
||||
MYSQL_STMT *stmt;
|
||||
MYSQL_BIND bind[4];
|
||||
int ret = 0;
|
||||
int param_count;
|
||||
int filed_count;
|
||||
my_ulonglong affected_rows;
|
||||
const char* query = "delete from test_new_ps";
|
||||
if (ret = mysql_real_query(mysql, query, strlen(query))) {
|
||||
my_log("mysql_real_query failed:%s", mysql_error(mysql));
|
||||
ASSERT_EQ(ret, 0, "mysql_real_query");
|
||||
}
|
||||
stmt = mysql_stmt_init(mysql);
|
||||
if (!stmt) {
|
||||
my_log("msyql_stmt_init failed: %s", mysql_error(mysql));
|
||||
ASSERT_EQ(-1, 0, "mysql_stmt_init");
|
||||
return -1;
|
||||
}
|
||||
if (ret = mysql_stmt_prepare_v2(stmt, pStatement, strlen(pStatement), 0)) {
|
||||
my_log("mysql_stmt_prepare_v2 failed:%s", mysql_error(mysql));
|
||||
ASSERT_EQ(ret, 0, "mysql_stmt_prepare_v2");
|
||||
}
|
||||
filed_count = mysql_stmt_field_count(stmt);
|
||||
my_log("filed_count is %u", filed_count);
|
||||
param_count = mysql_stmt_param_count(stmt);
|
||||
my_log("param_count is %d", param_count);
|
||||
unsigned int iteration_count = 1;
|
||||
// mysql_stmt_attr_set(stmt, STMT_ATTR_ITERRATION_COUNT, &iteration_count);
|
||||
//stmt->iteration_count = 0;
|
||||
if (mysql_stmt_execute_v2(stmt, pStatement, strlen(pStatement), iteration_count, 0, 0)) {
|
||||
my_log("mysql_stmt_execute_v2 select failed:%s", mysql_stmt_error(stmt));
|
||||
return -1;
|
||||
}
|
||||
// if (mysql_stmt_store_result(stmt)) {
|
||||
// my_log("mysql_stmt_store_result failed :%s", mysql_stmt_error(stmt));
|
||||
// return -1;
|
||||
// }
|
||||
filed_count = mysql_stmt_field_count(stmt);
|
||||
my_log("filed_count is %u", filed_count);
|
||||
my_ulonglong row_count = mysql_stmt_num_rows(stmt);
|
||||
my_log("row count is %u", row_count);
|
||||
memset(bind, 0, sizeof(bind));
|
||||
int id, num;
|
||||
char name[20];
|
||||
char birthday[20];
|
||||
bind[0].buffer_type = MYSQL_TYPE_LONG;
|
||||
bind[0].buffer = &id;
|
||||
bind[1].buffer_type = MYSQL_TYPE_LONG;
|
||||
bind[1].buffer = #
|
||||
bind[2].buffer_type = MYSQL_TYPE_STRING;
|
||||
bind[2].buffer = name;
|
||||
bind[2].buffer_length = sizeof(name);
|
||||
bind[3].buffer_type = MYSQL_TYPE_STRING;
|
||||
bind[3].buffer = birthday;
|
||||
bind[3].buffer_length = sizeof(birthday);
|
||||
|
||||
if (ret = mysql_stmt_bind_result(stmt, bind)) {
|
||||
my_log("mysql_stmt_bind_result failed:%s", mysql_stmt_error(stmt));
|
||||
ASSERT_EQ(ret, 0, "mysql_stmt_bind_result");
|
||||
}
|
||||
while (mysql_stmt_fetch(stmt) == 0) {
|
||||
printf("%d\t%d\t%s\t%s\n", id, num, name, birthday);
|
||||
}
|
||||
if (ret = mysql_stmt_close(stmt)) {
|
||||
my_log("mysql_stmt_close faled:%s", mysql_stmt_error(stmt));
|
||||
}
|
||||
ASSERT_EQ(0, 0, "stmt_select_test_no_param_no_result");
|
||||
return 0;
|
||||
}
|
||||
int stmt_select_test_with_param_no_result(MYSQL* mysql) {
|
||||
my_log("stmt_select_test_with_param_no_result");
|
||||
const char* pStatement = "select * from test_new_ps where id = ? and num = ? and name = ?";
|
||||
MYSQL_STMT *stmt;
|
||||
MYSQL_BIND bind[4];
|
||||
MYSQL_BIND param[4];
|
||||
int ret = 0;
|
||||
int param_count;
|
||||
int filed_count;
|
||||
my_ulonglong affected_rows;
|
||||
const char* query = "delete from test_new_ps";
|
||||
if (ret = mysql_real_query(mysql, query, strlen(query))) {
|
||||
my_log("mysql_real_query failed:%s", mysql_error(mysql));
|
||||
ASSERT_EQ(ret, 0, "mysql_real_query");
|
||||
}
|
||||
stmt = mysql_stmt_init(mysql);
|
||||
if (!stmt) {
|
||||
my_log("msyql_stmt_init failed: %s", mysql_error(mysql));
|
||||
ASSERT_EQ(-1, 0, "mysql_stmt_init");
|
||||
return -1;
|
||||
}
|
||||
if (ret = mysql_stmt_prepare_v2(stmt, pStatement, strlen(pStatement), 0)) {
|
||||
my_log("mysql_stmt_prepare_v2 failed:%s", mysql_error(mysql));
|
||||
ASSERT_EQ(ret, 0, "mysql_stmt_prepare_v2");
|
||||
}
|
||||
filed_count = mysql_stmt_field_count(stmt);
|
||||
my_log("filed_count is %u", filed_count);
|
||||
param_count = mysql_stmt_param_count(stmt);
|
||||
my_log("param_count is %d", param_count);
|
||||
int input_id = 0, input_num = 0;
|
||||
char input_name[20] = "test";
|
||||
unsigned long str_len;
|
||||
{
|
||||
//id
|
||||
param[0].buffer_type = MYSQL_TYPE_LONG;
|
||||
param[0].buffer = (char*)&input_id;
|
||||
param[0].buffer_length = 0;
|
||||
param[0].is_null = 0;
|
||||
param[0].length = 0;
|
||||
// bind[0].is_unsigned = 0;
|
||||
}
|
||||
{
|
||||
//num
|
||||
param[1].buffer_type = MYSQL_TYPE_LONG;
|
||||
param[1].buffer = (char*)&input_num;
|
||||
param[1].buffer_length = 0;
|
||||
param[1].is_null = 0;
|
||||
param[1].length = 0;
|
||||
// bind[1].is_unsigned = 0;
|
||||
}
|
||||
{
|
||||
//name
|
||||
str_len = strlen(input_name);
|
||||
my_log("str_len for name is %d", str_len);
|
||||
param[2].buffer_type = MYSQL_TYPE_STRING;
|
||||
param[2].buffer = (char*)input_name;
|
||||
param[2].buffer_length = str_len;
|
||||
param[2].is_null = 0;
|
||||
param[2].length = &str_len;
|
||||
// bind[2].is_unsigned = 0;
|
||||
}
|
||||
if (mysql_stmt_bind_param(stmt, param)) {
|
||||
my_log("bind failed:%s", mysql_stmt_error(stmt));
|
||||
return -1;
|
||||
}
|
||||
unsigned int iteration_count = 0;
|
||||
// mysql_stmt_attr_set(stmt, STMT_ATTR_ITERRATION_COUNT, &iteration_count);
|
||||
//stmt->iteration_count = 0;
|
||||
if (ret = mysql_stmt_execute_v2(stmt, pStatement, strlen(pStatement), iteration_count, 0, 0)) {
|
||||
my_log("mysql_stmt_execute_v2 select failed:%s", mysql_stmt_error(stmt));
|
||||
ASSERT_EQ(ret, 0, "mysql_stmt_execute_v2");
|
||||
return -1;
|
||||
}
|
||||
// if (mysql_stmt_store_result(stmt)) {
|
||||
// my_log("mysql_stmt_store_result failed :%s", mysql_stmt_error(stmt));
|
||||
// return -1;
|
||||
// }
|
||||
filed_count = mysql_stmt_field_count(stmt);
|
||||
my_log("filed_count is %u", filed_count);
|
||||
my_ulonglong row_count = mysql_stmt_num_rows(stmt);
|
||||
my_log("row count is %u", row_count);
|
||||
memset(bind, 0, sizeof(bind));
|
||||
|
||||
int id, num;
|
||||
char name[20];
|
||||
char birthday[20];
|
||||
bind[0].buffer_type = MYSQL_TYPE_LONG;
|
||||
bind[0].buffer = &id;
|
||||
bind[1].buffer_type = MYSQL_TYPE_LONG;
|
||||
bind[1].buffer = #
|
||||
bind[2].buffer_type = MYSQL_TYPE_STRING;
|
||||
bind[2].buffer = name;
|
||||
bind[2].buffer_length = sizeof(name);
|
||||
bind[3].buffer_type = MYSQL_TYPE_STRING;
|
||||
bind[3].buffer = birthday;
|
||||
bind[3].buffer_length = sizeof(birthday);
|
||||
|
||||
if (ret = mysql_stmt_bind_result(stmt, bind)) {
|
||||
my_log("mysql_stmt_bind_result failed:%s", mysql_stmt_error(stmt));
|
||||
ASSERT_EQ(ret, 0, "mysql_stmt_bind_result");
|
||||
}
|
||||
while (mysql_stmt_fetch(stmt) == 0) {
|
||||
my_log("%d\t%d\t%s\t%s", id, num, name, birthday);
|
||||
}
|
||||
if (ret = mysql_stmt_close(stmt)) {
|
||||
my_log("mysql_stmt_close faled:%s", mysql_stmt_error(stmt));
|
||||
}
|
||||
ASSERT_EQ(0, 0, "stmt_select_test_with_param_no_result");
|
||||
return 0;
|
||||
}
|
||||
int stmt_select_test_no_param_with_result(MYSQL* mysql) {
|
||||
my_log("stmt_select_test");
|
||||
const char* pStatement = "select * from test_new_ps";
|
||||
MYSQL_STMT *stmt;
|
||||
MYSQL_BIND bind[4];
|
||||
int ret = 0;
|
||||
int param_count;
|
||||
int filed_count;
|
||||
my_ulonglong affected_rows;
|
||||
int i = 0;
|
||||
char query[1000] = {0};
|
||||
snprintf(query, 1000, "delete from test_new_ps");
|
||||
if (ret = mysql_real_query(mysql, query, strlen(query))) {
|
||||
my_log("mysql_real_query failed:%s", mysql_error(mysql));
|
||||
ASSERT_EQ(ret, 0, "mysql_real_query");
|
||||
}
|
||||
for (i = 0; i < 10; i++)
|
||||
{
|
||||
snprintf(query, 1000, "insert into test_new_ps(id, num, name, birthday) values(%d,%d, 'name_%d', 'birth_%d')", i ,i, i, i);
|
||||
if (ret = mysql_real_query(mysql, query, strlen(query))) {
|
||||
my_log("mysql_real_query failed:%s", mysql_error(mysql));
|
||||
ASSERT_EQ(ret, 0, "mysql_real_query");
|
||||
}
|
||||
}
|
||||
stmt = mysql_stmt_init(mysql);
|
||||
if (!stmt) {
|
||||
my_log("msyql_stmt_init failed: %s", mysql_error(mysql));
|
||||
ASSERT_EQ(-1, 0, "mysql_stmt_init");
|
||||
return -1;
|
||||
}
|
||||
if (ret = mysql_stmt_prepare_v2(stmt, pStatement, strlen(pStatement), 0)) {
|
||||
my_log("mysql_stmt_prepare_v2 failed:%s", mysql_error(mysql));
|
||||
ASSERT_EQ(ret, 0, "mysql_stmt_prepare_v2");
|
||||
}
|
||||
filed_count = mysql_stmt_field_count(stmt);
|
||||
my_log("filed_count is %u", filed_count);
|
||||
param_count = mysql_stmt_param_count(stmt);
|
||||
my_log("param_count is %d", param_count);
|
||||
unsigned int iteration_count = 1;
|
||||
// mysql_stmt_attr_set(stmt, STMT_ATTR_ITERRATION_COUNT, &iteration_count);
|
||||
//stmt->iteration_count = 0;
|
||||
if (mysql_stmt_execute_v2(stmt, pStatement, strlen(pStatement), iteration_count, 0, 0)) {
|
||||
my_log("mysql_stmt_execute_v2 select failed:%s", mysql_stmt_error(stmt));
|
||||
return -1;
|
||||
}
|
||||
// if (mysql_stmt_store_result(stmt)) {
|
||||
// my_log("mysql_stmt_store_result failed :%s", mysql_stmt_error(stmt));
|
||||
// return -1;
|
||||
// }
|
||||
filed_count = mysql_stmt_field_count(stmt);
|
||||
my_log("filed_count is %u", filed_count);
|
||||
my_ulonglong row_count = mysql_stmt_num_rows(stmt);
|
||||
my_log("row count is %u", row_count);
|
||||
memset(bind, 0, sizeof(bind));
|
||||
int id, num;
|
||||
char name[20];
|
||||
char birthday[20];
|
||||
bind[0].buffer_type = MYSQL_TYPE_LONG;
|
||||
bind[0].buffer = &id;
|
||||
bind[1].buffer_type = MYSQL_TYPE_LONG;
|
||||
bind[1].buffer = #
|
||||
bind[2].buffer_type = MYSQL_TYPE_STRING;
|
||||
bind[2].buffer = name;
|
||||
bind[2].buffer_length = sizeof(name);
|
||||
bind[3].buffer_type = MYSQL_TYPE_STRING;
|
||||
bind[3].buffer = birthday;
|
||||
bind[3].buffer_length = sizeof(birthday);
|
||||
|
||||
if (ret = mysql_stmt_bind_result(stmt, bind)) {
|
||||
my_log("mysql_stmt_bind_result failed:%s", mysql_stmt_error(stmt));
|
||||
ASSERT_EQ(ret, 0, "mysql_stmt_bind_result");
|
||||
}
|
||||
i = 0;
|
||||
while (mysql_stmt_fetch(stmt) == 0) {
|
||||
i++;
|
||||
printf("%d\t%d\t%s\t%s\n", id, num, name, birthday);
|
||||
}
|
||||
ASSERT_EQ(10, i, "mysql_stmt_fetch");
|
||||
if (ret = mysql_stmt_close(stmt)) {
|
||||
my_log("mysql_stmt_close faled:%s", mysql_stmt_error(stmt));
|
||||
}
|
||||
ASSERT_EQ(0, 0, "stmt_select_test_no_param_with_result");
|
||||
return 0;
|
||||
}
|
||||
int stmt_select_test_with_param_with_result(MYSQL* mysql) {
|
||||
my_log("stmt_select_test_with_param_with_result");
|
||||
const char* pStatement = "select * from test_new_ps where id = ? and num = ? and name = ?";
|
||||
MYSQL_STMT *stmt;
|
||||
MYSQL_BIND bind[4];
|
||||
MYSQL_BIND param[4];
|
||||
int ret = 0;
|
||||
int param_count;
|
||||
int filed_count;
|
||||
int i = 0;
|
||||
my_ulonglong affected_rows;
|
||||
char query [400];
|
||||
snprintf(query, 400, "delete from test_new_ps");
|
||||
if (ret = mysql_real_query(mysql, query, strlen(query))) {
|
||||
my_log("mysql_real_query failed:%s", mysql_error(mysql));
|
||||
ASSERT_EQ(ret, 0, "mysql_real_query");
|
||||
}
|
||||
for (i = 0; i < 10; i++)
|
||||
{
|
||||
snprintf(query, 1000, "insert into test_new_ps(id, num, name, birthday) values(%d,%d, 'name_%d', 'birth_%d')", i ,i, i, i);
|
||||
if (ret = mysql_real_query(mysql, query, strlen(query))) {
|
||||
my_log("mysql_real_query failed:%s", mysql_error(mysql));
|
||||
ASSERT_EQ(ret, 0, "mysql_real_query");
|
||||
}
|
||||
}
|
||||
stmt = mysql_stmt_init(mysql);
|
||||
if (!stmt) {
|
||||
my_log("msyql_stmt_init failed: %s", mysql_error(mysql));
|
||||
ASSERT_EQ(-1, 0, "mysql_stmt_init");
|
||||
return -1;
|
||||
}
|
||||
if (ret = mysql_stmt_prepare_v2(stmt, pStatement, strlen(pStatement), 0)) {
|
||||
my_log("mysql_stmt_prepare_v2 failed:%s", mysql_error(mysql));
|
||||
ASSERT_EQ(ret, 0, "mysql_stmt_prepare_v2");
|
||||
}
|
||||
filed_count = mysql_stmt_field_count(stmt);
|
||||
my_log("filed_count is %u", filed_count);
|
||||
param_count = mysql_stmt_param_count(stmt);
|
||||
my_log("param_count is %d", param_count);
|
||||
int input_id = 0, input_num = 0;
|
||||
char input_name[20] = "name_0";
|
||||
unsigned long str_len;
|
||||
{
|
||||
//id
|
||||
param[0].buffer_type = MYSQL_TYPE_LONG;
|
||||
param[0].buffer = (char*)&input_id;
|
||||
param[0].buffer_length = 0;
|
||||
param[0].is_null = 0;
|
||||
param[0].length = 0;
|
||||
// bind[0].is_unsigned = 0;
|
||||
}
|
||||
{
|
||||
//num
|
||||
param[1].buffer_type = MYSQL_TYPE_LONG;
|
||||
param[1].buffer = (char*)&input_num;
|
||||
param[1].buffer_length = 0;
|
||||
param[1].is_null = 0;
|
||||
param[1].length = 0;
|
||||
// bind[1].is_unsigned = 0;
|
||||
}
|
||||
{
|
||||
//name
|
||||
str_len = strlen(input_name);
|
||||
my_log("str_len for name is %d", str_len);
|
||||
param[2].buffer_type = MYSQL_TYPE_STRING;
|
||||
param[2].buffer = (char*)input_name;
|
||||
param[2].buffer_length = str_len;
|
||||
param[2].is_null = 0;
|
||||
param[2].length = &str_len;
|
||||
// bind[2].is_unsigned = 0;
|
||||
}
|
||||
if (mysql_stmt_bind_param(stmt, param)) {
|
||||
my_log("bind failed:%s", mysql_stmt_error(stmt));
|
||||
return -1;
|
||||
}
|
||||
unsigned int iteration_count = 0;
|
||||
// mysql_stmt_attr_set(stmt, STMT_ATTR_ITERRATION_COUNT, &iteration_count);
|
||||
//stmt->iteration_count = 0;
|
||||
if (ret = mysql_stmt_execute_v2(stmt, pStatement, strlen(pStatement), iteration_count, 0, 0)) {
|
||||
my_log("mysql_stmt_execute_v2 select failed:%s", mysql_stmt_error(stmt));
|
||||
ASSERT_EQ(ret, 0, "mysql_stmt_execute_v2");
|
||||
return -1;
|
||||
}
|
||||
// if (mysql_stmt_store_result(stmt)) {
|
||||
// my_log("mysql_stmt_store_result failed :%s", mysql_stmt_error(stmt));
|
||||
// return -1;
|
||||
// }
|
||||
filed_count = mysql_stmt_field_count(stmt);
|
||||
my_log("filed_count is %u", filed_count);
|
||||
my_ulonglong row_count = mysql_stmt_num_rows(stmt);
|
||||
my_log("row count is %u", row_count);
|
||||
memset(bind, 0, sizeof(bind));
|
||||
|
||||
int id, num;
|
||||
char name[20];
|
||||
char birthday[20];
|
||||
bind[0].buffer_type = MYSQL_TYPE_LONG;
|
||||
bind[0].buffer = &id;
|
||||
bind[1].buffer_type = MYSQL_TYPE_LONG;
|
||||
bind[1].buffer = #
|
||||
bind[2].buffer_type = MYSQL_TYPE_STRING;
|
||||
bind[2].buffer = name;
|
||||
bind[2].buffer_length = sizeof(name);
|
||||
bind[3].buffer_type = MYSQL_TYPE_STRING;
|
||||
bind[3].buffer = birthday;
|
||||
bind[3].buffer_length = sizeof(birthday);
|
||||
|
||||
if (ret = mysql_stmt_bind_result(stmt, bind)) {
|
||||
my_log("mysql_stmt_bind_result failed:%s", mysql_stmt_error(stmt));
|
||||
ASSERT_EQ(ret, 0, "mysql_stmt_bind_result");
|
||||
}
|
||||
while (mysql_stmt_fetch(stmt) == 0) {
|
||||
my_log("%d\t%d\t%s\t%s", id, num, name, birthday);
|
||||
}
|
||||
if (ret = mysql_stmt_close(stmt)) {
|
||||
my_log("mysql_stmt_close faled:%s", mysql_stmt_error(stmt));
|
||||
}
|
||||
ASSERT_EQ(0, 0, "stmt_select_test_with_param_with_result");
|
||||
return 0;
|
||||
}
|
||||
int stmt_select_test_no_param_no_result_exact_not_match(MYSQL* mysql) {
|
||||
my_log("stmt_select_test_no_param_no_result");
|
||||
const char* pStatement = "select * from test_new_ps";
|
||||
MYSQL_STMT *stmt;
|
||||
MYSQL_BIND bind[4];
|
||||
int ret = 0;
|
||||
int param_count;
|
||||
int filed_count;
|
||||
my_ulonglong affected_rows;
|
||||
const char* query = "delete from test_new_ps";
|
||||
if (ret = mysql_real_query(mysql, query, strlen(query))) {
|
||||
my_log("mysql_real_query failed:%s", mysql_error(mysql));
|
||||
ASSERT_EQ(ret, 0, "mysql_real_query");
|
||||
}
|
||||
stmt = mysql_stmt_init(mysql);
|
||||
if (!stmt) {
|
||||
my_log("msyql_stmt_init failed: %s", mysql_error(mysql));
|
||||
ASSERT_EQ(-1, 0, "mysql_stmt_init");
|
||||
return -1;
|
||||
}
|
||||
if (ret = mysql_stmt_prepare_v2(stmt, pStatement, strlen(pStatement), 0)) {
|
||||
my_log("mysql_stmt_prepare_v2 failed:%s", mysql_error(mysql));
|
||||
ASSERT_EQ(ret, 0, "mysql_stmt_prepare_v2");
|
||||
}
|
||||
filed_count = mysql_stmt_field_count(stmt);
|
||||
my_log("filed_count is %u", filed_count);
|
||||
param_count = mysql_stmt_param_count(stmt);
|
||||
my_log("param_count is %d", param_count);
|
||||
unsigned int iteration_count = 2;
|
||||
// mysql_stmt_attr_set(stmt, STMT_ATTR_ITERRATION_COUNT, &iteration_count);
|
||||
//stmt->iteration_count = 0;
|
||||
if (ret = mysql_stmt_execute_v2(stmt, pStatement, strlen(pStatement), iteration_count, 0x00000002, 0)) {
|
||||
my_log("mysql_stmt_execute_v2 select failed:%s", mysql_stmt_error(stmt));
|
||||
ASSERT_EQ(1, ret, "mysql_stmt_execute_v2");
|
||||
return -1;
|
||||
} else {
|
||||
ASSERT_EQ(-1, ret, "mysql_stmt_execute_v2");
|
||||
return -1;
|
||||
}
|
||||
// if (mysql_stmt_store_result(stmt)) {
|
||||
// my_log("mysql_stmt_store_result failed :%s", mysql_stmt_error(stmt));
|
||||
// return -1;
|
||||
// }
|
||||
filed_count = mysql_stmt_field_count(stmt);
|
||||
my_log("filed_count is %u", filed_count);
|
||||
my_ulonglong row_count = mysql_stmt_num_rows(stmt);
|
||||
my_log("row count is %u", row_count);
|
||||
memset(bind, 0, sizeof(bind));
|
||||
int id, num;
|
||||
char name[20];
|
||||
char birthday[20];
|
||||
bind[0].buffer_type = MYSQL_TYPE_LONG;
|
||||
bind[0].buffer = &id;
|
||||
bind[1].buffer_type = MYSQL_TYPE_LONG;
|
||||
bind[1].buffer = #
|
||||
bind[2].buffer_type = MYSQL_TYPE_STRING;
|
||||
bind[2].buffer = name;
|
||||
bind[2].buffer_length = sizeof(name);
|
||||
bind[3].buffer_type = MYSQL_TYPE_STRING;
|
||||
bind[3].buffer = birthday;
|
||||
bind[3].buffer_length = sizeof(birthday);
|
||||
|
||||
if (ret = mysql_stmt_bind_result(stmt, bind)) {
|
||||
my_log("mysql_stmt_bind_result failed:%s", mysql_stmt_error(stmt));
|
||||
ASSERT_EQ(ret, 0, "mysql_stmt_bind_result");
|
||||
}
|
||||
while (mysql_stmt_fetch(stmt) == 0) {
|
||||
printf("%d\t%d\t%s\t%s\n", id, num, name, birthday);
|
||||
}
|
||||
if (ret = mysql_stmt_close(stmt)) {
|
||||
my_log("mysql_stmt_close faled:%s", mysql_stmt_error(stmt));
|
||||
}
|
||||
ASSERT_EQ(-1, 0, "stmt_select_test_no_param_no_result");
|
||||
return 0;
|
||||
}
|
||||
int stmt_select_test_no_param_with_result_exact_not_match(MYSQL* mysql) {
|
||||
my_log("stmt_select_test_no_param_with_result_exact_not_match");
|
||||
const char* pStatement = "select * from test_new_ps";
|
||||
MYSQL_STMT *stmt;
|
||||
MYSQL_BIND bind[4];
|
||||
int ret = 0;
|
||||
int param_count = 0;
|
||||
int filed_count = 0;
|
||||
my_ulonglong affected_rows;
|
||||
int i = 0;
|
||||
char query[1000] = {0};
|
||||
snprintf(query, 1000, "delete from test_new_ps");
|
||||
if (ret = mysql_real_query(mysql, query, strlen(query))) {
|
||||
my_log("mysql_real_query failed:%s", mysql_error(mysql));
|
||||
ASSERT_EQ(ret, 0, "mysql_real_query");
|
||||
}
|
||||
for (i = 0; i < 10; i++)
|
||||
{
|
||||
snprintf(query, 1000, "insert into test_new_ps(id, num, name, birthday) values(%d,%d, 'name_%d', 'birth_%d')", i ,i, i, i);
|
||||
if (ret = mysql_real_query(mysql, query, strlen(query))) {
|
||||
my_log("mysql_real_query failed:%s", mysql_error(mysql));
|
||||
ASSERT_EQ(ret, 0, "mysql_real_query");
|
||||
}
|
||||
}
|
||||
stmt = mysql_stmt_init(mysql);
|
||||
if (!stmt) {
|
||||
my_log("msyql_stmt_init failed: %s", mysql_error(mysql));
|
||||
ASSERT_EQ(-1, 0, "mysql_stmt_init");
|
||||
return -1;
|
||||
}
|
||||
if (ret = mysql_stmt_prepare_v2(stmt, pStatement, strlen(pStatement), 0)) {
|
||||
my_log("mysql_stmt_prepare_v2 failed:%s", mysql_error(mysql));
|
||||
ASSERT_EQ(ret, 0, "mysql_stmt_prepare_v2");
|
||||
}
|
||||
filed_count = mysql_stmt_field_count(stmt);
|
||||
my_log("filed_count is %u", filed_count);
|
||||
param_count = mysql_stmt_param_count(stmt);
|
||||
my_log("param_count is %d", param_count);
|
||||
unsigned int iteration_count = 2;
|
||||
// mysql_stmt_attr_set(stmt, STMT_ATTR_ITERRATION_COUNT, &iteration_count);
|
||||
//stmt->iteration_count = 0;
|
||||
if (ret = mysql_stmt_execute_v2(stmt, pStatement, strlen(pStatement), iteration_count, 0x00000002, 0)) {
|
||||
my_log("mysql_stmt_execute_v2 select failed:%s", mysql_stmt_error(stmt));
|
||||
ASSERT_EQ(1, ret, "mysql_stmt_execute_v2 with 2");
|
||||
} else {
|
||||
ASSERT_EQ(1, ret, "mysql_stmt_execute_v2 with 2");
|
||||
}
|
||||
filed_count = mysql_stmt_field_count(stmt);
|
||||
my_log("filed_count is %u", filed_count);
|
||||
param_count = mysql_stmt_param_count(stmt);
|
||||
my_log("param_count is %d", param_count);
|
||||
ASSERT_EQ(filed_count, 4, "mysql_stmt_field_count");
|
||||
if (ret = mysql_stmt_execute_v2(stmt, pStatement, strlen(pStatement), 12, 0x00000002, 0)) {
|
||||
my_log("mysql_stmt_execute_v2 select failed:%s", mysql_stmt_error(stmt));
|
||||
ASSERT_EQ(1, ret, "mysql_stmt_execute_v2 with 12");
|
||||
} else {
|
||||
ASSERT_EQ(-1, ret, "mysql_stmt_execute_v2 with 12");
|
||||
}
|
||||
if (ret = mysql_stmt_execute_v2(stmt, pStatement, strlen(pStatement), 10, 0x00000002, 0)) {
|
||||
my_log("mysql_stmt_execute_v2 select failed:%s", mysql_stmt_error(stmt));
|
||||
ASSERT_EQ(0, ret, "mysql_stmt_execute_v2 with 10");
|
||||
} else {
|
||||
ASSERT_EQ(0, ret, "mysql_stmt_execute_v2 with 10");
|
||||
}
|
||||
// if (mysql_stmt_store_result(stmt)) {
|
||||
// my_log("mysql_stmt_store_result failed :%s", mysql_stmt_error(stmt));
|
||||
// return -1;
|
||||
// }
|
||||
filed_count = mysql_stmt_field_count(stmt);
|
||||
my_log("filed_count is %u", filed_count);
|
||||
my_ulonglong row_count = mysql_stmt_num_rows(stmt);
|
||||
my_log("row count is %u", row_count);
|
||||
memset(bind, 0, sizeof(bind));
|
||||
int id, num;
|
||||
char name[20];
|
||||
char birthday[20];
|
||||
bind[0].buffer_type = MYSQL_TYPE_LONG;
|
||||
bind[0].buffer = &id;
|
||||
bind[1].buffer_type = MYSQL_TYPE_LONG;
|
||||
bind[1].buffer = #
|
||||
bind[2].buffer_type = MYSQL_TYPE_STRING;
|
||||
bind[2].buffer = name;
|
||||
bind[2].buffer_length = sizeof(name);
|
||||
bind[3].buffer_type = MYSQL_TYPE_STRING;
|
||||
bind[3].buffer = birthday;
|
||||
bind[3].buffer_length = sizeof(birthday);
|
||||
|
||||
if (ret = mysql_stmt_bind_result(stmt, bind)) {
|
||||
my_log("mysql_stmt_bind_result failed:%s", mysql_stmt_error(stmt));
|
||||
ASSERT_EQ(ret, 0, "mysql_stmt_bind_result");
|
||||
}
|
||||
i = 0;
|
||||
while (mysql_stmt_fetch(stmt) == 0) {
|
||||
i++;
|
||||
printf("%d\t%d\t%s\t%s\n", id, num, name, birthday);
|
||||
}
|
||||
ASSERT_EQ(10, i, "mysql_stmt_fetch");
|
||||
if (ret = mysql_stmt_close(stmt)) {
|
||||
my_log("mysql_stmt_close faled:%s", mysql_stmt_error(stmt));
|
||||
}
|
||||
ASSERT_EQ(0, 0, "stmt_select_test_no_param_with_result_exact_not_match");
|
||||
return 0;
|
||||
}
|
||||
int main(int argc, char** argv) {
|
||||
mysql_library_init(0, NULL, NULL);
|
||||
MYSQL *mysql = mysql_init(NULL);
|
||||
unsigned int timeout = 3000;
|
||||
init_conn_info(OB_ORACLE_MODE);
|
||||
mysql_options(mysql, MYSQL_OPT_CONNECT_TIMEOUT, &timeout);
|
||||
|
||||
if (mysql_real_connect(mysql, DBHOST, DBUSER, DBPASS, DBNAME, DBPORT, DBSOCK, DBPCNT) == NULL)
|
||||
{
|
||||
my_log("connect failed: %s\n", mysql_error(mysql));
|
||||
mysql_close(mysql);
|
||||
mysql_library_end();
|
||||
return 0;
|
||||
} else {
|
||||
my_log("connect to %s:%d using %s success", DBHOST, DBPORT, DBUSER);
|
||||
}
|
||||
int ret = mysql_query(mysql, "SET NAMES utf8");
|
||||
if (ret != 0)
|
||||
{
|
||||
printf("set names failed, %s\n", mysql_error(mysql));
|
||||
return ret;
|
||||
}
|
||||
mysql_query(mysql, "drop table test_new_ps");
|
||||
ret = mysql_query(mysql, "create table test_new_ps(id int, num int, name varchar2(20), birthday varchar2(20))");
|
||||
if (ret != 0)
|
||||
{
|
||||
my_log("create table error, %s\n", mysql_error(mysql));
|
||||
return ret;
|
||||
}
|
||||
stmt_select_test_no_param_no_result(mysql);
|
||||
stmt_select_test_no_param_with_result(mysql);
|
||||
stmt_select_test_with_param_no_result(mysql);
|
||||
stmt_select_test_with_param_with_result(mysql);
|
||||
stmt_select_test_no_param_no_result_exact_not_match(mysql);
|
||||
stmt_select_test_no_param_with_result_exact_not_match(mysql);
|
||||
return 0;
|
||||
}
|
||||
249
unittest/my_test/ob_new_ps_test.c
Normal file
249
unittest/my_test/ob_new_ps_test.c
Normal file
@ -0,0 +1,249 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "mysql.h"
|
||||
#include "test_util.h"
|
||||
|
||||
/*
|
||||
* simple delete
|
||||
*/
|
||||
int stmt_delete_test(MYSQL* mysql) {
|
||||
my_log("stmt_delete_test");
|
||||
const char* pStatement = "delete from person";
|
||||
MYSQL_STMT *stmt;
|
||||
my_ulonglong affected_rows;
|
||||
int ret = 0;
|
||||
stmt = mysql_stmt_init(mysql);
|
||||
if (!stmt) {
|
||||
my_log("msyql_stmt_init failed: %s\n", mysql_error(mysql));
|
||||
ASSERT_EQ(-1, 0, "mysql_stmt_init");
|
||||
return -1;
|
||||
}
|
||||
if (ret = mysql_stmt_prepare_v2(stmt, pStatement, strlen(pStatement), NULL)) {
|
||||
my_log("mysql_stmt_prepare_v2 failed:%s\n", mysql_error(mysql));
|
||||
return -1;
|
||||
}
|
||||
int param_count = mysql_stmt_param_count(stmt);
|
||||
my_log("param_count is %d", param_count);
|
||||
ASSERT_EQ(param_count, 0, "mysql_stmt_param_count");
|
||||
//stmt->iteration_count = 1;
|
||||
unsigned int iteration_count = 1;
|
||||
// mysql_stmt_attr_set(stmt, STMT_ATTR_ITERRATION_COUNT, &iteration_count);
|
||||
if (ret = mysql_stmt_execute_v2(stmt, pStatement, strlen(pStatement), iteration_count, 0, 0)) {
|
||||
my_log("mysql_stmt_execute_v2 delete failed:%s", mysql_stmt_error(stmt));
|
||||
ASSERT_EQ(ret, 0, "mysql_stmt_execute_v2");
|
||||
return -1;
|
||||
} else {
|
||||
ASSERT_EQ(0, 0, "mysql_stmt_execute_v2");
|
||||
}
|
||||
affected_rows = mysql_stmt_affected_rows(stmt);
|
||||
my_log("affected rows :%lu\n", affected_rows);
|
||||
ASSERT_EQ(0, 0, "mysql_stmt_affected_rows");
|
||||
if (ret = mysql_stmt_execute_v2(stmt, pStatement, strlen(pStatement), iteration_count, 0, 0)) {
|
||||
my_log("mysql_stmt_execute_v2 delete failed:%s\n", mysql_stmt_error(stmt));
|
||||
ASSERT_EQ(ret, 0, "mysql_stmt_execute_v2");
|
||||
} else {
|
||||
ASSERT_EQ(0, 0, "mysql_stmt_execute_v2");
|
||||
}
|
||||
if (ret = mysql_stmt_close(stmt)) {
|
||||
printf("mysql_stmt_close faield:%s\n", mysql_stmt_error(stmt));
|
||||
ASSERT_EQ(ret, 0, "mysql_stmt_close");
|
||||
return -1;
|
||||
} else {
|
||||
ASSERT_EQ(ret, 0, "mysql_stmt_close");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
int stmt_insert_test(MYSQL* mysql) {
|
||||
my_log("stmt_insert_test");
|
||||
const char* pStatement = "insert into person(id,num,name,birthday) values(?,?,?,?)";
|
||||
MYSQL_STMT *stmt;
|
||||
MYSQL_BIND bind[6];
|
||||
int param_count;
|
||||
int id = 8;
|
||||
int num = 10;
|
||||
// char table[30] = "test.person";
|
||||
// char name[30] = "jh";
|
||||
// char birthday[20] = "2018-01-01";
|
||||
char* name = "test";
|
||||
char* birthday = "2021-04-06";
|
||||
my_ulonglong affected_rows;
|
||||
stmt = mysql_stmt_init(mysql);
|
||||
if (!stmt) {
|
||||
my_log("msyql_stmt_init failed: %s\n", mysql_error(mysql));
|
||||
return -1;
|
||||
}
|
||||
if (mysql_stmt_prepare_v2(stmt, pStatement, strlen(pStatement), NULL)) {
|
||||
my_log("mysql_stmt_prepare_v2 failed:%s\n", mysql_error(mysql));
|
||||
return -1;
|
||||
}
|
||||
|
||||
param_count = mysql_stmt_param_count(stmt);
|
||||
my_log("param_count is %d", param_count);
|
||||
memset(bind, 0, sizeof(bind));
|
||||
{
|
||||
//id
|
||||
bind[0].buffer_type = MYSQL_TYPE_LONG;
|
||||
bind[0].buffer = (char*)&id;
|
||||
bind[0].buffer_length = 0;
|
||||
bind[0].is_null = 0;
|
||||
bind[0].length = 0;
|
||||
// bind[0].is_unsigned = 0;
|
||||
}
|
||||
{
|
||||
//num
|
||||
bind[1].buffer_type = MYSQL_TYPE_LONG;
|
||||
bind[1].buffer = (char*)#
|
||||
bind[1].buffer_length = 0;
|
||||
bind[1].is_null = 0;
|
||||
bind[1].length = 0;
|
||||
// bind[1].is_unsigned = 0;
|
||||
}
|
||||
{
|
||||
//name
|
||||
unsigned long str_len = strlen(name);
|
||||
printf("str_len for name is %d\n", str_len);
|
||||
bind[2].buffer_type = MYSQL_TYPE_STRING;
|
||||
bind[2].buffer = (char*)name;
|
||||
bind[2].buffer_length = str_len;
|
||||
bind[2].is_null = 0;
|
||||
bind[2].length = &str_len;
|
||||
// bind[2].is_unsigned = 0;
|
||||
}
|
||||
{
|
||||
//birthday
|
||||
unsigned long str_len = strlen(birthday);
|
||||
printf("str_len for birthday is %d\n", str_len);
|
||||
bind[3].buffer_type = MYSQL_TYPE_STRING;
|
||||
bind[3].buffer = (char*)birthday;
|
||||
bind[3].buffer_length = str_len;
|
||||
bind[3].is_null = 0;
|
||||
// bind[3].length = &str_len;
|
||||
// bind[3].is_unsigned = 0;
|
||||
}
|
||||
if (mysql_stmt_bind_param(stmt, bind)) {
|
||||
printf("bind failed:%s\n", mysql_stmt_error(stmt));
|
||||
return -1;
|
||||
}
|
||||
unsigned int iteration_count = 1;
|
||||
// mysql_stmt_attr_set(stmt, STMT_ATTR_ITERRATION_COUNT, &iteration_count);
|
||||
//stmt->iteration_count = 1;
|
||||
int i = 0;
|
||||
for (i = 1; i < 10; i++) {
|
||||
id = i;
|
||||
if (mysql_stmt_execute_v2(stmt, pStatement, strlen(pStatement), 1, 0, 0)) {
|
||||
printf("mysql_stmt_execute_v2 insert failed:%s, i is %d\n", mysql_stmt_error(stmt), i);
|
||||
return -1;
|
||||
}
|
||||
affected_rows = mysql_stmt_affected_rows(stmt);
|
||||
printf("insert %d affected rows :%lu\n", i, affected_rows);
|
||||
|
||||
}
|
||||
if (mysql_commit(mysql)) {
|
||||
printf("mysql_commit faield:%s\n", mysql_stmt_error(stmt));
|
||||
}
|
||||
if (mysql_stmt_close(stmt)) {
|
||||
printf("mysql_stmt_close faield:%s\n", mysql_stmt_error(stmt));
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
int stmt_select_test(MYSQL* mysql) {
|
||||
my_log("stmt_select_test");
|
||||
const char* pStatement = "select * from person";
|
||||
MYSQL_STMT *stmt;
|
||||
MYSQL_BIND bind[4];
|
||||
int param_count;
|
||||
int filed_count;
|
||||
my_ulonglong affected_rows;
|
||||
stmt = mysql_stmt_init(mysql);
|
||||
if (!stmt) {
|
||||
printf("msyql_stmt_init failed: %s\n", mysql_error(mysql));
|
||||
return -1;
|
||||
}
|
||||
if (mysql_stmt_prepare_v2(stmt, pStatement, strlen(pStatement), 0)) {
|
||||
printf("mysql_stmt_prepare_v2 failed:%s\n", mysql_error(mysql));
|
||||
return -1;
|
||||
}
|
||||
filed_count = mysql_stmt_field_count(stmt);
|
||||
my_log("filed_count is %u", filed_count);
|
||||
param_count = mysql_stmt_param_count(stmt);
|
||||
my_log("param_count is %d", param_count);
|
||||
unsigned int iteration_count = 1;
|
||||
// mysql_stmt_attr_set(stmt, STMT_ATTR_ITERRATION_COUNT, &iteration_count);
|
||||
//stmt->iteration_count = 0;
|
||||
if (mysql_stmt_execute_v2(stmt, pStatement, strlen(pStatement), 0, 0, 0)) {
|
||||
my_log("mysql_stmt_execute_v2 select failed:%s", mysql_stmt_error(stmt));
|
||||
return -1;
|
||||
}
|
||||
// if (mysql_stmt_store_result(stmt)) {
|
||||
// my_log("mysql_stmt_store_result failed :%s", mysql_stmt_error(stmt));
|
||||
// return -1;
|
||||
// }
|
||||
filed_count = mysql_stmt_field_count(stmt);
|
||||
my_log("filed_count is %u", filed_count);
|
||||
my_ulonglong row_count = mysql_stmt_num_rows(stmt);
|
||||
my_log("row count is %u", row_count);
|
||||
memset(bind, 0, sizeof(bind));
|
||||
int id, num;
|
||||
char name[20];
|
||||
char birthday[20];
|
||||
bind[0].buffer_type = MYSQL_TYPE_LONG;
|
||||
bind[0].buffer = &id;
|
||||
bind[1].buffer_type = MYSQL_TYPE_LONG;
|
||||
bind[1].buffer = #
|
||||
bind[2].buffer_type = MYSQL_TYPE_STRING;
|
||||
bind[2].buffer = name;
|
||||
bind[2].buffer_length = sizeof(name);
|
||||
bind[3].buffer_type = MYSQL_TYPE_STRING;
|
||||
bind[3].buffer = birthday;
|
||||
bind[3].buffer_length = sizeof(birthday);
|
||||
|
||||
if (mysql_stmt_bind_result(stmt, bind)) {
|
||||
printf("mysql_stmt_bind_result failed:%s", mysql_stmt_error(stmt));
|
||||
return -1;
|
||||
}
|
||||
row_count = 0;
|
||||
while (mysql_stmt_fetch(stmt) == 0) {
|
||||
printf("%d\t%d\t%s\t%s\n", id, num, name, birthday);
|
||||
row_count++;
|
||||
}
|
||||
ASSERT_EQ(row_count, 9, "row_count");
|
||||
mysql_stmt_close(stmt);
|
||||
|
||||
return 0;
|
||||
}
|
||||
int main(int argc, char** argv) {
|
||||
mysql_library_init(0, NULL, NULL);
|
||||
MYSQL *mysql = mysql_init(NULL);
|
||||
unsigned int timeout = 3000;
|
||||
init_conn_info(OB_ORACLE_MODE);
|
||||
mysql_options(mysql, MYSQL_OPT_CONNECT_TIMEOUT, &timeout);
|
||||
|
||||
if (mysql_real_connect(mysql, DBHOST, DBUSER, DBPASS, DBNAME, DBPORT, DBSOCK, DBPCNT) == NULL)
|
||||
{
|
||||
my_log("connect failed: %s, host:%s, port:%d, user:%s, pass:%s, dbname:%s",
|
||||
mysql_error(mysql),DBHOST, DBPORT, DBUSER, DBPASS, DBNAME);
|
||||
mysql_close(mysql);
|
||||
mysql_library_end();
|
||||
return 0;
|
||||
} else {
|
||||
my_log("connect %s:%d using %s succ", DBHOST, DBPORT, DBUSER);
|
||||
}
|
||||
int ret = mysql_query(mysql, "SET NAMES utf8");
|
||||
if (ret != 0)
|
||||
{
|
||||
printf("set names error, %s\n", mysql_error(mysql));
|
||||
return ret;
|
||||
}
|
||||
mysql_query(mysql, "drop table person");
|
||||
ret = mysql_query(mysql, "create table person(id int, num int, name varchar2(20), birthday varchar2(20))");
|
||||
if (ret != 0)
|
||||
{
|
||||
my_log("create table error, %s\n", mysql_error(mysql));
|
||||
return ret;
|
||||
}
|
||||
stmt_delete_test(mysql);
|
||||
stmt_insert_test(mysql);
|
||||
stmt_select_test(mysql);
|
||||
return 0;
|
||||
}
|
||||
193
unittest/my_test/ob_oracle_array_binding_test.c
Normal file
193
unittest/my_test/ob_oracle_array_binding_test.c
Normal file
@ -0,0 +1,193 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "mysql.h"
|
||||
#include "test_util.h"
|
||||
|
||||
#define check_error(mysql, status ) \
|
||||
check_error_internal(__FILE__, __LINE__, mysql, status)
|
||||
int check_error_internal(const char* file_name, int line_no, MYSQL* mysql, int status ) {
|
||||
if (status != 0) {
|
||||
printf("[%s:%d] (error:%d, msg:%s)\n", file_name, line_no, mysql_errno(mysql), mysql_error(mysql));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#define check_stmt_error(stmt, status) \
|
||||
check_stmt_error_internal(__FILE__, __LINE__, stmt, status)
|
||||
int check_stmt_error_internal(const char* file_name, int line_no, MYSQL_STMT* stmt, int status) {
|
||||
if (status != 0) {
|
||||
printf("[%s:%d] (error:%d, msg:%s)\n", file_name, line_no, mysql_stmt_errno(stmt), mysql_stmt_error(stmt));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
int stmt_insert_array_test(MYSQL* mysql)
|
||||
{
|
||||
my_log("stmt_insert_array_test");
|
||||
int status = 0;
|
||||
MYSQL_STMT *stmt;
|
||||
stmt = mysql_stmt_init(mysql);
|
||||
if (!stmt) {
|
||||
my_log("msyql_stmt_init failed: %s\n", mysql_error(mysql));
|
||||
ASSERT_EQ(-1, 0, "mysql_stmt_init");
|
||||
return -1;
|
||||
}
|
||||
MYSQL_BIND ps_params[3];
|
||||
int int_data[3];
|
||||
my_bool is_null[3];
|
||||
printf("===========testPlArrayIn===========\n");
|
||||
/* set up stored procedure */
|
||||
check_error(mysql, mysql_query(mysql, "DROP TABLE TEST_ARRAY"));
|
||||
check_error(mysql, mysql_query(mysql, "CREATE TABLE TEST_ARRAY (c1 int)"));
|
||||
check_error(mysql, mysql_query(mysql, "set autocommit = 0"));
|
||||
const char *insert_sql = "insert into TEST_ARRAY values(?)";
|
||||
check_stmt_error(stmt, mysql_stmt_prepare(stmt, insert_sql, strlen(insert_sql)));
|
||||
/* initialize parameters: p_in, p_out, p_inout (all INT) */
|
||||
memset(ps_params, 0, sizeof (ps_params));
|
||||
|
||||
//MYSQL_COMPLEX_BIND_BASIC number_struct[3];
|
||||
MYSQL_COMPLEX_BIND_STRING number_struct[3];
|
||||
int number[3] = {2, 3, 4};
|
||||
char str[3][20];
|
||||
int i = 0;
|
||||
for (i = 0; i < 3; i++) {
|
||||
number_struct[i].buffer_type = MYSQL_TYPE_NEWDECIMAL;
|
||||
snprintf(str[i], 20, "%d", i * 10 + 3);
|
||||
number_struct[i].buffer = &str[i];
|
||||
number_struct[i].length = strlen(str[i]);
|
||||
number_struct[i].is_null = 0;
|
||||
}
|
||||
MYSQL_COMPLEX_BIND_ARRAY array_struct;
|
||||
array_struct.buffer_type = MYSQL_TYPE_ARRAY;
|
||||
// type_name null will use anonymous array
|
||||
// array_struct.type_name = "int_array";
|
||||
array_struct.type_name = NULL;
|
||||
array_struct.buffer = number_struct;
|
||||
array_struct.length = 3;
|
||||
array_struct.is_null = 0;
|
||||
|
||||
ps_params[0].buffer_type = MYSQL_TYPE_OBJECT;
|
||||
ps_params[0].buffer = (char *) &array_struct;
|
||||
ps_params[0].buffer_length = sizeof(MYSQL_COMPLEX_BIND_ARRAY);
|
||||
ps_params[0].is_null = 0;
|
||||
|
||||
/* bind parameters */
|
||||
check_stmt_error(stmt, status = mysql_stmt_bind_param(stmt, ps_params));
|
||||
|
||||
/* assign values to parameters and execute statement */
|
||||
int_data[0] = 10; /* p_in */
|
||||
int_data[1] = 20; /* p_out */
|
||||
int_data[2] = 30; /* p_inout */
|
||||
|
||||
unsigned long type;
|
||||
const int ARRAY_TYPE_BINDING = 0x08;
|
||||
const int BATCH_ERROR_MODE = 0x16;
|
||||
|
||||
type = (unsigned long) ARRAY_TYPE_BINDING;
|
||||
stmt->flags = ARRAY_TYPE_BINDING;
|
||||
// check_stmt_error(stmt, status = mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, (void*) &type));
|
||||
check_stmt_error(stmt, status = mysql_stmt_execute(stmt));
|
||||
int affected_rows = mysql_stmt_affected_rows(stmt);
|
||||
ASSERT_EQ(affected_rows, 3, "mysql_stmt_affected_rows");
|
||||
stmt->flags = 0;
|
||||
check_stmt_error(stmt, mysql_stmt_prepare(stmt, "commit", strlen("commit")));
|
||||
check_stmt_error(stmt, mysql_stmt_execute(stmt));
|
||||
return status;
|
||||
}
|
||||
int stmt_select_test(MYSQL* mysql) {
|
||||
my_log("stmt_select_test");
|
||||
const char* pStatement = "select * from person";
|
||||
MYSQL_STMT *stmt;
|
||||
MYSQL_BIND bind[4];
|
||||
int param_count;
|
||||
int filed_count;
|
||||
my_ulonglong affected_rows;
|
||||
stmt = mysql_stmt_init(mysql);
|
||||
if (!stmt) {
|
||||
printf("msyql_stmt_init failed: %s\n", mysql_error(mysql));
|
||||
return -1;
|
||||
}
|
||||
if (mysql_stmt_prepare_v2(stmt, pStatement, strlen(pStatement), 0)) {
|
||||
printf("mysql_stmt_prepare_v2 failed:%s\n", mysql_error(mysql));
|
||||
return -1;
|
||||
}
|
||||
filed_count = mysql_stmt_field_count(stmt);
|
||||
my_log("filed_count is %u", filed_count);
|
||||
param_count = mysql_stmt_param_count(stmt);
|
||||
my_log("param_count is %d", param_count);
|
||||
unsigned int iteration_count = 1;
|
||||
// mysql_stmt_attr_set(stmt, STMT_ATTR_ITERRATION_COUNT, &iteration_count);
|
||||
//stmt->iteration_count = 0;
|
||||
if (mysql_stmt_execute_v2(stmt, pStatement, strlen(pStatement), 0, 0, 0)) {
|
||||
my_log("mysql_stmt_execute_v2 select failed:%s", mysql_stmt_error(stmt));
|
||||
return -1;
|
||||
}
|
||||
// if (mysql_stmt_store_result(stmt)) {
|
||||
// my_log("mysql_stmt_store_result failed :%s", mysql_stmt_error(stmt));
|
||||
// return -1;
|
||||
// }
|
||||
filed_count = mysql_stmt_field_count(stmt);
|
||||
my_log("filed_count is %u", filed_count);
|
||||
my_ulonglong row_count = mysql_stmt_num_rows(stmt);
|
||||
my_log("row count is %u", row_count);
|
||||
memset(bind, 0, sizeof(bind));
|
||||
int id, num;
|
||||
char name[20];
|
||||
char birthday[20];
|
||||
bind[0].buffer_type = MYSQL_TYPE_LONG;
|
||||
bind[0].buffer = &id;
|
||||
bind[1].buffer_type = MYSQL_TYPE_LONG;
|
||||
bind[1].buffer = #
|
||||
bind[2].buffer_type = MYSQL_TYPE_STRING;
|
||||
bind[2].buffer = name;
|
||||
bind[2].buffer_length = sizeof(name);
|
||||
bind[3].buffer_type = MYSQL_TYPE_STRING;
|
||||
bind[3].buffer = birthday;
|
||||
bind[3].buffer_length = sizeof(birthday);
|
||||
|
||||
if (mysql_stmt_bind_result(stmt, bind)) {
|
||||
printf("mysql_stmt_bind_result failed:%s", mysql_stmt_error(stmt));
|
||||
return -1;
|
||||
}
|
||||
row_count = 0;
|
||||
while (mysql_stmt_fetch(stmt) == 0) {
|
||||
printf("%d\t%d\t%s\t%s\n", id, num, name, birthday);
|
||||
row_count++;
|
||||
}
|
||||
ASSERT_EQ(row_count, 9, "row_count");
|
||||
mysql_stmt_close(stmt);
|
||||
|
||||
return 0;
|
||||
}
|
||||
int main(int argc, char** argv) {
|
||||
mysql_library_init(0, NULL, NULL);
|
||||
MYSQL *mysql = mysql_init(NULL);
|
||||
unsigned int timeout = 3000;
|
||||
init_conn_info(OB_ORACLE_MODE);
|
||||
mysql_options(mysql, MYSQL_OPT_CONNECT_TIMEOUT, &timeout);
|
||||
|
||||
if (mysql_real_connect(mysql, DBHOST, DBUSER, DBPASS, DBNAME, DBPORT, DBSOCK, DBPCNT) == NULL)
|
||||
{
|
||||
my_log("connect failed: %s, host:%s, port:%d, user:%s, pass:%s, dbname:%s",
|
||||
mysql_error(mysql),DBHOST, DBPORT, DBUSER, DBPASS, DBNAME);
|
||||
mysql_close(mysql);
|
||||
mysql_library_end();
|
||||
return 0;
|
||||
} else {
|
||||
my_log("connect %s:%d using %s succ", DBHOST, DBPORT, DBUSER);
|
||||
}
|
||||
int ret = mysql_query(mysql, "SET NAMES utf8");
|
||||
if (ret != 0)
|
||||
{
|
||||
printf("set names error, %s\n", mysql_error(mysql));
|
||||
return ret;
|
||||
}
|
||||
mysql_query(mysql, "drop table person");
|
||||
ret = mysql_query(mysql, "create table person(id int, num int, name varchar2(20), birthday varchar2(20))");
|
||||
if (ret != 0)
|
||||
{
|
||||
my_log("create table error, %s\n", mysql_error(mysql));
|
||||
return ret;
|
||||
}
|
||||
stmt_insert_array_test(mysql);
|
||||
// stmt_select_test(mysql);
|
||||
return 0;
|
||||
}
|
||||
295
unittest/my_test/ob_oracle_datetype_test.c
Normal file
295
unittest/my_test/ob_oracle_datetype_test.c
Normal file
@ -0,0 +1,295 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "mysql.h"
|
||||
#include "test_util.h"
|
||||
/*
|
||||
*
|
||||
*/
|
||||
int show_query_result(MYSQL* mysql, const char* query, int expect_field_count)
|
||||
{
|
||||
int filed_count = 0;
|
||||
if (mysql_real_query(mysql, query, strlen(query))) {
|
||||
my_log("mysql_real_query select failed:%s", mysql_error(mysql));
|
||||
ASSERT_EQ(0, -1, "mysql_real_query");
|
||||
return -1;
|
||||
}
|
||||
MYSQL_RES * result = mysql_store_result(mysql);
|
||||
if (!result) {
|
||||
my_log("unexpect null result");
|
||||
ASSERT_EQ(0, -1, "mysql_use_result get null");
|
||||
return -1;
|
||||
}
|
||||
filed_count = mysql_num_fields(result);
|
||||
if (expect_field_count > 0) {
|
||||
ASSERT_EQ(filed_count, expect_field_count, "mysql_num_fields");
|
||||
}
|
||||
int i = 0;
|
||||
MYSQL_FIELD *fields = mysql_fetch_fields(result);
|
||||
for(i = 0; i < filed_count; i++)
|
||||
{
|
||||
printf("%s\t", fields[i].name);
|
||||
}
|
||||
printf("\n");
|
||||
int result_count = 0;
|
||||
MYSQL_ROW sql_row;
|
||||
while (sql_row = mysql_fetch_row(result)) {
|
||||
result_count++;
|
||||
for (i = 0; i < filed_count; i++)
|
||||
{
|
||||
printf("%s,", sql_row[i]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
mysql_free_result(result);
|
||||
return 0;
|
||||
}
|
||||
int do_text_time_test1(MYSQL* mysql) {
|
||||
my_log("=========do_text_time_test1==========");
|
||||
const char* select_query = "select * from timetest;";
|
||||
// const char* insert_query = "insert into timetest values(sysdate,sysdate,sysdate,sysdate)";
|
||||
const char* insert_query = "insert into timetest values(to_date('2021-03-29 02.32.18', 'YYYY-mm-dd HH.MI.SS')"\
|
||||
",to_date('2021-03-29 02.32.18', 'YYYY-mm-dd HH.MI.SS')"
|
||||
",to_date('2021-03-29 02.32.18', 'YYYY-mm-dd HH.MI.SS')"
|
||||
",to_date('2021-03-29 02.32.18', 'YYYY-mm-dd HH.MI.SS'))";
|
||||
my_ulonglong affected_rows;
|
||||
mysql_real_query(mysql, "delete from timetest", strlen("delete from timetest"));
|
||||
mysql_query(mysql, "ALTER SESSION SET NLS_DATE_FORMAT='DD-MON-RR';");
|
||||
mysql_query(mysql, "ALTER SESSION SET NLS_TIMESTAMP_FORMAT='DD-MON-RR HH.MI.SSXFF AM';");
|
||||
mysql_query(mysql, "ALTER SESSION SET NLS_TIMESTAMP_TZ_FORMAT='DD-MON-RR HH.MI.SSXFF AM TZR';");
|
||||
if (mysql_real_query(mysql, insert_query, strlen(insert_query))) {
|
||||
my_log("mysql_real_query insert_query failed:%s", mysql_error(mysql));
|
||||
ASSERT_EQ(0, -1, "mysql_real_query");
|
||||
return -1;
|
||||
}
|
||||
show_query_result(mysql, "show variables like '%nls_date_format%'", 0);
|
||||
int filed_count = 0;
|
||||
if (mysql_real_query(mysql, select_query, strlen(select_query))) {
|
||||
my_log("mysql_real_query select failed:%s", mysql_error(mysql));
|
||||
ASSERT_EQ(0, -1, "mysql_real_query");
|
||||
return -1;
|
||||
}
|
||||
MYSQL_RES * result = mysql_store_result(mysql);
|
||||
if (!result) {
|
||||
my_log("unexpect null result");
|
||||
ASSERT_EQ(0, -1, "mysql_use_result get null");
|
||||
return -1;
|
||||
}
|
||||
filed_count = mysql_num_fields(result);
|
||||
ASSERT_EQ(filed_count, 4, "mysql_num_fields");
|
||||
int i = 0;
|
||||
MYSQL_FIELD *fields = mysql_fetch_fields(result);
|
||||
for(i = 0; i < filed_count; i++)
|
||||
{
|
||||
printf("%s\t", fields[i].name);
|
||||
}
|
||||
printf("\n");
|
||||
int result_count = 0;
|
||||
MYSQL_ROW sql_row;
|
||||
while (sql_row = mysql_fetch_row(result)) {
|
||||
result_count++;
|
||||
for (i = 0; i < filed_count; i++)
|
||||
{
|
||||
printf("%s,", sql_row[i]);
|
||||
switch(i){
|
||||
case 0:
|
||||
ASSERT_EQ(strncmp(sql_row[i], "29-MAR-21", strlen("29-MAR-21")), 0, "DATE_FORMAT");
|
||||
break;
|
||||
case 1:
|
||||
ASSERT_EQ(strncmp(sql_row[i], "29-MAR-21 02.32.18.000 AM", strlen("29-MAR-21 02.32.18.000 AM")), 0, "TIMESTAMP_FORMAT");
|
||||
break;
|
||||
case 2:
|
||||
ASSERT_EQ(strncmp(sql_row[i], "29-MAR-21 02.32.18.000 AM +08:00", strlen("29-MAR-21 02.32.18.000 AM +08:00")),
|
||||
0, "TIMESTAMP_WITH_TIMEEZONE_FORMAT");
|
||||
break;
|
||||
case 3:
|
||||
ASSERT_EQ(strncmp(sql_row[i], "29-MAR-21 02.32.18.000 AM", strlen("29-MAR-21 02.32.18.000 AM")),
|
||||
0, "TIMESTAMP_WITH_LOCAL_TIMEEZONE_FORMAT");
|
||||
break;
|
||||
default:
|
||||
ASSERT_EQ(0, -1, "unexpect index");
|
||||
break;
|
||||
}
|
||||
}
|
||||
// printf("\n");
|
||||
}
|
||||
mysql_free_result(result);
|
||||
mysql_real_query(mysql, "commit", strlen("commit"));
|
||||
return 0;
|
||||
}
|
||||
int do_text_time_test2(MYSQL* mysql) {
|
||||
my_log("=========do_text_time_test1==========");
|
||||
const char* select_query = "select * from timetest;";
|
||||
// const char* insert_query = "insert into timetest values(sysdate,sysdate,sysdate,sysdate)";
|
||||
const char* insert_query = "insert into timetest values(to_date('2021-03-29 02.32.18', 'YYYY-mm-dd HH.MI.SS')"\
|
||||
",to_date('2021-03-29 02.32.18', 'YYYY-mm-dd HH.MI.SS')"
|
||||
",to_date('2021-03-29 02.32.18', 'YYYY-mm-dd HH.MI.SS')"
|
||||
",to_date('2021-03-29 02.32.18', 'YYYY-mm-dd HH.MI.SS'))";
|
||||
my_ulonglong affected_rows;
|
||||
mysql_real_query(mysql, "delete from timetest", strlen("delete from timetest"));
|
||||
mysql_query(mysql, "ALTER SESSION SET NLS_DATE_FORMAT='YYYY-MM-DD';");
|
||||
mysql_query(mysql, "ALTER SESSION SET NLS_TIMESTAMP_FORMAT='YYYY-MM-DD HH24:MI:SS.FF';");
|
||||
mysql_query(mysql, "ALTER SESSION SET NLS_TIMESTAMP_TZ_FORMAT='YYYY-MM-DD HH24:MI:SS.FF TZR TZD';");
|
||||
if (mysql_real_query(mysql, insert_query, strlen(insert_query))) {
|
||||
my_log("mysql_real_query insert_query failed:%s", mysql_error(mysql));
|
||||
ASSERT_EQ(0, -1, "mysql_real_query");
|
||||
return -1;
|
||||
}
|
||||
show_query_result(mysql, "show variables like '%nls_date_format%'", 0);
|
||||
int filed_count = 0;
|
||||
if (mysql_real_query(mysql, select_query, strlen(select_query))) {
|
||||
my_log("mysql_real_query select failed:%s", mysql_error(mysql));
|
||||
ASSERT_EQ(0, -1, "mysql_real_query");
|
||||
return -1;
|
||||
}
|
||||
MYSQL_RES * result = mysql_store_result(mysql);
|
||||
if (!result) {
|
||||
my_log("unexpect null result");
|
||||
ASSERT_EQ(0, -1, "mysql_use_result get null");
|
||||
return -1;
|
||||
}
|
||||
filed_count = mysql_num_fields(result);
|
||||
ASSERT_EQ(filed_count, 4, "mysql_num_fields");
|
||||
int i = 0;
|
||||
MYSQL_FIELD *fields = mysql_fetch_fields(result);
|
||||
for(i = 0; i < filed_count; i++)
|
||||
{
|
||||
printf("%s\t", fields[i].name);
|
||||
}
|
||||
printf("\n");
|
||||
int result_count = 0;
|
||||
MYSQL_ROW sql_row;
|
||||
while (sql_row = mysql_fetch_row(result)) {
|
||||
result_count++;
|
||||
for (i = 0; i < filed_count; i++)
|
||||
{
|
||||
printf("%s,", sql_row[i]);
|
||||
switch(i){
|
||||
case 0:
|
||||
ASSERT_EQ(strncmp(sql_row[i], "2021-03-29", strlen("2021-03-29")), 0, "DATE_FORMAT");
|
||||
break;
|
||||
case 1:
|
||||
ASSERT_EQ(strncmp(sql_row[i], "2021-03-29 02:32:18.000", strlen("2021-03-29 02:32:18.000")), 0, "TIMESTAMP_FORMAT");
|
||||
break;
|
||||
case 2:
|
||||
ASSERT_EQ(strncmp(sql_row[i], "2021-03-29 02:32:18.000 +08:00", strlen("2021-03-29 02:32:18.000 +08:00")),
|
||||
0, "TIMESTAMP_WITH_TIMEEZONE_FORMAT");
|
||||
break;
|
||||
case 3:
|
||||
ASSERT_EQ(strncmp(sql_row[i], "2021-03-29 02:32:18.000", strlen("2021-03-29 02:32:18.000")),
|
||||
0, "TIMESTAMP_WITH_LOCAL_TIMEEZONE_FORMAT");
|
||||
break;
|
||||
default:
|
||||
ASSERT_EQ(0, -1, "unexpect index");
|
||||
break;
|
||||
}
|
||||
}
|
||||
// printf("\n");
|
||||
}
|
||||
mysql_free_result(result);
|
||||
mysql_real_query(mysql, "commit", strlen("commit"));
|
||||
return 0;
|
||||
}
|
||||
int do_ps_time_test1(MYSQL* mysql) {
|
||||
my_log("=========do_text_time_test1==========");
|
||||
const char* select_query = "select * from timetest;";
|
||||
// const char* insert_query = "insert into timetest values(sysdate,sysdate,sysdate,sysdate)";
|
||||
const char* insert_query = "insert into timetest values(to_date('2021-03-29 02.32.18', 'YYYY-mm-dd HH.MI.SS')"\
|
||||
",to_date('2021-03-29 02.32.18', 'YYYY-mm-dd HH.MI.SS')"
|
||||
",to_date('2021-03-29 02.32.18', 'YYYY-mm-dd HH.MI.SS')"
|
||||
",to_date('2021-03-29 02.32.18', 'YYYY-mm-dd HH.MI.SS'))";
|
||||
my_ulonglong affected_rows;
|
||||
mysql_real_query(mysql, "delete from timetest", strlen("delete from timetest"));
|
||||
MYSQL_STMT *stmt;
|
||||
MYSQL_BIND bind[4];
|
||||
int filed_count = 0;
|
||||
int param_count = 0;
|
||||
int i = 0;
|
||||
mysql_query(mysql, "ALTER SESSION SET NLS_DATE_FORMAT='DD-MON-RR';");
|
||||
mysql_query(mysql, "ALTER SESSION SET NLS_TIMESTAMP_FORMAT='DD-MON-RR HH.MI.SSXFF AM';");
|
||||
mysql_query(mysql, "ALTER SESSION SET NLS_TIMESTAMP_TZ_FORMAT='DD-MON-RR HH.MI.SSXFF AM TZR';");
|
||||
if (mysql_real_query(mysql, insert_query, strlen(insert_query))) {
|
||||
my_log("mysql_real_query insert_query failed:%s", mysql_error(mysql));
|
||||
ASSERT_EQ(0, -1, "mysql_real_query");
|
||||
return -1;
|
||||
}
|
||||
show_query_result(mysql, "show variables like '%nls_date_format%'", 0);
|
||||
stmt = mysql_stmt_init(mysql);
|
||||
if (!stmt) {
|
||||
my_log("msyql_stmt_init failed: %s", mysql_error(mysql));
|
||||
return -1;
|
||||
}
|
||||
if (mysql_stmt_prepare(stmt, select_query, strlen(select_query))) {
|
||||
my_log("mysql_stmt_prepare failed:%s", mysql_error(mysql));
|
||||
return -1;
|
||||
}
|
||||
filed_count = mysql_stmt_field_count(stmt);
|
||||
param_count = mysql_stmt_param_count(stmt);
|
||||
ASSERT_EQ(filed_count, 4, "mysql_stmt_field_count");
|
||||
ASSERT_EQ(param_count, 0, "mysql_stmt_param_count");
|
||||
unsigned int iteration_count = 1;
|
||||
//stmt->iteration_count = 0;
|
||||
if (mysql_stmt_execute(stmt)) {
|
||||
my_log("mysql_stmt_execute select failed:%s", mysql_stmt_error(stmt));
|
||||
return -1;
|
||||
}
|
||||
if (mysql_stmt_store_result(stmt)) {
|
||||
my_log("mysql_stmt_store_result failed :%s", mysql_stmt_error(stmt));
|
||||
return -1;
|
||||
}
|
||||
filed_count = mysql_stmt_field_count(stmt);
|
||||
ASSERT_EQ(filed_count, 4, "mysql_stmt_field_count");
|
||||
my_ulonglong row_count = mysql_stmt_num_rows(stmt);
|
||||
ASSERT_EQ(row_count, 1, "mysql_stmt_field_count");
|
||||
memset(bind, 0, sizeof(bind));
|
||||
char buffer[4][128];
|
||||
memset(buffer, 0, 4* 128);
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
bind[i].buffer = buffer[i];
|
||||
bind[i].buffer_length = 128;
|
||||
bind[i].buffer_type = MYSQL_TYPE_STRING;
|
||||
}
|
||||
if (mysql_stmt_bind_result(stmt, bind)) {
|
||||
my_log("mysql_stmt_bind_result failed:%s", mysql_stmt_error(stmt));
|
||||
return -1;
|
||||
}
|
||||
while (mysql_stmt_fetch(stmt) == 0) {
|
||||
for (i =0; i < filed_count; i++)
|
||||
{
|
||||
my_log("col[%d]:%s", i, buffer[i]);
|
||||
}
|
||||
}
|
||||
mysql_stmt_close(stmt);
|
||||
mysql_real_query(mysql, "commit", strlen("commit"));
|
||||
return 0;
|
||||
}
|
||||
int main(int argc, char** argv) {
|
||||
mysql_library_init(0, NULL, NULL);
|
||||
MYSQL *mysql = mysql_init(NULL);
|
||||
unsigned int timeout = 3000;
|
||||
init_conn_info(OB_ORACLE_MODE);
|
||||
mysql_options(mysql, MYSQL_OPT_CONNECT_TIMEOUT, &timeout);
|
||||
if (mysql_real_connect(mysql, DBHOST, DBUSER, DBPASS, DBNAME, DBPORT, DBSOCK, DBPCNT) == NULL)
|
||||
{
|
||||
my_log("connect failed: %s, host:%s, port:%d, user:%s, pass:%s, dbname:%s",
|
||||
mysql_error(mysql),DBHOST, DBPORT, DBUSER, DBPASS, DBNAME);
|
||||
mysql_close(mysql);
|
||||
mysql_library_end();
|
||||
return 0;
|
||||
} else {
|
||||
my_log("connect %s:%d using %s succ", DBHOST, DBPORT, DBUSER);
|
||||
}
|
||||
int ret = 0;
|
||||
mysql_real_query(mysql, "drop table timetest", strlen("drop table timetest"));
|
||||
ret = mysql_query(mysql, "create table timetest(tme date,tmestp timestamp(3),"\
|
||||
"tmestp_tz timestamp(3) with time zone,"\
|
||||
"tmpstp_tzl timestamp(3) with local time zone);");
|
||||
if (ret != 0){
|
||||
printf("create table failed, %s\n", mysql_error(mysql));
|
||||
return ret;
|
||||
}
|
||||
do_text_time_test1(mysql);
|
||||
do_text_time_test2(mysql);
|
||||
do_ps_time_test1(mysql);
|
||||
return 0;
|
||||
}
|
||||
428
unittest/my_test/ob_oracle_fetch_cursor_test.c
Normal file
428
unittest/my_test/ob_oracle_fetch_cursor_test.c
Normal file
@ -0,0 +1,428 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "mysql.h"
|
||||
#include "test_util.h"
|
||||
|
||||
int stmt_oracle_cursor_test_with_param_no_result(MYSQL* mysql) {
|
||||
my_log("stmt_oracle_cursor_test_with_param_no_result");
|
||||
const char* pStatement = "select * from test_new_ps where id = ? and num = ? and name = ?";
|
||||
MYSQL_STMT *stmt;
|
||||
MYSQL_BIND bind[4];
|
||||
MYSQL_BIND param[4];
|
||||
int ret = 0;
|
||||
int param_count;
|
||||
int filed_count;
|
||||
my_ulonglong affected_rows;
|
||||
const char* query = "delete from test_new_ps";
|
||||
if (ret = mysql_real_query(mysql, query, strlen(query))) {
|
||||
my_log("mysql_real_query failed:%s", mysql_error(mysql));
|
||||
ASSERT_EQ(ret, 0, "mysql_real_query");
|
||||
}
|
||||
stmt = mysql_stmt_init(mysql);
|
||||
if (!stmt) {
|
||||
my_log("msyql_stmt_init failed: %s", mysql_error(mysql));
|
||||
ASSERT_EQ(-1, 0, "mysql_stmt_init");
|
||||
return -1;
|
||||
}
|
||||
if (ret = mysql_stmt_prepare_v2(stmt, pStatement, strlen(pStatement), 0)) {
|
||||
my_log("mysql_stmt_prepare_v2 failed:%s", mysql_error(mysql));
|
||||
ASSERT_EQ(ret, 0, "mysql_stmt_prepare_v2");
|
||||
}
|
||||
filed_count = mysql_stmt_field_count(stmt);
|
||||
my_log("filed_count is %u", filed_count);
|
||||
param_count = mysql_stmt_param_count(stmt);
|
||||
my_log("param_count is %d", param_count);
|
||||
int input_id = 0, input_num = 0;
|
||||
char input_name[20] = "test";
|
||||
unsigned long str_len;
|
||||
{
|
||||
//id
|
||||
param[0].buffer_type = MYSQL_TYPE_LONG;
|
||||
param[0].buffer = (char*)&input_id;
|
||||
param[0].buffer_length = 0;
|
||||
param[0].is_null = 0;
|
||||
param[0].length = 0;
|
||||
// bind[0].is_unsigned = 0;
|
||||
}
|
||||
{
|
||||
//num
|
||||
param[1].buffer_type = MYSQL_TYPE_LONG;
|
||||
param[1].buffer = (char*)&input_num;
|
||||
param[1].buffer_length = 0;
|
||||
param[1].is_null = 0;
|
||||
param[1].length = 0;
|
||||
// bind[1].is_unsigned = 0;
|
||||
}
|
||||
{
|
||||
//name
|
||||
str_len = strlen(input_name);
|
||||
my_log("str_len for name is %d", str_len);
|
||||
param[2].buffer_type = MYSQL_TYPE_STRING;
|
||||
param[2].buffer = (char*)input_name;
|
||||
param[2].buffer_length = str_len;
|
||||
param[2].is_null = 0;
|
||||
param[2].length = &str_len;
|
||||
// bind[2].is_unsigned = 0;
|
||||
}
|
||||
if (mysql_stmt_bind_param(stmt, param)) {
|
||||
my_log("bind failed:%s", mysql_stmt_error(stmt));
|
||||
return -1;
|
||||
}
|
||||
unsigned int iteration_count = 0;
|
||||
// mysql_stmt_attr_set(stmt, STMT_ATTR_ITERRATION_COUNT, &iteration_count);
|
||||
//stmt->iteration_count = 0;
|
||||
if (ret = mysql_stmt_execute_v2(stmt, pStatement, strlen(pStatement), iteration_count, 0, 0)) {
|
||||
my_log("mysql_stmt_execute_v2 select failed:%s", mysql_stmt_error(stmt));
|
||||
ASSERT_EQ(ret, 0, "mysql_stmt_execute_v2");
|
||||
return -1;
|
||||
}
|
||||
// if (mysql_stmt_store_result(stmt)) {
|
||||
// my_log("mysql_stmt_store_result failed :%s", mysql_stmt_error(stmt));
|
||||
// return -1;
|
||||
// }
|
||||
filed_count = mysql_stmt_field_count(stmt);
|
||||
my_log("filed_count is %u", filed_count);
|
||||
my_ulonglong row_count = mysql_stmt_num_rows(stmt);
|
||||
my_log("row count is %u", row_count);
|
||||
memset(bind, 0, sizeof(bind));
|
||||
|
||||
int id, num;
|
||||
char name[20];
|
||||
char birthday[20];
|
||||
bind[0].buffer_type = MYSQL_TYPE_LONG;
|
||||
bind[0].buffer = &id;
|
||||
bind[1].buffer_type = MYSQL_TYPE_LONG;
|
||||
bind[1].buffer = #
|
||||
bind[2].buffer_type = MYSQL_TYPE_STRING;
|
||||
bind[2].buffer = name;
|
||||
bind[2].buffer_length = sizeof(name);
|
||||
bind[3].buffer_type = MYSQL_TYPE_STRING;
|
||||
bind[3].buffer = birthday;
|
||||
bind[3].buffer_length = sizeof(birthday);
|
||||
|
||||
if (ret = mysql_stmt_bind_result(stmt, bind)) {
|
||||
my_log("mysql_stmt_bind_result failed:%s", mysql_stmt_error(stmt));
|
||||
ASSERT_EQ(ret, 0, "mysql_stmt_bind_result");
|
||||
}
|
||||
while (mysql_stmt_fetch_oracle_implicit_cursor(stmt, 1) == 0) {
|
||||
my_log("%d\t%d\t%s\t%s", id, num, name, birthday);
|
||||
}
|
||||
if (ret = mysql_stmt_close(stmt)) {
|
||||
my_log("mysql_stmt_close faled:%s", mysql_stmt_error(stmt));
|
||||
}
|
||||
ASSERT_EQ(0, 0, "stmt_oracle_cursor_test_with_param_no_result");
|
||||
return 0;
|
||||
}
|
||||
int stmt_oracle_cursor_test_no_param_with_result(MYSQL* mysql) {
|
||||
my_log("stmt_oracle_cursor_test");
|
||||
const char* pStatement = "select * from test_new_ps";
|
||||
MYSQL_STMT *stmt;
|
||||
MYSQL_BIND bind[4];
|
||||
int ret = 0;
|
||||
int param_count;
|
||||
int filed_count;
|
||||
my_ulonglong affected_rows;
|
||||
int i = 0;
|
||||
char query[1000] = {0};
|
||||
snprintf(query, 1000, "delete from test_new_ps");
|
||||
if (ret = mysql_real_query(mysql, query, strlen(query))) {
|
||||
my_log("mysql_real_query failed:%s", mysql_error(mysql));
|
||||
ASSERT_EQ(ret, 0, "mysql_real_query");
|
||||
}
|
||||
for (i = 0; i < 10; i++)
|
||||
{
|
||||
snprintf(query, 1000, "insert into test_new_ps(id, num, name, birthday) values(%d,%d, 'name_%d', 'birth_%d')", i ,i, i, i);
|
||||
if (ret = mysql_real_query(mysql, query, strlen(query))) {
|
||||
my_log("mysql_real_query failed:%s", mysql_error(mysql));
|
||||
ASSERT_EQ(ret, 0, "mysql_real_query");
|
||||
}
|
||||
}
|
||||
stmt = mysql_stmt_init(mysql);
|
||||
if (!stmt) {
|
||||
my_log("msyql_stmt_init failed: %s", mysql_error(mysql));
|
||||
ASSERT_EQ(-1, 0, "mysql_stmt_init");
|
||||
return -1;
|
||||
}
|
||||
if (ret = mysql_stmt_prepare_v2(stmt, pStatement, strlen(pStatement), 0)) {
|
||||
my_log("mysql_stmt_prepare_v2 failed:%s", mysql_error(mysql));
|
||||
ASSERT_EQ(ret, 0, "mysql_stmt_prepare_v2");
|
||||
}
|
||||
filed_count = mysql_stmt_field_count(stmt);
|
||||
my_log("filed_count is %u", filed_count);
|
||||
param_count = mysql_stmt_param_count(stmt);
|
||||
my_log("param_count is %d", param_count);
|
||||
unsigned int iteration_count = 1;
|
||||
// mysql_stmt_attr_set(stmt, STMT_ATTR_ITERRATION_COUNT, &iteration_count);
|
||||
//stmt->iteration_count = 0;
|
||||
if (mysql_stmt_execute_v2(stmt, pStatement, strlen(pStatement), iteration_count, 0, 0)) {
|
||||
my_log("mysql_stmt_execute_v2 select failed:%s", mysql_stmt_error(stmt));
|
||||
return -1;
|
||||
}
|
||||
// if (mysql_stmt_store_result(stmt)) {
|
||||
// my_log("mysql_stmt_store_result failed :%s", mysql_stmt_error(stmt));
|
||||
// return -1;
|
||||
// }
|
||||
filed_count = mysql_stmt_field_count(stmt);
|
||||
my_log("filed_count is %u", filed_count);
|
||||
my_ulonglong row_count = mysql_stmt_num_rows(stmt);
|
||||
my_log("row count is %u", row_count);
|
||||
memset(bind, 0, sizeof(bind));
|
||||
int id, num;
|
||||
char name[20];
|
||||
char birthday[20];
|
||||
bind[0].buffer_type = MYSQL_TYPE_LONG;
|
||||
bind[0].buffer = &id;
|
||||
bind[1].buffer_type = MYSQL_TYPE_LONG;
|
||||
bind[1].buffer = #
|
||||
bind[2].buffer_type = MYSQL_TYPE_STRING;
|
||||
bind[2].buffer = name;
|
||||
bind[2].buffer_length = sizeof(name);
|
||||
bind[3].buffer_type = MYSQL_TYPE_STRING;
|
||||
bind[3].buffer = birthday;
|
||||
bind[3].buffer_length = sizeof(birthday);
|
||||
|
||||
if (ret = mysql_stmt_bind_result(stmt, bind)) {
|
||||
my_log("mysql_stmt_bind_result failed:%s", mysql_stmt_error(stmt));
|
||||
ASSERT_EQ(ret, 0, "mysql_stmt_bind_result");
|
||||
}
|
||||
i = 0;
|
||||
while (mysql_stmt_fetch_oracle_implicit_cursor(stmt, 0) == 0) {
|
||||
i++;
|
||||
printf("%d\t%d\t%s\t%s\n", id, num, name, birthday);
|
||||
}
|
||||
ASSERT_EQ(10, i, "mysql_stmt_fetch");
|
||||
if (ret = mysql_stmt_close(stmt)) {
|
||||
my_log("mysql_stmt_close faled:%s", mysql_stmt_error(stmt));
|
||||
}
|
||||
ASSERT_EQ(0, 0, "stmt_oracle_cursor_test_no_param_with_result");
|
||||
return 0;
|
||||
}
|
||||
int stmt_oracle_cursor_test_with_param_with_result(MYSQL* mysql) {
|
||||
my_log("stmt_oracle_cursor_test_with_param_with_result");
|
||||
const char* pStatement = "select * from test_new_ps where id = ? and num = ? and name = ?";
|
||||
MYSQL_STMT *stmt;
|
||||
MYSQL_BIND bind[4];
|
||||
MYSQL_BIND param[4];
|
||||
int ret = 0;
|
||||
int param_count;
|
||||
int filed_count;
|
||||
int i = 0;
|
||||
my_ulonglong affected_rows;
|
||||
char query [400];
|
||||
snprintf(query, 400, "delete from test_new_ps");
|
||||
if (ret = mysql_real_query(mysql, query, strlen(query))) {
|
||||
my_log("mysql_real_query failed:%s", mysql_error(mysql));
|
||||
ASSERT_EQ(ret, 0, "mysql_real_query");
|
||||
}
|
||||
for (i = 0; i < 10; i++)
|
||||
{
|
||||
snprintf(query, 1000, "insert into test_new_ps(id, num, name, birthday) values(%d,%d, 'name_%d', 'birth_%d')", i ,i, i, i);
|
||||
if (ret = mysql_real_query(mysql, query, strlen(query))) {
|
||||
my_log("mysql_real_query failed:%s", mysql_error(mysql));
|
||||
ASSERT_EQ(ret, 0, "mysql_real_query");
|
||||
}
|
||||
}
|
||||
stmt = mysql_stmt_init(mysql);
|
||||
if (!stmt) {
|
||||
my_log("msyql_stmt_init failed: %s", mysql_error(mysql));
|
||||
ASSERT_EQ(-1, 0, "mysql_stmt_init");
|
||||
return -1;
|
||||
}
|
||||
if (ret = mysql_stmt_prepare_v2(stmt, pStatement, strlen(pStatement), 0)) {
|
||||
my_log("mysql_stmt_prepare_v2 failed:%s", mysql_error(mysql));
|
||||
ASSERT_EQ(ret, 0, "mysql_stmt_prepare_v2");
|
||||
}
|
||||
filed_count = mysql_stmt_field_count(stmt);
|
||||
my_log("filed_count is %u", filed_count);
|
||||
param_count = mysql_stmt_param_count(stmt);
|
||||
my_log("param_count is %d", param_count);
|
||||
int input_id = 0, input_num = 0;
|
||||
char input_name[20] = "name_0";
|
||||
unsigned long str_len;
|
||||
{
|
||||
//id
|
||||
param[0].buffer_type = MYSQL_TYPE_LONG;
|
||||
param[0].buffer = (char*)&input_id;
|
||||
param[0].buffer_length = 0;
|
||||
param[0].is_null = 0;
|
||||
param[0].length = 0;
|
||||
// bind[0].is_unsigned = 0;
|
||||
}
|
||||
{
|
||||
//num
|
||||
param[1].buffer_type = MYSQL_TYPE_LONG;
|
||||
param[1].buffer = (char*)&input_num;
|
||||
param[1].buffer_length = 0;
|
||||
param[1].is_null = 0;
|
||||
param[1].length = 0;
|
||||
// bind[1].is_unsigned = 0;
|
||||
}
|
||||
{
|
||||
//name
|
||||
str_len = strlen(input_name);
|
||||
my_log("str_len for name is %d", str_len);
|
||||
param[2].buffer_type = MYSQL_TYPE_STRING;
|
||||
param[2].buffer = (char*)input_name;
|
||||
param[2].buffer_length = str_len;
|
||||
param[2].is_null = 0;
|
||||
param[2].length = &str_len;
|
||||
// bind[2].is_unsigned = 0;
|
||||
}
|
||||
if (mysql_stmt_bind_param(stmt, param)) {
|
||||
my_log("bind failed:%s", mysql_stmt_error(stmt));
|
||||
return -1;
|
||||
}
|
||||
unsigned int iteration_count = 0;
|
||||
// mysql_stmt_attr_set(stmt, STMT_ATTR_ITERRATION_COUNT, &iteration_count);
|
||||
//stmt->iteration_count = 0;
|
||||
if (ret = mysql_stmt_execute_v2(stmt, pStatement, strlen(pStatement), iteration_count, 0, 0)) {
|
||||
my_log("mysql_stmt_execute_v2 select failed:%s", mysql_stmt_error(stmt));
|
||||
ASSERT_EQ(ret, 0, "mysql_stmt_execute_v2");
|
||||
return -1;
|
||||
}
|
||||
// if (mysql_stmt_store_result(stmt)) {
|
||||
// my_log("mysql_stmt_store_result failed :%s", mysql_stmt_error(stmt));
|
||||
// return -1;
|
||||
// }
|
||||
filed_count = mysql_stmt_field_count(stmt);
|
||||
my_log("filed_count is %u", filed_count);
|
||||
my_ulonglong row_count = mysql_stmt_num_rows(stmt);
|
||||
my_log("row count is %u", row_count);
|
||||
memset(bind, 0, sizeof(bind));
|
||||
|
||||
int id, num;
|
||||
char name[20];
|
||||
char birthday[20];
|
||||
bind[0].buffer_type = MYSQL_TYPE_LONG;
|
||||
bind[0].buffer = &id;
|
||||
bind[1].buffer_type = MYSQL_TYPE_LONG;
|
||||
bind[1].buffer = #
|
||||
bind[2].buffer_type = MYSQL_TYPE_STRING;
|
||||
bind[2].buffer = name;
|
||||
bind[2].buffer_length = sizeof(name);
|
||||
bind[3].buffer_type = MYSQL_TYPE_STRING;
|
||||
bind[3].buffer = birthday;
|
||||
bind[3].buffer_length = sizeof(birthday);
|
||||
|
||||
if (ret = mysql_stmt_bind_result(stmt, bind)) {
|
||||
my_log("mysql_stmt_bind_result failed:%s", mysql_stmt_error(stmt));
|
||||
ASSERT_EQ(ret, 0, "mysql_stmt_bind_result");
|
||||
}
|
||||
while (mysql_stmt_fetch_oracle_implicit_cursor(stmt, 1) == 0) {
|
||||
my_log("%d\t%d\t%s\t%s", id, num, name, birthday);
|
||||
}
|
||||
if (ret = mysql_stmt_close(stmt)) {
|
||||
my_log("mysql_stmt_close faled:%s", mysql_stmt_error(stmt));
|
||||
}
|
||||
ASSERT_EQ(0, 0, "stmt_oracle_cursor_test_with_param_with_result");
|
||||
return 0;
|
||||
}
|
||||
int stmt_oracle_cursor_test_no_param_no_result_exact_not_match(MYSQL* mysql) {
|
||||
my_log("stmt_oracle_cursor_test_no_param_no_result");
|
||||
const char* pStatement = "select * from test_new_ps";
|
||||
MYSQL_STMT *stmt;
|
||||
MYSQL_BIND bind[4];
|
||||
int ret = 0;
|
||||
int param_count;
|
||||
int filed_count;
|
||||
my_ulonglong affected_rows;
|
||||
const char* query = "delete from test_new_ps";
|
||||
if (ret = mysql_real_query(mysql, query, strlen(query))) {
|
||||
my_log("mysql_real_query failed:%s", mysql_error(mysql));
|
||||
ASSERT_EQ(ret, 0, "mysql_real_query");
|
||||
}
|
||||
stmt = mysql_stmt_init(mysql);
|
||||
if (!stmt) {
|
||||
my_log("msyql_stmt_init failed: %s", mysql_error(mysql));
|
||||
ASSERT_EQ(-1, 0, "mysql_stmt_init");
|
||||
return -1;
|
||||
}
|
||||
if (ret = mysql_stmt_prepare_v2(stmt, pStatement, strlen(pStatement), 0)) {
|
||||
my_log("mysql_stmt_prepare_v2 failed:%s", mysql_error(mysql));
|
||||
ASSERT_EQ(ret, 0, "mysql_stmt_prepare_v2");
|
||||
}
|
||||
filed_count = mysql_stmt_field_count(stmt);
|
||||
my_log("filed_count is %u", filed_count);
|
||||
param_count = mysql_stmt_param_count(stmt);
|
||||
my_log("param_count is %d", param_count);
|
||||
unsigned int iteration_count = 2;
|
||||
// mysql_stmt_attr_set(stmt, STMT_ATTR_ITERRATION_COUNT, &iteration_count);
|
||||
//stmt->iteration_count = 0;
|
||||
if (ret = mysql_stmt_execute_v2(stmt, pStatement, strlen(pStatement), iteration_count, 0x00000002, 0)) {
|
||||
my_log("mysql_stmt_execute_v2 select failed:%s", mysql_stmt_error(stmt));
|
||||
ASSERT_EQ(1, ret, "mysql_stmt_execute_v2");
|
||||
return -1;
|
||||
} else {
|
||||
ASSERT_EQ(-1, ret, "mysql_stmt_execute_v2");
|
||||
return -1;
|
||||
}
|
||||
// if (mysql_stmt_store_result(stmt)) {
|
||||
// my_log("mysql_stmt_store_result failed :%s", mysql_stmt_error(stmt));
|
||||
// return -1;
|
||||
// }
|
||||
filed_count = mysql_stmt_field_count(stmt);
|
||||
my_log("filed_count is %u", filed_count);
|
||||
my_ulonglong row_count = mysql_stmt_num_rows(stmt);
|
||||
my_log("row count is %u", row_count);
|
||||
memset(bind, 0, sizeof(bind));
|
||||
int id, num;
|
||||
char name[20];
|
||||
char birthday[20];
|
||||
bind[0].buffer_type = MYSQL_TYPE_LONG;
|
||||
bind[0].buffer = &id;
|
||||
bind[1].buffer_type = MYSQL_TYPE_LONG;
|
||||
bind[1].buffer = #
|
||||
bind[2].buffer_type = MYSQL_TYPE_STRING;
|
||||
bind[2].buffer = name;
|
||||
bind[2].buffer_length = sizeof(name);
|
||||
bind[3].buffer_type = MYSQL_TYPE_STRING;
|
||||
bind[3].buffer = birthday;
|
||||
bind[3].buffer_length = sizeof(birthday);
|
||||
|
||||
if (ret = mysql_stmt_bind_result(stmt, bind)) {
|
||||
my_log("mysql_stmt_bind_result failed:%s", mysql_stmt_error(stmt));
|
||||
ASSERT_EQ(ret, 0, "mysql_stmt_bind_result");
|
||||
}
|
||||
while (mysql_stmt_fetch_oracle_implicit_cursor(stmt, 1) == 0) {
|
||||
printf("%d\t%d\t%s\t%s\n", id, num, name, birthday);
|
||||
}
|
||||
if (ret = mysql_stmt_close(stmt)) {
|
||||
my_log("mysql_stmt_close faled:%s", mysql_stmt_error(stmt));
|
||||
}
|
||||
ASSERT_EQ(-1, 0, "stmt_oracle_cursor_test_no_param_no_result");
|
||||
return 0;
|
||||
}
|
||||
int main(int argc, char** argv) {
|
||||
mysql_library_init(0, NULL, NULL);
|
||||
MYSQL *mysql = mysql_init(NULL);
|
||||
unsigned int timeout = 3000;
|
||||
init_conn_info(OB_ORACLE_MODE);
|
||||
mysql_options(mysql, MYSQL_OPT_CONNECT_TIMEOUT, &timeout);
|
||||
|
||||
if (mysql_real_connect(mysql, DBHOST, DBUSER, DBPASS, DBNAME, DBPORT, DBSOCK, DBPCNT) == NULL)
|
||||
{
|
||||
my_log("connect failed: %s\n", mysql_error(mysql));
|
||||
mysql_close(mysql);
|
||||
mysql_library_end();
|
||||
return 0;
|
||||
} else {
|
||||
my_log("connect to %s:%d using %s success", DBHOST, DBPORT, DBUSER);
|
||||
}
|
||||
int ret = mysql_query(mysql, "SET NAMES utf8");
|
||||
if (ret != 0)
|
||||
{
|
||||
printf("set names failed, %s\n", mysql_error(mysql));
|
||||
return ret;
|
||||
}
|
||||
mysql_query(mysql, "drop table test_new_ps");
|
||||
ret = mysql_query(mysql, "create table test_new_ps(id int, num int, name varchar2(20), birthday varchar2(20))");
|
||||
if (ret != 0)
|
||||
{
|
||||
my_log("create table error, %s\n", mysql_error(mysql));
|
||||
return ret;
|
||||
}
|
||||
stmt_oracle_cursor_test_no_param_with_result(mysql);
|
||||
stmt_oracle_cursor_test_with_param_no_result(mysql);
|
||||
stmt_oracle_cursor_test_with_param_with_result(mysql);
|
||||
return 0;
|
||||
}
|
||||
125
unittest/my_test/ob_oracle_pl_test.c
Normal file
125
unittest/my_test/ob_oracle_pl_test.c
Normal file
@ -0,0 +1,125 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "mysql.h"
|
||||
#include "test_util.h"
|
||||
/*
|
||||
*
|
||||
*/
|
||||
int do_pl_test(MYSQL* mysql) {
|
||||
my_log("=========do_pl_test==========");
|
||||
const char* create_pl = "create or replace procedure pl_test(x in number, y in out varchar2) "\
|
||||
"is begin "\
|
||||
" y:='this is a pl test';"\
|
||||
"END";
|
||||
int ret = 0;
|
||||
if (mysql_real_query(mysql, create_pl, strlen(create_pl))) {
|
||||
my_log("mysql_real_query failed: %s", mysql_error(mysql));
|
||||
ASSERT_EQ(0, -1, "mysql_real_query failed");
|
||||
return -1;
|
||||
}
|
||||
const char* pStatement = "call pl_test(?, ?)";
|
||||
MYSQL_STMT *stmt;
|
||||
MYSQL_BIND param_bind[2];
|
||||
MYSQL_BIND res_bind[2];
|
||||
int param_count;
|
||||
int id = 8;
|
||||
char name[20] = "jh";
|
||||
my_ulonglong affected_rows;
|
||||
stmt = mysql_stmt_init(mysql);
|
||||
if (!stmt) {
|
||||
my_log("msyql_stmt_init failed: %s", mysql_error(mysql));
|
||||
ASSERT_EQ(0, -1, "mysql_stmt_init failed");
|
||||
return -1;
|
||||
}
|
||||
if (mysql_stmt_prepare(stmt, pStatement, strlen(pStatement))) {
|
||||
my_log("mysql_stmt_prepare failed:%s", mysql_error(mysql));
|
||||
ASSERT_EQ(0, -1, "mysql_stmt_prepare failed");
|
||||
return -1;
|
||||
}
|
||||
param_count = mysql_stmt_param_count(stmt);
|
||||
ASSERT_EQ(param_count, 2, "mysql_stmt_param_count");
|
||||
MYSQL_RES *param_result = NULL;
|
||||
MYSQL_FIELD *params = NULL;
|
||||
if (NULL == (param_result = mysql_stmt_param_metadata(stmt))) {
|
||||
my_log("mysql_stmt_param_metadata failed:%s", mysql_stmt_error(stmt));
|
||||
} else if (NULL == (params = mysql_fetch_params(param_result))) {
|
||||
my_log("mysql_fetch_params failed:%s", mysql_stmt_error(stmt));
|
||||
} else {
|
||||
ASSERT_EQ(params[1].ob_routine_param_inout, 3, "ob_routine_param_inout");
|
||||
}
|
||||
memset(param_bind, 0, sizeof(param_bind));
|
||||
memset(res_bind, 0, sizeof(res_bind));
|
||||
{
|
||||
//id
|
||||
param_bind[0].buffer_type = MYSQL_TYPE_LONG;
|
||||
param_bind[0].buffer = (char*)&id;
|
||||
param_bind[0].buffer_length = 0;
|
||||
param_bind[0].is_null = 0;
|
||||
param_bind[0].length = 0;
|
||||
}
|
||||
{
|
||||
//name
|
||||
unsigned long str_len = strlen(name);
|
||||
param_bind[1].buffer_type = MYSQL_TYPE_STRING;
|
||||
param_bind[1].buffer = (char*)name;
|
||||
param_bind[1].buffer_length = str_len;
|
||||
param_bind[1].is_null = 0;
|
||||
param_bind[1].length = &str_len;
|
||||
// bind[1].is_unsigned = 0;
|
||||
}
|
||||
if (mysql_stmt_bind_param(stmt, param_bind)) {
|
||||
my_log("bind failed:%s", mysql_stmt_error(stmt));
|
||||
ASSERT_EQ(0, -1, "mysql_stmt_bind_param failed");
|
||||
return -1;
|
||||
}
|
||||
if (mysql_stmt_execute(stmt)) {
|
||||
my_log("mysql_stmt_execute insert failed:%s", mysql_stmt_error(stmt));
|
||||
ASSERT_EQ(0, -1, "mysql_stmt_execute failed");
|
||||
return -1;
|
||||
}
|
||||
char out_buf[20] = {0};
|
||||
res_bind[0].buffer_type = MYSQL_TYPE_STRING;
|
||||
res_bind[0].buffer = out_buf;
|
||||
res_bind[0].buffer_length = sizeof(out_buf);
|
||||
|
||||
if (mysql_stmt_bind_result(stmt, res_bind)) {
|
||||
my_log("mysql_stmt_bind_result failed:%s", mysql_stmt_error(stmt));
|
||||
return -1;
|
||||
}
|
||||
int i = 1;
|
||||
while (mysql_stmt_fetch(stmt) == 0) {
|
||||
// my_log("out_buf is %s", out_buf);
|
||||
if (strcmp(out_buf, "this is a pl test") == 0) {
|
||||
ASSERT_EQ(0, 0, "mysql_stmt_fetch");
|
||||
} else {
|
||||
ASSERT_EQ(0, -1, "mysql_stmt_fetch");
|
||||
}
|
||||
}
|
||||
if (mysql_stmt_close(stmt)) {
|
||||
my_log("mysql_stmt_close faield:%s", mysql_stmt_error(stmt));
|
||||
ASSERT_EQ(0, -1, "mysql_stmt_error");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
mysql_library_init(0, NULL, NULL);
|
||||
MYSQL *mysql = mysql_init(NULL);
|
||||
unsigned int timeout = 3000;
|
||||
init_conn_info(OB_ORACLE_MODE);
|
||||
mysql_options(mysql, MYSQL_OPT_CONNECT_TIMEOUT, &timeout);
|
||||
|
||||
if (mysql_real_connect(mysql, DBHOST, DBUSER, DBPASS, DBNAME, DBPORT, DBSOCK, DBPCNT) == NULL)
|
||||
{
|
||||
my_log("connect failed: %s, host:%s, port:%d, user:%s, pass:%s, dbname:%s",
|
||||
mysql_error(mysql),DBHOST, DBPORT, DBUSER, DBPASS, DBNAME);
|
||||
mysql_close(mysql);
|
||||
mysql_library_end();
|
||||
return 0;
|
||||
} else {
|
||||
my_log("connect %s:%d using %s succ", DBHOST, DBPORT, DBUSER);
|
||||
}
|
||||
do_pl_test(mysql);
|
||||
return 0;
|
||||
}
|
||||
@ -163,7 +163,7 @@ int do_stmt_select(MYSQL* mysql) {
|
||||
filed_count = mysql_stmt_field_count(stmt);
|
||||
ASSERT_EQ(filed_count, 4, "mysql_stmt_field_count");
|
||||
my_ulonglong row_count = mysql_stmt_num_rows(stmt);
|
||||
ASSERT_EQ(row_count, 9, "mysql_stmt_field_count");
|
||||
ASSERT_EQ(row_count, 9, "mysql_stmt_num_rows");
|
||||
memset(bind, 0, sizeof(bind));
|
||||
int id, num;
|
||||
char name[20];
|
||||
|
||||
@ -1,15 +0,0 @@
|
||||
#mysql-mode
|
||||
#obclient -h100.88.109.130 -P18815 -uadmin@mysql -padmin -Doceanbase -A
|
||||
export LD_LIBRARY_PATH=../../libmariadb/:$LD_LIBRARY_PATH
|
||||
export OB_MYSQL_SERVER_HOST=100.88.109.130
|
||||
export OB_MYSQL_SERVER_PORT=18815
|
||||
export OB_MYSQL_SERVER_DBNAME="test"
|
||||
export OB_MYSQL_SERVER_USERNAME="admin@mysql"
|
||||
export OB_MYSQL_SERVER_PASSWORD="admin"
|
||||
#oracle-mode
|
||||
#obclient -h100.88.105.197 -P30035 -utest@tt3 -ptest
|
||||
export OB_ORACLE_SERVER_HOST=100.88.105.197
|
||||
export OB_ORACLE_SERVER_PORT=30035
|
||||
export OB_ORACLE_SERVER_DBNAME="test"
|
||||
export OB_ORACLE_SERVER_USERNAME="test@tt3"
|
||||
export OB_ORACLE_SERVER_PASSWORD="test"
|
||||
@ -3,12 +3,11 @@
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <stdarg.h>
|
||||
//obclient -h 11.158.31.35 -usys@oracle -P27701
|
||||
const char* DBHOST = "11.158.31.35";
|
||||
const char* DBUSER = "sys@oracle";
|
||||
const char* DBHOST = "";
|
||||
const char* DBUSER = "";
|
||||
const char* DBPASS = "";
|
||||
unsigned int DBPORT = 27701;
|
||||
const char* DBNAME = "sys";
|
||||
unsigned int DBPORT = 0;
|
||||
const char* DBNAME = "";
|
||||
const char* DBSOCK = NULL; //"/var/lib/mysql/mysql.sock"
|
||||
const unsigned long DBPCNT = 0;
|
||||
#ifdef __cplusplus
|
||||
|
||||
17
unittest/ob20_test/Makefile
Normal file
17
unittest/ob20_test/Makefile
Normal file
@ -0,0 +1,17 @@
|
||||
CFLAGS= -I../../include
|
||||
CCFLAGS= -I../../include
|
||||
LDFLAGS= -g -L ../../libmariadb/ -lobclnt -lz -lpthread -lgtest
|
||||
BIN=ob20_appinfo_test ob20_trans_test ob20_clientinfo_test ob20_slowquery_test ob20_bigpacket_response_test ob20_bigpacket_request_test
|
||||
EXEC=env LD_LIBRARY_PATH=../../libmariadb/:${LD_LIBRARY_PATH}
|
||||
all:${BIN}
|
||||
.PHONY:clean
|
||||
ob20_appinfo_test:ob20_appinfo_test.c
|
||||
ob20_trans_test:ob20_trans_test.c
|
||||
ob20_clientinfo_test:ob20_clientinfo_test.c
|
||||
ob20_slowquery_test:ob20_slowquery_test.c
|
||||
ob20_bigpacket_response_test:ob20_bigpacket_response_test.c
|
||||
ob20_bigpacket_request_test:ob20_bigpacket_request_test.c
|
||||
# run:
|
||||
# $(EXEC) ./ob_oracle_array_binding_test
|
||||
clean:
|
||||
rm -rf ${BIN} *.o
|
||||
73
unittest/ob20_test/ob20_appinfo_test.c
Normal file
73
unittest/ob20_test/ob20_appinfo_test.c
Normal file
@ -0,0 +1,73 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "mysql.h"
|
||||
#include "test_util.h"
|
||||
#include "ob_protocol20.h"
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
mysql_library_init(0, NULL, NULL);
|
||||
MYSQL *mysql = mysql_init(NULL);
|
||||
MYSQL_RES *RES;
|
||||
unsigned int timeout = 3000;
|
||||
if (6 == argc) {
|
||||
DBHOST = argv[1];
|
||||
DBUSER = argv[2];
|
||||
DBPASS = argv[3];
|
||||
DBNAME = argv[4];
|
||||
DBPORT = atoi(argv[5]);
|
||||
|
||||
printf("host is %s, user is %s, pass is %s, name is %s, port is %u\n", DBHOST, DBUSER, DBPASS, DBNAME, DBPORT);
|
||||
}
|
||||
|
||||
if (mysql_real_connect(mysql, DBHOST, DBUSER, DBPASS, DBNAME, DBPORT, DBSOCK, DBPCNT) == NULL)
|
||||
{
|
||||
my_log("connect failed: %s, host:%s, port:%d, user:%s, pass:%s, dbname:%s",
|
||||
mysql_error(mysql),DBHOST, DBPORT, DBUSER, DBPASS, DBNAME);
|
||||
mysql_close(mysql);
|
||||
mysql_library_end();
|
||||
return 0;
|
||||
} else {
|
||||
my_log("connect %s:%d using %s succ", DBHOST, DBPORT, DBUSER);
|
||||
}
|
||||
int ret = 0;
|
||||
|
||||
{
|
||||
const char *module = "mod";
|
||||
const char *action = "act";
|
||||
flt_set_module(mysql, module);
|
||||
flt_set_action(mysql, action);
|
||||
if (mysql_query(mysql, "select 1 from dual where 1 = 0;")) {
|
||||
printf("query one error\n");
|
||||
return 0;
|
||||
} else {
|
||||
RES = mysql_store_result(mysql);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
// const char *module = "module";
|
||||
const char *action = "act1";
|
||||
// flt_set_module(mysql, module);
|
||||
flt_set_action(mysql, action);
|
||||
if (mysql_query(mysql, "select 1 from dual where 1 = 0;")) {
|
||||
printf("query two error\n");
|
||||
return 0;
|
||||
} else {
|
||||
RES = mysql_store_result(mysql);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
const char *identifier = "id1";
|
||||
flt_set_identifier(mysql, identifier);
|
||||
if (mysql_query(mysql, "select 1 from dual where 1 = 0;")) {
|
||||
printf("query four error\n");
|
||||
return 0;
|
||||
} else {
|
||||
RES = mysql_store_result(mysql);
|
||||
}
|
||||
}
|
||||
|
||||
mysql_library_end();
|
||||
return 0;
|
||||
}
|
||||
61
unittest/ob20_test/ob20_bigpacket_request_test.c
Normal file
61
unittest/ob20_test/ob20_bigpacket_request_test.c
Normal file
@ -0,0 +1,61 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "mysql.h"
|
||||
#include "test_util.h"
|
||||
#include "ob_object.h"
|
||||
#include "ob_protocol20.h"
|
||||
#include "ob_full_link_trace.h"
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
mysql_library_init(0, NULL, NULL);
|
||||
MYSQL *mysql = mysql_init(NULL);
|
||||
MYSQL_RES *RES;
|
||||
unsigned int timeout = 3000;
|
||||
char *big_query;
|
||||
size_t big_query_size = 256 * 256 * 256 - 1; // 16M请求
|
||||
|
||||
// init_conn_info(OB_MYSQL_MODE);
|
||||
// mysql_options(mysql, MYSQL_OPT_CONNECT_TIMEOUT, &timeout);
|
||||
if (6 == argc) {
|
||||
DBHOST = argv[1];
|
||||
DBUSER = argv[2];
|
||||
DBPASS = argv[3];
|
||||
DBNAME = argv[4];
|
||||
DBPORT = atoi(argv[5]);
|
||||
|
||||
printf("host is %s, user is %s, pass is %s, name is %s, port is %u\n", DBHOST, DBUSER, DBPASS, DBNAME, DBPORT);
|
||||
}
|
||||
|
||||
if (mysql_real_connect(mysql, DBHOST, DBUSER, DBPASS, DBNAME, DBPORT, DBSOCK, DBPCNT) == NULL)
|
||||
{
|
||||
my_log("connect failed: %s, host:%s, port:%d, user:%s, pass:%s, dbname:%s",
|
||||
mysql_error(mysql),DBHOST, DBPORT, DBUSER, DBPASS, DBNAME);
|
||||
mysql_close(mysql);
|
||||
mysql_library_end();
|
||||
return 0;
|
||||
} else {
|
||||
my_log("connect %s:%d using %s succ", DBHOST, DBPORT, DBUSER);
|
||||
}
|
||||
|
||||
// malloc 16M size query
|
||||
big_query = (char *)malloc(big_query_size);
|
||||
if (NULL == big_query) {
|
||||
printf("malloc error\n");
|
||||
return 0;
|
||||
} else {
|
||||
memset(big_query, 0, big_query_size);
|
||||
memcpy(big_query, "select 1 from dual where 1 = 0;", sizeof("select 1 from dual where 1 = 0;"));
|
||||
}
|
||||
|
||||
{
|
||||
if (mysql_real_query(mysql, big_query, big_query_size)) {
|
||||
printf("query one error, %d, %s\n", mysql_errno(mysql), mysql_error(mysql));
|
||||
return 0;
|
||||
} else {
|
||||
RES = mysql_store_result(mysql);
|
||||
}
|
||||
}
|
||||
|
||||
mysql_library_end();
|
||||
return 0;
|
||||
}
|
||||
57
unittest/ob20_test/ob20_bigpacket_response_test.c
Normal file
57
unittest/ob20_test/ob20_bigpacket_response_test.c
Normal file
@ -0,0 +1,57 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "mysql.h"
|
||||
#include "test_util.h"
|
||||
#include "ob_object.h"
|
||||
#include "ob_protocol20.h"
|
||||
#include "ob_full_link_trace.h"
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
mysql_library_init(0, NULL, NULL);
|
||||
MYSQL *mysql = mysql_init(NULL);
|
||||
MYSQL_RES *RES;
|
||||
unsigned int timeout = 3000;
|
||||
// init_conn_info(OB_MYSQL_MODE);
|
||||
// mysql_options(mysql, MYSQL_OPT_CONNECT_TIMEOUT, &timeout);
|
||||
if (6 == argc) {
|
||||
DBHOST = argv[1];
|
||||
DBUSER = argv[2];
|
||||
DBPASS = argv[3];
|
||||
DBNAME = argv[4];
|
||||
DBPORT = atoi(argv[5]);
|
||||
|
||||
printf("host is %s, user is %s, pass is %s, name is %s, port is %u\n", DBHOST, DBUSER, DBPASS, DBNAME, DBPORT);
|
||||
}
|
||||
|
||||
if (mysql_real_connect(mysql, DBHOST, DBUSER, DBPASS, DBNAME, DBPORT, DBSOCK, DBPCNT) == NULL)
|
||||
{
|
||||
my_log("connect failed: %s, host:%s, port:%d, user:%s, pass:%s, dbname:%s",
|
||||
mysql_error(mysql),DBHOST, DBPORT, DBUSER, DBPASS, DBNAME);
|
||||
mysql_close(mysql);
|
||||
mysql_library_end();
|
||||
return 0;
|
||||
} else {
|
||||
my_log("connect %s:%d using %s succ", DBHOST, DBPORT, DBUSER);
|
||||
}
|
||||
|
||||
{
|
||||
if (mysql_query(mysql, "select * from gv$sql_audit;")) {
|
||||
printf("query one error\n");
|
||||
return 0;
|
||||
} else {
|
||||
RES = mysql_store_result(mysql);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
if (mysql_query(mysql, "select 1 from dual where 1 = 0;")) {
|
||||
printf("query four error\n");
|
||||
return 0;
|
||||
} else {
|
||||
RES = mysql_store_result(mysql);
|
||||
}
|
||||
}
|
||||
|
||||
mysql_library_end();
|
||||
return 0;
|
||||
}
|
||||
51
unittest/ob20_test/ob20_clientinfo_test.c
Normal file
51
unittest/ob20_test/ob20_clientinfo_test.c
Normal file
@ -0,0 +1,51 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "mysql.h"
|
||||
#include "test_util.h"
|
||||
#include "ob_object.h"
|
||||
#include "ob_protocol20.h"
|
||||
#include "ob_full_link_trace.h"
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
mysql_library_init(0, NULL, NULL);
|
||||
MYSQL *mysql = mysql_init(NULL);
|
||||
MYSQL_RES *RES;
|
||||
unsigned int timeout = 3000;
|
||||
// init_conn_info(OB_MYSQL_MODE);
|
||||
// mysql_options(mysql, MYSQL_OPT_CONNECT_TIMEOUT, &timeout);
|
||||
if (6 == argc) {
|
||||
DBHOST = argv[1];
|
||||
DBUSER = argv[2];
|
||||
DBPASS = argv[3];
|
||||
DBNAME = argv[4];
|
||||
DBPORT = atoi(argv[5]);
|
||||
|
||||
printf("host is %s, user is %s, pass is %s, name is %s, port is %u\n", DBHOST, DBUSER, DBPASS, DBNAME, DBPORT);
|
||||
}
|
||||
|
||||
if (mysql_real_connect(mysql, DBHOST, DBUSER, DBPASS, DBNAME, DBPORT, DBSOCK, DBPCNT) == NULL)
|
||||
{
|
||||
my_log("connect failed: %s, host:%s, port:%d, user:%s, pass:%s, dbname:%s",
|
||||
mysql_error(mysql),DBHOST, DBPORT, DBUSER, DBPASS, DBNAME);
|
||||
mysql_close(mysql);
|
||||
mysql_library_end();
|
||||
return 0;
|
||||
} else {
|
||||
my_log("connect %s:%d using %s succ", DBHOST, DBPORT, DBUSER);
|
||||
}
|
||||
|
||||
{
|
||||
const char *client_info = "cli";
|
||||
flt_set_client_info(mysql, client_info);
|
||||
if (mysql_query(mysql, "select 1 from dual where 1 = 0;")) {
|
||||
printf("query one error\n");
|
||||
return 0;
|
||||
} else {
|
||||
RES = mysql_store_result(mysql);
|
||||
sleep(10);
|
||||
}
|
||||
}
|
||||
|
||||
mysql_library_end();
|
||||
return 0;
|
||||
}
|
||||
55
unittest/ob20_test/ob20_slowquery_test.c
Normal file
55
unittest/ob20_test/ob20_slowquery_test.c
Normal file
@ -0,0 +1,55 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "mysql.h"
|
||||
#include "test_util.h"
|
||||
#include "ob_object.h"
|
||||
#include "ob_protocol20.h"
|
||||
#include "ob_full_link_trace.h"
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
mysql_library_init(0, NULL, NULL);
|
||||
MYSQL *mysql = mysql_init(NULL);
|
||||
MYSQL_RES *RES;
|
||||
unsigned int timeout = 3000;
|
||||
if (6 == argc) {
|
||||
DBHOST = argv[1];
|
||||
DBUSER = argv[2];
|
||||
DBPASS = argv[3];
|
||||
DBNAME = argv[4];
|
||||
DBPORT = atoi(argv[5]);
|
||||
|
||||
printf("host is %s, user is %s, pass is %s, name is %s, port is %u\n", DBHOST, DBUSER, DBPASS, DBNAME, DBPORT);
|
||||
}
|
||||
|
||||
if (mysql_real_connect(mysql, DBHOST, DBUSER, DBPASS, DBNAME, DBPORT, DBSOCK, DBPCNT) == NULL)
|
||||
{
|
||||
my_log("connect failed: %s, host:%s, port:%d, user:%s, pass:%s, dbname:%s",
|
||||
mysql_error(mysql),DBHOST, DBPORT, DBUSER, DBPASS, DBNAME);
|
||||
mysql_close(mysql);
|
||||
mysql_library_end();
|
||||
return 0;
|
||||
} else {
|
||||
my_log("connect %s:%d using %s succ", DBHOST, DBPORT, DBUSER);
|
||||
}
|
||||
|
||||
{
|
||||
if (mysql_query(mysql, "select sleep(2) from dual")) {
|
||||
printf("query one error, %s\n", mysql_error(mysql));
|
||||
return 0;
|
||||
} else {
|
||||
RES = mysql_store_result(mysql);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
if (mysql_query(mysql, "commit;")) {
|
||||
printf("query four error, %s\n", mysql_error(mysql));
|
||||
return 0;
|
||||
} else {
|
||||
RES = mysql_store_result(mysql);
|
||||
}
|
||||
}
|
||||
|
||||
mysql_library_end();
|
||||
return 0;
|
||||
}
|
||||
72
unittest/ob20_test/ob20_trans_test.c
Normal file
72
unittest/ob20_test/ob20_trans_test.c
Normal file
@ -0,0 +1,72 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "mysql.h"
|
||||
#include "test_util.h"
|
||||
#include "ob_object.h"
|
||||
#include "ob_protocol20.h"
|
||||
#include "ob_full_link_trace.h"
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
mysql_library_init(0, NULL, NULL);
|
||||
MYSQL *mysql = mysql_init(NULL);
|
||||
MYSQL_RES *RES;
|
||||
unsigned int timeout = 3000;
|
||||
if (6 == argc) {
|
||||
DBHOST = argv[1];
|
||||
DBUSER = argv[2];
|
||||
DBPASS = argv[3];
|
||||
DBNAME = argv[4];
|
||||
DBPORT = atoi(argv[5]);
|
||||
|
||||
printf("host is %s, user is %s, pass is %s, name is %s, port is %u\n", DBHOST, DBUSER, DBPASS, DBNAME, DBPORT);
|
||||
}
|
||||
|
||||
if (mysql_real_connect(mysql, DBHOST, DBUSER, DBPASS, DBNAME, DBPORT, DBSOCK, DBPCNT) == NULL)
|
||||
{
|
||||
my_log("connect failed: %s, host:%s, port:%d, user:%s, pass:%s, dbname:%s",
|
||||
mysql_error(mysql),DBHOST, DBPORT, DBUSER, DBPASS, DBNAME);
|
||||
mysql_close(mysql);
|
||||
mysql_library_end();
|
||||
return 0;
|
||||
} else {
|
||||
my_log("connect %s:%d using %s succ", DBHOST, DBPORT, DBUSER);
|
||||
}
|
||||
|
||||
if (mysql_query(mysql, "create table test_trace(c1 number);")) {
|
||||
printf("query 0 error\n");
|
||||
return 0;
|
||||
} else {
|
||||
RES = mysql_store_result(mysql);
|
||||
}
|
||||
|
||||
{
|
||||
int i = 0;
|
||||
for (; i < 20; ++i) {
|
||||
if (mysql_query(mysql, "insert into test_trace values (1);")) {
|
||||
printf("query one error\n");
|
||||
return 0;
|
||||
} else {
|
||||
RES = mysql_store_result(mysql);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
if (mysql_query(mysql, "commit")) {
|
||||
printf("commit error\n");
|
||||
return 0;
|
||||
} else {
|
||||
RES = mysql_store_result(mysql);
|
||||
}
|
||||
}
|
||||
if (mysql_query(mysql, "drop table test_trace;")) {
|
||||
printf("query one error\n");
|
||||
return 0;
|
||||
} else {
|
||||
RES = mysql_store_result(mysql);
|
||||
}
|
||||
|
||||
mysql_close(mysql);
|
||||
mysql_library_end();
|
||||
return 0;
|
||||
}
|
||||
2
unittest/ob20_test/run.sh
Normal file
2
unittest/ob20_test/run.sh
Normal file
@ -0,0 +1,2 @@
|
||||
export LD_LIBRARY_PATH=../../libmariadb/:${LD_LIBRARY_PATH}
|
||||
./$1
|
||||
100
unittest/ob20_test/test_util.h
Normal file
100
unittest/ob20_test/test_util.h
Normal file
@ -0,0 +1,100 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <stdarg.h>
|
||||
const char* DBHOST = "";
|
||||
const char* DBUSER = "";
|
||||
const char* DBPASS = "";
|
||||
unsigned int DBPORT = 0;
|
||||
const char* DBNAME = "SYS";
|
||||
const char* DBSOCK = NULL; //"/var/lib/mysql/mysql.sock"
|
||||
const unsigned long DBPCNT = 0;
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
enum DB_MODE
|
||||
{
|
||||
OB_MYSQL_MODE = 0,
|
||||
OB_ORACLE_MODE = 1
|
||||
};
|
||||
void init_conn_info(int mode)
|
||||
{
|
||||
const char* env_name = (mode == OB_ORACLE_MODE) ? "OB_ORACLE_SERVER_USERNAME": "OB_MYSQL_SERVER_USERNAME";
|
||||
const char* tmp = getenv(env_name);
|
||||
if (tmp != NULL)
|
||||
{
|
||||
DBUSER = tmp;
|
||||
}
|
||||
env_name = (mode == OB_ORACLE_MODE) ? "OB_ORACLE_SERVER_PASSWORD" : "OB_MYSQL_SERVER_PASSWORD";
|
||||
tmp = getenv(env_name);
|
||||
if (tmp != NULL)
|
||||
{
|
||||
DBPASS = tmp;
|
||||
}
|
||||
env_name = (mode == OB_ORACLE_MODE) ? "OB_ORACLE_SERVER_HOST" : "OB_MYSQL_SERVER_HOST";
|
||||
tmp = getenv(env_name);
|
||||
if (tmp != NULL)
|
||||
{
|
||||
DBHOST = tmp;
|
||||
}
|
||||
env_name = (mode == OB_ORACLE_MODE) ? "OB_ORACLE_SERVER_PORT" : "OB_MYSQL_SERVER_PORT";
|
||||
tmp = getenv(env_name);
|
||||
if (tmp != NULL)
|
||||
{
|
||||
DBPORT = atoi(tmp);
|
||||
}
|
||||
env_name = (mode == OB_ORACLE_MODE) ? "OB_ORACLE_SERVER_DBNAME" : "OB_MYSQL_SERVER_DBNAME";
|
||||
tmp = getenv(env_name);
|
||||
if (tmp != NULL)
|
||||
{
|
||||
DBNAME = tmp;
|
||||
}
|
||||
}
|
||||
const char * getRelativeFileName(const char* file_name)
|
||||
{
|
||||
int j = 0;
|
||||
size_t len = strlen(file_name);
|
||||
if (len <= 2) {
|
||||
printf("too short \n");
|
||||
return file_name;
|
||||
}
|
||||
const char *ptr = file_name;
|
||||
for (j = len - 2; j >=0; j--) {
|
||||
if (ptr[j] == '/')
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
return &ptr[j+1];
|
||||
}
|
||||
#define ASSERT_EQ(a, b, info) assert_internal(__FILE__, __LINE__, __FUNCTION__, a, b, info)
|
||||
void assert_internal(const char* file, int lineno, const char* func, int a, int b, const char* info)
|
||||
{
|
||||
if(a == b){
|
||||
printf("[%s:%s:%d]: %-40s ------- \e[1;0;32;1m PASS \e[0m\n", getRelativeFileName(file), func, lineno, info);
|
||||
}
|
||||
else {
|
||||
printf("[%s:%s:%d]: %-40s------- \e[1;0;31;1m FAILED \e[0m, expected:%d,real:%d\n",
|
||||
getRelativeFileName(file), func, lineno, info, a, b);
|
||||
}
|
||||
}
|
||||
#define my_log(fmt, ...) \
|
||||
my_log_internal(stdout, __FILE__, __LINE__, fmt, ##__VA_ARGS__)
|
||||
|
||||
static void my_log_internal(FILE* fp, const char* file_name, int lineno, const char* fmt, ...) {
|
||||
time_t now = time(NULL);
|
||||
struct tm* local;
|
||||
local = localtime(&now);
|
||||
fprintf(fp, "[%04d-%02d-%02d %02d:%02d:%02d][%s:%d] ", 1900 + local->tm_year, local->tm_mon + 1,
|
||||
local->tm_mday, local->tm_hour, local->tm_min, local->tm_sec, getRelativeFileName(file_name), lineno);
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
vfprintf(fp, fmt, ap);
|
||||
fprintf(fp, "\n");
|
||||
va_end(ap);
|
||||
fflush(fp);
|
||||
}
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@ -7,6 +7,7 @@
|
||||
|
||||
#define ZLIB_INTERNAL
|
||||
#include "zlib.h"
|
||||
#include "string.h"
|
||||
|
||||
/* ===========================================================================
|
||||
Compresses the source buffer into the destination buffer. The level
|
||||
@ -34,6 +35,8 @@ int ZEXPORT compress2 (dest, destLen, source, sourceLen, level)
|
||||
left = *destLen;
|
||||
*destLen = 0;
|
||||
|
||||
memset(&stream, 0, sizeof(stream));
|
||||
|
||||
stream.zalloc = (alloc_func)0;
|
||||
stream.zfree = (free_func)0;
|
||||
stream.opaque = (voidpf)0;
|
||||
|
||||
@ -33,6 +33,8 @@
|
||||
|
||||
#ifdef _WIN32
|
||||
# include <stddef.h>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#if defined(__TURBOC__) || defined(_MSC_VER) || defined(_WIN32)
|
||||
|
||||
@ -7,6 +7,7 @@
|
||||
|
||||
#define ZLIB_INTERNAL
|
||||
#include "zlib.h"
|
||||
#include "string.h"
|
||||
|
||||
/* ===========================================================================
|
||||
Decompresses the source buffer into the destination buffer. *sourceLen is
|
||||
@ -36,6 +37,8 @@ int ZEXPORT uncompress2 (dest, destLen, source, sourceLen)
|
||||
uLong len, left;
|
||||
Byte buf[1]; /* for detection of incomplete stream when *destLen == 0 */
|
||||
|
||||
memset(&stream, 0, sizeof(stream));
|
||||
|
||||
len = *sourceLen;
|
||||
if (*destLen) {
|
||||
left = *destLen;
|
||||
|
||||
Reference in New Issue
Block a user