Merge branch 'feature_patch_228' into 'master'
patch228 See merge request oceanbase-ce-publish/obconnector-c!2
This commit is contained in:
commit
6b1835d31e
@ -144,11 +144,11 @@ 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")
|
||||
IF(UNIX AND NOT APPLE)
|
||||
SET(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -z noexecstack -z relro -z now -pie -fPIC -fstack-protector")
|
||||
SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -z noexecstack -z relro -z now -pie -fPIC -fstack-protector")
|
||||
SET(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} -z noexecstack -z relro -z now -pie -fPIC -fstack-protector")
|
||||
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -z noexecstack -z relro -z now -pie -fPIC -fstack-protector")
|
||||
ENDIF()
|
||||
|
||||
IF(CMAKE_COMPILER_IS_GNUCC)
|
||||
|
@ -1,228 +0,0 @@
|
||||
resources:
|
||||
containers:
|
||||
|
||||
- container: ubuntu-1804
|
||||
image: ubuntu:18.04
|
||||
options: "--name ubuntu-1804 --add-host=mariadb.example.com:127.0.0.1 -v /usr/bin/docker:/tmp/docker:ro"
|
||||
|
||||
jobs:
|
||||
|
||||
- job: SSLFiles
|
||||
displayName: 'Creating SSL Files'
|
||||
pool:
|
||||
vmImage: 'ubuntu-16.04'
|
||||
container: $[ variables['containerImage'] ]
|
||||
steps:
|
||||
- script: |
|
||||
java --version
|
||||
mkdir tmp
|
||||
chmod 777 .travis/gen-ssl.sh
|
||||
.travis/gen-ssl.sh mariadb.example.com tmp
|
||||
cp -R tmp $BUILD_ARTIFACTSTAGINGDIRECTORY
|
||||
displayName: 'create SSL certificates'
|
||||
|
||||
- task: PublishPipelineArtifact@0
|
||||
inputs:
|
||||
targetPath: '$(Build.ArtifactStagingDirectory)'
|
||||
artifactName: ssl_certs
|
||||
|
||||
- job: windowsTest
|
||||
displayName: 'test windows'
|
||||
pool:
|
||||
vmImage: 'windows-2019'
|
||||
dependsOn:
|
||||
- SSLFiles
|
||||
steps:
|
||||
- task: DownloadPipelineArtifact@2
|
||||
displayName: 'Download SSL files'
|
||||
inputs:
|
||||
artifactName: ssl_certs
|
||||
targetPath: $(System.DefaultWorkingDirectory)
|
||||
|
||||
- task: DownloadPipelineArtifact@2
|
||||
displayName: 'Download 10.4 server'
|
||||
inputs:
|
||||
source: 'specific'
|
||||
project: '550599d3-6165-4abd-8c86-e3f7e53a1847'
|
||||
artifact: 'Windows'
|
||||
pipeline: 3
|
||||
runVersion: 'latestFromBranch'
|
||||
runBranch: 'refs/heads/10.4-enterprise'
|
||||
downloadPath: $(System.DefaultWorkingDirectory)
|
||||
|
||||
- script: |
|
||||
for /f %%a in ('dir /B $(System.DefaultWorkingDirectory)\win_build\mariadb-enterprise-10.*-winx64.msi') do set servername=$(System.DefaultWorkingDirectory)\win_build\%%a
|
||||
echo %servername%
|
||||
msiexec /i %servername% INSTALLDIR=c:\projects\server SERVICENAME=mariadb ALLOWREMOTEROOTACCESS=true /qn
|
||||
c:\projects\server\bin\mysql.exe -e "create database testc" --user=root
|
||||
displayName: 'install server'
|
||||
|
||||
- script: |
|
||||
echo 127.0.0.1 mariadb.example.com >> %WINDIR%\System32\Drivers\Etc\Hosts
|
||||
displayName: 'set hostname'
|
||||
|
||||
- script: |
|
||||
cmake -G "Visual Studio 16 2019" -DCMAKE_BUILD_TYPE=RelWithDebInfo
|
||||
cmake --build . --config RelWithDebInfo
|
||||
displayName: 'build connector'
|
||||
|
||||
- script: |
|
||||
cd $(System.DefaultWorkingDirectory)\unittest\libmariadb
|
||||
set MARIADB_PLUGIN_DIR=$(System.DefaultWorkingDirectory)\plugins\lib\RelWithDebInfo
|
||||
ctest -V
|
||||
if %ERRORLEVEL% EQU 0 (
|
||||
echo Success
|
||||
) else (
|
||||
echo exit code is %errorlevel%
|
||||
exit /b %errorlevel%
|
||||
)
|
||||
displayName: 'run tests'
|
||||
env:
|
||||
MYSQL_TEST_HOST: "mariadb.example.com"
|
||||
MYSQL_TEST_USER: 'someUser'
|
||||
MYSQL_TEST_DB: 'testc'
|
||||
MYSQL_TEST_PORT: 3306
|
||||
TEST_SSL_CA_FILE: "$(System.DefaultWorkingDirectory)/tmp/server.crt"
|
||||
TEST_SSL_CLIENT_KEY_FILE: "$(System.DefaultWorkingDirectory)/tmp/client.key"
|
||||
TEST_SSL_CLIENT_CERT_FILE: "$(System.DefaultWorkingDirectory)/tmp/client.crt"
|
||||
TEST_SSL_CLIENT_KEYSTORE_FILE: "$(System.DefaultWorkingDirectory)/tmp/client-keystore.p12"
|
||||
|
||||
- job: RunInContainer
|
||||
pool:
|
||||
vmImage: 'ubuntu-16.04'
|
||||
displayName: 'test ubuntu bionic'
|
||||
dependsOn:
|
||||
- SSLFiles
|
||||
strategy:
|
||||
matrix:
|
||||
ubuntu-1804:
|
||||
containerImage: ubuntu-1804
|
||||
containerName: bionic
|
||||
|
||||
container: $[variables['containerImage']]
|
||||
|
||||
steps:
|
||||
|
||||
- task: DownloadPipelineArtifact@2
|
||||
inputs:
|
||||
artifactName: ssl_certs
|
||||
targetPath: $(System.DefaultWorkingDirectory)
|
||||
|
||||
- script: /tmp/docker exec -t -u 0 $(containerImage) sh -c "apt-get update && DEBIAN_FRONTEND=noninteractive apt-get -o Dpkg::Options::="--force-confold" -y install sudo"
|
||||
displayName: Set up sudo
|
||||
|
||||
- task: DownloadPipelineArtifact@2
|
||||
displayName: 'Download 10.4 enterprise server artifact files'
|
||||
inputs:
|
||||
source: 'specific'
|
||||
project: '550599d3-6165-4abd-8c86-e3f7e53a1847'
|
||||
artifact: '$(containerImage)'
|
||||
pipeline: 3
|
||||
runVersion: 'latestFromBranch'
|
||||
runBranch: 'refs/heads/10.4-enterprise'
|
||||
downloadPath: $(System.DefaultWorkingDirectory)
|
||||
|
||||
- task: DownloadPipelineArtifact@2
|
||||
displayName: 'Download galera server artifact files'
|
||||
inputs:
|
||||
source: 'specific'
|
||||
project: '550599d3-6165-4abd-8c86-e3f7e53a1847'
|
||||
artifact: $(containerImage)
|
||||
runVersion: 'latestFromBranch'
|
||||
pipeline: 2
|
||||
runBranch: 'refs/heads/es-mariadb-4.x'
|
||||
downloadPath: $(System.DefaultWorkingDirectory)
|
||||
|
||||
|
||||
- script: |
|
||||
tar xf mariadb-enterprise*
|
||||
|
||||
sudo ln -fs /usr/share/zoneinfo/UTC /etc/localtime
|
||||
|
||||
sudo apt-get update && sudo apt-get install -y --no-install-recommends apt-transport-https ca-certificates tzdata pwgen
|
||||
export DEBIAN_FRONTEND="noninteractive"
|
||||
sudo debconf-set-selections <<< "mariadb-server-10.4 mysql-server/root_password password P4ssw@rd"
|
||||
sudo debconf-set-selections <<< "mariadb-server-10.4 mysql-server/root_password_again password P4ssw@rd"
|
||||
sudo apt-get update -y
|
||||
sudo apt-get install --allow-unauthenticated -f -y libssl-dev libaio1 libaio-dev libxml2 libcurl4 curl libc-dev linux-libc-dev libc-dev-bin libdbi-perl rsync socat libnuma1 zlib1g-dev libreadline5 libjemalloc1 libsnappy1v5 libcrack2 gawk lsof psmisc perl libreadline5
|
||||
|
||||
cd mariadb-enterprise*/
|
||||
sudo groupadd mysql
|
||||
sudo useradd -g mysql mysql
|
||||
|
||||
export PROJ_PATH=`pwd`
|
||||
echo $PROJ_PATH
|
||||
|
||||
cat <<EOT >> my.cnf
|
||||
[mysqld]
|
||||
port=3306
|
||||
max_allowed_packet=16M
|
||||
datadir=$PROJ_PATH/data
|
||||
socket=/tmp/mysql.sock
|
||||
user=mysql
|
||||
ssl-ca=$(System.DefaultWorkingDirectory)/tmp/ca.crt
|
||||
ssl-cert=$(System.DefaultWorkingDirectory)/tmp/server.crt
|
||||
ssl-key=$(System.DefaultWorkingDirectory)/tmp/server.key
|
||||
EOT
|
||||
|
||||
sudo chown mysql $PROJ_PATH/my.cnf
|
||||
sudo tail -n 5000 $PROJ_PATH/my.cnf
|
||||
|
||||
sudo chmod 777 $PROJ_PATH
|
||||
sudo ln -s $PROJ_PATH /usr/local/mysql
|
||||
|
||||
sudo ./scripts/mysql_install_db --defaults-file=$PROJ_PATH/my.cnf --user=mysql
|
||||
sudo chown -R root .
|
||||
sudo chown -R mysql data
|
||||
|
||||
export PATH=$PATH:$PROJ_PATH/bin/
|
||||
|
||||
env:
|
||||
WORKING_DIR: $(System.DefaultWorkingDirectory)
|
||||
displayName: 'install server'
|
||||
|
||||
- script: |
|
||||
sudo apt-get install -f -y make cmake
|
||||
cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -DWITH_SSL=OPENSSL -DCERT_PATH=$(System.DefaultWorkingDirectory)/tmp
|
||||
make
|
||||
displayName: 'Build'
|
||||
|
||||
- script: |
|
||||
cd mariadb-enterprise*/
|
||||
sudo ./bin/mysqld --defaults-file=./my.cnf &
|
||||
|
||||
for i in {30..0}; do
|
||||
if sudo ./bin/mysql -e "SELECT 1" &> /dev/null; then
|
||||
echo 'MySQL connected...'
|
||||
break
|
||||
fi
|
||||
echo 'MySQL init process in progress...'
|
||||
sleep 1
|
||||
done
|
||||
if [ "$i" = 0 ]; then
|
||||
echo >&2 'MySQL init process failed.'
|
||||
sudo ./bin/mysql -e "SELECT 1"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
sudo ./bin/mysql -e "CREATE DATABASE testc;"
|
||||
|
||||
echo "Running tests"
|
||||
cd ../unittest/libmariadb
|
||||
ctest -V
|
||||
if [ $? -ne 0 ]; then
|
||||
exit 1
|
||||
fi
|
||||
cd $(System.DefaultWorkingDirectory)/mariadb-enterprise*/
|
||||
sudo ./bin/mysqladmin shutdown
|
||||
env:
|
||||
MYSQL_TEST_HOST: mariadb.example.com
|
||||
MYSQL_TEST_DB: testc
|
||||
MYSQL_TEST_USER: 'someUser'
|
||||
MYSQL_TEST_PORT: 3306
|
||||
MYSQL_TEST_TRAVIS: 1
|
||||
TEST_SSL_CA_FILE: "$(System.DefaultWorkingDirectory)/tmp/server.crt"
|
||||
TEST_SSL_CLIENT_KEY_FILE: "$(System.DefaultWorkingDirectory)/tmp/client.key"
|
||||
TEST_SSL_CLIENT_CERT_FILE: "$(System.DefaultWorkingDirectory)/tmp/client.crt"
|
||||
TEST_SSL_CLIENT_KEYSTORE_FILE: "$(System.DefaultWorkingDirectory)/tmp/client-keystore.p12"
|
||||
displayName: 'run tests'
|
@ -39,7 +39,7 @@ static inline uint ma_extended_type_info_rows(const MYSQL *mysql)
|
||||
|
||||
static inline uint ma_result_set_rows(const MYSQL *mysql)
|
||||
{
|
||||
return ma_has_extended_type_info(mysql) ? 9 : 8;
|
||||
return ma_has_extended_type_info(mysql) ? 8 : 7;
|
||||
}
|
||||
|
||||
MA_FIELD_EXTENSION *ma_field_extension_deep_dup(MA_MEM_ROOT *memroot,
|
||||
|
@ -200,6 +200,7 @@ extern const char *SQLSTATE_UNKNOWN;
|
||||
typedef struct st_mysql_rows {
|
||||
struct st_mysql_rows *next; /* list of rows */
|
||||
MYSQL_ROW data;
|
||||
unsigned long* data_length;
|
||||
unsigned long length;
|
||||
} MYSQL_ROWS;
|
||||
|
||||
|
@ -47,6 +47,13 @@ typedef enum enum_types {
|
||||
TYPE_SHORT,
|
||||
TYPE_FLOAT,
|
||||
TYPE_DOUBLE,
|
||||
TYPE_NVARCHAR2,
|
||||
TYPE_OB_NUMBER_FLOAT,
|
||||
TYPE_OB_TIMESTAMP_NANO,
|
||||
TYPE_OB_TIMESTAMP_WITH_TIME_ZONE,
|
||||
TYPE_OB_TIMESTAMP_WITH_LOCAL_TIME_ZONE,
|
||||
TYPE_OB_INTERVAL_YM,
|
||||
TYPE_OB_INTERVAL_DS,
|
||||
TYPE_UNKNOW,
|
||||
TYPE_MAX
|
||||
} enum_types;
|
||||
|
@ -17,12 +17,13 @@ typedef struct _st_obclient_lb_AddressList {
|
||||
}ObClientLbAddressList;
|
||||
|
||||
typedef struct _st_obclient_lb_config{
|
||||
int retry_all_downs; //总的次数
|
||||
int black_remove_strategy; //2001
|
||||
int black_remove_timeout; //移出黑名单时间
|
||||
int black_append_strategy; //3002 NORMAL, 3001 RETRYDURATION
|
||||
int black_append_retrytimes; //单个address次数
|
||||
int black_append_duration; //时间duration内,执行>= retrytimes次加黑
|
||||
unsigned int retry_all_downs; //总的次数
|
||||
unsigned int retry_timeout; // LB 阶段总的超时时间(ms)
|
||||
unsigned int black_remove_strategy; //2001
|
||||
unsigned int black_remove_timeout; //移出黑名单时间(ms)
|
||||
unsigned int black_append_strategy; //3002 NORMAL, 3001 RETRYDURATION
|
||||
unsigned int black_append_retrytimes; //单个address次数
|
||||
unsigned int black_append_duration; //时间duration内(ms),执行>= retrytimes次加黑
|
||||
|
||||
unsigned int mysql_connect_timeout;
|
||||
unsigned int mysql_read_timeout;
|
||||
@ -42,6 +43,7 @@ typedef struct _st_obclient_lb_config{
|
||||
my_bool mysql_opt_interactive;
|
||||
my_bool mysql_report_data_truncation;
|
||||
my_bool mysql_opt_reconnect;
|
||||
char* mysql_read_default_file;
|
||||
|
||||
my_bool mysql_opt_use_ssl;
|
||||
my_bool mysql_opt_ssl_verify_server_cert;
|
||||
@ -59,6 +61,10 @@ typedef struct _st_obclient_lb_config{
|
||||
MYSQL* ob_mysql_real_connect(MYSQL* mysql, const char* tns_name, ObClientLbAddressList *addr_list, ObClientLbConfig *config,
|
||||
const char *user, const char *passwd, const char *db, const char *unix_socket, unsigned long client_flag, ObClientLbAddress* success);
|
||||
|
||||
//addr_list [fe80::42:acff:fe11:2%eth0]:38884,[xxx.xxx.xxx.xxx]:2222,xxx.xxx.xxx.xxx:38884
|
||||
MYSQL* ob_mysql_real_connect2(MYSQL* mysql, const char* tns_name, const char *addr_list, ObClientLbConfig *config,
|
||||
const char *user, const char *passwd, const char *db, const char *unix_socket, unsigned long client_flag, char* success, int len_success);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -342,6 +342,7 @@ SET(MARIADB_NONBLOCK_SYMBOLS
|
||||
get_ob_lob_payload_data_len
|
||||
stmt_get_data_from_lobv2
|
||||
ob_mysql_real_connect
|
||||
ob_mysql_real_connect2
|
||||
ob_get_libobclient_version
|
||||
ob_set_socket5_proxy
|
||||
)
|
||||
|
@ -1535,6 +1535,7 @@ static ulong get_complex_header_length(enum_types type) {
|
||||
return sizeof(MYSQL_COMPLEX_BIND_OBJECT);
|
||||
case TYPE_COLLECTION:
|
||||
return sizeof(MYSQL_COMPLEX_BIND_ARRAY);
|
||||
case TYPE_NVARCHAR2:
|
||||
case TYPE_VARCHAR2:
|
||||
case TYPE_CHAR:
|
||||
case TYPE_RAW:
|
||||
@ -1548,6 +1549,14 @@ static ulong get_complex_header_length(enum_types type) {
|
||||
case TYPE_FLOAT:
|
||||
case TYPE_DOUBLE:
|
||||
return sizeof(MYSQL_COMPLEX_BIND_BASIC);
|
||||
case TYPE_OB_NUMBER_FLOAT:
|
||||
return sizeof(MYSQL_COMPLEX_BIND_STRING);
|
||||
case TYPE_OB_INTERVAL_YM:
|
||||
case TYPE_OB_INTERVAL_DS:
|
||||
case TYPE_OB_TIMESTAMP_NANO:
|
||||
case TYPE_OB_TIMESTAMP_WITH_LOCAL_TIME_ZONE:
|
||||
case TYPE_OB_TIMESTAMP_WITH_TIME_ZONE:
|
||||
return sizeof(MYSQL_COMPLEX_BIND_BASIC);
|
||||
default:
|
||||
return sizeof(MYSQL_COMPLEX_BIND_BASIC);
|
||||
}
|
||||
@ -1671,6 +1680,122 @@ static void fetch_result_double_complex(MYSQL_COMPLEX_BIND_BASIC *header,
|
||||
return;
|
||||
}
|
||||
|
||||
static void read_binary_interval(int type, ORACLE_INTERVAL *tm, uchar **pos)
|
||||
{
|
||||
uint length = net_field_length(pos);
|
||||
uchar *to = *pos;
|
||||
ORACLE_INTERVAL *interval = tm;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case MYSQL_TYPE_OB_INTERVAL_DS: {
|
||||
if (length == 14) {
|
||||
interval->mysql_type = MYSQL_TYPE_OB_INTERVAL_DS;
|
||||
interval->data_symbol = (to[0] > 0 ? -1 : 1);
|
||||
interval->data_object.ds_object.ds_day = sint4korr(to + 1);
|
||||
interval->data_object.ds_object.ds_hour = to[5];
|
||||
interval->data_object.ds_object.ds_minute = to[6];
|
||||
interval->data_object.ds_object.ds_second = to[7];
|
||||
interval->data_object.ds_object.ds_frac_second = sint4korr(to + 8);
|
||||
interval->data_object.ds_object.ds_day_scale = to[12];
|
||||
interval->data_object.ds_object.ds_frac_second_scale = to[13];
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MYSQL_TYPE_OB_INTERVAL_YM: {
|
||||
if (length == 7) {
|
||||
interval->mysql_type = MYSQL_TYPE_OB_INTERVAL_YM;
|
||||
interval->data_symbol = (to[0] > 0 ? -1 : 1);
|
||||
interval->data_object.ym_object.ym_year = sint4korr(to + 1);
|
||||
interval->data_object.ym_object.ym_month = to[5];
|
||||
interval->data_object.ym_object.ym_scale = to[6];
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
*pos += length;
|
||||
}
|
||||
static void fetch_result_ob_interval_complex(MYSQL_COMPLEX_BIND_BASIC *header,
|
||||
MYSQL_BIND *param,
|
||||
uchar **row)
|
||||
{
|
||||
ORACLE_INTERVAL *tm = NULL;
|
||||
|
||||
tm = fetch_result_complex_alloc_space(header, param, sizeof(ORACLE_INTERVAL));
|
||||
if (NULL == tm) {
|
||||
return;
|
||||
}
|
||||
|
||||
read_binary_interval(header->buffer_type, tm, row);
|
||||
return;
|
||||
}
|
||||
|
||||
static void fetch_result_ob_timestamp_complex(MYSQL_COMPLEX_BIND_BASIC *header,
|
||||
MYSQL_BIND *param,
|
||||
uchar **row)
|
||||
{
|
||||
void *buffer = NULL;
|
||||
ulong bufferlen = 0;
|
||||
ulong length = 0;
|
||||
ulong tz_length = 0;
|
||||
ulong buffer_offset = 0;
|
||||
ulong buffer_length = 0;
|
||||
ORACLE_TIME *tm = NULL;
|
||||
uchar *to = NULL;
|
||||
|
||||
length = net_field_length(row);
|
||||
bufferlen = sizeof(ORACLE_TIME) + length; //+length 包括TZ信息
|
||||
buffer = fetch_result_complex_alloc_space((MYSQL_COMPLEX_BIND_HEADER *)header, param, bufferlen);
|
||||
if (NULL == buffer || length < 12) {
|
||||
return;
|
||||
}
|
||||
|
||||
to = *row;
|
||||
|
||||
tm = (ORACLE_TIME*)buffer;
|
||||
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 < bufferlen) {
|
||||
memcpy((char*)buffer + buffer_offset, to, tz_length);
|
||||
tm->tz_name = (char*)buffer + buffer_offset;
|
||||
buffer_offset += tz_length;
|
||||
*((char*)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 < bufferlen) {
|
||||
memcpy((char*)buffer + buffer_offset, to, tz_length);
|
||||
tm->tz_abbr = (char*)buffer + buffer_offset;
|
||||
buffer_offset += tz_length;
|
||||
*((char*)buffer + buffer_offset) = '\0';
|
||||
buffer_offset++;
|
||||
}
|
||||
to += tz_length;
|
||||
}
|
||||
*row = to;
|
||||
return;
|
||||
}
|
||||
|
||||
static void fetch_result_object_complex(MYSQL_COMPLEX_BIND_OBJECT *header,
|
||||
MYSQL_BIND *param,
|
||||
@ -1725,6 +1850,7 @@ static void fetch_result_object_complex(MYSQL_COMPLEX_BIND_OBJECT *header,
|
||||
header->length = (char*)buffer - (char*)header->buffer;
|
||||
return;
|
||||
}
|
||||
|
||||
static void read_binary_datetime(MYSQL_TIME *tm, uchar **pos)
|
||||
{
|
||||
uint length= net_field_length(pos);
|
||||
@ -1850,11 +1976,13 @@ static void fetch_result_complex(MYSQL_BIND *param, void *buffer,
|
||||
CHILD_TYPE *child, uchar **row)
|
||||
{
|
||||
switch (child->type) {
|
||||
case TYPE_OB_NUMBER_FLOAT:
|
||||
case TYPE_NUMBER:
|
||||
{
|
||||
fetch_result_str_complex((MYSQL_COMPLEX_BIND_STRING *)buffer, param, row);
|
||||
break;
|
||||
}
|
||||
case TYPE_NVARCHAR2:
|
||||
case TYPE_VARCHAR2:
|
||||
case TYPE_CHAR:
|
||||
{
|
||||
@ -1911,6 +2039,19 @@ static void fetch_result_complex(MYSQL_BIND *param, void *buffer,
|
||||
fetch_result_double_complex((MYSQL_COMPLEX_BIND_BASIC *)buffer, param, row);
|
||||
break;
|
||||
}
|
||||
case TYPE_OB_INTERVAL_DS:
|
||||
case TYPE_OB_INTERVAL_YM:
|
||||
{
|
||||
fetch_result_ob_interval_complex((MYSQL_COMPLEX_BIND_BASIC *)buffer, param, row);
|
||||
break;
|
||||
}
|
||||
case TYPE_OB_TIMESTAMP_NANO:
|
||||
case TYPE_OB_TIMESTAMP_WITH_TIME_ZONE:
|
||||
case TYPE_OB_TIMESTAMP_WITH_LOCAL_TIME_ZONE:
|
||||
{
|
||||
fetch_result_ob_timestamp_complex((MYSQL_COMPLEX_BIND_BASIC *)buffer, param, row);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
*param->error= 1;
|
||||
break;
|
||||
@ -1987,6 +2128,11 @@ static uint mysql_type_to_object_type(uint mysql_type)
|
||||
object_type = TYPE_VARCHAR2;
|
||||
break;
|
||||
}
|
||||
case MYSQL_TYPE_OB_NVARCHAR2:
|
||||
{
|
||||
object_type = TYPE_NVARCHAR2;
|
||||
break;
|
||||
}
|
||||
case MYSQL_TYPE_OB_RAW:
|
||||
{
|
||||
object_type = TYPE_RAW;
|
||||
@ -2007,6 +2153,36 @@ static uint mysql_type_to_object_type(uint mysql_type)
|
||||
object_type = TYPE_COLLECTION;
|
||||
break;
|
||||
}
|
||||
case MYSQL_TYPE_OB_NUMBER_FLOAT:
|
||||
{
|
||||
object_type = TYPE_OB_NUMBER_FLOAT;
|
||||
break;
|
||||
}
|
||||
case MYSQL_TYPE_OB_INTERVAL_DS:
|
||||
{
|
||||
object_type = TYPE_OB_INTERVAL_DS;
|
||||
break;
|
||||
}
|
||||
case MYSQL_TYPE_OB_INTERVAL_YM:
|
||||
{
|
||||
object_type = TYPE_OB_INTERVAL_YM;
|
||||
break;
|
||||
}
|
||||
case MYSQL_TYPE_OB_TIMESTAMP_NANO:
|
||||
{
|
||||
object_type = TYPE_OB_TIMESTAMP_NANO;
|
||||
break;
|
||||
}
|
||||
case MYSQL_TYPE_OB_TIMESTAMP_WITH_TIME_ZONE:
|
||||
{
|
||||
object_type = TYPE_OB_TIMESTAMP_WITH_TIME_ZONE;
|
||||
break;
|
||||
}
|
||||
case MYSQL_TYPE_OB_TIMESTAMP_WITH_LOCAL_TIME_ZONE:
|
||||
{
|
||||
object_type = TYPE_OB_TIMESTAMP_WITH_LOCAL_TIME_ZONE;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
object_type = TYPE_UNKNOW;
|
||||
break;
|
||||
@ -2031,6 +2207,12 @@ static void fill_complex_type(MYSQL_BIND *param, void *buffer,
|
||||
header->buffer_type = MYSQL_TYPE_VARCHAR;
|
||||
break;
|
||||
}
|
||||
case TYPE_NVARCHAR2:
|
||||
{
|
||||
MYSQL_COMPLEX_BIND_STRING *header = (MYSQL_COMPLEX_BIND_STRING *)buffer;
|
||||
header->buffer_type = MYSQL_TYPE_OB_NVARCHAR2;
|
||||
break;
|
||||
}
|
||||
case TYPE_RAW:
|
||||
{
|
||||
MYSQL_COMPLEX_BIND_STRING *header = (MYSQL_COMPLEX_BIND_STRING *)buffer;
|
||||
@ -2079,6 +2261,42 @@ static void fill_complex_type(MYSQL_BIND *param, void *buffer,
|
||||
header->buffer_type = MYSQL_TYPE_DOUBLE;
|
||||
break;
|
||||
}
|
||||
case TYPE_OB_NUMBER_FLOAT:
|
||||
{
|
||||
MYSQL_COMPLEX_BIND_STRING *header = (MYSQL_COMPLEX_BIND_STRING *)buffer;
|
||||
header->buffer_type = MYSQL_TYPE_OB_NUMBER_FLOAT;
|
||||
break;
|
||||
}
|
||||
case TYPE_OB_INTERVAL_DS:
|
||||
{
|
||||
MYSQL_COMPLEX_BIND_BASIC *header = (MYSQL_COMPLEX_BIND_BASIC *)buffer;
|
||||
header->buffer_type = MYSQL_TYPE_OB_INTERVAL_DS;
|
||||
break;
|
||||
}
|
||||
case TYPE_OB_INTERVAL_YM:
|
||||
{
|
||||
MYSQL_COMPLEX_BIND_BASIC *header = (MYSQL_COMPLEX_BIND_BASIC *)buffer;
|
||||
header->buffer_type = MYSQL_TYPE_OB_INTERVAL_YM;
|
||||
break;
|
||||
}
|
||||
case TYPE_OB_TIMESTAMP_NANO:
|
||||
{
|
||||
MYSQL_COMPLEX_BIND_BASIC *header = (MYSQL_COMPLEX_BIND_BASIC *)buffer;
|
||||
header->buffer_type = MYSQL_TYPE_OB_TIMESTAMP_NANO;
|
||||
break;
|
||||
}
|
||||
case TYPE_OB_TIMESTAMP_WITH_TIME_ZONE:
|
||||
{
|
||||
MYSQL_COMPLEX_BIND_BASIC *header = (MYSQL_COMPLEX_BIND_BASIC *)buffer;
|
||||
header->buffer_type = MYSQL_TYPE_OB_TIMESTAMP_WITH_TIME_ZONE;
|
||||
break;
|
||||
}
|
||||
case TYPE_OB_TIMESTAMP_WITH_LOCAL_TIME_ZONE:
|
||||
{
|
||||
MYSQL_COMPLEX_BIND_BASIC *header = (MYSQL_COMPLEX_BIND_BASIC *)buffer;
|
||||
header->buffer_type = MYSQL_TYPE_OB_TIMESTAMP_WITH_LOCAL_TIME_ZONE;
|
||||
break;
|
||||
}
|
||||
case TYPE_OBJECT:
|
||||
{
|
||||
MYSQL_COMPLEX_BIND_OBJECT *header = (MYSQL_COMPLEX_BIND_OBJECT *)buffer;
|
||||
|
@ -946,15 +946,18 @@ static size_t rset_field_offsets[]= {
|
||||
|
||||
MYSQL_FIELD *
|
||||
unpack_fields(const MYSQL *mysql,
|
||||
MYSQL_DATA *data, MA_MEM_ROOT *alloc, uint fields,
|
||||
my_bool default_value)
|
||||
MYSQL_DATA *data, MA_MEM_ROOT *alloc, uint fields, my_bool default_value)
|
||||
{
|
||||
#define CHECK_PKT_LENGTH(len1, len2) {if ((len1) > (len2)) goto error;}
|
||||
#define CHECK_PKT_LENGTH_END(len1, len2) {if ((len1) >= (len2)) goto error;}
|
||||
|
||||
MYSQL_ROWS *row;
|
||||
MYSQL_FIELD *field,*result;
|
||||
uchar *p; /* use unsigned char for data to avoid convert error for char to uint. */
|
||||
unsigned int i, field_count= sizeof(rset_field_offsets)/sizeof(size_t)/2;
|
||||
uchar *complex_type;
|
||||
ulong len;
|
||||
uchar *complex_type = NULL;
|
||||
ulong len = 0;
|
||||
ulong pkt_len = 0;
|
||||
|
||||
field=result=(MYSQL_FIELD*) ma_alloc_root(alloc,sizeof(MYSQL_FIELD)*fields);
|
||||
if (!result)
|
||||
@ -1016,27 +1019,32 @@ unpack_fields(const MYSQL *mysql,
|
||||
|
||||
if (MYSQL_TYPE_OBJECT == field->type) {
|
||||
complex_type = (uchar*)row->data[i];
|
||||
pkt_len = row->data_length[i];
|
||||
|
||||
len=(ulong) net_field_length(&complex_type);
|
||||
field->owner_name_length = len;
|
||||
if (0 == len) {
|
||||
field->owner_name = NULL;
|
||||
} else {
|
||||
field->owner_name = (unsigned char *)ma_memdup_root(alloc, (char*)complex_type, len+1);
|
||||
CHECK_PKT_LENGTH(len, (pkt_len - ((char*)complex_type - row->data[i])));
|
||||
field->owner_name = (unsigned char *)ma_memdup_root(alloc, (char*)complex_type, len + 1);
|
||||
field->owner_name[len] = 0;
|
||||
complex_type += len;
|
||||
}
|
||||
|
||||
CHECK_PKT_LENGTH_END((char*)complex_type - row->data[i], (long)pkt_len);
|
||||
len=(ulong) net_field_length(&complex_type);
|
||||
field->type_name_length = len;
|
||||
if (0 == len) {
|
||||
field->type_name = NULL;
|
||||
} else {
|
||||
CHECK_PKT_LENGTH(len, (pkt_len - ((char*)complex_type - row->data[i])));
|
||||
field->type_name = (unsigned char *)ma_memdup_root(alloc, (char*)complex_type, len+1);
|
||||
field->type_name[len] = 0;
|
||||
complex_type += len;
|
||||
}
|
||||
|
||||
CHECK_PKT_LENGTH_END((char*)complex_type - row->data[i], (long)pkt_len);
|
||||
field->version = (ulong) net_field_length(&complex_type);
|
||||
|
||||
if (0 == len) {
|
||||
@ -1044,6 +1052,7 @@ unpack_fields(const MYSQL *mysql,
|
||||
complex_type++;
|
||||
|
||||
if (MYSQL_TYPE_OBJECT == field->elem_type) {
|
||||
CHECK_PKT_LENGTH_END((char*)complex_type - row->data[i], (long)pkt_len);
|
||||
len=(ulong) net_field_length(&complex_type);
|
||||
field->elem_owner_name_length = len;
|
||||
if (0 == len) {
|
||||
@ -1051,35 +1060,53 @@ unpack_fields(const MYSQL *mysql,
|
||||
}
|
||||
else
|
||||
{
|
||||
field->elem_owner_name = (unsigned char *)ma_memdup_root(alloc, (char *)complex_type, len);
|
||||
CHECK_PKT_LENGTH(len, (pkt_len - ((char*)complex_type - row->data[i])));
|
||||
field->elem_owner_name = (unsigned char *)ma_memdup_root(alloc, (char *)complex_type, len + 1);
|
||||
field->elem_owner_name[len] = 0;
|
||||
complex_type += len;
|
||||
}
|
||||
|
||||
CHECK_PKT_LENGTH_END((char*)complex_type - row->data[i], (long)pkt_len);
|
||||
len=(ulong) net_field_length(&complex_type);
|
||||
field->elem_type_name_length = len;
|
||||
if (0 == len) {
|
||||
field->elem_type_name = NULL;
|
||||
} else {
|
||||
field->elem_type_name = (unsigned char *)ma_memdup_root(alloc, (char*)complex_type, len);
|
||||
CHECK_PKT_LENGTH(len, (pkt_len - ((char*)complex_type - row->data[i])));
|
||||
field->elem_type_name = (unsigned char *)ma_memdup_root(alloc, (char*)complex_type, len+1);
|
||||
field->elem_type_name[len] = 0;
|
||||
complex_type += len;
|
||||
}
|
||||
|
||||
CHECK_PKT_LENGTH_END((char*)complex_type - row->data[i], (long)pkt_len);
|
||||
field->elem_version = (ulong) net_field_length(&complex_type);
|
||||
}
|
||||
}
|
||||
|
||||
len = (ulong) net_field_length(&complex_type);
|
||||
|
||||
if (default_value && len > 0) {
|
||||
field->def=ma_memdup_root(alloc, (char*)complex_type, len);
|
||||
} else {
|
||||
field->def=0;
|
||||
//object 检查下长度,这里后面应该是没有数据了,防止core
|
||||
if ((char*)complex_type - row->data[i] > (long)pkt_len)
|
||||
{
|
||||
//CHECK_PKT_LENGTH_END((char*)complex_type - row->data[i], pkt_len);
|
||||
len = (ulong)net_field_length(&complex_type);
|
||||
if (default_value && len > 0 && len != NULL_LENGTH) {
|
||||
field->def = ma_memdup_root(alloc, (char*)complex_type, len);
|
||||
} else {
|
||||
field->def = 0;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (default_value && row->data[i]) {
|
||||
field->def=ma_strdup_root(alloc,(char*) row->data[i]);
|
||||
/*
|
||||
mthd_my_read_query_result ma_result_set_rows 9:8->8:7, 保证最后的row->data[i]里面含有length
|
||||
为了兼容PS协议/二合一协议object处理,最后row->data[i]里面包含length,所以这里要先解析length
|
||||
*/
|
||||
if (default_value && row->data[i] && row->data_length[i] > 0) {
|
||||
len = (ulong)net_field_length(&(row->data[i]));
|
||||
if (default_value && len > 0 && len != NULL_LENGTH) {
|
||||
field->def = ma_strdup_root(alloc, (char*)row->data[i]);
|
||||
} else {
|
||||
field->def = 0;
|
||||
}
|
||||
} else {
|
||||
field->def=0;
|
||||
field->def = 0;
|
||||
}
|
||||
}
|
||||
field->def_length= 0;
|
||||
@ -1580,7 +1607,7 @@ MYSQL_DATA *mthd_my_read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields,
|
||||
uint field;
|
||||
ulong pkt_len;
|
||||
ulong len;
|
||||
uchar *cp;
|
||||
uchar *cp, *end_cp;
|
||||
char *to, *end_to;
|
||||
MYSQL_DATA *result;
|
||||
MYSQL_ROWS **prev_ptr,*cur;
|
||||
@ -1603,6 +1630,7 @@ MYSQL_DATA *mthd_my_read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields,
|
||||
|
||||
while (*(cp=net->read_pos) != 254 || pkt_len >= 8)
|
||||
{
|
||||
end_cp = cp + pkt_len;
|
||||
if (mysql_fields) {
|
||||
for (field=0 ; field < fields ; field++) {
|
||||
if ((len=(ulong) net_field_length(&cp)) == NULL_LENGTH) {
|
||||
@ -1632,17 +1660,21 @@ MYSQL_DATA *mthd_my_read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields,
|
||||
}
|
||||
}
|
||||
cp = net->read_pos;
|
||||
end_cp = cp + pkt_len;
|
||||
result->rows++;
|
||||
if (!(cur= (MYSQL_ROWS*) ma_alloc_root(&result->alloc,
|
||||
sizeof(MYSQL_ROWS))) ||
|
||||
if (!(cur= (MYSQL_ROWS*) ma_alloc_root(&result->alloc, sizeof(MYSQL_ROWS))) ||
|
||||
!(cur->data= ((MYSQL_ROW)
|
||||
ma_alloc_root(&result->alloc,
|
||||
(fields+1)*sizeof(char *)+fields+pkt_len))))
|
||||
ma_alloc_root(&result->alloc, (fields+1)*sizeof(char *)+fields+pkt_len))) ||
|
||||
!(cur->data_length= (unsigned long*)
|
||||
ma_alloc_root(&result->alloc, (fields + 1) * sizeof(unsigned long)))
|
||||
)
|
||||
{
|
||||
free_rows(result);
|
||||
SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
|
||||
return(0);
|
||||
}
|
||||
memset(cur->data, 0, (fields + 1) * sizeof(char *) + fields + pkt_len);
|
||||
memset(cur->data_length, 0, (fields + 1) * sizeof(unsigned long));
|
||||
*prev_ptr=cur;
|
||||
prev_ptr= &cur->next;
|
||||
to= (char*) (cur->data+fields+1);
|
||||
@ -1652,6 +1684,7 @@ MYSQL_DATA *mthd_my_read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields,
|
||||
if ((len=(ulong) net_field_length(&cp)) == NULL_LENGTH)
|
||||
{ /* null field */
|
||||
cur->data[field] = 0;
|
||||
cur->data_length[field] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1682,6 +1715,7 @@ MYSQL_DATA *mthd_my_read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields,
|
||||
to+=convert_len+1;
|
||||
cp+=len;
|
||||
len = convert_len;
|
||||
cur->data_length[field] = len;
|
||||
is_done = 1;
|
||||
} else if (mysql_fields[field].type == MYSQL_TYPE_OB_RAW) {
|
||||
uchar *end = cp + len;
|
||||
@ -1691,6 +1725,7 @@ MYSQL_DATA *mthd_my_read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields,
|
||||
|
||||
(*to++)=0;
|
||||
len *= 2;
|
||||
cur->data_length[field] = len;
|
||||
is_done = 1;
|
||||
} else if (mysql_fields[field].type == MYSQL_TYPE_OB_INTERVAL_YM
|
||||
|| mysql_fields[field].type == MYSQL_TYPE_OB_INTERVAL_DS) {
|
||||
@ -1702,6 +1737,7 @@ MYSQL_DATA *mthd_my_read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields,
|
||||
to+=convert_len+1;
|
||||
cp+=len;
|
||||
len = convert_len;
|
||||
cur->data_length[field] = len;
|
||||
is_done = 1;
|
||||
}
|
||||
}
|
||||
@ -1709,6 +1745,7 @@ MYSQL_DATA *mthd_my_read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields,
|
||||
memcpy(to,(char*) cp,len); to[len]=0;
|
||||
to+=len+1;
|
||||
cp+=len;
|
||||
cur->data_length[field] = len;
|
||||
is_done = 1;
|
||||
}
|
||||
|
||||
@ -1719,8 +1756,12 @@ MYSQL_DATA *mthd_my_read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields,
|
||||
}
|
||||
}
|
||||
}
|
||||
memcpy(to, (char *)cp, (ulong)(end_to - to));
|
||||
convert_len = (ulong)(end_cp - cp >= 0 ? (end_cp - cp) : 0);
|
||||
memcpy(to, (char *)cp, convert_len);
|
||||
//convert_len = (ulong)(end_to - to >= 0 ? (end_to - to) : 0);
|
||||
//memcpy(to, (char *)cp, (ulong)(end_to - to));
|
||||
cur->data[field]=to; /* End of last field */
|
||||
cur->data_length[field] = convert_len; //convert_len
|
||||
if ((pkt_len=ma_net_safe_read(mysql)) == packet_error)
|
||||
{
|
||||
free_rows(result);
|
||||
@ -2147,7 +2188,7 @@ ma_set_ob_connect_attrs(MYSQL *mysql)
|
||||
cap |= OBCLIENT_CAP_PROXY_LOCAL_INFILES;
|
||||
}
|
||||
|
||||
snprintf(cap_buf, OB_MAX_UINT64_BUF_LEN, "%lu", cap);
|
||||
snprintf(cap_buf, OB_MAX_UINT64_BUF_LEN, "%llu", cap);
|
||||
|
||||
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");
|
||||
@ -2156,7 +2197,7 @@ ma_set_ob_connect_attrs(MYSQL *mysql)
|
||||
|
||||
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);
|
||||
snprintf(caplob_buf, OB_MAX_UINT64_BUF_LEN, "%llu", caplob);
|
||||
rc += mysql_optionsv(mysql, MYSQL_OPT_CONNECT_ATTR_ADD, OB_MYSQL_LOB_LOCATOR_V2, caplob_buf);
|
||||
}
|
||||
if (mysql->proxy_user && mysql->proxy_user[0]) {
|
||||
|
@ -1275,6 +1275,35 @@ static void store_param_oracle_timestamp_tz_complex(unsigned char **pos, MYSQL_C
|
||||
*(*pos - length - 1) = length;
|
||||
}
|
||||
|
||||
static void store_param_oracle_interval_complex(unsigned char **pos, MYSQL_COMPLEX_BIND_HEADER *param)
|
||||
{
|
||||
ORACLE_INTERVAL *interval = (ORACLE_INTERVAL *)param->buffer;
|
||||
uchar buff[20] = {0};
|
||||
int len = 0;
|
||||
|
||||
if (param->buffer_type == MYSQL_TYPE_OB_INTERVAL_YM) {
|
||||
len = 8;
|
||||
buff[0] = 7;
|
||||
buff[1] = interval->data_symbol > 0 ? 0 : 1; //正 0, 负 1
|
||||
int4store(buff + 2, interval->data_object.ym_object.ym_year);
|
||||
buff[6] = (uchar)(interval->data_object.ym_object.ym_month);
|
||||
buff[7] = (uchar)(interval->data_object.ym_object.ym_scale);
|
||||
} else if (param->buffer_type == MYSQL_TYPE_OB_INTERVAL_DS) {
|
||||
len = 15;
|
||||
buff[0] = 14;
|
||||
buff[1] = interval->data_symbol > 0 ? 0 : 1; //正 0, 负 1
|
||||
int4store(buff + 2, interval->data_object.ds_object.ds_day);
|
||||
buff[6] = (uchar)(interval->data_object.ds_object.ds_hour);
|
||||
buff[7] = (uchar)(interval->data_object.ds_object.ds_minute);
|
||||
buff[8] = (uchar)(interval->data_object.ds_object.ds_second);
|
||||
int4store(buff + 9, interval->data_object.ds_object.ds_frac_second);
|
||||
buff[13] = (uchar)(interval->data_object.ds_object.ds_day_scale);
|
||||
buff[14] = (uchar)(interval->data_object.ds_object.ds_frac_second_scale);
|
||||
}
|
||||
memcpy((char *)*pos, buff, len);
|
||||
(*pos) += len;
|
||||
}
|
||||
|
||||
static void store_param_str_complex(unsigned char **pos, MYSQL_COMPLEX_BIND_STRING *param)
|
||||
{
|
||||
/* param->length is always set in mysql_stmt_bind_param */
|
||||
@ -1453,6 +1482,10 @@ static void store_param_all_complex(unsigned char **pos, MYSQL_COMPLEX_BIND_HEAD
|
||||
case MYSQL_TYPE_OB_TIMESTAMP_WITH_TIME_ZONE:
|
||||
store_param_oracle_timestamp_tz_complex(pos, header);
|
||||
break;
|
||||
case MYSQL_TYPE_OB_INTERVAL_YM:
|
||||
case MYSQL_TYPE_OB_INTERVAL_DS:
|
||||
store_param_oracle_interval_complex(pos, header);
|
||||
break;
|
||||
case MYSQL_TYPE_TINY_BLOB:
|
||||
case MYSQL_TYPE_MEDIUM_BLOB:
|
||||
case MYSQL_TYPE_LONG_BLOB:
|
||||
@ -1807,6 +1840,8 @@ int convert_type_to_complex(enum enum_field_types type)
|
||||
case MYSQL_TYPE_CURSOR:
|
||||
case MYSQL_TYPE_ORA_BLOB:
|
||||
case MYSQL_TYPE_ORA_CLOB:
|
||||
case MYSQL_TYPE_OB_INTERVAL_DS:
|
||||
case MYSQL_TYPE_OB_INTERVAL_YM:
|
||||
case MYSQL_TYPE_OB_TIMESTAMP_NANO:
|
||||
case MYSQL_TYPE_OB_TIMESTAMP_WITH_TIME_ZONE:
|
||||
case MYSQL_TYPE_OB_TIMESTAMP_WITH_LOCAL_TIME_ZONE:
|
||||
@ -3160,6 +3195,8 @@ int STDCALL mysql_stmt_prepare(MYSQL_STMT *stmt, const char *query, unsigned lon
|
||||
if (length == (unsigned long) -1)
|
||||
length= (unsigned long)strlen(query);
|
||||
|
||||
free_old_query(mysql); //new query clean old feilds
|
||||
|
||||
/* clear flags */
|
||||
CLEAR_CLIENT_STMT_ERROR(stmt);
|
||||
CLEAR_CLIENT_ERROR(stmt->mysql);
|
||||
@ -3370,6 +3407,12 @@ static int madb_alloc_stmt_fields(MYSQL_STMT *stmt)
|
||||
SET_CLIENT_STMT_ERROR(stmt, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
|
||||
return(1);
|
||||
}
|
||||
if (!stmt->mysql->fields) {
|
||||
if (stmt->mysql->net.last_errno == 0)
|
||||
SET_CLIENT_STMT_ERROR(stmt, CR_NEW_STMT_METADATA, SQLSTATE_UNKNOWN, 0);
|
||||
return(1);
|
||||
}
|
||||
|
||||
memset(stmt->fields, 0, sizeof(MYSQL_FIELD) * stmt->mysql->field_count);
|
||||
stmt->field_count= stmt->mysql->field_count;
|
||||
|
||||
@ -3558,8 +3601,8 @@ int stmt_read_execute_response(MYSQL_STMT *stmt)
|
||||
|
||||
/* Only cursor read */
|
||||
stmt->default_rset_handler = _mysql_stmt_use_result;
|
||||
|
||||
} else if (stmt->flags & CURSOR_TYPE_READ_ONLY)
|
||||
stmt->state = MYSQL_STMT_WAITING_USE_OR_STORE;
|
||||
} else if ((stmt->flags & CURSOR_TYPE_READ_ONLY) && !(stmt->upsert_status.server_status & SERVER_MORE_RESULTS_EXIST))
|
||||
{
|
||||
/*
|
||||
We have asked for CURSOR but got no cursor, because the condition
|
||||
@ -3571,6 +3614,8 @@ int stmt_read_execute_response(MYSQL_STMT *stmt)
|
||||
precached on client and server's resources are freed.
|
||||
*/
|
||||
|
||||
if (stmt->mysql->status == MYSQL_STATUS_GET_RESULT)
|
||||
stmt->mysql->status = MYSQL_STATUS_STMT_RESULT;
|
||||
/* preferred is buffered read */
|
||||
if (mysql_stmt_store_result(stmt))
|
||||
return 1;
|
||||
@ -3590,8 +3635,9 @@ int stmt_read_execute_response(MYSQL_STMT *stmt)
|
||||
} else {
|
||||
stmt->mysql->status= MYSQL_STATUS_STMT_RESULT;
|
||||
}
|
||||
stmt->state = MYSQL_STMT_WAITING_USE_OR_STORE;
|
||||
}
|
||||
stmt->state= MYSQL_STMT_WAITING_USE_OR_STORE;
|
||||
//stmt->state= MYSQL_STMT_WAITING_USE_OR_STORE;
|
||||
/* in certain cases parameter types can change: For example see bug
|
||||
4026 (SELECT ?), so we need to update field information */
|
||||
// if (mysql->field_count == stmt->field_count)
|
||||
@ -4523,7 +4569,7 @@ uint32 ob_crc32(uint64_t crc, const char *buf, int64_t len)
|
||||
return crc64 & 0xffffffff;
|
||||
}
|
||||
|
||||
uint64 ob_crc64(uint64_t crc, const char *buf, int64_t len)
|
||||
uint64_t ob_crc64(uint64_t crc, const char *buf, int64_t len)
|
||||
{
|
||||
uint64_t crc64 = crc64_sse42_dispatch(crc, buf, len);
|
||||
return crc64;
|
||||
@ -5248,6 +5294,8 @@ mysql_stmt_prepare_v2(MYSQL_STMT *stmt, const char *query,
|
||||
if (length == (unsigned long) -1)
|
||||
length= (unsigned long)strlen(query);
|
||||
|
||||
free_old_query(mysql); //new query clean old feilds
|
||||
|
||||
/* clear flags */
|
||||
CLEAR_CLIENT_STMT_ERROR(stmt);
|
||||
CLEAR_CLIENT_ERROR(stmt->mysql);
|
||||
@ -6139,7 +6187,7 @@ mysql_stmt_read_piece_data(MYSQL_STMT *stmt, unsigned int param_number,
|
||||
*param->error = 1;
|
||||
} else {
|
||||
ulong copy_length = MIN(*ret_data_len, param->buffer_length);
|
||||
memcpy(param->buffer, (char *)*row, copy_length);
|
||||
memcpy(param->buffer, (char *)row, copy_length);
|
||||
*param->error = copy_length < *ret_data_len;
|
||||
}
|
||||
*param->length = *ret_data_len;
|
||||
|
@ -207,6 +207,26 @@ static enum_types convert_type(const char *type) {
|
||||
return TYPE_DATE;
|
||||
} else if (!strcmp(type, "RAW")) {
|
||||
return TYPE_RAW;
|
||||
} else if (!strcmp(type, "NVARCHAR2")) {
|
||||
return TYPE_NVARCHAR2;
|
||||
} else if (!strcmp(type, "FLOAT")) {
|
||||
return TYPE_OB_NUMBER_FLOAT;
|
||||
} else if (!strncmp(type, "INTERVAL YEAR", 13)) {
|
||||
return TYPE_OB_INTERVAL_YM;
|
||||
} else if (!strncmp(type, "INTERVAL DAY", 12)) {
|
||||
return TYPE_OB_INTERVAL_DS;
|
||||
} else if (!strncmp(type, "TIMESTAMP", 9)) {
|
||||
if (strstr(type, "WITH TIME ZONE")) {
|
||||
return TYPE_OB_TIMESTAMP_WITH_TIME_ZONE;
|
||||
} else if (strstr(type, "WITH LOCAL TIME ZONE")) {
|
||||
return TYPE_OB_TIMESTAMP_WITH_LOCAL_TIME_ZONE;
|
||||
} else {
|
||||
return TYPE_OB_TIMESTAMP_NANO;
|
||||
}
|
||||
} else if (!strcmp(type, "BINARY_FLOAT")) {
|
||||
return TYPE_FLOAT;
|
||||
} else if (!strcmp(type, "BINARY_DOUBLE")) {
|
||||
return TYPE_DOUBLE;
|
||||
} else {
|
||||
return TYPE_MAX;
|
||||
}
|
||||
|
@ -44,8 +44,8 @@ typedef struct _st_ob_lb_address_list {
|
||||
}ObLbAddressList;
|
||||
|
||||
typedef struct _st_connect_info {
|
||||
int connect_cnt;
|
||||
int connect_max;
|
||||
unsigned int connect_cnt;
|
||||
unsigned int connect_max;
|
||||
int64_t *connect_list;
|
||||
}ConnectInfo;
|
||||
|
||||
@ -137,8 +137,8 @@ static ObLbAddress* get_ob_address_by_address_list(ObLbAddressList *addr_list)
|
||||
break;
|
||||
}
|
||||
case OBCLIENT_LB_OPTION_SERVERAFFINITY: {
|
||||
int rand_number = (int)rand() % weight + 1;
|
||||
int index = 0;
|
||||
int rand_number = (int)rand() % weight + 1;
|
||||
for (index = 0; index < valid_cnt; ++index) {
|
||||
rand_number -= addr_list->add_arr[idxarr[index]].weight;
|
||||
if (index == valid_cnt - 1 || rand_number <= 0) {
|
||||
@ -192,7 +192,7 @@ static void check_ob_address_black(ObLbAddress * address, ObClientLbConfig *conf
|
||||
int len = info->connect_cnt;
|
||||
int64_t *list = info->connect_list;
|
||||
int64_t curtime = get_current_time_us();
|
||||
int64_t duration = config->black_append_duration * 1000;// ��λmsתΪus
|
||||
int64_t duration = config->black_append_duration * 1000;// µ¥Î»msתΪus
|
||||
for (idx = 0; idx < len; idx++) {
|
||||
if (curtime - list[idx] <= duration) {
|
||||
break;
|
||||
@ -236,16 +236,74 @@ static void check_ob_address_white(ObLbAddressList * addr_list, ObClientLbConfig
|
||||
}
|
||||
}
|
||||
|
||||
static int init_oblb_addresslist(ObLbAddressList* list, ObClientLbAddressList* addrlist) {
|
||||
static int init_oblb_addresslist_str(ObLbAddressList* list, char* str, ObClientLBOption oblb_strategy) {
|
||||
int ret = 0;
|
||||
if (NULL == list || NULL == str) {
|
||||
ret = -1;
|
||||
} else {
|
||||
char *p = str, *s = NULL, *e = NULL;
|
||||
int count = 1;
|
||||
while (p && *p) {
|
||||
if (*p++ == ',')
|
||||
count++;
|
||||
}
|
||||
|
||||
if (OB_ISNULL(list->add_arr = (ObLbAddress*)calloc(1, count * sizeof(ObLbAddress)))) {
|
||||
ret = -1;
|
||||
} else {
|
||||
unsigned int i = 0;
|
||||
my_bool valid = 0;
|
||||
my_bool instring = 0;
|
||||
int idx = 0;
|
||||
int port = 0;
|
||||
p = str;
|
||||
while (p && *p) {
|
||||
if (instring == 0 && *p == '[') {
|
||||
instring = 1;
|
||||
s = p + 1;
|
||||
valid = 0;
|
||||
} else if (instring == 1 && *p == ']') {
|
||||
instring = 0;
|
||||
e = p;
|
||||
valid = 1;
|
||||
} else if (instring == 0 && *p == ',') {
|
||||
s = p + 1;
|
||||
e = NULL;
|
||||
valid = 0;
|
||||
} else if (instring == 0 && *p == ':') {
|
||||
if (valid == 0) {
|
||||
e = p;
|
||||
}
|
||||
if (s && e) {
|
||||
memcpy(list->add_arr[idx].host, s, e - s);
|
||||
list->add_arr[idx].port = atoi(p + 1);
|
||||
list->add_arr[i].weight = 1;
|
||||
list->add_arr[i].state = OBCLIENT_LB_WHITE;
|
||||
|
||||
idx++;
|
||||
s = NULL;
|
||||
e = NULL;
|
||||
valid = 0;
|
||||
}
|
||||
}
|
||||
p++;
|
||||
}
|
||||
list->count = idx;
|
||||
list->rotation_flag = 0;
|
||||
list->option = oblb_strategy;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
static int init_oblb_addresslist(ObLbAddressList* list, ObClientLbAddressList* addrlist, ObClientLBOption oblb_strategy) {
|
||||
int ret = 0;
|
||||
|
||||
if (!list || !addrlist || !addrlist->address_list || addrlist->address_list_count <= 0) {
|
||||
ret = -1;
|
||||
} else if (OB_ISNULL(list->add_arr = (ObLbAddress*)malloc(addrlist->address_list_count * sizeof(ObLbAddress)))) {
|
||||
} else if (OB_ISNULL(list->add_arr = (ObLbAddress*)calloc(1, addrlist->address_list_count * sizeof(ObLbAddress)))) {
|
||||
ret = -1;
|
||||
} else {
|
||||
unsigned int i = 0;
|
||||
memset(list->add_arr, 0, addrlist->address_list_count * sizeof(ObLbAddress));
|
||||
for (i = 0; i < addrlist->address_list_count; i++) {
|
||||
memcpy(list->add_arr[i].host, addrlist->address_list[i].host, strlen(addrlist->address_list[i].host));
|
||||
list->add_arr[i].port = addrlist->address_list[i].port;
|
||||
@ -254,19 +312,18 @@ static int init_oblb_addresslist(ObLbAddressList* list, ObClientLbAddressList* a
|
||||
}
|
||||
list->count = addrlist->address_list_count;
|
||||
list->rotation_flag = 0;
|
||||
list->option = OBCLIENT_LB_OPTION_ROTATION;
|
||||
list->option = oblb_strategy;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
static int init_oblb_addresslist_tns(ObLbAddressList* list, ObClientAddressList* addrlist) {
|
||||
static int init_oblb_addresslist_tns(ObLbAddressList* list, ObClientAddressList* addrlist, ObClientLBOption oblb_strategy) {
|
||||
int ret = 0;
|
||||
if (!list || !addrlist || !addrlist->address || addrlist->address_count <= 0) {
|
||||
ret = -1;
|
||||
} else if (OB_ISNULL(list->add_arr = (ObLbAddress*)malloc(addrlist->address_count * sizeof(ObLbAddress)))){
|
||||
} else if (OB_ISNULL(list->add_arr = (ObLbAddress*)calloc(1, addrlist->address_count * sizeof(ObLbAddress)))){
|
||||
ret = -1;
|
||||
} else {
|
||||
unsigned int i = 0;
|
||||
memset(list->add_arr, 0, addrlist->address_count * sizeof(ObLbAddress));
|
||||
for (i = 0; i < addrlist->address_count; i++) {
|
||||
memcpy(list->add_arr[i].host, addrlist->address[i].host, addrlist->address[i].host_len);
|
||||
list->add_arr[i].port = addrlist->address[i].port;
|
||||
@ -275,18 +332,57 @@ static int init_oblb_addresslist_tns(ObLbAddressList* list, ObClientAddressList*
|
||||
}
|
||||
list->count = addrlist->address_count;
|
||||
list->rotation_flag = 0;
|
||||
list->option = addrlist->oblb_strategy;
|
||||
if (addrlist->oblb_strategy != OBCLIENT_LB_OPTION_RANDOM &&
|
||||
addrlist->oblb_strategy != OBCLIENT_LB_OPTION_SERVERAFFINITY &&
|
||||
addrlist->oblb_strategy != OBCLIENT_LB_OPTION_ROTATION) {
|
||||
list->option = oblb_strategy;
|
||||
} else {
|
||||
list->option = addrlist->oblb_strategy;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
static void release_oblb_addresslist(ObLbAddressList* list) {
|
||||
if (list && list->add_arr) {
|
||||
free(list->add_arr);
|
||||
list->add_arr = NULL;
|
||||
list->count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int post_session_variable(MYSQL *mysql, char *session_variable, int session_variable_len)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (NULL == mysql) {
|
||||
ret = -1;
|
||||
} else if (0 == session_variable_len) {
|
||||
;
|
||||
} else {
|
||||
char post_sql[1024] = { 0 };
|
||||
int post_sql_len = snprintf(post_sql, 1024, "set %.*s", session_variable_len, session_variable);
|
||||
if (post_sql_len < 0) {
|
||||
ret = -1;
|
||||
} else if (mysql_real_query(mysql, post_sql, post_sql_len)) {
|
||||
ret = -1;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static MYSQL* connect_by_addresslist(MYSQL* mysql, ObLbAddressList *addr_list, ObClientLbConfig *config,
|
||||
|
||||
static MYSQL* connect_by_addresslist(MYSQL* mysql, int64_t lb_starttime, ObLbAddressList *addr_list, ObClientLbConfig *config,
|
||||
const char *user, const char *passwd, const char *db, const char *unix_socket, unsigned long client_flag, ObClientLbAddress* success)
|
||||
{
|
||||
ObLbAddress *address = NULL;
|
||||
MYSQL* tmp = NULL;
|
||||
unsigned int i = 0;
|
||||
int err = 0;
|
||||
char buf[128] = { 0 };
|
||||
int64_t lb_endtime = 0;
|
||||
my_bool default_report_data_truncation = 1;
|
||||
unsigned int default_local_infile = 2;
|
||||
unsigned int default_connect_timeout = 6;//s
|
||||
|
||||
unsigned int mysql_connect_timeout = 0;
|
||||
unsigned int mysql_read_timeout = 0;
|
||||
@ -307,6 +403,7 @@ static MYSQL* connect_by_addresslist(MYSQL* mysql, ObLbAddressList *addr_list, O
|
||||
my_bool mysql_opt_interactive = 0;
|
||||
my_bool mysql_report_data_truncation = 0;
|
||||
my_bool mysql_opt_reconnect = 0;
|
||||
char* mysql_read_default_file = NULL;
|
||||
|
||||
my_bool mysql_opt_use_ssl = 0;
|
||||
my_bool mysql_opt_ssl_verify_server_cert = 0;
|
||||
@ -318,8 +415,9 @@ static MYSQL* connect_by_addresslist(MYSQL* mysql, ObLbAddressList *addr_list, O
|
||||
char *mysql_opt_ssl_crl = NULL;
|
||||
char *mysql_opt_ssl_crlpath = NULL;
|
||||
char *mysql_opt_tls_version = NULL;
|
||||
|
||||
|
||||
if (mysql == NULL || addr_list == NULL || config == NULL || addr_list->add_arr == NULL || addr_list->count <= 0) {
|
||||
SET_CLIENT_ERROR(mysql, CR_UNKNOWN_ERROR, SQLSTATE_UNKNOWN, "invalid handle or address list is zero.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -328,13 +426,6 @@ static MYSQL* connect_by_addresslist(MYSQL* mysql, ObLbAddressList *addr_list, O
|
||||
addr_list->option != OBCLIENT_LB_OPTION_SERVERAFFINITY) {
|
||||
addr_list->option = OBCLIENT_LB_OPTION_ROTATION;
|
||||
}
|
||||
if (config->black_append_strategy != OBCLIENT_LB_OPTION_NORMAL &&
|
||||
config->black_append_strategy != OBCLIENT_LB_OPTION_RETRY_DERUATION) {
|
||||
config->black_append_strategy = OBCLIENT_LB_OPTION_NORMAL;
|
||||
}
|
||||
if (config->retry_all_downs <= 0) config->retry_all_downs = addr_list->count;
|
||||
if (config->black_append_duration <= 0) config->black_append_duration = 60 * 1000;
|
||||
if (config->black_append_retrytimes <= 0) config->black_append_retrytimes = 1;
|
||||
|
||||
for (i = 0; i < addr_list->count; i++) {
|
||||
addr_list->add_arr[i].state = OBCLIENT_LB_WHITE;
|
||||
@ -344,6 +435,8 @@ static MYSQL* connect_by_addresslist(MYSQL* mysql, ObLbAddressList *addr_list, O
|
||||
}
|
||||
init_connect_info(&(addr_list->add_arr[i]));
|
||||
}
|
||||
lb_endtime = lb_starttime + config->retry_timeout * 1000;
|
||||
srand(time(NULL));
|
||||
|
||||
//init mysql options
|
||||
mysql_connect_timeout = config->mysql_connect_timeout;
|
||||
@ -364,6 +457,7 @@ static MYSQL* connect_by_addresslist(MYSQL* mysql, ObLbAddressList *addr_list, O
|
||||
mysql_opt_interactive = config->mysql_opt_interactive;
|
||||
mysql_report_data_truncation = config->mysql_report_data_truncation;
|
||||
mysql_opt_reconnect = config->mysql_opt_reconnect;
|
||||
mysql_read_default_file = config->mysql_read_default_file;
|
||||
|
||||
mysql_opt_use_ssl = config->mysql_opt_use_ssl;
|
||||
mysql_opt_ssl_verify_server_cert = config->mysql_opt_ssl_verify_server_cert;
|
||||
@ -382,6 +476,7 @@ static MYSQL* connect_by_addresslist(MYSQL* mysql, ObLbAddressList *addr_list, O
|
||||
|
||||
//get address
|
||||
if (NULL == (address = get_ob_address_by_address_list(addr_list))) {
|
||||
SET_CLIENT_ERROR(mysql, CR_UNKNOWN_ERROR, SQLSTATE_UNKNOWN, "address list is empty(all in black).");
|
||||
break;
|
||||
}
|
||||
|
||||
@ -392,6 +487,10 @@ static MYSQL* connect_by_addresslist(MYSQL* mysql, ObLbAddressList *addr_list, O
|
||||
#ifdef DEBUG_LOAD_BALANCE
|
||||
printf("host:%s,port:%d,state:%d\n", address->host, address->port, address->state);
|
||||
#endif
|
||||
//set default options
|
||||
mysql_options(mysql, MYSQL_REPORT_DATA_TRUNCATION, (char *)&default_report_data_truncation);
|
||||
mysql_options(mysql, MYSQL_OPT_LOCAL_INFILE, (char*)&default_local_infile);
|
||||
mysql_options(mysql, MYSQL_OPT_CONNECT_TIMEOUT, &default_connect_timeout);
|
||||
|
||||
//mysql options
|
||||
if (mysql_connect_timeout > 0)
|
||||
@ -430,6 +529,8 @@ static MYSQL* connect_by_addresslist(MYSQL* mysql, ObLbAddressList *addr_list, O
|
||||
mysql_options(mysql, MYSQL_REPORT_DATA_TRUNCATION, (char *)&mysql_report_data_truncation);
|
||||
if (mysql_opt_reconnect)
|
||||
mysql_options(mysql, MYSQL_OPT_RECONNECT, (char *)&mysql_opt_reconnect);
|
||||
if (mysql_read_default_file && *mysql_read_default_file)
|
||||
mysql_options(mysql, MYSQL_READ_DEFAULT_FILE, (char*)mysql_read_default_file);
|
||||
|
||||
if (mysql_opt_use_ssl) {
|
||||
mysql_ssl_set(mysql, mysql_opt_ssl_key, mysql_opt_ssl_cert, mysql_opt_ssl_ca, mysql_opt_ssl_capath, mysql_opt_ssl_cipher);
|
||||
@ -459,8 +560,18 @@ static MYSQL* connect_by_addresslist(MYSQL* mysql, ObLbAddressList *addr_list, O
|
||||
//check black
|
||||
check_ob_address_black(address, config);
|
||||
|
||||
if (config->retry_timeout > 0 && get_current_time_us() > lb_endtime) {
|
||||
snprintf(buf, sizeof(buf), "retry_timeout(%d)(%lld-%lld).", config->retry_timeout, lb_starttime, get_current_time_us());
|
||||
SET_CLIENT_ERROR(mysql, CR_UNKNOWN_ERROR, SQLSTATE_UNKNOWN, buf);
|
||||
break;
|
||||
}
|
||||
|
||||
config->retry_all_downs--;
|
||||
} while (address && config->retry_all_downs > 0);
|
||||
if (config->retry_all_downs <= 0) {
|
||||
SET_CLIENT_ERROR(mysql, CR_UNKNOWN_ERROR, SQLSTATE_UNKNOWN, "retry_all_downs is zero.");
|
||||
break;
|
||||
}
|
||||
} while (address);
|
||||
|
||||
//release connect
|
||||
for (i = 0; i < addr_list->count; i++) {
|
||||
@ -470,23 +581,28 @@ static MYSQL* connect_by_addresslist(MYSQL* mysql, ObLbAddressList *addr_list, O
|
||||
return tmp;
|
||||
}
|
||||
|
||||
static MYSQL* connect_by_tnsname(MYSQL* mysql, const char* tns_name, ObClientLbConfig * config,
|
||||
static MYSQL* connect_by_tnsname(MYSQL* mysql, int64_t lb_starttime, const char* tns_name, ObClientLbConfig * config,
|
||||
const char *user, const char* passwd, const char *db, const char* unix_socket, unsigned long client_flag, ObClientLbAddress *success)
|
||||
{
|
||||
int ret = 0;
|
||||
MYSQL *tmp = NULL;
|
||||
char buf[128] = { 0 };
|
||||
my_bool find = 0;
|
||||
ObClientTns tns;
|
||||
const char *sid = db;
|
||||
char session_variable[1024] = { 0 };
|
||||
char new_user_name[256] = { 0 };
|
||||
int user_len = strlen((const char *)user ? user : "");
|
||||
int64_t lb_endtime = 0;
|
||||
|
||||
if (OB_FAIL(ObClientTnsInit(&tns))) {
|
||||
tmp = NULL;
|
||||
if (NULL == tns_name || NULL == config) {
|
||||
SET_CLIENT_ERROR(mysql, CR_UNKNOWN_ERROR, SQLSTATE_UNKNOWN, "invalid tns_name or config.");
|
||||
} else if (OB_FAIL(ObClientTnsInit(&tns))) {
|
||||
SET_CLIENT_ERROR(mysql, CR_UNKNOWN_ERROR, SQLSTATE_UNKNOWN, "tns init fail.");
|
||||
} else if (OB_FAIL(ObClientTnsBuild(&tns, tns_name, strlen(tns_name), &find))) {
|
||||
tmp = NULL;
|
||||
SET_CLIENT_ERROR(mysql, CR_UNKNOWN_ERROR, SQLSTATE_UNKNOWN, "ob client tns build fail.");
|
||||
} else if (1 != find || !tns.tns_service || !tns.tns_service->description || tns.tns_service->description_count == 0) {
|
||||
tmp = NULL;
|
||||
SET_CLIENT_ERROR(mysql, CR_UNKNOWN_ERROR, SQLSTATE_UNKNOWN, "tns description is null.");
|
||||
} else {
|
||||
unsigned int i = 0;
|
||||
ObClientDescription *des = tns.tns_service->description;
|
||||
@ -507,28 +623,40 @@ static MYSQL* connect_by_tnsname(MYSQL* mysql, const char* tns_name, ObClientLbC
|
||||
|
||||
//tns config
|
||||
config->retry_all_downs = des->retry_all_downs;
|
||||
config->retry_timeout = des->retry_timeout;
|
||||
config->black_remove_strategy = des->black_list_conf.remove_strategy;
|
||||
config->black_remove_timeout = des->black_list_conf.remove_timeout;
|
||||
config->black_append_strategy = des->black_list_conf.append_strategy;
|
||||
config->black_append_duration = des->black_list_conf.duration;
|
||||
config->black_append_retrytimes = des->black_list_conf.retry_times;
|
||||
if (des->connect_timout > 0) config->mysql_connect_timeout = des->connect_timout;
|
||||
if (des->read_timout > 0) config->mysql_read_timeout = des->read_timout;
|
||||
if (des->write_timout > 0) config->mysql_write_timeout = des->write_timout;
|
||||
lb_endtime = lb_starttime + config->retry_timeout * 1000;
|
||||
|
||||
for (i = 0; i < des->address_list_count; i++) {
|
||||
ObLbAddressList list;
|
||||
memset(&list, 0, sizeof(list));
|
||||
#ifdef DEBUG_LOAD_BALANCE
|
||||
printf("------------------------------------------\n");
|
||||
#endif
|
||||
|
||||
if (OB_SUCC(init_oblb_addresslist_tns(&list, &(des->address_list[i])))) {
|
||||
tmp = connect_by_addresslist(mysql, &list, config, new_user_name, passwd, sid, unix_socket, client_flag, success);
|
||||
}
|
||||
if (list.add_arr) {
|
||||
free(list.add_arr);
|
||||
list.add_arr = NULL;
|
||||
list.count = 0;
|
||||
ObLbAddressList list;
|
||||
memset(&list, 0, sizeof(list));
|
||||
if (OB_SUCC(init_oblb_addresslist_tns(&list, &(des->address_list[i]), des->oblb_strategy))) {
|
||||
tmp = connect_by_addresslist(mysql, lb_starttime, &list, config, new_user_name, passwd, sid, unix_socket, client_flag, success);
|
||||
}
|
||||
release_oblb_addresslist(&list);
|
||||
|
||||
//connect success
|
||||
if (tmp) {
|
||||
if (des && des->connect_data && des->connect_data->session_variable_len > 0) {
|
||||
post_session_variable(tmp, des->connect_data->session_variable, des->connect_data->session_variable_len);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (config->retry_timeout > 0 && get_current_time_us() > lb_endtime) {
|
||||
snprintf(buf, sizeof(buf), "retry_timeout(%d)(%lld-%lld).", config->retry_timeout, lb_starttime, get_current_time_us());
|
||||
SET_CLIENT_ERROR(mysql, CR_UNKNOWN_ERROR, SQLSTATE_UNKNOWN, buf);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -542,20 +670,84 @@ MYSQL* ob_mysql_real_connect(MYSQL* mysql, const char* tns_name, ObClientLbAddre
|
||||
{
|
||||
int ret = 0;
|
||||
MYSQL *tmp = NULL;
|
||||
ObClientLbConfig default_config = {0};
|
||||
int64_t lb_starttime = get_current_time_us();
|
||||
|
||||
if (NULL == config) {
|
||||
memset(&default_config, 0, sizeof(ObClientLbConfig));
|
||||
config = &default_config;
|
||||
}
|
||||
|
||||
if (tns_name && *tns_name) {
|
||||
tmp = connect_by_tnsname(mysql, tns_name, config, user, passwd, db, unix_socket, client_flag, success);
|
||||
} else {
|
||||
tmp = connect_by_tnsname(mysql, lb_starttime, tns_name, config, user, passwd, db, unix_socket, client_flag, success);
|
||||
} else if (addr_list) {
|
||||
ObLbAddressList list;
|
||||
memset(&list, 0, sizeof(list));
|
||||
if (OB_SUCC(init_oblb_addresslist(&list, addr_list))) {
|
||||
tmp = connect_by_addresslist(mysql, &list, config, user, passwd, db, unix_socket, client_flag, success);
|
||||
}
|
||||
if (list.add_arr) {
|
||||
free(list.add_arr);
|
||||
list.add_arr = NULL;
|
||||
list.count = 0;
|
||||
if (OB_SUCC(init_oblb_addresslist(&list, addr_list, OBCLIENT_LB_OPTION_ROTATION))) {
|
||||
if (config->retry_all_downs <= 0) config->retry_all_downs = addr_list->address_list_count;
|
||||
if (config->retry_timeout <= 0) config->retry_timeout = 0; //list µØÖ·Ä£Ê½Ä¬ÈÏÂÖѵ£¬Õâ¸ö²ÎÊý²»ÉúЧ
|
||||
if (config->black_append_strategy != OBCLIENT_LB_OPTION_NORMAL &&
|
||||
config->black_append_strategy != OBCLIENT_LB_OPTION_RETRY_DERUATION) {
|
||||
config->black_append_strategy = OBCLIENT_LB_OPTION_NORMAL;
|
||||
}
|
||||
if (config->black_append_duration <= 0) config->black_append_duration = 10 * 1000;
|
||||
if (config->black_append_retrytimes <= 0) config->black_append_retrytimes = 1;
|
||||
if (config->black_remove_strategy != OBCLIENT_LB_OPTION_TIMEOUT) {
|
||||
config->black_remove_strategy = OBCLIENT_LB_OPTION_TIMEOUT;
|
||||
}
|
||||
//if (config->black_remove_timeout <= 0) config->black_remove_timeout = 50 * 1000;
|
||||
|
||||
tmp = connect_by_addresslist(mysql, lb_starttime, &list, config, user, passwd, db, unix_socket, client_flag, success);
|
||||
}
|
||||
release_oblb_addresslist(&list);
|
||||
} else {
|
||||
SET_CLIENT_ERROR(mysql, CR_UNKNOWN_ERROR, SQLSTATE_UNKNOWN, "tns_name/addr_list is null.");
|
||||
}
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
MYSQL* ob_mysql_real_connect2(MYSQL* mysql, const char* tns_name, const char *addr_list, ObClientLbConfig *config,
|
||||
const char *user, const char *passwd, const char *db, const char *unix_socket, unsigned long client_flag, char* success, int len_success)
|
||||
{
|
||||
int ret = 0;
|
||||
MYSQL *tmp = NULL;
|
||||
ObClientLbConfig default_config = { 0 };
|
||||
ObClientLbAddress success_addr;
|
||||
int64_t lb_starttime = get_current_time_us();
|
||||
memset(&success_addr, 0, sizeof(success_addr));
|
||||
|
||||
if (NULL == config) {
|
||||
memset(&default_config, 0, sizeof(ObClientLbConfig));
|
||||
config = &default_config;
|
||||
}
|
||||
|
||||
if (tns_name && *tns_name) {
|
||||
tmp = connect_by_tnsname(mysql, lb_starttime, tns_name, config, user, passwd, db, unix_socket, client_flag, &success_addr);
|
||||
} else if (addr_list) {
|
||||
ObLbAddressList list;
|
||||
memset(&list, 0, sizeof(list));
|
||||
if (OB_SUCC(init_oblb_addresslist_str(&list, (char*)addr_list, OBCLIENT_LB_OPTION_ROTATION))) {
|
||||
if (config->retry_all_downs <= 0) config->retry_all_downs = list.count;
|
||||
if (config->retry_timeout <= 0) config->retry_timeout = 0; //list µØÖ·Ä£Ê½Ä¬ÈÏÂÖѵ£¬Õâ¸ö²ÎÊý²»ÉúЧ
|
||||
if (config->black_append_strategy != OBCLIENT_LB_OPTION_NORMAL &&
|
||||
config->black_append_strategy != OBCLIENT_LB_OPTION_RETRY_DERUATION) {
|
||||
config->black_append_strategy = OBCLIENT_LB_OPTION_NORMAL;
|
||||
}
|
||||
if (config->black_append_duration <= 0) config->black_append_duration = 10 * 1000;
|
||||
if (config->black_append_retrytimes <= 0) config->black_append_retrytimes = 1;
|
||||
if (config->black_remove_strategy != OBCLIENT_LB_OPTION_TIMEOUT) {
|
||||
config->black_remove_strategy = OBCLIENT_LB_OPTION_TIMEOUT;
|
||||
}
|
||||
//if (config->black_remove_timeout <= 0) config->black_remove_timeout = 50 * 1000;
|
||||
tmp = connect_by_addresslist(mysql, lb_starttime, &list, config, user, passwd, db, unix_socket, client_flag, &success_addr);
|
||||
}
|
||||
release_oblb_addresslist(&list);
|
||||
} else {
|
||||
SET_CLIENT_ERROR(mysql, CR_UNKNOWN_ERROR, SQLSTATE_UNKNOWN, "tns_name/addr_list is null.");
|
||||
}
|
||||
if (tmp && success && len_success > 0) {
|
||||
snprintf(success, len_success, "[%s]:%d", success_addr.host, success_addr.port);
|
||||
}
|
||||
|
||||
return tmp;
|
||||
|
@ -5,7 +5,6 @@
|
||||
|
||||
#include "mysql.h"
|
||||
#include "ma_global.h"
|
||||
#include "ob_object.h"
|
||||
#include "ob_full_link_trace.h"
|
||||
#include "ob_rwlock.h"
|
||||
|
||||
|
@ -101,7 +101,7 @@ static ObClientLBKeyType tns_keytype_15[] = { OBCLIENT_LB_REMOVE_STRATEGY, OBCLI
|
||||
static ObClientLBKeyType tns_keytype_16[] = { OBCLIENT_LB_SESSION_VARIABLE};
|
||||
static ObClientLBKeyType tns_keytype_17[] = { OBCLIENT_LB_READ_TIMEOUT};
|
||||
static ObClientLBKeyType tns_keytype_18[] = { OBCLIENT_LB_EXTRA_INFO, OBCLIENT_LB_OBLB_RETRY_TIMEOUT, OBCLIENT_LB_WRITE_TIMEOUT};
|
||||
static ObClientLBKeyType tns_keytype_19[] = { OBCLIENT_LB_OBLB_GROUP_STRATEGY };
|
||||
static ObClientLBKeyType tns_keytype_19[] = { OBCLIENT_LB_OBLB_GROUP_STRATEGY};
|
||||
static ObClientLBKeyType tns_keytype_20[] = { OBCLIENT_LB_OBLB_RETRY_ALL_DOWNS, OBCLIENT_LB_CONNECT_TIMEOUT};
|
||||
|
||||
static const void *tns_key_array[] = {
|
||||
@ -568,7 +568,7 @@ int ObClientTnsServiceSkip(ObClientTnsParseParams *parse_params)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObClientTnsServiceExtraInfoGet(ObClientTnsService *tns_service, char *extra_info, int *extra_info_len, int *ob_mode)
|
||||
int ObClientTnsServiceExtraInfoGet(ObClientTnsService *tns_service, char *extra_info, int *extra_info_len, int *ob_mode, char* session_variable, int *session_variable_len)
|
||||
{
|
||||
int ret = 0;
|
||||
ObClientDescription *des;
|
||||
@ -580,10 +580,16 @@ int ObClientTnsServiceExtraInfoGet(ObClientTnsService *tns_service, char *extra_
|
||||
ret = -1;
|
||||
} else if (OB_ISNULL(con_data = des->connect_data)) {
|
||||
ret = -1;
|
||||
} else if (0 != con_data->user_extra_info_len) {
|
||||
*extra_info_len = con_data->user_extra_info_len;
|
||||
strncpy(extra_info, con_data->user_extra_info, *extra_info_len);
|
||||
*ob_mode = con_data->ob_mode;
|
||||
} else {
|
||||
if (0 != con_data->user_extra_info_len) {
|
||||
*extra_info_len = con_data->user_extra_info_len;
|
||||
strncpy(extra_info, con_data->user_extra_info, *extra_info_len);
|
||||
*ob_mode = con_data->ob_mode;
|
||||
}
|
||||
if (0 != con_data->session_variable_len) {
|
||||
*session_variable_len = con_data->session_variable_len;
|
||||
strncpy(session_variable, con_data->session_variable, *session_variable_len);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
@ -791,6 +797,17 @@ int ObClientDescriptionBuild(ObClientTnsService *tns_service, ObClientTnsParsePa
|
||||
TNS_PARSE_INTRGER_VALUE(parse_params, des->read_timout);
|
||||
} else if (OBCLIENT_LB_WRITE_TIMEOUT == parse_params->key_type) {
|
||||
TNS_PARSE_INTRGER_VALUE(parse_params, des->write_timout);
|
||||
} else if (OBCLIENT_LB_OBLB_STRATEGY == parse_params->key_type) {
|
||||
TNS_PARSE(parse_params, TNS_KEY);
|
||||
if (0 == strncasecmp(parse_params->tns_key, "RANDOM", parse_params->tns_key_len)) {
|
||||
des->oblb_strategy = OBCLIENT_LB_OPTION_RANDOM;
|
||||
} else if (0 == strncasecmp(parse_params->tns_key, "SERVERAFFINITY", parse_params->tns_key_len)) {
|
||||
des->oblb_strategy = OBCLIENT_LB_OPTION_SERVERAFFINITY;
|
||||
} else if (0 == strncasecmp(parse_params->tns_key, "ROTATION", parse_params->tns_key_len)) {
|
||||
des->oblb_strategy = OBCLIENT_LB_OPTION_ROTATION;
|
||||
} else {
|
||||
ret = -1;
|
||||
}
|
||||
} else if (OBCLIENT_LB_OBLB_GROUP_STRATEGY == parse_params->key_type) {
|
||||
TNS_PARSE(parse_params, TNS_KEY);
|
||||
if (0 == strncasecmp(parse_params->tns_key, "ROTATION", parse_params->tns_key_len)) {
|
||||
@ -1244,6 +1261,9 @@ int ObClientConnectDataDisplay(ObClientConnectData *con_data, FILE *display_file
|
||||
fprintf(display_file, "----------obmode:%ld\n", con_data->ob_mode);
|
||||
fprintf(display_file, "----------use_default_sid:%ld\n", con_data->use_default_sid);
|
||||
}
|
||||
if (0 != con_data->session_variable_len) {
|
||||
fprintf(display_file, "----------session_variable:%.*s\n", con_data->session_variable_len, con_data->session_variable);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
@ -1283,6 +1303,8 @@ int ObClientConnectDataBuild(ObClientDescription *des, ObClientTnsParseParams *p
|
||||
TNS_PARSE_INTRGER_VALUE(parse_params, connect_data->ob_mode);
|
||||
} else if (OBCLIENT_LB_USE_DEFAULT_SID == parse_params->key_type) {
|
||||
TNS_PARSE_INTRGER_VALUE(parse_params, connect_data->use_default_sid);
|
||||
} else if (OBCLIENT_LB_SESSION_VARIABLE == parse_params->key_type) {
|
||||
TNS_PARSE_STRING_VALUE(parse_params, connect_data->session_variable, connect_data->session_variable_len, OBCLIENT_TNS_KEY_SIZE);
|
||||
} else {
|
||||
ret = -1;
|
||||
}
|
||||
@ -1467,19 +1489,25 @@ int ObClientTnsParseBlank(ObClientTnsParseParams *parse_params)
|
||||
}
|
||||
} else {
|
||||
while (parse_params->buffer_pos < parse_params->buffer_len) {
|
||||
ch = parse_params->tns_buffer[parse_params->buffer_pos];
|
||||
if ('\t' == ch || '\n' == ch || ' ' == ch) {
|
||||
parse_params->buffer_pos++;
|
||||
} else if ('#' == ch) { // ignore comments
|
||||
if (!parse_params->is_comment) {
|
||||
ch = parse_params->tns_buffer[parse_params->buffer_pos];
|
||||
if (('\t' == ch || '\n' == ch || ' ' == ch || '\r' == ch)) {
|
||||
parse_params->buffer_pos++;
|
||||
} else if ('#' == ch) { // ignore comments
|
||||
parse_params->is_comment = 1;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
unsigned int tmp = parse_params->buffer_pos;
|
||||
for (; tmp < parse_params->buffer_len; tmp++) {
|
||||
char tmpch = parse_params->tns_buffer[tmp];
|
||||
if ('\n' == tmpch || '\0' == tmpch)
|
||||
if ('\n' == tmpch || '\0' == tmpch) {
|
||||
parse_params->is_comment = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
parse_params->buffer_pos = tmp;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (parse_params->buffer_pos < parse_params->buffer_len) {
|
||||
|
@ -149,6 +149,7 @@ struct obclient_description
|
||||
unsigned long read_timout; // 单次读的超时时间
|
||||
unsigned long write_timout; // 单次写的超时时间
|
||||
unsigned long retry_timeout; // 整个LB阶段的超时时间
|
||||
ObClientLBOption oblb_strategy;
|
||||
ObClientLBOption oblb_group_strategy;
|
||||
ObClientBlacklistConf black_list_conf;
|
||||
};
|
||||
@ -178,6 +179,8 @@ struct obclient_connect_data
|
||||
unsigned int service_name_len;
|
||||
char user_extra_info[OBCLIENT_TNS_KEY_SIZE];
|
||||
unsigned int user_extra_info_len;
|
||||
char session_variable[OBCLIENT_TNS_KEY_SIZE];
|
||||
unsigned int session_variable_len;
|
||||
unsigned long ob_mode;
|
||||
unsigned long use_default_sid;
|
||||
};
|
||||
@ -196,6 +199,7 @@ struct obclient_tns_parse_params
|
||||
char *description;
|
||||
int description_len;
|
||||
int description_offset;
|
||||
int is_comment;
|
||||
ObClientTnsTokenType tns_token_type;
|
||||
ObClientLBKeyType key_type;
|
||||
};
|
||||
@ -214,7 +218,7 @@ int ObClientTnsServiceDisplay(ObClientTnsService *tns_service, FILE *display_fil
|
||||
int ObClientTnsServiceBuild(ObClientTns *tns, ObClientTnsParseParams *parse_params);
|
||||
int ObClientTnsServiceSkip(ObClientTnsParseParams *parse_params);
|
||||
// 非负载均衡模式下获取extra info
|
||||
int ObClientTnsServiceExtraInfoGet(ObClientTnsService *tns_service, char *extra_info, int *extra_info_len, int *ob_mode);
|
||||
int ObClientTnsServiceExtraInfoGet(ObClientTnsService *tns_service, char *extra_info, int *extra_info_len, int *ob_mode, char* session_variable, int *session_variable_len);
|
||||
// 非负载均衡模式下获取dblink, 直接获取第一个address,拼接dblink
|
||||
int ObClientTnsServiceDblinkGet(ObClientTnsService *tns_service, char *dblink, int *dblink_len);
|
||||
|
||||
|
@ -32,5 +32,5 @@ int64_t get_current_time_us()
|
||||
{
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, NULL);
|
||||
return tv.tv_sec * 1000000 + tv.tv_usec;
|
||||
return (int64_t)tv.tv_sec * 1000000 + tv.tv_usec;
|
||||
}
|
||||
|
@ -1 +1 @@
|
||||
2.2.7
|
||||
2.2.8
|
||||
|
Loading…
x
Reference in New Issue
Block a user