mirror of
https://github.com/MariaDB/server.git
synced 2025-08-08 11:22:35 +03:00
Merge tag 'mariadb-10.0.17' into 10.0-galera
Conflicts: storage/innobase/include/trx0trx.h
This commit is contained in:
@@ -49,6 +49,8 @@
|
|||||||
|
|
||||||
#include "mysqld.h"
|
#include "mysqld.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
Rpl_filter *binlog_filter= 0;
|
Rpl_filter *binlog_filter= 0;
|
||||||
|
|
||||||
#define BIN_LOG_HEADER_SIZE 4
|
#define BIN_LOG_HEADER_SIZE 4
|
||||||
@@ -67,6 +69,7 @@ ulong server_id = 0;
|
|||||||
ulong bytes_sent = 0L, bytes_received = 0L;
|
ulong bytes_sent = 0L, bytes_received = 0L;
|
||||||
ulong mysqld_net_retry_count = 10L;
|
ulong mysqld_net_retry_count = 10L;
|
||||||
ulong open_files_limit;
|
ulong open_files_limit;
|
||||||
|
ulong opt_binlog_rows_event_max_size;
|
||||||
uint test_flags = 0;
|
uint test_flags = 0;
|
||||||
static uint opt_protocol= 0;
|
static uint opt_protocol= 0;
|
||||||
static FILE *result_file;
|
static FILE *result_file;
|
||||||
@@ -1436,6 +1439,12 @@ that may lead to an endless loop.",
|
|||||||
"Used to reserve file descriptors for use by this program.",
|
"Used to reserve file descriptors for use by this program.",
|
||||||
&open_files_limit, &open_files_limit, 0, GET_ULONG,
|
&open_files_limit, &open_files_limit, 0, GET_ULONG,
|
||||||
REQUIRED_ARG, MY_NFILE, 8, OS_FILE_LIMIT, 0, 1, 0},
|
REQUIRED_ARG, MY_NFILE, 8, OS_FILE_LIMIT, 0, 1, 0},
|
||||||
|
{"binlog-row-event-max-size", 0,
|
||||||
|
"The maximum size of a row-based binary log event in bytes. Rows will be "
|
||||||
|
"grouped into events smaller than this size if possible. "
|
||||||
|
"This value must be a multiple of 256.",
|
||||||
|
&opt_binlog_rows_event_max_size, &opt_binlog_rows_event_max_size, 0,
|
||||||
|
GET_ULONG, REQUIRED_ARG, UINT_MAX, 256, ULONG_MAX, 0, 256, 0},
|
||||||
{"verify-binlog-checksum", 'c', "Verify checksum binlog events.",
|
{"verify-binlog-checksum", 'c', "Verify checksum binlog events.",
|
||||||
(uchar**) &opt_verify_binlog_checksum, (uchar**) &opt_verify_binlog_checksum,
|
(uchar**) &opt_verify_binlog_checksum, (uchar**) &opt_verify_binlog_checksum,
|
||||||
0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
|
0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
|
||||||
|
@@ -35,7 +35,7 @@ IF(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
|||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
||||||
# Turn on Werror (warning => error) when using maintainer mode.
|
# Turn on Werror (warning => error) when using maintainer mode.
|
||||||
IF(MYSQL_MAINTAINER_MODE MATCHES "ON")
|
IF(MYSQL_MAINTAINER_MODE MATCHES "ERR")
|
||||||
SET(MY_C_WARNING_FLAGS "${MY_C_WARNING_FLAGS} -DFORCE_INIT_OF_VARS -Werror")
|
SET(MY_C_WARNING_FLAGS "${MY_C_WARNING_FLAGS} -DFORCE_INIT_OF_VARS -Werror")
|
||||||
SET(MY_CXX_WARNING_FLAGS "${MY_CXX_WARNING_FLAGS} -DFORCE_INIT_OF_VARS -Werror")
|
SET(MY_CXX_WARNING_FLAGS "${MY_CXX_WARNING_FLAGS} -DFORCE_INIT_OF_VARS -Werror")
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
@@ -156,37 +156,37 @@ MACRO (MYSQL_CHECK_SSL)
|
|||||||
LIST(REVERSE CMAKE_FIND_LIBRARY_SUFFIXES)
|
LIST(REVERSE CMAKE_FIND_LIBRARY_SUFFIXES)
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
||||||
# Verify version number. Version information looks like:
|
|
||||||
# #define OPENSSL_VERSION_NUMBER 0x1000103fL
|
|
||||||
# Encoded as MNNFFPPS: major minor fix patch status
|
|
||||||
FILE(STRINGS "${OPENSSL_INCLUDE_DIR}/openssl/opensslv.h"
|
|
||||||
OPENSSL_VERSION_NUMBER
|
|
||||||
REGEX "^#define[\t ]+OPENSSL_VERSION_NUMBER[\t ]+0x[0-9].*"
|
|
||||||
)
|
|
||||||
STRING(REGEX REPLACE
|
|
||||||
"^.*OPENSSL_VERSION_NUMBER[\t ]+0x([0-9]).*$" "\\1"
|
|
||||||
OPENSSL_MAJOR_VERSION "${OPENSSL_VERSION_NUMBER}"
|
|
||||||
)
|
|
||||||
|
|
||||||
IF(OPENSSL_INCLUDE_DIR AND
|
IF(OPENSSL_INCLUDE_DIR AND
|
||||||
OPENSSL_LIBRARIES AND
|
OPENSSL_LIBRARIES AND
|
||||||
CRYPTO_LIBRARY
|
CRYPTO_LIBRARY
|
||||||
)
|
)
|
||||||
|
# Verify version number. Version information looks like:
|
||||||
|
# #define OPENSSL_VERSION_NUMBER 0x1000103fL
|
||||||
|
# Encoded as MNNFFPPS: major minor fix patch status
|
||||||
|
FILE(STRINGS "${OPENSSL_INCLUDE_DIR}/openssl/opensslv.h"
|
||||||
|
OPENSSL_VERSION_NUMBER
|
||||||
|
REGEX "^#define[\t ]+OPENSSL_VERSION_NUMBER[\t ]+0x[0-9].*"
|
||||||
|
)
|
||||||
|
STRING(REGEX REPLACE
|
||||||
|
"^.*OPENSSL_VERSION_NUMBER[\t ]+0x([0-9]).*$" "\\1"
|
||||||
|
OPENSSL_MAJOR_VERSION "${OPENSSL_VERSION_NUMBER}"
|
||||||
|
)
|
||||||
|
INCLUDE(CheckSymbolExists)
|
||||||
|
SET(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
|
||||||
|
CHECK_SYMBOL_EXISTS(SHA512_DIGEST_LENGTH "openssl/sha.h"
|
||||||
|
HAVE_SHA512_DIGEST_LENGTH)
|
||||||
SET(OPENSSL_FOUND TRUE)
|
SET(OPENSSL_FOUND TRUE)
|
||||||
ELSE()
|
ELSE()
|
||||||
SET(OPENSSL_FOUND FALSE)
|
SET(OPENSSL_FOUND FALSE)
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
||||||
MESSAGE(STATUS "OPENSSL_INCLUDE_DIR = ${OPENSSL_INCLUDE_DIR}")
|
|
||||||
MESSAGE(STATUS "OPENSSL_LIBRARIES = ${OPENSSL_LIBRARIES}")
|
|
||||||
MESSAGE(STATUS "CRYPTO_LIBRARY = ${CRYPTO_LIBRARY}")
|
|
||||||
MESSAGE(STATUS "OPENSSL_MAJOR_VERSION = ${OPENSSL_MAJOR_VERSION}")
|
|
||||||
|
|
||||||
INCLUDE(CheckSymbolExists)
|
|
||||||
SET(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
|
|
||||||
CHECK_SYMBOL_EXISTS(SHA512_DIGEST_LENGTH "openssl/sha.h"
|
|
||||||
HAVE_SHA512_DIGEST_LENGTH)
|
|
||||||
IF(OPENSSL_FOUND AND HAVE_SHA512_DIGEST_LENGTH)
|
IF(OPENSSL_FOUND AND HAVE_SHA512_DIGEST_LENGTH)
|
||||||
|
MESSAGE(STATUS "OPENSSL_INCLUDE_DIR = ${OPENSSL_INCLUDE_DIR}")
|
||||||
|
MESSAGE(STATUS "OPENSSL_LIBRARIES = ${OPENSSL_LIBRARIES}")
|
||||||
|
MESSAGE(STATUS "CRYPTO_LIBRARY = ${CRYPTO_LIBRARY}")
|
||||||
|
MESSAGE(STATUS "OPENSSL_MAJOR_VERSION = ${OPENSSL_MAJOR_VERSION}")
|
||||||
|
|
||||||
|
|
||||||
SET(SSL_SOURCES "")
|
SET(SSL_SOURCES "")
|
||||||
SET(SSL_LIBRARIES ${OPENSSL_LIBRARIES} ${CRYPTO_LIBRARY})
|
SET(SSL_LIBRARIES ${OPENSSL_LIBRARIES} ${CRYPTO_LIBRARY})
|
||||||
IF(CMAKE_SYSTEM_NAME MATCHES "SunOS")
|
IF(CMAKE_SYSTEM_NAME MATCHES "SunOS")
|
||||||
|
@@ -2,7 +2,6 @@ usr/sbin/mysqld
|
|||||||
usr/lib/mysql/plugin/auth_pam.so
|
usr/lib/mysql/plugin/auth_pam.so
|
||||||
usr/lib/mysql/plugin/auth_socket.so
|
usr/lib/mysql/plugin/auth_socket.so
|
||||||
usr/lib/mysql/plugin/ha_mroonga.so
|
usr/lib/mysql/plugin/ha_mroonga.so
|
||||||
usr/lib/mysql/plugin/ha_oqgraph.so
|
|
||||||
usr/lib/mysql/plugin/ha_sequence.so
|
usr/lib/mysql/plugin/ha_sequence.so
|
||||||
usr/lib/mysql/plugin/ha_sphinx.so
|
usr/lib/mysql/plugin/ha_sphinx.so
|
||||||
usr/lib/mysql/plugin/ha_innodb.so
|
usr/lib/mysql/plugin/ha_innodb.so
|
||||||
@@ -15,7 +14,6 @@ usr/lib/mysql/plugin/semisync_master.so
|
|||||||
usr/lib/mysql/plugin/semisync_slave.so
|
usr/lib/mysql/plugin/semisync_slave.so
|
||||||
usr/lib/mysql/plugin/sql_errlog.so
|
usr/lib/mysql/plugin/sql_errlog.so
|
||||||
usr/lib/mysql/plugin/server_audit.so
|
usr/lib/mysql/plugin/server_audit.so
|
||||||
usr/lib/mysql/plugin/sphinx.so
|
|
||||||
usr/lib/libhsclient.so.*
|
usr/lib/libhsclient.so.*
|
||||||
etc/mysql/debian-start
|
etc/mysql/debian-start
|
||||||
etc/mysql/conf.d/mysqld_safe_syslog.cnf
|
etc/mysql/conf.d/mysqld_safe_syslog.cnf
|
||||||
|
@@ -21,7 +21,7 @@ invoke() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
MYSQL_BOOTSTRAP="/usr/sbin/mysqld --bootstrap --user=mysql --skip-grant-tables --default-storage-engine=myisam"
|
MYSQL_BOOTSTRAP="/usr/sbin/mysqld --bootstrap --user=mysql --disable-log-bin --skip-grant-tables --default-storage-engine=myisam"
|
||||||
|
|
||||||
test_mysql_access() {
|
test_mysql_access() {
|
||||||
mysql --no-defaults -u root -h localhost </dev/null >/dev/null 2>&1
|
mysql --no-defaults -u root -h localhost </dev/null >/dev/null 2>&1
|
||||||
@@ -40,6 +40,7 @@ set_mysql_rootpw() {
|
|||||||
# this avoids us having to call "test" or "[" on $rootpw
|
# this avoids us having to call "test" or "[" on $rootpw
|
||||||
cat << EOF > $tfile
|
cat << EOF > $tfile
|
||||||
USE mysql;
|
USE mysql;
|
||||||
|
SET sql_log_bin=0;
|
||||||
UPDATE user SET password=PASSWORD("$rootpw") WHERE user='root';
|
UPDATE user SET password=PASSWORD("$rootpw") WHERE user='root';
|
||||||
FLUSH PRIVILEGES;
|
FLUSH PRIVILEGES;
|
||||||
EOF
|
EOF
|
||||||
@@ -144,7 +145,7 @@ EOF
|
|||||||
# Debian: beware of the bashisms...
|
# Debian: beware of the bashisms...
|
||||||
# Debian: can safely run on upgrades with existing databases
|
# Debian: can safely run on upgrades with existing databases
|
||||||
set +e
|
set +e
|
||||||
/bin/bash /usr/bin/mysql_install_db --rpm --user=mysql 2>&1 | $ERR_LOGGER
|
/bin/bash /usr/bin/mysql_install_db --rpm --user=mysql --disable-log-bin 2>&1 | $ERR_LOGGER
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
## On every reconfiguration the maintenance user is recreated.
|
## On every reconfiguration the maintenance user is recreated.
|
||||||
|
@@ -2,7 +2,6 @@ usr/sbin/mysqld
|
|||||||
usr/lib/mysql/plugin/auth_pam.so
|
usr/lib/mysql/plugin/auth_pam.so
|
||||||
usr/lib/mysql/plugin/auth_socket.so
|
usr/lib/mysql/plugin/auth_socket.so
|
||||||
usr/lib/mysql/plugin/ha_mroonga.so
|
usr/lib/mysql/plugin/ha_mroonga.so
|
||||||
usr/lib/mysql/plugin/ha_oqgraph.so
|
|
||||||
usr/lib/mysql/plugin/ha_sequence.so
|
usr/lib/mysql/plugin/ha_sequence.so
|
||||||
usr/lib/mysql/plugin/ha_sphinx.so
|
usr/lib/mysql/plugin/ha_sphinx.so
|
||||||
usr/lib/mysql/plugin/ha_innodb.so
|
usr/lib/mysql/plugin/ha_innodb.so
|
||||||
@@ -15,7 +14,6 @@ usr/lib/mysql/plugin/semisync_master.so
|
|||||||
usr/lib/mysql/plugin/semisync_slave.so
|
usr/lib/mysql/plugin/semisync_slave.so
|
||||||
usr/lib/mysql/plugin/sql_errlog.so
|
usr/lib/mysql/plugin/sql_errlog.so
|
||||||
usr/lib/mysql/plugin/server_audit.so
|
usr/lib/mysql/plugin/server_audit.so
|
||||||
usr/lib/mysql/plugin/sphinx.so
|
|
||||||
usr/lib/libhsclient.so.*
|
usr/lib/libhsclient.so.*
|
||||||
etc/apparmor.d/usr.sbin.mysqld
|
etc/apparmor.d/usr.sbin.mysqld
|
||||||
usr/share/apport/package-hooks/source_mariadb-10.0.py
|
usr/share/apport/package-hooks/source_mariadb-10.0.py
|
||||||
|
@@ -21,7 +21,7 @@ invoke() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
MYSQL_BOOTSTRAP="/usr/sbin/mysqld --bootstrap --user=mysql --skip-grant-tables --default-storage-engine=myisam"
|
MYSQL_BOOTSTRAP="/usr/sbin/mysqld --bootstrap --user=mysql --disable-log-bin --skip-grant-tables --default-storage-engine=myisam"
|
||||||
|
|
||||||
test_mysql_access() {
|
test_mysql_access() {
|
||||||
mysql --no-defaults -u root -h localhost </dev/null >/dev/null 2>&1
|
mysql --no-defaults -u root -h localhost </dev/null >/dev/null 2>&1
|
||||||
@@ -41,6 +41,7 @@ set_mysql_rootpw() {
|
|||||||
# this avoids us having to call "test" or "[" on $rootpw
|
# this avoids us having to call "test" or "[" on $rootpw
|
||||||
cat << EOF > $tfile
|
cat << EOF > $tfile
|
||||||
USE mysql;
|
USE mysql;
|
||||||
|
SET sql_log_bin=0;
|
||||||
UPDATE user SET password=PASSWORD("$rootpw") WHERE user='root';
|
UPDATE user SET password=PASSWORD("$rootpw") WHERE user='root';
|
||||||
FLUSH PRIVILEGES;
|
FLUSH PRIVILEGES;
|
||||||
EOF
|
EOF
|
||||||
@@ -145,7 +146,7 @@ EOF
|
|||||||
# Debian: beware of the bashisms...
|
# Debian: beware of the bashisms...
|
||||||
# Debian: can safely run on upgrades with existing databases
|
# Debian: can safely run on upgrades with existing databases
|
||||||
set +e
|
set +e
|
||||||
/bin/bash /usr/bin/mysql_install_db --rpm --user=mysql 2>&1 | $ERR_LOGGER
|
/bin/bash /usr/bin/mysql_install_db --rpm --user=mysql --disable-log-bin 2>&1 | $ERR_LOGGER
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
## On every reconfiguration the maintenance user is recreated.
|
## On every reconfiguration the maintenance user is recreated.
|
||||||
|
@@ -618,14 +618,17 @@ void scramble_323(char *to, const char *message, const char *password);
|
|||||||
my_bool check_scramble_323(const unsigned char *reply, const char *message,
|
my_bool check_scramble_323(const unsigned char *reply, const char *message,
|
||||||
unsigned long *salt);
|
unsigned long *salt);
|
||||||
void get_salt_from_password_323(unsigned long *res, const char *password);
|
void get_salt_from_password_323(unsigned long *res, const char *password);
|
||||||
|
#if MYSQL_VERSION_ID < 100100
|
||||||
void make_password_from_salt_323(char *to, const unsigned long *salt);
|
void make_password_from_salt_323(char *to, const unsigned long *salt);
|
||||||
|
#endif
|
||||||
void make_scrambled_password(char *to, const char *password);
|
void make_scrambled_password(char *to, const char *password);
|
||||||
void scramble(char *to, const char *message, const char *password);
|
void scramble(char *to, const char *message, const char *password);
|
||||||
my_bool check_scramble(const unsigned char *reply, const char *message,
|
my_bool check_scramble(const unsigned char *reply, const char *message,
|
||||||
const unsigned char *hash_stage2);
|
const unsigned char *hash_stage2);
|
||||||
void get_salt_from_password(unsigned char *res, const char *password);
|
void get_salt_from_password(unsigned char *res, const char *password);
|
||||||
|
#if MYSQL_VERSION_ID < 100100
|
||||||
void make_password_from_salt(char *to, const unsigned char *hash_stage2);
|
void make_password_from_salt(char *to, const unsigned char *hash_stage2);
|
||||||
|
#endif
|
||||||
char *octet2hex(char *to, const char *str, unsigned int len);
|
char *octet2hex(char *to, const char *str, unsigned int len);
|
||||||
|
|
||||||
/* end of password.c */
|
/* end of password.c */
|
||||||
|
@@ -52,7 +52,7 @@ eval SELECT 'hello' INTO OUTFILE 'fake_file.$prefix';
|
|||||||
|
|
||||||
# Use '/' instead of '\' in the error message. On windows platform, dir is
|
# Use '/' instead of '\' in the error message. On windows platform, dir is
|
||||||
# formed with '\'.
|
# formed with '\'.
|
||||||
--replace_regex /\\testing_1\\*/\/testing_1\//
|
--replace_regex /\\testing_1\\*/\/testing_1\// /66/39/
|
||||||
--error 1010
|
--error 1010
|
||||||
DROP DATABASE testing_1;
|
DROP DATABASE testing_1;
|
||||||
let $wait_binlog_event= DROP TABLE IF EXIST;
|
let $wait_binlog_event= DROP TABLE IF EXIST;
|
||||||
|
@@ -1506,7 +1506,12 @@ sub command_line_setup {
|
|||||||
{
|
{
|
||||||
$default_vardir= "$glob_mysql_test_dir/var";
|
$default_vardir= "$glob_mysql_test_dir/var";
|
||||||
}
|
}
|
||||||
$default_vardir = realpath $default_vardir unless IS_WINDOWS;
|
unless (IS_WINDOWS) {
|
||||||
|
my $realpath = realpath($default_vardir);
|
||||||
|
die "realpath('$default_vardir') failed: $!\n"
|
||||||
|
unless defined($realpath) && $realpath ne '';
|
||||||
|
$default_vardir = $realpath;
|
||||||
|
}
|
||||||
|
|
||||||
if ( ! $opt_vardir )
|
if ( ! $opt_vardir )
|
||||||
{
|
{
|
||||||
|
@@ -3008,5 +3008,11 @@ Warnings:
|
|||||||
Note 1003 select `test`.`t1`.`c1` AS `c1` from `test`.`t1` where ('%' = concat(`test`.`t1`.`c1`))
|
Note 1003 select `test`.`t1`.`c1` AS `c1` from `test`.`t1` where ('%' = concat(`test`.`t1`.`c1`))
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
#
|
#
|
||||||
|
# MDEV-7629 Regression: Bit and hex string literals changed column names in 10.0.14
|
||||||
|
#
|
||||||
|
SELECT _binary 0x7E, _binary X'7E', _binary B'01111110';
|
||||||
|
_binary 0x7E _binary X'7E' _binary B'01111110'
|
||||||
|
~ ~ ~
|
||||||
|
#
|
||||||
# End of 10.0 tests
|
# End of 10.0 tests
|
||||||
#
|
#
|
||||||
|
@@ -7907,5 +7907,11 @@ HEX(a) a
|
|||||||
3F23 ?#
|
3F23 ?#
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
#
|
#
|
||||||
|
# MDEV-7629 Regression: Bit and hex string literals changed column names in 10.0.14
|
||||||
|
#
|
||||||
|
SELECT _latin1 0x7E, _latin1 X'7E', _latin1 B'01111110';
|
||||||
|
_latin1 0x7E _latin1 X'7E' _latin1 B'01111110'
|
||||||
|
~ ~ ~
|
||||||
|
#
|
||||||
# End of 10.0 tests
|
# End of 10.0 tests
|
||||||
#
|
#
|
||||||
|
@@ -6259,6 +6259,12 @@ EXECUTE stmt USING @b,@b;
|
|||||||
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,IMPLICIT) and (utf8_general_ci,COERCIBLE) for operation 'concat'
|
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,IMPLICIT) and (utf8_general_ci,COERCIBLE) for operation 'concat'
|
||||||
DEALLOCATE PREPARE stmt;
|
DEALLOCATE PREPARE stmt;
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
|
#
|
||||||
|
# MDEV-7629 Regression: Bit and hex string literals changed column names in 10.0.14
|
||||||
|
#
|
||||||
|
SELECT _utf8 0x7E, _utf8 X'7E', _utf8 B'01111110';
|
||||||
|
_utf8 0x7E _utf8 X'7E' _utf8 B'01111110'
|
||||||
|
~ ~ ~
|
||||||
# Start of ctype_unescape.inc
|
# Start of ctype_unescape.inc
|
||||||
SET @query=_binary'SELECT CHARSET(\'test\'),@@character_set_client,@@character_set_connection';
|
SET @query=_binary'SELECT CHARSET(\'test\'),@@character_set_client,@@character_set_connection';
|
||||||
PREPARE stmt FROM @query;
|
PREPARE stmt FROM @query;
|
||||||
|
@@ -5,7 +5,7 @@ explain extended select INTERVAL(55,10,20,30,40,50,60,70,80,90,100),interval(3,1
|
|||||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||||
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
|
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
|
||||||
Warnings:
|
Warnings:
|
||||||
Note 1003 select interval((55,10,20,30,40,50,60,70,80,90,100)) AS `INTERVAL(55,10,20,30,40,50,60,70,80,90,100)`,interval((3,1,(1 + 1),(((1 + 1) + 1) + 1))) AS `interval(3,1,1+1,1+1+1+1)`,field('IBM','NCA','ICL','SUN','IBM','DIGITAL') AS `field("IBM","NCA","ICL","SUN","IBM","DIGITAL")`,field('A','B','C') AS `field("A","B","C")`,elt(2,'ONE','TWO','THREE') AS `elt(2,"ONE","TWO","THREE")`,interval((0,1,2,3,4)) AS `interval(0,1,2,3,4)`,(elt(1,1,2,3) | 0) AS `elt(1,1,2,3)|0`,(elt(1,1.1,1.2,1.3) + 0) AS `elt(1,1.1,1.2,1.3)+0`
|
Note 1003 select interval(55,10,20,30,40,50,60,70,80,90,100) AS `INTERVAL(55,10,20,30,40,50,60,70,80,90,100)`,interval(3,1,(1 + 1),(((1 + 1) + 1) + 1)) AS `interval(3,1,1+1,1+1+1+1)`,field('IBM','NCA','ICL','SUN','IBM','DIGITAL') AS `field("IBM","NCA","ICL","SUN","IBM","DIGITAL")`,field('A','B','C') AS `field("A","B","C")`,elt(2,'ONE','TWO','THREE') AS `elt(2,"ONE","TWO","THREE")`,interval(0,1,2,3,4) AS `interval(0,1,2,3,4)`,(elt(1,1,2,3) | 0) AS `elt(1,1,2,3)|0`,(elt(1,1.1,1.2,1.3) + 0) AS `elt(1,1.1,1.2,1.3)+0`
|
||||||
SELECT INTERVAL(13, 7, 14, 21, 28, 35, 42, 49, 56);
|
SELECT INTERVAL(13, 7, 14, 21, 28, 35, 42, 49, 56);
|
||||||
INTERVAL(13, 7, 14, 21, 28, 35, 42, 49, 56)
|
INTERVAL(13, 7, 14, 21, 28, 35, 42, 49, 56)
|
||||||
1
|
1
|
||||||
|
@@ -5874,4 +5874,17 @@ id select_type table type possible_keys key key_len ref rows Extra
|
|||||||
1 SIMPLE t2 ALL NULL NULL NULL NULL 11 Using where
|
1 SIMPLE t2 ALL NULL NULL NULL NULL 11 Using where
|
||||||
set join_buffer_space_limit=default;
|
set join_buffer_space_limit=default;
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
#
|
||||||
|
# MDEV-6687: Assertion `0' failed in Protocol::end_statement on query
|
||||||
|
#
|
||||||
|
SET join_cache_level = 3;
|
||||||
|
# The following should have
|
||||||
|
# - table order PROFILING,user,
|
||||||
|
# - table user accessed with hash_ALL:
|
||||||
|
explain
|
||||||
|
SELECT * FROM INFORMATION_SCHEMA.PROFILING, mysql.user WHERE password_expired = PAGE_FAULTS_MINOR;
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 SIMPLE PROFILING ALL NULL NULL NULL NULL NULL Using where
|
||||||
|
1 SIMPLE user hash_ALL NULL #hash#$hj 1 information_schema.PROFILING.PAGE_FAULTS_MINOR 4 Using where; Using join buffer (flat, BNLH join)
|
||||||
|
set join_cache_level=default;
|
||||||
set @@optimizer_switch=@save_optimizer_switch;
|
set @@optimizer_switch=@save_optimizer_switch;
|
||||||
|
@@ -1409,4 +1409,40 @@ Note 1003 select `test`.`a`.`a` AS `a`,`test`.`a`.`b` AS `b`,`test`.`b`.`a` AS `
|
|||||||
set histogram_size=@save_histogram_size;
|
set histogram_size=@save_histogram_size;
|
||||||
set optimizer_use_condition_selectivity=@save_optimizer_use_condition_selectivity;
|
set optimizer_use_condition_selectivity=@save_optimizer_use_condition_selectivity;
|
||||||
drop table t0,t1,t2;
|
drop table t0,t1,t2;
|
||||||
|
#
|
||||||
|
# Bug mdev-7316: a conjunct in WHERE with selectivity == 0
|
||||||
|
#
|
||||||
|
CREATE TABLE t1 (a varchar(16), b int, PRIMARY KEY(a), KEY(b)) ENGINE=INNODB;
|
||||||
|
Warnings:
|
||||||
|
Warning 1286 Unknown storage engine 'INNODB'
|
||||||
|
Warning 1266 Using storage engine MyISAM for table 't1'
|
||||||
|
INSERT INTO t1 VALUES
|
||||||
|
('USAChinese',10), ('USAEnglish',20), ('USAFrench',30);
|
||||||
|
CREATE TABLE t2 (i int) ENGINE=INNODB;
|
||||||
|
Warnings:
|
||||||
|
Warning 1286 Unknown storage engine 'INNODB'
|
||||||
|
Warning 1266 Using storage engine MyISAM for table 't2'
|
||||||
|
INSERT INTO t2 VALUES
|
||||||
|
(1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(1),(2),(3),(4);
|
||||||
|
ANALYZE TABLE t1, t2;
|
||||||
|
Table Op Msg_type Msg_text
|
||||||
|
test.t1 analyze status Engine-independent statistics collected
|
||||||
|
test.t1 analyze status OK
|
||||||
|
test.t2 analyze status Engine-independent statistics collected
|
||||||
|
test.t2 analyze status OK
|
||||||
|
set use_stat_tables='preferably';
|
||||||
|
set optimizer_use_condition_selectivity=3;
|
||||||
|
EXPLAIN EXTENDED
|
||||||
|
SELECT * FROM t1, t2
|
||||||
|
WHERE a <> 'USARussian' AND b IS NULL;
|
||||||
|
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||||
|
1 SIMPLE t1 ref PRIMARY,b b 5 const 1 100.00 Using index condition; Using where
|
||||||
|
1 SIMPLE t2 ALL NULL NULL NULL NULL 14 100.00 Using join buffer (flat, BNL join)
|
||||||
|
Warnings:
|
||||||
|
Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t2`.`i` AS `i` from `test`.`t1` join `test`.`t2` where ((`test`.`t1`.`a` <> 'USARussian') and isnull(`test`.`t1`.`b`))
|
||||||
|
SELECT * FROM t1, t2
|
||||||
|
WHERE a <> 'USARussian' AND b IS NULL;
|
||||||
|
a b i
|
||||||
|
set optimizer_use_condition_selectivity=@save_optimizer_use_condition_selectivity;
|
||||||
|
DROP TABLE t1,t2;
|
||||||
set use_stat_tables=@save_use_stat_tables;
|
set use_stat_tables=@save_use_stat_tables;
|
||||||
|
@@ -1419,6 +1419,36 @@ Note 1003 select `test`.`a`.`a` AS `a`,`test`.`a`.`b` AS `b`,`test`.`b`.`a` AS `
|
|||||||
set histogram_size=@save_histogram_size;
|
set histogram_size=@save_histogram_size;
|
||||||
set optimizer_use_condition_selectivity=@save_optimizer_use_condition_selectivity;
|
set optimizer_use_condition_selectivity=@save_optimizer_use_condition_selectivity;
|
||||||
drop table t0,t1,t2;
|
drop table t0,t1,t2;
|
||||||
|
#
|
||||||
|
# Bug mdev-7316: a conjunct in WHERE with selectivity == 0
|
||||||
|
#
|
||||||
|
CREATE TABLE t1 (a varchar(16), b int, PRIMARY KEY(a), KEY(b)) ENGINE=INNODB;
|
||||||
|
INSERT INTO t1 VALUES
|
||||||
|
('USAChinese',10), ('USAEnglish',20), ('USAFrench',30);
|
||||||
|
CREATE TABLE t2 (i int) ENGINE=INNODB;
|
||||||
|
INSERT INTO t2 VALUES
|
||||||
|
(1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(1),(2),(3),(4);
|
||||||
|
ANALYZE TABLE t1, t2;
|
||||||
|
Table Op Msg_type Msg_text
|
||||||
|
test.t1 analyze status Engine-independent statistics collected
|
||||||
|
test.t1 analyze status OK
|
||||||
|
test.t2 analyze status Engine-independent statistics collected
|
||||||
|
test.t2 analyze status OK
|
||||||
|
set use_stat_tables='preferably';
|
||||||
|
set optimizer_use_condition_selectivity=3;
|
||||||
|
EXPLAIN EXTENDED
|
||||||
|
SELECT * FROM t1, t2
|
||||||
|
WHERE a <> 'USARussian' AND b IS NULL;
|
||||||
|
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||||
|
1 SIMPLE t1 ref PRIMARY,b b 5 const 2 66.67 Using where; Using index
|
||||||
|
1 SIMPLE t2 ALL NULL NULL NULL NULL 14 100.00 Using join buffer (flat, BNL join)
|
||||||
|
Warnings:
|
||||||
|
Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t2`.`i` AS `i` from `test`.`t1` join `test`.`t2` where ((`test`.`t1`.`a` <> 'USARussian') and isnull(`test`.`t1`.`b`))
|
||||||
|
SELECT * FROM t1, t2
|
||||||
|
WHERE a <> 'USARussian' AND b IS NULL;
|
||||||
|
a b i
|
||||||
|
set optimizer_use_condition_selectivity=@save_optimizer_use_condition_selectivity;
|
||||||
|
DROP TABLE t1,t2;
|
||||||
set use_stat_tables=@save_use_stat_tables;
|
set use_stat_tables=@save_use_stat_tables;
|
||||||
set optimizer_switch=@save_optimizer_switch_for_selectivity_test;
|
set optimizer_switch=@save_optimizer_switch_for_selectivity_test;
|
||||||
set @tmp_ust= @@use_stat_tables;
|
set @tmp_ust= @@use_stat_tables;
|
||||||
@@ -1482,6 +1512,30 @@ select * from t1 where col2 != true;
|
|||||||
col1 col2
|
col1 col2
|
||||||
drop table t1;
|
drop table t1;
|
||||||
#
|
#
|
||||||
|
# MDEV-7413: optimizer_use_condition_selectivity > 2 crashes 10.0.15+maria-1~wheezy
|
||||||
|
#
|
||||||
|
CREATE TABLE t1 (
|
||||||
|
parent_id int,
|
||||||
|
child_group_id int,
|
||||||
|
child_user_id int,
|
||||||
|
KEY (parent_id,child_group_id,child_user_id)
|
||||||
|
) ENGINE=InnoDB;
|
||||||
|
CREATE TABLE t2 (
|
||||||
|
id int,
|
||||||
|
lower_group_name varchar(255),
|
||||||
|
directory_id int(20),
|
||||||
|
UNIQUE KEY (directory_id)
|
||||||
|
) ENGINE=InnoDB;
|
||||||
|
CREATE TABLE t3 (id int) ENGINE=InnoDB;
|
||||||
|
insert into t1 values (1,1,1),(2,2,2);
|
||||||
|
insert into t2 values (10,'foo',10),(20,'bar',20);
|
||||||
|
insert into t3 values (101),(102);
|
||||||
|
set use_stat_tables = PREFERABLY, optimizer_use_condition_selectivity = 3;
|
||||||
|
select * from t1, t2, t3
|
||||||
|
where t1.child_user_id=t3.id and t1.child_group_id is null and t2.lower_group_name='foo' and t1.parent_id=t2.id and t2.directory_id=10;
|
||||||
|
parent_id child_group_id child_user_id id lower_group_name directory_id id
|
||||||
|
drop table t1,t2,t3;
|
||||||
|
#
|
||||||
# End of 10.0 tests
|
# End of 10.0 tests
|
||||||
#
|
#
|
||||||
set use_stat_tables= @tmp_ust;
|
set use_stat_tables= @tmp_ust;
|
||||||
|
@@ -284,4 +284,23 @@ DROP EVENT teste_bug11763507;
|
|||||||
# ------------------------------------------------------------------
|
# ------------------------------------------------------------------
|
||||||
# -- End of 5.1 tests
|
# -- End of 5.1 tests
|
||||||
# ------------------------------------------------------------------
|
# ------------------------------------------------------------------
|
||||||
|
grant create routine on test.* to foo1@localhost identified by 'foo';
|
||||||
|
update mysql.user set password = replace(password, '*', '-') where user='foo1';
|
||||||
|
show grants;
|
||||||
|
Grants for foo1@localhost
|
||||||
|
GRANT USAGE ON *.* TO 'foo1'@'localhost' IDENTIFIED BY PASSWORD '*F3A2A51A9B0F2BE2468926B4132313728C250DBF'
|
||||||
|
GRANT CREATE ROUTINE ON `test`.* TO 'foo1'@'localhost'
|
||||||
|
flush privileges;
|
||||||
|
show grants;
|
||||||
|
Grants for foo1@localhost
|
||||||
|
GRANT USAGE ON *.* TO 'foo1'@'localhost' IDENTIFIED BY PASSWORD '-F3A2A51A9B0F2BE2468926B4132313728C250DBF'
|
||||||
|
GRANT CREATE ROUTINE ON `test`.* TO 'foo1'@'localhost'
|
||||||
|
create procedure spfoo() select 1;
|
||||||
|
show grants;
|
||||||
|
Grants for foo1@localhost
|
||||||
|
GRANT USAGE ON *.* TO 'foo1'@'localhost' IDENTIFIED BY PASSWORD '-F3A2A51A9B0F2BE2468926B4132313728C250DBF'
|
||||||
|
GRANT CREATE ROUTINE ON `test`.* TO 'foo1'@'localhost'
|
||||||
|
GRANT EXECUTE, ALTER ROUTINE ON PROCEDURE `test`.`spfoo` TO 'foo1'@'localhost'
|
||||||
|
drop procedure spfoo;
|
||||||
|
drop user foo1@localhost;
|
||||||
set @@global.concurrent_insert= @old_concurrent_insert;
|
set @@global.concurrent_insert= @old_concurrent_insert;
|
||||||
|
@@ -2146,6 +2146,57 @@ drop database mysqltest2;
|
|||||||
drop database mysqltest3;
|
drop database mysqltest3;
|
||||||
drop database mysqltest4;
|
drop database mysqltest4;
|
||||||
# End of 5.5 tests
|
# End of 5.5 tests
|
||||||
|
#
|
||||||
|
# MDEV-7220: Materialization strategy is not used for REPLACE ... SELECT
|
||||||
|
#
|
||||||
|
create table t0(a int);
|
||||||
|
insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
|
||||||
|
create table t1 (a int, b int, c int);
|
||||||
|
insert into t1
|
||||||
|
select A.a+B.a*10+C.a*100, A.a+B.a*10+C.a*100, A.a+B.a*10+C.a*100
|
||||||
|
from t0 A, t0 B, t0 C;
|
||||||
|
create table t2 (a int, b int, c int);
|
||||||
|
insert into t2 select A.a, A.a, A.a from t1 A;
|
||||||
|
insert into t2 select * from t2;
|
||||||
|
insert into t2 select * from t2;
|
||||||
|
create table t3 as select * from t2 limit 1;
|
||||||
|
# The testcase only makes sense if the following uses Materialization:
|
||||||
|
explain
|
||||||
|
select * from t1 where (a,b) in (select max(a),b from t2 group by b);
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 PRIMARY t1 ALL NULL NULL NULL NULL 1000 Using where
|
||||||
|
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 test.t1.a,test.t1.b 1
|
||||||
|
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 4000 Using temporary
|
||||||
|
flush status;
|
||||||
|
replace into t3
|
||||||
|
select * from t1 where (a,b) in (select max(a),b from t2 group by b);
|
||||||
|
# Sequential reads:
|
||||||
|
# 1K is read from t1
|
||||||
|
# 4K is read from t2
|
||||||
|
# 1K groups is read from the tmp. table
|
||||||
|
#
|
||||||
|
# Lookups:
|
||||||
|
# 4K lookups in group by table
|
||||||
|
# 1K lookups in temp.table
|
||||||
|
#
|
||||||
|
# Writes:
|
||||||
|
# 2x 1K writes to temporary tables (grouping table and subquery materialization table
|
||||||
|
#
|
||||||
|
# The point is that neither counter should be in the millions (this
|
||||||
|
# will happen if Materialization is not used
|
||||||
|
show status where Variable_name like 'Handler_read%' or Variable_name like 'Handler_%write%';
|
||||||
|
Variable_name Value
|
||||||
|
Handler_read_first 0
|
||||||
|
Handler_read_key 5000
|
||||||
|
Handler_read_last 0
|
||||||
|
Handler_read_next 0
|
||||||
|
Handler_read_prev 0
|
||||||
|
Handler_read_rnd 0
|
||||||
|
Handler_read_rnd_deleted 0
|
||||||
|
Handler_read_rnd_next 6003
|
||||||
|
Handler_tmp_write 2000
|
||||||
|
Handler_write 1000
|
||||||
|
drop table t0,t1,t2,t3;
|
||||||
set @subselect_mat_test_optimizer_switch_value=null;
|
set @subselect_mat_test_optimizer_switch_value=null;
|
||||||
set @@optimizer_switch='materialization=on,in_to_exists=off,semijoin=off';
|
set @@optimizer_switch='materialization=on,in_to_exists=off,semijoin=off';
|
||||||
set optimizer_switch='mrr=on,mrr_sort_keys=on,index_condition_pushdown=on';
|
set optimizer_switch='mrr=on,mrr_sort_keys=on,index_condition_pushdown=on';
|
||||||
|
@@ -2186,3 +2186,54 @@ drop database mysqltest2;
|
|||||||
drop database mysqltest3;
|
drop database mysqltest3;
|
||||||
drop database mysqltest4;
|
drop database mysqltest4;
|
||||||
# End of 5.5 tests
|
# End of 5.5 tests
|
||||||
|
#
|
||||||
|
# MDEV-7220: Materialization strategy is not used for REPLACE ... SELECT
|
||||||
|
#
|
||||||
|
create table t0(a int);
|
||||||
|
insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
|
||||||
|
create table t1 (a int, b int, c int);
|
||||||
|
insert into t1
|
||||||
|
select A.a+B.a*10+C.a*100, A.a+B.a*10+C.a*100, A.a+B.a*10+C.a*100
|
||||||
|
from t0 A, t0 B, t0 C;
|
||||||
|
create table t2 (a int, b int, c int);
|
||||||
|
insert into t2 select A.a, A.a, A.a from t1 A;
|
||||||
|
insert into t2 select * from t2;
|
||||||
|
insert into t2 select * from t2;
|
||||||
|
create table t3 as select * from t2 limit 1;
|
||||||
|
# The testcase only makes sense if the following uses Materialization:
|
||||||
|
explain
|
||||||
|
select * from t1 where (a,b) in (select max(a),b from t2 group by b);
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 PRIMARY t1 ALL NULL NULL NULL NULL 1000 Using where
|
||||||
|
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 test.t1.a,test.t1.b 1
|
||||||
|
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 4000 Using temporary
|
||||||
|
flush status;
|
||||||
|
replace into t3
|
||||||
|
select * from t1 where (a,b) in (select max(a),b from t2 group by b);
|
||||||
|
# Sequential reads:
|
||||||
|
# 1K is read from t1
|
||||||
|
# 4K is read from t2
|
||||||
|
# 1K groups is read from the tmp. table
|
||||||
|
#
|
||||||
|
# Lookups:
|
||||||
|
# 4K lookups in group by table
|
||||||
|
# 1K lookups in temp.table
|
||||||
|
#
|
||||||
|
# Writes:
|
||||||
|
# 2x 1K writes to temporary tables (grouping table and subquery materialization table
|
||||||
|
#
|
||||||
|
# The point is that neither counter should be in the millions (this
|
||||||
|
# will happen if Materialization is not used
|
||||||
|
show status where Variable_name like 'Handler_read%' or Variable_name like 'Handler_%write%';
|
||||||
|
Variable_name Value
|
||||||
|
Handler_read_first 0
|
||||||
|
Handler_read_key 5000
|
||||||
|
Handler_read_last 0
|
||||||
|
Handler_read_next 0
|
||||||
|
Handler_read_prev 0
|
||||||
|
Handler_read_rnd 0
|
||||||
|
Handler_read_rnd_deleted 0
|
||||||
|
Handler_read_rnd_next 6003
|
||||||
|
Handler_tmp_write 2000
|
||||||
|
Handler_write 1000
|
||||||
|
drop table t0,t1,t2,t3;
|
||||||
|
@@ -109,3 +109,11 @@ DROP VIEW v1;
|
|||||||
CREATE VIEW v1 AS select `test`.`t1`.`a` AS `a` from `test`.`t1` where exists(select ' a ' AS `alias` from `test`.`t1` group by ' a ');
|
CREATE VIEW v1 AS select `test`.`t1`.`a` AS `a` from `test`.`t1` where exists(select ' a ' AS `alias` from `test`.`t1` group by ' a ');
|
||||||
DROP VIEW v1;
|
DROP VIEW v1;
|
||||||
DROP TABLE t1, t2;
|
DROP TABLE t1, t2;
|
||||||
|
create view v1 as select interval(55,10) as my_col;
|
||||||
|
show create view v1;
|
||||||
|
View Create View character_set_client collation_connection
|
||||||
|
v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select interval(55,10) AS `my_col` latin1 latin1_swedish_ci
|
||||||
|
select * from v1;
|
||||||
|
my_col
|
||||||
|
1
|
||||||
|
drop view v1;
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
create table t1(a int not null primary key, b int) engine=innodb;
|
call mtr.add_suppression("InnoDB: Error: row_merge_drop_indexes_dict failed with error code*");
|
||||||
|
create table t1(a int, b int) engine=innodb;
|
||||||
create procedure innodb_insert_proc (repeat_count int)
|
create procedure innodb_insert_proc (repeat_count int)
|
||||||
begin
|
begin
|
||||||
declare current_num int;
|
declare current_num int;
|
||||||
@@ -10,41 +11,53 @@ end while;
|
|||||||
end//
|
end//
|
||||||
commit;
|
commit;
|
||||||
set autocommit=0;
|
set autocommit=0;
|
||||||
call innodb_insert_proc(10000);
|
call innodb_insert_proc(20000);
|
||||||
commit;
|
commit;
|
||||||
set autocommit=1;
|
set autocommit=1;
|
||||||
|
create table t2(a int) engine=innodb;
|
||||||
|
show create table t2;
|
||||||
|
Table Create Table
|
||||||
|
t2 CREATE TABLE `t2` (
|
||||||
|
`a` int(11) DEFAULT NULL
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=latin1
|
||||||
set DEBUG_DBUG='+d,ib_os_aio_func_io_failure_28';
|
set DEBUG_DBUG='+d,ib_os_aio_func_io_failure_28';
|
||||||
alter table t1 add testcol int;
|
alter table t1 add testcol int;
|
||||||
ERROR HY000: The table 't1' is full
|
ERROR HY000: The table 't1' is full
|
||||||
show create table t1;
|
show create table t1;
|
||||||
Table Create Table
|
Table Create Table
|
||||||
t1 CREATE TABLE `t1` (
|
t1 CREATE TABLE `t1` (
|
||||||
`a` int(11) NOT NULL,
|
`a` int(11) DEFAULT NULL,
|
||||||
`b` int(11) DEFAULT NULL,
|
`b` int(11) DEFAULT NULL
|
||||||
PRIMARY KEY (`a`)
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1
|
) ENGINE=InnoDB DEFAULT CHARSET=latin1
|
||||||
set DEBUG_DBUG='+d,ib_os_aio_func_io_failure_28_2';
|
alter table t2 add testcol int;
|
||||||
|
ERROR HY000: The table 't2' is full
|
||||||
|
alter table t1 add testcol int;
|
||||||
|
ERROR HY000: The table 't1' is full
|
||||||
|
alter table t1 add testcol int;
|
||||||
|
ERROR HY000: The table 't1' is full
|
||||||
|
alter table t1 add testcol2 int;
|
||||||
|
ERROR HY000: The table 't1' is full
|
||||||
|
alter table t1 add testcol3 int;
|
||||||
|
ERROR HY000: The table 't1' is full
|
||||||
alter table t1 add testcol int;
|
alter table t1 add testcol int;
|
||||||
ERROR HY000: The table 't1' is full
|
ERROR HY000: The table 't1' is full
|
||||||
show create table t1;
|
show create table t1;
|
||||||
Table Create Table
|
Table Create Table
|
||||||
t1 CREATE TABLE `t1` (
|
t1 CREATE TABLE `t1` (
|
||||||
`a` int(11) NOT NULL,
|
`a` int(11) DEFAULT NULL,
|
||||||
`b` int(11) DEFAULT NULL,
|
`b` int(11) DEFAULT NULL
|
||||||
PRIMARY KEY (`a`)
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1
|
) ENGINE=InnoDB DEFAULT CHARSET=latin1
|
||||||
set DEBUG_DBUG=NULL;
|
drop table t2;
|
||||||
alter table t1 add testcol2 int;
|
alter table t1 add testcol2 int;
|
||||||
show create table t1;
|
ERROR HY000: The table 't1' is full
|
||||||
Table Create Table
|
alter table t1 add testcol3 int;
|
||||||
t1 CREATE TABLE `t1` (
|
ERROR HY000: The table 't1' is full
|
||||||
`a` int(11) NOT NULL,
|
call innodb_insert_proc(20000);
|
||||||
`b` int(11) DEFAULT NULL,
|
set autocommit=0;
|
||||||
`testcol2` int(11) DEFAULT NULL,
|
call innodb_insert_proc(20000);
|
||||||
PRIMARY KEY (`a`)
|
commit;
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1
|
set autocommit=1;
|
||||||
select count(1) from t1;
|
set DEBUG_DBUG='';
|
||||||
count(1)
|
|
||||||
10000
|
|
||||||
drop procedure innodb_insert_proc;
|
drop procedure innodb_insert_proc;
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
drop table if exists t2;
|
||||||
|
12
mysql-test/suite/innodb/r/innodb-mdev-7408.result
Normal file
12
mysql-test/suite/innodb/r/innodb-mdev-7408.result
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
select @@global.innodb_ft_server_stopword_table;
|
||||||
|
@@global.innodb_ft_server_stopword_table
|
||||||
|
NULL
|
||||||
|
CREATE TABLE `stop_it-IT` ENGINE = InnoDB SELECT * FROM information_schema.INNODB_FT_DEFAULT_STOPWORD;
|
||||||
|
SET @@global.innodb_ft_server_stopword_table = 'test/stop_it-IT';
|
||||||
|
ERROR 42000: Variable 'innodb_ft_server_stopword_table' can't be set to the value of 'test/stop_it-IT'
|
||||||
|
SET @@global.innodb_ft_server_stopword_table = 'test/stop_it@002dIT';
|
||||||
|
drop table `stop_it-IT`;
|
||||||
|
CREATE TABLE stop_it ENGINE = InnoDB SELECT * FROM information_schema.INNODB_FT_DEFAULT_STOPWORD;
|
||||||
|
SET @@global.innodb_ft_server_stopword_table = 'test/stop_it';
|
||||||
|
SET @@global.innodb_ft_server_stopword_table = NULL;
|
||||||
|
drop table stop_it;
|
@@ -1,3 +1,3 @@
|
|||||||
ERROR 42000: Row size too large (> ####). Changing some columns to TEXT or BLOB or using ROW_FORMAT=DYNAMIC or ROW_FORMAT=COMPRESSED may help. In current row format, BLOB prefix of 768 bytes is stored inline.
|
ERROR 42000: The size of BLOB/TEXT data inserted in one transaction is greater than 10% of redo log size. Increase the redo log size using innodb_log_file_size.
|
||||||
f4 f8
|
f4 f8
|
||||||
f4 f8
|
f4 f8
|
||||||
|
@@ -7,7 +7,9 @@
|
|||||||
# DEBUG_SYNC must be compiled in.
|
# DEBUG_SYNC must be compiled in.
|
||||||
--source include/have_debug_sync.inc
|
--source include/have_debug_sync.inc
|
||||||
|
|
||||||
create table t1(a int not null primary key, b int) engine=innodb;
|
call mtr.add_suppression("InnoDB: Error: row_merge_drop_indexes_dict failed with error code*");
|
||||||
|
|
||||||
|
create table t1(a int, b int) engine=innodb;
|
||||||
|
|
||||||
delimiter //;
|
delimiter //;
|
||||||
create procedure innodb_insert_proc (repeat_count int)
|
create procedure innodb_insert_proc (repeat_count int)
|
||||||
@@ -23,28 +25,51 @@ delimiter ;//
|
|||||||
commit;
|
commit;
|
||||||
|
|
||||||
set autocommit=0;
|
set autocommit=0;
|
||||||
call innodb_insert_proc(10000);
|
call innodb_insert_proc(20000);
|
||||||
commit;
|
commit;
|
||||||
set autocommit=1;
|
set autocommit=1;
|
||||||
|
|
||||||
|
create table t2(a int) engine=innodb;
|
||||||
|
show create table t2;
|
||||||
|
|
||||||
# This caused crash earlier
|
# This caused crash earlier
|
||||||
set DEBUG_DBUG='+d,ib_os_aio_func_io_failure_28';
|
set DEBUG_DBUG='+d,ib_os_aio_func_io_failure_28';
|
||||||
--error 1114
|
--error 1114
|
||||||
alter table t1 add testcol int;
|
alter table t1 add testcol int;
|
||||||
show create table t1;
|
show create table t1;
|
||||||
|
--error 1114
|
||||||
# This caused crash earlier
|
alter table t2 add testcol int;
|
||||||
set DEBUG_DBUG='+d,ib_os_aio_func_io_failure_28_2';
|
--error 1114
|
||||||
|
alter table t1 add testcol int;
|
||||||
|
--error 1114
|
||||||
|
alter table t1 add testcol int;
|
||||||
|
--error 1114
|
||||||
|
alter table t1 add testcol2 int;
|
||||||
|
--error 1114
|
||||||
|
alter table t1 add testcol3 int;
|
||||||
--error 1114
|
--error 1114
|
||||||
alter table t1 add testcol int;
|
alter table t1 add testcol int;
|
||||||
show create table t1;
|
show create table t1;
|
||||||
|
--error 0,1051
|
||||||
set DEBUG_DBUG=NULL;
|
drop table t2;
|
||||||
|
--error 1114
|
||||||
alter table t1 add testcol2 int;
|
alter table t1 add testcol2 int;
|
||||||
show create table t1;
|
--error 1114
|
||||||
|
alter table t1 add testcol3 int;
|
||||||
|
--error 0,1114
|
||||||
|
call innodb_insert_proc(20000);
|
||||||
|
set autocommit=0;
|
||||||
|
--error 0,1114
|
||||||
|
call innodb_insert_proc(20000);
|
||||||
|
commit;
|
||||||
|
set autocommit=1;
|
||||||
|
|
||||||
select count(1) from t1;
|
set DEBUG_DBUG='';
|
||||||
|
|
||||||
drop procedure innodb_insert_proc;
|
drop procedure innodb_insert_proc;
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
--disable_warnings
|
||||||
|
drop table if exists t2;
|
||||||
|
--enable_warnings
|
||||||
|
|
||||||
|
|
||||||
|
2
mysql-test/suite/innodb/t/innodb-mdev-7408.opt
Normal file
2
mysql-test/suite/innodb/t/innodb-mdev-7408.opt
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
--innodb_ft_default_stopword
|
||||||
|
|
16
mysql-test/suite/innodb/t/innodb-mdev-7408.test
Normal file
16
mysql-test/suite/innodb/t/innodb-mdev-7408.test
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
--source include/have_innodb.inc
|
||||||
|
|
||||||
|
select @@global.innodb_ft_server_stopword_table;
|
||||||
|
CREATE TABLE `stop_it-IT` ENGINE = InnoDB SELECT * FROM information_schema.INNODB_FT_DEFAULT_STOPWORD;
|
||||||
|
--error 1231
|
||||||
|
SET @@global.innodb_ft_server_stopword_table = 'test/stop_it-IT';
|
||||||
|
--error 0,1231
|
||||||
|
SET @@global.innodb_ft_server_stopword_table = 'test/stop_it@002dIT';
|
||||||
|
drop table `stop_it-IT`;
|
||||||
|
|
||||||
|
CREATE TABLE stop_it ENGINE = InnoDB SELECT * FROM information_schema.INNODB_FT_DEFAULT_STOPWORD;
|
||||||
|
SET @@global.innodb_ft_server_stopword_table = 'test/stop_it';
|
||||||
|
|
||||||
|
SET @@global.innodb_ft_server_stopword_table = NULL;
|
||||||
|
|
||||||
|
drop table stop_it;
|
@@ -1,5 +1,7 @@
|
|||||||
--source include/have_innodb.inc
|
--source include/have_innodb.inc
|
||||||
--source include/have_partition.inc
|
--source include/have_partition.inc
|
||||||
|
# Test causes OS error printout
|
||||||
|
--source include/not_windows.inc
|
||||||
|
|
||||||
--disable_query_log
|
--disable_query_log
|
||||||
--disable_result_log
|
--disable_result_log
|
||||||
|
@@ -5,6 +5,11 @@
|
|||||||
|
|
||||||
-- source include/have_innodb.inc
|
-- source include/have_innodb.inc
|
||||||
|
|
||||||
|
if (`select plugin_auth_version <= "5.6.22-MariaDB-72.0" from information_schema.plugins where plugin_name='innodb'`)
|
||||||
|
{
|
||||||
|
--skip Not fixed in XtraDB as of 5.6.22-MariaDB-72.0 or earlier
|
||||||
|
}
|
||||||
|
|
||||||
-- disable_query_log
|
-- disable_query_log
|
||||||
-- disable_result_log
|
-- disable_result_log
|
||||||
|
|
||||||
|
@@ -1136,6 +1136,80 @@ SET GLOBAL debug_dbug=@old_dbug;
|
|||||||
SET GLOBAL slave_parallel_threads=0;
|
SET GLOBAL slave_parallel_threads=0;
|
||||||
SET GLOBAL slave_parallel_threads=10;
|
SET GLOBAL slave_parallel_threads=10;
|
||||||
include/start_slave.inc
|
include/start_slave.inc
|
||||||
|
*** MDEV-7335: Potential parallel slave deadlock with specific binlog corruption ***
|
||||||
|
include/stop_slave.inc
|
||||||
|
SET GLOBAL slave_parallel_threads=1;
|
||||||
|
SET @old_dbug= @@GLOBAL.debug_dbug;
|
||||||
|
SET GLOBAL debug_dbug="+d,slave_discard_xid_for_gtid_0_x_1000";
|
||||||
|
INSERT INTO t2 VALUES (101);
|
||||||
|
INSERT INTO t2 VALUES (102);
|
||||||
|
INSERT INTO t2 VALUES (103);
|
||||||
|
INSERT INTO t2 VALUES (104);
|
||||||
|
INSERT INTO t2 VALUES (105);
|
||||||
|
SET gtid_seq_no=1000;
|
||||||
|
INSERT INTO t2 VALUES (106);
|
||||||
|
INSERT INTO t2 VALUES (107);
|
||||||
|
INSERT INTO t2 VALUES (108);
|
||||||
|
INSERT INTO t2 VALUES (109);
|
||||||
|
INSERT INTO t2 VALUES (110);
|
||||||
|
INSERT INTO t2 VALUES (111);
|
||||||
|
INSERT INTO t2 VALUES (112);
|
||||||
|
INSERT INTO t2 VALUES (113);
|
||||||
|
INSERT INTO t2 VALUES (114);
|
||||||
|
INSERT INTO t2 VALUES (115);
|
||||||
|
INSERT INTO t2 VALUES (116);
|
||||||
|
INSERT INTO t2 VALUES (117);
|
||||||
|
INSERT INTO t2 VALUES (118);
|
||||||
|
INSERT INTO t2 VALUES (119);
|
||||||
|
INSERT INTO t2 VALUES (120);
|
||||||
|
INSERT INTO t2 VALUES (121);
|
||||||
|
INSERT INTO t2 VALUES (122);
|
||||||
|
INSERT INTO t2 VALUES (123);
|
||||||
|
INSERT INTO t2 VALUES (124);
|
||||||
|
INSERT INTO t2 VALUES (125);
|
||||||
|
INSERT INTO t2 VALUES (126);
|
||||||
|
INSERT INTO t2 VALUES (127);
|
||||||
|
INSERT INTO t2 VALUES (128);
|
||||||
|
INSERT INTO t2 VALUES (129);
|
||||||
|
INSERT INTO t2 VALUES (130);
|
||||||
|
include/save_master_gtid.inc
|
||||||
|
include/start_slave.inc
|
||||||
|
include/sync_with_master_gtid.inc
|
||||||
|
SELECT * FROM t2 WHERE a >= 100 ORDER BY a;
|
||||||
|
a
|
||||||
|
101
|
||||||
|
102
|
||||||
|
103
|
||||||
|
104
|
||||||
|
105
|
||||||
|
107
|
||||||
|
108
|
||||||
|
109
|
||||||
|
110
|
||||||
|
111
|
||||||
|
112
|
||||||
|
113
|
||||||
|
114
|
||||||
|
115
|
||||||
|
116
|
||||||
|
117
|
||||||
|
118
|
||||||
|
119
|
||||||
|
120
|
||||||
|
121
|
||||||
|
122
|
||||||
|
123
|
||||||
|
124
|
||||||
|
125
|
||||||
|
126
|
||||||
|
127
|
||||||
|
128
|
||||||
|
129
|
||||||
|
130
|
||||||
|
include/stop_slave.inc
|
||||||
|
SET GLOBAL debug_dbug=@old_dbug;
|
||||||
|
SET GLOBAL slave_parallel_threads=10;
|
||||||
|
include/start_slave.inc
|
||||||
include/stop_slave.inc
|
include/stop_slave.inc
|
||||||
SET GLOBAL slave_parallel_threads=@old_parallel_threads;
|
SET GLOBAL slave_parallel_threads=@old_parallel_threads;
|
||||||
include/start_slave.inc
|
include/start_slave.inc
|
||||||
|
@@ -986,4 +986,15 @@ Warning 1196 Some non-transactional changed tables couldn't be rolled back
|
|||||||
include/diff_tables.inc [master:t1, slave:t1]
|
include/diff_tables.inc [master:t1, slave:t1]
|
||||||
include/diff_tables.inc [master:log, slave:log]
|
include/diff_tables.inc [master:log, slave:log]
|
||||||
drop table t1, log;
|
drop table t1, log;
|
||||||
|
drop trigger if exists notexistent;
|
||||||
|
Warnings:
|
||||||
|
Note 1360 Trigger does not exist
|
||||||
|
include/show_binlog_events.inc
|
||||||
|
Log_name Pos Event_type Server_id End_log_pos Info
|
||||||
|
master-bin.000001 # Gtid # # GTID #-#-#
|
||||||
|
master-bin.000001 # Query # # use `test`; drop trigger if exists notexistent
|
||||||
|
include/show_binlog_events.inc
|
||||||
|
Log_name Pos Event_type Server_id End_log_pos Info
|
||||||
|
slave-bin.000001 # Gtid # # GTID #-#-#
|
||||||
|
slave-bin.000001 # Query # # use `test`; drop trigger if exists notexistent
|
||||||
include/rpl_end.inc
|
include/rpl_end.inc
|
||||||
|
19
mysql-test/suite/rpl/r/semisync_future-7591.result
Normal file
19
mysql-test/suite/rpl/r/semisync_future-7591.result
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
include/master-slave.inc
|
||||||
|
[connection master]
|
||||||
|
call mtr.add_suppression("Timeout waiting for reply of binlog*");
|
||||||
|
create table t1 (i int);
|
||||||
|
set global rpl_semi_sync_master_enabled = ON;
|
||||||
|
include/stop_slave.inc
|
||||||
|
set global rpl_semi_sync_slave_enabled = ON;
|
||||||
|
change master to master_log_file='master-bin.000002', master_log_pos = 320;
|
||||||
|
start slave;
|
||||||
|
include/wait_for_slave_io_error.inc [errno=1236]
|
||||||
|
insert into t1 values (1);
|
||||||
|
reset master;
|
||||||
|
include/stop_slave.inc
|
||||||
|
reset slave;
|
||||||
|
include/start_slave.inc
|
||||||
|
set global rpl_semi_sync_slave_enabled = OFF;
|
||||||
|
drop table t1;
|
||||||
|
set global rpl_semi_sync_master_enabled = OFF;
|
||||||
|
include/rpl_end.inc
|
@@ -1843,6 +1843,62 @@ SET GLOBAL slave_parallel_threads=10;
|
|||||||
--source include/start_slave.inc
|
--source include/start_slave.inc
|
||||||
|
|
||||||
|
|
||||||
|
--echo *** MDEV-7335: Potential parallel slave deadlock with specific binlog corruption ***
|
||||||
|
|
||||||
|
--connection server_2
|
||||||
|
--source include/stop_slave.inc
|
||||||
|
SET GLOBAL slave_parallel_threads=1;
|
||||||
|
SET @old_dbug= @@GLOBAL.debug_dbug;
|
||||||
|
SET GLOBAL debug_dbug="+d,slave_discard_xid_for_gtid_0_x_1000";
|
||||||
|
|
||||||
|
--connection server_1
|
||||||
|
INSERT INTO t2 VALUES (101);
|
||||||
|
INSERT INTO t2 VALUES (102);
|
||||||
|
INSERT INTO t2 VALUES (103);
|
||||||
|
INSERT INTO t2 VALUES (104);
|
||||||
|
INSERT INTO t2 VALUES (105);
|
||||||
|
# Inject a partial event group (missing XID at the end). The bug was that such
|
||||||
|
# partial group was not handled appropriately, leading to server deadlock.
|
||||||
|
SET gtid_seq_no=1000;
|
||||||
|
INSERT INTO t2 VALUES (106);
|
||||||
|
INSERT INTO t2 VALUES (107);
|
||||||
|
INSERT INTO t2 VALUES (108);
|
||||||
|
INSERT INTO t2 VALUES (109);
|
||||||
|
INSERT INTO t2 VALUES (110);
|
||||||
|
INSERT INTO t2 VALUES (111);
|
||||||
|
INSERT INTO t2 VALUES (112);
|
||||||
|
INSERT INTO t2 VALUES (113);
|
||||||
|
INSERT INTO t2 VALUES (114);
|
||||||
|
INSERT INTO t2 VALUES (115);
|
||||||
|
INSERT INTO t2 VALUES (116);
|
||||||
|
INSERT INTO t2 VALUES (117);
|
||||||
|
INSERT INTO t2 VALUES (118);
|
||||||
|
INSERT INTO t2 VALUES (119);
|
||||||
|
INSERT INTO t2 VALUES (120);
|
||||||
|
INSERT INTO t2 VALUES (121);
|
||||||
|
INSERT INTO t2 VALUES (122);
|
||||||
|
INSERT INTO t2 VALUES (123);
|
||||||
|
INSERT INTO t2 VALUES (124);
|
||||||
|
INSERT INTO t2 VALUES (125);
|
||||||
|
INSERT INTO t2 VALUES (126);
|
||||||
|
INSERT INTO t2 VALUES (127);
|
||||||
|
INSERT INTO t2 VALUES (128);
|
||||||
|
INSERT INTO t2 VALUES (129);
|
||||||
|
INSERT INTO t2 VALUES (130);
|
||||||
|
--source include/save_master_gtid.inc
|
||||||
|
|
||||||
|
--connection server_2
|
||||||
|
--source include/start_slave.inc
|
||||||
|
--source include/sync_with_master_gtid.inc
|
||||||
|
# The partial event group (a=106) should be rolled back and thus missing.
|
||||||
|
SELECT * FROM t2 WHERE a >= 100 ORDER BY a;
|
||||||
|
|
||||||
|
--source include/stop_slave.inc
|
||||||
|
SET GLOBAL debug_dbug=@old_dbug;
|
||||||
|
SET GLOBAL slave_parallel_threads=10;
|
||||||
|
--source include/start_slave.inc
|
||||||
|
|
||||||
|
|
||||||
# Clean up.
|
# Clean up.
|
||||||
--connection server_2
|
--connection server_2
|
||||||
--source include/stop_slave.inc
|
--source include/stop_slave.inc
|
||||||
|
@@ -532,6 +532,19 @@ connection master;
|
|||||||
drop table t1, log;
|
drop table t1, log;
|
||||||
sync_slave_with_master;
|
sync_slave_with_master;
|
||||||
|
|
||||||
|
#
|
||||||
|
# MDEV-6769 DROP TRIGGER IF NOT EXIST binlogged on master but not on slave
|
||||||
|
#
|
||||||
|
let $slave_pos= query_get_value(SHOW MASTER STATUS, Position, 1);
|
||||||
|
connection master;
|
||||||
|
let $binlog_start= query_get_value(SHOW MASTER STATUS, Position, 1);
|
||||||
|
drop trigger if exists notexistent;
|
||||||
|
source include/show_binlog_events.inc;
|
||||||
|
sync_slave_with_master;
|
||||||
|
let $binlog_start= $slave_pos;
|
||||||
|
source include/show_binlog_events.inc;
|
||||||
|
connection master;
|
||||||
|
|
||||||
#
|
#
|
||||||
# End of tests
|
# End of tests
|
||||||
#
|
#
|
||||||
|
31
mysql-test/suite/rpl/t/semisync_future-7591.test
Normal file
31
mysql-test/suite/rpl/t/semisync_future-7591.test
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
--source include/have_semisync.inc
|
||||||
|
--source include/master-slave.inc
|
||||||
|
|
||||||
|
call mtr.add_suppression("Timeout waiting for reply of binlog*");
|
||||||
|
create table t1 (i int);
|
||||||
|
|
||||||
|
set global rpl_semi_sync_master_enabled = ON;
|
||||||
|
|
||||||
|
--connection slave
|
||||||
|
--source include/stop_slave.inc
|
||||||
|
set global rpl_semi_sync_slave_enabled = ON;
|
||||||
|
change master to master_log_file='master-bin.000002', master_log_pos = 320;
|
||||||
|
|
||||||
|
start slave;
|
||||||
|
--let $slave_io_errno=1236
|
||||||
|
--source include/wait_for_slave_io_error.inc
|
||||||
|
|
||||||
|
--connection master
|
||||||
|
insert into t1 values (1);
|
||||||
|
reset master;
|
||||||
|
|
||||||
|
--connection slave
|
||||||
|
--source include/stop_slave.inc
|
||||||
|
reset slave;
|
||||||
|
--source include/start_slave.inc
|
||||||
|
|
||||||
|
set global rpl_semi_sync_slave_enabled = OFF;
|
||||||
|
--connection master
|
||||||
|
drop table t1;
|
||||||
|
set global rpl_semi_sync_master_enabled = OFF;
|
||||||
|
--source include/rpl_end.inc
|
@@ -19,6 +19,11 @@ set names binary;
|
|||||||
SET NAMES binary;
|
SET NAMES binary;
|
||||||
--source include/ctype_like_cond_propagation.inc
|
--source include/ctype_like_cond_propagation.inc
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # MDEV-7629 Regression: Bit and hex string literals changed column names in 10.0.14
|
||||||
|
--echo #
|
||||||
|
SELECT _binary 0x7E, _binary X'7E', _binary B'01111110';
|
||||||
|
|
||||||
--echo #
|
--echo #
|
||||||
--echo # End of 10.0 tests
|
--echo # End of 10.0 tests
|
||||||
--echo #
|
--echo #
|
||||||
|
@@ -240,6 +240,11 @@ SHOW WARNINGS;
|
|||||||
SELECT HEX(a),a FROM t1;
|
SELECT HEX(a),a FROM t1;
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # MDEV-7629 Regression: Bit and hex string literals changed column names in 10.0.14
|
||||||
|
--echo #
|
||||||
|
SELECT _latin1 0x7E, _latin1 X'7E', _latin1 B'01111110';
|
||||||
|
|
||||||
--echo #
|
--echo #
|
||||||
--echo # End of 10.0 tests
|
--echo # End of 10.0 tests
|
||||||
--echo #
|
--echo #
|
||||||
|
@@ -1744,6 +1744,11 @@ EXECUTE stmt USING @b,@b;
|
|||||||
DEALLOCATE PREPARE stmt;
|
DEALLOCATE PREPARE stmt;
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # MDEV-7629 Regression: Bit and hex string literals changed column names in 10.0.14
|
||||||
|
--echo #
|
||||||
|
SELECT _utf8 0x7E, _utf8 X'7E', _utf8 B'01111110';
|
||||||
|
|
||||||
|
|
||||||
let $ctype_unescape_combinations=selected;
|
let $ctype_unescape_combinations=selected;
|
||||||
--source include/ctype_unescape.inc
|
--source include/ctype_unescape.inc
|
||||||
|
@@ -3848,6 +3848,18 @@ set join_buffer_space_limit=default;
|
|||||||
|
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # MDEV-6687: Assertion `0' failed in Protocol::end_statement on query
|
||||||
|
--echo #
|
||||||
|
SET join_cache_level = 3;
|
||||||
|
--echo # The following should have
|
||||||
|
--echo # - table order PROFILING,user,
|
||||||
|
--echo # - table user accessed with hash_ALL:
|
||||||
|
explain
|
||||||
|
SELECT * FROM INFORMATION_SCHEMA.PROFILING, mysql.user WHERE password_expired = PAGE_FAULTS_MINOR;
|
||||||
|
|
||||||
|
set join_cache_level=default;
|
||||||
|
|
||||||
# The following command must be the last one the file
|
# The following command must be the last one the file
|
||||||
# this must be the last command in the file
|
# this must be the last command in the file
|
||||||
set @@optimizer_switch=@save_optimizer_switch;
|
set @@optimizer_switch=@save_optimizer_switch;
|
||||||
|
@@ -149,11 +149,11 @@ UPDATE `t``\""e` SET a = 4 WHERE a = 22;
|
|||||||
# NOTE: replace_regex is very slow on match copy/past '(.*)' regex's
|
# NOTE: replace_regex is very slow on match copy/past '(.*)' regex's
|
||||||
# on big texts, removing a lot of text before + after makes it much faster.
|
# on big texts, removing a lot of text before + after makes it much faster.
|
||||||
#/.*in (.*) trx.*/\1/
|
#/.*in (.*) trx.*/\1/
|
||||||
--replace_regex /.*RECORD LOCKS space id [0-9]* page no [0-9]* n bits [0-9]* // / trx id .*// /.*index .* in //
|
--replace_regex /.*RECORD LOCKS space id [0-9]* page no [0-9]* n bits [0-9]* // / trx id .*// /.*index .* in // /trx table locks [0-9]* // /total table locks [0-9]* //
|
||||||
SHOW ENGINE InnoDB STATUS;
|
SHOW ENGINE InnoDB STATUS;
|
||||||
set @old_sql_mode = @@sql_mode;
|
set @old_sql_mode = @@sql_mode;
|
||||||
set sql_mode = 'ANSI_QUOTES';
|
set sql_mode = 'ANSI_QUOTES';
|
||||||
--replace_regex /.*RECORD LOCKS space id [0-9]* page no [0-9]* n bits [0-9]* // / trx id .*// /.*index .* in //
|
--replace_regex /.*RECORD LOCKS space id [0-9]* page no [0-9]* n bits [0-9]* // / trx id .*// /.*index .* in // /trx table locks [0-9]* // /total table locks [0-9]* //
|
||||||
SHOW ENGINE InnoDB STATUS;
|
SHOW ENGINE InnoDB STATUS;
|
||||||
set @@sql_mode = @old_sql_mode;
|
set @@sql_mode = @old_sql_mode;
|
||||||
--echo # con1
|
--echo # con1
|
||||||
|
@@ -942,5 +942,34 @@ set optimizer_use_condition_selectivity=@save_optimizer_use_condition_selectivit
|
|||||||
|
|
||||||
drop table t0,t1,t2;
|
drop table t0,t1,t2;
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # Bug mdev-7316: a conjunct in WHERE with selectivity == 0
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
CREATE TABLE t1 (a varchar(16), b int, PRIMARY KEY(a), KEY(b)) ENGINE=INNODB;
|
||||||
|
INSERT INTO t1 VALUES
|
||||||
|
('USAChinese',10), ('USAEnglish',20), ('USAFrench',30);
|
||||||
|
|
||||||
|
CREATE TABLE t2 (i int) ENGINE=INNODB;
|
||||||
|
INSERT INTO t2 VALUES
|
||||||
|
(1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(1),(2),(3),(4);
|
||||||
|
|
||||||
|
ANALYZE TABLE t1, t2;
|
||||||
|
|
||||||
|
set use_stat_tables='preferably';
|
||||||
|
set optimizer_use_condition_selectivity=3;
|
||||||
|
|
||||||
|
EXPLAIN EXTENDED
|
||||||
|
SELECT * FROM t1, t2
|
||||||
|
WHERE a <> 'USARussian' AND b IS NULL;
|
||||||
|
|
||||||
|
SELECT * FROM t1, t2
|
||||||
|
WHERE a <> 'USARussian' AND b IS NULL;
|
||||||
|
|
||||||
|
set optimizer_use_condition_selectivity=@save_optimizer_use_condition_selectivity;
|
||||||
|
|
||||||
|
DROP TABLE t1,t2;
|
||||||
|
|
||||||
|
|
||||||
set use_stat_tables=@save_use_stat_tables;
|
set use_stat_tables=@save_use_stat_tables;
|
||||||
|
|
||||||
|
@@ -79,6 +79,36 @@ select * from t1 where col2 != true;
|
|||||||
|
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # MDEV-7413: optimizer_use_condition_selectivity > 2 crashes 10.0.15+maria-1~wheezy
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
CREATE TABLE t1 (
|
||||||
|
parent_id int,
|
||||||
|
child_group_id int,
|
||||||
|
child_user_id int,
|
||||||
|
KEY (parent_id,child_group_id,child_user_id)
|
||||||
|
) ENGINE=InnoDB;
|
||||||
|
|
||||||
|
CREATE TABLE t2 (
|
||||||
|
id int,
|
||||||
|
lower_group_name varchar(255),
|
||||||
|
directory_id int(20),
|
||||||
|
UNIQUE KEY (directory_id)
|
||||||
|
) ENGINE=InnoDB;
|
||||||
|
|
||||||
|
CREATE TABLE t3 (id int) ENGINE=InnoDB;
|
||||||
|
|
||||||
|
insert into t1 values (1,1,1),(2,2,2);
|
||||||
|
insert into t2 values (10,'foo',10),(20,'bar',20);
|
||||||
|
insert into t3 values (101),(102);
|
||||||
|
set use_stat_tables = PREFERABLY, optimizer_use_condition_selectivity = 3;
|
||||||
|
|
||||||
|
select * from t1, t2, t3
|
||||||
|
where t1.child_user_id=t3.id and t1.child_group_id is null and t2.lower_group_name='foo' and t1.parent_id=t2.id and t2.directory_id=10;
|
||||||
|
|
||||||
|
drop table t1,t2,t3;
|
||||||
|
|
||||||
--echo #
|
--echo #
|
||||||
--echo # End of 10.0 tests
|
--echo # End of 10.0 tests
|
||||||
--echo #
|
--echo #
|
||||||
|
@@ -461,6 +461,26 @@ DROP EVENT teste_bug11763507;
|
|||||||
--echo # -- End of 5.1 tests
|
--echo # -- End of 5.1 tests
|
||||||
--echo # ------------------------------------------------------------------
|
--echo # ------------------------------------------------------------------
|
||||||
|
|
||||||
|
#
|
||||||
|
# A case of SHOW GRANTS
|
||||||
|
# (creating a new procedure changes the password)
|
||||||
|
#
|
||||||
|
grant create routine on test.* to foo1@localhost identified by 'foo';
|
||||||
|
update mysql.user set password = replace(password, '*', '-') where user='foo1';
|
||||||
|
--connect (foo,localhost,foo1,foo)
|
||||||
|
show grants;
|
||||||
|
--connection default
|
||||||
|
flush privileges;
|
||||||
|
--connection foo
|
||||||
|
show grants;
|
||||||
|
create procedure spfoo() select 1;
|
||||||
|
show grants;
|
||||||
|
|
||||||
|
--connection default
|
||||||
|
--disconnect foo
|
||||||
|
drop procedure spfoo;
|
||||||
|
drop user foo1@localhost;
|
||||||
|
|
||||||
#
|
#
|
||||||
# Restore global concurrent_insert value. Keep in the end of the test file.
|
# Restore global concurrent_insert value. Keep in the end of the test file.
|
||||||
#
|
#
|
||||||
|
@@ -1843,3 +1843,45 @@ drop database mysqltest4;
|
|||||||
|
|
||||||
--echo # End of 5.5 tests
|
--echo # End of 5.5 tests
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # MDEV-7220: Materialization strategy is not used for REPLACE ... SELECT
|
||||||
|
--echo #
|
||||||
|
create table t0(a int);
|
||||||
|
insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
|
||||||
|
|
||||||
|
create table t1 (a int, b int, c int);
|
||||||
|
insert into t1
|
||||||
|
select A.a+B.a*10+C.a*100, A.a+B.a*10+C.a*100, A.a+B.a*10+C.a*100
|
||||||
|
from t0 A, t0 B, t0 C;
|
||||||
|
|
||||||
|
create table t2 (a int, b int, c int);
|
||||||
|
insert into t2 select A.a, A.a, A.a from t1 A;
|
||||||
|
insert into t2 select * from t2;
|
||||||
|
insert into t2 select * from t2;
|
||||||
|
|
||||||
|
create table t3 as select * from t2 limit 1;
|
||||||
|
|
||||||
|
--echo # The testcase only makes sense if the following uses Materialization:
|
||||||
|
explain
|
||||||
|
select * from t1 where (a,b) in (select max(a),b from t2 group by b);
|
||||||
|
|
||||||
|
flush status;
|
||||||
|
replace into t3
|
||||||
|
select * from t1 where (a,b) in (select max(a),b from t2 group by b);
|
||||||
|
--echo # Sequential reads:
|
||||||
|
--echo # 1K is read from t1
|
||||||
|
--echo # 4K is read from t2
|
||||||
|
--echo # 1K groups is read from the tmp. table
|
||||||
|
--echo #
|
||||||
|
--echo # Lookups:
|
||||||
|
--echo # 4K lookups in group by table
|
||||||
|
--echo # 1K lookups in temp.table
|
||||||
|
--echo #
|
||||||
|
--echo # Writes:
|
||||||
|
--echo # 2x 1K writes to temporary tables (grouping table and subquery materialization table
|
||||||
|
--echo #
|
||||||
|
--echo # The point is that neither counter should be in the millions (this
|
||||||
|
--echo # will happen if Materialization is not used
|
||||||
|
show status where Variable_name like 'Handler_read%' or Variable_name like 'Handler_%write%';
|
||||||
|
|
||||||
|
drop table t0,t1,t2,t3;
|
||||||
|
@@ -90,3 +90,12 @@ eval CREATE VIEW v1 AS $query;
|
|||||||
DROP VIEW v1;
|
DROP VIEW v1;
|
||||||
|
|
||||||
DROP TABLE t1, t2;
|
DROP TABLE t1, t2;
|
||||||
|
|
||||||
|
#
|
||||||
|
# MDEV-7482 VIEW containing INTERVAL(...)
|
||||||
|
#
|
||||||
|
create view v1 as select interval(55,10) as my_col;
|
||||||
|
show create view v1;
|
||||||
|
select * from v1;
|
||||||
|
drop view v1;
|
||||||
|
|
||||||
|
@@ -855,7 +855,7 @@ static int search_default_file_with_ext(Process_option_func opt_handler,
|
|||||||
ptr, name, line)))
|
ptr, name, line)))
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
if (!(search_dir= my_dir(ptr, MYF(MY_WME))))
|
if (!(search_dir= my_dir(ptr, MYF(MY_WME | MY_WANT_SORT))))
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
for (i= 0; i < (uint) search_dir->number_of_files; i++)
|
for (i= 0; i < (uint) search_dir->number_of_files; i++)
|
||||||
|
@@ -1503,7 +1503,13 @@ done:
|
|||||||
/* Come here if error and we need to rollback. */
|
/* Come here if error and we need to rollback. */
|
||||||
err:
|
err:
|
||||||
error= 1; /* Transaction was rolled back */
|
error= 1; /* Transaction was rolled back */
|
||||||
ha_rollback_trans(thd, all);
|
/*
|
||||||
|
In parallel replication, rollback is delayed, as there is extra replication
|
||||||
|
book-keeping to be done before rolling back and allowing a conflicting
|
||||||
|
transaction to continue (MDEV-7458).
|
||||||
|
*/
|
||||||
|
if (!(thd->rgi_slave && thd->rgi_slave->is_parallel_exec))
|
||||||
|
ha_rollback_trans(thd, all);
|
||||||
|
|
||||||
end:
|
end:
|
||||||
if (rw_trans && mdl_request.ticket)
|
if (rw_trans && mdl_request.ticket)
|
||||||
|
@@ -2931,8 +2931,9 @@ public:
|
|||||||
{
|
{
|
||||||
set_cs_specified(true);
|
set_cs_specified(true);
|
||||||
}
|
}
|
||||||
Item_string_with_introducer(const String *str, CHARSET_INFO *tocs)
|
Item_string_with_introducer(const char *name,
|
||||||
:Item_string(str->ptr(), str->length(), tocs)
|
const char *str, uint length, CHARSET_INFO *tocs)
|
||||||
|
:Item_string(name, str, length, tocs)
|
||||||
{
|
{
|
||||||
set_cs_specified(true);
|
set_cs_specified(true);
|
||||||
}
|
}
|
||||||
|
@@ -734,6 +734,11 @@ public:
|
|||||||
void fix_length_and_dec();
|
void fix_length_and_dec();
|
||||||
const char *func_name() const { return "interval"; }
|
const char *func_name() const { return "interval"; }
|
||||||
uint decimal_precision() const { return 2; }
|
uint decimal_precision() const { return 2; }
|
||||||
|
void print(String *str, enum_query_type query_type)
|
||||||
|
{
|
||||||
|
str->append(func_name());
|
||||||
|
print_args(str, 0, query_type);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@@ -55,6 +55,8 @@
|
|||||||
|
|
||||||
#define my_b_write_string(A, B) my_b_write((A), (B), (uint) (sizeof(B) - 1))
|
#define my_b_write_string(A, B) my_b_write((A), (B), (uint) (sizeof(B) - 1))
|
||||||
|
|
||||||
|
using std::max;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
BINLOG_CHECKSUM variable.
|
BINLOG_CHECKSUM variable.
|
||||||
*/
|
*/
|
||||||
@@ -1329,9 +1331,10 @@ int Log_event::read_log_event(IO_CACHE* file, String* packet,
|
|||||||
}
|
}
|
||||||
data_len= uint4korr(buf + EVENT_LEN_OFFSET);
|
data_len= uint4korr(buf + EVENT_LEN_OFFSET);
|
||||||
if (data_len < LOG_EVENT_MINIMAL_HEADER_LEN ||
|
if (data_len < LOG_EVENT_MINIMAL_HEADER_LEN ||
|
||||||
data_len > current_thd->variables.max_allowed_packet)
|
data_len > max(current_thd->variables.max_allowed_packet,
|
||||||
|
opt_binlog_rows_event_max_size + MAX_LOG_EVENT_HEADER))
|
||||||
{
|
{
|
||||||
DBUG_PRINT("error",("data_len: %ld", data_len));
|
DBUG_PRINT("error",("data_len: %lu", data_len));
|
||||||
result= ((data_len < LOG_EVENT_MINIMAL_HEADER_LEN) ? LOG_READ_BOGUS :
|
result= ((data_len < LOG_EVENT_MINIMAL_HEADER_LEN) ? LOG_READ_BOGUS :
|
||||||
LOG_READ_TOO_LARGE);
|
LOG_READ_TOO_LARGE);
|
||||||
goto end;
|
goto end;
|
||||||
@@ -1452,7 +1455,7 @@ failed my_b_read"));
|
|||||||
*/
|
*/
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
}
|
}
|
||||||
uint data_len = uint4korr(head + EVENT_LEN_OFFSET);
|
ulong data_len = uint4korr(head + EVENT_LEN_OFFSET);
|
||||||
char *buf= 0;
|
char *buf= 0;
|
||||||
const char *error= 0;
|
const char *error= 0;
|
||||||
Log_event *res= 0;
|
Log_event *res= 0;
|
||||||
@@ -1461,7 +1464,8 @@ failed my_b_read"));
|
|||||||
uint max_allowed_packet= thd ? slave_max_allowed_packet:~(uint)0;
|
uint max_allowed_packet= thd ? slave_max_allowed_packet:~(uint)0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (data_len > max_allowed_packet)
|
if (data_len > max<ulong>(max_allowed_packet,
|
||||||
|
opt_binlog_rows_event_max_size + MAX_LOG_EVENT_HEADER))
|
||||||
{
|
{
|
||||||
error = "Event too big";
|
error = "Event too big";
|
||||||
goto err;
|
goto err;
|
||||||
@@ -1495,7 +1499,7 @@ err:
|
|||||||
{
|
{
|
||||||
DBUG_ASSERT(error != 0);
|
DBUG_ASSERT(error != 0);
|
||||||
sql_print_error("Error in Log_event::read_log_event(): "
|
sql_print_error("Error in Log_event::read_log_event(): "
|
||||||
"'%s', data_len: %d, event_type: %d",
|
"'%s', data_len: %lu, event_type: %d",
|
||||||
error,data_len,(uchar)(head[EVENT_TYPE_OFFSET]));
|
error,data_len,(uchar)(head[EVENT_TYPE_OFFSET]));
|
||||||
my_free(buf);
|
my_free(buf);
|
||||||
/*
|
/*
|
||||||
|
@@ -513,8 +513,6 @@ bool is_materialization_applicable(THD *thd, Item_in_subselect *in_subs,
|
|||||||
Subquery !contains {GROUP BY, ORDER BY [LIMIT],
|
Subquery !contains {GROUP BY, ORDER BY [LIMIT],
|
||||||
aggregate functions}) && subquery predicate is not under "NOT IN"))
|
aggregate functions}) && subquery predicate is not under "NOT IN"))
|
||||||
|
|
||||||
(*) The subquery must be part of a SELECT or CREATE TABLE ... SELECT statement.
|
|
||||||
The current condition also excludes multi-table update statements.
|
|
||||||
A note about prepared statements: we want the if-branch to be taken on
|
A note about prepared statements: we want the if-branch to be taken on
|
||||||
PREPARE and each EXECUTE. The rewrites are only done once, but we need
|
PREPARE and each EXECUTE. The rewrites are only done once, but we need
|
||||||
select_lex->sj_subselects list to be populated for every EXECUTE.
|
select_lex->sj_subselects list to be populated for every EXECUTE.
|
||||||
@@ -523,9 +521,7 @@ bool is_materialization_applicable(THD *thd, Item_in_subselect *in_subs,
|
|||||||
if (optimizer_flag(thd, OPTIMIZER_SWITCH_MATERIALIZATION) && // 0
|
if (optimizer_flag(thd, OPTIMIZER_SWITCH_MATERIALIZATION) && // 0
|
||||||
!child_select->is_part_of_union() && // 1
|
!child_select->is_part_of_union() && // 1
|
||||||
parent_unit->first_select()->leaf_tables.elements && // 2
|
parent_unit->first_select()->leaf_tables.elements && // 2
|
||||||
(thd->lex->sql_command == SQLCOM_SELECT || // *
|
child_select->outer_select()->leaf_tables.elements && // 2A
|
||||||
thd->lex->sql_command == SQLCOM_CREATE_TABLE) && // *
|
|
||||||
child_select->outer_select()->leaf_tables.elements && // 2A
|
|
||||||
subquery_types_allow_materialization(in_subs) &&
|
subquery_types_allow_materialization(in_subs) &&
|
||||||
(in_subs->is_top_level_item() || //3
|
(in_subs->is_top_level_item() || //3
|
||||||
optimizer_flag(thd,
|
optimizer_flag(thd,
|
||||||
|
@@ -640,7 +640,7 @@ handle_rpl_parallel_thread(void *arg)
|
|||||||
}
|
}
|
||||||
DBUG_ASSERT(qev->typ==rpl_parallel_thread::queued_event::QUEUED_EVENT);
|
DBUG_ASSERT(qev->typ==rpl_parallel_thread::queued_event::QUEUED_EVENT);
|
||||||
|
|
||||||
thd->rgi_slave= group_rgi= rgi;
|
thd->rgi_slave= rgi;
|
||||||
gco= rgi->gco;
|
gco= rgi->gco;
|
||||||
/* Handle a new event group, which will be initiated by a GTID event. */
|
/* Handle a new event group, which will be initiated by a GTID event. */
|
||||||
if ((event_type= qev->ev->get_type_code()) == GTID_EVENT)
|
if ((event_type= qev->ev->get_type_code()) == GTID_EVENT)
|
||||||
@@ -657,6 +657,21 @@ handle_rpl_parallel_thread(void *arg)
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if(unlikely(thd->wait_for_commit_ptr) && group_rgi != NULL)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
This indicates that we get a new GTID event in the middle of
|
||||||
|
a not completed event group. This is corrupt binlog (the master
|
||||||
|
will never write such binlog), so it does not happen unless
|
||||||
|
someone tries to inject wrong crafted binlog, but let us still
|
||||||
|
try to handle it somewhat nicely.
|
||||||
|
*/
|
||||||
|
group_rgi->cleanup_context(thd, true);
|
||||||
|
finish_event_group(rpt, group_rgi->gtid_sub_id,
|
||||||
|
group_rgi->parallel_entry, group_rgi);
|
||||||
|
rpt->loc_free_rgi(group_rgi);
|
||||||
|
}
|
||||||
|
|
||||||
in_event_group= true;
|
in_event_group= true;
|
||||||
/*
|
/*
|
||||||
If the standalone flag is set, then this event group consists of a
|
If the standalone flag is set, then this event group consists of a
|
||||||
@@ -742,19 +757,6 @@ handle_rpl_parallel_thread(void *arg)
|
|||||||
unlock_or_exit_cond(thd, &entry->LOCK_parallel_entry,
|
unlock_or_exit_cond(thd, &entry->LOCK_parallel_entry,
|
||||||
&did_enter_cond, &old_stage);
|
&did_enter_cond, &old_stage);
|
||||||
|
|
||||||
if(thd->wait_for_commit_ptr)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
This indicates that we get a new GTID event in the middle of
|
|
||||||
a not completed event group. This is corrupt binlog (the master
|
|
||||||
will never write such binlog), so it does not happen unless
|
|
||||||
someone tries to inject wrong crafted binlog, but let us still
|
|
||||||
try to handle it somewhat nicely.
|
|
||||||
*/
|
|
||||||
rgi->cleanup_context(thd, true);
|
|
||||||
thd->wait_for_commit_ptr->unregister_wait_for_prior_commit();
|
|
||||||
thd->wait_for_commit_ptr->wakeup_subsequent_commits(rgi->worker_error);
|
|
||||||
}
|
|
||||||
thd->wait_for_commit_ptr= &rgi->commit_orderer;
|
thd->wait_for_commit_ptr= &rgi->commit_orderer;
|
||||||
|
|
||||||
if (opt_gtid_ignore_duplicates)
|
if (opt_gtid_ignore_duplicates)
|
||||||
@@ -780,6 +782,7 @@ handle_rpl_parallel_thread(void *arg)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
group_rgi= rgi;
|
||||||
group_ending= is_group_ending(qev->ev, event_type);
|
group_ending= is_group_ending(qev->ev, event_type);
|
||||||
if (group_ending && likely(!rgi->worker_error))
|
if (group_ending && likely(!rgi->worker_error))
|
||||||
{
|
{
|
||||||
|
18
sql/slave.cc
18
sql/slave.cc
@@ -374,6 +374,9 @@ int init_slave()
|
|||||||
if (run_slave_init_thread())
|
if (run_slave_init_thread())
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
if (global_rpl_thread_pool.init(opt_slave_parallel_threads))
|
||||||
|
return 1;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
This is called when mysqld starts. Before client connections are
|
This is called when mysqld starts. Before client connections are
|
||||||
accepted. However bootstrap may conflict with us if it does START SLAVE.
|
accepted. However bootstrap may conflict with us if it does START SLAVE.
|
||||||
@@ -407,9 +410,6 @@ int init_slave()
|
|||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (global_rpl_thread_pool.init(opt_slave_parallel_threads))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
If --slave-skip-errors=... was not used, the string value for the
|
If --slave-skip-errors=... was not used, the string value for the
|
||||||
system variable has not been set up yet. Do it now.
|
system variable has not been set up yet. Do it now.
|
||||||
@@ -5691,6 +5691,18 @@ static int queue_event(Master_info* mi,const char* buf, ulong event_len)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
#ifndef DBUG_OFF
|
||||||
|
case XID_EVENT:
|
||||||
|
DBUG_EXECUTE_IF("slave_discard_xid_for_gtid_0_x_1000",
|
||||||
|
{
|
||||||
|
/* Inject an event group that is missing its XID commit event. */
|
||||||
|
if (mi->last_queued_gtid.domain_id == 0 &&
|
||||||
|
mi->last_queued_gtid.seq_no == 1000)
|
||||||
|
goto skip_relay_logging;
|
||||||
|
});
|
||||||
|
/* Fall through to default case ... */
|
||||||
|
#endif
|
||||||
|
|
||||||
default:
|
default:
|
||||||
default_action:
|
default_action:
|
||||||
if (mi->using_gtid != Master_info::USE_GTID_NO && mi->gtid_event_seen)
|
if (mi->using_gtid != Master_info::USE_GTID_NO && mi->gtid_event_seen)
|
||||||
|
@@ -9879,7 +9879,6 @@ bool sp_grant_privileges(THD *thd, const char *sp_db, const char *sp_name,
|
|||||||
List<LEX_USER> user_list;
|
List<LEX_USER> user_list;
|
||||||
bool result;
|
bool result;
|
||||||
ACL_USER *au;
|
ACL_USER *au;
|
||||||
char passwd_buff[SCRAMBLED_PASSWORD_CHAR_LENGTH+1];
|
|
||||||
Dummy_error_handler error_handler;
|
Dummy_error_handler error_handler;
|
||||||
DBUG_ENTER("sp_grant_privileges");
|
DBUG_ENTER("sp_grant_privileges");
|
||||||
|
|
||||||
@@ -9920,33 +9919,10 @@ bool sp_grant_privileges(THD *thd, const char *sp_db, const char *sp_name,
|
|||||||
|
|
||||||
if(au)
|
if(au)
|
||||||
{
|
{
|
||||||
if (au->salt_len)
|
|
||||||
{
|
|
||||||
if (au->salt_len == SCRAMBLE_LENGTH)
|
|
||||||
{
|
|
||||||
make_password_from_salt(passwd_buff, au->salt);
|
|
||||||
combo->password.length= SCRAMBLED_PASSWORD_CHAR_LENGTH;
|
|
||||||
}
|
|
||||||
else if (au->salt_len == SCRAMBLE_LENGTH_323)
|
|
||||||
{
|
|
||||||
make_password_from_salt_323(passwd_buff, (ulong *) au->salt);
|
|
||||||
combo->password.length= SCRAMBLED_PASSWORD_CHAR_LENGTH_323;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, ER_PASSWD_LENGTH,
|
|
||||||
ER(ER_PASSWD_LENGTH), SCRAMBLED_PASSWORD_CHAR_LENGTH);
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
combo->password.str= passwd_buff;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (au->plugin.str != native_password_plugin_name.str &&
|
if (au->plugin.str != native_password_plugin_name.str &&
|
||||||
au->plugin.str != old_password_plugin_name.str)
|
au->plugin.str != old_password_plugin_name.str)
|
||||||
{
|
|
||||||
combo->plugin= au->plugin;
|
combo->plugin= au->plugin;
|
||||||
combo->auth= au->auth_string;
|
combo->auth= au->auth_string;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (user_list.push_back(combo))
|
if (user_list.push_back(combo))
|
||||||
|
@@ -2499,11 +2499,15 @@ mysql_execute_command(THD *thd)
|
|||||||
according to slave filtering rules.
|
according to slave filtering rules.
|
||||||
Returning success without producing any errors in this case.
|
Returning success without producing any errors in this case.
|
||||||
*/
|
*/
|
||||||
DBUG_RETURN(0);
|
if (!thd->lex->check_exists)
|
||||||
|
DBUG_RETURN(0);
|
||||||
|
/*
|
||||||
|
DROP TRIGGER IF NOT EXISTS will return without an error later
|
||||||
|
after possibly writing the query to a binlog
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
else // force searching in slave.cc:tables_ok()
|
||||||
// force searching in slave.cc:tables_ok()
|
all_tables->updating= 1;
|
||||||
all_tables->updating= 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@@ -1948,6 +1948,7 @@ void mysql_binlog_send(THD* thd, char* log_ident, my_off_t pos,
|
|||||||
slave_connection_state until_gtid_state_obj;
|
slave_connection_state until_gtid_state_obj;
|
||||||
rpl_gtid error_gtid;
|
rpl_gtid error_gtid;
|
||||||
binlog_send_info info(thd, packet, flags, log_file_name);
|
binlog_send_info info(thd, packet, flags, log_file_name);
|
||||||
|
bool has_transmit_started= false;
|
||||||
|
|
||||||
int old_max_allowed_packet= thd->variables.max_allowed_packet;
|
int old_max_allowed_packet= thd->variables.max_allowed_packet;
|
||||||
|
|
||||||
@@ -2007,16 +2008,6 @@ void mysql_binlog_send(THD* thd, char* log_ident, my_off_t pos,
|
|||||||
DBUG_SET("+d,corrupt_read_log_event2");
|
DBUG_SET("+d,corrupt_read_log_event2");
|
||||||
});
|
});
|
||||||
|
|
||||||
if (global_system_variables.log_warnings > 1)
|
|
||||||
sql_print_information("Start binlog_dump to slave_server(%lu), pos(%s, %lu)",
|
|
||||||
thd->variables.server_id, log_ident, (ulong)pos);
|
|
||||||
if (RUN_HOOK(binlog_transmit, transmit_start, (thd, flags, log_ident, pos)))
|
|
||||||
{
|
|
||||||
errmsg= "Failed to run hook 'transmit_start'";
|
|
||||||
my_errno= ER_UNKNOWN_ERROR;
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef DBUG_OFF
|
#ifndef DBUG_OFF
|
||||||
if (opt_sporadic_binlog_dump_fail && (binlog_dump_count++ % 2))
|
if (opt_sporadic_binlog_dump_fail && (binlog_dump_count++ % 2))
|
||||||
{
|
{
|
||||||
@@ -2113,6 +2104,17 @@ impossible position";
|
|||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (global_system_variables.log_warnings > 1)
|
||||||
|
sql_print_information("Start binlog_dump to slave_server(%lu), pos(%s, %lu)",
|
||||||
|
thd->variables.server_id, log_ident, (ulong)pos);
|
||||||
|
if (RUN_HOOK(binlog_transmit, transmit_start, (thd, flags, log_ident, pos)))
|
||||||
|
{
|
||||||
|
errmsg= "Failed to run hook 'transmit_start'";
|
||||||
|
my_errno= ER_UNKNOWN_ERROR;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
has_transmit_started= true;
|
||||||
|
|
||||||
/* reset transmit packet for the fake rotate event below */
|
/* reset transmit packet for the fake rotate event below */
|
||||||
if (reset_transmit_packet(thd, flags, &ev_offset, &errmsg))
|
if (reset_transmit_packet(thd, flags, &ev_offset, &errmsg))
|
||||||
goto err;
|
goto err;
|
||||||
@@ -2680,7 +2682,8 @@ end:
|
|||||||
end_io_cache(&log);
|
end_io_cache(&log);
|
||||||
mysql_file_close(file, MYF(MY_WME));
|
mysql_file_close(file, MYF(MY_WME));
|
||||||
|
|
||||||
RUN_HOOK(binlog_transmit, transmit_stop, (thd, flags));
|
if (has_transmit_started)
|
||||||
|
RUN_HOOK(binlog_transmit, transmit_stop, (thd, flags));
|
||||||
my_eof(thd);
|
my_eof(thd);
|
||||||
THD_STAGE_INFO(thd, stage_waiting_to_finalize_termination);
|
THD_STAGE_INFO(thd, stage_waiting_to_finalize_termination);
|
||||||
mysql_mutex_lock(&LOCK_thread_count);
|
mysql_mutex_lock(&LOCK_thread_count);
|
||||||
@@ -2749,7 +2752,8 @@ err:
|
|||||||
else
|
else
|
||||||
strcpy(error_text, errmsg);
|
strcpy(error_text, errmsg);
|
||||||
end_io_cache(&log);
|
end_io_cache(&log);
|
||||||
RUN_HOOK(binlog_transmit, transmit_stop, (thd, flags));
|
if (has_transmit_started)
|
||||||
|
RUN_HOOK(binlog_transmit, transmit_stop, (thd, flags));
|
||||||
/*
|
/*
|
||||||
Exclude iteration through thread list
|
Exclude iteration through thread list
|
||||||
this is needed for purge_logs() - it will iterate through
|
this is needed for purge_logs() - it will iterate through
|
||||||
|
@@ -4958,7 +4958,18 @@ add_key_part(DYNAMIC_ARRAY *keyuse_array, KEY_FIELD *key_field)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#define FT_KEYPART (MAX_REF_PARTS+10)
|
/*
|
||||||
|
A key part number that means we're using a fulltext scan.
|
||||||
|
|
||||||
|
In order not to confuse it with regular equalities, we need to pick
|
||||||
|
a number that's greater than MAX_REF_PARTS.
|
||||||
|
|
||||||
|
Hash Join code stores field->field_index in KEYUSE::keypart, so the
|
||||||
|
number needs to be bigger than MAX_FIELDS, also.
|
||||||
|
|
||||||
|
CAUTION: sql_test.cc has its own definition of FT_KEYPART.
|
||||||
|
*/
|
||||||
|
#define FT_KEYPART (MAX_FIELDS+10)
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
add_ft_keys(DYNAMIC_ARRAY *keyuse_array,
|
add_ft_keys(DYNAMIC_ARRAY *keyuse_array,
|
||||||
@@ -7452,7 +7463,11 @@ double table_cond_selectivity(JOIN *join, uint idx, JOIN_TAB *s,
|
|||||||
fldno= table->key_info[key].key_part[keyparts-1].fieldnr - 1;
|
fldno= table->key_info[key].key_part[keyparts-1].fieldnr - 1;
|
||||||
if (keyuse->val->const_item())
|
if (keyuse->val->const_item())
|
||||||
{
|
{
|
||||||
sel /= table->field[fldno]->cond_selectivity;
|
if (table->field[fldno]->cond_selectivity > 0)
|
||||||
|
{
|
||||||
|
sel /= table->field[fldno]->cond_selectivity;
|
||||||
|
set_if_smaller(sel, 1.0);
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
TODO: we could do better here:
|
TODO: we could do better here:
|
||||||
1. cond_selectivity might be =1 (the default) because quick
|
1. cond_selectivity might be =1 (the default) because quick
|
||||||
@@ -7506,7 +7521,10 @@ double table_cond_selectivity(JOIN *join, uint idx, JOIN_TAB *s,
|
|||||||
if (!(next_field->table->map & rem_tables) && next_field->table != table)
|
if (!(next_field->table->map & rem_tables) && next_field->table != table)
|
||||||
{
|
{
|
||||||
if (field->cond_selectivity > 0)
|
if (field->cond_selectivity > 0)
|
||||||
|
{
|
||||||
sel/= field->cond_selectivity;
|
sel/= field->cond_selectivity;
|
||||||
|
set_if_smaller(sel, 1.0);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -220,7 +220,7 @@ TEST_join(JOIN *join)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#define FT_KEYPART (MAX_REF_PARTS+10)
|
#define FT_KEYPART (MAX_FIELDS+10)
|
||||||
|
|
||||||
void print_keyuse(KEYUSE *keyuse)
|
void print_keyuse(KEYUSE *keyuse)
|
||||||
{
|
{
|
||||||
|
@@ -13404,7 +13404,12 @@ literal:
|
|||||||
| UNDERSCORE_CHARSET hex_or_bin_String
|
| UNDERSCORE_CHARSET hex_or_bin_String
|
||||||
{
|
{
|
||||||
Item_string_with_introducer *item_str;
|
Item_string_with_introducer *item_str;
|
||||||
item_str= new (thd->mem_root) Item_string_with_introducer($2, $1);
|
/*
|
||||||
|
Pass NULL as name. Name will be set in the "select_item" rule and
|
||||||
|
will include the introducer and the original hex/bin notation.
|
||||||
|
*/
|
||||||
|
item_str= new (thd->mem_root)
|
||||||
|
Item_string_with_introducer(NULL, $2->ptr(), $2->length(), $1);
|
||||||
if (!item_str || !item_str->check_well_formed_result(true))
|
if (!item_str || !item_str->check_well_formed_result(true))
|
||||||
MYSQL_YYABORT;
|
MYSQL_YYABORT;
|
||||||
|
|
||||||
|
@@ -21,9 +21,9 @@ ha_connect.cc connect.cc user_connect.cc mycat.cc
|
|||||||
fmdlex.c osutil.c plugutil.c rcmsg.c rcmsg.h
|
fmdlex.c osutil.c plugutil.c rcmsg.c rcmsg.h
|
||||||
array.cpp blkfil.cpp colblk.cpp csort.cpp
|
array.cpp blkfil.cpp colblk.cpp csort.cpp
|
||||||
filamap.cpp filamdbf.cpp filamfix.cpp filamtxt.cpp filamvct.cpp filamzip.cpp
|
filamap.cpp filamdbf.cpp filamfix.cpp filamtxt.cpp filamvct.cpp filamzip.cpp
|
||||||
filter.cpp json.cpp maputil.cpp myutil.cpp plgdbutl.cpp reldef.cpp tabcol.cpp
|
filter.cpp json.cpp jsonudf.cpp maputil.cpp myutil.cpp plgdbutl.cpp reldef.cpp
|
||||||
tabdos.cpp tabfix.cpp tabfmt.cpp tabjson.cpp table.cpp tabmul.cpp taboccur.cpp
|
tabcol.cpp tabdos.cpp tabfix.cpp tabfmt.cpp tabjson.cpp table.cpp tabmul.cpp
|
||||||
tabpivot.cpp tabsys.cpp tabtbl.cpp tabutil.cpp tabvct.cpp tabvir.cpp
|
taboccur.cpp tabpivot.cpp tabsys.cpp tabtbl.cpp tabutil.cpp tabvct.cpp tabvir.cpp
|
||||||
tabxcl.cpp valblk.cpp value.cpp xindex.cpp xobject.cpp
|
tabxcl.cpp valblk.cpp value.cpp xindex.cpp xobject.cpp
|
||||||
|
|
||||||
array.h blkfil.h block.h catalog.h checklvl.h colblk.h connect.h csort.h
|
array.h blkfil.h block.h catalog.h checklvl.h colblk.h connect.h csort.h
|
||||||
|
@@ -50,6 +50,7 @@ class DllExport ARRAY : public XOBJECT, public CSORT { // Array descblock
|
|||||||
// void SetCorrel(bool b) {Correlated = b;}
|
// void SetCorrel(bool b) {Correlated = b;}
|
||||||
|
|
||||||
// Methods
|
// Methods
|
||||||
|
using XOBJECT::GetIntValue;
|
||||||
virtual void Reset(void) {Bot = -1;}
|
virtual void Reset(void) {Bot = -1;}
|
||||||
virtual int Qcompare(int *, int *);
|
virtual int Qcompare(int *, int *);
|
||||||
virtual bool Compare(PXOB) {assert(FALSE); return FALSE;}
|
virtual bool Compare(PXOB) {assert(FALSE); return FALSE;}
|
||||||
|
@@ -40,4 +40,11 @@ enum USETEMP {TMP_NO = 0, /* Never */
|
|||||||
TMP_FORCE = 3, /* Forced for MAP tables */
|
TMP_FORCE = 3, /* Forced for MAP tables */
|
||||||
TMP_TEST = 4}; /* Testing value */
|
TMP_TEST = 4}; /* Testing value */
|
||||||
|
|
||||||
|
/***********************************************************************/
|
||||||
|
/* Following definitions indicate conversion of TEXT columns. */
|
||||||
|
/***********************************************************************/
|
||||||
|
enum TYPCONV {TPC_NO = 0, /* Never */
|
||||||
|
TPC_YES = 1, /* Always */
|
||||||
|
TPC_SKIP = 2}; /* Skip TEXT columns */
|
||||||
|
|
||||||
#endif // _CHKLVL_DEFINED_
|
#endif // _CHKLVL_DEFINED_
|
||||||
|
@@ -469,9 +469,12 @@ RCODE CntReadNext(PGLOBAL g, PTDB tdbp)
|
|||||||
|
|
||||||
} while (rc == RC_NF);
|
} while (rc == RC_NF);
|
||||||
|
|
||||||
|
if (rc == RC_OK)
|
||||||
|
rc= EvalColumns(g, tdbp, false);
|
||||||
|
|
||||||
err:
|
err:
|
||||||
g->jump_level--;
|
g->jump_level--;
|
||||||
return (rc != RC_OK) ? rc : EvalColumns(g, tdbp, false);
|
return rc;
|
||||||
} // end of CntReadNext
|
} // end of CntReadNext
|
||||||
|
|
||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
|
@@ -235,7 +235,7 @@ typedef struct _global { /* Global structure */
|
|||||||
void *Xchk; /* indexes in create/alter */
|
void *Xchk; /* indexes in create/alter */
|
||||||
short Alchecked; /* Checked for ALTER */
|
short Alchecked; /* Checked for ALTER */
|
||||||
short Mrr; /* True when doing mrr */
|
short Mrr; /* True when doing mrr */
|
||||||
short Trace;
|
int N; /* Utility */
|
||||||
int jump_level;
|
int jump_level;
|
||||||
jmp_buf jumper[MAX_JUMP + 2];
|
jmp_buf jumper[MAX_JUMP + 2];
|
||||||
} GLOBAL;
|
} GLOBAL;
|
||||||
|
@@ -165,23 +165,24 @@
|
|||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
/* Initialize the ha_connect static members. */
|
/* Initialize the ha_connect static members. */
|
||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
#define SZCONV 8192
|
#define SZCONV 8192
|
||||||
#define SZWORK 67108864 // Default work area size 64M
|
#define SZWORK 67108864 // Default work area size 64M
|
||||||
#define SZWMIN 4194304 // Minimum work area size 4M
|
#define SZWMIN 4194304 // Minimum work area size 4M
|
||||||
|
#define JSONMAX 10 // JSON Default max grp size
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
char version[]= "Version 1.03.0006 January 13, 2015";
|
char version[]= "Version 1.03.0006 February 06, 2015";
|
||||||
char compver[]= "Version 1.03.0006 " __DATE__ " " __TIME__;
|
|
||||||
|
|
||||||
#if defined(WIN32)
|
#if defined(WIN32)
|
||||||
|
char compver[]= "Version 1.03.0006 " __DATE__ " " __TIME__;
|
||||||
char slash= '\\';
|
char slash= '\\';
|
||||||
#else // !WIN32
|
#else // !WIN32
|
||||||
char slash= '/';
|
char slash= '/';
|
||||||
#endif // !WIN32
|
#endif // !WIN32
|
||||||
|
|
||||||
// int trace= 0; // The general trace value
|
// int trace= 0; // The general trace value
|
||||||
ulong xconv= 0; // The type conversion option
|
// ulong xconv= 0; // The type conversion option
|
||||||
int zconv= 0; // The text conversion size
|
// int zconv= 0; // The text conversion size
|
||||||
} // extern "C"
|
} // extern "C"
|
||||||
|
|
||||||
#if defined(XMAP)
|
#if defined(XMAP)
|
||||||
@@ -215,6 +216,9 @@ bool CheckSelf(PGLOBAL g, TABLE_SHARE *s, const char *host,
|
|||||||
const char *db, char *tab, const char *src, int port);
|
const char *db, char *tab, const char *src, int port);
|
||||||
bool ExactInfo(void);
|
bool ExactInfo(void);
|
||||||
USETEMP UseTemp(void);
|
USETEMP UseTemp(void);
|
||||||
|
int GetConvSize(void);
|
||||||
|
TYPCONV GetTypeConv(void);
|
||||||
|
uint GetJsonGrpSize(void);
|
||||||
uint GetWorkSize(void);
|
uint GetWorkSize(void);
|
||||||
void SetWorkSize(uint);
|
void SetWorkSize(uint);
|
||||||
extern "C" const char *msglang(void);
|
extern "C" const char *msglang(void);
|
||||||
@@ -289,6 +293,44 @@ static MYSQL_THDVAR_UINT(work_size,
|
|||||||
"Size of the CONNECT work area.",
|
"Size of the CONNECT work area.",
|
||||||
NULL, NULL, SZWORK, SZWMIN, UINT_MAX, 1);
|
NULL, NULL, SZWORK, SZWMIN, UINT_MAX, 1);
|
||||||
|
|
||||||
|
// Size used when converting TEXT columns to VARCHAR
|
||||||
|
static MYSQL_THDVAR_INT(conv_size,
|
||||||
|
PLUGIN_VAR_RQCMDARG, // opt
|
||||||
|
"Size used when converting TEXT columns.",
|
||||||
|
NULL, NULL, SZCONV, 0, 65500, 1);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Type conversion:
|
||||||
|
no: Unsupported types -> TYPE_ERROR
|
||||||
|
yes: TEXT -> VARCHAR
|
||||||
|
skip: skip unsupported type columns in Discovery
|
||||||
|
*/
|
||||||
|
const char *xconv_names[]=
|
||||||
|
{
|
||||||
|
"NO", "YES", "SKIP", NullS
|
||||||
|
};
|
||||||
|
|
||||||
|
TYPELIB xconv_typelib=
|
||||||
|
{
|
||||||
|
array_elements(xconv_names) - 1, "xconv_typelib",
|
||||||
|
xconv_names, NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
static MYSQL_THDVAR_ENUM(
|
||||||
|
type_conv, // name
|
||||||
|
PLUGIN_VAR_RQCMDARG, // opt
|
||||||
|
"Unsupported types conversion.", // comment
|
||||||
|
NULL, // check
|
||||||
|
NULL, // update function
|
||||||
|
0, // def (no)
|
||||||
|
&xconv_typelib); // typelib
|
||||||
|
|
||||||
|
// Estimate max number of rows for JSON aggregate functions
|
||||||
|
static MYSQL_THDVAR_UINT(json_grp_size,
|
||||||
|
PLUGIN_VAR_RQCMDARG, // opt
|
||||||
|
"max number of rows for JSON aggregate functions.",
|
||||||
|
NULL, NULL, JSONMAX, 1, INT_MAX, 1);
|
||||||
|
|
||||||
#if defined(XMSG) || defined(NEWMSG)
|
#if defined(XMSG) || defined(NEWMSG)
|
||||||
const char *language_names[]=
|
const char *language_names[]=
|
||||||
{
|
{
|
||||||
@@ -317,6 +359,9 @@ static MYSQL_THDVAR_ENUM(
|
|||||||
extern "C" int GetTraceValue(void) {return THDVAR(current_thd, xtrace);}
|
extern "C" int GetTraceValue(void) {return THDVAR(current_thd, xtrace);}
|
||||||
bool ExactInfo(void) {return THDVAR(current_thd, exact_info);}
|
bool ExactInfo(void) {return THDVAR(current_thd, exact_info);}
|
||||||
USETEMP UseTemp(void) {return (USETEMP)THDVAR(current_thd, use_tempfile);}
|
USETEMP UseTemp(void) {return (USETEMP)THDVAR(current_thd, use_tempfile);}
|
||||||
|
int GetConvSize(void) {return THDVAR(current_thd, conv_size);}
|
||||||
|
TYPCONV GetTypeConv(void) {return (TYPCONV)THDVAR(current_thd, type_conv);}
|
||||||
|
uint GetJsonGrpSize(void) {return THDVAR(current_thd, json_grp_size);}
|
||||||
uint GetWorkSize(void) {return THDVAR(current_thd, work_size);}
|
uint GetWorkSize(void) {return THDVAR(current_thd, work_size);}
|
||||||
void SetWorkSize(uint n)
|
void SetWorkSize(uint n)
|
||||||
{
|
{
|
||||||
@@ -598,7 +643,11 @@ static int connect_init_func(void *p)
|
|||||||
}
|
}
|
||||||
#endif // 0 (LINUX)
|
#endif // 0 (LINUX)
|
||||||
|
|
||||||
|
#if defined(WIN32)
|
||||||
sql_print_information("CONNECT: %s", compver);
|
sql_print_information("CONNECT: %s", compver);
|
||||||
|
#else // !WIN32
|
||||||
|
sql_print_information("CONNECT: %s", version);
|
||||||
|
#endif // !WIN32
|
||||||
|
|
||||||
#ifdef LIBXML2_SUPPORT
|
#ifdef LIBXML2_SUPPORT
|
||||||
XmlInitParserLib();
|
XmlInitParserLib();
|
||||||
@@ -934,6 +983,9 @@ ulonglong ha_connect::table_flags() const
|
|||||||
char *GetListOption(PGLOBAL g, const char *opname,
|
char *GetListOption(PGLOBAL g, const char *opname,
|
||||||
const char *oplist, const char *def)
|
const char *oplist, const char *def)
|
||||||
{
|
{
|
||||||
|
if (!oplist)
|
||||||
|
return (char*)def;
|
||||||
|
|
||||||
char key[16], val[256];
|
char key[16], val[256];
|
||||||
char *pk, *pv, *pn;
|
char *pk, *pv, *pn;
|
||||||
char *opval= (char*) def;
|
char *opval= (char*) def;
|
||||||
@@ -997,8 +1049,12 @@ char *ha_connect::GetRealString(const char *s)
|
|||||||
char *sv;
|
char *sv;
|
||||||
|
|
||||||
if (IsPartitioned() && s) {
|
if (IsPartitioned() && s) {
|
||||||
sv= (char*)PlugSubAlloc(xp->g, NULL, strlen(s) + strlen(partname));
|
// sv= (char*)PlugSubAlloc(xp->g, NULL, strlen(s) + strlen(partname));
|
||||||
|
// With wrong string pattern, the size of the constructed string
|
||||||
|
// can be more than strlen(s) + strlen(partname)
|
||||||
|
sv= (char*)PlugSubAlloc(xp->g, NULL, 0);
|
||||||
sprintf(sv, s, partname);
|
sprintf(sv, s, partname);
|
||||||
|
PlugSubAlloc(xp->g, NULL, strlen(sv) + 1);
|
||||||
} else
|
} else
|
||||||
sv= (char*)s;
|
sv= (char*)s;
|
||||||
|
|
||||||
@@ -1064,9 +1120,16 @@ char *ha_connect::GetStringOption(char *opname, char *sdef)
|
|||||||
|
|
||||||
} // endif Table_charset
|
} // endif Table_charset
|
||||||
|
|
||||||
if (!opval && options && options->oplist)
|
if (!opval && options && options->oplist) {
|
||||||
opval= GetListOption(xp->g, opname, options->oplist);
|
opval= GetListOption(xp->g, opname, options->oplist);
|
||||||
|
|
||||||
|
if (opval && (!stricmp(opname, "connect")
|
||||||
|
|| !stricmp(opname, "tabname")
|
||||||
|
|| !stricmp(opname, "filename")))
|
||||||
|
opval = GetRealString(opval);
|
||||||
|
|
||||||
|
} // endif opval
|
||||||
|
|
||||||
if (!opval) {
|
if (!opval) {
|
||||||
if (sdef && !strcmp(sdef, "*")) {
|
if (sdef && !strcmp(sdef, "*")) {
|
||||||
// Return the handler default value
|
// Return the handler default value
|
||||||
@@ -2467,6 +2530,8 @@ PCFIL ha_connect::CheckCond(PGLOBAL g, PCFIL filp, AMT tty, Item *cond)
|
|||||||
char *body= filp->Body;
|
char *body= filp->Body;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
bool ismul= false, x= (tty == TYPE_AM_MYX || tty == TYPE_AM_XDBC);
|
bool ismul= false, x= (tty == TYPE_AM_MYX || tty == TYPE_AM_XDBC);
|
||||||
|
bool nonul= (tty == TYPE_AM_ODBC && (tdbp->GetMode() == MODE_INSERT ||
|
||||||
|
tdbp->GetMode() == MODE_DELETE));
|
||||||
OPVAL vop= OP_XX;
|
OPVAL vop= OP_XX;
|
||||||
|
|
||||||
if (!cond)
|
if (!cond)
|
||||||
@@ -2484,7 +2549,7 @@ PCFIL ha_connect::CheckCond(PGLOBAL g, PCFIL filp, AMT tty, Item *cond)
|
|||||||
|
|
||||||
if (trace)
|
if (trace)
|
||||||
htrc("Cond: Ftype=%d name=%s\n", cond_item->functype(),
|
htrc("Cond: Ftype=%d name=%s\n", cond_item->functype(),
|
||||||
cond_item->func_name());
|
cond_item->func_name());
|
||||||
|
|
||||||
switch (cond_item->functype()) {
|
switch (cond_item->functype()) {
|
||||||
case Item_func::COND_AND_FUNC: vop= OP_AND; break;
|
case Item_func::COND_AND_FUNC: vop= OP_AND; break;
|
||||||
@@ -2503,7 +2568,7 @@ PCFIL ha_connect::CheckCond(PGLOBAL g, PCFIL filp, AMT tty, Item *cond)
|
|||||||
for (i= 0; i < arglist->elements; i++)
|
for (i= 0; i < arglist->elements; i++)
|
||||||
if ((subitem= li++)) {
|
if ((subitem= li++)) {
|
||||||
if (!CheckCond(g, filp, tty, subitem)) {
|
if (!CheckCond(g, filp, tty, subitem)) {
|
||||||
if (vop == OP_OR)
|
if (vop == OP_OR || nonul)
|
||||||
return NULL;
|
return NULL;
|
||||||
else
|
else
|
||||||
*p2= 0;
|
*p2= 0;
|
||||||
@@ -2599,6 +2664,8 @@ PCFIL ha_connect::CheckCond(PGLOBAL g, PCFIL filp, AMT tty, Item *cond)
|
|||||||
if (trace) {
|
if (trace) {
|
||||||
htrc("Field index=%d\n", pField->field->field_index);
|
htrc("Field index=%d\n", pField->field->field_index);
|
||||||
htrc("Field name=%s\n", pField->field->field_name);
|
htrc("Field name=%s\n", pField->field->field_name);
|
||||||
|
htrc("Field type=%d\n", pField->field->type());
|
||||||
|
htrc("Field_type=%d\n", args[i]->field_type());
|
||||||
} // endif trace
|
} // endif trace
|
||||||
|
|
||||||
// IN and BETWEEN clauses should be col VOP list
|
// IN and BETWEEN clauses should be col VOP list
|
||||||
@@ -2618,8 +2685,9 @@ PCFIL ha_connect::CheckCond(PGLOBAL g, PCFIL filp, AMT tty, Item *cond)
|
|||||||
char buff[256];
|
char buff[256];
|
||||||
String *res, tmp(buff, sizeof(buff), &my_charset_bin);
|
String *res, tmp(buff, sizeof(buff), &my_charset_bin);
|
||||||
Item_basic_constant *pval= (Item_basic_constant *)args[i];
|
Item_basic_constant *pval= (Item_basic_constant *)args[i];
|
||||||
|
Item::Type type= args[i]->real_type();
|
||||||
|
|
||||||
switch (args[i]->real_type()) {
|
switch (type) {
|
||||||
case COND::STRING_ITEM:
|
case COND::STRING_ITEM:
|
||||||
case COND::INT_ITEM:
|
case COND::INT_ITEM:
|
||||||
case COND::REAL_ITEM:
|
case COND::REAL_ITEM:
|
||||||
@@ -2644,10 +2712,64 @@ PCFIL ha_connect::CheckCond(PGLOBAL g, PCFIL filp, AMT tty, Item *cond)
|
|||||||
|
|
||||||
if (!x) {
|
if (!x) {
|
||||||
// Append the value to the filter
|
// Append the value to the filter
|
||||||
if (args[i]->field_type() == MYSQL_TYPE_VARCHAR)
|
switch (args[i]->field_type()) {
|
||||||
strcat(strncat(strcat(body, "'"), res->ptr(), res->length()), "'");
|
case MYSQL_TYPE_TIMESTAMP:
|
||||||
else
|
case MYSQL_TYPE_DATETIME:
|
||||||
strncat(body, res->ptr(), res->length());
|
if (tty == TYPE_AM_ODBC) {
|
||||||
|
strcat(body, "{ts '");
|
||||||
|
strcat(strncat(body, res->ptr(), res->length()), "'}");
|
||||||
|
break;
|
||||||
|
} // endif ODBC
|
||||||
|
|
||||||
|
case MYSQL_TYPE_DATE:
|
||||||
|
if (tty == TYPE_AM_ODBC) {
|
||||||
|
strcat(body, "{d '");
|
||||||
|
strcat(strncat(body, res->ptr(), res->length()), "'}");
|
||||||
|
break;
|
||||||
|
} // endif ODBC
|
||||||
|
|
||||||
|
case MYSQL_TYPE_TIME:
|
||||||
|
if (tty == TYPE_AM_ODBC) {
|
||||||
|
strcat(body, "{t '");
|
||||||
|
strcat(strncat(body, res->ptr(), res->length()), "'}");
|
||||||
|
break;
|
||||||
|
} // endif ODBC
|
||||||
|
|
||||||
|
case MYSQL_TYPE_VARCHAR:
|
||||||
|
if (tty == TYPE_AM_ODBC && i) {
|
||||||
|
switch (args[0]->field_type()) {
|
||||||
|
case MYSQL_TYPE_TIMESTAMP:
|
||||||
|
case MYSQL_TYPE_DATETIME:
|
||||||
|
strcat(body, "{ts '");
|
||||||
|
strncat(body, res->ptr(), res->length());
|
||||||
|
strcat(body, "'}");
|
||||||
|
break;
|
||||||
|
case MYSQL_TYPE_DATE:
|
||||||
|
strcat(body, "{d '");
|
||||||
|
strncat(body, res->ptr(), res->length());
|
||||||
|
strcat(body, "'}");
|
||||||
|
break;
|
||||||
|
case MYSQL_TYPE_TIME:
|
||||||
|
strcat(body, "{t '");
|
||||||
|
strncat(body, res->ptr(), res->length());
|
||||||
|
strcat(body, "'}");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
strcat(body, "'");
|
||||||
|
strncat(body, res->ptr(), res->length());
|
||||||
|
strcat(body, "'");
|
||||||
|
} // endswitch field type
|
||||||
|
|
||||||
|
} else {
|
||||||
|
strcat(body, "'");
|
||||||
|
strncat(body, res->ptr(), res->length());
|
||||||
|
strcat(body, "'");
|
||||||
|
} // endif tty
|
||||||
|
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
strncat(body, res->ptr(), res->length());
|
||||||
|
} // endswitch field type
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if (args[i]->field_type() == MYSQL_TYPE_VARCHAR) {
|
if (args[i]->field_type() == MYSQL_TYPE_VARCHAR) {
|
||||||
@@ -2753,7 +2875,7 @@ const COND *ha_connect::cond_push(const COND *cond)
|
|||||||
} else if (x && cond)
|
} else if (x && cond)
|
||||||
tdbp->SetCondFil(filp); // Wrong filter
|
tdbp->SetCondFil(filp); // Wrong filter
|
||||||
|
|
||||||
} else
|
} else if (tty != TYPE_AM_JSN && tty != TYPE_AM_JSON)
|
||||||
tdbp->SetFilter(CondFilter(g, (Item *)cond));
|
tdbp->SetFilter(CondFilter(g, (Item *)cond));
|
||||||
|
|
||||||
fin:
|
fin:
|
||||||
@@ -4620,7 +4742,7 @@ static bool add_field(String *sql, const char *field_name, int typ,
|
|||||||
char *dft, char *xtra, int flag, bool dbf, char v)
|
char *dft, char *xtra, int flag, bool dbf, char v)
|
||||||
{
|
{
|
||||||
char var = (len > 255) ? 'V' : v;
|
char var = (len > 255) ? 'V' : v;
|
||||||
bool error= false;
|
bool q, error= false;
|
||||||
const char *type= PLGtoMYSQLtype(typ, dbf, var);
|
const char *type= PLGtoMYSQLtype(typ, dbf, var);
|
||||||
|
|
||||||
error|= sql->append('`');
|
error|= sql->append('`');
|
||||||
@@ -4661,7 +4783,12 @@ static bool add_field(String *sql, const char *field_name, int typ,
|
|||||||
if (dft && *dft) {
|
if (dft && *dft) {
|
||||||
error|= sql->append(" DEFAULT ");
|
error|= sql->append(" DEFAULT ");
|
||||||
|
|
||||||
if (!IsTypeNum(typ)) {
|
if (typ == TYPE_DATE)
|
||||||
|
q = (strspn(dft, "0123456789 -:/") == strlen(dft));
|
||||||
|
else
|
||||||
|
q = !IsTypeNum(typ);
|
||||||
|
|
||||||
|
if (q) {
|
||||||
error|= sql->append("'");
|
error|= sql->append("'");
|
||||||
error|= sql->append_for_single_quote(dft, strlen(dft));
|
error|= sql->append_for_single_quote(dft, strlen(dft));
|
||||||
error|= sql->append("'");
|
error|= sql->append("'");
|
||||||
@@ -4831,6 +4958,9 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
|
|||||||
int port= 0, hdr= 0, mxr __attribute__((unused))= 0, mxe= 0, rc= 0;
|
int port= 0, hdr= 0, mxr __attribute__((unused))= 0, mxe= 0, rc= 0;
|
||||||
int cop __attribute__((unused)) = 0;
|
int cop __attribute__((unused)) = 0;
|
||||||
#if defined(ODBC_SUPPORT)
|
#if defined(ODBC_SUPPORT)
|
||||||
|
POPARM sop = NULL;
|
||||||
|
char *ucnc = NULL;
|
||||||
|
bool cnc= false;
|
||||||
int cto= -1, qto= -1;
|
int cto= -1, qto= -1;
|
||||||
#endif // ODBC_SUPPORT
|
#endif // ODBC_SUPPORT
|
||||||
uint tm, fnc= FNC_NO, supfnc= (FNC_NO | FNC_COL);
|
uint tm, fnc= FNC_NO, supfnc= (FNC_NO | FNC_COL);
|
||||||
@@ -4875,7 +5005,8 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
|
|||||||
|
|
||||||
if (topt->oplist) {
|
if (topt->oplist) {
|
||||||
host= GetListOption(g, "host", topt->oplist, "localhost");
|
host= GetListOption(g, "host", topt->oplist, "localhost");
|
||||||
user= GetListOption(g, "user", topt->oplist, "root");
|
user= GetListOption(g, "user", topt->oplist,
|
||||||
|
(ttp == TAB_ODBC ? NULL : "root"));
|
||||||
// Default value db can come from the DBNAME=xxx option.
|
// Default value db can come from the DBNAME=xxx option.
|
||||||
db= GetListOption(g, "database", topt->oplist, db);
|
db= GetListOption(g, "database", topt->oplist, db);
|
||||||
col= GetListOption(g, "colist", topt->oplist, col);
|
col= GetListOption(g, "colist", topt->oplist, col);
|
||||||
@@ -4894,6 +5025,9 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
|
|||||||
mxr= atoi(GetListOption(g,"maxres", topt->oplist, "0"));
|
mxr= atoi(GetListOption(g,"maxres", topt->oplist, "0"));
|
||||||
cto= atoi(GetListOption(g,"ConnectTimeout", topt->oplist, "-1"));
|
cto= atoi(GetListOption(g,"ConnectTimeout", topt->oplist, "-1"));
|
||||||
qto= atoi(GetListOption(g,"QueryTimeout", topt->oplist, "-1"));
|
qto= atoi(GetListOption(g,"QueryTimeout", topt->oplist, "-1"));
|
||||||
|
|
||||||
|
if ((ucnc= GetListOption(g, "UseDSN", topt->oplist)))
|
||||||
|
cnc= (!*ucnc || *ucnc == 'y' || *ucnc == 'Y' || atoi(ucnc) != 0);
|
||||||
#endif
|
#endif
|
||||||
mxe= atoi(GetListOption(g,"maxerr", topt->oplist, "0"));
|
mxe= atoi(GetListOption(g,"maxerr", topt->oplist, "0"));
|
||||||
#if defined(PROMPT_OK)
|
#if defined(PROMPT_OK)
|
||||||
@@ -4901,7 +5035,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
|
|||||||
#endif // PROMPT_OK
|
#endif // PROMPT_OK
|
||||||
} else {
|
} else {
|
||||||
host= "localhost";
|
host= "localhost";
|
||||||
user= "root";
|
user= (ttp == TAB_ODBC ? NULL : "root");
|
||||||
} // endif option_list
|
} // endif option_list
|
||||||
|
|
||||||
if (!(shm= (char*)db))
|
if (!(shm= (char*)db))
|
||||||
@@ -4978,10 +5112,18 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
|
|||||||
} // endif dsn
|
} // endif dsn
|
||||||
#endif // PROMPT_OK
|
#endif // PROMPT_OK
|
||||||
|
|
||||||
} else if (!dsn)
|
} else if (!dsn) {
|
||||||
sprintf(g->Message, "Missing %s connection string", topt->type);
|
sprintf(g->Message, "Missing %s connection string", topt->type);
|
||||||
else
|
} else {
|
||||||
|
// Store ODBC additional parameters
|
||||||
|
sop= (POPARM)PlugSubAlloc(g, NULL, sizeof(ODBCPARM));
|
||||||
|
sop->User= (char*)user;
|
||||||
|
sop->Pwd= (char*)pwd;
|
||||||
|
sop->Cto= cto;
|
||||||
|
sop->Qto= qto;
|
||||||
|
sop->UseCnc= cnc;
|
||||||
ok= true;
|
ok= true;
|
||||||
|
} // endif's
|
||||||
|
|
||||||
supfnc |= (FNC_TABLE | FNC_DSN | FNC_DRIVER);
|
supfnc |= (FNC_TABLE | FNC_DSN | FNC_DRIVER);
|
||||||
break;
|
break;
|
||||||
@@ -5112,15 +5254,15 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
|
|||||||
case FNC_NO:
|
case FNC_NO:
|
||||||
case FNC_COL:
|
case FNC_COL:
|
||||||
if (src) {
|
if (src) {
|
||||||
qrp= ODBCSrcCols(g, dsn, (char*)src, cto, qto);
|
qrp= ODBCSrcCols(g, dsn, (char*)src, sop);
|
||||||
src= NULL; // for next tests
|
src= NULL; // for next tests
|
||||||
} else
|
} else
|
||||||
qrp= ODBCColumns(g, dsn, shm, tab, NULL,
|
qrp= ODBCColumns(g, dsn, shm, tab, NULL,
|
||||||
mxr, cto, qto, fnc == FNC_COL);
|
mxr, fnc == FNC_COL, sop);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case FNC_TABLE:
|
case FNC_TABLE:
|
||||||
qrp= ODBCTables(g, dsn, shm, tab, mxr, cto, qto, true);
|
qrp= ODBCTables(g, dsn, shm, tab, mxr, true, sop);
|
||||||
break;
|
break;
|
||||||
case FNC_DSN:
|
case FNC_DSN:
|
||||||
qrp= ODBCDataSources(g, mxr, true);
|
qrp= ODBCDataSources(g, mxr, true);
|
||||||
@@ -5237,9 +5379,10 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
|
|||||||
for (crp= qrp->Colresp; crp; crp= crp->Next)
|
for (crp= qrp->Colresp; crp; crp= crp->Next)
|
||||||
switch (crp->Fld) {
|
switch (crp->Fld) {
|
||||||
case FLD_NAME:
|
case FLD_NAME:
|
||||||
if (ttp == TAB_CSV && topt->data_charset &&
|
if (ttp == TAB_PRX ||
|
||||||
|
(ttp == TAB_CSV && topt->data_charset &&
|
||||||
(!stricmp(topt->data_charset, "UTF8") ||
|
(!stricmp(topt->data_charset, "UTF8") ||
|
||||||
!stricmp(topt->data_charset, "UTF-8")))
|
!stricmp(topt->data_charset, "UTF-8"))))
|
||||||
cnm= crp->Kdata->GetCharValue(i);
|
cnm= crp->Kdata->GetCharValue(i);
|
||||||
else
|
else
|
||||||
cnm= encode(g, crp->Kdata->GetCharValue(i));
|
cnm= encode(g, crp->Kdata->GetCharValue(i));
|
||||||
@@ -5299,9 +5442,18 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
|
|||||||
|
|
||||||
// typ must be PLG type, not SQL type
|
// typ must be PLG type, not SQL type
|
||||||
if (!(plgtyp= TranslateSQLType(typ, dec, prec, v))) {
|
if (!(plgtyp= TranslateSQLType(typ, dec, prec, v))) {
|
||||||
sprintf(g->Message, "Unsupported SQL type %d", typ);
|
if (GetTypeConv() == TPC_SKIP) {
|
||||||
my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0));
|
// Skip this column
|
||||||
goto err;
|
sprintf(g->Message, "Column %s skipped (unsupported type %d)",
|
||||||
|
cnm, typ);
|
||||||
|
push_warning(thd, Sql_condition::WARN_LEVEL_WARN, 0, g->Message);
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
sprintf(g->Message, "Unsupported SQL type %d", typ);
|
||||||
|
my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0));
|
||||||
|
goto err;
|
||||||
|
} // endif type_conv
|
||||||
|
|
||||||
} else
|
} else
|
||||||
typ= plgtyp;
|
typ= plgtyp;
|
||||||
|
|
||||||
@@ -6341,58 +6493,6 @@ struct st_mysql_storage_engine connect_storage_engine=
|
|||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
/* CONNECT global variables definitions. */
|
/* CONNECT global variables definitions. */
|
||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
// Size used when converting TEXT columns to VARCHAR
|
|
||||||
#if defined(_DEBUG)
|
|
||||||
static MYSQL_SYSVAR_INT(conv_size, zconv,
|
|
||||||
PLUGIN_VAR_RQCMDARG, // opt
|
|
||||||
"Size used when converting TEXT columns.",
|
|
||||||
NULL, NULL, SZCONV, 0, 65500, 1);
|
|
||||||
#else
|
|
||||||
static MYSQL_SYSVAR_INT(conv_size, zconv,
|
|
||||||
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, // opt
|
|
||||||
"Size used when converting TEXT columns.",
|
|
||||||
NULL, NULL, SZCONV, 0, 65500, 1);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
|
||||||
Type conversion:
|
|
||||||
no: Unsupported types -> TYPE_ERROR
|
|
||||||
yes: TEXT -> VARCHAR
|
|
||||||
skip: skip unsupported type columns in Discovery
|
|
||||||
*/
|
|
||||||
const char *xconv_names[]=
|
|
||||||
{
|
|
||||||
"NO", "YES", "SKIP", NullS
|
|
||||||
};
|
|
||||||
|
|
||||||
TYPELIB xconv_typelib=
|
|
||||||
{
|
|
||||||
array_elements(xconv_names) - 1, "xconv_typelib",
|
|
||||||
xconv_names, NULL
|
|
||||||
};
|
|
||||||
|
|
||||||
#if defined(_DEBUG)
|
|
||||||
static MYSQL_SYSVAR_ENUM(
|
|
||||||
type_conv, // name
|
|
||||||
xconv, // varname
|
|
||||||
PLUGIN_VAR_RQCMDARG, // opt
|
|
||||||
"Unsupported types conversion.", // comment
|
|
||||||
NULL, // check
|
|
||||||
NULL, // update function
|
|
||||||
0, // def (no)
|
|
||||||
&xconv_typelib); // typelib
|
|
||||||
#else
|
|
||||||
static MYSQL_SYSVAR_ENUM(
|
|
||||||
type_conv, // name
|
|
||||||
xconv, // varname
|
|
||||||
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
|
|
||||||
"Unsupported types conversion.", // comment
|
|
||||||
NULL, // check
|
|
||||||
NULL, // update function
|
|
||||||
0, // def (no)
|
|
||||||
&xconv_typelib); // typelib
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(XMAP)
|
#if defined(XMAP)
|
||||||
// Using file mapping for indexes if true
|
// Using file mapping for indexes if true
|
||||||
static MYSQL_SYSVAR_BOOL(indx_map, xmap, PLUGIN_VAR_RQCMDARG,
|
static MYSQL_SYSVAR_BOOL(indx_map, xmap, PLUGIN_VAR_RQCMDARG,
|
||||||
@@ -6425,6 +6525,7 @@ static struct st_mysql_sys_var* connect_system_variables[]= {
|
|||||||
#if defined(XMSG)
|
#if defined(XMSG)
|
||||||
MYSQL_SYSVAR(errmsg_dir_path),
|
MYSQL_SYSVAR(errmsg_dir_path),
|
||||||
#endif // XMSG
|
#endif // XMSG
|
||||||
|
MYSQL_SYSVAR(json_grp_size),
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -34,7 +34,7 @@
|
|||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
PJSON ParseJson(PGLOBAL g, char *s, int len, int pretty, bool *comma)
|
PJSON ParseJson(PGLOBAL g, char *s, int len, int pretty, bool *comma)
|
||||||
{
|
{
|
||||||
int i;
|
int i, rc;
|
||||||
bool b = false;
|
bool b = false;
|
||||||
PJSON jsp = NULL;
|
PJSON jsp = NULL;
|
||||||
STRG src;
|
STRG src;
|
||||||
@@ -48,22 +48,33 @@ PJSON ParseJson(PGLOBAL g, char *s, int len, int pretty, bool *comma)
|
|||||||
src.str = s;
|
src.str = s;
|
||||||
src.len = len;
|
src.len = len;
|
||||||
|
|
||||||
|
// Save stack and allocation environment and prepare error return
|
||||||
|
if (g->jump_level == MAX_JUMP) {
|
||||||
|
strcpy(g->Message, MSG(TOO_MANY_JUMPS));
|
||||||
|
return NULL;
|
||||||
|
} // endif jump_level
|
||||||
|
|
||||||
|
if ((rc= setjmp(g->jumper[++g->jump_level])) != 0) {
|
||||||
|
goto err;
|
||||||
|
} // endif rc
|
||||||
|
|
||||||
for (i = 0; i < len; i++)
|
for (i = 0; i < len; i++)
|
||||||
switch (s[i]) {
|
switch (s[i]) {
|
||||||
case '[':
|
case '[':
|
||||||
if (jsp) {
|
if (jsp) {
|
||||||
strcpy(g->Message, "More than one item in file");
|
strcpy(g->Message, "More than one item in file");
|
||||||
return NULL;
|
goto err;
|
||||||
} else if (!(jsp = ParseArray(g, ++i, src)))
|
} else if (!(jsp = ParseArray(g, ++i, src)))
|
||||||
return NULL;
|
goto err;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case '{':
|
case '{':
|
||||||
if (jsp) {
|
if (jsp) {
|
||||||
strcpy(g->Message, "More than one item in file");
|
strcpy(g->Message, "More than one item in file");
|
||||||
return NULL;
|
goto err;
|
||||||
} else if (!(jsp = ParseObject(g, ++i, src)))
|
} else if (!(jsp = ParseObject(g, ++i, src)))
|
||||||
return NULL;
|
goto err;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case ' ':
|
case ' ':
|
||||||
case '\t':
|
case '\t':
|
||||||
@@ -79,7 +90,12 @@ PJSON ParseJson(PGLOBAL g, char *s, int len, int pretty, bool *comma)
|
|||||||
} // endif pretty
|
} // endif pretty
|
||||||
|
|
||||||
sprintf(g->Message, "Unexpected ',' (pretty=%d)", pretty);
|
sprintf(g->Message, "Unexpected ',' (pretty=%d)", pretty);
|
||||||
return NULL;
|
goto err;
|
||||||
|
case '"':
|
||||||
|
if (!(jsp = ParseValue(g, i, src)))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
break;
|
||||||
case '(':
|
case '(':
|
||||||
b = true;
|
b = true;
|
||||||
break;
|
break;
|
||||||
@@ -92,13 +108,18 @@ PJSON ParseJson(PGLOBAL g, char *s, int len, int pretty, bool *comma)
|
|||||||
default:
|
default:
|
||||||
sprintf(g->Message, "Bad '%c' character near %.*s",
|
sprintf(g->Message, "Bad '%c' character near %.*s",
|
||||||
s[i], ARGS);
|
s[i], ARGS);
|
||||||
return NULL;
|
goto err;
|
||||||
}; // endswitch s[i]
|
}; // endswitch s[i]
|
||||||
|
|
||||||
if (!jsp)
|
if (!jsp)
|
||||||
sprintf(g->Message, "Invalid Json string '%.*s'", 50, s);
|
sprintf(g->Message, "Invalid Json string '%.*s'", 50, s);
|
||||||
|
|
||||||
|
g->jump_level--;
|
||||||
return jsp;
|
return jsp;
|
||||||
|
|
||||||
|
err:
|
||||||
|
g->jump_level--;
|
||||||
|
return NULL;
|
||||||
} // end of ParseJson
|
} // end of ParseJson
|
||||||
|
|
||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
@@ -312,18 +333,25 @@ err:
|
|||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
char *ParseString(PGLOBAL g, int& i, STRG& src)
|
char *ParseString(PGLOBAL g, int& i, STRG& src)
|
||||||
{
|
{
|
||||||
char *p, *s = src.str;
|
char *s = src.str;
|
||||||
int n = 0, len = src.len;
|
uchar *p;
|
||||||
|
int n = 0, len = src.len;
|
||||||
|
|
||||||
|
// Be sure of memory availability
|
||||||
|
if (len + 1 - i > (signed)((PPOOLHEADER)g->Sarea)->FreeBlk) {
|
||||||
|
strcpy(g->Message, "ParseString: Out of memory");
|
||||||
|
return NULL;
|
||||||
|
} // endif len
|
||||||
|
|
||||||
// The size to allocate is not known yet
|
// The size to allocate is not known yet
|
||||||
p = (char*)PlugSubAlloc(g, NULL, 0);
|
p = (uchar*)PlugSubAlloc(g, NULL, 0);
|
||||||
|
|
||||||
for (; i < len; i++)
|
for (; i < len; i++)
|
||||||
switch (s[i]) {
|
switch (s[i]) {
|
||||||
case '"':
|
case '"':
|
||||||
p[n++] = 0;
|
p[n++] = 0;
|
||||||
PlugSubAlloc(g, NULL, n);
|
PlugSubAlloc(g, NULL, n);
|
||||||
return p;
|
return (char*)p;
|
||||||
case '\\':
|
case '\\':
|
||||||
if (++i < len) {
|
if (++i < len) {
|
||||||
if (s[i] == 'u') {
|
if (s[i] == 'u') {
|
||||||
@@ -504,8 +532,11 @@ PSZ Serialize(PGLOBAL g, PJSON jsp, FILE *fs, int pretty)
|
|||||||
err = (b && jp->WriteChr('\t'));
|
err = (b && jp->WriteChr('\t'));
|
||||||
err |= SerializeObject(jp, (PJOB)jsp);
|
err |= SerializeObject(jp, (PJOB)jsp);
|
||||||
break;
|
break;
|
||||||
|
case TYPE_JVAL:
|
||||||
|
err = SerializeValue(jp, (PJVAL)jsp);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
strcpy(g->Message, "json tree is not an Array or an Object");
|
strcpy(g->Message, "Invalid json tree");
|
||||||
} // endswitch Type
|
} // endswitch Type
|
||||||
|
|
||||||
if (fs) {
|
if (fs) {
|
||||||
@@ -575,9 +606,9 @@ bool SerializeObject(JOUT *js, PJOB jobp)
|
|||||||
else if (js->WriteChr(','))
|
else if (js->WriteChr(','))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (js->WriteChr('\"') ||
|
if (js->WriteChr('"') ||
|
||||||
js->WriteStr(pair->Key) ||
|
js->WriteStr(pair->Key) ||
|
||||||
js->WriteChr('\"') ||
|
js->WriteChr('"') ||
|
||||||
js->WriteChr(':') ||
|
js->WriteChr(':') ||
|
||||||
SerializeValue(js, pair->Val))
|
SerializeValue(js, pair->Val))
|
||||||
return true;
|
return true;
|
||||||
@@ -675,12 +706,13 @@ bool JOUTSTR::Escape(const char *s)
|
|||||||
|
|
||||||
for (unsigned int i = 0; i < strlen(s); i++)
|
for (unsigned int i = 0; i < strlen(s); i++)
|
||||||
switch (s[i]) {
|
switch (s[i]) {
|
||||||
|
case '"':
|
||||||
|
case '\\':
|
||||||
case '\t':
|
case '\t':
|
||||||
case '\n':
|
case '\n':
|
||||||
case '\r':
|
case '\r':
|
||||||
case '\b':
|
case '\b':
|
||||||
case '\f':
|
case '\f': WriteChr('\\');
|
||||||
case '"': WriteChr('\\');
|
|
||||||
// passthru
|
// passthru
|
||||||
default:
|
default:
|
||||||
WriteChr(s[i]);
|
WriteChr(s[i]);
|
||||||
@@ -723,12 +755,13 @@ bool JOUTFILE::Escape(const char *s)
|
|||||||
|
|
||||||
for (unsigned int i = 0; i < strlen(s); i++)
|
for (unsigned int i = 0; i < strlen(s); i++)
|
||||||
switch (s[i]) {
|
switch (s[i]) {
|
||||||
case '\t': fputs("\\t", Stream); break;
|
case '"': fputs("\\\"", Stream); break;
|
||||||
case '\n': fputs("\\n", Stream); break;
|
case '\\': fputs("\\\\", Stream); break;
|
||||||
case '\r': fputs("\\r", Stream); break;
|
case '\t': fputs("\\t", Stream); break;
|
||||||
case '\b': fputs("\\b", Stream); break;
|
case '\n': fputs("\\n", Stream); break;
|
||||||
case '\f': fputs("\\f", Stream); break;
|
case '\r': fputs("\\r", Stream); break;
|
||||||
case '"': fputs("\\\"", Stream); break;
|
case '\b': fputs("\\b", Stream); break;
|
||||||
|
case '\f': fputs("\\f", Stream); break;
|
||||||
default:
|
default:
|
||||||
fputc(s[i], Stream);
|
fputc(s[i], Stream);
|
||||||
break;
|
break;
|
||||||
@@ -1053,3 +1086,27 @@ PSZ JVALUE::GetString(void)
|
|||||||
return (Value) ? Value->GetCharString(buf) : NULL;
|
return (Value) ? Value->GetCharString(buf) : NULL;
|
||||||
} // end of GetString
|
} // end of GetString
|
||||||
|
|
||||||
|
/***********************************************************************/
|
||||||
|
/* Set the Value's value as the given integer. */
|
||||||
|
/***********************************************************************/
|
||||||
|
void JVALUE::SetInteger(PGLOBAL g, int n)
|
||||||
|
{
|
||||||
|
Value = AllocateValue(g, &n, TYPE_INT);
|
||||||
|
} // end of AddInteger
|
||||||
|
|
||||||
|
/***********************************************************************/
|
||||||
|
/* Set the Value's value as the given DOUBLE. */
|
||||||
|
/***********************************************************************/
|
||||||
|
void JVALUE::SetFloat(PGLOBAL g, double f)
|
||||||
|
{
|
||||||
|
Value = AllocateValue(g, &f, TYPE_DOUBLE, 6);
|
||||||
|
} // end of AddFloat
|
||||||
|
|
||||||
|
/***********************************************************************/
|
||||||
|
/* Set the Value's value as the given string. */
|
||||||
|
/***********************************************************************/
|
||||||
|
void JVALUE::SetString(PGLOBAL g, PSZ s)
|
||||||
|
{
|
||||||
|
Value = AllocateValue(g, s, TYPE_STRING);
|
||||||
|
} // end of AddFloat
|
||||||
|
|
||||||
|
@@ -18,7 +18,8 @@ enum JTYP {TYPE_STRG = 1,
|
|||||||
TYPE_BOOL = 4,
|
TYPE_BOOL = 4,
|
||||||
TYPE_INTG = 7,
|
TYPE_INTG = 7,
|
||||||
TYPE_JSON = 12,
|
TYPE_JSON = 12,
|
||||||
TYPE_JAR, TYPE_JOB,
|
TYPE_JAR,
|
||||||
|
TYPE_JOB,
|
||||||
TYPE_JVAL};
|
TYPE_JVAL};
|
||||||
|
|
||||||
class JOUT;
|
class JOUT;
|
||||||
@@ -156,6 +157,9 @@ class JSON : public BLOCK {
|
|||||||
virtual void SetValue(PGLOBAL g, PJVAL jvp, PSZ key) {X}
|
virtual void SetValue(PGLOBAL g, PJVAL jvp, PSZ key) {X}
|
||||||
virtual void SetValue(PVAL valp) {X}
|
virtual void SetValue(PVAL valp) {X}
|
||||||
virtual void SetValue(PJSON jsp) {X}
|
virtual void SetValue(PJSON jsp) {X}
|
||||||
|
virtual void SetString(PGLOBAL g, PSZ s) {X}
|
||||||
|
virtual void SetInteger(PGLOBAL g, int n) {X}
|
||||||
|
virtual void SetFloat(PGLOBAL g, double f) {X}
|
||||||
virtual bool DeleteValue(int i) {X return true;}
|
virtual bool DeleteValue(int i) {X return true;}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@@ -171,6 +175,8 @@ class JOBJECT : public JSON {
|
|||||||
public:
|
public:
|
||||||
JOBJECT(void) : JSON() {First = Last = NULL;}
|
JOBJECT(void) : JSON() {First = Last = NULL;}
|
||||||
|
|
||||||
|
using JSON::GetValue;
|
||||||
|
using JSON::SetValue;
|
||||||
virtual void Clear(void) {First = Last = NULL; Size = 0;}
|
virtual void Clear(void) {First = Last = NULL; Size = 0;}
|
||||||
virtual JTYP GetType(void) {return TYPE_JOB;}
|
virtual JTYP GetType(void) {return TYPE_JOB;}
|
||||||
virtual PJPR AddPair(PGLOBAL g, PSZ key);
|
virtual PJPR AddPair(PGLOBAL g, PSZ key);
|
||||||
@@ -192,6 +198,8 @@ class JARRAY : public JSON {
|
|||||||
public:
|
public:
|
||||||
JARRAY(void) : JSON() {Alloc = 0; First = Last = NULL; Mvals = NULL;}
|
JARRAY(void) : JSON() {Alloc = 0; First = Last = NULL; Mvals = NULL;}
|
||||||
|
|
||||||
|
using JSON::GetValue;
|
||||||
|
using JSON::SetValue;
|
||||||
virtual void Clear(void) {First = Last = NULL; Size = 0;}
|
virtual void Clear(void) {First = Last = NULL; Size = 0;}
|
||||||
virtual JTYP GetType(void) {return TYPE_JAR;}
|
virtual JTYP GetType(void) {return TYPE_JAR;}
|
||||||
virtual PJAR GetArray(void) {return this;}
|
virtual PJAR GetArray(void) {return this;}
|
||||||
@@ -223,6 +231,8 @@ class JVALUE : public JSON {
|
|||||||
{Jsp = jsp; Value = NULL; Next = NULL; Del = false;}
|
{Jsp = jsp; Value = NULL; Next = NULL; Del = false;}
|
||||||
JVALUE(PGLOBAL g, PVAL valp);
|
JVALUE(PGLOBAL g, PVAL valp);
|
||||||
|
|
||||||
|
using JSON::GetValue;
|
||||||
|
using JSON::SetValue;
|
||||||
virtual void Clear(void)
|
virtual void Clear(void)
|
||||||
{Jsp = NULL; Value = NULL; Next = NULL; Del = false; Size = 0;}
|
{Jsp = NULL; Value = NULL; Next = NULL; Del = false; Size = 0;}
|
||||||
virtual JTYP GetType(void) {return TYPE_JVAL;}
|
virtual JTYP GetType(void) {return TYPE_JVAL;}
|
||||||
@@ -236,6 +246,9 @@ class JVALUE : public JSON {
|
|||||||
virtual PSZ GetString(void);
|
virtual PSZ GetString(void);
|
||||||
virtual void SetValue(PVAL valp) {Value = valp;}
|
virtual void SetValue(PVAL valp) {Value = valp;}
|
||||||
virtual void SetValue(PJSON jsp) {Jsp = jsp;}
|
virtual void SetValue(PJSON jsp) {Jsp = jsp;}
|
||||||
|
virtual void SetString(PGLOBAL g, PSZ s);
|
||||||
|
virtual void SetInteger(PGLOBAL g, int n);
|
||||||
|
virtual void SetFloat(PGLOBAL g, double f);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
PJSON Jsp; // To the json value
|
PJSON Jsp; // To the json value
|
||||||
|
582
storage/connect/jsonudf.cpp
Normal file
582
storage/connect/jsonudf.cpp
Normal file
@@ -0,0 +1,582 @@
|
|||||||
|
/************* jsonudf C++ Program Source Code File (.CPP) *************/
|
||||||
|
/* PROGRAM NAME: jsonudf Version 1.0 */
|
||||||
|
/* (C) Copyright to the author Olivier BERTRAND 2015 */
|
||||||
|
/* This program are the JSON User Defined Functions . */
|
||||||
|
/***********************************************************************/
|
||||||
|
|
||||||
|
/***********************************************************************/
|
||||||
|
/* Include relevant sections of the MariaDB header file. */
|
||||||
|
/***********************************************************************/
|
||||||
|
#include <my_global.h>
|
||||||
|
#include <mysqld.h>
|
||||||
|
#include <mysql.h>
|
||||||
|
#include <sql_error.h>
|
||||||
|
|
||||||
|
#include "global.h"
|
||||||
|
#include "plgdbsem.h"
|
||||||
|
#include "json.h"
|
||||||
|
|
||||||
|
#define MEMFIX 512
|
||||||
|
|
||||||
|
uint GetJsonGrpSize(void);
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
DllExport my_bool Json_Value_init(UDF_INIT*, UDF_ARGS*, char*);
|
||||||
|
DllExport char *Json_Value(UDF_INIT*, UDF_ARGS*, char*,
|
||||||
|
unsigned long*, char *, char *);
|
||||||
|
DllExport void Json_Value_deinit(UDF_INIT*);
|
||||||
|
DllExport my_bool Json_Array_init(UDF_INIT*, UDF_ARGS*, char*);
|
||||||
|
DllExport char *Json_Array(UDF_INIT*, UDF_ARGS*, char*,
|
||||||
|
unsigned long*, char *, char *);
|
||||||
|
DllExport void Json_Array_deinit(UDF_INIT*);
|
||||||
|
DllExport my_bool Json_Array_Add_init(UDF_INIT*, UDF_ARGS*, char*);
|
||||||
|
DllExport char *Json_Array_Add(UDF_INIT*, UDF_ARGS*, char*,
|
||||||
|
unsigned long*, char *, char *);
|
||||||
|
DllExport void Json_Array_Add_deinit(UDF_INIT*);
|
||||||
|
DllExport my_bool Json_Object_init(UDF_INIT*, UDF_ARGS*, char*);
|
||||||
|
DllExport char *Json_Object(UDF_INIT*, UDF_ARGS*, char*,
|
||||||
|
unsigned long*, char *, char *);
|
||||||
|
DllExport void Json_Object_deinit(UDF_INIT*);
|
||||||
|
DllExport my_bool Json_Array_Grp_init(UDF_INIT*, UDF_ARGS*, char*);
|
||||||
|
DllExport void Json_Array_Grp_add(UDF_INIT *, UDF_ARGS *, char *, char *);
|
||||||
|
DllExport char *Json_Array_Grp(UDF_INIT*, UDF_ARGS*, char*,
|
||||||
|
unsigned long*, char *, char *);
|
||||||
|
DllExport void Json_Array_Grp_clear(UDF_INIT *, char *, char *);
|
||||||
|
DllExport void Json_Array_Grp_deinit(UDF_INIT*);
|
||||||
|
DllExport my_bool Json_Object_Grp_init(UDF_INIT*, UDF_ARGS*, char*);
|
||||||
|
DllExport void Json_Object_Grp_add(UDF_INIT *, UDF_ARGS *, char *, char *);
|
||||||
|
DllExport char *Json_Object_Grp(UDF_INIT*, UDF_ARGS*, char*,
|
||||||
|
unsigned long*, char *, char *);
|
||||||
|
DllExport void Json_Object_Grp_clear(UDF_INIT *, char *, char *);
|
||||||
|
DllExport void Json_Object_Grp_deinit(UDF_INIT*);
|
||||||
|
} // extern "C"
|
||||||
|
|
||||||
|
/***********************************************************************/
|
||||||
|
/* Allocate and initialise the memory area. */
|
||||||
|
/***********************************************************************/
|
||||||
|
static my_bool JsonInit(UDF_INIT *initid, char *message,
|
||||||
|
unsigned long reslen, unsigned long memlen)
|
||||||
|
{
|
||||||
|
PGLOBAL g = PlugInit(NULL, memlen);
|
||||||
|
|
||||||
|
if (!g) {
|
||||||
|
strcpy(message, "Allocation error");
|
||||||
|
return true;
|
||||||
|
} else if (g->Sarea_Size == 0) {
|
||||||
|
strcpy(message, g->Message);
|
||||||
|
PlugExit(g);
|
||||||
|
return true;
|
||||||
|
} else
|
||||||
|
initid->ptr = (char*)g;
|
||||||
|
|
||||||
|
initid->maybe_null = false;
|
||||||
|
initid->max_length = reslen;
|
||||||
|
return false;
|
||||||
|
} // end of Json_Object_init
|
||||||
|
|
||||||
|
/***********************************************************************/
|
||||||
|
/* Returns true if the argument is a JSON string. */
|
||||||
|
/***********************************************************************/
|
||||||
|
static my_bool IsJson(UDF_ARGS *args, int i)
|
||||||
|
{
|
||||||
|
return (args->arg_type[i] == STRING_RESULT &&
|
||||||
|
!strnicmp(args->attributes[i], "Json_", 5));
|
||||||
|
} // end of IsJson
|
||||||
|
|
||||||
|
/***********************************************************************/
|
||||||
|
/* Calculate the reslen and memlen needed by a function. */
|
||||||
|
/***********************************************************************/
|
||||||
|
static my_bool CalcLen(UDF_ARGS *args, my_bool obj,
|
||||||
|
unsigned long& reslen, unsigned long& memlen)
|
||||||
|
{
|
||||||
|
unsigned long i, k;
|
||||||
|
reslen = args->arg_count + 2;
|
||||||
|
|
||||||
|
// Calculate the result max length
|
||||||
|
for (i = 0; i < args->arg_count; i++) {
|
||||||
|
if (obj) {
|
||||||
|
if (!(k = args->attribute_lengths[i]))
|
||||||
|
k = strlen(args->attributes[i]);
|
||||||
|
|
||||||
|
reslen += (k + 3); // For quotes and :
|
||||||
|
} // endif obj
|
||||||
|
|
||||||
|
switch (args->arg_type[i]) {
|
||||||
|
case STRING_RESULT:
|
||||||
|
if (IsJson(args, i))
|
||||||
|
reslen += args->lengths[i];
|
||||||
|
else
|
||||||
|
reslen += (args->lengths[i] + 1) * 2; // Pessimistic !
|
||||||
|
|
||||||
|
break;
|
||||||
|
case INT_RESULT:
|
||||||
|
reslen += 20;
|
||||||
|
break;
|
||||||
|
case REAL_RESULT:
|
||||||
|
reslen += 31;
|
||||||
|
break;
|
||||||
|
case DECIMAL_RESULT:
|
||||||
|
reslen += (args->lengths[i] + 7); // 6 decimals
|
||||||
|
break;
|
||||||
|
case TIME_RESULT:
|
||||||
|
case ROW_RESULT:
|
||||||
|
case IMPOSSIBLE_RESULT:
|
||||||
|
default:
|
||||||
|
// What should we do here ?
|
||||||
|
break;
|
||||||
|
} // endswitch arg_type
|
||||||
|
|
||||||
|
} // endfor i
|
||||||
|
|
||||||
|
// Calculate the amount of memory needed
|
||||||
|
memlen = MEMFIX + sizeof(JOUTSTR) + reslen;
|
||||||
|
|
||||||
|
for (i = 0; i < args->arg_count; i++) {
|
||||||
|
memlen += (args->lengths[i] + sizeof(JVALUE));
|
||||||
|
|
||||||
|
if (obj) {
|
||||||
|
if (!(k = args->attribute_lengths[i]))
|
||||||
|
k = strlen(args->attributes[i]);
|
||||||
|
|
||||||
|
memlen += (k + sizeof(JOBJECT) + sizeof(JPAIR));
|
||||||
|
} else
|
||||||
|
memlen += sizeof(JARRAY);
|
||||||
|
|
||||||
|
switch (args->arg_type[i]) {
|
||||||
|
case STRING_RESULT:
|
||||||
|
if (IsJson(args, i))
|
||||||
|
memlen += args->lengths[i] * 5; // Estimate parse memory
|
||||||
|
|
||||||
|
memlen += sizeof(TYPVAL<PSZ>);
|
||||||
|
break;
|
||||||
|
case INT_RESULT:
|
||||||
|
memlen += sizeof(TYPVAL<int>);
|
||||||
|
break;
|
||||||
|
case REAL_RESULT:
|
||||||
|
case DECIMAL_RESULT:
|
||||||
|
memlen += sizeof(TYPVAL<double>);
|
||||||
|
break;
|
||||||
|
case TIME_RESULT:
|
||||||
|
case ROW_RESULT:
|
||||||
|
case IMPOSSIBLE_RESULT:
|
||||||
|
default:
|
||||||
|
// What should we do here ?
|
||||||
|
break;
|
||||||
|
} // endswitch arg_type
|
||||||
|
|
||||||
|
} // endfor i
|
||||||
|
|
||||||
|
return false;
|
||||||
|
} // end of CalcLen
|
||||||
|
|
||||||
|
/***********************************************************************/
|
||||||
|
/* Make a zero terminated string from the passed argument. */
|
||||||
|
/***********************************************************************/
|
||||||
|
static PSZ MakePSZ(PGLOBAL g, UDF_ARGS *args, int i)
|
||||||
|
{
|
||||||
|
if (args->args[i]) {
|
||||||
|
int n = args->lengths[i];
|
||||||
|
PSZ s = (PSZ)PlugSubAlloc(g, NULL, n + 1);
|
||||||
|
|
||||||
|
memcpy(s, args->args[i], n);
|
||||||
|
s[n] = 0;
|
||||||
|
return s;
|
||||||
|
} else
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
} // end of MakePSZ
|
||||||
|
|
||||||
|
/***********************************************************************/
|
||||||
|
/* Make a valid key from the passed argument. */
|
||||||
|
/***********************************************************************/
|
||||||
|
static PSZ MakeKey(PGLOBAL g, UDF_ARGS *args, int i)
|
||||||
|
{
|
||||||
|
int n = args->attribute_lengths[i];
|
||||||
|
bool b; // true if attribute is zero terminated
|
||||||
|
PSZ p, s = args->attributes[i];
|
||||||
|
|
||||||
|
if (s && *s && (n || *s == '\'')) {
|
||||||
|
if ((b = (!n || !s[n])))
|
||||||
|
n = strlen(s);
|
||||||
|
|
||||||
|
if (n > 5 && IsJson(args, i)) {
|
||||||
|
s += 5;
|
||||||
|
n -= 5;
|
||||||
|
} else if (*s == '\'' && s[n-1] == '\'') {
|
||||||
|
s++;
|
||||||
|
n -= 2;
|
||||||
|
b = false;
|
||||||
|
} // endif *s
|
||||||
|
|
||||||
|
if (n < 1)
|
||||||
|
return "Key";
|
||||||
|
|
||||||
|
if (!b) {
|
||||||
|
p = (PSZ)PlugSubAlloc(g, NULL, n + 1);
|
||||||
|
memcpy(p, s, n);
|
||||||
|
p[n] = 0;
|
||||||
|
s = p;
|
||||||
|
} // endif b
|
||||||
|
|
||||||
|
} // endif s
|
||||||
|
|
||||||
|
return s;
|
||||||
|
} // end of MakeKey
|
||||||
|
|
||||||
|
/***********************************************************************/
|
||||||
|
/* Make a JSON value from the passed argument. */
|
||||||
|
/***********************************************************************/
|
||||||
|
static PJVAL MakeValue(PGLOBAL g, UDF_ARGS *args, int i)
|
||||||
|
{
|
||||||
|
char *sap = args->args[i];
|
||||||
|
PJSON jsp;
|
||||||
|
PJVAL jvp = new(g) JVALUE;
|
||||||
|
|
||||||
|
if (sap) switch (args->arg_type[i]) {
|
||||||
|
case STRING_RESULT:
|
||||||
|
if (args->lengths[i]) {
|
||||||
|
if (IsJson(args, i)) {
|
||||||
|
if (!(jsp = ParseJson(g, sap, args->lengths[i], 0)))
|
||||||
|
push_warning(current_thd, Sql_condition::WARN_LEVEL_WARN, 0,
|
||||||
|
g->Message);
|
||||||
|
|
||||||
|
if (jsp && jsp->GetType() == TYPE_JVAL)
|
||||||
|
jvp = (PJVAL)jsp;
|
||||||
|
else
|
||||||
|
jvp->SetValue(jsp);
|
||||||
|
|
||||||
|
} else
|
||||||
|
jvp->SetString(g, MakePSZ(g, args, i));
|
||||||
|
|
||||||
|
} // endif str
|
||||||
|
|
||||||
|
break;
|
||||||
|
case INT_RESULT:
|
||||||
|
jvp->SetInteger(g, *(int*)sap);
|
||||||
|
break;
|
||||||
|
case REAL_RESULT:
|
||||||
|
jvp->SetFloat(g, *(double*)sap);
|
||||||
|
break;
|
||||||
|
case DECIMAL_RESULT:
|
||||||
|
jvp->SetFloat(g, atof(MakePSZ(g, args, i)));
|
||||||
|
break;
|
||||||
|
case TIME_RESULT:
|
||||||
|
case ROW_RESULT:
|
||||||
|
case IMPOSSIBLE_RESULT:
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
} // endswitch arg_type
|
||||||
|
|
||||||
|
return jvp;
|
||||||
|
} // end of MakeValue
|
||||||
|
|
||||||
|
/***********************************************************************/
|
||||||
|
/* Make a Json value containing the parameter. */
|
||||||
|
/***********************************************************************/
|
||||||
|
my_bool Json_Value_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
|
||||||
|
{
|
||||||
|
unsigned long reslen, memlen;
|
||||||
|
|
||||||
|
if (args->arg_count > 1) {
|
||||||
|
strcpy(message, "Json_Value cannot accept more than 1 argument");
|
||||||
|
return true;
|
||||||
|
} else
|
||||||
|
CalcLen(args, false, reslen, memlen);
|
||||||
|
|
||||||
|
return JsonInit(initid, message, reslen, memlen);
|
||||||
|
} // end of Json_Value_init
|
||||||
|
|
||||||
|
char *Json_Value(UDF_INIT *initid, UDF_ARGS *args, char *result,
|
||||||
|
unsigned long *res_length, char *is_null, char *error)
|
||||||
|
{
|
||||||
|
char *str;
|
||||||
|
PJVAL jvp;
|
||||||
|
PGLOBAL g = (PGLOBAL)initid->ptr;
|
||||||
|
|
||||||
|
PlugSubSet(g, g->Sarea, g->Sarea_Size);
|
||||||
|
jvp = MakeValue(g, args, 0);
|
||||||
|
|
||||||
|
if (!(str = Serialize(g, jvp, NULL, 0)))
|
||||||
|
str = strcpy(result, g->Message);
|
||||||
|
|
||||||
|
*res_length = strlen(str);
|
||||||
|
return str;
|
||||||
|
} // end of Json_Value
|
||||||
|
|
||||||
|
void Json_Value_deinit(UDF_INIT* initid)
|
||||||
|
{
|
||||||
|
PlugExit((PGLOBAL)initid->ptr);
|
||||||
|
} // end of Json_Value_deinit
|
||||||
|
|
||||||
|
/***********************************************************************/
|
||||||
|
/* Make a Json array containing all the parameters. */
|
||||||
|
/***********************************************************************/
|
||||||
|
my_bool Json_Array_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
|
||||||
|
{
|
||||||
|
unsigned long reslen, memlen;
|
||||||
|
|
||||||
|
CalcLen(args, false, reslen, memlen);
|
||||||
|
return JsonInit(initid, message, reslen, memlen);
|
||||||
|
} // end of Json_Array_init
|
||||||
|
|
||||||
|
char *Json_Array(UDF_INIT *initid, UDF_ARGS *args, char *result,
|
||||||
|
unsigned long *res_length, char *is_null, char *error)
|
||||||
|
{
|
||||||
|
char *str;
|
||||||
|
uint i;
|
||||||
|
PJAR arp;
|
||||||
|
PGLOBAL g = (PGLOBAL)initid->ptr;
|
||||||
|
|
||||||
|
PlugSubSet(g, g->Sarea, g->Sarea_Size);
|
||||||
|
arp = new(g) JARRAY;
|
||||||
|
|
||||||
|
for (i = 0; i < args->arg_count; i++)
|
||||||
|
arp->AddValue(g, MakeValue(g, args, i));
|
||||||
|
|
||||||
|
arp->InitArray(g);
|
||||||
|
|
||||||
|
if (!(str = Serialize(g, arp, NULL, 0)))
|
||||||
|
str = strcpy(result, g->Message);
|
||||||
|
|
||||||
|
*res_length = strlen(str);
|
||||||
|
return str;
|
||||||
|
} // end of Json_Array
|
||||||
|
|
||||||
|
void Json_Array_deinit(UDF_INIT* initid)
|
||||||
|
{
|
||||||
|
PlugExit((PGLOBAL)initid->ptr);
|
||||||
|
} // end of Json_Array_deinit
|
||||||
|
|
||||||
|
/***********************************************************************/
|
||||||
|
/* Add values to a Json array. */
|
||||||
|
/***********************************************************************/
|
||||||
|
my_bool Json_Array_Add_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
|
||||||
|
{
|
||||||
|
unsigned long reslen, memlen;
|
||||||
|
|
||||||
|
if (args->arg_count < 2) {
|
||||||
|
strcpy(message, "Json_Value_Add must have at least 2 arguments");
|
||||||
|
return true;
|
||||||
|
} else if (!IsJson(args, 0)) {
|
||||||
|
strcpy(message, "Json_Value_Add first argument must be a json array");
|
||||||
|
return true;
|
||||||
|
} else
|
||||||
|
CalcLen(args, false, reslen, memlen);
|
||||||
|
|
||||||
|
return JsonInit(initid, message, reslen, memlen);
|
||||||
|
} // end of Json_Array_Add_init
|
||||||
|
|
||||||
|
char *Json_Array_Add(UDF_INIT *initid, UDF_ARGS *args, char *result,
|
||||||
|
unsigned long *res_length, char *is_null, char *error)
|
||||||
|
{
|
||||||
|
char *str;
|
||||||
|
PJVAL jvp;
|
||||||
|
PJAR arp;
|
||||||
|
PGLOBAL g = (PGLOBAL)initid->ptr;
|
||||||
|
|
||||||
|
PlugSubSet(g, g->Sarea, g->Sarea_Size);
|
||||||
|
jvp = MakeValue(g, args, 0);
|
||||||
|
|
||||||
|
if (jvp->GetValType() != TYPE_JAR) {
|
||||||
|
arp = new(g) JARRAY;
|
||||||
|
arp->AddValue(g, jvp);
|
||||||
|
} else
|
||||||
|
arp = jvp->GetArray();
|
||||||
|
|
||||||
|
for (uint i = 1; i < args->arg_count; i++)
|
||||||
|
arp->AddValue(g, MakeValue(g, args, i));
|
||||||
|
|
||||||
|
arp->InitArray(g);
|
||||||
|
|
||||||
|
if (!(str = Serialize(g, arp, NULL, 0)))
|
||||||
|
str = strcpy(result, g->Message);
|
||||||
|
|
||||||
|
*res_length = strlen(str);
|
||||||
|
return str;
|
||||||
|
} // end of Json_Array_Add
|
||||||
|
|
||||||
|
void Json_Array_Add_deinit(UDF_INIT* initid)
|
||||||
|
{
|
||||||
|
PlugExit((PGLOBAL)initid->ptr);
|
||||||
|
} // end of Json_Array_Add_deinit
|
||||||
|
|
||||||
|
/***********************************************************************/
|
||||||
|
/* Make a Json Oject containing all the parameters. */
|
||||||
|
/***********************************************************************/
|
||||||
|
my_bool Json_Object_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
|
||||||
|
{
|
||||||
|
unsigned long reslen, memlen;
|
||||||
|
|
||||||
|
CalcLen(args, true, reslen, memlen);
|
||||||
|
return JsonInit(initid, message, reslen, memlen);
|
||||||
|
} // end of Json_Object_init
|
||||||
|
|
||||||
|
char *Json_Object(UDF_INIT *initid, UDF_ARGS *args, char *result,
|
||||||
|
unsigned long *res_length, char *is_null, char *error)
|
||||||
|
{
|
||||||
|
char *str;
|
||||||
|
uint i;
|
||||||
|
PJOB objp;
|
||||||
|
PGLOBAL g = (PGLOBAL)initid->ptr;
|
||||||
|
|
||||||
|
PlugSubSet(g, g->Sarea, g->Sarea_Size);
|
||||||
|
objp = new(g) JOBJECT;
|
||||||
|
|
||||||
|
for (i = 0; i < args->arg_count; i++)
|
||||||
|
objp->SetValue(g, MakeValue(g, args, i), MakeKey(g, args, i));
|
||||||
|
|
||||||
|
if (!(str = Serialize(g, objp, NULL, 0)))
|
||||||
|
str = strcpy(result, g->Message);
|
||||||
|
|
||||||
|
*res_length = strlen(str);
|
||||||
|
return str;
|
||||||
|
} // end of Json_Object
|
||||||
|
|
||||||
|
void Json_Object_deinit(UDF_INIT* initid)
|
||||||
|
{
|
||||||
|
PlugExit((PGLOBAL)initid->ptr);
|
||||||
|
} // end of Json_Object_deinit
|
||||||
|
|
||||||
|
/***********************************************************************/
|
||||||
|
/* Make a Json array from values comming from rows. */
|
||||||
|
/***********************************************************************/
|
||||||
|
my_bool Json_Array_Grp_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
|
||||||
|
{
|
||||||
|
unsigned long reslen, memlen, n = GetJsonGrpSize();
|
||||||
|
|
||||||
|
if (args->arg_count != 1) {
|
||||||
|
strcpy(message, "Json_Array_Grp can only accept 1 argument");
|
||||||
|
return true;
|
||||||
|
} else
|
||||||
|
CalcLen(args, false, reslen, memlen);
|
||||||
|
|
||||||
|
reslen *= n;
|
||||||
|
memlen += ((memlen - MEMFIX) * (n - 1));
|
||||||
|
|
||||||
|
if (JsonInit(initid, message, reslen, memlen))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
PGLOBAL g = (PGLOBAL)initid->ptr;
|
||||||
|
|
||||||
|
PlugSubSet(g, g->Sarea, g->Sarea_Size);
|
||||||
|
g->Activityp = (PACTIVITY)new(g) JARRAY;
|
||||||
|
g->N = (int)n;
|
||||||
|
return false;
|
||||||
|
} // end of Json_Array_Grp_init
|
||||||
|
|
||||||
|
void Json_Array_Grp_add(UDF_INIT *initid, UDF_ARGS *args,
|
||||||
|
char *is_null, char *error)
|
||||||
|
{
|
||||||
|
PGLOBAL g = (PGLOBAL)initid->ptr;
|
||||||
|
PJAR arp = (PJAR)g->Activityp;
|
||||||
|
|
||||||
|
if (g->N-- > 0)
|
||||||
|
arp->AddValue(g, MakeValue(g, args, 0));
|
||||||
|
|
||||||
|
} // end of Json_Array_Grp_add
|
||||||
|
|
||||||
|
char *Json_Array_Grp(UDF_INIT *initid, UDF_ARGS *args, char *result,
|
||||||
|
unsigned long *res_length, char *is_null, char *error)
|
||||||
|
{
|
||||||
|
char *str;
|
||||||
|
PGLOBAL g = (PGLOBAL)initid->ptr;
|
||||||
|
PJAR arp = (PJAR)g->Activityp;
|
||||||
|
|
||||||
|
if (g->N < 0)
|
||||||
|
push_warning(current_thd, Sql_condition::WARN_LEVEL_WARN, 0,
|
||||||
|
"Result truncated to json_grp_size values");
|
||||||
|
|
||||||
|
arp->InitArray(g);
|
||||||
|
|
||||||
|
if (!(str = Serialize(g, arp, NULL, 0)))
|
||||||
|
str = strcpy(result, g->Message);
|
||||||
|
|
||||||
|
*res_length = strlen(str);
|
||||||
|
return str;
|
||||||
|
} // end of Json_Array_Grp
|
||||||
|
|
||||||
|
void Json_Array_Grp_clear(UDF_INIT *initid, char *is_null, char *error)
|
||||||
|
{
|
||||||
|
PGLOBAL g = (PGLOBAL)initid->ptr;
|
||||||
|
|
||||||
|
PlugSubSet(g, g->Sarea, g->Sarea_Size);
|
||||||
|
g->Activityp = (PACTIVITY)new(g) JARRAY;
|
||||||
|
g->N = GetJsonGrpSize();
|
||||||
|
} // end of Json_Array_Grp_clear
|
||||||
|
|
||||||
|
void Json_Array_Grp_deinit(UDF_INIT* initid)
|
||||||
|
{
|
||||||
|
PlugExit((PGLOBAL)initid->ptr);
|
||||||
|
} // end of Json_Array_Grp_deinit
|
||||||
|
|
||||||
|
/***********************************************************************/
|
||||||
|
/* Make a Json object from values comming from rows. */
|
||||||
|
/***********************************************************************/
|
||||||
|
my_bool Json_Object_Grp_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
|
||||||
|
{
|
||||||
|
unsigned long reslen, memlen, n = GetJsonGrpSize();
|
||||||
|
|
||||||
|
if (args->arg_count != 2) {
|
||||||
|
strcpy(message, "Json_Array_Grp can only accept 2 argument");
|
||||||
|
return true;
|
||||||
|
} else
|
||||||
|
CalcLen(args, true, reslen, memlen);
|
||||||
|
|
||||||
|
reslen *= n;
|
||||||
|
memlen += ((memlen - MEMFIX) * (n - 1));
|
||||||
|
|
||||||
|
if (JsonInit(initid, message, reslen, memlen))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
PGLOBAL g = (PGLOBAL)initid->ptr;
|
||||||
|
|
||||||
|
PlugSubSet(g, g->Sarea, g->Sarea_Size);
|
||||||
|
g->Activityp = (PACTIVITY)new(g) JOBJECT;
|
||||||
|
g->N = (int)n;
|
||||||
|
return false;
|
||||||
|
} // end of Json_Object_Grp_init
|
||||||
|
|
||||||
|
void Json_Object_Grp_add(UDF_INIT *initid, UDF_ARGS *args,
|
||||||
|
char *is_null, char *error)
|
||||||
|
{
|
||||||
|
PGLOBAL g = (PGLOBAL)initid->ptr;
|
||||||
|
PJOB objp = (PJOB)g->Activityp;
|
||||||
|
|
||||||
|
if (g->N-- > 0)
|
||||||
|
objp->SetValue(g, MakeValue(g, args, 0), MakePSZ(g, args, 1));
|
||||||
|
|
||||||
|
} // end of Json_Object_Grp_add
|
||||||
|
|
||||||
|
char *Json_Object_Grp(UDF_INIT *initid, UDF_ARGS *args, char *result,
|
||||||
|
unsigned long *res_length, char *is_null, char *error)
|
||||||
|
{
|
||||||
|
char *str;
|
||||||
|
PGLOBAL g = (PGLOBAL)initid->ptr;
|
||||||
|
PJOB objp = (PJOB)g->Activityp;
|
||||||
|
|
||||||
|
if (g->N < 0)
|
||||||
|
push_warning(current_thd, Sql_condition::WARN_LEVEL_WARN, 0,
|
||||||
|
"Result truncated to json_grp_size values");
|
||||||
|
|
||||||
|
if (!(str = Serialize(g, objp, NULL, 0)))
|
||||||
|
str = strcpy(result, g->Message);
|
||||||
|
|
||||||
|
*res_length = strlen(str);
|
||||||
|
return str;
|
||||||
|
} // end of Json_Object_Grp
|
||||||
|
|
||||||
|
void Json_Object_Grp_clear(UDF_INIT *initid, char *is_null, char *error)
|
||||||
|
{
|
||||||
|
PGLOBAL g = (PGLOBAL)initid->ptr;
|
||||||
|
|
||||||
|
PlugSubSet(g, g->Sarea, g->Sarea_Size);
|
||||||
|
g->Activityp = (PACTIVITY)new(g) JOBJECT;
|
||||||
|
g->N = GetJsonGrpSize();
|
||||||
|
} // end of Json_Object_Grp_clear
|
||||||
|
|
||||||
|
void Json_Object_Grp_deinit(UDF_INIT* initid)
|
||||||
|
{
|
||||||
|
PlugExit((PGLOBAL)initid->ptr);
|
||||||
|
} // end of Json_Object_Grp_deinit
|
||||||
|
|
||||||
|
|
@@ -51,7 +51,8 @@
|
|||||||
#define DLL_EXPORT // Items are exported from this DLL
|
#define DLL_EXPORT // Items are exported from this DLL
|
||||||
#include "myconn.h"
|
#include "myconn.h"
|
||||||
|
|
||||||
extern "C" int zconv;
|
//extern "C" int zconv;
|
||||||
|
int GetConvSize(void);
|
||||||
extern MYSQL_PLUGIN_IMPORT uint mysqld_port;
|
extern MYSQL_PLUGIN_IMPORT uint mysqld_port;
|
||||||
extern MYSQL_PLUGIN_IMPORT char *mysqld_unix_port;
|
extern MYSQL_PLUGIN_IMPORT char *mysqld_unix_port;
|
||||||
|
|
||||||
@@ -265,7 +266,7 @@ PQRYRES MyColumns(PGLOBAL g, THD *thd, const char *host, const char *db,
|
|||||||
return NULL;
|
return NULL;
|
||||||
} else if (type == TYPE_STRING) {
|
} else if (type == TYPE_STRING) {
|
||||||
if (v == 'X') {
|
if (v == 'X') {
|
||||||
len = zconv;
|
len = GetConvSize();
|
||||||
sprintf(g->Message, "Column %s converted to varchar(%d)",
|
sprintf(g->Message, "Column %s converted to varchar(%d)",
|
||||||
colname, len);
|
colname, len);
|
||||||
PushWarning(g, thd);
|
PushWarning(g, thd);
|
||||||
|
@@ -89,8 +89,8 @@ ISBN Language Subject AuthorFN AuthorLN Title Translation Translator Publisher L
|
|||||||
UPDATE t1 SET AuthorFN = 'Philippe' WHERE AuthorLN = 'Knab';
|
UPDATE t1 SET AuthorFN = 'Philippe' WHERE AuthorLN = 'Knab';
|
||||||
SELECT * FROM t1 WHERE ISBN = '9782212090819';
|
SELECT * FROM t1 WHERE ISBN = '9782212090819';
|
||||||
ISBN Language Subject AuthorFN AuthorLN Title Translation Translator Publisher Location Year
|
ISBN Language Subject AuthorFN AuthorLN Title Translation Translator Publisher Location Year
|
||||||
9782212090819 fr applications Jean-Christophe Bernadac Construire une application XML Eyrolles Paris 1999
|
9782212090819 fr applications Philippe Bernadac Construire une application XML Eyrolles Paris 1999
|
||||||
9782212090819 fr applications Philippe Knab Construire une application XML Eyrolles Paris 1999
|
9782212090819 fr applications Fran<EFBFBD>ois Knab Construire une application XML Eyrolles Paris 1999
|
||||||
#
|
#
|
||||||
# To add an author a new table must be created
|
# To add an author a new table must be created
|
||||||
#
|
#
|
||||||
@@ -104,8 +104,8 @@ William J. Pardi
|
|||||||
INSERT INTO t2 VALUES('Charles','Dickens');
|
INSERT INTO t2 VALUES('Charles','Dickens');
|
||||||
SELECT * FROM t1;
|
SELECT * FROM t1;
|
||||||
ISBN Language Subject AuthorFN AuthorLN Title Translation Translator Publisher Location Year
|
ISBN Language Subject AuthorFN AuthorLN Title Translation Translator Publisher Location Year
|
||||||
9782212090819 fr applications Jean-Christophe Bernadac Construire une application XML Eyrolles Paris 1999
|
9782212090819 fr applications Philippe Bernadac Construire une application XML Eyrolles Paris 1999
|
||||||
9782212090819 fr applications Philippe Knab Construire une application XML Eyrolles Paris 1999
|
9782212090819 fr applications Fran<EFBFBD>ois Knab Construire une application XML Eyrolles Paris 1999
|
||||||
9782840825685 fr applications William J. Pardi XML en Action adapt<70> de l'anglais par James Guerin Microsoft Press Paris 1999
|
9782840825685 fr applications William J. Pardi XML en Action adapt<70> de l'anglais par James Guerin Microsoft Press Paris 1999
|
||||||
9782840825685 fr applications Charles Dickens XML en Action adapt<70> de l'anglais par James Guerin Microsoft Press Paris 1999
|
9782840825685 fr applications Charles Dickens XML en Action adapt<70> de l'anglais par James Guerin Microsoft Press Paris 1999
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
@@ -127,11 +127,11 @@ line
|
|||||||
"SUBJECT": "applications",
|
"SUBJECT": "applications",
|
||||||
"AUTHOR": [
|
"AUTHOR": [
|
||||||
{
|
{
|
||||||
"FIRSTNAME": "Jean-Christophe",
|
"FIRSTNAME": "Philippe",
|
||||||
"LASTNAME": "Bernadac"
|
"LASTNAME": "Bernadac"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"FIRSTNAME": "Philippe",
|
"FIRSTNAME": "Fran<EFBFBD>ois",
|
||||||
"LASTNAME": "Knab"
|
"LASTNAME": "Knab"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@@ -192,7 +192,7 @@ Janet 4 Car 17.00
|
|||||||
Janet 5 Beer+Car+Beer+Food 57.00
|
Janet 5 Beer+Car+Beer+Food 57.00
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
#
|
#
|
||||||
# Cannot be fully expanded
|
# Now it can be fully expanded
|
||||||
#
|
#
|
||||||
CREATE TABLE t1 (
|
CREATE TABLE t1 (
|
||||||
WHO CHAR(12),
|
WHO CHAR(12),
|
||||||
@@ -201,7 +201,31 @@ WHAT CHAR(32) FIELD_FORMAT='WEEK:[X]:EXPENSE:[X]:WHAT',
|
|||||||
AMOUNT DOUBLE(8,2) FIELD_FORMAT='WEEK:[X]:EXPENSE:[X]:AMOUNT')
|
AMOUNT DOUBLE(8,2) FIELD_FORMAT='WEEK:[X]:EXPENSE:[X]:AMOUNT')
|
||||||
ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='expense.jsn';
|
ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='expense.jsn';
|
||||||
SELECT * FROM t1;
|
SELECT * FROM t1;
|
||||||
ERROR HY000: Got error 174 'Cannot expand more than one array' from CONNECT
|
WHO WEEK WHAT AMOUNT
|
||||||
|
Joe 3 Beer 18.00
|
||||||
|
Joe 3 Food 12.00
|
||||||
|
Joe 3 Food 19.00
|
||||||
|
Joe 3 Car 20.00
|
||||||
|
Joe 4 Beer 19.00
|
||||||
|
Joe 4 Beer 16.00
|
||||||
|
Joe 4 Food 17.00
|
||||||
|
Joe 4 Food 17.00
|
||||||
|
Joe 4 Beer 14.00
|
||||||
|
Joe 5 Beer 14.00
|
||||||
|
Joe 5 Food 12.00
|
||||||
|
Beth 3 Beer 16.00
|
||||||
|
Beth 4 Food 17.00
|
||||||
|
Beth 4 Beer 15.00
|
||||||
|
Beth 5 Food 12.00
|
||||||
|
Beth 5 Beer 20.00
|
||||||
|
Janet 3 Car 19.00
|
||||||
|
Janet 3 Food 18.00
|
||||||
|
Janet 3 Beer 18.00
|
||||||
|
Janet 4 Car 17.00
|
||||||
|
Janet 5 Beer 14.00
|
||||||
|
Janet 5 Car 12.00
|
||||||
|
Janet 5 Beer 19.00
|
||||||
|
Janet 5 Food 12.00
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
#
|
#
|
||||||
# Expand expense in 3 one week tables
|
# Expand expense in 3 one week tables
|
||||||
|
@@ -128,7 +128,7 @@ SELECT * FROM t1;
|
|||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
|
|
||||||
--echo #
|
--echo #
|
||||||
--echo # Cannot be fully expanded
|
--echo # Now it can be fully expanded
|
||||||
--echo #
|
--echo #
|
||||||
CREATE TABLE t1 (
|
CREATE TABLE t1 (
|
||||||
WHO CHAR(12),
|
WHO CHAR(12),
|
||||||
@@ -136,7 +136,7 @@ WEEK INT(2) FIELD_FORMAT='WEEK:[X]:NUMBER',
|
|||||||
WHAT CHAR(32) FIELD_FORMAT='WEEK:[X]:EXPENSE:[X]:WHAT',
|
WHAT CHAR(32) FIELD_FORMAT='WEEK:[X]:EXPENSE:[X]:WHAT',
|
||||||
AMOUNT DOUBLE(8,2) FIELD_FORMAT='WEEK:[X]:EXPENSE:[X]:AMOUNT')
|
AMOUNT DOUBLE(8,2) FIELD_FORMAT='WEEK:[X]:EXPENSE:[X]:AMOUNT')
|
||||||
ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='expense.jsn';
|
ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='expense.jsn';
|
||||||
--error ER_GET_ERRMSG
|
#--error ER_GET_ERRMSG
|
||||||
SELECT * FROM t1;
|
SELECT * FROM t1;
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
@@ -26,14 +26,16 @@
|
|||||||
#include "myutil.h"
|
#include "myutil.h"
|
||||||
#define DLL_EXPORT // Items are exported from this DLL
|
#define DLL_EXPORT // Items are exported from this DLL
|
||||||
|
|
||||||
extern "C" int xconv;
|
//extern "C" int xconv;
|
||||||
|
TYPCONV GetTypeConv(void);
|
||||||
|
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
/* Convert from MySQL type name to PlugDB type number */
|
/* Convert from MySQL type name to PlugDB type number */
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
int MYSQLtoPLG(char *typname, char *var)
|
int MYSQLtoPLG(char *typname, char *var)
|
||||||
{
|
{
|
||||||
int type;
|
int type;
|
||||||
|
TYPCONV xconv = GetTypeConv();
|
||||||
|
|
||||||
if (!stricmp(typname, "int") || !stricmp(typname, "mediumint") ||
|
if (!stricmp(typname, "int") || !stricmp(typname, "mediumint") ||
|
||||||
!stricmp(typname, "integer"))
|
!stricmp(typname, "integer"))
|
||||||
@@ -57,13 +59,13 @@ int MYSQLtoPLG(char *typname, char *var)
|
|||||||
type = TYPE_TINY;
|
type = TYPE_TINY;
|
||||||
else if (!stricmp(typname, "text") && var) {
|
else if (!stricmp(typname, "text") && var) {
|
||||||
switch (xconv) {
|
switch (xconv) {
|
||||||
case 1:
|
case TPC_YES:
|
||||||
type = TYPE_STRING;
|
type = TYPE_STRING;
|
||||||
*var = 'X';
|
*var = 'X';
|
||||||
break;
|
break;
|
||||||
case 2:
|
case TPC_SKIP:
|
||||||
*var = 'K';
|
*var = 'K';
|
||||||
default:
|
default: // TPC_NO
|
||||||
type = TYPE_ERROR;
|
type = TYPE_ERROR;
|
||||||
} // endswitch xconv
|
} // endswitch xconv
|
||||||
|
|
||||||
@@ -88,7 +90,7 @@ int MYSQLtoPLG(char *typname, char *var)
|
|||||||
} else if (type == TYPE_STRING && !stricmp(typname, "varchar"))
|
} else if (type == TYPE_STRING && !stricmp(typname, "varchar"))
|
||||||
// This is to make the difference between CHAR and VARCHAR
|
// This is to make the difference between CHAR and VARCHAR
|
||||||
*var = 'V';
|
*var = 'V';
|
||||||
else if (type == TYPE_ERROR && xconv == 2)
|
else if (type == TYPE_ERROR && xconv == TPC_SKIP)
|
||||||
*var = 'K';
|
*var = 'K';
|
||||||
else
|
else
|
||||||
*var = 0;
|
*var = 0;
|
||||||
@@ -174,7 +176,7 @@ const char *PLGtoMYSQLtype(int type, bool dbf, char v)
|
|||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
int MYSQLtoPLG(int mytype, char *var)
|
int MYSQLtoPLG(int mytype, char *var)
|
||||||
{
|
{
|
||||||
int type;
|
int type, xconv = GetTypeConv();
|
||||||
|
|
||||||
switch (mytype) {
|
switch (mytype) {
|
||||||
case MYSQL_TYPE_SHORT:
|
case MYSQL_TYPE_SHORT:
|
||||||
@@ -221,7 +223,7 @@ int MYSQLtoPLG(int mytype, char *var)
|
|||||||
case MYSQL_TYPE_LONG_BLOB:
|
case MYSQL_TYPE_LONG_BLOB:
|
||||||
if (var) {
|
if (var) {
|
||||||
switch (xconv) {
|
switch (xconv) {
|
||||||
case 1:
|
case TPC_YES:
|
||||||
if (*var != 'B') {
|
if (*var != 'B') {
|
||||||
// This is a TEXT column
|
// This is a TEXT column
|
||||||
type = TYPE_STRING;
|
type = TYPE_STRING;
|
||||||
@@ -230,9 +232,9 @@ int MYSQLtoPLG(int mytype, char *var)
|
|||||||
type = TYPE_ERROR;
|
type = TYPE_ERROR;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case 2:
|
case TPC_SKIP:
|
||||||
*var = 'K'; // Skip
|
*var = 'K'; // Skip
|
||||||
default:
|
default: // TPC_NO
|
||||||
type = TYPE_ERROR;
|
type = TYPE_ERROR;
|
||||||
} // endswitch xconv
|
} // endswitch xconv
|
||||||
|
|
||||||
|
@@ -2,6 +2,14 @@
|
|||||||
#define DEFAULT_LOGIN_TIMEOUT -1 // means do not set
|
#define DEFAULT_LOGIN_TIMEOUT -1 // means do not set
|
||||||
#define DEFAULT_QUERY_TIMEOUT -1 // means do not set
|
#define DEFAULT_QUERY_TIMEOUT -1 // means do not set
|
||||||
|
|
||||||
|
typedef struct odbc_parms {
|
||||||
|
char *User; // User connect info
|
||||||
|
char *Pwd; // Password connect info
|
||||||
|
int Cto; // Connect timeout
|
||||||
|
int Qto; // Query timeout
|
||||||
|
bool UseCnc; // Use SQLConnect (!SQLDriverConnect)
|
||||||
|
} ODBCPARM, *POPARM;
|
||||||
|
|
||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
/* ODBC catalog function prototypes. */
|
/* ODBC catalog function prototypes. */
|
||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
@@ -10,8 +18,8 @@ char *ODBCCheckConnection(PGLOBAL g, char *dsn, int cop);
|
|||||||
#endif // PROMPT_OK
|
#endif // PROMPT_OK
|
||||||
PQRYRES ODBCDataSources(PGLOBAL g, int maxres, bool info);
|
PQRYRES ODBCDataSources(PGLOBAL g, int maxres, bool info);
|
||||||
PQRYRES ODBCColumns(PGLOBAL g, char *dsn, char *db, char *table,
|
PQRYRES ODBCColumns(PGLOBAL g, char *dsn, char *db, char *table,
|
||||||
char *colpat, int maxres, int cto, int qto, bool info);
|
char *colpat, int maxres, bool info, POPARM sop);
|
||||||
PQRYRES ODBCSrcCols(PGLOBAL g, char *dsn, char *src, int cto, int qto);
|
PQRYRES ODBCSrcCols(PGLOBAL g, char *dsn, char *src, POPARM sop);
|
||||||
PQRYRES ODBCTables(PGLOBAL g, char *dsn, char *db, char *tabpat,
|
PQRYRES ODBCTables(PGLOBAL g, char *dsn, char *db, char *tabpat,
|
||||||
int maxres, int cto, int qto, bool info);
|
int maxres, bool info, POPARM sop);
|
||||||
PQRYRES ODBCDrivers(PGLOBAL g, int maxres, bool info);
|
PQRYRES ODBCDrivers(PGLOBAL g, int maxres, bool info);
|
||||||
|
@@ -37,8 +37,8 @@
|
|||||||
#include "xobject.h"
|
#include "xobject.h"
|
||||||
//#include "kindex.h"
|
//#include "kindex.h"
|
||||||
#include "xtable.h"
|
#include "xtable.h"
|
||||||
#include "tabodbc.h"
|
|
||||||
#include "odbccat.h"
|
#include "odbccat.h"
|
||||||
|
#include "tabodbc.h"
|
||||||
#include "plgcnx.h" // For DB types
|
#include "plgcnx.h" // For DB types
|
||||||
#include "resource.h"
|
#include "resource.h"
|
||||||
#include "valblk.h"
|
#include "valblk.h"
|
||||||
@@ -53,6 +53,8 @@
|
|||||||
extern "C" HINSTANCE s_hModule; // Saved module handle
|
extern "C" HINSTANCE s_hModule; // Saved module handle
|
||||||
#endif // WIN32
|
#endif // WIN32
|
||||||
|
|
||||||
|
int GetConvSize();
|
||||||
|
|
||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
/* Some macro's (should be defined elsewhere to be more accessible) */
|
/* Some macro's (should be defined elsewhere to be more accessible) */
|
||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
@@ -122,7 +124,7 @@ int TranslateSQLType(int stp, int prec, int& len, char& v)
|
|||||||
case SQL_LONGVARCHAR: // (-1)
|
case SQL_LONGVARCHAR: // (-1)
|
||||||
v = 'V';
|
v = 'V';
|
||||||
type = TYPE_STRING;
|
type = TYPE_STRING;
|
||||||
len = MY_MIN(abs(len), 256);
|
len = MY_MIN(abs(len), GetConvSize());
|
||||||
break;
|
break;
|
||||||
case SQL_NUMERIC: // 2
|
case SQL_NUMERIC: // 2
|
||||||
case SQL_DECIMAL: // 3
|
case SQL_DECIMAL: // 3
|
||||||
@@ -291,7 +293,7 @@ static void ResetNullValues(CATPARM *cap)
|
|||||||
/* of an ODBC table that will be retrieved by GetData commands. */
|
/* of an ODBC table that will be retrieved by GetData commands. */
|
||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
PQRYRES ODBCColumns(PGLOBAL g, char *dsn, char *db, char *table,
|
PQRYRES ODBCColumns(PGLOBAL g, char *dsn, char *db, char *table,
|
||||||
char *colpat, int maxres, int cto, int qto, bool info)
|
char *colpat, int maxres, bool info, POPARM sop)
|
||||||
{
|
{
|
||||||
int buftyp[] = {TYPE_STRING, TYPE_STRING, TYPE_STRING, TYPE_STRING,
|
int buftyp[] = {TYPE_STRING, TYPE_STRING, TYPE_STRING, TYPE_STRING,
|
||||||
TYPE_SHORT, TYPE_STRING, TYPE_INT, TYPE_INT,
|
TYPE_SHORT, TYPE_STRING, TYPE_INT, TYPE_INT,
|
||||||
@@ -310,10 +312,8 @@ PQRYRES ODBCColumns(PGLOBAL g, char *dsn, char *db, char *table,
|
|||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
if (!info) {
|
if (!info) {
|
||||||
ocp = new(g) ODBConn(g, NULL);
|
ocp = new(g) ODBConn(g, NULL);
|
||||||
ocp->SetLoginTimeout((DWORD)cto);
|
|
||||||
ocp->SetQueryTimeout((DWORD)qto);
|
|
||||||
|
|
||||||
if (ocp->Open(dsn, 10) < 1) // openReadOnly + noODBCdialog
|
if (ocp->Open(dsn, sop, 10) < 1) // openReadOnly + noODBCdialog
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (table && !strchr(table, '%')) {
|
if (table && !strchr(table, '%')) {
|
||||||
@@ -342,7 +342,7 @@ PQRYRES ODBCColumns(PGLOBAL g, char *dsn, char *db, char *table,
|
|||||||
} // endif ocp
|
} // endif ocp
|
||||||
|
|
||||||
if (trace)
|
if (trace)
|
||||||
htrc("ODBCColumns: max=%d len=%d,%d,%d\n",
|
htrc("ODBCColumns: max=%d len=%d,%d,%d,%d\n",
|
||||||
maxres, length[0], length[1], length[2], length[3]);
|
maxres, length[0], length[1], length[2], length[3]);
|
||||||
|
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
@@ -388,12 +388,13 @@ PQRYRES ODBCColumns(PGLOBAL g, char *dsn, char *db, char *table,
|
|||||||
/* ODBCSrcCols: constructs the result blocks containing the */
|
/* ODBCSrcCols: constructs the result blocks containing the */
|
||||||
/* description of all the columns of a Srcdef option. */
|
/* description of all the columns of a Srcdef option. */
|
||||||
/**************************************************************************/
|
/**************************************************************************/
|
||||||
PQRYRES ODBCSrcCols(PGLOBAL g, char *dsn, char *src, int cto, int qto)
|
PQRYRES ODBCSrcCols(PGLOBAL g, char *dsn, char *src, POPARM sop)
|
||||||
{
|
{
|
||||||
ODBConn *ocp = new(g) ODBConn(g, NULL);
|
ODBConn *ocp = new(g) ODBConn(g, NULL);
|
||||||
|
|
||||||
ocp->SetLoginTimeout((DWORD)cto);
|
if (ocp->Open(dsn, sop, 10) < 1) // openReadOnly + noOdbcDialog
|
||||||
ocp->SetQueryTimeout((DWORD)qto);
|
return NULL;
|
||||||
|
|
||||||
return ocp->GetMetaData(g, dsn, src);
|
return ocp->GetMetaData(g, dsn, src);
|
||||||
} // end of ODBCSrcCols
|
} // end of ODBCSrcCols
|
||||||
|
|
||||||
@@ -574,7 +575,7 @@ PQRYRES ODBCDataSources(PGLOBAL g, int maxres, bool info)
|
|||||||
/* an ODBC database that will be retrieved by GetData commands. */
|
/* an ODBC database that will be retrieved by GetData commands. */
|
||||||
/**************************************************************************/
|
/**************************************************************************/
|
||||||
PQRYRES ODBCTables(PGLOBAL g, char *dsn, char *db, char *tabpat,
|
PQRYRES ODBCTables(PGLOBAL g, char *dsn, char *db, char *tabpat,
|
||||||
int maxres, int cto, int qto, bool info)
|
int maxres, bool info, POPARM sop)
|
||||||
{
|
{
|
||||||
int buftyp[] = {TYPE_STRING, TYPE_STRING, TYPE_STRING,
|
int buftyp[] = {TYPE_STRING, TYPE_STRING, TYPE_STRING,
|
||||||
TYPE_STRING, TYPE_STRING};
|
TYPE_STRING, TYPE_STRING};
|
||||||
@@ -594,10 +595,8 @@ PQRYRES ODBCTables(PGLOBAL g, char *dsn, char *db, char *tabpat,
|
|||||||
/* Open the connection with the ODBC data source. */
|
/* Open the connection with the ODBC data source. */
|
||||||
/**********************************************************************/
|
/**********************************************************************/
|
||||||
ocp = new(g) ODBConn(g, NULL);
|
ocp = new(g) ODBConn(g, NULL);
|
||||||
ocp->SetLoginTimeout((DWORD)cto);
|
|
||||||
ocp->SetQueryTimeout((DWORD)qto);
|
|
||||||
|
|
||||||
if (ocp->Open(dsn, 2) < 1) // 2 is openReadOnly
|
if (ocp->Open(dsn, sop, 2) < 1) // 2 is openReadOnly
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (!maxres)
|
if (!maxres)
|
||||||
@@ -925,11 +924,14 @@ ODBConn::ODBConn(PGLOBAL g, TDBODBC *tdbp)
|
|||||||
m_Catver = (tdbp) ? tdbp->Catver : 0;
|
m_Catver = (tdbp) ? tdbp->Catver : 0;
|
||||||
m_Rows = 0;
|
m_Rows = 0;
|
||||||
m_Connect = NULL;
|
m_Connect = NULL;
|
||||||
|
m_User = NULL;
|
||||||
|
m_Pwd = NULL;
|
||||||
m_Updatable = true;
|
m_Updatable = true;
|
||||||
m_Transact = false;
|
m_Transact = false;
|
||||||
m_Scrollable = (tdbp) ? tdbp->Scrollable : false;
|
m_Scrollable = (tdbp) ? tdbp->Scrollable : false;
|
||||||
m_First = true;
|
m_First = true;
|
||||||
m_Full = false;
|
m_Full = false;
|
||||||
|
m_UseCnc = false;
|
||||||
m_IDQuoteChar[0] = '"';
|
m_IDQuoteChar[0] = '"';
|
||||||
m_IDQuoteChar[1] = 0;
|
m_IDQuoteChar[1] = 0;
|
||||||
//*m_ErrMsg = '\0';
|
//*m_ErrMsg = '\0';
|
||||||
@@ -1061,7 +1063,7 @@ void ODBConn::OnSetOptions(HSTMT hstmt)
|
|||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
/* Open: connect to a data source. */
|
/* Open: connect to a data source. */
|
||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
int ODBConn::Open(PSZ ConnectString, DWORD options)
|
int ODBConn::Open(PSZ ConnectString, POPARM sop, DWORD options)
|
||||||
{
|
{
|
||||||
PGLOBAL& g = m_G;
|
PGLOBAL& g = m_G;
|
||||||
//ASSERT_VALID(this);
|
//ASSERT_VALID(this);
|
||||||
@@ -1070,6 +1072,11 @@ int ODBConn::Open(PSZ ConnectString, DWORD options)
|
|||||||
|
|
||||||
m_Updatable = !(options & openReadOnly);
|
m_Updatable = !(options & openReadOnly);
|
||||||
m_Connect = ConnectString;
|
m_Connect = ConnectString;
|
||||||
|
m_User = sop->User;
|
||||||
|
m_Pwd = sop->Pwd;
|
||||||
|
m_LoginTimeout = sop->Cto;
|
||||||
|
m_QueryTimeout = sop->Qto;
|
||||||
|
m_UseCnc = sop->UseCnc;
|
||||||
|
|
||||||
// Allocate the HDBC and make connection
|
// Allocate the HDBC and make connection
|
||||||
try {
|
try {
|
||||||
@@ -1078,10 +1085,14 @@ int ODBConn::Open(PSZ ConnectString, DWORD options)
|
|||||||
AllocConnect(options);
|
AllocConnect(options);
|
||||||
/*ver = GetStringInfo(SQL_ODBC_VER);*/
|
/*ver = GetStringInfo(SQL_ODBC_VER);*/
|
||||||
|
|
||||||
if (Connect(options)) {
|
if (!m_UseCnc) {
|
||||||
strcpy(g->Message, MSG(CONNECT_CANCEL));
|
if (DriverConnect(options)) {
|
||||||
return 0;
|
strcpy(g->Message, MSG(CONNECT_CANCEL));
|
||||||
} // endif
|
return 0;
|
||||||
|
} // endif
|
||||||
|
|
||||||
|
} else // Connect using SQLConnect
|
||||||
|
Connect();
|
||||||
|
|
||||||
/*ver = GetStringInfo(SQL_DRIVER_ODBC_VER);*/
|
/*ver = GetStringInfo(SQL_DRIVER_ODBC_VER);*/
|
||||||
// Verify support for required functionality and cache info
|
// Verify support for required functionality and cache info
|
||||||
@@ -1163,10 +1174,27 @@ void ODBConn::AllocConnect(DWORD Options)
|
|||||||
return;
|
return;
|
||||||
} // end of AllocConnect
|
} // end of AllocConnect
|
||||||
|
|
||||||
|
/***********************************************************************/
|
||||||
|
/* Connect to data source using SQLConnect. */
|
||||||
|
/***********************************************************************/
|
||||||
|
void ODBConn::Connect(void)
|
||||||
|
{
|
||||||
|
SQLRETURN rc;
|
||||||
|
SQLSMALLINT ul = (m_User ? SQL_NTS : 0);
|
||||||
|
SQLSMALLINT pl = (m_Pwd ? SQL_NTS : 0);
|
||||||
|
|
||||||
|
rc = SQLConnect(m_hdbc, (SQLCHAR*)m_Connect, SQL_NTS,
|
||||||
|
(SQLCHAR*)m_User, ul, (SQLCHAR*)m_Pwd, pl);
|
||||||
|
|
||||||
|
if (!Check(rc))
|
||||||
|
ThrowDBX(rc, "SQLConnect");
|
||||||
|
|
||||||
|
} // end of Connect
|
||||||
|
|
||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
/* Connect to data source using SQLDriverConnect. */
|
/* Connect to data source using SQLDriverConnect. */
|
||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
bool ODBConn::Connect(DWORD Options)
|
bool ODBConn::DriverConnect(DWORD Options)
|
||||||
{
|
{
|
||||||
RETCODE rc;
|
RETCODE rc;
|
||||||
SWORD nResult;
|
SWORD nResult;
|
||||||
@@ -1213,7 +1241,7 @@ bool ODBConn::Connect(DWORD Options)
|
|||||||
|
|
||||||
// All done
|
// All done
|
||||||
return false;
|
return false;
|
||||||
} // end of Connect
|
} // end of DriverConnect
|
||||||
|
|
||||||
void ODBConn::VerifyConnect()
|
void ODBConn::VerifyConnect()
|
||||||
{
|
{
|
||||||
@@ -1712,6 +1740,8 @@ bool ODBConn::BindParam(ODBCCOL *colp)
|
|||||||
strcpy(m_G->Message, x->GetErrorMessage(0));
|
strcpy(m_G->Message, x->GetErrorMessage(0));
|
||||||
colsize = colp->GetPrecision();
|
colsize = colp->GetPrecision();
|
||||||
sqlt = GetSQLType(buftype);
|
sqlt = GetSQLType(buftype);
|
||||||
|
dec = IsTypeChar(buftype) ? 0 : colp->GetScale();
|
||||||
|
nul = SQL_NULLABLE_UNKNOWN;
|
||||||
} // end try/catch
|
} // end try/catch
|
||||||
|
|
||||||
buf = colp->GetBuffer(0);
|
buf = colp->GetBuffer(0);
|
||||||
@@ -1865,9 +1895,6 @@ PQRYRES ODBConn::GetMetaData(PGLOBAL g, char *dsn, char *src)
|
|||||||
RETCODE rc;
|
RETCODE rc;
|
||||||
HSTMT hstmt;
|
HSTMT hstmt;
|
||||||
|
|
||||||
if (Open(dsn, 10) < 1) // openReadOnly + noOdbcDialog
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
rc = SQLAllocStmt(m_hdbc, &hstmt);
|
rc = SQLAllocStmt(m_hdbc, &hstmt);
|
||||||
|
|
||||||
|
@@ -119,7 +119,7 @@ class ODBConn : public BLOCK {
|
|||||||
noOdbcDialog = 0x0008, // Don't display ODBC Connect dialog
|
noOdbcDialog = 0x0008, // Don't display ODBC Connect dialog
|
||||||
forceOdbcDialog = 0x0010}; // Always display ODBC connect dialog
|
forceOdbcDialog = 0x0010}; // Always display ODBC connect dialog
|
||||||
|
|
||||||
int Open(PSZ ConnectString, DWORD Options = 0);
|
int Open(PSZ ConnectString, POPARM sop, DWORD Options = 0);
|
||||||
int Rewind(char *sql, ODBCCOL *tocols);
|
int Rewind(char *sql, ODBCCOL *tocols);
|
||||||
void Close(void);
|
void Close(void);
|
||||||
PQRYRES AllocateResult(PGLOBAL g);
|
PQRYRES AllocateResult(PGLOBAL g);
|
||||||
@@ -135,8 +135,10 @@ class ODBConn : public BLOCK {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
// Operations
|
// Operations
|
||||||
void SetLoginTimeout(DWORD sec) {m_LoginTimeout = sec;}
|
//void SetLoginTimeout(DWORD sec) {m_LoginTimeout = sec;}
|
||||||
void SetQueryTimeout(DWORD sec) {m_QueryTimeout = sec;}
|
//void SetQueryTimeout(DWORD sec) {m_QueryTimeout = sec;}
|
||||||
|
//void SetUserName(PSZ user) {m_User = user;}
|
||||||
|
//void SetUserPwd(PSZ pwd) {m_Pwd = pwd;}
|
||||||
int GetResultSize(char *sql, ODBCCOL *colp);
|
int GetResultSize(char *sql, ODBCCOL *colp);
|
||||||
int ExecDirectSQL(char *sql, ODBCCOL *tocols);
|
int ExecDirectSQL(char *sql, ODBCCOL *tocols);
|
||||||
int Fetch(void);
|
int Fetch(void);
|
||||||
@@ -155,7 +157,7 @@ class ODBConn : public BLOCK {
|
|||||||
|
|
||||||
// Implementation
|
// Implementation
|
||||||
public:
|
public:
|
||||||
// virtual ~ODBConn();
|
//virtual ~ODBConn();
|
||||||
|
|
||||||
// ODBC operations
|
// ODBC operations
|
||||||
protected:
|
protected:
|
||||||
@@ -163,7 +165,8 @@ class ODBConn : public BLOCK {
|
|||||||
void ThrowDBX(RETCODE rc, PSZ msg, HSTMT hstmt = SQL_NULL_HSTMT);
|
void ThrowDBX(RETCODE rc, PSZ msg, HSTMT hstmt = SQL_NULL_HSTMT);
|
||||||
void ThrowDBX(PSZ msg);
|
void ThrowDBX(PSZ msg);
|
||||||
void AllocConnect(DWORD dwOptions);
|
void AllocConnect(DWORD dwOptions);
|
||||||
bool Connect(DWORD Options);
|
void Connect(void);
|
||||||
|
bool DriverConnect(DWORD Options);
|
||||||
void VerifyConnect(void);
|
void VerifyConnect(void);
|
||||||
void GetConnectInfo(void);
|
void GetConnectInfo(void);
|
||||||
void Free(void);
|
void Free(void);
|
||||||
@@ -185,11 +188,14 @@ class ODBConn : public BLOCK {
|
|||||||
DWORD m_RowsetSize;
|
DWORD m_RowsetSize;
|
||||||
char m_IDQuoteChar[2];
|
char m_IDQuoteChar[2];
|
||||||
PSZ m_Connect;
|
PSZ m_Connect;
|
||||||
|
PSZ m_User;
|
||||||
|
PSZ m_Pwd;
|
||||||
int m_Catver;
|
int m_Catver;
|
||||||
int m_Rows;
|
int m_Rows;
|
||||||
bool m_Updatable;
|
bool m_Updatable;
|
||||||
bool m_Transact;
|
bool m_Transact;
|
||||||
bool m_Scrollable;
|
bool m_Scrollable;
|
||||||
|
bool m_UseCnc;
|
||||||
bool m_First;
|
bool m_First;
|
||||||
bool m_Full;
|
bool m_Full;
|
||||||
}; // end of ODBConn class definition
|
}; // end of ODBConn class definition
|
||||||
|
@@ -311,7 +311,7 @@ PQRYRES PlgAllocResult(PGLOBAL g, int ncol, int maxres, int ids,
|
|||||||
else
|
else
|
||||||
crp->Kdata = NULL;
|
crp->Kdata = NULL;
|
||||||
|
|
||||||
if (g->Trace)
|
if (trace)
|
||||||
htrc("Column(%d) %s type=%d len=%d value=%p\n",
|
htrc("Column(%d) %s type=%d len=%d value=%p\n",
|
||||||
crp->Ncol, crp->Name, crp->Type, crp->Length, crp->Kdata);
|
crp->Ncol, crp->Name, crp->Type, crp->Length, crp->Kdata);
|
||||||
|
|
||||||
|
@@ -144,12 +144,12 @@ PGLOBAL PlugInit(LPCSTR Language, uint worksize)
|
|||||||
return NULL;
|
return NULL;
|
||||||
} else {
|
} else {
|
||||||
g->Sarea_Size = worksize;
|
g->Sarea_Size = worksize;
|
||||||
g->Trace = 0;
|
|
||||||
g->Createas = 0;
|
g->Createas = 0;
|
||||||
g->Alchecked = 0;
|
g->Alchecked = 0;
|
||||||
g->Mrr = 0;
|
g->Mrr = 0;
|
||||||
g->Activityp = g->ActivityStart = NULL;
|
g->Activityp = g->ActivityStart = NULL;
|
||||||
g->Xchk = NULL;
|
g->Xchk = NULL;
|
||||||
|
g->N = 0;
|
||||||
strcpy(g->Message, "");
|
strcpy(g->Message, "");
|
||||||
|
|
||||||
/*******************************************************************/
|
/*******************************************************************/
|
||||||
|
@@ -222,6 +222,7 @@ class DllExport DOSCOL : public COLBLK {
|
|||||||
virtual PVBLK GetDval(void) {return Dval;}
|
virtual PVBLK GetDval(void) {return Dval;}
|
||||||
|
|
||||||
// Methods
|
// Methods
|
||||||
|
using COLBLK::Print;
|
||||||
virtual bool VarSize(void);
|
virtual bool VarSize(void);
|
||||||
virtual bool SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check);
|
virtual bool SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check);
|
||||||
virtual void ReadColumn(PGLOBAL g);
|
virtual void ReadColumn(PGLOBAL g);
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/************* tabjson C++ Program Source Code File (.CPP) *************/
|
/************* tabjson C++ Program Source Code File (.CPP) *************/
|
||||||
/* PROGRAM NAME: tabxjson Version 1.0 */
|
/* PROGRAM NAME: tabjson Version 1.0 */
|
||||||
/* (C) Copyright to the author Olivier BERTRAND 2014 - 2015 */
|
/* (C) Copyright to the author Olivier BERTRAND 2014 - 2015 */
|
||||||
/* This program are the JSON class DB execution routines. */
|
/* This program are the JSON class DB execution routines. */
|
||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
@@ -119,12 +119,12 @@ TDBJSN::TDBJSN(PJDEF tdp, PTXF txfp) : TDBDOS(tdp, txfp)
|
|||||||
Fpos = -1;
|
Fpos = -1;
|
||||||
Spos = N = 0;
|
Spos = N = 0;
|
||||||
Limit = tdp->Limit;
|
Limit = tdp->Limit;
|
||||||
Pretty = tdp->Pretty;
|
NextSame = 0;
|
||||||
Strict = tdp->Strict;
|
|
||||||
NextSame = false;
|
|
||||||
Comma = false;
|
|
||||||
SameRow = 0;
|
SameRow = 0;
|
||||||
Xval = -1;
|
Xval = -1;
|
||||||
|
Pretty = tdp->Pretty;
|
||||||
|
Strict = tdp->Strict;
|
||||||
|
Comma = false;
|
||||||
} // end of TDBJSN standard constructor
|
} // end of TDBJSN standard constructor
|
||||||
|
|
||||||
TDBJSN::TDBJSN(TDBJSN *tdbp) : TDBDOS(NULL, tdbp)
|
TDBJSN::TDBJSN(TDBJSN *tdbp) : TDBDOS(NULL, tdbp)
|
||||||
@@ -137,12 +137,12 @@ TDBJSN::TDBJSN(TDBJSN *tdbp) : TDBDOS(NULL, tdbp)
|
|||||||
Spos = tdbp->Spos;
|
Spos = tdbp->Spos;
|
||||||
N = tdbp->N;
|
N = tdbp->N;
|
||||||
Limit = tdbp->Limit;
|
Limit = tdbp->Limit;
|
||||||
Pretty = tdbp->Pretty;
|
|
||||||
Strict = tdbp->Strict;
|
|
||||||
NextSame = tdbp->NextSame;
|
NextSame = tdbp->NextSame;
|
||||||
Comma = tdbp->Comma;
|
|
||||||
SameRow = tdbp->SameRow;
|
SameRow = tdbp->SameRow;
|
||||||
Xval = tdbp->Xval;
|
Xval = tdbp->Xval;
|
||||||
|
Pretty = tdbp->Pretty;
|
||||||
|
Strict = tdbp->Strict;
|
||||||
|
Comma = tdbp->Comma;
|
||||||
} // end of TDBJSN copy constructor
|
} // end of TDBJSN copy constructor
|
||||||
|
|
||||||
// Used for update
|
// Used for update
|
||||||
@@ -221,14 +221,9 @@ bool TDBJSN::OpenDB(PGLOBAL g)
|
|||||||
/*******************************************************************/
|
/*******************************************************************/
|
||||||
/* Table already open replace it at its beginning. */
|
/* Table already open replace it at its beginning. */
|
||||||
/*******************************************************************/
|
/*******************************************************************/
|
||||||
for (PJCOL cp = (PJCOL)Columns; cp; cp = (PJCOL)cp->GetNext()) {
|
|
||||||
cp->Nx = 0;
|
|
||||||
cp->Arp = NULL;
|
|
||||||
} // endfor cp
|
|
||||||
|
|
||||||
Fpos= -1;
|
Fpos= -1;
|
||||||
Spos = 0;
|
Spos = 0;
|
||||||
NextSame = false;
|
NextSame = 0;
|
||||||
SameRow = 0;
|
SameRow = 0;
|
||||||
} else {
|
} else {
|
||||||
/*******************************************************************/
|
/*******************************************************************/
|
||||||
@@ -292,7 +287,8 @@ int TDBJSN::ReadDB(PGLOBAL g)
|
|||||||
N++;
|
N++;
|
||||||
|
|
||||||
if (NextSame) {
|
if (NextSame) {
|
||||||
SameRow++;
|
SameRow = NextSame;
|
||||||
|
NextSame = 0;
|
||||||
return RC_OK;
|
return RC_OK;
|
||||||
} else if ((rc = TDBDOS::ReadDB(g)) == RC_OK)
|
} else if ((rc = TDBDOS::ReadDB(g)) == RC_OK)
|
||||||
if (!IsRead() && ((rc = ReadBuffer(g)) != RC_OK)) {
|
if (!IsRead() && ((rc = ReadBuffer(g)) != RC_OK)) {
|
||||||
@@ -333,21 +329,20 @@ int TDBJSN::ReadDB(PGLOBAL g)
|
|||||||
|
|
||||||
} // end of PrepareWriting
|
} // end of PrepareWriting
|
||||||
|
|
||||||
/* ----------------------------- JSNCOL ------------------------------- */
|
/* ---------------------------- JSONCOL ------------------------------ */
|
||||||
|
|
||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
/* JSNCOL public constructor. */
|
/* JSONCOL public constructor. */
|
||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
JSONCOL::JSONCOL(PGLOBAL g, PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i)
|
JSONCOL::JSONCOL(PGLOBAL g, PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i)
|
||||||
: DOSCOL(g, cdp, tdbp, cprec, i, "DOS")
|
: DOSCOL(g, cdp, tdbp, cprec, i, "DOS")
|
||||||
{
|
{
|
||||||
Tjp = (TDBJSN *)(tdbp->GetOrig() ? tdbp->GetOrig() : tdbp);
|
Tjp = (TDBJSN *)(tdbp->GetOrig() ? tdbp->GetOrig() : tdbp);
|
||||||
Arp = NULL;
|
|
||||||
Jpath = cdp->GetFmt();
|
Jpath = cdp->GetFmt();
|
||||||
MulVal = NULL;
|
MulVal = NULL;
|
||||||
Nodes = NULL;
|
Nodes = NULL;
|
||||||
Nod = Nx =0;
|
Nod = 0;
|
||||||
Ival = -1;
|
Xnod = -1;
|
||||||
Xpd = false;
|
Xpd = false;
|
||||||
Parsed = false;
|
Parsed = false;
|
||||||
} // end of JSONCOL constructor
|
} // end of JSONCOL constructor
|
||||||
@@ -359,13 +354,11 @@ JSONCOL::JSONCOL(PGLOBAL g, PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i)
|
|||||||
JSONCOL::JSONCOL(JSONCOL *col1, PTDB tdbp) : DOSCOL(col1, tdbp)
|
JSONCOL::JSONCOL(JSONCOL *col1, PTDB tdbp) : DOSCOL(col1, tdbp)
|
||||||
{
|
{
|
||||||
Tjp = col1->Tjp;
|
Tjp = col1->Tjp;
|
||||||
Arp = col1->Arp;
|
|
||||||
Jpath = col1->Jpath;
|
Jpath = col1->Jpath;
|
||||||
MulVal = col1->MulVal;
|
MulVal = col1->MulVal;
|
||||||
Nodes = col1->Nodes;
|
Nodes = col1->Nodes;
|
||||||
Nod = col1->Nod;
|
Nod = col1->Nod;
|
||||||
Ival = col1->Ival;
|
Xnod = col1->Xnod;
|
||||||
Nx = col1->Nx;
|
|
||||||
Xpd = col1->Xpd;
|
Xpd = col1->Xpd;
|
||||||
Parsed = col1->Parsed;
|
Parsed = col1->Parsed;
|
||||||
} // end of JSONCOL copy constructor
|
} // end of JSONCOL copy constructor
|
||||||
@@ -387,17 +380,16 @@ bool JSONCOL::SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check)
|
|||||||
} // end of SetBuffer
|
} // end of SetBuffer
|
||||||
|
|
||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
/* Analyse array processing options. */
|
/* Check whether this object is expanded. */
|
||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
bool JSONCOL::CheckExpand(PGLOBAL g, int i, PSZ nm, bool b)
|
bool JSONCOL::CheckExpand(PGLOBAL g, int i, PSZ nm, bool b)
|
||||||
{
|
{
|
||||||
if (Tjp->Xcol && nm && !strcmp(nm, Tjp->Xcol) &&
|
if ((Tjp->Xcol && nm && !strcmp(nm, Tjp->Xcol) &&
|
||||||
(Tjp->Xval < 0 || Tjp->Xval == i)) {
|
(Tjp->Xval < 0 || Tjp->Xval == i)) || Xpd) {
|
||||||
Xpd = true; // Expandable object
|
Xpd = true; // Expandable object
|
||||||
Nodes[i].Op = OP_XX;
|
Nodes[i].Op = OP_EXP;
|
||||||
Tjp->Xval = i;
|
|
||||||
} else if (b) {
|
} else if (b) {
|
||||||
strcpy(g->Message, "Cannot expand more than one array");
|
strcpy(g->Message, "Cannot expand more than one branch");
|
||||||
return true;
|
return true;
|
||||||
} // endif Xcol
|
} // endif Xcol
|
||||||
|
|
||||||
@@ -434,7 +426,7 @@ bool JSONCOL::SetArrayOptions(PGLOBAL g, char *p, int i, PSZ nm)
|
|||||||
// Default specifications
|
// Default specifications
|
||||||
if (CheckExpand(g, i, nm, false))
|
if (CheckExpand(g, i, nm, false))
|
||||||
return true;
|
return true;
|
||||||
else if (jnp->Op != OP_XX)
|
else if (jnp->Op != OP_EXP)
|
||||||
if (!Value->IsTypeNum()) {
|
if (!Value->IsTypeNum()) {
|
||||||
jnp->CncVal = AllocateValue(g, (void*)", ", TYPE_STRING);
|
jnp->CncVal = AllocateValue(g, (void*)", ", TYPE_STRING);
|
||||||
jnp->Op = OP_CNC;
|
jnp->Op = OP_CNC;
|
||||||
@@ -456,13 +448,13 @@ bool JSONCOL::SetArrayOptions(PGLOBAL g, char *p, int i, PSZ nm)
|
|||||||
case '*': jnp->Op = OP_MULT; break;
|
case '*': jnp->Op = OP_MULT; break;
|
||||||
case '>': jnp->Op = OP_MAX; break;
|
case '>': jnp->Op = OP_MAX; break;
|
||||||
case '<': jnp->Op = OP_MIN; break;
|
case '<': jnp->Op = OP_MIN; break;
|
||||||
case '#': jnp->Op = OP_NUM; break;
|
|
||||||
case '!': jnp->Op = OP_SEP; break; // Average
|
case '!': jnp->Op = OP_SEP; break; // Average
|
||||||
|
case '#': jnp->Op = OP_NUM; break;
|
||||||
case 'x':
|
case 'x':
|
||||||
case 'X': // Expand this array
|
case 'X': // Expand this array
|
||||||
if (!Tjp->Xcol && nm) {
|
if (!Tjp->Xcol && nm) {
|
||||||
Xpd = true;
|
Xpd = true;
|
||||||
jnp->Op = OP_XX;
|
jnp->Op = OP_EXP;
|
||||||
Tjp->Xval = i;
|
Tjp->Xval = i;
|
||||||
Tjp->Xcol = nm;
|
Tjp->Xcol = nm;
|
||||||
} else if (CheckExpand(g, i, nm, true))
|
} else if (CheckExpand(g, i, nm, true))
|
||||||
@@ -490,6 +482,38 @@ bool JSONCOL::SetArrayOptions(PGLOBAL g, char *p, int i, PSZ nm)
|
|||||||
return true;
|
return true;
|
||||||
} // endif's
|
} // endif's
|
||||||
|
|
||||||
|
// For calculated arrays, a local Value must be used
|
||||||
|
switch (jnp->Op) {
|
||||||
|
case OP_NUM:
|
||||||
|
jnp->Valp = AllocateValue(g, TYPE_INT);
|
||||||
|
break;
|
||||||
|
case OP_ADD:
|
||||||
|
case OP_MULT:
|
||||||
|
case OP_SEP:
|
||||||
|
if (!IsTypeChar(Buf_Type))
|
||||||
|
jnp->Valp = AllocateValue(g, Buf_Type, 0, GetPrecision());
|
||||||
|
else
|
||||||
|
jnp->Valp = AllocateValue(g, TYPE_DOUBLE);
|
||||||
|
|
||||||
|
break;
|
||||||
|
case OP_MIN:
|
||||||
|
case OP_MAX:
|
||||||
|
jnp->Valp = AllocateValue(g, Buf_Type, Long, GetPrecision());
|
||||||
|
break;
|
||||||
|
case OP_CNC:
|
||||||
|
if (IsTypeChar(Buf_Type))
|
||||||
|
jnp->Valp = AllocateValue(g, TYPE_STRING, Long, GetPrecision());
|
||||||
|
else
|
||||||
|
jnp->Valp = AllocateValue(g, TYPE_STRING, 512);
|
||||||
|
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
} // endswitch Op
|
||||||
|
|
||||||
|
if (jnp->Valp)
|
||||||
|
MulVal = AllocateValue(g, jnp->Valp);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
} // end of SetArrayOptions
|
} // end of SetArrayOptions
|
||||||
|
|
||||||
@@ -533,6 +557,9 @@ bool JSONCOL::ParseJpath(PGLOBAL g)
|
|||||||
if (SetArrayOptions(g, p, i, Nodes[i-1].Key))
|
if (SetArrayOptions(g, p, i, Nodes[i-1].Key))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
} else if (*p == '*') {
|
||||||
|
// Return JSON
|
||||||
|
Nodes[i].Op = OP_XX;
|
||||||
} else {
|
} else {
|
||||||
Nodes[i].Key = p;
|
Nodes[i].Key = p;
|
||||||
Nodes[i].Op = OP_EXIST;
|
Nodes[i].Op = OP_EXIST;
|
||||||
@@ -545,60 +572,262 @@ bool JSONCOL::ParseJpath(PGLOBAL g)
|
|||||||
return false;
|
return false;
|
||||||
} // end of ParseJpath
|
} // end of ParseJpath
|
||||||
|
|
||||||
|
/***********************************************************************/
|
||||||
|
/* MakeJson: Serialize the json item and set value to it. */
|
||||||
|
/***********************************************************************/
|
||||||
|
PVAL JSONCOL::MakeJson(PGLOBAL g, PJSON jsp)
|
||||||
|
{
|
||||||
|
if (Value->IsTypeNum()) {
|
||||||
|
strcpy(g->Message, "Cannot make Json for a numeric column");
|
||||||
|
Value->Reset();
|
||||||
|
} else
|
||||||
|
Value->SetValue_psz(Serialize(g, jsp, NULL, 0));
|
||||||
|
|
||||||
|
return Value;
|
||||||
|
} // end of MakeJson
|
||||||
|
|
||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
/* SetValue: Set a value from a JVALUE contains. */
|
/* SetValue: Set a value from a JVALUE contains. */
|
||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
void JSONCOL::SetJsonValue(PGLOBAL g, PVAL vp, PJVAL val, int n)
|
void JSONCOL::SetJsonValue(PGLOBAL g, PVAL vp, PJVAL val, int n)
|
||||||
{
|
{
|
||||||
if (val) {
|
if (val) {
|
||||||
if (Nodes[n].Op == OP_NUM)
|
switch (val->GetValType()) {
|
||||||
vp->SetValue(1);
|
case TYPE_STRG:
|
||||||
else {
|
case TYPE_INTG:
|
||||||
again:
|
case TYPE_DBL:
|
||||||
switch (val->GetValType()) {
|
vp->SetValue_pval(val->GetValue());
|
||||||
case TYPE_STRG:
|
break;
|
||||||
case TYPE_INTG:
|
case TYPE_BOOL:
|
||||||
case TYPE_DBL:
|
if (vp->IsTypeNum())
|
||||||
vp->SetValue_pval(val->GetValue());
|
vp->SetValue(val->GetInteger() ? 1 : 0);
|
||||||
|
else
|
||||||
|
vp->SetValue_psz((PSZ)(val->GetInteger() ? "true" : "false"));
|
||||||
|
|
||||||
|
break;
|
||||||
|
case TYPE_JAR:
|
||||||
|
SetJsonValue(g, vp, val->GetArray()->GetValue(0), n);
|
||||||
|
break;
|
||||||
|
case TYPE_JOB:
|
||||||
|
// if (!vp->IsTypeNum() || !Strict) {
|
||||||
|
vp->SetValue_psz(val->GetObject()->GetText(g));
|
||||||
break;
|
break;
|
||||||
case TYPE_BOOL:
|
// } // endif Type
|
||||||
if (vp->IsTypeNum())
|
|
||||||
vp->SetValue(val->GetInteger() ? 1 : 0);
|
|
||||||
else
|
|
||||||
vp->SetValue_psz((PSZ)(val->GetInteger() ? "true" : "false"));
|
|
||||||
|
|
||||||
break;
|
default:
|
||||||
case TYPE_JAR:
|
vp->Reset();
|
||||||
val = val->GetArray()->GetValue(0);
|
} // endswitch Type
|
||||||
goto again;
|
|
||||||
case TYPE_JOB:
|
|
||||||
if (!vp->IsTypeNum()) {
|
|
||||||
vp->SetValue_psz(val->GetObject()->GetText(g));
|
|
||||||
break;
|
|
||||||
} // endif Type
|
|
||||||
|
|
||||||
default:
|
|
||||||
vp->Reset();
|
|
||||||
} // endswitch Type
|
|
||||||
|
|
||||||
} // endelse
|
|
||||||
|
|
||||||
} else
|
} else
|
||||||
vp->Reset();
|
vp->Reset();
|
||||||
|
|
||||||
} // end of SetJsonValue
|
} // end of SetJsonValue
|
||||||
|
|
||||||
|
/***********************************************************************/
|
||||||
|
/* ReadColumn: */
|
||||||
|
/***********************************************************************/
|
||||||
|
void JSONCOL::ReadColumn(PGLOBAL g)
|
||||||
|
{
|
||||||
|
if (!Tjp->SameRow || Xnod >= Tjp->SameRow)
|
||||||
|
Value->SetValue_pval(GetColumnValue(g, Tjp->Row, 0));
|
||||||
|
|
||||||
|
} // end of ReadColumn
|
||||||
|
|
||||||
|
/***********************************************************************/
|
||||||
|
/* GetColumnValue: */
|
||||||
|
/***********************************************************************/
|
||||||
|
PVAL JSONCOL::GetColumnValue(PGLOBAL g, PJSON row, int i)
|
||||||
|
{
|
||||||
|
int n = Nod - 1;
|
||||||
|
bool expd = false;
|
||||||
|
PJAR arp;
|
||||||
|
PJVAL val = NULL;
|
||||||
|
|
||||||
|
for (; i < Nod && row; i++) {
|
||||||
|
if (Nodes[i].Op == OP_NUM) {
|
||||||
|
Value->SetValue(row->GetType() == TYPE_JAR ? row->size() : 1);
|
||||||
|
return(Value);
|
||||||
|
} else if (Nodes[i].Op == OP_XX) {
|
||||||
|
return MakeJson(g, row);
|
||||||
|
} else switch (row->GetType()) {
|
||||||
|
case TYPE_JOB:
|
||||||
|
if (!Nodes[i].Key) {
|
||||||
|
// Expected Array was not there
|
||||||
|
if (i < Nod-1)
|
||||||
|
continue;
|
||||||
|
else
|
||||||
|
val = new(g) JVALUE(row);
|
||||||
|
|
||||||
|
} else
|
||||||
|
val = ((PJOB)row)->GetValue(Nodes[i].Key);
|
||||||
|
|
||||||
|
break;
|
||||||
|
case TYPE_JAR:
|
||||||
|
arp = (PJAR)row;
|
||||||
|
|
||||||
|
if (!Nodes[i].Key) {
|
||||||
|
if (Nodes[i].Op != OP_NULL) {
|
||||||
|
if (Nodes[i].Rank) {
|
||||||
|
val = arp->GetValue(Nodes[i].Rank - 1);
|
||||||
|
} else if (Nodes[i].Op == OP_EXP) {
|
||||||
|
return ExpandArray(g, arp, i);
|
||||||
|
} else
|
||||||
|
return CalculateArray(g, arp, i);
|
||||||
|
|
||||||
|
} else
|
||||||
|
val = NULL;
|
||||||
|
|
||||||
|
} else if (i < Nod-1) {
|
||||||
|
strcpy(g->Message, "Unexpected array");
|
||||||
|
val = NULL; // Not an expected array
|
||||||
|
} else
|
||||||
|
val = arp->GetValue(0);
|
||||||
|
|
||||||
|
break;
|
||||||
|
case TYPE_JVAL:
|
||||||
|
val = (PJVAL)row;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
sprintf(g->Message, "Invalid row JSON type %d", row->GetType());
|
||||||
|
val = NULL;
|
||||||
|
} // endswitch Type
|
||||||
|
|
||||||
|
if (i < Nod-1)
|
||||||
|
row = (val) ? val->GetJson() : NULL;
|
||||||
|
|
||||||
|
} // endfor i
|
||||||
|
|
||||||
|
SetJsonValue(g, Value, val, n);
|
||||||
|
return Value;
|
||||||
|
} // end of GetColumnValue
|
||||||
|
|
||||||
|
/***********************************************************************/
|
||||||
|
/* ExpandArray: */
|
||||||
|
/***********************************************************************/
|
||||||
|
PVAL JSONCOL::ExpandArray(PGLOBAL g, PJAR arp, int n)
|
||||||
|
{
|
||||||
|
int ars;
|
||||||
|
PJVAL jvp;
|
||||||
|
JVALUE jval;
|
||||||
|
|
||||||
|
ars = MY_MIN(Tjp->Limit, arp->size());
|
||||||
|
|
||||||
|
if (!(jvp = arp->GetValue(Nodes[n].Nx))) {
|
||||||
|
strcpy(g->Message, "Logical error expanding array");
|
||||||
|
longjmp(g->jumper[g->jump_level], 666);
|
||||||
|
} // endif jvp
|
||||||
|
|
||||||
|
if (n < Nod - 1 && jvp->GetJson()) {
|
||||||
|
jval.SetValue(GetColumnValue(g, jvp->GetJson(), n + 1));
|
||||||
|
jvp = &jval;
|
||||||
|
} // endif n
|
||||||
|
|
||||||
|
if (n >= Tjp->NextSame) {
|
||||||
|
if (++Nodes[n].Nx == ars) {
|
||||||
|
Nodes[n].Nx = 0;
|
||||||
|
Xnod = 0;
|
||||||
|
} else
|
||||||
|
Xnod = n;
|
||||||
|
|
||||||
|
Tjp->NextSame = Xnod;
|
||||||
|
} // endif NextSame
|
||||||
|
|
||||||
|
SetJsonValue(g, Value, jvp, n);
|
||||||
|
return Value;
|
||||||
|
} // end of ExpandArray
|
||||||
|
|
||||||
|
/***********************************************************************/
|
||||||
|
/* CalculateArray: */
|
||||||
|
/***********************************************************************/
|
||||||
|
PVAL JSONCOL::CalculateArray(PGLOBAL g, PJAR arp, int n)
|
||||||
|
{
|
||||||
|
int i, ars, nv = 0, nextsame = Tjp->NextSame;
|
||||||
|
bool err;
|
||||||
|
OPVAL op = Nodes[n].Op;
|
||||||
|
PVAL val[2], vp = Nodes[n].Valp;
|
||||||
|
PJVAL jvrp, jvp;
|
||||||
|
JVALUE jval;
|
||||||
|
|
||||||
|
vp->Reset();
|
||||||
|
ars = MY_MIN(Tjp->Limit, arp->size());
|
||||||
|
|
||||||
|
for (i = 0; i < ars; i++) {
|
||||||
|
jvrp = arp->GetValue(i);
|
||||||
|
|
||||||
|
do {
|
||||||
|
if (n < Nod - 1 && jvrp->GetJson()) {
|
||||||
|
Tjp->NextSame = nextsame;
|
||||||
|
jval.SetValue(GetColumnValue(g, jvrp->GetJson(), n + 1));
|
||||||
|
jvp = &jval;
|
||||||
|
} else
|
||||||
|
jvp = jvrp;
|
||||||
|
|
||||||
|
if (!nv++) {
|
||||||
|
SetJsonValue(g, vp, jvp, n);
|
||||||
|
continue;
|
||||||
|
} else
|
||||||
|
SetJsonValue(g, MulVal, jvp, n);
|
||||||
|
|
||||||
|
if (!MulVal->IsZero()) {
|
||||||
|
switch (op) {
|
||||||
|
case OP_CNC:
|
||||||
|
if (Nodes[n].CncVal) {
|
||||||
|
val[0] = Nodes[n].CncVal;
|
||||||
|
err = vp->Compute(g, val, 1, op);
|
||||||
|
} // endif CncVal
|
||||||
|
|
||||||
|
val[0] = MulVal;
|
||||||
|
err = vp->Compute(g, val, 1, op);
|
||||||
|
break;
|
||||||
|
// case OP_NUM:
|
||||||
|
case OP_SEP:
|
||||||
|
val[0] = Nodes[n].Valp;
|
||||||
|
val[1] = MulVal;
|
||||||
|
err = vp->Compute(g, val, 2, OP_ADD);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
val[0] = Nodes[n].Valp;
|
||||||
|
val[1] = MulVal;
|
||||||
|
err = vp->Compute(g, val, 2, op);
|
||||||
|
} // endswitch Op
|
||||||
|
|
||||||
|
if (err)
|
||||||
|
vp->Reset();
|
||||||
|
|
||||||
|
} // endif Zero
|
||||||
|
|
||||||
|
} while (Tjp->NextSame > nextsame);
|
||||||
|
|
||||||
|
} // endfor i
|
||||||
|
|
||||||
|
if (op == OP_SEP) {
|
||||||
|
// Calculate average
|
||||||
|
MulVal->SetValue(nv);
|
||||||
|
val[0] = vp;
|
||||||
|
val[1] = MulVal;
|
||||||
|
|
||||||
|
if (vp->Compute(g, val, 2, OP_DIV))
|
||||||
|
vp->Reset();
|
||||||
|
|
||||||
|
} // endif Op
|
||||||
|
|
||||||
|
Tjp->NextSame = nextsame;
|
||||||
|
return vp;
|
||||||
|
} // end of CalculateArray
|
||||||
|
|
||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
/* GetRow: Get the object containing this column. */
|
/* GetRow: Get the object containing this column. */
|
||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
PJSON JSONCOL::GetRow(PGLOBAL g, int mode)
|
PJSON JSONCOL::GetRow(PGLOBAL g)
|
||||||
{
|
{
|
||||||
PJVAL val;
|
PJVAL val;
|
||||||
PJAR arp;
|
PJAR arp;
|
||||||
PJSON nwr, row = Tjp->Row;
|
PJSON nwr, row = Tjp->Row;
|
||||||
|
|
||||||
for (int i = 0; i < Nod-1 && row; i++) {
|
for (int i = 0; i < Nod-1 && row; i++) {
|
||||||
switch (row->GetType()) {
|
if (Nodes[i+1].Op == OP_XX)
|
||||||
|
break;
|
||||||
|
else switch (row->GetType()) {
|
||||||
case TYPE_JOB:
|
case TYPE_JOB:
|
||||||
if (!Nodes[i].Key)
|
if (!Nodes[i].Key)
|
||||||
// Expected Array was not there
|
// Expected Array was not there
|
||||||
@@ -609,20 +838,12 @@ PJSON JSONCOL::GetRow(PGLOBAL g, int mode)
|
|||||||
case TYPE_JAR:
|
case TYPE_JAR:
|
||||||
if (!Nodes[i].Key) {
|
if (!Nodes[i].Key) {
|
||||||
if (Nodes[i].Op != OP_NULL) {
|
if (Nodes[i].Op != OP_NULL) {
|
||||||
Ival = i;
|
|
||||||
arp = (PJAR)row;
|
arp = (PJAR)row;
|
||||||
|
|
||||||
if (mode < 2) // First pass
|
if (Nodes[i].Rank)
|
||||||
Arp = arp;
|
val = arp->GetValue(Nodes[i].Rank - 1);
|
||||||
|
else
|
||||||
if (Nodes[i].Op != OP_XX) {
|
val = arp->GetValue(Nodes[i].Nx);
|
||||||
if (Nodes[i].Rank)
|
|
||||||
val = arp->GetValue(Nodes[i].Rank - 1);
|
|
||||||
else
|
|
||||||
val = arp->GetValue(arp == Arp ? Nx : 0);
|
|
||||||
|
|
||||||
} else
|
|
||||||
val = arp->GetValue(Tjp->SameRow);
|
|
||||||
|
|
||||||
} else
|
} else
|
||||||
val = NULL;
|
val = NULL;
|
||||||
@@ -643,15 +864,16 @@ PJSON JSONCOL::GetRow(PGLOBAL g, int mode)
|
|||||||
|
|
||||||
if (val) {
|
if (val) {
|
||||||
row = val->GetJson();
|
row = val->GetJson();
|
||||||
} else if (mode == 1) { // mode write
|
} else {
|
||||||
// Construct missing objects
|
// Construct missing objects
|
||||||
for (i++; row && i < Nod; i++) {
|
for (i++; row && i < Nod; i++) {
|
||||||
if (!Nodes[i].Key) {
|
if (Nodes[i].Op == OP_XX)
|
||||||
|
break;
|
||||||
|
else if (!Nodes[i].Key)
|
||||||
// Construct intermediate array
|
// Construct intermediate array
|
||||||
nwr = new(g) JARRAY;
|
nwr = new(g) JARRAY;
|
||||||
} else {
|
else
|
||||||
nwr = new(g) JOBJECT;
|
nwr = new(g) JOBJECT;
|
||||||
} // endif Nodes
|
|
||||||
|
|
||||||
if (row->GetType() == TYPE_JOB) {
|
if (row->GetType() == TYPE_JOB) {
|
||||||
((PJOB)row)->SetValue(g, new(g) JVALUE(nwr), Nodes[i-1].Key);
|
((PJOB)row)->SetValue(g, new(g) JVALUE(nwr), Nodes[i-1].Key);
|
||||||
@@ -667,139 +889,13 @@ PJSON JSONCOL::GetRow(PGLOBAL g, int mode)
|
|||||||
} // endfor i
|
} // endfor i
|
||||||
|
|
||||||
break;
|
break;
|
||||||
} else
|
} // endelse
|
||||||
row = NULL;
|
|
||||||
|
|
||||||
} // endfor i
|
} // endfor i
|
||||||
|
|
||||||
return row;
|
return row;
|
||||||
} // end of GetRow
|
} // end of GetRow
|
||||||
|
|
||||||
/***********************************************************************/
|
|
||||||
/* ReadColumn: */
|
|
||||||
/***********************************************************************/
|
|
||||||
void JSONCOL::ReadColumn(PGLOBAL g)
|
|
||||||
{
|
|
||||||
int mode = 0, n = Nod - 1;
|
|
||||||
PJSON row;
|
|
||||||
PJVAL val = NULL;
|
|
||||||
|
|
||||||
evenmore:
|
|
||||||
row = GetRow(g, mode);
|
|
||||||
|
|
||||||
more:
|
|
||||||
if (row) switch (row->GetType()) {
|
|
||||||
case TYPE_JOB:
|
|
||||||
if (Nodes[n].Key)
|
|
||||||
val = row->GetValue(Nodes[n].Key);
|
|
||||||
else
|
|
||||||
val = new(g) JVALUE(row);
|
|
||||||
|
|
||||||
break;
|
|
||||||
case TYPE_JAR:
|
|
||||||
// Multiple column ?
|
|
||||||
if (Nodes[n].Op != OP_NULL) {
|
|
||||||
Arp = (PJAR)row;
|
|
||||||
val = Arp->GetValue(Nodes[n].Rank > 0 ?
|
|
||||||
Nodes[n].Rank - 1 :
|
|
||||||
Nodes[n].Op == OP_XX ? Tjp->SameRow : Nx);
|
|
||||||
Ival = n;
|
|
||||||
} else
|
|
||||||
val = NULL;
|
|
||||||
|
|
||||||
break;
|
|
||||||
case TYPE_JVAL:
|
|
||||||
val = (PJVAL)row;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
sprintf(g->Message, "Wrong return value type %d", row->GetType());
|
|
||||||
Value->Reset();
|
|
||||||
return;
|
|
||||||
} // endswitch Type
|
|
||||||
|
|
||||||
if (!Nx /*|| (Xpd)*/)
|
|
||||||
SetJsonValue(g, Value, val, n);
|
|
||||||
|
|
||||||
if (Arp) {
|
|
||||||
// Multiple column
|
|
||||||
int ars = (Nodes[Ival].Rank > 0) ? 1 : MY_MIN(Tjp->Limit, Arp->size());
|
|
||||||
|
|
||||||
if (Nodes[Ival].Op == OP_XX) {
|
|
||||||
if (ars > Tjp->SameRow + 1)
|
|
||||||
Tjp->NextSame = true; // More to come
|
|
||||||
else {
|
|
||||||
Tjp->NextSame = false;
|
|
||||||
Arp = NULL;
|
|
||||||
} // endelse
|
|
||||||
|
|
||||||
} else {
|
|
||||||
if (Nx && val) {
|
|
||||||
SetJsonValue(g, MulVal, val, Ival);
|
|
||||||
|
|
||||||
if (!MulVal->IsZero()) {
|
|
||||||
PVAL val[2];
|
|
||||||
bool err;
|
|
||||||
|
|
||||||
switch (Nodes[Ival].Op) {
|
|
||||||
case OP_CNC:
|
|
||||||
if (Nodes[Ival].CncVal) {
|
|
||||||
val[0] = Nodes[Ival].CncVal;
|
|
||||||
err = Value->Compute(g, val, 1, Nodes[Ival].Op);
|
|
||||||
} // endif CncVal
|
|
||||||
|
|
||||||
val[0] = MulVal;
|
|
||||||
err = Value->Compute(g, val, 1, Nodes[Ival].Op);
|
|
||||||
break;
|
|
||||||
case OP_NUM:
|
|
||||||
case OP_SEP:
|
|
||||||
val[0] = Value;
|
|
||||||
val[1] = MulVal;
|
|
||||||
err = Value->Compute(g, val, 2, OP_ADD);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
val[0] = Value;
|
|
||||||
val[1] = MulVal;
|
|
||||||
err = Value->Compute(g, val, 2, Nodes[Ival].Op);
|
|
||||||
} // endswitch Op
|
|
||||||
|
|
||||||
if (err)
|
|
||||||
Value->Reset();
|
|
||||||
|
|
||||||
} // endif Zero
|
|
||||||
|
|
||||||
} // endif Nx
|
|
||||||
|
|
||||||
if (ars > ++Nx) {
|
|
||||||
if (Ival != n) {
|
|
||||||
mode = 2;
|
|
||||||
goto evenmore;
|
|
||||||
} else
|
|
||||||
goto more;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
if (Nodes[Ival].Op == OP_SEP) {
|
|
||||||
// Calculate average
|
|
||||||
PVAL val[2];
|
|
||||||
|
|
||||||
MulVal->SetValue(ars);
|
|
||||||
val[0] = Value;
|
|
||||||
val[1] = MulVal;
|
|
||||||
|
|
||||||
if (Value->Compute(g, val, 2, OP_DIV))
|
|
||||||
Value->Reset();
|
|
||||||
|
|
||||||
} // endif Op
|
|
||||||
|
|
||||||
Arp = NULL;
|
|
||||||
Nx = 0;
|
|
||||||
} // endif ars
|
|
||||||
|
|
||||||
} // endif Op
|
|
||||||
|
|
||||||
} // endif Arp
|
|
||||||
|
|
||||||
} // end of ReadColumn
|
|
||||||
|
|
||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
/* WriteColumn: */
|
/* WriteColumn: */
|
||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
@@ -817,10 +913,11 @@ void JSONCOL::WriteColumn(PGLOBAL g)
|
|||||||
if (Value->IsNull() && Tjp->Mode == MODE_INSERT)
|
if (Value->IsNull() && Tjp->Mode == MODE_INSERT)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
char *s;
|
||||||
PJOB objp = NULL;
|
PJOB objp = NULL;
|
||||||
PJAR arp = NULL;
|
PJAR arp = NULL;
|
||||||
PJVAL jvp = NULL;
|
PJVAL jvp = NULL;
|
||||||
PJSON row = GetRow(g, 1);
|
PJSON jsp, row = GetRow(g);
|
||||||
JTYP type = row->GetType();
|
JTYP type = row->GetType();
|
||||||
|
|
||||||
switch (row->GetType()) {
|
switch (row->GetType()) {
|
||||||
@@ -832,6 +929,32 @@ void JSONCOL::WriteColumn(PGLOBAL g)
|
|||||||
|
|
||||||
if (row) switch (Buf_Type) {
|
if (row) switch (Buf_Type) {
|
||||||
case TYPE_STRING:
|
case TYPE_STRING:
|
||||||
|
if (Nodes[Nod-1].Op == OP_XX) {
|
||||||
|
s = Value->GetCharValue();
|
||||||
|
|
||||||
|
if (!(jsp = ParseJson(g, s, (int)strlen(s), 0))) {
|
||||||
|
strcpy(g->Message, s);
|
||||||
|
longjmp(g->jumper[g->jump_level], 666);
|
||||||
|
} // endif jsp
|
||||||
|
|
||||||
|
if (arp) {
|
||||||
|
if (Nod > 1 && Nodes[Nod-2].Rank)
|
||||||
|
arp->SetValue(g, new(g) JVALUE(jsp), Nodes[Nod-2].Rank-1);
|
||||||
|
else
|
||||||
|
arp->AddValue(g, new(g) JVALUE(jsp));
|
||||||
|
|
||||||
|
arp->InitArray(g);
|
||||||
|
} else if (objp) {
|
||||||
|
if (Nod > 1 && Nodes[Nod-2].Key)
|
||||||
|
objp->SetValue(g, new(g) JVALUE(jsp), Nodes[Nod-2].Key);
|
||||||
|
|
||||||
|
} else if (jvp)
|
||||||
|
jvp->SetValue(jsp);
|
||||||
|
|
||||||
|
break;
|
||||||
|
} // endif Op
|
||||||
|
|
||||||
|
// Passthru
|
||||||
case TYPE_DATE:
|
case TYPE_DATE:
|
||||||
case TYPE_INT:
|
case TYPE_INT:
|
||||||
case TYPE_DOUBLE:
|
case TYPE_DOUBLE:
|
||||||
@@ -1175,11 +1298,6 @@ bool TDBJSON::OpenDB(PGLOBAL g)
|
|||||||
/*******************************************************************/
|
/*******************************************************************/
|
||||||
/* Table already open replace it at its beginning. */
|
/* Table already open replace it at its beginning. */
|
||||||
/*******************************************************************/
|
/*******************************************************************/
|
||||||
for (PJCOL cp = (PJCOL)Columns; cp; cp = (PJCOL)cp->GetNext()) {
|
|
||||||
cp->Nx = 0;
|
|
||||||
cp->Arp = NULL;
|
|
||||||
} // endfor cp
|
|
||||||
|
|
||||||
Fpos= -1;
|
Fpos= -1;
|
||||||
Spos = 0;
|
Spos = 0;
|
||||||
NextSame = false;
|
NextSame = false;
|
||||||
@@ -1217,7 +1335,8 @@ int TDBJSON::ReadDB(PGLOBAL g)
|
|||||||
N++;
|
N++;
|
||||||
|
|
||||||
if (NextSame) {
|
if (NextSame) {
|
||||||
SameRow++;
|
SameRow = NextSame;
|
||||||
|
NextSame = false;
|
||||||
rc = RC_OK;
|
rc = RC_OK;
|
||||||
} else if (++Fpos < (signed)Doc->size()) {
|
} else if (++Fpos < (signed)Doc->size()) {
|
||||||
Row = Doc->GetValue(Fpos);
|
Row = Doc->GetValue(Fpos);
|
||||||
@@ -1257,9 +1376,10 @@ int TDBJSON::WriteDB(PGLOBAL g)
|
|||||||
return RC_FX;
|
return RC_FX;
|
||||||
|
|
||||||
} else { // if (Jmode == MODE_VALUE)
|
} else { // if (Jmode == MODE_VALUE)
|
||||||
if (Mode == MODE_INSERT)
|
if (Mode == MODE_INSERT) {
|
||||||
Doc->AddValue(g, (PJVAL)Row);
|
Doc->AddValue(g, (PJVAL)Row);
|
||||||
else if (Doc->SetValue(g, (PJVAL)Row, Fpos))
|
Row = new(g) JVALUE;
|
||||||
|
} else if (Doc->SetValue(g, (PJVAL)Row, Fpos))
|
||||||
return RC_FX;
|
return RC_FX;
|
||||||
|
|
||||||
} // endif Jmode
|
} // endif Jmode
|
||||||
|
@@ -16,8 +16,6 @@ typedef class JSONDEF *PJDEF;
|
|||||||
typedef class TDBJSON *PJTDB;
|
typedef class TDBJSON *PJTDB;
|
||||||
typedef class JSONCOL *PJCOL;
|
typedef class JSONCOL *PJCOL;
|
||||||
|
|
||||||
class TDBJSN;
|
|
||||||
|
|
||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
/* The JSON tree node. Can be an Object or an Array. */
|
/* The JSON tree node. Can be an Object or an Array. */
|
||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
@@ -25,7 +23,9 @@ typedef struct _jnode {
|
|||||||
PSZ Key; // The key used for object
|
PSZ Key; // The key used for object
|
||||||
OPVAL Op; // Operator used for this node
|
OPVAL Op; // Operator used for this node
|
||||||
PVAL CncVal; // To cont value used for OP_CNC
|
PVAL CncVal; // To cont value used for OP_CNC
|
||||||
|
PVAL Valp; // The internal array VALUE
|
||||||
int Rank; // The rank in array
|
int Rank; // The rank in array
|
||||||
|
int Nx; // Same row number
|
||||||
} JNODE, *PJNODE;
|
} JNODE, *PJNODE;
|
||||||
|
|
||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
@@ -77,7 +77,7 @@ class TDBJSN : public TDBDOS {
|
|||||||
virtual PTDB CopyOne(PTABS t);
|
virtual PTDB CopyOne(PTABS t);
|
||||||
virtual PCOL MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n);
|
virtual PCOL MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n);
|
||||||
virtual PCOL InsertSpecialColumn(PGLOBAL g, PCOL colp);
|
virtual PCOL InsertSpecialColumn(PGLOBAL g, PCOL colp);
|
||||||
virtual int RowNumber(PGLOBAL g, BOOL b = FALSE)
|
virtual int RowNumber(PGLOBAL g, bool b = FALSE)
|
||||||
{return (b) ? N : Fpos + 1;}
|
{return (b) ? N : Fpos + 1;}
|
||||||
|
|
||||||
// Database routines
|
// Database routines
|
||||||
@@ -98,11 +98,11 @@ class TDBJSN : public TDBDOS {
|
|||||||
int N; // The current Rownum
|
int N; // The current Rownum
|
||||||
int Limit; // Limit of multiple values
|
int Limit; // Limit of multiple values
|
||||||
int Pretty; // Depends on file structure
|
int Pretty; // Depends on file structure
|
||||||
bool Strict; // Strict syntax checking
|
int NextSame; // Same next row
|
||||||
bool NextSame; // Same next row
|
|
||||||
bool Comma; // Row has final comma
|
|
||||||
int SameRow; // Same row nb
|
int SameRow; // Same row nb
|
||||||
int Xval; // Index of expandable array
|
int Xval; // Index of expandable array
|
||||||
|
bool Strict; // Strict syntax checking
|
||||||
|
bool Comma; // Row has final comma
|
||||||
}; // end of class TDBJSN
|
}; // end of class TDBJSN
|
||||||
|
|
||||||
/* -------------------------- JSONCOL class -------------------------- */
|
/* -------------------------- JSONCOL class -------------------------- */
|
||||||
@@ -130,8 +130,12 @@ class JSONCOL : public DOSCOL {
|
|||||||
protected:
|
protected:
|
||||||
bool CheckExpand(PGLOBAL g, int i, PSZ nm, bool b);
|
bool CheckExpand(PGLOBAL g, int i, PSZ nm, bool b);
|
||||||
bool SetArrayOptions(PGLOBAL g, char *p, int i, PSZ nm);
|
bool SetArrayOptions(PGLOBAL g, char *p, int i, PSZ nm);
|
||||||
PJSON GetRow(PGLOBAL g, int mode);
|
PVAL GetColumnValue(PGLOBAL g, PJSON row, int i);
|
||||||
|
PVAL ExpandArray(PGLOBAL g, PJAR arp, int n);
|
||||||
|
PVAL CalculateArray(PGLOBAL g, PJAR arp, int n);
|
||||||
|
PVAL MakeJson(PGLOBAL g, PJSON jsp);
|
||||||
void SetJsonValue(PGLOBAL g, PVAL vp, PJVAL val, int n);
|
void SetJsonValue(PGLOBAL g, PVAL vp, PJVAL val, int n);
|
||||||
|
PJSON GetRow(PGLOBAL g);
|
||||||
|
|
||||||
// Default constructor not to be used
|
// Default constructor not to be used
|
||||||
JSONCOL(void) {}
|
JSONCOL(void) {}
|
||||||
@@ -139,12 +143,10 @@ class JSONCOL : public DOSCOL {
|
|||||||
// Members
|
// Members
|
||||||
TDBJSN *Tjp; // To the JSN table block
|
TDBJSN *Tjp; // To the JSN table block
|
||||||
PVAL MulVal; // To value used by multiple column
|
PVAL MulVal; // To value used by multiple column
|
||||||
PJAR Arp; // The intermediate array
|
|
||||||
char *Jpath; // The json path
|
char *Jpath; // The json path
|
||||||
JNODE *Nodes ; // The intermediate objects
|
JNODE *Nodes; // The intermediate objects
|
||||||
int Nod; // The number of intermediate objects
|
int Nod; // The number of intermediate objects
|
||||||
int Ival; // Index of multiple values
|
int Xnod; // Index of multiple values
|
||||||
int Nx; // The last read sub-row
|
|
||||||
bool Xpd; // True for expandable column
|
bool Xpd; // True for expandable column
|
||||||
bool Parsed; // True when parsed
|
bool Parsed; // True when parsed
|
||||||
}; // end of class JSONCOL
|
}; // end of class JSONCOL
|
||||||
|
@@ -1141,19 +1141,16 @@ int TDBMYSQL::WriteDB(PGLOBAL g)
|
|||||||
int rc;
|
int rc;
|
||||||
uint len = Query->GetLength();
|
uint len = Query->GetLength();
|
||||||
char buf[64];
|
char buf[64];
|
||||||
bool b, oom = false;
|
bool oom = false;
|
||||||
|
|
||||||
// Make the Insert command value list
|
// Make the Insert command value list
|
||||||
for (PCOL colp = Columns; colp; colp = colp->GetNext()) {
|
for (PCOL colp = Columns; colp; colp = colp->GetNext()) {
|
||||||
if (!colp->GetValue()->IsNull()) {
|
if (!colp->GetValue()->IsNull()) {
|
||||||
if ((b = colp->GetResultType() == TYPE_STRING ||
|
if (colp->GetResultType() == TYPE_STRING ||
|
||||||
colp->GetResultType() == TYPE_DATE))
|
colp->GetResultType() == TYPE_DATE)
|
||||||
oom |= Query->Append('\'');
|
oom |= Query->Append_quoted(colp->GetValue()->GetCharString(buf));
|
||||||
|
else
|
||||||
oom |= Query->Append(colp->GetValue()->GetCharString(buf));
|
oom |= Query->Append(colp->GetValue()->GetCharString(buf));
|
||||||
|
|
||||||
if (b)
|
|
||||||
oom |= Query->Append('\'');
|
|
||||||
|
|
||||||
} else
|
} else
|
||||||
oom |= Query->Append("NULL");
|
oom |= Query->Append("NULL");
|
||||||
|
@@ -355,7 +355,7 @@ bool TDBOCCUR::MakeColumnList(PGLOBAL g)
|
|||||||
|
|
||||||
for (colp = Columns; colp; colp = colp->GetNext())
|
for (colp = Columns; colp; colp = colp->GetNext())
|
||||||
if (colp->GetAmType() == TYPE_AM_PRX)
|
if (colp->GetAmType() == TYPE_AM_PRX)
|
||||||
if (((PPRXCOL)colp)->Init(g))
|
if (((PPRXCOL)colp)->Init(g, NULL))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
Col = (PCOL*)PlugSubAlloc(g, NULL, Mult * sizeof(PCOL));
|
Col = (PCOL*)PlugSubAlloc(g, NULL, Mult * sizeof(PCOL));
|
||||||
|
@@ -66,8 +66,8 @@
|
|||||||
#include "plgdbsem.h"
|
#include "plgdbsem.h"
|
||||||
#include "mycat.h"
|
#include "mycat.h"
|
||||||
#include "xtable.h"
|
#include "xtable.h"
|
||||||
#include "tabodbc.h"
|
|
||||||
#include "odbccat.h"
|
#include "odbccat.h"
|
||||||
|
#include "tabodbc.h"
|
||||||
#include "tabmul.h"
|
#include "tabmul.h"
|
||||||
#include "reldef.h"
|
#include "reldef.h"
|
||||||
#include "tabcol.h"
|
#include "tabcol.h"
|
||||||
@@ -93,9 +93,10 @@ bool ExactInfo(void);
|
|||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
ODBCDEF::ODBCDEF(void)
|
ODBCDEF::ODBCDEF(void)
|
||||||
{
|
{
|
||||||
Connect= Tabname= Tabschema= Tabcat= Srcdef= Qchar= Qrystr= Sep= NULL;
|
Connect = Tabname = Tabschema = Username = Password = NULL;
|
||||||
|
Tabcat = Srcdef = Qchar = Qrystr = Sep = NULL;
|
||||||
Catver = Options = Cto = Qto = Quoted = Maxerr = Maxres = 0;
|
Catver = Options = Cto = Qto = Quoted = Maxerr = Maxres = 0;
|
||||||
Scrollable = Memory = Xsrc = false;
|
Scrollable = Memory = Xsrc = UseCnc = false;
|
||||||
} // end of ODBCDEF constructor
|
} // end of ODBCDEF constructor
|
||||||
|
|
||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
@@ -117,6 +118,8 @@ bool ODBCDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
|
|||||||
Tabschema = GetStringCatInfo(g, "Schema", Tabschema);
|
Tabschema = GetStringCatInfo(g, "Schema", Tabschema);
|
||||||
Tabcat = GetStringCatInfo(g, "Qualifier", NULL);
|
Tabcat = GetStringCatInfo(g, "Qualifier", NULL);
|
||||||
Tabcat = GetStringCatInfo(g, "Catalog", Tabcat);
|
Tabcat = GetStringCatInfo(g, "Catalog", Tabcat);
|
||||||
|
Username = GetStringCatInfo(g, "User", NULL);
|
||||||
|
Password = GetStringCatInfo(g, "Password", NULL);
|
||||||
|
|
||||||
if ((Srcdef = GetStringCatInfo(g, "Srcdef", NULL)))
|
if ((Srcdef = GetStringCatInfo(g, "Srcdef", NULL)))
|
||||||
Read_Only = true;
|
Read_Only = true;
|
||||||
@@ -133,6 +136,7 @@ bool ODBCDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
|
|||||||
Cto= GetIntCatInfo("ConnectTimeout", DEFAULT_LOGIN_TIMEOUT);
|
Cto= GetIntCatInfo("ConnectTimeout", DEFAULT_LOGIN_TIMEOUT);
|
||||||
Qto= GetIntCatInfo("QueryTimeout", DEFAULT_QUERY_TIMEOUT);
|
Qto= GetIntCatInfo("QueryTimeout", DEFAULT_QUERY_TIMEOUT);
|
||||||
Scrollable = GetBoolCatInfo("Scrollable", false);
|
Scrollable = GetBoolCatInfo("Scrollable", false);
|
||||||
|
UseCnc = GetBoolCatInfo("UseDSN", false);
|
||||||
Memory = GetBoolCatInfo("Memory", false);
|
Memory = GetBoolCatInfo("Memory", false);
|
||||||
Pseudo = 2; // FILID is Ok but not ROWID
|
Pseudo = 2; // FILID is Ok but not ROWID
|
||||||
return false;
|
return false;
|
||||||
@@ -190,34 +194,40 @@ TDBODBC::TDBODBC(PODEF tdp) : TDBASE(tdp)
|
|||||||
Connect = tdp->Connect;
|
Connect = tdp->Connect;
|
||||||
TableName = tdp->Tabname;
|
TableName = tdp->Tabname;
|
||||||
Schema = tdp->Tabschema;
|
Schema = tdp->Tabschema;
|
||||||
|
Ops.User = tdp->Username;
|
||||||
|
Ops.Pwd = tdp->Password;
|
||||||
Catalog = tdp->Tabcat;
|
Catalog = tdp->Tabcat;
|
||||||
Srcdef = tdp->Srcdef;
|
Srcdef = tdp->Srcdef;
|
||||||
Qrystr = tdp->Qrystr;
|
Qrystr = tdp->Qrystr;
|
||||||
Sep = tdp->GetSep();
|
Sep = tdp->GetSep();
|
||||||
Options = tdp->Options;
|
Options = tdp->Options;
|
||||||
Cto = tdp->Cto;
|
Ops.Cto = tdp->Cto;
|
||||||
Qto = tdp->Qto;
|
Ops.Qto = tdp->Qto;
|
||||||
Quoted = MY_MAX(0, tdp->GetQuoted());
|
Quoted = MY_MAX(0, tdp->GetQuoted());
|
||||||
Rows = tdp->GetElemt();
|
Rows = tdp->GetElemt();
|
||||||
Catver = tdp->Catver;
|
Catver = tdp->Catver;
|
||||||
Memory = (tdp->Memory) ? 1 : 0;
|
Memory = (tdp->Memory) ? 1 : 0;
|
||||||
Scrollable = tdp->Scrollable;
|
Scrollable = tdp->Scrollable;
|
||||||
|
Ops.UseCnc = tdp->UseCnc;
|
||||||
} else {
|
} else {
|
||||||
Connect = NULL;
|
Connect = NULL;
|
||||||
TableName = NULL;
|
TableName = NULL;
|
||||||
Schema = NULL;
|
Schema = NULL;
|
||||||
|
Ops.User = NULL;
|
||||||
|
Ops.Pwd = NULL;
|
||||||
Catalog = NULL;
|
Catalog = NULL;
|
||||||
Srcdef = NULL;
|
Srcdef = NULL;
|
||||||
Qrystr = NULL;
|
Qrystr = NULL;
|
||||||
Sep = 0;
|
Sep = 0;
|
||||||
Options = 0;
|
Options = 0;
|
||||||
Cto = DEFAULT_LOGIN_TIMEOUT;
|
Ops.Cto = DEFAULT_LOGIN_TIMEOUT;
|
||||||
Qto = DEFAULT_QUERY_TIMEOUT;
|
Ops.Qto = DEFAULT_QUERY_TIMEOUT;
|
||||||
Quoted = 0;
|
Quoted = 0;
|
||||||
Rows = 0;
|
Rows = 0;
|
||||||
Catver = 0;
|
Catver = 0;
|
||||||
Memory = 0;
|
Memory = 0;
|
||||||
Scrollable = false;
|
Scrollable = false;
|
||||||
|
Ops.UseCnc = false;
|
||||||
} // endif tdp
|
} // endif tdp
|
||||||
|
|
||||||
Quote = NULL;
|
Quote = NULL;
|
||||||
@@ -242,6 +252,7 @@ TDBODBC::TDBODBC(PTDBODBC tdbp) : TDBASE(tdbp)
|
|||||||
Connect = tdbp->Connect;
|
Connect = tdbp->Connect;
|
||||||
TableName = tdbp->TableName;
|
TableName = tdbp->TableName;
|
||||||
Schema = tdbp->Schema;
|
Schema = tdbp->Schema;
|
||||||
|
Ops = tdbp->Ops;
|
||||||
Catalog = tdbp->Catalog;
|
Catalog = tdbp->Catalog;
|
||||||
Srcdef = tdbp->Srcdef;
|
Srcdef = tdbp->Srcdef;
|
||||||
Qrystr = tdbp->Qrystr;
|
Qrystr = tdbp->Qrystr;
|
||||||
@@ -254,8 +265,6 @@ TDBODBC::TDBODBC(PTDBODBC tdbp) : TDBASE(tdbp)
|
|||||||
MulConn = tdbp->MulConn;
|
MulConn = tdbp->MulConn;
|
||||||
DBQ = tdbp->DBQ;
|
DBQ = tdbp->DBQ;
|
||||||
Options = tdbp->Options;
|
Options = tdbp->Options;
|
||||||
Cto = tdbp->Cto;
|
|
||||||
Qto = tdbp->Qto;
|
|
||||||
Quoted = tdbp->Quoted;
|
Quoted = tdbp->Quoted;
|
||||||
Rows = tdbp->Rows;
|
Rows = tdbp->Rows;
|
||||||
Fpos = tdbp->Fpos;
|
Fpos = tdbp->Fpos;
|
||||||
@@ -370,7 +379,7 @@ int TDBODBC::Decode(char *txt, char *buf, size_t n)
|
|||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
char *TDBODBC::MakeSQL(PGLOBAL g, bool cnt)
|
char *TDBODBC::MakeSQL(PGLOBAL g, bool cnt)
|
||||||
{
|
{
|
||||||
char *colist, *tabname, *sql, buf[64];
|
char *colist, *tabname, *sql, buf[NAM_LEN * 3];
|
||||||
LPCSTR schmp = NULL, catp = NULL;
|
LPCSTR schmp = NULL, catp = NULL;
|
||||||
int len, ncol = 0;
|
int len, ncol = 0;
|
||||||
bool first = true;
|
bool first = true;
|
||||||
@@ -475,6 +484,9 @@ char *TDBODBC::MakeSQL(PGLOBAL g, bool cnt)
|
|||||||
if (To_CondFil)
|
if (To_CondFil)
|
||||||
strcat(strcat(sql, " WHERE "), To_CondFil->Body);
|
strcat(strcat(sql, " WHERE "), To_CondFil->Body);
|
||||||
|
|
||||||
|
if (trace)
|
||||||
|
htrc("sql: '%s'\n", sql);
|
||||||
|
|
||||||
return sql;
|
return sql;
|
||||||
} // end of MakeSQL
|
} // end of MakeSQL
|
||||||
|
|
||||||
@@ -483,7 +495,7 @@ char *TDBODBC::MakeSQL(PGLOBAL g, bool cnt)
|
|||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
char *TDBODBC::MakeInsert(PGLOBAL g)
|
char *TDBODBC::MakeInsert(PGLOBAL g)
|
||||||
{
|
{
|
||||||
char *stmt, *colist, *valist;
|
char *stmt, *colist, *valist, buf[NAM_LEN * 3];
|
||||||
// char *tk = "`";
|
// char *tk = "`";
|
||||||
int len = 0;
|
int len = 0;
|
||||||
bool b = FALSE;
|
bool b = FALSE;
|
||||||
@@ -510,10 +522,13 @@ char *TDBODBC::MakeInsert(PGLOBAL g)
|
|||||||
} else
|
} else
|
||||||
b = true;
|
b = true;
|
||||||
|
|
||||||
|
// Column name can be in UTF-8 encoding
|
||||||
|
Decode(colp->GetName(), buf, sizeof(buf));
|
||||||
|
|
||||||
if (Quote)
|
if (Quote)
|
||||||
strcat(strcat(strcat(colist, Quote), colp->GetName()), Quote);
|
strcat(strcat(strcat(colist, Quote), buf), Quote);
|
||||||
else
|
else
|
||||||
strcat(colist, colp->GetName());
|
strcat(colist, buf);
|
||||||
|
|
||||||
strcat(valist, "?"); // Parameter marker
|
strcat(valist, "?"); // Parameter marker
|
||||||
} // endfor colp
|
} // endfor colp
|
||||||
@@ -558,8 +573,7 @@ bool TDBODBC::BindParameters(PGLOBAL g)
|
|||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
char *TDBODBC::MakeCommand(PGLOBAL g)
|
char *TDBODBC::MakeCommand(PGLOBAL g)
|
||||||
{
|
{
|
||||||
char *p, name[68], *qc = Ocp->GetQuoteChar();
|
char *p, *stmt, name[68], *body = NULL, *qc = Ocp->GetQuoteChar();
|
||||||
char *stmt = (char*)PlugSubAlloc(g, NULL, strlen(Qrystr) + 64);
|
|
||||||
char *qrystr = (char*)PlugSubAlloc(g, NULL, strlen(Qrystr) + 1);
|
char *qrystr = (char*)PlugSubAlloc(g, NULL, strlen(Qrystr) + 1);
|
||||||
bool qtd = Quoted > 0;
|
bool qtd = Quoted > 0;
|
||||||
int i = 0, k = 0;
|
int i = 0, k = 0;
|
||||||
@@ -570,6 +584,15 @@ char *TDBODBC::MakeCommand(PGLOBAL g)
|
|||||||
qrystr[i] = (Qrystr[i] == '`') ? *qc : tolower(Qrystr[i]);
|
qrystr[i] = (Qrystr[i] == '`') ? *qc : tolower(Qrystr[i]);
|
||||||
} while (Qrystr[i++]);
|
} while (Qrystr[i++]);
|
||||||
|
|
||||||
|
if (To_CondFil && (p = strstr(qrystr, " where "))) {
|
||||||
|
p[7] = 0; // Remove where clause
|
||||||
|
Qrystr[(p - qrystr) + 7] = 0;
|
||||||
|
body = To_CondFil->Body;
|
||||||
|
stmt = (char*)PlugSubAlloc(g, NULL, strlen(qrystr)
|
||||||
|
+ strlen(body) + 64);
|
||||||
|
} else
|
||||||
|
stmt = (char*)PlugSubAlloc(g, NULL, strlen(Qrystr) + 64);
|
||||||
|
|
||||||
// Check whether the table name is equal to a keyword
|
// Check whether the table name is equal to a keyword
|
||||||
// If so, it must be quoted in the original query
|
// If so, it must be quoted in the original query
|
||||||
strlwr(strcat(strcat(strcpy(name, " "), Name), " "));
|
strlwr(strcat(strcat(strcpy(name, " "), Name), " "));
|
||||||
@@ -597,6 +620,9 @@ char *TDBODBC::MakeCommand(PGLOBAL g)
|
|||||||
stmt[i++] = (Qrystr[k] == '`') ? *qc : Qrystr[k];
|
stmt[i++] = (Qrystr[k] == '`') ? *qc : Qrystr[k];
|
||||||
} while (Qrystr[k++]);
|
} while (Qrystr[k++]);
|
||||||
|
|
||||||
|
if (body)
|
||||||
|
strcat(stmt, body);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
sprintf(g->Message, "Cannot use this %s command",
|
sprintf(g->Message, "Cannot use this %s command",
|
||||||
(Mode == MODE_UPDATE) ? "UPDATE" : "DELETE");
|
(Mode == MODE_UPDATE) ? "UPDATE" : "DELETE");
|
||||||
@@ -698,10 +724,7 @@ int TDBODBC::Cardinality(PGLOBAL g)
|
|||||||
char qry[96], tbn[64];
|
char qry[96], tbn[64];
|
||||||
ODBConn *ocp = new(g) ODBConn(g, this);
|
ODBConn *ocp = new(g) ODBConn(g, this);
|
||||||
|
|
||||||
ocp->SetLoginTimeout((DWORD)Cto);
|
if (ocp->Open(Connect, &Ops, Options) < 1)
|
||||||
ocp->SetQueryTimeout((DWORD)Qto);
|
|
||||||
|
|
||||||
if (ocp->Open(Connect, Options) < 1)
|
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
// Table name can be encoded in UTF-8
|
// Table name can be encoded in UTF-8
|
||||||
@@ -762,9 +785,9 @@ int TDBODBC::GetProgMax(PGLOBAL g)
|
|||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
bool TDBODBC::OpenDB(PGLOBAL g)
|
bool TDBODBC::OpenDB(PGLOBAL g)
|
||||||
{
|
{
|
||||||
bool rc = false;
|
bool rc = true;
|
||||||
|
|
||||||
if (g->Trace)
|
if (trace)
|
||||||
htrc("ODBC OpenDB: tdbp=%p tdb=R%d use=%dmode=%d\n",
|
htrc("ODBC OpenDB: tdbp=%p tdb=R%d use=%dmode=%d\n",
|
||||||
this, Tdb_No, Use, Mode);
|
this, Tdb_No, Use, Mode);
|
||||||
|
|
||||||
@@ -802,14 +825,12 @@ bool TDBODBC::OpenDB(PGLOBAL g)
|
|||||||
/* and if so to allocate just a new result set. But this only for */
|
/* and if so to allocate just a new result set. But this only for */
|
||||||
/* drivers allowing concurency in getting results ??? */
|
/* drivers allowing concurency in getting results ??? */
|
||||||
/*********************************************************************/
|
/*********************************************************************/
|
||||||
if (!Ocp) {
|
if (!Ocp)
|
||||||
Ocp = new(g) ODBConn(g, this);
|
Ocp = new(g) ODBConn(g, this);
|
||||||
Ocp->SetLoginTimeout((DWORD)Cto);
|
else if (Ocp->IsOpen())
|
||||||
Ocp->SetQueryTimeout((DWORD)Qto);
|
|
||||||
} else if (Ocp->IsOpen())
|
|
||||||
Ocp->Close();
|
Ocp->Close();
|
||||||
|
|
||||||
if (Ocp->Open(Connect, Options) < 1)
|
if (Ocp->Open(Connect, &Ops, Options) < 1)
|
||||||
return true;
|
return true;
|
||||||
else if (Quoted)
|
else if (Quoted)
|
||||||
Quote = Ocp->GetQuoteChar();
|
Quote = Ocp->GetQuoteChar();
|
||||||
@@ -839,12 +860,12 @@ bool TDBODBC::OpenDB(PGLOBAL g)
|
|||||||
|
|
||||||
} // endif Query
|
} // endif Query
|
||||||
|
|
||||||
} else if (Mode == MODE_UPDATE || Mode == MODE_DELETE)
|
} else if (Mode == MODE_UPDATE || Mode == MODE_DELETE) {
|
||||||
Query = MakeCommand(g);
|
rc = false; // wait for CheckCond before calling MakeCommand(g);
|
||||||
else
|
} else
|
||||||
sprintf(g->Message, "Invalid mode %d", Mode);
|
sprintf(g->Message, "Invalid mode %d", Mode);
|
||||||
|
|
||||||
if (!Query || rc) {
|
if (rc) {
|
||||||
Ocp->Close();
|
Ocp->Close();
|
||||||
return true;
|
return true;
|
||||||
} // endif rc
|
} // endif rc
|
||||||
@@ -876,6 +897,9 @@ int TDBODBC::ReadDB(PGLOBAL g)
|
|||||||
GetTdb_No(), Mode, To_Key_Col, To_Link, To_Kindex);
|
GetTdb_No(), Mode, To_Key_Col, To_Link, To_Kindex);
|
||||||
|
|
||||||
if (Mode == MODE_UPDATE || Mode == MODE_DELETE) {
|
if (Mode == MODE_UPDATE || Mode == MODE_DELETE) {
|
||||||
|
if (!Query && !(Query = MakeCommand(g)))
|
||||||
|
return RC_FX;
|
||||||
|
|
||||||
// Send the UPDATE/DELETE command to the remote table
|
// Send the UPDATE/DELETE command to the remote table
|
||||||
if (!Ocp->ExecSQLcommand(Query)) {
|
if (!Ocp->ExecSQLcommand(Query)) {
|
||||||
sprintf(g->Message, "%s: %d affected rows", TableName, AftRows);
|
sprintf(g->Message, "%s: %d affected rows", TableName, AftRows);
|
||||||
@@ -945,6 +969,9 @@ int TDBODBC::WriteDB(PGLOBAL g)
|
|||||||
int TDBODBC::DeleteDB(PGLOBAL g, int irc)
|
int TDBODBC::DeleteDB(PGLOBAL g, int irc)
|
||||||
{
|
{
|
||||||
if (irc == RC_FX) {
|
if (irc == RC_FX) {
|
||||||
|
if (!Query && !(Query = MakeCommand(g)))
|
||||||
|
return RC_FX;
|
||||||
|
|
||||||
// Send the DELETE (all) command to the remote table
|
// Send the DELETE (all) command to the remote table
|
||||||
if (!Ocp->ExecSQLcommand(Query)) {
|
if (!Ocp->ExecSQLcommand(Query)) {
|
||||||
sprintf(g->Message, "%s: %d affected rows", TableName, AftRows);
|
sprintf(g->Message, "%s: %d affected rows", TableName, AftRows);
|
||||||
@@ -1158,12 +1185,12 @@ void ODBCCOL::ReadColumn(PGLOBAL g)
|
|||||||
|
|
||||||
} // endif Buf_Type
|
} // endif Buf_Type
|
||||||
|
|
||||||
if (g->Trace) {
|
if (trace) {
|
||||||
char buf[64];
|
char buf[64];
|
||||||
|
|
||||||
htrc("ODBC Column %s: rows=%d buf=%p type=%d value=%s\n",
|
htrc("ODBC Column %s: rows=%d buf=%p type=%d value=%s\n",
|
||||||
Name, tdbp->Rows, Bufp, Buf_Type, Value->GetCharString(buf));
|
Name, tdbp->Rows, Bufp, Buf_Type, Value->GetCharString(buf));
|
||||||
} // endif Trace
|
} // endif trace
|
||||||
|
|
||||||
put:
|
put:
|
||||||
if (tdbp->Memory != 2)
|
if (tdbp->Memory != 2)
|
||||||
@@ -1397,7 +1424,7 @@ bool TDBXDBC::OpenDB(PGLOBAL g)
|
|||||||
{
|
{
|
||||||
bool rc = false;
|
bool rc = false;
|
||||||
|
|
||||||
if (g->Trace)
|
if (trace)
|
||||||
htrc("ODBC OpenDB: tdbp=%p tdb=R%d use=%dmode=%d\n",
|
htrc("ODBC OpenDB: tdbp=%p tdb=R%d use=%dmode=%d\n",
|
||||||
this, Tdb_No, Use, Mode);
|
this, Tdb_No, Use, Mode);
|
||||||
|
|
||||||
@@ -1415,12 +1442,10 @@ bool TDBXDBC::OpenDB(PGLOBAL g)
|
|||||||
/*********************************************************************/
|
/*********************************************************************/
|
||||||
if (!Ocp) {
|
if (!Ocp) {
|
||||||
Ocp = new(g) ODBConn(g, this);
|
Ocp = new(g) ODBConn(g, this);
|
||||||
Ocp->SetLoginTimeout((DWORD)Cto);
|
|
||||||
Ocp->SetQueryTimeout((DWORD)Qto);
|
|
||||||
} else if (Ocp->IsOpen())
|
} else if (Ocp->IsOpen())
|
||||||
Ocp->Close();
|
Ocp->Close();
|
||||||
|
|
||||||
if (Ocp->Open(Connect, Options) < 1)
|
if (Ocp->Open(Connect, &Ops, Options) < 1)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
Use = USE_OPEN; // Do it now in case we are recursively called
|
Use = USE_OPEN; // Do it now in case we are recursively called
|
||||||
@@ -1554,8 +1579,11 @@ TDBOTB::TDBOTB(PODEF tdp) : TDBDRV(tdp)
|
|||||||
Dsn = tdp->GetConnect();
|
Dsn = tdp->GetConnect();
|
||||||
Schema = tdp->GetTabschema();
|
Schema = tdp->GetTabschema();
|
||||||
Tab = tdp->GetTabname();
|
Tab = tdp->GetTabname();
|
||||||
Cto = tdp->Cto;
|
Ops.User = tdp->Username;
|
||||||
Qto = tdp->Qto;
|
Ops.Pwd = tdp->Password;
|
||||||
|
Ops.Cto = tdp->Cto;
|
||||||
|
Ops.Qto = tdp->Qto;
|
||||||
|
Ops.UseCnc = tdp->UseCnc;
|
||||||
} // end of TDBOTB constructor
|
} // end of TDBOTB constructor
|
||||||
|
|
||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
@@ -1563,7 +1591,7 @@ TDBOTB::TDBOTB(PODEF tdp) : TDBDRV(tdp)
|
|||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
PQRYRES TDBOTB::GetResult(PGLOBAL g)
|
PQRYRES TDBOTB::GetResult(PGLOBAL g)
|
||||||
{
|
{
|
||||||
return ODBCTables(g, Dsn, Schema, Tab, Maxres, Cto, Qto, false);
|
return ODBCTables(g, Dsn, Schema, Tab, Maxres, false, &Ops);
|
||||||
} // end of GetResult
|
} // end of GetResult
|
||||||
|
|
||||||
/* ---------------------------TDBOCL class --------------------------- */
|
/* ---------------------------TDBOCL class --------------------------- */
|
||||||
@@ -1573,7 +1601,7 @@ PQRYRES TDBOTB::GetResult(PGLOBAL g)
|
|||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
PQRYRES TDBOCL::GetResult(PGLOBAL g)
|
PQRYRES TDBOCL::GetResult(PGLOBAL g)
|
||||||
{
|
{
|
||||||
return ODBCColumns(g, Dsn, Schema, Tab, NULL, Maxres, Cto, Qto, false);
|
return ODBCColumns(g, Dsn, Schema, Tab, NULL, Maxres, false, &Ops);
|
||||||
} // end of GetResult
|
} // end of GetResult
|
||||||
|
|
||||||
/* ------------------------ End of Tabodbc --------------------------- */
|
/* ------------------------ End of Tabodbc --------------------------- */
|
||||||
|
@@ -50,6 +50,8 @@ class DllExport ODBCDEF : public TABDEF { /* Logical table description */
|
|||||||
PSZ Connect; /* ODBC connection string */
|
PSZ Connect; /* ODBC connection string */
|
||||||
PSZ Tabname; /* External table name */
|
PSZ Tabname; /* External table name */
|
||||||
PSZ Tabschema; /* External table schema */
|
PSZ Tabschema; /* External table schema */
|
||||||
|
PSZ Username; /* User connect name */
|
||||||
|
PSZ Password; /* Password connect info */
|
||||||
PSZ Tabcat; /* External table catalog */
|
PSZ Tabcat; /* External table catalog */
|
||||||
PSZ Srcdef; /* The source table SQL definition */
|
PSZ Srcdef; /* The source table SQL definition */
|
||||||
PSZ Qchar; /* Identifier quoting character */
|
PSZ Qchar; /* Identifier quoting character */
|
||||||
@@ -65,6 +67,7 @@ class DllExport ODBCDEF : public TABDEF { /* Logical table description */
|
|||||||
bool Scrollable; /* Use scrollable cursor */
|
bool Scrollable; /* Use scrollable cursor */
|
||||||
bool Memory; /* Put result set in memory */
|
bool Memory; /* Put result set in memory */
|
||||||
bool Xsrc; /* Execution type */
|
bool Xsrc; /* Execution type */
|
||||||
|
bool UseCnc; /* Use SQLConnect (!SQLDriverConnect) */
|
||||||
}; // end of ODBCDEF
|
}; // end of ODBCDEF
|
||||||
|
|
||||||
#if !defined(NODBC)
|
#if !defined(NODBC)
|
||||||
@@ -124,9 +127,12 @@ class TDBODBC : public TDBASE {
|
|||||||
// Members
|
// Members
|
||||||
ODBConn *Ocp; // Points to an ODBC connection class
|
ODBConn *Ocp; // Points to an ODBC connection class
|
||||||
ODBCCOL *Cnp; // Points to count(*) column
|
ODBCCOL *Cnp; // Points to count(*) column
|
||||||
|
ODBCPARM Ops; // Additional parameters
|
||||||
char *Connect; // Points to connection string
|
char *Connect; // Points to connection string
|
||||||
char *TableName; // Points to ODBC table name
|
char *TableName; // Points to ODBC table name
|
||||||
char *Schema; // Points to ODBC table Schema
|
char *Schema; // Points to ODBC table Schema
|
||||||
|
char *User; // User connect info
|
||||||
|
char *Pwd; // Password connect info
|
||||||
char *Catalog; // Points to ODBC table Catalog
|
char *Catalog; // Points to ODBC table Catalog
|
||||||
char *Srcdef; // The source table SQL definition
|
char *Srcdef; // The source table SQL definition
|
||||||
char *Query; // Points to SQL statement
|
char *Query; // Points to SQL statement
|
||||||
@@ -151,6 +157,7 @@ class TDBODBC : public TDBASE {
|
|||||||
int Nparm; // The number of statement parameters
|
int Nparm; // The number of statement parameters
|
||||||
int Memory; // 0: No 1: Alloc 2: Put 3: Get
|
int Memory; // 0: No 1: Alloc 2: Put 3: Get
|
||||||
bool Scrollable; // Use scrollable cursor
|
bool Scrollable; // Use scrollable cursor
|
||||||
|
bool UseCnc; // Use SQLConnect (!SQLDriverConnect)
|
||||||
PQRYRES Qrp; // Points to storage result
|
PQRYRES Qrp; // Points to storage result
|
||||||
}; // end of class TDBODBC
|
}; // end of class TDBODBC
|
||||||
|
|
||||||
@@ -316,8 +323,7 @@ class TDBOTB : public TDBDRV {
|
|||||||
char *Dsn; // Points to connection string
|
char *Dsn; // Points to connection string
|
||||||
char *Schema; // Points to schema name or NULL
|
char *Schema; // Points to schema name or NULL
|
||||||
char *Tab; // Points to ODBC table name or pattern
|
char *Tab; // Points to ODBC table name or pattern
|
||||||
int Cto; // Connect timeout
|
ODBCPARM Ops; // Additional parameters
|
||||||
int Qto; // Query timeout
|
|
||||||
}; // end of class TDBOTB
|
}; // end of class TDBOTB
|
||||||
|
|
||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
|
@@ -558,7 +558,7 @@ bool TDBPIVOT::MakePivotColumns(PGLOBAL g)
|
|||||||
// Check and initialize the subtable columns
|
// Check and initialize the subtable columns
|
||||||
for (PCOL cp = Columns; cp; cp = cp->GetNext())
|
for (PCOL cp = Columns; cp; cp = cp->GetNext())
|
||||||
if (cp->GetAmType() == TYPE_AM_SRC) {
|
if (cp->GetAmType() == TYPE_AM_SRC) {
|
||||||
if (((PSRCCOL)cp)->Init(g))
|
if (((PSRCCOL)cp)->Init(g, NULL))
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
} else if (cp->GetAmType() == TYPE_AM_FNC)
|
} else if (cp->GetAmType() == TYPE_AM_FNC)
|
||||||
@@ -874,9 +874,9 @@ SRCCOL::SRCCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int n)
|
|||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
/* Initialize the column as pointing to the source column. */
|
/* Initialize the column as pointing to the source column. */
|
||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
bool SRCCOL::Init(PGLOBAL g)
|
bool SRCCOL::Init(PGLOBAL g, PTDBASE tp)
|
||||||
{
|
{
|
||||||
if (PRXCOL::Init(g))
|
if (PRXCOL::Init(g, tp))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
AddStatus(BUF_READ); // All is done here
|
AddStatus(BUF_READ); // All is done here
|
||||||
|
@@ -180,9 +180,10 @@ class SRCCOL : public PRXCOL {
|
|||||||
virtual int GetAmType(void) {return TYPE_AM_SRC;}
|
virtual int GetAmType(void) {return TYPE_AM_SRC;}
|
||||||
|
|
||||||
// Methods
|
// Methods
|
||||||
|
using PRXCOL::Init;
|
||||||
virtual void Reset(void) {}
|
virtual void Reset(void) {}
|
||||||
void SetColumn(void);
|
void SetColumn(void);
|
||||||
bool Init(PGLOBAL g);
|
virtual bool Init(PGLOBAL g, PTDBASE tp);
|
||||||
bool CompareLast(void);
|
bool CompareLast(void);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@@ -266,7 +266,7 @@ bool TDBTBL::InitTableList(PGLOBAL g)
|
|||||||
// Real initialization will be done later.
|
// Real initialization will be done later.
|
||||||
for (colp = Columns; colp; colp = colp->GetNext())
|
for (colp = Columns; colp; colp = colp->GetNext())
|
||||||
if (!colp->IsSpecial())
|
if (!colp->IsSpecial())
|
||||||
if (((PPRXCOL)colp)->Init(g) && !Accept)
|
if (((PPRXCOL)colp)->Init(g, NULL) && !Accept)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
if (Tablist)
|
if (Tablist)
|
||||||
@@ -352,7 +352,9 @@ bool TDBTBL::TestFil(PGLOBAL g, PCFIL filp, PTABLE tabp)
|
|||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
int TDBTBL::Cardinality(PGLOBAL g)
|
int TDBTBL::Cardinality(PGLOBAL g)
|
||||||
{
|
{
|
||||||
if (Cardinal < 0) {
|
if (!g)
|
||||||
|
return 0; // Cannot make the table list
|
||||||
|
else if (Cardinal < 0) {
|
||||||
int tsz;
|
int tsz;
|
||||||
|
|
||||||
if (!Tablist && InitTableList(g))
|
if (!Tablist && InitTableList(g))
|
||||||
@@ -468,7 +470,7 @@ bool TDBTBL::OpenDB(PGLOBAL g)
|
|||||||
for (PCOL cp = Columns; cp; cp = cp->GetNext())
|
for (PCOL cp = Columns; cp; cp = cp->GetNext())
|
||||||
if (cp->GetAmType() == TYPE_AM_TABID)
|
if (cp->GetAmType() == TYPE_AM_TABID)
|
||||||
cp->COLBLK::Reset();
|
cp->COLBLK::Reset();
|
||||||
else if (((PPRXCOL)cp)->Init(g) && !Accept)
|
else if (((PPRXCOL)cp)->Init(g, NULL) && !Accept)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
if (trace)
|
if (trace)
|
||||||
@@ -523,7 +525,7 @@ int TDBTBL::ReadDB(PGLOBAL g)
|
|||||||
if (cp->GetAmType() == TYPE_AM_TABID ||
|
if (cp->GetAmType() == TYPE_AM_TABID ||
|
||||||
cp->GetAmType() == TYPE_AM_SRVID)
|
cp->GetAmType() == TYPE_AM_SRVID)
|
||||||
cp->COLBLK::Reset();
|
cp->COLBLK::Reset();
|
||||||
else if (((PPRXCOL)cp)->Init(g) && !Accept)
|
else if (((PPRXCOL)cp)->Init(g, NULL) && !Accept)
|
||||||
return RC_FX;
|
return RC_FX;
|
||||||
|
|
||||||
if (trace)
|
if (trace)
|
||||||
@@ -716,7 +718,7 @@ bool TDBTBM::OpenDB(PGLOBAL g)
|
|||||||
for (PCOL cp = Columns; cp; cp = cp->GetNext())
|
for (PCOL cp = Columns; cp; cp = cp->GetNext())
|
||||||
if (cp->GetAmType() == TYPE_AM_TABID)
|
if (cp->GetAmType() == TYPE_AM_TABID)
|
||||||
cp->COLBLK::Reset();
|
cp->COLBLK::Reset();
|
||||||
else if (((PPRXCOL)cp)->Init(g) && !Accept)
|
else if (((PPRXCOL)cp)->Init(g, NULL) && !Accept)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
if (trace)
|
if (trace)
|
||||||
@@ -807,7 +809,7 @@ int TDBTBM::ReadNextRemote(PGLOBAL g)
|
|||||||
for (PCOL cp = Columns; cp; cp = cp->GetNext())
|
for (PCOL cp = Columns; cp; cp = cp->GetNext())
|
||||||
if (cp->GetAmType() == TYPE_AM_TABID)
|
if (cp->GetAmType() == TYPE_AM_TABID)
|
||||||
cp->COLBLK::Reset();
|
cp->COLBLK::Reset();
|
||||||
else if (((PPRXCOL)cp)->Init(g) && !Accept)
|
else if (((PPRXCOL)cp)->Init(g, NULL) && !Accept)
|
||||||
return RC_FX;
|
return RC_FX;
|
||||||
|
|
||||||
if (trace)
|
if (trace)
|
||||||
|
@@ -54,7 +54,8 @@
|
|||||||
#include "tabutil.h"
|
#include "tabutil.h"
|
||||||
#include "ha_connect.h"
|
#include "ha_connect.h"
|
||||||
|
|
||||||
extern "C" int zconv;
|
//extern "C" int zconv;
|
||||||
|
int GetConvSize(void);
|
||||||
|
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
/* Used by MYSQL tables to get MySQL parameters from the calling proxy */
|
/* Used by MYSQL tables to get MySQL parameters from the calling proxy */
|
||||||
@@ -132,6 +133,7 @@ PQRYRES TabColumns(PGLOBAL g, THD *thd, const char *db,
|
|||||||
char *fld, *colname, *chset, *fmt, v;
|
char *fld, *colname, *chset, *fmt, v;
|
||||||
int i, n, ncol = sizeof(buftyp) / sizeof(int);
|
int i, n, ncol = sizeof(buftyp) / sizeof(int);
|
||||||
int prec, len, type, scale;
|
int prec, len, type, scale;
|
||||||
|
int zconv = GetConvSize();
|
||||||
bool mysql;
|
bool mysql;
|
||||||
TABLE_SHARE *s = NULL;
|
TABLE_SHARE *s = NULL;
|
||||||
Field* *field;
|
Field* *field;
|
||||||
@@ -668,6 +670,22 @@ PRXCOL::PRXCOL(PRXCOL *col1, PTDB tdbp) : COLBLK(col1, tdbp)
|
|||||||
Colnum = col1->Colnum;
|
Colnum = col1->Colnum;
|
||||||
} // end of PRXCOL copy constructor
|
} // end of PRXCOL copy constructor
|
||||||
|
|
||||||
|
/***********************************************************************/
|
||||||
|
/* Convert an UTF-8 name to latin characters. */
|
||||||
|
/***********************************************************************/
|
||||||
|
char *PRXCOL::Decode(PGLOBAL g, const char *cnm)
|
||||||
|
{
|
||||||
|
char *buf= (char*)PlugSubAlloc(g, NULL, strlen(cnm) + 1);
|
||||||
|
uint dummy_errors;
|
||||||
|
uint32 len= copy_and_convert(buf, strlen(cnm) + 1,
|
||||||
|
&my_charset_latin1,
|
||||||
|
cnm, strlen(cnm),
|
||||||
|
&my_charset_utf8_general_ci,
|
||||||
|
&dummy_errors);
|
||||||
|
buf[len]= '\0';
|
||||||
|
return buf;
|
||||||
|
} // end of Decode
|
||||||
|
|
||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
/* PRXCOL initialization routine. */
|
/* PRXCOL initialization routine. */
|
||||||
/* Look for the matching column in the object table. */
|
/* Look for the matching column in the object table. */
|
||||||
@@ -683,6 +701,9 @@ bool PRXCOL::Init(PGLOBAL g, PTDBASE tp)
|
|||||||
if (Colp) {
|
if (Colp) {
|
||||||
MODE mode = To_Tdb->GetMode();
|
MODE mode = To_Tdb->GetMode();
|
||||||
|
|
||||||
|
// Needed for MYSQL subtables
|
||||||
|
((XCOLBLK*)Colp)->Name = Decode(g, Colp->GetName());
|
||||||
|
|
||||||
// May not have been done elsewhere
|
// May not have been done elsewhere
|
||||||
Colp->InitValue(g);
|
Colp->InitValue(g);
|
||||||
To_Val = Colp->GetValue();
|
To_Val = Colp->GetValue();
|
||||||
|
@@ -108,15 +108,18 @@ class DllExport PRXCOL : public COLBLK {
|
|||||||
virtual int GetAmType(void) {return TYPE_AM_PRX;}
|
virtual int GetAmType(void) {return TYPE_AM_PRX;}
|
||||||
|
|
||||||
// Methods
|
// Methods
|
||||||
|
using COLBLK::Init;
|
||||||
virtual void Reset(void);
|
virtual void Reset(void);
|
||||||
virtual bool IsSpecial(void) {return Pseudo;}
|
virtual bool IsSpecial(void) {return Pseudo;}
|
||||||
virtual bool SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check)
|
virtual bool SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check)
|
||||||
{return false;}
|
{return false;}
|
||||||
virtual void ReadColumn(PGLOBAL g);
|
virtual void ReadColumn(PGLOBAL g);
|
||||||
virtual void WriteColumn(PGLOBAL g);
|
virtual void WriteColumn(PGLOBAL g);
|
||||||
virtual bool Init(PGLOBAL g, PTDBASE tp = NULL);
|
virtual bool Init(PGLOBAL g, PTDBASE tp);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
char *Decode(PGLOBAL g, const char *cnm);
|
||||||
|
|
||||||
// Default constructor not to be used
|
// Default constructor not to be used
|
||||||
PRXCOL(void) {}
|
PRXCOL(void) {}
|
||||||
|
|
||||||
@@ -144,4 +147,8 @@ class TDBTBC : public TDBCAT {
|
|||||||
PSZ Tab; // Table name
|
PSZ Tab; // Table name
|
||||||
}; // end of class TDBMCL
|
}; // end of class TDBMCL
|
||||||
|
|
||||||
|
class XCOLBLK : public COLBLK {
|
||||||
|
friend class PRXCOL;
|
||||||
|
}; // end of class XCOLBLK
|
||||||
|
|
||||||
#endif // TABUTIL
|
#endif // TABUTIL
|
||||||
|
@@ -183,7 +183,7 @@ bool TDBXCL::OpenDB(PGLOBAL g)
|
|||||||
/*********************************************************************/
|
/*********************************************************************/
|
||||||
for (PCOL cp = Columns; cp; cp = cp->GetNext())
|
for (PCOL cp = Columns; cp; cp = cp->GetNext())
|
||||||
if (!cp->IsSpecial())
|
if (!cp->IsSpecial())
|
||||||
if (((PPRXCOL)cp)->Init(g))
|
if (((PPRXCOL)cp)->Init(g, NULL))
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
/*********************************************************************/
|
/*********************************************************************/
|
||||||
|
@@ -88,6 +88,7 @@ class XCLCOL : public PRXCOL {
|
|||||||
XCLCOL(PGLOBAL g, PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i);
|
XCLCOL(PGLOBAL g, PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i);
|
||||||
|
|
||||||
// Methods
|
// Methods
|
||||||
|
using PRXCOL::Init;
|
||||||
virtual void Reset(void) {} // Evaluated only by TDBXCL
|
virtual void Reset(void) {} // Evaluated only by TDBXCL
|
||||||
virtual void ReadColumn(PGLOBAL g);
|
virtual void ReadColumn(PGLOBAL g);
|
||||||
virtual bool Init(PGLOBAL g, PTDBASE tp = NULL);
|
virtual bool Init(PGLOBAL g, PTDBASE tp = NULL);
|
||||||
|
@@ -163,6 +163,7 @@ class TYPBLK : public VALBLK {
|
|||||||
virtual void Reset(int n) {Typp[n] = 0;}
|
virtual void Reset(int n) {Typp[n] = 0;}
|
||||||
|
|
||||||
// Methods
|
// Methods
|
||||||
|
using VALBLK::SetValue;
|
||||||
virtual void SetValue(PSZ sp, int n);
|
virtual void SetValue(PSZ sp, int n);
|
||||||
virtual void SetValue(char *sp, uint len, int n);
|
virtual void SetValue(char *sp, uint len, int n);
|
||||||
virtual void SetValue(short sval, int n)
|
virtual void SetValue(short sval, int n)
|
||||||
@@ -233,6 +234,7 @@ class CHRBLK : public VALBLK {
|
|||||||
virtual bool IsCi(void) {return Ci;}
|
virtual bool IsCi(void) {return Ci;}
|
||||||
|
|
||||||
// Methods
|
// Methods
|
||||||
|
using VALBLK::SetValue;
|
||||||
virtual void SetValue(PSZ sp, int n);
|
virtual void SetValue(PSZ sp, int n);
|
||||||
virtual void SetValue(char *sp, uint len, int n);
|
virtual void SetValue(char *sp, uint len, int n);
|
||||||
virtual void SetValue(PVAL valp, int n);
|
virtual void SetValue(PVAL valp, int n);
|
||||||
@@ -286,6 +288,7 @@ class STRBLK : public VALBLK {
|
|||||||
virtual void Reset(int n) {Strp[n] = NULL;}
|
virtual void Reset(int n) {Strp[n] = NULL;}
|
||||||
|
|
||||||
// Methods
|
// Methods
|
||||||
|
using VALBLK::SetValue;
|
||||||
virtual void SetValue(PSZ sp, int n);
|
virtual void SetValue(PSZ sp, int n);
|
||||||
virtual void SetValue(char *sp, uint len, int n);
|
virtual void SetValue(char *sp, uint len, int n);
|
||||||
virtual void SetValue(PVAL valp, int n);
|
virtual void SetValue(PVAL valp, int n);
|
||||||
@@ -322,6 +325,7 @@ class DATBLK : public TYPBLK<int> {
|
|||||||
virtual char *GetCharString(char *p, int n);
|
virtual char *GetCharString(char *p, int n);
|
||||||
|
|
||||||
// Methods
|
// Methods
|
||||||
|
using TYPBLK<int>::SetValue;
|
||||||
virtual void SetValue(PSZ sp, int n);
|
virtual void SetValue(PSZ sp, int n);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@@ -345,6 +349,8 @@ class PTRBLK : public STRBLK {
|
|||||||
// Implementation
|
// Implementation
|
||||||
|
|
||||||
// Methods
|
// Methods
|
||||||
|
using STRBLK::SetValue;
|
||||||
|
using STRBLK::CompVal;
|
||||||
virtual void SetValue(PSZ p, int n) {Strp[n] = p;}
|
virtual void SetValue(PSZ p, int n) {Strp[n] = p;}
|
||||||
virtual int CompVal(int i1, int i2);
|
virtual int CompVal(int i1, int i2);
|
||||||
|
|
||||||
|
@@ -436,6 +436,9 @@ PVAL AllocateValue(PGLOBAL g, PVAL valp, int newtype, int uns)
|
|||||||
bool un = (uns < 0) ? false : (uns > 0) ? true : valp->IsUnsigned();
|
bool un = (uns < 0) ? false : (uns > 0) ? true : valp->IsUnsigned();
|
||||||
PVAL vp;
|
PVAL vp;
|
||||||
|
|
||||||
|
if (!valp)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
if (newtype == TYPE_VOID) // Means allocate a value of the same type
|
if (newtype == TYPE_VOID) // Means allocate a value of the same type
|
||||||
newtype = valp->GetType();
|
newtype = valp->GetType();
|
||||||
|
|
||||||
@@ -443,8 +446,8 @@ PVAL AllocateValue(PGLOBAL g, PVAL valp, int newtype, int uns)
|
|||||||
case TYPE_STRING:
|
case TYPE_STRING:
|
||||||
p = (PSZ)PlugSubAlloc(g, NULL, 1 + valp->GetValLen());
|
p = (PSZ)PlugSubAlloc(g, NULL, 1 + valp->GetValLen());
|
||||||
|
|
||||||
if ((sp = valp->GetCharString(p)) != p)
|
if ((sp = valp->GetCharString(p)) != p && sp)
|
||||||
strcpy (p, sp);
|
strcpy(p, sp);
|
||||||
|
|
||||||
vp = new(g) TYPVAL<PSZ>(g, p, valp->GetValLen(), valp->GetValPrec());
|
vp = new(g) TYPVAL<PSZ>(g, p, valp->GetValLen(), valp->GetValPrec());
|
||||||
break;
|
break;
|
||||||
@@ -1216,12 +1219,12 @@ TYPVAL<PSZ>::TYPVAL(PSZ s) : VALUE(TYPE_STRING)
|
|||||||
TYPVAL<PSZ>::TYPVAL(PGLOBAL g, PSZ s, int n, int c)
|
TYPVAL<PSZ>::TYPVAL(PGLOBAL g, PSZ s, int n, int c)
|
||||||
: VALUE(TYPE_STRING)
|
: VALUE(TYPE_STRING)
|
||||||
{
|
{
|
||||||
Len = (g) ? n : strlen(s);
|
Len = (g) ? n : (s) ? strlen(s) : 0;
|
||||||
|
|
||||||
if (!s) {
|
if (!s) {
|
||||||
if (g) {
|
if (g) {
|
||||||
if ((Strp = (char *)PlgDBSubAlloc(g, NULL, Len + 1)))
|
if ((Strp = (char *)PlgDBSubAlloc(g, NULL, Len + 1)))
|
||||||
Strp[Len] = '\0';
|
memset(Strp, 0, Len + 1);
|
||||||
else
|
else
|
||||||
Len = 0;
|
Len = 0;
|
||||||
|
|
||||||
|
@@ -391,6 +391,7 @@ class DllExport XHUGE : public XLOAD {
|
|||||||
XHUGE(void) : XLOAD() {}
|
XHUGE(void) : XLOAD() {}
|
||||||
|
|
||||||
// Methods
|
// Methods
|
||||||
|
using XLOAD::Close;
|
||||||
virtual bool Open(PGLOBAL g, char *filename, int id, MODE mode);
|
virtual bool Open(PGLOBAL g, char *filename, int id, MODE mode);
|
||||||
virtual bool Seek(PGLOBAL g, int low, int high, int origin);
|
virtual bool Seek(PGLOBAL g, int low, int high, int origin);
|
||||||
virtual bool Read(PGLOBAL g, void *buf, int n, int size);
|
virtual bool Read(PGLOBAL g, void *buf, int n, int size);
|
||||||
|
@@ -346,6 +346,31 @@ bool STRING::Append(char c)
|
|||||||
return false;
|
return false;
|
||||||
} // end of Append
|
} // end of Append
|
||||||
|
|
||||||
|
/***********************************************************************/
|
||||||
|
/* Append a quoted PSZ to a STRING. */
|
||||||
|
/***********************************************************************/
|
||||||
|
bool STRING::Append_quoted(PSZ s)
|
||||||
|
{
|
||||||
|
bool b = Append('\'');
|
||||||
|
|
||||||
|
if (s) for (char *p = s; !b && *p; p++)
|
||||||
|
switch (*p) {
|
||||||
|
case '\'':
|
||||||
|
case '\\':
|
||||||
|
case '\t':
|
||||||
|
case '\n':
|
||||||
|
case '\r':
|
||||||
|
case '\b':
|
||||||
|
case '\f': b |= Append('\\');
|
||||||
|
// passthru
|
||||||
|
default:
|
||||||
|
b |= Append(*p);
|
||||||
|
break;
|
||||||
|
} // endswitch *p
|
||||||
|
|
||||||
|
return (b |= Append('\''));
|
||||||
|
} // end of Append_quoted
|
||||||
|
|
||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
/* Resize to given length but only when last suballocated. */
|
/* Resize to given length but only when last suballocated. */
|
||||||
/* New size should be greater than string length. */
|
/* New size should be greater than string length. */
|
||||||
|
@@ -138,6 +138,7 @@ class DllExport STRING : public BLOCK {
|
|||||||
bool Append(STRING &str);
|
bool Append(STRING &str);
|
||||||
bool Append(char c);
|
bool Append(char c);
|
||||||
bool Resize(uint n);
|
bool Resize(uint n);
|
||||||
|
bool Append_quoted(PSZ s);
|
||||||
inline void Trim(void) {(void)Resize(Length + 1);}
|
inline void Trim(void) {(void)Resize(Length + 1);}
|
||||||
inline void Chop(void) {if (Length) Strp[--Length] = 0;}
|
inline void Chop(void) {if (Length) Strp[--Length] = 0;}
|
||||||
inline void RepLast(char c) {if (Length) Strp[Length-1] = c;}
|
inline void RepLast(char c) {if (Length) Strp[Length-1] = c;}
|
||||||
|
@@ -3055,6 +3055,12 @@ func_start:
|
|||||||
/* 2. Allocate a new page to the index */
|
/* 2. Allocate a new page to the index */
|
||||||
new_block = btr_page_alloc(cursor->index, hint_page_no, direction,
|
new_block = btr_page_alloc(cursor->index, hint_page_no, direction,
|
||||||
btr_page_get_level(page, mtr), mtr, mtr);
|
btr_page_get_level(page, mtr), mtr, mtr);
|
||||||
|
|
||||||
|
/* Play safe, if new page is not allocated */
|
||||||
|
if (!new_block) {
|
||||||
|
return(rec);
|
||||||
|
}
|
||||||
|
|
||||||
new_page = buf_block_get_frame(new_block);
|
new_page = buf_block_get_frame(new_block);
|
||||||
new_page_zip = buf_block_get_page_zip(new_block);
|
new_page_zip = buf_block_get_page_zip(new_block);
|
||||||
btr_page_create(new_block, new_page_zip, cursor->index,
|
btr_page_create(new_block, new_page_zip, cursor->index,
|
||||||
|
@@ -2368,15 +2368,15 @@ btr_cur_pess_upd_restore_supremum(
|
|||||||
Check if the total length of the modified blob for the row is within 10%
|
Check if the total length of the modified blob for the row is within 10%
|
||||||
of the total redo log size. This constraint on the blob length is to
|
of the total redo log size. This constraint on the blob length is to
|
||||||
avoid overwriting the redo logs beyond the last checkpoint lsn.
|
avoid overwriting the redo logs beyond the last checkpoint lsn.
|
||||||
@return DB_SUCCESS or DB_TOO_BIG_RECORD. */
|
@return DB_SUCCESS or DB_TOO_BIG_FOR_REDO. */
|
||||||
static
|
static
|
||||||
dberr_t
|
dberr_t
|
||||||
btr_check_blob_limit(const big_rec_t* big_rec_vec)
|
btr_check_blob_limit(const big_rec_t* big_rec_vec)
|
||||||
{
|
{
|
||||||
const ib_uint64_t redo_size = srv_n_log_files * srv_log_file_size
|
const ib_uint64_t redo_size = srv_n_log_files * srv_log_file_size
|
||||||
* UNIV_PAGE_SIZE;
|
* UNIV_PAGE_SIZE;
|
||||||
const ulint redo_10p = redo_size / 10;
|
const ib_uint64_t redo_10p = redo_size / 10;
|
||||||
ulint total_blob_len = 0;
|
ib_uint64_t total_blob_len = 0;
|
||||||
dberr_t err = DB_SUCCESS;
|
dberr_t err = DB_SUCCESS;
|
||||||
|
|
||||||
/* Calculate the total number of bytes for blob data */
|
/* Calculate the total number of bytes for blob data */
|
||||||
@@ -2386,11 +2386,11 @@ btr_check_blob_limit(const big_rec_t* big_rec_vec)
|
|||||||
|
|
||||||
if (total_blob_len > redo_10p) {
|
if (total_blob_len > redo_10p) {
|
||||||
ib_logf(IB_LOG_LEVEL_ERROR, "The total blob data"
|
ib_logf(IB_LOG_LEVEL_ERROR, "The total blob data"
|
||||||
" length (" ULINTPF ") is greater than"
|
" length (" UINT64PF ") is greater than"
|
||||||
" 10%% of the total redo log size (" UINT64PF
|
" 10%% of the total redo log size (" UINT64PF
|
||||||
"). Please increase total redo log size.",
|
"). Please increase total redo log size.",
|
||||||
total_blob_len, redo_size);
|
total_blob_len, redo_size);
|
||||||
err = DB_TOO_BIG_RECORD;
|
err = DB_TOO_BIG_FOR_REDO;
|
||||||
}
|
}
|
||||||
|
|
||||||
return(err);
|
return(err);
|
||||||
@@ -4453,7 +4453,7 @@ Stores the fields in big_rec_vec to the tablespace and puts pointers to
|
|||||||
them in rec. The extern flags in rec will have to be set beforehand.
|
them in rec. The extern flags in rec will have to be set beforehand.
|
||||||
The fields are stored on pages allocated from leaf node
|
The fields are stored on pages allocated from leaf node
|
||||||
file segment of the index tree.
|
file segment of the index tree.
|
||||||
@return DB_SUCCESS or DB_OUT_OF_FILE_SPACE */
|
@return DB_SUCCESS or DB_OUT_OF_FILE_SPACE or DB_TOO_BIG_FOR_REDO */
|
||||||
UNIV_INTERN
|
UNIV_INTERN
|
||||||
dberr_t
|
dberr_t
|
||||||
btr_store_big_rec_extern_fields(
|
btr_store_big_rec_extern_fields(
|
||||||
|
@@ -2427,10 +2427,10 @@ too_big:
|
|||||||
dict_mem_index_free(new_index);
|
dict_mem_index_free(new_index);
|
||||||
dict_mem_index_free(index);
|
dict_mem_index_free(index);
|
||||||
return(DB_TOO_BIG_RECORD);
|
return(DB_TOO_BIG_RECORD);
|
||||||
} else {
|
} else if (current_thd != NULL) {
|
||||||
|
/* Avoid the warning to be printed
|
||||||
|
during recovery. */
|
||||||
ib_warn_row_too_big(table);
|
ib_warn_row_too_big(table);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -319,6 +319,9 @@ dict_mem_table_col_rename_low(
|
|||||||
ut_ad(from_len <= NAME_LEN);
|
ut_ad(from_len <= NAME_LEN);
|
||||||
ut_ad(to_len <= NAME_LEN);
|
ut_ad(to_len <= NAME_LEN);
|
||||||
|
|
||||||
|
char from[NAME_LEN];
|
||||||
|
strncpy(from, s, NAME_LEN);
|
||||||
|
|
||||||
if (from_len == to_len) {
|
if (from_len == to_len) {
|
||||||
/* The easy case: simply replace the column name in
|
/* The easy case: simply replace the column name in
|
||||||
table->col_names. */
|
table->col_names. */
|
||||||
@@ -386,14 +389,53 @@ dict_mem_table_col_rename_low(
|
|||||||
|
|
||||||
foreign = *it;
|
foreign = *it;
|
||||||
|
|
||||||
for (unsigned f = 0; f < foreign->n_fields; f++) {
|
if (foreign->foreign_index == NULL) {
|
||||||
/* These can point straight to
|
/* We may go here when we set foreign_key_checks to 0,
|
||||||
table->col_names, because the foreign key
|
and then try to rename a column and modify the
|
||||||
constraints will be freed at the same time
|
corresponding foreign key constraint. The index
|
||||||
when the table object is freed. */
|
would have been dropped, we have to find an equivalent
|
||||||
foreign->foreign_col_names[f]
|
one */
|
||||||
= dict_index_get_nth_field(
|
for (unsigned f = 0; f < foreign->n_fields; f++) {
|
||||||
foreign->foreign_index, f)->name;
|
if (strcmp(foreign->foreign_col_names[f], from)
|
||||||
|
== 0) {
|
||||||
|
|
||||||
|
char** rc = const_cast<char**>(
|
||||||
|
foreign->foreign_col_names
|
||||||
|
+ f);
|
||||||
|
|
||||||
|
if (to_len <= strlen(*rc)) {
|
||||||
|
memcpy(*rc, to, to_len + 1);
|
||||||
|
} else {
|
||||||
|
*rc = static_cast<char*>(
|
||||||
|
mem_heap_dup(
|
||||||
|
foreign->heap,
|
||||||
|
to,
|
||||||
|
to_len + 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dict_index_t* new_index = dict_foreign_find_index(
|
||||||
|
foreign->foreign_table, NULL,
|
||||||
|
foreign->foreign_col_names,
|
||||||
|
foreign->n_fields, NULL, true, false);
|
||||||
|
/* There must be an equivalent index in this case. */
|
||||||
|
ut_ad(new_index != NULL);
|
||||||
|
|
||||||
|
foreign->foreign_index = new_index;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
for (unsigned f = 0; f < foreign->n_fields; f++) {
|
||||||
|
/* These can point straight to
|
||||||
|
table->col_names, because the foreign key
|
||||||
|
constraints will be freed at the same time
|
||||||
|
when the table object is freed. */
|
||||||
|
foreign->foreign_col_names[f]
|
||||||
|
= dict_index_get_nth_field(
|
||||||
|
foreign->foreign_index,
|
||||||
|
f)->name;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -403,6 +445,8 @@ dict_mem_table_col_rename_low(
|
|||||||
|
|
||||||
foreign = *it;
|
foreign = *it;
|
||||||
|
|
||||||
|
ut_ad(foreign->referenced_index != NULL);
|
||||||
|
|
||||||
for (unsigned f = 0; f < foreign->n_fields; f++) {
|
for (unsigned f = 0; f < foreign->n_fields; f++) {
|
||||||
/* foreign->referenced_col_names[] need to be
|
/* foreign->referenced_col_names[] need to be
|
||||||
copies, because the constraint may become
|
copies, because the constraint may become
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user