support protocol ob20 and full link trace

This commit is contained in:
weihao.twh
2022-10-17 16:49:00 +08:00
parent dccacf24d6
commit 4c565b9dd7
77 changed files with 17741 additions and 375 deletions

113
.secignore Normal file
View 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

View File

@ -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

View File

@ -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`

View File

@ -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})

View File

@ -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)

View File

@ -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

View File

@ -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;

View File

@ -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 */

View File

@ -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)

View File

@ -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

View File

@ -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"

View File

@ -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);

View File

@ -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@

View File

@ -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
View 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
View 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
View 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 */

View 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
View 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

View 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
View 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
View 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
View 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
View 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
View 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

View File

@ -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}

View File

@ -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;
}

View File

@ -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;

View File

@ -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(&param->bind_alloc, length);
} else if (param->offset + length > param->buffer_length) {
*param->error= 1;
buffer = (void *)ma_alloc_root(&param->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(&param->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(&param->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;
}
/* }}} */

View File

@ -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
View 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
View 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
View 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

File diff suppressed because it is too large Load Diff

524
libmariadb/ob_object.c Normal file
View 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 */

File diff suppressed because it is too large Load Diff

702
libmariadb/ob_protocol20.c Normal file
View 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
View 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
View 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
View 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
View 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

View 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

View File

@ -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@

View File

@ -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@"

View File

@ -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 */

View File

@ -1 +1 @@
2.0.2
2.2.0

View File

@ -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

View File

@ -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

View File

@ -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

View 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 = &num;
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;
}

View File

@ -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;

View 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;
}

View 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;
}

View 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;
}

View 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 = &num;
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 = &num;
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 = &num;
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 = &num;
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 = &num;
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 = &num;
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;
}

View 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*)&num;
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 = &num;
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;
}

View 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 = &num;
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;
}

View 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;
}

View 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 = &num;
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 = &num;
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 = &num;
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 = &num;
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;
}

View 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;
}

View File

@ -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];

View File

@ -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"

View File

@ -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

View 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

View 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;
}

View 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;
}

View 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;
}

View 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;
}

View 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;
}

View 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;
}

View File

@ -0,0 +1,2 @@
export LD_LIBRARY_PATH=../../libmariadb/:${LD_LIBRARY_PATH}
./$1

View 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

View File

@ -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;

View File

@ -33,6 +33,8 @@
#ifdef _WIN32
# include <stddef.h>
#else
#include <unistd.h>
#endif
#if defined(__TURBOC__) || defined(_MSC_VER) || defined(_WIN32)

View File

@ -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;