From f48ca5c695630d93b1b0c35ec1e525ea81e2926c Mon Sep 17 00:00:00 2001 From: wb-wqs885808 Date: Fri, 22 Sep 2023 11:26:54 +0800 Subject: [PATCH] patch 223 --- CMakeLists.txt | 36 +- include/mariadb_com.h | 55 ++- include/mariadb_stmt.h | 85 +++- include/mariadb_version.h.in | 16 + include/mysql.h | 32 +- include/ob_full_link_trace.h | 48 +- include/ob_protocol20.h | 1 - include/ob_serialize.h | 4 +- libmariadb/CMakeLists.txt | 29 +- libmariadb/ma_net.c | 81 ++-- libmariadb/ma_stmt_codec.c | 418 ++++++++++++++---- libmariadb/mariadb_lib.c | 114 +++-- libmariadb/mariadb_stmt.c | 514 ++++++++++++++++++---- libmariadb/ob_full_link_trace.c | 274 +++++++++--- libmariadb/ob_protocol20.c | 65 +-- libmariadb/ob_serialize.c | 4 +- libmariadb/ob_strtoll10.c | 15 + rpm/libobclient-VER.txt | 2 +- unittest/ob20_test/Makefile | 3 +- unittest/ob20_test/ob20_show_trace_test.c | 79 ++++ 20 files changed, 1498 insertions(+), 377 deletions(-) create mode 100644 unittest/ob20_test/ob20_show_trace_test.c diff --git a/CMakeLists.txt b/CMakeLists.txt index d2748ab..596208c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -34,9 +34,26 @@ ENDFOREACH() SET(CC_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}) SET(CC_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}) -SET(CPACK_PACKAGE_VERSION_MAJOR 20) -SET(CPACK_PACKAGE_VERSION_MINOR 1) -SET(CPACK_PACKAGE_VERSION_PATCH 13) +SET(CPACK_PACKAGE_VERSION_MAJOR 0) +SET(CPACK_PACKAGE_VERSION_MINOR 0) +SET(CPACK_PACKAGE_VERSION_PATCH 0) + +#get rpm version for Win pack and mariadb_version.h.in +SET(CPACK_PACKAGE_VERSION_RPM "1.0.0") +file(STRINGS ./rpm/libobclient-VER.txt STRLIST LIMIT_COUNT 1) +foreach(STR IN LISTS STRLIST) + SET(CPACK_PACKAGE_VERSION_RPM ${STR}) +endforeach(STR) + +string(REPLACE "." ";" VERSION_LIST ${CPACK_PACKAGE_VERSION_RPM}) +list(GET VERSION_LIST 0 CPACK_PACKAGE_VERSION_MAJOR) +list(GET VERSION_LIST 1 CPACK_PACKAGE_VERSION_MINOR) +list(GET VERSION_LIST 2 CPACK_PACKAGE_VERSION_PATCH) +list(LENGTH VERSION_LIST len) +IF(len EQUAL 4) + list(GET VERSION_LIST 3 CPACK_PACKAGE_VERSION_EXTRA) +ENDIF() + SET(CPACK_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}") MATH(EXPR MARIADB_PACKAGE_VERSION_ID "${CPACK_PACKAGE_VERSION_MAJOR} * 10000 + ${CPACK_PACKAGE_VERSION_MINOR} * 100 + @@ -127,6 +144,13 @@ SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -DDBUG_OFF") SET(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} -DDBUG_OFF") SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -DDBUG_OFF") +IF(UNIX) + SET(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -z noexecstack -z now -pie -fPIC -fstack-protector-all") + SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -z noexecstack -z now -pie -fPIC -fstack-protector-all") + SET(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} -z noexecstack -z now -pie -fPIC -fstack-protector-all") + SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -z noexecstack -z now -pie -fPIC -fstack-protector-all") +ENDIF() + IF(CMAKE_COMPILER_IS_GNUCC) INCLUDE(CheckCCompilerFlag) SET(GCC_FLAGS -Wunused -Wlogical-op -Wno-uninitialized -Wall -Wextra -Wformat-security -Wno-init-self -Wwrite-strings -Wshift-count-overflow -Wdeclaration-after-statement -Wno-undef -Wno-unknown-pragmas) @@ -446,12 +470,6 @@ ELSE() 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") diff --git a/include/mariadb_com.h b/include/mariadb_com.h index 38e32e9..3f2a721 100644 --- a/include/mariadb_com.h +++ b/include/mariadb_com.h @@ -378,30 +378,37 @@ enum ObCapabilityFlagShift OBCLIENT_CAP_PROXY_REROUTE_SHIFT, OBCLIENT_CAP_PROXY_SESSION_SYNC_SHIFT, OBCLIENT_CAP_FULL_LINK_TRACE_SHIFT, - OBCLIENT_CAP_PROXY_NEW_EXTRA_INFO_SHIFT + OBCLIENT_CAP_PROXY_NEW_EXTRA_INFO_SHIFT, + OBCLIENT_CAP_PROXY_SESSION_VAR_SYNC_SHIFT, + OBCLIENT_CAP_PROXY_WEAK_STALE_FEEDBACK_SHIFT, + OBCLIENT_CAP_PROXY_FULL_LINK_TRACE_SHOW_TRACE_SHIFT }; -#define OB_TEST_CAPABILITY(cap, tg_cap) (((cap) & (tg_cap)) == (tg_cap)) +#define OBCLIENT_TEST_CAPABILITY(cap, tg_cap) (((cap) & (tg_cap)) == (tg_cap)) #define OBCLIENT_CAP_GET_TYPE(i) (1LL << i) -#define OBCLIENT_CAP_PARTITION_TABLE OBCLIENT_CAP_GET_TYPE(OBCLIENT_CAP_PARTITION_TABLE_SHIFT) -#define OBCLIENT_CAP_CHANGE_USER OBCLIENT_CAP_GET_TYPE(OBCLIENT_CAP_CHANGE_USER_SHIFT) -#define OBCLIENT_CAP_READ_WEAK OBCLIENT_CAP_GET_TYPE(OBCLIENT_CAP_READ_WEAK_SHIFT) -#define OBCLIENT_CAP_CHECKSUM OBCLIENT_CAP_GET_TYPE(OBCLIENT_CAP_CHECKSUM_SHIFT) -#define OBCLIENT_CAP_SAFE_WEAK_READ OBCLIENT_CAP_GET_TYPE(OBCLIENT_CAP_SAFE_WEAK_READ_SHIFT) -#define OBCLIENT_CAP_PRIORITY_HIT OBCLIENT_CAP_GET_TYPE(OBCLIENT_CAP_PRIORITY_HIT_SHIFT) -#define OBCLIENT_CAP_CHECKSUM_SWITCH OBCLIENT_CAP_GET_TYPE(OBCLIENT_CAP_CHECKSUM_SWITCH_SHIFT) -#define OBCLIENT_CAP_OB_PROTOCOL_V2 OBCLIENT_CAP_GET_TYPE(OBCLIENT_CAP_OB_PROTOCOL_V2_SHIFT) +#define OBCLIENT_CAP_PARTITION_TABLE OBCLIENT_CAP_GET_TYPE(OBCLIENT_CAP_PARTITION_TABLE_SHIFT) +#define OBCLIENT_CAP_CHANGE_USER OBCLIENT_CAP_GET_TYPE(OBCLIENT_CAP_CHANGE_USER_SHIFT) +#define OBCLIENT_CAP_READ_WEAK OBCLIENT_CAP_GET_TYPE(OBCLIENT_CAP_READ_WEAK_SHIFT) +#define OBCLIENT_CAP_CHECKSUM OBCLIENT_CAP_GET_TYPE(OBCLIENT_CAP_CHECKSUM_SHIFT) +#define OBCLIENT_CAP_SAFE_WEAK_READ OBCLIENT_CAP_GET_TYPE(OBCLIENT_CAP_SAFE_WEAK_READ_SHIFT) +#define OBCLIENT_CAP_PRIORITY_HIT OBCLIENT_CAP_GET_TYPE(OBCLIENT_CAP_PRIORITY_HIT_SHIFT) +#define OBCLIENT_CAP_CHECKSUM_SWITCH OBCLIENT_CAP_GET_TYPE(OBCLIENT_CAP_CHECKSUM_SWITCH_SHIFT) +#define OBCLIENT_CAP_OB_PROTOCOL_V2 OBCLIENT_CAP_GET_TYPE(OBCLIENT_CAP_OB_PROTOCOL_V2_SHIFT) #define OBCLIENT_CAP_EXTRA_OK_PACKET_FOR_STATISTICS OBCLIENT_CAP_GET_TYPE(OBCLIENT_CAP_EXTRA_OK_PACKET_FOR_STATISTICS_SHIFT) -#define OBCLIENT_CAP_PL_ROUTE OBCLIENT_CAP_GET_TYPE(OBCLIENT_CAP_PL_ROUTE_SHIFT) -#define OBCLIENT_CAP_PROXY_REROUTE OBCLIENT_CAP_GET_TYPE(OBCLIENT_CAP_PROXY_REROUTE_SHIFT) -#define OBCLIENT_CAP_PROXY_SESSION_SYNC OBCLIENT_CAP_GET_TYPE(OBCLIENT_CAP_PROXY_SESSION_SYNC_SHIFT) -#define OBCLIENT_CAP_FULL_LINK_TRACE OBCLIENT_CAP_GET_TYPE(OBCLIENT_CAP_FULL_LINK_TRACE_SHIFT) -#define OBCLIENT_CAP_PROXY_NEW_EXTRA_INFO OBCLIENT_CAP_GET_TYPE(OBCLIENT_CAP_PROXY_NEW_EXTRA_INFO_SHIFT) +#define OBCLIENT_CAP_PL_ROUTE OBCLIENT_CAP_GET_TYPE(OBCLIENT_CAP_PL_ROUTE_SHIFT) +#define OBCLIENT_CAP_PROXY_REROUTE OBCLIENT_CAP_GET_TYPE(OBCLIENT_CAP_PROXY_REROUTE_SHIFT) +#define OBCLIENT_CAP_PROXY_SESSION_SYNC OBCLIENT_CAP_GET_TYPE(OBCLIENT_CAP_PROXY_SESSION_SYNC_SHIFT) +#define OBCLIENT_CAP_FULL_LINK_TRACE OBCLIENT_CAP_GET_TYPE(OBCLIENT_CAP_FULL_LINK_TRACE_SHIFT) +#define OBCLIENT_CAP_PROXY_NEW_EXTRA_INFO OBCLIENT_CAP_GET_TYPE(OBCLIENT_CAP_PROXY_NEW_EXTRA_INFO_SHIFT) +#define OBCLIENT_CAP_PROXY_SESSION_VAR_SYNC OBCLIENT_CAP_GET_TYPE(OBCLIENT_CAP_PROXY_SESSION_VAR_SYNC_SHIFT) +#define OBCLIENT_CAP_PROXY_WEAK_STALE_FEEDBACK OBCLIENT_CAP_GET_TYPE(OBCLIENT_CAP_PROXY_WEAK_STALE_FEEDBACK_SHIFT) +#define OBCLIENT_CAP_PROXY_FULL_LINK_TRACE_SHOW_TRACE OBCLIENT_CAP_GET_TYPE(OBCLIENT_CAP_PROXY_FULL_LINK_TRACE_SHOW_TRACE_SHIFT) static const unsigned long OBPROXY_DEFAULT_CAPABILITY_FLAG = (OBCLIENT_CAP_OB_PROTOCOL_V2 | OBCLIENT_CAP_FULL_LINK_TRACE - | OBCLIENT_CAP_PROXY_NEW_EXTRA_INFO); + | OBCLIENT_CAP_PROXY_NEW_EXTRA_INFO + | OBCLIENT_CAP_PROXY_FULL_LINK_TRACE_SHOW_TRACE); 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) @@ -415,6 +422,22 @@ 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"; + +enum ObClientLobLocatorVersion +{ + OBCLIENT_LOB_LOCATORV1 = 1, + OBCLIENT_LOB_LOCATORV2 = 2, + OBCLIENT_LOB_LOCATOR_ERROR +}; +enum ObCapabilityFlagLob +{ + OBCLIENT_CAP_OB_LOB_LOCATOR_V2 = 0 +}; +#define OBCLIENT_CAP_OB_LOB_LOCATOR_V2 OBCLIENT_CAP_GET_TYPE(OBCLIENT_CAP_OB_LOB_LOCATOR_V2) +static const unsigned long OBCLIENT_CAP_OB_LOB_LOCATOR_V2_FLAG = OBCLIENT_CAP_OB_LOB_LOCATOR_V2; +static const char *const OB_MYSQL_LOB_LOCATOR_V2 = "__ob_client_attribute_capability_flag"; + + typedef enum enum_field_types { MYSQL_TYPE_DECIMAL, MYSQL_TYPE_TINY, MYSQL_TYPE_SHORT, MYSQL_TYPE_LONG, MYSQL_TYPE_FLOAT, MYSQL_TYPE_DOUBLE, diff --git a/include/mariadb_stmt.h b/include/mariadb_stmt.h index 0a53dd4..5f1d03c 100644 --- a/include/mariadb_stmt.h +++ b/include/mariadb_stmt.h @@ -219,6 +219,65 @@ typedef struct ObLobLocator char data_[1]; // rowid + varchar } OB_LOB_LOCATOR; + +typedef struct st_ObClientMemLobCommon +{ + uint32_t magic_; // Keep the old version consistent + uint32_t version_ : 8; + uint32_t type_ : 4; // Persistent/TmpFull/TmpDelta + uint32_t read_only_ : 1; // Whether to write + uint32_t is_inrow_ : 1; + uint32_t is_open_ : 1; // only persist lob could be open + uint32_t is_simple : 1; + uint32_t has_extern : 1; + uint32_t reserved_ : 15; +}ObClientMemLobCommon; +typedef struct st_ObClientMemLobExternHeader +{ + int64_t snapshot_ver_; + uint64_t table_id_; + uint32_t column_idx_; + uint16_t has_tx_info : 1; + uint16_t has_cid_hash : 1; + uint16_t has_view_info : 1; + uint16_t extern_flags_ : 13; + uint16_t rowkey_size_; + uint32_t payload_offset_; + uint32_t payload_size_; +}ObClientMemLobExternHeader; +typedef struct st_ObClientLobCommon +{ + uint32_t version_ : 8; + uint32_t is_init_ : 1; + uint32_t is_empty_ : 1; + uint32_t in_row_ : 1; + uint32_t opt_encrypt_ : 1; + uint32_t opt_compress_ : 1; + uint32_t opt_deduplicate_ : 1; + uint32_t has_content_type_ : 1; + uint32_t use_big_endian_ : 1; + uint32_t is_mem_loc_ : 1; + uint32_t reserve_ : 15; +}ObClientLobCommon; +typedef struct st_ObClientLobData +{ + uint64_t tablet_id_; + uint64_t lob_id_; + uint64_t byte_size_; +}ObClientLobData; +typedef struct ObLobLocatorV2 +{ + ObClientMemLobCommon common; + ObClientMemLobExternHeader extern_header; + char data_[1]; +}OB_LOB_LOCATOR_V2; +uint8_t get_ob_lob_locator_version(void *lob); +int64_t get_ob_lob_payload_data_len(void *lob); +int stmt_get_data_from_lobv2(MYSQL *mysql, void * lob, enum_field_types dty, + int64_t char_offset, int64_t byte_offset, int64_t char_len, int64_t byte_len, char *buf, const int64_t buf_len, int64_t *data_len, int64_t *act_len); + + + typedef struct st_mysqlnd_upsert_result { unsigned int warning_count; @@ -374,7 +433,7 @@ enum enum_ob20_protocol PROTOCOL_OB20_FORCE_CLOSE = 0, PROTOCOL_OB20_AUTO_OPEN, PROTOCOL_OB20_FORCE_OPEN, - PROTOCOL_OB20_FLAY_MAX + PROTOCOL_OB20_FLAG_MAX }; my_bool determine_protocol_ob20(MYSQL *mysql); my_bool get_use_protocol_ob20(MYSQL *mysql); @@ -384,15 +443,37 @@ enum enum_full_link_trace PROTOCOL_FLT_FORCE_CLOSE = 0, PROTOCOL_FLT_AUTO_OPEN, PROTOCOL_FLT_FORCE_OPEN, - PROTOCOL_FLT_FLAY_MAX + PROTOCOL_FLT_FLAG_MAX }; my_bool determine_full_link_trace(MYSQL *mysql); my_bool get_use_full_link_trace(MYSQL *mysql); +enum enum_flt_show_trace +{ + FLT_SHOW_TRACE_FORCE_CLOSE = 0, + FLT_SHOW_TRACE_AUTO_OPEN, + FLT_SHOW_TRACE_FORCE_OPEN, + FLT_SHOW_TRACE_FLAG_MAX +}; +my_bool determine_flt_show_trace(MYSQL *mysql); +my_bool get_use_flt_show_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*/ +enum enum_ob_client_lob_locatorv2 +{ + OB_CLIENT_LOB_LOCATORV2_FORCE_CLOSE = 0, + OB_CLIENT_LOB_LOCATORV2_AUTO_OPEN, + OB_CLIENT_LOB_LOCATORV2_FORCE_OPEN, + OB_CLIENT_LOB_LOCATORV2_FLAY_MAX +}; +my_bool determine_ob_client_lob_locatorv2(MYSQL *mysql); +my_bool get_use_ob_client_lob_locatorv2(MYSQL *mysql); + +my_bool set_nls_format(MYSQL *mysql); + /* add for support bindbyname for plarray */ struct prepare_extend_args_t { diff --git a/include/mariadb_version.h.in b/include/mariadb_version.h.in index e40cbcc..6985ef1 100644 --- a/include/mariadb_version.h.in +++ b/include/mariadb_version.h.in @@ -45,4 +45,20 @@ /* Source information */ #define CC_SOURCE_REVISION "@CC_SOURCE_REVISION@" +#ifndef LIBOBCLIENT_VERSION_MAJOR +#define LIBOBCLIENT_VERSION_MAJOR @CPACK_PACKAGE_VERSION_MAJOR@ +#endif + +#ifndef LIBOBCLIENT_VERSION_MINOR +#define LIBOBCLIENT_VERSION_MINOR @CPACK_PACKAGE_VERSION_MINOR@ +#endif + +#ifndef LIBOBCLIENT_VERSION_PATCH +#define LIBOBCLIENT_VERSION_PATCH @CPACK_PACKAGE_VERSION_PATCH@ +#endif + +#ifndef LIBOBCLIENT_VERSION +#define LIBOBCLIENT_VERSION "@CPACK_PACKAGE_VERSION_RPM@" +#endif + #endif /* _mariadb_version_h_ */ diff --git a/include/mysql.h b/include/mysql.h index eda98d9..f335705 100644 --- a/include/mysql.h +++ b/include/mysql.h @@ -408,10 +408,13 @@ struct st_mysql_options { my_bool can_plarray_bindbyname; my_bool can_use_protocol_ob20; my_bool can_use_full_link_trace; + my_bool can_use_ob_client_lob_locatorv2; + my_bool can_use_flt_show_trace; unsigned long ob_server_version; unsigned long ob_proxy_version; unsigned long capability; // system varaiable } MYSQL; + /** * @brief * For mysql_use_result, an additional buffer is needed to store rows. @@ -424,7 +427,7 @@ struct st_mysql_options { typedef struct st_ob_result_extension { ulong pkt_len; char *pkt_buffer; - MYSQL_FIELD *mysql_fields; + MYSQL_FIELD *mysql_fields; // fieldϢ } OB_RES_EXT; struct st_mysql_trace_info; @@ -522,6 +525,33 @@ typedef struct st_oracle_time int offset_hour, offset_minute; char *tz_name, *tz_abbr; } ORACLE_TIME; + +typedef struct st_ym_object +{ + int ym_year; + int ym_month; + int ym_scale; +}YM_OBJECT; +typedef struct st_ds_object +{ + int ds_day; + int ds_hour; + int ds_minute; + int ds_second; + int ds_frac_second; + int ds_day_scale; + int ds_frac_second_scale; +}DS_OBJECT; +typedef struct st_oracle_interval +{ + unsigned short mysql_type; + char data_symbol; //1:+, -1:- 0, default + union { + struct st_ym_object ym_object; + struct st_ds_object ds_object; + } data_object; +}ORACLE_INTERVAL; + #define AUTO_SEC_PART_DIGITS 39 #endif diff --git a/include/ob_full_link_trace.h b/include/ob_full_link_trace.h index c772edd..6a2c11e 100644 --- a/include/ob_full_link_trace.h +++ b/include/ob_full_link_trace.h @@ -20,7 +20,7 @@ #define _ob_full_link_trace_h #include -#include "ob_object.h" +#include "mysql.h" #include "ma_list.h" #include "ob_thread_key.h" @@ -44,11 +44,12 @@ 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) { \ + if ((TRUE == flt->control_info_.flt_show_trace_enable_) \ + || !(mysql->server_status & SERVER_STATUS_IN_TRANS)) { \ + BEGIN_TRACE(flt); \ + } else { \ /* A reset is required before each begin in the current transaction to prevent insufficient span*/ \ reset_span(flt->trace_); \ - } else { \ - BEGIN_TRACE(flt); \ } \ span = BEGIN_SPAN(flt, span_level); \ SET_TAG(flt, tag_level, tag_str); \ @@ -78,10 +79,8 @@ trace->slow_query_print_ = FALSE; /* Slow query is set to FALSE for each request */ \ flush_first_span(trace); \ } \ - if (mysql->server_status & SERVER_STATUS_IN_TRANS) { \ - /* do nothing */ \ - } else { \ - /* 不在事务中需要结束trace */ \ + if ((TRUE == flt->control_info_.flt_show_trace_enable_) \ + || !(mysql->server_status & SERVER_STATUS_IN_TRANS)) { \ END_TRACE(flt); \ } \ } \ @@ -104,15 +103,20 @@ #define DEFINE_TO_STRING_FUNC_FOR(type) \ int tostring_##type(char *buf, const int64_t buf_len, int64_t *pos, type *src) -// Currently maintains a size of 4k for each trace, which is the size of all space allocated during the entire trace -#define OBTRACE_DEFAULT_BUFFER_SIZE (1L << 12) +// Currently maintains a size of 5k for each trace, which is the size of all space allocated during the entire trace +#define OBTRACE_DEFAULT_BUFFER_SIZE (5 * (1L << 10)) // The current driver free span is 4 #define SPAN_CACHE_COUNT (1L << 2) +// The current driver free span is 4 +#define TAG_CACHE_COUNT (1L << 4) // Since there is currently at most one SPAN, the largest LOG buffer is 1k #define MAX_TRACE_LOG_SIZE (1L << 10) // The current maximum size of the full link after serialization is 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))) +// span cache begin buffer +#define TAG_BUFFER_BEGIN ((2 * MAX_TRACE_LOG_SIZE) + MAX_FLT_SERIALIZE_SIZE) +#define SPAN_BUFFER_BEGIN ((2 * MAX_TRACE_LOG_SIZE) + MAX_FLT_SERIALIZE_SIZE + TAG_CACHE_COUNT * (sizeof(ObTagCtx))) +#define INIT_OFFSET (SPAN_BUFFER_BEGIN + SPAN_CACHE_COUNT * (sizeof(LIST) + sizeof(ObSpanCtx))) #define OBTRACE(flt) get_trace_instance(flt) #define BEGIN_TRACE(flt) (begin_trace(OBTRACE(flt))) @@ -171,14 +175,17 @@ typedef enum enum_fulllinktraceextrainfoid FLT_SAMPLE_PERCENTAGE, FLT_RECORD_POLICY, FLT_PRINT_SAMPLE_PCT, - FLT_SHOW_TRACE_ENABLE, FLT_SLOW_QUERY_THRES, + FLT_SHOW_TRACE_ENABLE, // SPAN_INFO FLT_TRACE_ENABLE = 2030, FLT_FORCE_PRINT, FLT_TRACE_ID, FLT_REF_TYPE, FLT_SPAN_ID, + // FLT_SHOW_TRACE + FLT_DRV_SHOW_TRACE_SPAN = 2050, + FLT_PROXY_SHOW_TRACE_SPAN, FLT_EXTRA_INFO_ID_END } FullLinkTraceExtraInfoId; @@ -196,6 +203,8 @@ typedef enum enum_fulllinktraceextrainfotype FLT_QUERY_INFO, FLT_CONTROL_INFO, FLT_SPAN_INFO, + FLT_TYPE_SHOW_TRACE_SPAN, + FLT_EXTRA_INFO_TYPE_END } FullLinkTraceExtraInfoType; @@ -219,6 +228,8 @@ typedef struct st_fltcontrolinfo RecordPolicy rp_; double print_sample_pct_; int64_t slow_query_threshold_; + + int8_t flt_show_trace_enable_; // enable show trace or not } FLTControlInfo; typedef struct st_fltappinfo @@ -253,6 +264,12 @@ typedef struct st_fltdriverspaninfo const char *client_span_; } FLTDriverSpanInfo; +typedef struct st_showtracespan +{ + FullLinkTraceExtraInfoType type_; + const char *client_span_json_; +} FLTShowTraceSpan; + typedef struct st_fltvaluedata { void *value_data_; @@ -261,6 +278,7 @@ typedef struct st_fltvaluedata typedef struct st_fltinfo { + FLTShowTraceSpan show_trace_span_; FLTDriverSpanInfo client_span_; FLTControlInfo control_info_; FLTAppInfo app_info_; @@ -340,6 +358,7 @@ struct st_obtrace uint64_t seq_; my_bool in_trans_; my_bool trace_enable_; + my_bool show_trace_enable_; my_bool force_print_; my_bool slow_query_print_; FLTInfo *flt; // point to flt struct @@ -349,6 +368,7 @@ struct st_obtrace LIST *current_span_list_; LIST *free_span_list_; ObSpanCtx *last_active_span_; + ObTagCtx free_tag_list_; union { uint8_t policy_; struct { @@ -358,6 +378,8 @@ struct st_obtrace }; uint64_t log_buf_offset_; char *log_buf_; // size is MAX_TRACE_LOG_SIZE + uint64_t show_trace_buf_offset_; + char *show_trace_buf_; // size is MAX_TRACE_LOG_SIZE char *flt_serialize_buf_; // size is MAX_FLT_SERIALIZE_SIZE char data_[0]; // Multi-allocated space to store free span and facilitate subsequent tagging }; @@ -370,6 +392,7 @@ ObSpanCtx* begin_span(ObTrace *trace, uint32_t span_type, uint8_t level, my_bool void end_span(ObTrace *trace, ObSpanCtx *span); void reset_span(ObTrace *trace); void append_tag(ObTrace *trace, ObSpanCtx *span, uint16_t tag_type, const char *str); +void reset_tag(ObTrace *trace, ObSpanCtx *span, ObTagCtx *tag); ObTrace *get_trace_instance(FLTInfo *flt); void flush_first_span(ObTrace *trace); void flush_trace(ObTrace *trace); @@ -379,6 +402,7 @@ 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(showtracespan); // FLT_TYPE_SHOW_TRACE_SPAN DEFINE_FLT_SERIALIZE_FUNC(nosupport); // FLT_EXTRA_INFO_TYPE_END my_bool flt_is_vaild(FLTInfo *flt); diff --git a/include/ob_protocol20.h b/include/ob_protocol20.h index 8971444..d2d9efd 100644 --- a/include/ob_protocol20.h +++ b/include/ob_protocol20.h @@ -24,7 +24,6 @@ #include #include #include -#include #include diff --git a/include/ob_serialize.h b/include/ob_serialize.h index 50db215..236d8ea 100644 --- a/include/ob_serialize.h +++ b/include/ob_serialize.h @@ -128,9 +128,9 @@ int encode_vstr_with_len(char *buf, const int64_t buf_len, int64_t *ppos, const 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); +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, +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) \ diff --git a/libmariadb/CMakeLists.txt b/libmariadb/CMakeLists.txt index cd71250..5205678 100644 --- a/libmariadb/CMakeLists.txt +++ b/libmariadb/CMakeLists.txt @@ -337,6 +337,10 @@ SET(MARIADB_NONBLOCK_SYMBOLS ob_delete_thread_key ob_get_thread_key ob_set_thread_key +#for lobv2 + get_ob_lob_locator_version + get_ob_lob_payload_data_len + stmt_get_data_from_lobv2 ) # handle static plugins @@ -383,7 +387,7 @@ ob_strtoll10.c ob_oracle_format_models.c ob_thread.c ob_serialize.c -#ob_object.c +ob_object.c ob_full_link_trace.c ob_rwlock.c ob_cond.c @@ -540,10 +544,27 @@ IF(WITH_MYSQLCOMPAT) ENDIF() ENDIF() +IF(UNIX) + IF(CMAKE_SYSTEM_NAME MATCHES "FreeBSD" OR APPLE) + SET(OS_SHARED_LIB_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}") + ELSE() + if(${SHARED_LIB_EXTRA_VERSION}) + SET(OS_SHARED_LIB_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}.${CPACK_PACKAGE_VERSION_EXTRA}") + ELSE() + SET(OS_SHARED_LIB_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}") + ENDIF() + ENDIF() + SET_TARGET_PROPERTIES(libobclnt PROPERTIES + OUTPUT_NAME libobclnt + VERSION "${OS_SHARED_LIB_VERSION}" + SOVERSION "${CPACK_PACKAGE_VERSION_MAJOR}") +ENDIF() -SET_TARGET_PROPERTIES(libobclnt PROPERTIES VERSION - ${CPACK_PACKAGE_VERSION_MAJOR} - SOVERSION ${CPACK_PACKAGE_VERSION_MAJOR}) +IF(WIN32) + SET_TARGET_PROPERTIES(libobclnt PROPERTIES VERSION + ${CPACK_PACKAGE_VERSION_MAJOR} + SOVERSION ${CPACK_PACKAGE_VERSION_MAJOR}) +ENDIF() IF(NOT WIN32) SET_TARGET_PROPERTIES(obclnt PROPERTIES OUTPUT_NAME "${LIBMARIADB_STATIC_NAME}") diff --git a/libmariadb/ma_net.c b/libmariadb/ma_net.c index aa9bf34..4d8bb4a 100644 --- a/libmariadb/ma_net.c +++ b/libmariadb/ma_net.c @@ -201,13 +201,14 @@ int ma_net_flush(NET *net) int ma_net_write(NET *net, const uchar *packet, size_t len) { uchar buff[NET_HEADER_SIZE]; + unsigned long max_packet_length = MAX_PACKET_LENGTH; // 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) + while (len >= max_packet_length) { - const ulong max_len= MAX_PACKET_LENGTH; + const ulong max_len= max_packet_length; int3store(buff,max_len); buff[3]= (uchar)net->pkt_nr++; if (ma_net_write_buff(net,(char*) buff,NET_HEADER_SIZE) || @@ -233,6 +234,7 @@ int ma_net_write_command(NET *net, uchar command, size_t buff_size= NET_HEADER_SIZE + 1; size_t length= 1 + len; /* 1 extra byte for command */ int rc; + unsigned long max_packet_length = MAX_PACKET_LENGTH; buff[NET_HEADER_SIZE]= 0; buff[4]=command; @@ -242,26 +244,34 @@ int ma_net_write_command(NET *net, uchar command, update_request_id(&net->ob20protocol->header.request_id); } - if (length >= MAX_PACKET_LENGTH) + if (length >= max_packet_length) { - len= MAX_PACKET_LENGTH - 1; + len= max_packet_length - 1; do { - int3store(buff, MAX_PACKET_LENGTH); - buff[3]= (net->compress) ? 0 : (uchar) (net->pkt_nr++); + int3store(buff, max_packet_length); + if (net->use_ob20protocol) { + buff[3]= (uchar) (net->pkt_nr++); + } else { + buff[3]= (net->compress) ? 0 : (uchar) (net->pkt_nr++); + } if (ma_net_write_buff(net, (char *)buff, buff_size) || ma_net_write_buff(net, packet, len)) return(1); packet+= len; - length-= MAX_PACKET_LENGTH; - len= MAX_PACKET_LENGTH; + length-= max_packet_length; + len= max_packet_length; buff_size= NET_HEADER_SIZE; /* don't send command for further packets */ - } while (length >= MAX_PACKET_LENGTH); + } while (length >= max_packet_length); len= length; } int3store(buff,length); - buff[3]= (net->compress) ? 0 :(uchar) (net->pkt_nr++); + if (net->use_ob20protocol) { + buff[3]= (uchar) (net->pkt_nr++); + } else { + buff[3]= (net->compress) ? 0 : (uchar) (net->pkt_nr++); + } rc= test (ma_net_write_buff(net,(char *)buff, buff_size) || ma_net_write_buff(net,packet,len)); if (!rc && !disable_flush) @@ -292,39 +302,33 @@ static int ma_net_write_buff(NET *net,const char *packet, size_t len) 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,然后结束 + // do nothing } - } - 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 (net->use_ob20protocol && len > left_length && net->buf_length < net->max_packet_size - 1) { - size_t write_len = net->write_pos - net->buff; - size_t resize_len = len + write_len; + if (net->use_ob20protocol && len > left_length && net->max_packet <= MAX_PACKET_LENGTH_WITH_OB20) { + size_t write_len = net->write_pos - net->buff; + size_t resize_len = len + write_len; - if (resize_len >= net->max_packet_size) { - resize_len = net->max_packet_size - 1; - } - if (net_realloc(net, resize_len)) - { - return 1; + if (resize_len >= MAX_PACKET_LENGTH_WITH_OB20) { + resize_len = MAX_PACKET_LENGTH_WITH_OB20; + } + if (net_realloc(net, resize_len)) + { + return 1; + } + net->write_pos += write_len; + left_length=(size_t) (net->buff_end - net->write_pos); } - net->write_pos += write_len; + } + + if (net->max_packet > MAX_PACKET_LENGTH_WITH_OB20 && net->compress && net->use_ob20protocol) { + left_length= (size_t)(MAX_PACKET_LENGTH_WITH_OB20 - (net->write_pos - net->buff)); + } else if (net->max_packet > MAX_PACKET_LENGTH && net->compress) { + left_length= (size_t)(MAX_PACKET_LENGTH - (net->write_pos - net->buff)); + } else { left_length=(size_t) (net->buff_end - net->write_pos); } @@ -342,11 +346,11 @@ 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 */ 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) @@ -805,6 +809,7 @@ ulong ma_net_read(NET *net) net->read_pos[len]=0; /* Safeguard for mysql_use_result */ } #endif + return (ulong)len; } diff --git a/libmariadb/ma_stmt_codec.c b/libmariadb/ma_stmt_codec.c index c0e648e..b2bac13 100644 --- a/libmariadb/ma_stmt_codec.c +++ b/libmariadb/ma_stmt_codec.c @@ -94,6 +94,11 @@ my_bool mysql_ps_subsystem_initialized= 0; ((((val) > (max_range)) || ((val) < (min_range)) ? 1 : 0)) +extern ulong calculate_interval_length(uchar *cp, enum_field_types type); +extern int rewrite_interval(uchar *cp, char *to, const uint to_size, ulong *convert_len, enum_field_types type); +extern ulong calculate_new_time_length_with_nls(MYSQL *mysql, uchar *cp, ulong len, enum_field_types type); +extern ulong rewrite_new_time_with_nls(MYSQL *mysql, uchar *cp, ulong len, char *to, int64_t buf_len, enum_field_types type); + void ma_bmove_upp(register char *dst, register const char *src, register size_t len) { while (len-- != 0) *--dst = *--src; @@ -881,13 +886,26 @@ static void convert_from_float(MYSQL_BIND *r_param, const MYSQL_FIELD *field, fl length= MIN(MAX_DOUBLE_STRING_REP_LENGTH - 1, r_param->buffer_length); - if (field->decimals >= NOT_FIXED_DEC) - { - length= ma_gcvt(val, MY_GCVT_ARG_FLOAT, (int)length, buff, NULL); - } - else - { - length= ma_fcvt(val, field->decimals, buff, NULL); + if (isnan(val)) { + snprintf(buff, length, "%s", "Nan"); + length = 3; + } else if (isinf(val)) { + if (val > 0) { + snprintf(buff, length, "%s", "Inf"); + length = 3; + } else { + snprintf(buff, length, "%s", "-Inf"); + length = 4; + } + } else { + if (field->decimals >= NOT_FIXED_DEC) + { + length = ma_gcvt(val, MY_GCVT_ARG_FLOAT, (int)length, buff, NULL); + } + else + { + length = ma_fcvt(val, field->decimals, buff, NULL); + } } /* check if ZEROFILL flag is active */ @@ -982,13 +1000,26 @@ static void convert_from_double(MYSQL_BIND *r_param, const MYSQL_FIELD *field, d length= MIN(MAX_DOUBLE_STRING_REP_LENGTH - 1, r_param->buffer_length); - if (field->decimals >= NOT_FIXED_DEC) - { - length= ma_gcvt(val, MY_GCVT_ARG_DOUBLE, (int)length, buff, NULL); - } - else - { - length= ma_fcvt(val, field->decimals, buff, NULL); + if (isnan(val)) { + snprintf(buff, length, "%s", "Nan"); + length = 3; + } else if (isinf(val)) { + if (val > 0) { + snprintf(buff, length, "%s", "Inf"); + length = 3; + } else { + snprintf(buff, length, "%s", "-Inf"); + length = 4; + } + } else { + if (field->decimals >= NOT_FIXED_DEC) + { + length = ma_gcvt(val, MY_GCVT_ARG_DOUBLE, (int)length, buff, NULL); + } + else + { + length = ma_fcvt(val, field->decimals, buff, NULL); + } } /* check if ZEROFILL flag is active */ @@ -1122,68 +1153,192 @@ void ps_fetch_oracle_timestamp(MYSQL_BIND *param, uint buffer_length = 0; uint length = net_field_length(row); - UNUSED(field); + switch (param->buffer_type) { + case MYSQL_TYPE_OB_TIMESTAMP_NANO: + case MYSQL_TYPE_OB_TIMESTAMP_WITH_LOCAL_TIME_ZONE: + case MYSQL_TYPE_OB_TIMESTAMP_WITH_TIME_ZONE: { + if (length > 16) { + buffer_length = length - 16 + sizeof(ORACLE_TIME) + 2; + } else { + buffer_length = sizeof(ORACLE_TIME); + } - if (length > 16) { - buffer_length = length - 16 + sizeof(ORACLE_TIME) + 2; - } else { - buffer_length = sizeof(ORACLE_TIME); + if (param->buffer_length < buffer_length) { + *param->length = buffer_length; + *param->error = 1; + *row += length; + } else { + ORACLE_TIME *tm = (ORACLE_TIME *)param->buffer; + uint tz_length = 0; + uint buffer_offset = 0; + uchar *to = *row; + + memset(tm, 0, sizeof(ORACLE_TIME)); + tm->century = (int)(*(char*)to++); + tm->year = (int)(*(char*)to++); + tm->month = (uint)(*to++); + tm->day = (uint)(*to++); + tm->hour = (uint)(*to++); + tm->minute = (uint)(*to++); + tm->second = (uint)(*to++); + + tm->second_part = (ulong)sint4korr(to); + to += 4; + tm->scale = (uint)(*to++); + + buffer_length = buffer_offset = sizeof(ORACLE_TIME); + if (length > 12) { + tm->offset_hour = (int)(*(char*)to++); + tm->offset_minute = (int)(*(char*)to++); + + tz_length = (uint)(*to++); + buffer_length += (tz_length + 1); + if (tz_length > 0 && buffer_offset + tz_length + 1 < param->buffer_length) { + memcpy((char*)param->buffer + buffer_offset, to, tz_length); + tm->tz_name = (char*)param->buffer + buffer_offset; + buffer_offset += tz_length; + *((char*)param->buffer + buffer_offset) = '\0'; + buffer_offset++; + } + to += tz_length; + + tz_length = (uint)(*to++); + buffer_length += (tz_length + 1); + if (tz_length > 0 && buffer_offset + tz_length + 1 < param->buffer_length) { + memcpy((char*)param->buffer + buffer_offset, to, tz_length); + tm->tz_abbr = (char*)param->buffer + buffer_offset; + buffer_offset += tz_length; + *((char*)param->buffer + buffer_offset) = '\0'; + buffer_offset++; + } + to += tz_length; + } + *param->length = buffer_length; + *param->error = param->buffer_length < buffer_length; + *row = to; + } + break; } - - if (param->buffer_length < buffer_length) { - *param->length= buffer_length; - *param->error= 1; + case MYSQL_TYPE_VAR_STRING: + case MYSQL_TYPE_STRING:{ + uchar *buffer = *row; + ulong convert_len = calculate_new_time_length_with_nls(param->mysql, buffer, length, field->type); + *param->length = convert_len; + if (param->buffer_length < convert_len) { + *param->error = 1; + } else { + convert_len = rewrite_new_time_with_nls(param->mysql, buffer, length, param->buffer, (uint)(param->buffer_length), field->type); + *param->length = convert_len; + } *row += length; - } else { - ORACLE_TIME *tm= (ORACLE_TIME *)param->buffer; - uint tz_length = 0; - uint buffer_offset = 0; - uchar *to= *row; - - memset(tm, 0, sizeof(ORACLE_TIME)); - tm->century= (int) (*(char*)to++); - tm->year= (int) (*(char*)to++); - tm->month= (uint) (*to++); - tm->day= (uint) (*to++); - tm->hour= (uint) (*to++); - tm->minute= (uint) (*to++); - tm->second= (uint) (*to++); - - tm->second_part= (ulong) sint4korr(to); - to += 4; - tm->scale = (uint) (*to++); - - buffer_length = buffer_offset = sizeof(ORACLE_TIME); - if (length > 12) { - tm->offset_hour = (int) (*(char*)to++); - tm->offset_minute = (int) (*(char*)to++); - - tz_length = (uint) (*to++); - buffer_length += (tz_length + 1); - if (tz_length > 0 && buffer_offset + tz_length + 1 < param->buffer_length) { - memcpy((char*)param->buffer + buffer_offset, to, tz_length); - tm->tz_name = (char*)param->buffer + buffer_offset; - buffer_offset += tz_length; - *((char*)param->buffer + buffer_offset) = '\0'; - buffer_offset++; + break; + } + default: { + convert_froma_string(param, (char *)*row, length); + *row += length; + break; + } + } +} + +static +void ps_fetch_oracle_interval(MYSQL_BIND *param, const MYSQL_FIELD *field, uchar **row) +{ + uint length = net_field_length(row); + uchar * buffer = *row; + + switch (param->buffer_type) + { + case MYSQL_TYPE_OB_INTERVAL_DS: { + *param->length = sizeof(ORACLE_INTERVAL); + if (length != 14) { + *param->error = 1; + } else { + ORACLE_INTERVAL * interval = (ORACLE_INTERVAL*)param->buffer; + interval->mysql_type = MYSQL_TYPE_OB_INTERVAL_DS; + interval->data_symbol = (buffer[0] > 0 ? -1 : 1); + interval->data_object.ds_object.ds_day = sint4korr(buffer + 1); + interval->data_object.ds_object.ds_hour = buffer[5]; + interval->data_object.ds_object.ds_minute = buffer[6]; + interval->data_object.ds_object.ds_second = buffer[7]; + interval->data_object.ds_object.ds_frac_second = sint4korr(buffer + 8); + interval->data_object.ds_object.ds_day_scale = buffer[12]; + interval->data_object.ds_object.ds_frac_second_scale = buffer[13]; + } + break; + } + case MYSQL_TYPE_OB_INTERVAL_YM: { + *param->length = sizeof(ORACLE_INTERVAL); + if (length != 7) { + *param->error = 1; + } else { + ORACLE_INTERVAL * interval = (ORACLE_INTERVAL*)param->buffer; + interval->mysql_type = MYSQL_TYPE_OB_INTERVAL_YM; + interval->data_symbol = (buffer[0] > 0 ? -1 : 1); + interval->data_object.ym_object.ym_year = sint4korr(buffer + 1); + interval->data_object.ym_object.ym_month = buffer[5]; + interval->data_object.ym_object.ym_scale = buffer[6]; + } + break; + } + case MYSQL_TYPE_VAR_STRING: + case MYSQL_TYPE_STRING: { + ulong convert_len = calculate_interval_length(buffer, field->type); + *param->length = convert_len; + if ((length != 7 && length != 14) || param->buffer_length < convert_len) { + *param->error = 1; + } else { + if (!rewrite_interval(buffer, param->buffer, (uint)(param->buffer_length), &convert_len, field->type)) { + *param->error = 1; } - to += tz_length; - - tz_length = (uint) (*to++); - buffer_length += (tz_length + 1); - if (tz_length > 0 && buffer_offset + tz_length + 1 < param->buffer_length) { - memcpy((char*)param->buffer + buffer_offset, to, tz_length); - tm->tz_abbr = (char*)param->buffer + buffer_offset; - buffer_offset += tz_length; - *((char*)param->buffer + buffer_offset) = '\0'; - buffer_offset++; + *param->length = convert_len; + } + break; + } + default: { + convert_froma_string(param, (char *)*row, length); + break; + } + } + + *row += length; +} + +static +void ps_fetch_oracle_raw(MYSQL_BIND *param, const MYSQL_FIELD *field, uchar **row) +{ + ulong length = net_field_length(row); + uchar * buffer = *row; + UNUSED(field); + + switch (param->buffer_type) + { + case MYSQL_TYPE_OB_RAW: { + convert_froma_string(param, (char *)*row, length); + break; + } + case MYSQL_TYPE_VAR_STRING: + case MYSQL_TYPE_STRING:{ + uchar *to = param->buffer; + uchar *cp = buffer; + uchar *end = buffer + length; + if (param->buffer_length < length * 2) { + *param->error = 1; + } else { + for (; cp < end; cp++, to += 2) { + sprintf((char *)to, "%02X", *((uchar*)cp)); } - to += tz_length; + (*to++) = 0; } - *param->length= buffer_length; - *param->error= param->buffer_length < buffer_length; - *row = to; + *param->length = length * 2; + break; + } + default: { + convert_froma_string(param, (char *)*row, length); + break; } + } + *row += length; } @@ -1277,22 +1432,92 @@ static void fill_ob_lob_locator(OB_LOB_LOCATOR *ob_lob_locator, uchar *row) ob_lob_locator->payload_size_ = uint4korr(row + 36); } + +static void fill_ob_client_mem_lob_common(ObClientMemLobCommon* common, uchar *row) +{ +#define BIT1 0x01 +#define BIT4 0x0F +#define BIT8 0xFF +#define BIT15 0x7FFF + uint32_t tmps = 0; + common->magic_ = uint4korr(row); + tmps = uint4korr(row + 4); + common->version_ = tmps & BIT8; + tmps >>= 8; + common->type_ = tmps & BIT4; + tmps >>= 4; + common->read_only_ = tmps & BIT1; + tmps >>= 1; + common->is_inrow_ = tmps & BIT1; + tmps >>= 1; + common->is_open_ = tmps & BIT1; + tmps >>= 1; + common->is_simple = tmps & BIT1; + tmps >>= 1; + common->has_extern = tmps & BIT1; + tmps >>= 1; + common->reserved_ = tmps & BIT15; +} +static void fill_ob_client_mem_lob_extern_header(ObClientMemLobExternHeader* header, uchar *row) +{ +#define BIT1 0x01 +#define BIT13 0x1FFF + uint16_t tmps = 0; + header->snapshot_ver_ = sint8korr(row); + header->table_id_ = uint8korr(row+8); + header->column_idx_ = uint4korr(row+16); + + tmps = uint2korr(row + 20); + header->has_tx_info = tmps & BIT1; + tmps >>= 1; + header->has_cid_hash = tmps & BIT1; + tmps >>= 1; + header->has_view_info = tmps & BIT1; + tmps >>= 1; + header->extern_flags_ = tmps & BIT13; + + header->rowkey_size_ = uint2korr(row + 22); + header->payload_offset_ = uint4korr(row + 24); + header->payload_size_ = uint4korr(row + 28); +} +static void fill_ob_lob_locator_v2(OB_LOB_LOCATOR_V2 *ob_lob_locator, uchar *row) +{ + fill_ob_client_mem_lob_common(&ob_lob_locator->common, row); + if (ob_lob_locator->common.has_extern){ + fill_ob_client_mem_lob_extern_header(&ob_lob_locator->extern_header, row+sizeof(ObClientMemLobCommon)); + } +} + static void fetch_result_ob_lob(MYSQL_BIND *param, const MYSQL_FIELD *field __attribute__((unused)), uchar **row) { ulong length= net_field_length(row); + ulong copy_length = 0; 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; + ObClientMemLobCommon common; + fill_ob_client_mem_lob_common(&common, *row); + if (common.version_ == OBCLIENT_LOB_LOCATORV1) { + OB_LOB_LOCATOR *ob_lob_locator = (OB_LOB_LOCATOR *)param->buffer; + fill_ob_lob_locator(ob_lob_locator, *row); + + copy_length = MIN(param->buffer_length - MAX_OB_LOB_LOCATOR_HEADER_LENGTH, length - MAX_OB_LOB_LOCATOR_HEADER_LENGTH); + 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; + } else if (common.version_ == OBCLIENT_LOB_LOCATORV2) { + OB_LOB_LOCATOR_V2 *ob_lob_locatorv2 = (OB_LOB_LOCATOR_V2 *)param->buffer; + //for oracle mode, common.has_extern = 1 + fill_ob_lob_locator_v2(ob_lob_locatorv2, *row); + + copy_length = MIN(param->buffer_length - MAX_OB_LOB_LOCATOR_HEADER_LENGTH, length - MAX_OB_LOB_LOCATOR_HEADER_LENGTH); + memcpy(ob_lob_locatorv2->data_, (*row) + MAX_OB_LOB_LOCATOR_HEADER_LENGTH, copy_length); + *param->error = copy_length + MAX_OB_LOB_LOCATOR_HEADER_LENGTH < length; + } } *param->length= length; @@ -2006,6 +2231,32 @@ void ps_fetch_bin(MYSQL_BIND *r_param, } /* }}} */ +static +void ps_fetch_mysql_lob(MYSQL_BIND *r_param, const MYSQL_FIELD *field, unsigned char **row) +{ + ulong length = net_field_length(row); + if (field->charsetnr == 63) + { + ulong field_length = *r_param->length = length; + uchar *current_pos = (*row) + r_param->offset, *end = (*row) + field_length; + size_t copylen = 0; + if (current_pos < end) + { + copylen = end - current_pos; + if (r_param->buffer_length) + memcpy(r_param->buffer, current_pos, MIN(copylen, r_param->buffer_length)); + } + if (copylen < r_param->buffer_length && + (r_param->buffer_type == MYSQL_TYPE_STRING || + r_param->buffer_type == MYSQL_TYPE_JSON)) + ((char *)r_param->buffer)[copylen] = 0; + *r_param->error = copylen > r_param->buffer_length; + } else { + convert_froma_string(r_param, (char *)*row, length); + } + (*row) += length; +} + /* {{{ ps_fetch_result_skip_direct */ static void ps_fetch_result_skip_direct(MYSQL_BIND *r_param, @@ -2083,6 +2334,13 @@ void mysql_init_ps_subsystem(void) mysql_ps_fetch_functions[MYSQL_TYPE_OB_TIMESTAMP_WITH_TIME_ZONE].pack_len = MYSQL_PS_SKIP_RESULT_W_LEN; mysql_ps_fetch_functions[MYSQL_TYPE_OB_TIMESTAMP_WITH_TIME_ZONE].max_len = -1; + mysql_ps_fetch_functions[MYSQL_TYPE_OB_INTERVAL_YM].func = ps_fetch_oracle_interval; + mysql_ps_fetch_functions[MYSQL_TYPE_OB_INTERVAL_YM].pack_len = MYSQL_PS_SKIP_RESULT_W_LEN; + mysql_ps_fetch_functions[MYSQL_TYPE_OB_INTERVAL_YM].max_len = -1; + + mysql_ps_fetch_functions[MYSQL_TYPE_OB_INTERVAL_DS].func = ps_fetch_oracle_interval; + mysql_ps_fetch_functions[MYSQL_TYPE_OB_INTERVAL_DS].pack_len = MYSQL_PS_SKIP_RESULT_W_LEN; + mysql_ps_fetch_functions[MYSQL_TYPE_OB_INTERVAL_DS].max_len = -1; mysql_ps_fetch_functions[MYSQL_TYPE_NEWDATE].func = ps_fetch_string; mysql_ps_fetch_functions[MYSQL_TYPE_NEWDATE].pack_len = MYSQL_PS_SKIP_RESULT_W_LEN; @@ -2096,19 +2354,19 @@ void mysql_init_ps_subsystem(void) mysql_ps_fetch_functions[MYSQL_TYPE_TIMESTAMP].pack_len= MYSQL_PS_SKIP_RESULT_W_LEN; mysql_ps_fetch_functions[MYSQL_TYPE_TIMESTAMP].max_len = 30; - mysql_ps_fetch_functions[MYSQL_TYPE_TINY_BLOB].func = ps_fetch_bin; + mysql_ps_fetch_functions[MYSQL_TYPE_TINY_BLOB].func = ps_fetch_mysql_lob; mysql_ps_fetch_functions[MYSQL_TYPE_TINY_BLOB].pack_len= MYSQL_PS_SKIP_RESULT_STR; mysql_ps_fetch_functions[MYSQL_TYPE_TINY_BLOB].max_len = -1; - mysql_ps_fetch_functions[MYSQL_TYPE_BLOB].func = ps_fetch_bin; + mysql_ps_fetch_functions[MYSQL_TYPE_BLOB].func = ps_fetch_mysql_lob; mysql_ps_fetch_functions[MYSQL_TYPE_BLOB].pack_len = MYSQL_PS_SKIP_RESULT_STR; mysql_ps_fetch_functions[MYSQL_TYPE_BLOB].max_len = -1; - mysql_ps_fetch_functions[MYSQL_TYPE_MEDIUM_BLOB].func = ps_fetch_bin; + mysql_ps_fetch_functions[MYSQL_TYPE_MEDIUM_BLOB].func = ps_fetch_mysql_lob; mysql_ps_fetch_functions[MYSQL_TYPE_MEDIUM_BLOB].pack_len= MYSQL_PS_SKIP_RESULT_STR; mysql_ps_fetch_functions[MYSQL_TYPE_MEDIUM_BLOB].max_len = -1; - mysql_ps_fetch_functions[MYSQL_TYPE_LONG_BLOB].func = ps_fetch_bin; + mysql_ps_fetch_functions[MYSQL_TYPE_LONG_BLOB].func = ps_fetch_mysql_lob; mysql_ps_fetch_functions[MYSQL_TYPE_LONG_BLOB].pack_len = MYSQL_PS_SKIP_RESULT_STR; mysql_ps_fetch_functions[MYSQL_TYPE_LONG_BLOB].max_len = -1; @@ -2173,8 +2431,8 @@ void mysql_init_ps_subsystem(void) 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].func = ps_fetch_oracle_raw; + mysql_ps_fetch_functions[MYSQL_TYPE_OB_RAW].pack_len = MYSQL_PS_SKIP_RESULT_W_LEN; mysql_ps_fetch_functions[MYSQL_TYPE_OB_RAW].max_len = -1; mysql_ps_fetch_functions[MYSQL_TYPE_OBJECT].func = ps_fetch_result_type; diff --git a/libmariadb/mariadb_lib.c b/libmariadb/mariadb_lib.c index 1898f95..1260e7b 100644 --- a/libmariadb/mariadb_lib.c +++ b/libmariadb/mariadb_lib.c @@ -181,7 +181,7 @@ my_bool get_local_ip_port(my_socket fd, char *ip, int iplen, int *port) static void mysql_close_memory(MYSQL *mysql); void read_user_name(char *name); my_bool STDCALL mariadb_reconnect(MYSQL *mysql); -static int cli_report_progress(MYSQL *mysql, uchar *packet, uint length); +// static int cli_report_progress(MYSQL *mysql, uchar *packet, uint length); extern int mysql_client_plugin_init(); extern void mysql_client_plugin_deinit(); @@ -288,7 +288,7 @@ ma_net_safe_read(MYSQL *mysql) NET *net= &mysql->net; ulong len=0; -restart: +// restart: if (net->pvio != 0) len=ma_net_read(net); @@ -310,18 +310,18 @@ ma_net_safe_read(MYSQL *mysql) pos+=2; len-=2; - if (last_errno== 65535 && - ((mariadb_connection(mysql) && (mysql->server_capabilities & CLIENT_PROGRESS)) || - (!(mysql->extension->mariadb_server_capabilities & MARIADB_CLIENT_PROGRESS << 32)))) - { - if (cli_report_progress(mysql, (uchar *)pos, (uint) (len-1))) - { - /* Wrong packet */ - my_set_error(mysql, CR_MALFORMED_PACKET, SQLSTATE_UNKNOWN, 0); - return (packet_error); - } - goto restart; - } + // if (last_errno== 65535 && + // ((mariadb_connection(mysql) && (mysql->server_capabilities & CLIENT_PROGRESS)) || + // (!(mysql->extension->mariadb_server_capabilities & MARIADB_CLIENT_PROGRESS << 32)))) + // { + // if (cli_report_progress(mysql, (uchar *)pos, (uint) (len-1))) + // { + // /* Wrong packet */ + // my_set_error(mysql, CR_MALFORMED_PACKET, SQLSTATE_UNKNOWN, 0); + // return (packet_error); + // } + // goto restart; + // } net->last_errno= last_errno; if (pos[0]== '#') { @@ -354,31 +354,31 @@ ma_net_safe_read(MYSQL *mysql) 0 ok 1 error */ -static int cli_report_progress(MYSQL *mysql, uchar *packet, uint length) -{ - uint stage, max_stage, proc_length; - double progress; - uchar *start= packet; - - if (length < 5) - return 1; /* Wrong packet */ - - if (!(mysql->options.extension && mysql->options.extension->report_progress)) - return 0; /* No callback, ignore packet */ - - packet++; /* Ignore number of strings */ - stage= (uint) *packet++; - max_stage= (uint) *packet++; - progress= uint3korr(packet)/1000.0; - packet+= 3; - proc_length= net_field_length(&packet); - if (packet + proc_length > start + length) - return 1; /* Wrong packet */ - (*mysql->options.extension->report_progress)(mysql, stage, max_stage, - progress, (char*) packet, - proc_length); - return 0; -} +// static int cli_report_progress(MYSQL *mysql, uchar *packet, uint length) +// { +// uint stage, max_stage, proc_length; +// double progress; +// uchar *start= packet; + +// if (length < 5) +// return 1; /* Wrong packet */ + +// if (!(mysql->options.extension && mysql->options.extension->report_progress)) +// return 0; /* No callback, ignore packet */ + +// packet++; /* Ignore number of strings */ +// stage= (uint) *packet++; +// max_stage= (uint) *packet++; +// progress= uint3korr(packet)/1000.0; +// packet+= 3; +// proc_length= net_field_length(&packet); +// if (packet + proc_length > start + length) +// return 1; /* Wrong packet */ +// (*mysql->options.extension->report_progress)(mysql, stage, max_stage, +// progress, (char*) packet, +// proc_length); +// return 0; +// } /* Get the length of next field. Change parameter to point at fieldstart */ ulong @@ -1022,7 +1022,8 @@ unpack_fields(const MYSQL *mysql, if (0 == len) { field->owner_name = NULL; } else { - field->owner_name = (unsigned char *)ma_memdup_root(alloc, (char*)complex_type, len); + field->owner_name = (unsigned char *)ma_memdup_root(alloc, (char*)complex_type, len+1); + field->owner_name[len] = 0; complex_type += len; } @@ -1031,7 +1032,8 @@ unpack_fields(const MYSQL *mysql, if (0 == len) { field->type_name = NULL; } else { - field->type_name = (unsigned char *)ma_memdup_root(alloc, (char*)complex_type, len); + field->type_name = (unsigned char *)ma_memdup_root(alloc, (char*)complex_type, len+1); + field->type_name[len] = 0; complex_type += len; } @@ -1834,7 +1836,7 @@ int mthd_my_read_one_row(MYSQL *mysql,uint fields,MYSQL_ROW row, ulong *lengths) if (NULL == mysql_fields) { return 1; } - + for (field=0 ; field < fields ; field++) { if ((len=(ulong) net_field_length(&cp)) == NULL_LENGTH) { continue; @@ -1947,7 +1949,7 @@ int mthd_my_read_one_row(MYSQL *mysql,uint fields,MYSQL_ROW row, ulong *lengths) if (mysql_fields[field].max_length < len) mysql_fields[field].max_length=len; } - } + } } else { for (field=0 ; field < fields ; field++) { @@ -2114,15 +2116,23 @@ char *ma_send_connect_attr(MYSQL *mysql, unsigned char *buffer) static my_bool ma_set_ob_connect_attrs(MYSQL *mysql) { +#define OB_MAX_UINT64_BUF_LEN 128 int rc = 0; uint64_t cap = OBPROXY_DEFAULT_CAPABILITY_FLAG; - char cap_buf[OB_MAX_UINT64_BUF_LEN]; + char cap_buf[OB_MAX_UINT64_BUF_LEN] = {0}; + uint64_t caplob = 0; + char caplob_buf[OB_MAX_UINT64_BUF_LEN] = {0}; if (mysql->can_use_protocol_ob20) { cap |= OBCLIENT_CAP_OB_PROTOCOL_V2; cap |= OBCLIENT_CAP_PROXY_NEW_EXTRA_INFO; if (mysql->can_use_full_link_trace) { cap |= OBCLIENT_CAP_FULL_LINK_TRACE; + if (mysql->can_use_flt_show_trace) { + cap |= OBCLIENT_CAP_PROXY_FULL_LINK_TRACE_SHOW_TRACE; + } else { + cap &= ~OBCLIENT_CAP_PROXY_FULL_LINK_TRACE_SHOW_TRACE; + } } else { cap &= ~OBCLIENT_CAP_FULL_LINK_TRACE; } @@ -2130,6 +2140,7 @@ ma_set_ob_connect_attrs(MYSQL *mysql) cap &= ~OBCLIENT_CAP_OB_PROTOCOL_V2; cap &= ~OBCLIENT_CAP_FULL_LINK_TRACE; cap &= ~OBCLIENT_CAP_PROXY_NEW_EXTRA_INFO; + cap &= ~OBCLIENT_CAP_PROXY_FULL_LINK_TRACE_SHOW_TRACE; } snprintf(cap_buf, OB_MAX_UINT64_BUF_LEN, "%lu", cap); @@ -2137,6 +2148,11 @@ ma_set_ob_connect_attrs(MYSQL *mysql) rc += mysql_optionsv(mysql, MYSQL_OPT_CONNECT_ATTR_ADD, OB_MYSQL_CAPABILITY_FLAG, cap_buf); rc += mysql_optionsv(mysql, MYSQL_OPT_CONNECT_ATTR_ADD, OB_MYSQL_CLIENT_MODE, "__ob_libobclient"); + if (mysql->can_use_ob_client_lob_locatorv2) { + caplob |= OBCLIENT_CAP_OB_LOB_LOCATOR_V2; + snprintf(caplob_buf, OB_MAX_UINT64_BUF_LEN, "%lu", caplob); + rc += mysql_optionsv(mysql, MYSQL_OPT_CONNECT_ATTR_ADD, OB_MYSQL_LOB_LOCATOR_V2, caplob_buf); + } return rc; } @@ -2670,6 +2686,8 @@ MYSQL *mthd_my_real_connect(MYSQL *mysql, const char *host, const char *user, // check env variable to determine if use ob20 determine_protocol_ob20(mysql); determine_full_link_trace(mysql); + determine_ob_client_lob_locatorv2(mysql); + determine_flt_show_trace(mysql); if (run_plugin_auth(mysql, scramble_data, scramble_len, scramble_plugin, db)) @@ -2706,8 +2724,14 @@ MYSQL *mthd_my_real_connect(MYSQL *mysql, const char *host, const char *user, } if (get_ob_server_version(mysql)) { // select version errro - goto error; + // goto error; + } + + if (!set_nls_format(mysql)) { + // goto error; + // do nothing } + determine_use_prepare_execute(mysql); determine_send_plarray_maxrarr_len(mysql); determine_plarray_bindbyname(mysql); diff --git a/libmariadb/mariadb_stmt.c b/libmariadb/mariadb_stmt.c index a28c958..f3f57b3 100644 --- a/libmariadb/mariadb_stmt.c +++ b/libmariadb/mariadb_stmt.c @@ -771,7 +771,7 @@ int STDCALL mysql_stmt_fetch_oracle_buffered_result(MYSQL_STMT *stmt) return(1); } /* just read the buffered result for some situation, not to fetch the result from ObServer any more */ - if (rc = stmt_buffered_fetch(stmt, &row)) + if ((rc = stmt_buffered_fetch(stmt, &row))) { stmt->state= MYSQL_STMT_FETCH_DONE; stmt->mysql->status= MYSQL_STATUS_READY; @@ -1286,28 +1286,107 @@ static void store_param_str(MYSQL_STMT *stmt, int column, unsigned char **pos, u store_param_str_complex(pos, &header); } +static void ob_client_mem_lob_common_to_buff(unsigned char** pos, uint32_t *len, ObClientMemLobCommon* common) +{ + uint32_t tmps = 0; + int4store(*pos, common->magic_); + *pos += 4; *len -= 4; + tmps <<= 15; + tmps |= common->reserved_; + tmps <<= 1; + tmps |= common->has_extern; + tmps <<= 1; + tmps |= common->is_simple; + tmps <<= 1; + tmps |= common->is_open_; + tmps <<= 1; + tmps |= common->is_inrow_; + tmps <<= 1; + tmps |= common->read_only_; + tmps <<= 4; + tmps |= common->type_; + tmps <<= 8; + tmps |= common->version_; + int4store(*pos, tmps); + *pos += 4; *len -= 4; +} +static void ob_client_mem_lob_extern_header_to_buff(unsigned char** pos, uint32_t *len, ObClientMemLobExternHeader *header) +{ + uint16_t tmps = 0; + int8store(*pos, header->snapshot_ver_); + *pos += 8; *len -= 8; + int8store(*pos, header->table_id_); + *pos += 8; *len -= 8; + int4store(*pos, header->column_idx_); + *pos += 4; *len -= 4; + + tmps <<= 13; + tmps |= header->extern_flags_; + tmps <<= 1; + tmps |= header->has_view_info; + tmps <<= 1; + tmps |= header->has_cid_hash; + tmps <<= 1; + tmps |= header->has_tx_info; + int2store(*pos, tmps); + *pos += 2; *len -= 2; + + int2store(*pos, header->rowkey_size_); + *pos += 2; *len -= 2; + int4store(*pos, header->payload_offset_); + *pos += 4; *len -= 4; + int4store(*pos, header->payload_size_); + *pos += 4; *len -= 4; +} +static void store_ob_lob_locator_v2(unsigned char** pos, uint32_t* len, OB_LOB_LOCATOR_V2* ob_lob_locator) { + ob_client_mem_lob_common_to_buff(pos, len, &ob_lob_locator->common); + if (ob_lob_locator->common.has_extern) { + ob_client_mem_lob_extern_header_to_buff(pos, len, &ob_lob_locator->extern_header); + } +} +static void store_ob_lob_locator_v1(unsigned char** pos, uint32_t *len, OB_LOB_LOCATOR* lob_locator){ + int4store(*pos, lob_locator->magic_code_); + *pos += 4; *len -= 4; + int4store(*pos, lob_locator->version_); + *pos += 4; *len -= 4; + int8store(*pos, lob_locator->snapshot_version_); + *pos += 8; *len -= 8; + int8store(*pos, lob_locator->table_id_); + *pos += 8; *len -= 8; + int4store(*pos, lob_locator->column_id_); + *pos += 4; *len -= 4; + int2store(*pos, lob_locator->mode_); + *pos += 2; *len -= 2; + int2store(*pos, lob_locator->option_); + *pos += 2; *len -= 2; + int4store(*pos, lob_locator->payload_offset_); + *pos += 4; *len -= 4; + int4store(*pos, lob_locator->payload_size_); + *pos += 4; *len -= 4; +} + static void store_param_ob_lob_complex(unsigned char **pos, MYSQL_COMPLEX_BIND_HEADER *param) { OB_LOB_LOCATOR *lob_locator = (OB_LOB_LOCATOR *) param->buffer; - uchar buff[MAX_OB_LOB_LOCATOR_HEADER_LENGTH]; - - *pos = mysql_net_store_length(*pos, MAX_OB_LOB_LOCATOR_HEADER_LENGTH + lob_locator->payload_size_ + lob_locator->payload_offset_); - - int4store(buff, lob_locator->magic_code_); - int4store(buff + 4, lob_locator->version_); - int8store(buff + 8, lob_locator->snapshot_version_); - int8store(buff + 16, lob_locator->table_id_); - int4store(buff + 24, lob_locator->column_id_); - int2store(buff + 28, lob_locator->mode_); - int2store(buff + 30, lob_locator->option_); - int4store(buff + 32, lob_locator->payload_offset_); - int4store(buff + 36, lob_locator->payload_size_); - - memcpy((char *)*pos, buff, MAX_OB_LOB_LOCATOR_HEADER_LENGTH); - *pos += MAX_OB_LOB_LOCATOR_HEADER_LENGTH; + uint8_t version = get_ob_lob_locator_version(lob_locator); + if (version == OBCLIENT_LOB_LOCATORV1) { + uint32_t len = MAX_OB_LOB_LOCATOR_HEADER_LENGTH; + *pos = mysql_net_store_length(*pos, MAX_OB_LOB_LOCATOR_HEADER_LENGTH + lob_locator->payload_size_ + lob_locator->payload_offset_); + + store_ob_lob_locator_v1(pos, &len, lob_locator); + + memcpy((char *)*pos, lob_locator->data_, lob_locator->payload_size_ + lob_locator->payload_offset_); + *pos += lob_locator->payload_size_ + lob_locator->payload_offset_; + } else if (version == OBCLIENT_LOB_LOCATORV2) { + uint32_t len = MAX_OB_LOB_LOCATOR_HEADER_LENGTH; + OB_LOB_LOCATOR_V2 *lob_locatorv2 = (OB_LOB_LOCATOR_V2 *)param->buffer; + *pos = mysql_net_store_length(*pos, MAX_OB_LOB_LOCATOR_HEADER_LENGTH + lob_locatorv2->extern_header.payload_size_ + lob_locatorv2->extern_header.payload_offset_); + + store_ob_lob_locator_v2(pos, &len, lob_locatorv2); - memcpy((char *)*pos, lob_locator->data_, lob_locator->payload_size_ + lob_locator->payload_offset_); - *pos += lob_locator->payload_size_ + lob_locator->payload_offset_; + memcpy((char *)*pos, lob_locatorv2->data_, lob_locatorv2->extern_header.payload_size_ + lob_locatorv2->extern_header.payload_offset_); + *pos += lob_locatorv2->extern_header.payload_size_ + lob_locatorv2->extern_header.payload_offset_; + } } static void store_param_ob_lob(MYSQL_STMT *stmt, int column, unsigned char **pos, unsigned long row_nr) @@ -1941,8 +2020,14 @@ static ulong calculate_param_ob_lob_len(MYSQL_BIND *param) if (NULL != param->buffer) { OB_LOB_LOCATOR *ob_lob_locator= (OB_LOB_LOCATOR *) param->buffer; - len = MAX_OB_LOB_LOCATOR_HEADER_LENGTH + ob_lob_locator->payload_offset_ + ob_lob_locator->payload_size_; - len += mysql_store_length_size(len); + if (OBCLIENT_LOB_LOCATORV1 == get_ob_lob_locator_version(ob_lob_locator)) { + len = MAX_OB_LOB_LOCATOR_HEADER_LENGTH + ob_lob_locator->payload_offset_ + ob_lob_locator->payload_size_; + len += mysql_store_length_size(len); + } else if (OBCLIENT_LOB_LOCATORV2 == get_ob_lob_locator_version(ob_lob_locator)) { + OB_LOB_LOCATOR_V2 *ob_lob_locatorv2 = (OB_LOB_LOCATOR_V2*)param->buffer; + len = MAX_OB_LOB_LOCATOR_HEADER_LENGTH + ob_lob_locatorv2->extern_header.payload_offset_ + ob_lob_locatorv2->extern_header.payload_size_; + len += mysql_store_length_size(len); + } } return len; } @@ -2924,6 +3009,7 @@ int STDCALL mysql_stmt_fetch_column(MYSQL_STMT *stmt, MYSQL_BIND *bind, unsigned bind[0].error= &bind[0].error_value; *bind[0].error= 0; bind[0].offset= offset; + bind[0].mysql = stmt->mysql; save_ptr= stmt->bind[column].u.row_ptr; if (bind->piece_data_used) fetch_result_with_piece(&bind[0], &stmt->fields[column], &stmt->bind[column].u.row_ptr); @@ -3050,6 +3136,7 @@ int STDCALL mysql_stmt_prepare(MYSQL_STMT *stmt, const char *query, unsigned lon { MYSQL *mysql= stmt->mysql; int rc= 1; + int ret = 0; my_bool is_multi= 0; FLT_DECLARE; @@ -3099,8 +3186,13 @@ int STDCALL mysql_stmt_prepare(MYSQL_STMT *stmt, const char *query, unsigned lon FLT_BEFORE_COMMAND(0, FLT_TAG_COMMAND_NAME, "\"mysql_stmt_prepare\""); - if (mysql->methods->db_command(mysql, COM_STMT_PREPARE, query, length, 1, stmt)) + ret = mysql->methods->db_command(mysql, COM_STMT_PREPARE, query, length, 1, stmt); + // end trace + FLT_AFTER_COMMAND; + + if (ret) { goto fail; + } if (!is_multi && mysql->net.extension->multi_status == COM_MULTI_ENABLED && FALSE == get_use_protocol_ob20(mysql)) ma_multi_command(mysql, COM_MULTI_END); @@ -3157,10 +3249,7 @@ int STDCALL mysql_stmt_prepare(MYSQL_STMT *stmt, const char *query, unsigned lon } stmt->state = MYSQL_STMT_PREPARED; - // end trace - FLT_AFTER_COMMAND; - - return(0); + return(0); fail: stmt->state= MYSQL_STMT_INITTED; @@ -4538,35 +4627,24 @@ my_bool determine_send_plarray_maxrarr_len(MYSQL *mysql) char* env = getenv("ENABLE_PLARRAY_MAXRARRLEN"); if (env) { tmp_val = atoi(env); - if (tmp_val >= 0 && tmp_val < SEND_PLARRAY_MAXRARRLEN_FLAG_MAX) - { + if (tmp_val >= 0 && tmp_val < SEND_PLARRAY_MAXRARRLEN_FLAG_MAX) { ival = tmp_val; } } - if (ival == SEND_PLARRAY_MAXRARRLEN_FORCE_OPEN) - { + if (ival == SEND_PLARRAY_MAXRARRLEN_FORCE_OPEN) { bret = TRUE; - } - else if (ival == SEND_PLARRAY_MAXRARRLEN_FORCE_CLOSE) - { + } else if (ival == SEND_PLARRAY_MAXRARRLEN_FORCE_CLOSE) { bret = FALSE; - } - else if (NULL != mysql) - { - if (!mysql->oracle_mode) - { + } else if (NULL != mysql) { + if (!mysql->oracle_mode) { // only oracle mode use new protocol - } - else - { - if (mysql->ob_server_version >= SUPPORT_SEND_PLARRAY_MAXRARR_LEN) - { + } else { + if (mysql->ob_server_version >= SUPPORT_SEND_PLARRAY_MAXRARR_LEN) { bret = TRUE; } } } - if (mysql) - { + if (mysql) { mysql->can_send_plarray_maxrarr_len = bret; } DBUG_RETURN(bret); @@ -4574,8 +4652,7 @@ my_bool determine_send_plarray_maxrarr_len(MYSQL *mysql) my_bool get_support_send_plarray_maxrarr_len(MYSQL *mysql) { - if (mysql) - { + if (mysql) { return mysql->can_send_plarray_maxrarr_len; } return FALSE; @@ -4592,35 +4669,24 @@ my_bool determine_plarray_bindbyname(MYSQL *mysql) char* env = getenv("ENABLE_PLARRAY_BINDBYNAME"); if (env) { tmp_val = atoi(env); - if (tmp_val >= 0 && tmp_val < PLARRAY_BINDBYNAME_FLAG_MAX) - { + if (tmp_val >= 0 && tmp_val < PLARRAY_BINDBYNAME_FLAG_MAX) { ival = tmp_val; } } - if (ival == PLARRAY_BINDBYNAME_FORCE_OPEN) - { + if (ival == PLARRAY_BINDBYNAME_FORCE_OPEN) { bret = TRUE; - } - else if (ival == PLARRAY_BINDBYNAME_FORCE_CLOSE) - { + } else if (ival == PLARRAY_BINDBYNAME_FORCE_CLOSE) { bret = FALSE; - } - else if (NULL != mysql) - { - if (!mysql->oracle_mode) - { + } else if (NULL != mysql) { + if (!mysql->oracle_mode) { // only oracle mode use new protocol - } - else - { - if (mysql->ob_server_version >= SUPPORT_PLARRAY_BINDBYNAME) - { + } else { + if (mysql->ob_server_version >= SUPPORT_PLARRAY_BINDBYNAME) { bret = TRUE; } } } - if (mysql) - { + if (mysql) { mysql->can_plarray_bindbyname = bret; } DBUG_RETURN(bret); @@ -4628,8 +4694,7 @@ my_bool determine_plarray_bindbyname(MYSQL *mysql) my_bool get_support_plarray_bindbyname(MYSQL *mysql) { - if (mysql) - { + if (mysql) { return mysql->can_plarray_bindbyname; } return FALSE; @@ -4647,21 +4712,16 @@ my_bool determine_protocol_ob20(MYSQL *mysql) char* env = getenv("ENABLE_PROTOCOL_OB20"); if (env) { tmp_val = atoi(env); - if (tmp_val >= 0 && tmp_val < PROTOCOL_OB20_FLAY_MAX) - { + if (tmp_val >= 0 && tmp_val < PROTOCOL_OB20_FLAG_MAX) { ival = tmp_val; } } - if (ival == PROTOCOL_OB20_FORCE_OPEN) - { + if (ival == PROTOCOL_OB20_FORCE_OPEN) { bret = TRUE; - } - else if (ival == PROTOCOL_OB20_FORCE_CLOSE) - { + } else if (ival == PROTOCOL_OB20_FORCE_CLOSE) { bret = FALSE; } - if (mysql) - { + if (mysql) { mysql->can_use_protocol_ob20 = bret; } DBUG_RETURN(bret); @@ -4684,21 +4744,16 @@ my_bool determine_full_link_trace(MYSQL *mysql) char* env = getenv("ENABLE_FLT"); if (env) { tmp_val = atoi(env); - if (tmp_val >= 0 && tmp_val < PROTOCOL_FLT_FLAY_MAX) - { + if (tmp_val >= 0 && tmp_val < PROTOCOL_FLT_FLAG_MAX) { ival = tmp_val; } } - if (ival == PROTOCOL_FLT_FORCE_OPEN) - { + if (ival == PROTOCOL_FLT_FORCE_OPEN) { bret = TRUE; - } - else if (ival == PROTOCOL_FLT_FORCE_CLOSE) - { + } else if (ival == PROTOCOL_FLT_FORCE_CLOSE) { bret = FALSE; } - if (mysql) - { + if (mysql) { mysql->can_use_full_link_trace = bret; } DBUG_RETURN(bret); @@ -4717,6 +4772,287 @@ my_bool get_use_full_link_trace(MYSQL *mysql) } return bret; } + +my_bool determine_flt_show_trace(MYSQL *mysql) +{ + my_bool bret = TRUE; + int ival = FLT_SHOW_TRACE_AUTO_OPEN; //default is AUTO + int tmp_val = 0; + char* env = getenv("ENABLE_FLT_SHOW_TRACE"); + if (env) { + tmp_val = atoi(env); + if (tmp_val >= 0 && tmp_val < FLT_SHOW_TRACE_FLAG_MAX) { + ival = tmp_val; + } + } + if (ival == FLT_SHOW_TRACE_FORCE_OPEN) { + bret = TRUE; + } else if (ival == FLT_SHOW_TRACE_FORCE_CLOSE) { + bret = FALSE; + } + if (mysql) { + mysql->can_use_flt_show_trace = bret; + } + DBUG_RETURN(bret); +} + +my_bool get_use_flt_show_trace(MYSQL *mysql) +{ + my_bool bret = FALSE; + if (mysql && (mysql->capability & OBCLIENT_CAP_FULL_LINK_TRACE) + && (mysql->capability & OBCLIENT_CAP_PROXY_NEW_EXTRA_INFO)) { + bret = TRUE; + if (mysql->capability & OBCLIENT_CAP_PROXY_FULL_LINK_TRACE_SHOW_TRACE) { + // do nothing, bret = TRUE; + } else { + bret = FALSE; + } + } + return bret; +} + +my_bool determine_ob_client_lob_locatorv2(MYSQL *mysql) +{ + my_bool bret = TRUE; + int ival = OB_CLIENT_LOB_LOCATORV2_AUTO_OPEN; //default is AUTO + int tmp_val = 0; + char* env = getenv("ENABLE_OB_CLIENT_LOB_LOCATORV2"); + if (env) { + tmp_val = atoi(env); + if (tmp_val >= 0 && tmp_val < OB_CLIENT_LOB_LOCATORV2_FLAY_MAX) { + ival = tmp_val; + } + } + if (ival == OB_CLIENT_LOB_LOCATORV2_FORCE_OPEN) { + bret = TRUE; + } else if (ival == OB_CLIENT_LOB_LOCATORV2_FORCE_CLOSE) { + bret = FALSE; + } + if (mysql) { + mysql->can_use_ob_client_lob_locatorv2 = bret; + } + DBUG_RETURN(bret); +} +my_bool get_use_ob_client_lob_locatorv2(MYSQL *mysql) +{ + if (mysql) { + return mysql->can_use_ob_client_lob_locatorv2; + } + return FALSE; +} + +uint8_t get_ob_lob_locator_version(void *lob) +{ + uint8_t ver = 0; + if (NULL == lob) { + ver = 0; + } else { + ObClientMemLobCommon *plob = (ObClientMemLobCommon*)lob; + ver = plob->version_; + } + return ver; +} +int64_t get_ob_lob_payload_data_len(void *lob) +{ + int64_t len = -1; + if (NULL == lob) { + len = -1; + } else { + ObClientMemLobCommon *plob = (ObClientMemLobCommon*)lob; + if (plob->version_ == OBCLIENT_LOB_LOCATORV1) { + OB_LOB_LOCATOR *tmp = (OB_LOB_LOCATOR*)lob; + len = tmp->payload_size_; + } else if (plob->version_ == OBCLIENT_LOB_LOCATORV2) { + OB_LOB_LOCATOR_V2 *tmp = (OB_LOB_LOCATOR_V2*)lob; + if (0 == tmp->common.has_extern) + len = -1; + + if (tmp->common.is_inrow_) { + len = tmp->extern_header.payload_size_; + } else { + //这种情况下的数据大小是位置在 + //sizeof(ObMemLobCommon ) + sizeof(ObMemLobExternHeader) + sizeof(uint16)+ ex_size + rowkey_size + sizeof(ObLobCommon)+sizeof(ObLobData) + int tmp_len = tmp->extern_header.payload_offset_+ tmp->extern_header.payload_size_; + char *tmp_buf = tmp->data_; + uint16_t ex_size = uint2korr(tmp_buf); + int offset = MAX_OB_LOB_LOCATOR_HEADER_LENGTH + sizeof(uint16) + ex_size + tmp->extern_header.rowkey_size_ + sizeof(ObClientLobCommon) + sizeof(ObClientLobData); + if (tmp_len > offset) { + len = uint8korr(tmp_buf + offset - 8); + } + } + } + } + return len; +} + +int prepare_execute_v2(MYSQL *mysql, MYSQL_STMT* stmt, const char* query, MYSQL_BIND* params) { + int ret = 0; + int length = strlen(query); + if (get_use_prepare_execute(mysql)) { + void* extend_arg = NULL; + if (mysql_stmt_prepare_v2(stmt, query, length, extend_arg)) { + ret = -1; + } else if (params && mysql_stmt_bind_param(stmt, params)) { + ret = -1; + } else if (mysql_stmt_execute_v2(stmt, query, length, 1, 0, extend_arg)) { + ret = -1; + } + } else { + if (mysql_stmt_prepare(stmt, query, length)) { + ret = -1; + } else if (params && mysql_stmt_bind_param(stmt, params)) { + ret = -1; + } else if (mysql_stmt_execute(stmt)) { + ret = -1; + } + } + return ret; +} +int stmt_get_data_from_lobv2( MYSQL *mysql, void * lob, enum_field_types type, + int64_t char_offset, int64_t byte_offset, int64_t char_len, int64_t byte_len, char *buf, const int64_t buf_len, int64_t *data_len, int64_t *act_len) +{ + int ret = -1; + const char *read_sql = "call DBMS_LOB.read(?, ?, ?, ?)"; + MYSQL_BIND param_bind[4]; + MYSQL_BIND param_res[2]; + MYSQL_STMT* stmt = NULL; + int64_t length = 0; + OB_LOB_LOCATOR_V2 *loblocator = (OB_LOB_LOCATOR_V2*)lob; + + char_offset = char_offset; + char_len = char_len; + + if (!mysql) { + SET_CLIENT_STMT_ERROR(stmt, CR_SERVER_LOST, unknown_sqlstate, NULL); + DBUG_RETURN(1); + } + if (NULL == lob) { + SET_CLIENT_STMT_ERROR(stmt, CR_UNKNOWN_ERROR, unknown_sqlstate, NULL); + DBUG_RETURN(1); + } + if (OBCLIENT_LOB_LOCATORV2 != get_ob_lob_locator_version(lob)) { + SET_CLIENT_STMT_ERROR(stmt, CR_UNKNOWN_ERROR, unknown_sqlstate, NULL); + DBUG_RETURN(1); + } + if (type != MYSQL_TYPE_ORA_CLOB && type != MYSQL_TYPE_ORA_BLOB) { + SET_CLIENT_STMT_ERROR(stmt, CR_UNKNOWN_ERROR, unknown_sqlstate, NULL); + DBUG_RETURN(1); + } + if (1 != loblocator->common.has_extern) { + SET_CLIENT_STMT_ERROR(stmt, CR_UNKNOWN_ERROR, unknown_sqlstate, NULL); + DBUG_RETURN(1); + } + + if (1 == loblocator->common.is_inrow_) { + length = byte_len > buf_len ? buf_len : byte_len; + length = length > loblocator->extern_header.payload_size_ ? loblocator->extern_header.payload_size_ : length; + memcpy(buf, loblocator->data_ + loblocator->extern_header.payload_offset_, length); + if (data_len) + *data_len = length; + if (act_len) + *act_len = loblocator->extern_header.payload_size_; + ret = 0; + } else { + int64_t tmp_len = byte_len + 1; + char *tmp_buf = calloc(1, byte_len); + if (NULL != tmp_buf) { + //params + memset(param_bind, 0, sizeof(param_bind)); + param_bind[0].buffer = lob; + param_bind[0].buffer_length = loblocator->extern_header.payload_size_ + loblocator->extern_header.payload_offset_ + MAX_OB_LOB_LOCATOR_HEADER_LENGTH; + param_bind[0].buffer_type = type; + param_bind[1].buffer = (char *)&tmp_len; + param_bind[1].buffer_type = MYSQL_TYPE_LONGLONG; + param_bind[2].buffer = (char *)&byte_offset; + param_bind[2].buffer_type = MYSQL_TYPE_LONGLONG; + param_bind[3].is_null = ¶m_bind[3].is_null_value; + *param_bind[3].is_null = 1; + if (MYSQL_TYPE_ORA_CLOB == type) { + param_bind[3].buffer_type = MYSQL_TYPE_VAR_STRING; + } else { + param_bind[3].buffer_type = MYSQL_TYPE_OB_RAW; + } + + //result + memset(param_res, 0, sizeof(param_res)); + param_res[0].error = ¶m_res[0].error_value; + param_res[0].is_null = ¶m_res[0].is_null_value; + param_res[0].buffer = &length; + param_res[0].buffer_type = MYSQL_TYPE_LONGLONG; + param_res[1].error = ¶m_res[1].error_value; + param_res[1].is_null = ¶m_res[1].is_null_value; + param_res[1].length = ¶m_res[1].length_value; + param_res[1].buffer = tmp_buf; + param_res[1].buffer_length = tmp_len; + if (MYSQL_TYPE_ORA_CLOB == type) { + param_res[1].buffer_type = MYSQL_TYPE_VAR_STRING; + } else { + param_res[1].buffer_type = MYSQL_TYPE_OB_RAW; + } + + if (NULL == (stmt = mysql_stmt_init(mysql))) { + ret = -1; + } else if (prepare_execute_v2(mysql, stmt, read_sql, param_bind)) { + ret = -1; + } else if (mysql_stmt_bind_result(stmt, param_res)) { + ret = -1; + } else { + ret = mysql_stmt_fetch(stmt); + if (0 == ret) { + *data_len = param_res[1].length_value; + *act_len = *data_len; + if (*data_len > byte_len) { + *data_len = byte_len > buf_len ? buf_len : byte_len; + } else { + *data_len = *data_len > buf_len ? buf_len : *data_len; + } + memcpy(buf, tmp_buf, *data_len); + } + } + + if (NULL != stmt) { + mysql_stmt_close(stmt); + } + + free(tmp_buf); + tmp_buf = NULL; + } + } + return ret; +} + +my_bool set_nls_format(MYSQL *mysql) +{ + my_bool bret = TRUE; + if (mysql->oracle_mode) { + char *nls_date_format = getenv("NLS_DATE_FORMAT"); + char *nls_timestamp_format = getenv("NLS_TIMESTAMP_FORMAT"); + char *nls_timestamp_tz_format = getenv("NLS_TIMESTAMP_TZ_FORMAT"); + + if (NULL != nls_date_format) { + char change_date_format_sql[100]; + snprintf(change_date_format_sql, 100, "ALTER SESSION SET NLS_DATE_FORMAT='%s';", nls_date_format); + if (mysql_query(mysql, change_date_format_sql)) { + bret = FALSE; + } + } + if (bret && NULL != nls_timestamp_format) { + char change_timestamp_format_sql[100]; + snprintf(change_timestamp_format_sql, 100, "ALTER SESSION SET NLS_TIMESTAMP_FORMAT='%s';", nls_timestamp_format); + if (mysql_query(mysql, change_timestamp_format_sql)) { + bret = FALSE; + } + } + if (bret && NULL != nls_timestamp_tz_format) { + char change_timestamp_tz_format_sql[100]; + snprintf(change_timestamp_tz_format_sql, 100, "ALTER SESSION SET NLS_TIMESTAMP_TZ_FORMAT='%s';", nls_timestamp_tz_format); + if (mysql_query(mysql, change_timestamp_tz_format_sql)) { + bret = FALSE; + } + } + } + return bret; +} /* * judge where can use prepare_execute protocol * use version to judge @@ -5334,10 +5670,12 @@ static int madb_update_stmt_fields(MYSQL_STMT *stmt) // same as update_stmt_fiel if (MYSQL_TYPE_OBJECT == field->type && NULL == stmt_field->owner_name && NULL != field->owner_name) { stmt_field->owner_name= (unsigned char *)ma_memdup_root(fields_ma_alloc_root, (char*)field->owner_name, - field->owner_name_length); + field->owner_name_length+1); + stmt_field->owner_name[field->owner_name_length] = 0; stmt_field->type_name= (unsigned char *)ma_memdup_root(fields_ma_alloc_root, (char*)field->type_name, - field->type_name_length); + field->type_name_length+1); + stmt_field->type_name[field->type_name_length] = 0; } } return 0; diff --git a/libmariadb/ob_full_link_trace.c b/libmariadb/ob_full_link_trace.c index 01d8ad5..5cbb16a 100644 --- a/libmariadb/ob_full_link_trace.c +++ b/libmariadb/ob_full_link_trace.c @@ -60,6 +60,9 @@ if (OB_NOT_NULL(span) && 0 == span->span_id_.high_) { \ FLT_EXTRA_INFO_DEF(FLT_TRACE_ID, MYSQL_TYPE_VAR_STRING); \ FLT_EXTRA_INFO_DEF(FLT_REF_TYPE, MYSQL_TYPE_TINY); \ FLT_EXTRA_INFO_DEF(FLT_SPAN_ID, MYSQL_TYPE_VAR_STRING); \ + /* SHOW_TRACE_SPAN */ \ + FLT_EXTRA_INFO_DEF(FLT_DRV_SHOW_TRACE_SPAN, MYSQL_TYPE_VAR_STRING); \ + FLT_EXTRA_INFO_DEF(FLT_PROXY_SHOW_TRACE_SPAN, MYSQL_TYPE_VAR_STRING); \ FLT_EXTRA_INFO_DEF(FLT_EXTRA_INFO_ID_END, MAX_NO_FIELD_TYPES); \ } while (0); #define FLT_SERIALIZE_FUNC_SET(id, funcname) (flt_funcs[id] = (FLTFunc)FLT_SERIALIZE_FUNC(funcname)) @@ -76,6 +79,8 @@ if (OB_NOT_NULL(span) && 0 == span->span_id_.high_) { \ FLT_SERIALIZE_FUNC_SET(FLT_CONTROL_INFO, controlinfo); \ /* SPAN_INFO */ \ FLT_SERIALIZE_FUNC_SET(FLT_SPAN_INFO, spaninfo); \ + /* SHOW_TRACE_SPAN */ \ + FLT_SERIALIZE_FUNC_SET(FLT_TYPE_SHOW_TRACE_SPAN, showtracespan); \ } while (0); const char *tag_str[FLT_TAG_MAX_TYPE] = @@ -132,6 +137,7 @@ int flt_init(FLTInfo *flt) memset(flt, 0, sizeof(*flt)); + flt->show_trace_span_.type_ = FLT_TYPE_SHOW_TRACE_SPAN; flt->client_span_.type_ = FLT_DRIVER_SPAN_INFO; flt->app_info_.type_ = FLT_APP_INFO; flt->query_info_.type_ = FLT_QUERY_INFO; @@ -145,6 +151,7 @@ int flt_init(FLTInfo *flt) flt->control_info_.rp_ = MAX_RECORD_POLICY; flt->control_info_.print_sample_pct_ = -1; flt->control_info_.slow_query_threshold_ = -1; + flt->control_info_.flt_show_trace_enable_ = 0; if (OB_FAIL(trace_init(flt))) { // trace init error; @@ -188,6 +195,7 @@ int flt_build_request(MYSQL *mysql, FLTInfo *flt) int32_t span_info_serialize_size = 0; int32_t client_log_serialize_size = 0; int32_t app_info_serialize_size = 0; + int32_t show_trace_serialize_size = 0; int64_t tmp_trace_id_pos = 0; int64_t tmp_span_id_pos = 0; @@ -221,21 +229,36 @@ int flt_build_request(MYSQL *mysql, FLTInfo *flt) flt->client_span_.client_span_ = NULL; } + if (1 < trace->show_trace_buf_offset_ && trace->show_trace_enable_) { + flt->show_trace_span_.client_span_json_ = trace->show_trace_buf_; + // Change the final comma to a parenthesis + trace->show_trace_buf_[trace->show_trace_buf_offset_ - 1] = ']'; + } else { + flt->show_trace_span_.client_span_json_ = NULL; + } + if (OB_FAIL(flt_get_serialize_size_extra_info(&app_info_serialize_size, &flt->app_info_))) { // error } else if (OB_FAIL(flt_get_serialize_size_extra_info(&client_log_serialize_size, &flt->client_span_))) { // error } else if (OB_FAIL(flt_get_serialize_size_extra_info(&span_info_serialize_size, &flt->span_info_))) { // error + } else if (OB_FAIL(flt_get_serialize_size_extra_info(&show_trace_serialize_size, &flt->show_trace_span_))) { + // error } else { serialize_size += app_info_serialize_size; serialize_size += client_log_serialize_size; serialize_size += span_info_serialize_size; + serialize_size += show_trace_serialize_size; #ifdef DEBUG_OB20 - printf("spaninfo ssize is %d, log ssize is %d, appinfo ssize %d\n", span_info_serialize_size, client_log_serialize_size, app_info_serialize_size); + printf("spaninfo ssize:%d, log ssize:%d, appinfo ssize:%d, show trace ssize:%d\n", span_info_serialize_size, + client_log_serialize_size, app_info_serialize_size, show_trace_serialize_size); if (0 != client_log_serialize_size) { printf("log:%s\n", flt->client_span_.client_span_); } + if (0 != show_trace_serialize_size) { + printf("log:%s\n", flt->show_trace_span_.client_span_json_); + } #endif } @@ -256,6 +279,10 @@ int flt_build_request(MYSQL *mysql, FLTInfo *flt) // error } else if (pos != span_info_serialize_size + client_log_serialize_size) { ret = OB_ERROR; + } else if (0 != show_trace_serialize_size && OB_FAIL(flt_serialize_extra_info(flt->flt_value_data_.value_data_, serialize_size, &pos, &flt->show_trace_span_))) { + // error + } else if (pos != span_info_serialize_size + client_log_serialize_size + show_trace_serialize_size) { + ret = OB_ERROR; } else if (0 != app_info_serialize_size && OB_FAIL(flt_serialize_extra_info(flt->flt_value_data_.value_data_, serialize_size, &pos, &flt->app_info_))) { // error } else if (pos != serialize_size) { @@ -269,6 +296,10 @@ int flt_build_request(MYSQL *mysql, FLTInfo *flt) // reset the log buf offset trace->log_buf_offset_ = 0; flt->client_span_.client_span_ = NULL; + // reset show trace log buffer + trace->show_trace_buf_[0] = '['; + trace->show_trace_buf_offset_ = 1; + flt->show_trace_span_.client_span_json_ = NULL; } if (OB_SUCC(ret)) { if (OB_FAIL(ob20_set_extra_info(mysql, FULL_TRC, &flt->flt_value_data_))) { @@ -328,11 +359,12 @@ int flt_get_serialize_size_controlinfo(int32_t *size, void *flt_info) UNUSED(flt_info); local_size += TYPE_LENGTH + LEN_LENGTH; - local_size += flt_get_store_int1_size(); - local_size += flt_get_store_double_size(); - local_size += flt_get_store_int1_size(); - local_size += flt_get_store_double_size(); - local_size += flt_get_store_int8_size(); + local_size += flt_get_store_int1_size(); // type_ + local_size += flt_get_store_double_size(); // sample_pct_ + local_size += flt_get_store_int1_size(); // rp_ + local_size += flt_get_store_double_size(); // print_sample_pct_ + local_size += flt_get_store_int8_size(); // slow_query_threshold_ + local_size += flt_get_store_int8_size(); // flt_show_trace_enable_ *size = local_size; return ret; @@ -361,6 +393,8 @@ int flt_serialize_controlinfo(char *buf, const int64_t len, int64_t *pos, void * ret = OB_ERROR; } else if (OB_FAIL(flt_store_int8(buf, len, pos, control_info->slow_query_threshold_, FLT_SLOW_QUERY_THRES))) { ret = OB_ERROR; + } else if (OB_FAIL(flt_store_int8(buf, len, pos, control_info->flt_show_trace_enable_, FLT_SHOW_TRACE_ENABLE))) { + ret = OB_ERROR; } else { // fill type and len in the head int32_t total_len = *pos - org_pos - 6; @@ -431,6 +465,16 @@ int flt_deserialize_field_controlinfo(FullLinkTraceExtraInfoId extra_id, const i // do nothing #ifdef DEBUG_OB20 printf("slow_query_threshold is %ld\n", flt_control_info->slow_query_threshold_); +#endif + } + break; + } + case FLT_SHOW_TRACE_ENABLE: { + if (OB_FAIL(flt_get_int1(buf, len, pos, v_len, &flt_control_info->flt_show_trace_enable_))) { + ret = OB_ERROR; + } else { +#ifdef DEBUG_OB20 + printf("show_trace_enable is %hhd\n", flt_control_info->flt_show_trace_enable_); #endif } break; @@ -544,7 +588,7 @@ int flt_deserialize_field_appinfo(FullLinkTraceExtraInfoId extra_id, const int64 break; } default: { - // get an unrecognized key here, skip it directly + // get an unrecognized key here, skip it directly *pos += *pos + v_len; break; } @@ -619,7 +663,7 @@ int flt_deserialize_field_queryinfo(FullLinkTraceExtraInfoId extra_id, const int break; } default: { - // get an unrecognized key here, skip it directly + // get an unrecognized key here, skip it directly *pos += *pos + v_len; break; } @@ -811,6 +855,72 @@ int flt_deserialize_field_driverspaninfo(FullLinkTraceExtraInfoId extra_id, cons } // for driverspaninfo info +// for show trace span +int flt_get_serialize_size_showtracespan(int32_t *size, void *flt_info) +{ + int ret = OB_SUCCESS; + int32_t local_size = 0; + FLTShowTraceSpan *show_trace_span = (FLTShowTraceSpan *)flt_info; + + if (NULL != show_trace_span->client_span_json_) { + local_size += TYPE_LENGTH + LEN_LENGTH; + local_size += flt_get_store_str_size(strlen(show_trace_span->client_span_json_) + 1); + } + + *size = local_size; + return ret; +} + +int flt_serialize_showtracespan(char *buf, const int64_t len, int64_t *pos, void *flt_info) +{ + int ret = OB_SUCCESS; + int64_t org_pos = *pos; + FLTShowTraceSpan *show_trace_span = (FLTShowTraceSpan *)flt_info; + // resrver for type and len + if (*pos + 6 > len) { + ret = OB_SIZE_OVERFLOW; + } else { + *pos += 6; + } + if (OB_FAIL(ret)) { + // do nothing + } else if (OB_FAIL(flt_store_str(buf, len, pos, show_trace_span->client_span_json_, strlen(show_trace_span->client_span_json_) + 1, FLT_DRV_SHOW_TRACE_SPAN))) { + ret = OB_ERROR; + } else { + // fill type and len in the head + int32_t total_len = *pos - org_pos - 6; + if (OB_FAIL(flt_store_type_and_len(buf, len, &org_pos, show_trace_span->type_, total_len))) { + ret = OB_ERROR; + } else { + // do nothing + } + } + return ret; +} + +int flt_deserialize_field_showtracespan(FullLinkTraceExtraInfoId extra_id, const int64_t v_len, + const char *buf, const int64_t len, int64_t *pos, void *flt_info) +{ + int ret = OB_SUCCESS; + FLTShowTraceSpan *show_trace_span = (FLTShowTraceSpan *)flt_info; + switch(extra_id) { + case FLT_CLIENT_IDENTIFIER: { + if (OB_FAIL(flt_get_str(buf, len, pos, v_len, (char **)&show_trace_span->client_span_json_))) { + ret = OB_ERROR; + } else { + // do nothing + } + break; + } + default: { + *pos += *pos + v_len; + break; + } + } + return ret; +} +// for driverspaninfo info + // for no support int flt_deserialize_field_nosupport(FullLinkTraceExtraInfoId extra_id, const int64_t v_len, const char *buf, const int64_t len, int64_t *pos, void *flt_info) @@ -1281,18 +1391,31 @@ int trace_init(FLTInfo *flt) memset(trace, 0, sizeof(*trace)); trace->buffer_size_ = OBTRACE_DEFAULT_BUFFER_SIZE - sizeof(*trace); trace->log_buf_ = trace->data_; // size is MAX_TRACE_LOG_SIZE - trace->flt_serialize_buf_ = trace->data_ + MAX_TRACE_LOG_SIZE; // size is MAX_FLT_SERIALIZE_SIZE + trace->show_trace_buf_ = trace->data_ + MAX_TRACE_LOG_SIZE; // size is MAX_TRACE_LOG_SIZE + trace->flt_serialize_buf_ = trace->data_ + (2 * MAX_TRACE_LOG_SIZE); // size is MAX_FLT_SERIALIZE_SIZE trace->offset_ = INIT_OFFSET; trace->auto_flush_ = 1; trace->trace_enable_ = FALSE; + trace->show_trace_enable_ = FALSE; trace->force_print_ = FALSE; trace->slow_query_print_ = FALSE; trace->root_span_id_.low_ = 0; trace->root_span_id_.high_ = 0; trace->flt = flt; flt->trace_ = trace; + // set the starting parentheses + trace->show_trace_buf_[0] = '['; + trace->show_trace_buf_offset_ = 1; + trace->free_tag_list_.data_ = NULL; + trace->free_tag_list_.next_ = NULL; + trace->free_tag_list_.tag_type_ = 0; + for (index = 0; index < TAG_CACHE_COUNT; ++index) { + ObTagCtx *tag = (ObTagCtx *)(trace->data_ + TAG_BUFFER_BEGIN + (index * sizeof(ObTagCtx))); + tag->next_ = trace->free_tag_list_.next_; + trace->free_tag_list_.next_ = tag; + } for (index = 0; index < SPAN_CACHE_COUNT; ++index) { - char *begin_addr = trace->data_ + MAX_TRACE_LOG_SIZE + MAX_FLT_SERIALIZE_SIZE + (index * (sizeof(LIST) + sizeof(ObSpanCtx))); + char *begin_addr = trace->data_ + SPAN_BUFFER_BEGIN + (index * (sizeof(LIST) + sizeof(ObSpanCtx))); LIST *list = (LIST *)begin_addr; list->data = (ObSpanCtx *)(begin_addr + sizeof(LIST)); trace->free_span_list_ = list_add(trace->free_span_list_, list); @@ -1322,11 +1445,18 @@ void begin_trace(ObTrace *trace) if (OB_ISNULL(flt)) { // error, do not entable trace trace->trace_enable_ = FALSE; + trace->show_trace_enable_ = FALSE; } else if (FALSE == flt_is_vaild(flt)) { // error, invalid trace trace->trace_enable_ = FALSE; + trace->show_trace_enable_ = FALSE; + } else if (TRUE == flt->control_info_.flt_show_trace_enable_) { + // for show trace , always true + trace->trace_enable_ = TRUE; + trace->show_trace_enable_ = TRUE; } else { double trace_pct = flt_get_pct(trace->uuid_random_seed); + trace->show_trace_enable_ = FALSE; if (trace_pct <= flt->control_info_.sample_pct_) { // trace enable @@ -1337,10 +1467,15 @@ void begin_trace(ObTrace *trace) } if (TRUE == trace->trace_enable_) { + // todo : add interface to set trace id trace->trace_id_ = uuid4_generate(trace->uuid_random_seed); trace->level_ = flt->control_info_.level_; // If the trace hits, the subsequent calculation and printing strategy - if (RP_ALL == flt->control_info_.rp_) { + + if (TRUE == flt->control_info_.flt_show_trace_enable_) { + // for show trace , always true + trace->force_print_ = TRUE; + } else if (RP_ALL == flt->control_info_.rp_) { trace->force_print_ = TRUE; } else if (RP_SAMPLE_AND_SLOW_QUERY == flt->control_info_.rp_) { // Hit print samples need to print @@ -1380,8 +1515,8 @@ void end_trace(ObTrace *trace) if (0 == span->end_ts_) { span->end_ts_ = get_current_time_us(); } - trace->current_span_list_ = trace->current_span_list_->next; // add all elem to free span list + trace->current_span_list_ = list_delete(trace->current_span_list_, span_elem); trace->free_span_list_ = list_add(trace->free_span_list_, span_elem); } trace->offset_ = INIT_OFFSET; @@ -1454,29 +1589,37 @@ void flush_first_span(ObTrace *trace) } } if (OB_SUCC(ret) && 0 != span->end_ts_) { + // clear span and reset tag + ObTagCtx *tag = span->tags_; + while(OB_NOT_NULL(tag)) { + ObTagCtx *free_tag = tag; + tag = tag->next_; + reset_tag(trace, span, free_tag); + } + span->tags_ = NULL; trace->current_span_list_ = list_delete(trace->current_span_list_, span_list); trace->free_span_list_ = list_add(trace->free_span_list_, span_list); } - span->tags_ = 0; } } void flush_trace(ObTrace *trace) { - LIST *next; - LIST *span_list; + LIST *span_elem; ObSpanCtx *span; int64_t pos = 0; int ret = OB_SUCCESS; + int log_buf_len = 0; + int show_trace_buf_len = 0; if (OB_ISNULL(trace) || (0 == trace->trace_id_.low_ && 0 == trace->trace_id_.high_)) { // do nothing - } else if (OB_ISNULL(span_list = trace->current_span_list_)) { + } else if (OB_ISNULL(trace->current_span_list_)) { // do nothing } else { - while (OB_NOT_NULL(span_list)) { - span = (ObSpanCtx *)span_list->data; - next = span_list->next; + while (OB_NOT_NULL(trace->current_span_list_) && OB_SUCC(ret)) { + span_elem = trace->current_span_list_; + span = (ObSpanCtx *)span_elem->data; if (OB_NOT_NULL(span)) { ObTagCtx *tag = span->tags_; my_bool first = TRUE; @@ -1508,31 +1651,50 @@ void flush_trace(ObTrace *trace) } if (OB_SUCC(ret)) { INIT_SPAN(trace, span->source_span_); - ret = snprintf(trace->log_buf_ + trace->log_buf_offset_, - MAX_TRACE_LOG_SIZE - trace->log_buf_offset_, - TRACE_PATTERN "%s}", - UUID_TOSTRING(trace->trace_id_), - "obclient", - UUID_TOSTRING(span->span_id_), - span->start_ts_, - span->end_ts_, - UUID_TOSTRING(OB_ISNULL(span->source_span_) ? trace->root_span_id_ : span->source_span_->span_id_), - span->is_follow_ ? "true" : "false", - buf); - if (ret < 0 || trace->log_buf_offset_ + ret >= MAX_TRACE_LOG_SIZE) { + log_buf_len = snprintf(trace->log_buf_ + trace->log_buf_offset_, + MAX_TRACE_LOG_SIZE - trace->log_buf_offset_, + TRACE_PATTERN "%s}", + UUID_TOSTRING(trace->trace_id_), + "obclient", + UUID_TOSTRING(span->span_id_), + span->start_ts_, + span->end_ts_, + UUID_TOSTRING(OB_ISNULL(span->source_span_) ? trace->root_span_id_ : span->source_span_->span_id_), + span->is_follow_ ? "true" : "false", + buf); + if (log_buf_len < 0 || trace->log_buf_offset_ + log_buf_len >= MAX_TRACE_LOG_SIZE) { ret = OB_ERROR; } else { - trace->log_buf_offset_ += ret; - ret = OB_SUCCESS; + trace->log_buf_offset_ += log_buf_len; + if (0 != span->end_ts_) { + // The span that has ended needs to be put into the show trace buffer and sent to the backend next time + show_trace_buf_len = snprintf(trace->show_trace_buf_ + trace->show_trace_buf_offset_, + MAX_TRACE_LOG_SIZE - trace->show_trace_buf_offset_, + "%.*s,", + log_buf_len, + trace->log_buf_ + trace->log_buf_offset_ - log_buf_len); + if (show_trace_buf_len < 0 || trace->show_trace_buf_offset_ + show_trace_buf_len >= MAX_TRACE_LOG_SIZE) { + ret = OB_ERROR; + } else { + trace->show_trace_buf_offset_ += show_trace_buf_len; + } + } } } if (OB_SUCC(ret) && 0 != span->end_ts_) { - trace->current_span_list_ = list_delete(trace->current_span_list_, span_list); - trace->free_span_list_ = list_add(trace->free_span_list_, span_list); + + // clear span and reset tag + ObTagCtx *tag = span->tags_; + while(OB_NOT_NULL(tag)) { + ObTagCtx *free_tag = tag; + tag = tag->next_; + reset_tag(trace, span, free_tag); + } + span->tags_ = 0; + trace->current_span_list_ = list_delete(trace->current_span_list_, span_elem); + trace->free_span_list_ = list_add(trace->free_span_list_, span_elem); } - span->tags_ = 0; } - span_list = next; } trace->offset_ = INIT_OFFSET; } @@ -1556,7 +1718,6 @@ ObSpanCtx* begin_span(ObTrace *trace, uint32_t span_type, uint8_t level, my_bool } if (OB_NOT_NULL(trace->free_span_list_)) { LIST *span_elem = trace->free_span_list_; - trace->free_span_list_ = trace->free_span_list_->next; if (OB_NOT_NULL(span_elem)) { new_span = (ObSpanCtx *)span_elem->data; new_span->span_type_ = span_type; @@ -1568,6 +1729,7 @@ ObSpanCtx* begin_span(ObTrace *trace, uint32_t span_type, uint8_t level, my_bool new_span->end_ts_ = 0; new_span->tags_ = NULL; trace->last_active_span_ = new_span; + trace->free_span_list_ = list_delete(trace->free_span_list_, span_elem); trace->current_span_list_ = list_add(trace->current_span_list_, span_elem); } } @@ -1619,17 +1781,14 @@ void reset_span(ObTrace *trace) // trace is not inited } else { ObSpanCtx *span; - LIST *next; - LIST *span_elem = trace->current_span_list_; - while(OB_NOT_NULL(span_elem)) { + LIST *span_elem; + while(OB_NOT_NULL(trace->current_span_list_)) { + span_elem = trace->current_span_list_; span = (ObSpanCtx *)span_elem->data; - next = span_elem->next; - if (0 != span->end_ts_) { - trace->current_span_list_ = list_delete(trace->current_span_list_, span_elem); - trace->free_span_list_ = list_add(trace->free_span_list_, span_elem); - } + // All spans are recycled after a statement in the transaction ends + trace->current_span_list_ = list_delete(trace->current_span_list_, span_elem); + trace->free_span_list_ = list_add(trace->free_span_list_, span_elem); span->tags_ = NULL; - span_elem = next; } } } @@ -1640,15 +1799,30 @@ void append_tag(ObTrace *trace, ObSpanCtx *span, uint16_t tag_type, const char * // do nothing } else if (OB_ISNULL(str)) { // do nothing - } else if (trace->offset_ + sizeof(ObTagCtx) > trace->buffer_size_) { + } else if (OB_ISNULL(trace->free_tag_list_.next_)) { // do nothing } else { - ObTagCtx *tag = (ObTagCtx *)(trace->data_ + trace->offset_); + // get tag from free tag list + ObTagCtx *tag = (ObTagCtx *)(trace->free_tag_list_.next_); + trace->free_tag_list_.next_ = tag->next_; + // append tag into span tag->next_ = span->tags_; span->tags_ = tag; tag->tag_type_ = tag_type; tag->data_ = str; - trace->offset_ += sizeof(ObTagCtx); + } +} + +void reset_tag(ObTrace *trace, ObSpanCtx *span, ObTagCtx *tag) +{ + UNUSED(span); + if (OB_ISNULL(trace)) { + // do nothing + } else if (OB_ISNULL(tag)) { + // do nothing + } else { + tag->next_ = trace->free_tag_list_.next_; + trace->free_tag_list_.next_ = tag; } } diff --git a/libmariadb/ob_protocol20.c b/libmariadb/ob_protocol20.c index dc47610..e61d65c 100644 --- a/libmariadb/ob_protocol20.c +++ b/libmariadb/ob_protocol20.c @@ -389,8 +389,6 @@ uchar *fill_protocol20_header(Ob20Protocol *ob20protocol, size_t len, size_t pkt { 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); @@ -417,6 +415,22 @@ uchar *fill_protocol20_header(Ob20Protocol *ob20protocol, size_t len, size_t pkt int2store(&buffer[pos], ob20protocol->header.header_checksum); pos += 2; + #ifdef DEBUG_OB20 + printf("////////////////begin ob20 pkt write[%u]//////////////////////////\n", pkt_nr); + printf("mysql pkt_len is %u\n", len); + printf("mysql pkt_nr is %u\n", pkt_nr); + printf("complen is %u\n", complen); + printf("magic_num is %u\n", ob20protocol->header.magic_num); + printf("version is %u\n", ob20protocol->header.version); + printf("connection_id is %u\n", ob20protocol->header.connection_id); + printf("request_id is %u\n", ob20protocol->header.request_id); + printf("ob20 pkt_seq is %u\n", ob20protocol->header.pkt_seq); + printf("ob20 payload_len is %u\n", ob20protocol->header.payload_len); + printf("flag is %u\n", ob20protocol->header.flag.flags); + printf("header checksum is %u\n", ob20protocol->header.header_checksum); + printf("////////////////end ob20 pkt write[%u]//////////////////////////\n", pkt_nr); +#endif + return buffer + pos; } @@ -468,22 +482,6 @@ int decode_protocol20_header(Ob20Protocol *ob20protocol, uchar *buffer, uint32_t 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) { @@ -495,10 +493,8 @@ int decode_protocol20_header(Ob20Protocol *ob20protocol, uchar *buffer, uint32_t } else if (request_id != ob20protocol->header.request_id) { ret = 1; // error } else { - //check request id and pkt_seq ob20protocol->header.pkt_seq++; if (pkt_seq != ob20protocol->header.pkt_seq) { - // 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; @@ -509,6 +505,26 @@ int decode_protocol20_header(Ob20Protocol *ob20protocol, uchar *buffer, uint32_t } } +#ifdef DEBUG_OB20 + printf("////////////////begin ob20 pkt read[%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); + + if (0 != ret) { + printf("decode header error\n"); + } + printf("////////////////end ob20 pkt read[%u]//////////////////////////\n", pkt_nr); +#endif + return ret; } @@ -517,7 +533,6 @@ int extrainfo_serialize_flt(char *buf, const int64_t len, int64_t *ppos, void *d 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)) { @@ -579,13 +594,13 @@ int extrainfo_deserialize_flt(const char *buf, const int64_t len, int64_t *ppos, } } } else { - // 对于不识别的key,需要跳过 + // For unrecognized keys, need to skip pos += tmp_v_len; } } } if (OB_SUCC(ret)) { - *ppos = pos; // 最后设置好pos + *ppos = pos; } return ret; } @@ -616,7 +631,7 @@ uchar *fill_protocol20_extra_info(Ob20Protocol *ob20protocol, uchar *buffer, siz 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 + // do nothing } if (OB_FAIL(extra_serialize_funcs[extra_info_item->key].serialize_func(packet + pos, buffer_len, &pos, extra_info_item->value))) { return buffer; } @@ -669,7 +684,7 @@ int decode_protocol20_extra_info(Ob20Protocol *ob20protocol, uchar *buffer) check_pos = pos; if (OB_ISNULL(extra_serialize_funcs[key_type].deserialize_func)) { - // 如果函数指针没有设置,直接跳过value不解析 + // If the function pointer is not set, skip the value directly without parsing pos += value_len; } else if (OB_FAIL(extra_serialize_funcs[key_type].deserialize_func(row, extra_info_len, &pos, ob20protocol, sizeof(*ob20protocol)))) { // error diff --git a/libmariadb/ob_serialize.c b/libmariadb/ob_serialize.c index 5a6c3d5..aac5a61 100644 --- a/libmariadb/ob_serialize.c +++ b/libmariadb/ob_serialize.c @@ -189,7 +189,7 @@ inline int decode_i8(const char *buf, const int64_t data_len, int64_t *ppos, int return ret; } -int encode_i64(char *buf, const int64_t buf_len, int64_t *ppos, int64_t val) +inline int encode_i64(char *buf, const int64_t buf_len, int64_t *ppos, int64_t val) { int pos = *ppos; int ret = ((NULL != buf) && @@ -209,7 +209,7 @@ int encode_i64(char *buf, const int64_t buf_len, int64_t *ppos, int64_t val) return ret; } -int decode_i64(const char *buf, const int64_t data_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) { int pos = *ppos; int ret = (NULL != buf && data_len - pos >= 8) ? OB_SUCCESS : OB_ERROR; diff --git a/libmariadb/ob_strtoll10.c b/libmariadb/ob_strtoll10.c index 23d33db..73b64b3 100644 --- a/libmariadb/ob_strtoll10.c +++ b/libmariadb/ob_strtoll10.c @@ -32,7 +32,22 @@ longlong strtoll10(const char *nptr, char **endptr, int *error) { longlong ret = 0; + char *tmp_endptr = NULL; + char tmp_endptr_value; + if (NULL != endptr && NULL != *endptr) { + tmp_endptr = *endptr; + tmp_endptr_value = **endptr; + *tmp_endptr = '\0'; + } + /* + * Obclient 2.2.2 changes, obclient 1.x uses my_strtoll10, 2.x uses lib c to provide strtoll after rectification, + * the two perform differently on endptr, my_strtoll10 will detect endptr and not convert the bit result, + * so set 0 here, Compatible with obclient 1.x + */ ret = strtoll(nptr, endptr, 10); *error = errno; + if (NULL != tmp_endptr) { + *tmp_endptr = tmp_endptr_value; + } return ret; } \ No newline at end of file diff --git a/rpm/libobclient-VER.txt b/rpm/libobclient-VER.txt index b1b25a5..5859406 100644 --- a/rpm/libobclient-VER.txt +++ b/rpm/libobclient-VER.txt @@ -1 +1 @@ -2.2.2 +2.2.3 diff --git a/unittest/ob20_test/Makefile b/unittest/ob20_test/Makefile index dd3561a..6e7388f 100644 --- a/unittest/ob20_test/Makefile +++ b/unittest/ob20_test/Makefile @@ -1,7 +1,7 @@ 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 +BIN=ob20_appinfo_test ob20_trans_test ob20_clientinfo_test ob20_slowquery_test ob20_bigpacket_response_test ob20_bigpacket_request_test ob20_show_trace_test EXEC=env LD_LIBRARY_PATH=../../libmariadb/:${LD_LIBRARY_PATH} all:${BIN} .PHONY:clean @@ -11,6 +11,7 @@ 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 +ob20_show_trace_test:ob20_show_trace_test.c # run: # $(EXEC) ./ob_oracle_array_binding_test clean: diff --git a/unittest/ob20_test/ob20_show_trace_test.c b/unittest/ob20_test/ob20_show_trace_test.c new file mode 100644 index 0000000..1d6889b --- /dev/null +++ b/unittest/ob20_test/ob20_show_trace_test.c @@ -0,0 +1,79 @@ +#include +#include +#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; + const char *enable_show_trace = "set ob_enable_show_trace = true;"; + const char *disable_show_trace = "set ob_enable_show_trace = false;"; + 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, enable_show_trace)) { + printf("query error:%s\n", mysql_error(mysql)); + return 0; + } else { + RES = mysql_store_result(mysql); + } + + if (mysql_query(mysql, "drop table if exists test_trace;")) { + printf("query error:%s\n", mysql_error(mysql)); + return 0; + } else { + RES = mysql_store_result(mysql); + } + + if (mysql_query(mysql, "create table test_trace(c1 number);")) { + printf("query error:%s\n", mysql_error(mysql)); + return 0; + } else { + RES = mysql_store_result(mysql); + } + if (mysql_query(mysql, "insert into test_trace values (1);")) { + printf("query error:%s\n", mysql_error(mysql)); + return 0; + } else { + RES = mysql_store_result(mysql); + } + if (mysql_query(mysql, "commit")) { + printf("query error:%s\n", mysql_error(mysql)); + return 0; + } else { + RES = mysql_store_result(mysql); + } + if (mysql_query(mysql, disable_show_trace)) { + printf("query error:%s\n", mysql_error(mysql)); + return 0; + } else { + RES = mysql_store_result(mysql); + } + + + mysql_close(mysql); + mysql_library_end(); + return 0; +}