Merge remote-tracking branch 'origin/10.0' into 10.0
This commit is contained in:
commit
f2cb45daf3
@ -156,37 +156,37 @@ MACRO (MYSQL_CHECK_SSL)
|
||||
LIST(REVERSE CMAKE_FIND_LIBRARY_SUFFIXES)
|
||||
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
|
||||
OPENSSL_LIBRARIES AND
|
||||
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)
|
||||
ELSE()
|
||||
SET(OPENSSL_FOUND FALSE)
|
||||
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)
|
||||
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_LIBRARIES ${OPENSSL_LIBRARIES} ${CRYPTO_LIBRARY})
|
||||
IF(CMAKE_SYSTEM_NAME MATCHES "SunOS")
|
||||
|
@ -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,
|
||||
unsigned long *salt);
|
||||
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);
|
||||
|
||||
#endif
|
||||
void make_scrambled_password(char *to, const char *password);
|
||||
void scramble(char *to, const char *message, const char *password);
|
||||
my_bool check_scramble(const unsigned char *reply, const char *message,
|
||||
const unsigned char *hash_stage2);
|
||||
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);
|
||||
#endif
|
||||
char *octet2hex(char *to, const char *str, unsigned int len);
|
||||
|
||||
/* end of password.c */
|
||||
|
@ -141,12 +141,12 @@ ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
|
||||
# First table reported in 'SHOW ENGINE InnoDB STATUS'
|
||||
SHOW ENGINE InnoDB STATUS;
|
||||
Type Name Status
|
||||
InnoDB index `PRIMARY` of table `test`.`t``\""e` /* Partition `p0``\""e`, Subpartition `sp0``\""e` */
|
||||
InnoDB index `PRIMARY` of table `test`.`t``\""e` /* Partition `p0``\""e`, Subpartition `sp0``\""e` */
|
||||
set @old_sql_mode = @@sql_mode;
|
||||
set sql_mode = 'ANSI_QUOTES';
|
||||
SHOW ENGINE InnoDB STATUS;
|
||||
Type Name Status
|
||||
InnoDB index `PRIMARY` of table `test`.`t``\""e` /* Partition `p0``\""e`, Subpartition `sp0``\""e` */
|
||||
InnoDB index `PRIMARY` of table `test`.`t``\""e` /* Partition `p0``\""e`, Subpartition `sp0``\""e` */
|
||||
set @@sql_mode = @old_sql_mode;
|
||||
# con1
|
||||
ROLLBACK;
|
||||
|
@ -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 optimizer_use_condition_selectivity=@save_optimizer_use_condition_selectivity;
|
||||
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;
|
||||
|
@ -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 optimizer_use_condition_selectivity=@save_optimizer_use_condition_selectivity;
|
||||
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 optimizer_switch=@save_optimizer_switch_for_selectivity_test;
|
||||
set @tmp_ust= @@use_stat_tables;
|
||||
|
@ -284,4 +284,23 @@ DROP EVENT teste_bug11763507;
|
||||
# ------------------------------------------------------------------
|
||||
# -- 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;
|
||||
|
@ -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)
|
||||
begin
|
||||
declare current_num int;
|
||||
@ -10,41 +11,53 @@ end while;
|
||||
end//
|
||||
commit;
|
||||
set autocommit=0;
|
||||
call innodb_insert_proc(10000);
|
||||
call innodb_insert_proc(20000);
|
||||
commit;
|
||||
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';
|
||||
alter table t1 add testcol int;
|
||||
ERROR HY000: The table 't1' is full
|
||||
show create table t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`a` int(11) NOT NULL,
|
||||
`b` int(11) DEFAULT NULL,
|
||||
PRIMARY KEY (`a`)
|
||||
`a` int(11) DEFAULT NULL,
|
||||
`b` int(11) DEFAULT NULL
|
||||
) 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;
|
||||
ERROR HY000: The table 't1' is full
|
||||
show create table t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`a` int(11) NOT NULL,
|
||||
`b` int(11) DEFAULT NULL,
|
||||
PRIMARY KEY (`a`)
|
||||
`a` int(11) DEFAULT NULL,
|
||||
`b` int(11) DEFAULT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1
|
||||
set DEBUG_DBUG=NULL;
|
||||
drop table t2;
|
||||
alter table t1 add testcol2 int;
|
||||
show create table t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`a` int(11) NOT NULL,
|
||||
`b` int(11) DEFAULT NULL,
|
||||
`testcol2` int(11) DEFAULT NULL,
|
||||
PRIMARY KEY (`a`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1
|
||||
select count(1) from t1;
|
||||
count(1)
|
||||
10000
|
||||
ERROR HY000: The table 't1' is full
|
||||
alter table t1 add testcol3 int;
|
||||
ERROR HY000: The table 't1' is full
|
||||
call innodb_insert_proc(20000);
|
||||
set autocommit=0;
|
||||
call innodb_insert_proc(20000);
|
||||
commit;
|
||||
set autocommit=1;
|
||||
set DEBUG_DBUG='';
|
||||
drop procedure innodb_insert_proc;
|
||||
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
|
||||
|
@ -7,7 +7,9 @@
|
||||
# DEBUG_SYNC must be compiled in.
|
||||
--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 //;
|
||||
create procedure innodb_insert_proc (repeat_count int)
|
||||
@ -23,28 +25,51 @@ delimiter ;//
|
||||
commit;
|
||||
|
||||
set autocommit=0;
|
||||
call innodb_insert_proc(10000);
|
||||
call innodb_insert_proc(20000);
|
||||
commit;
|
||||
set autocommit=1;
|
||||
|
||||
create table t2(a int) engine=innodb;
|
||||
show create table t2;
|
||||
|
||||
# This caused crash earlier
|
||||
set DEBUG_DBUG='+d,ib_os_aio_func_io_failure_28';
|
||||
--error 1114
|
||||
alter table t1 add testcol int;
|
||||
show create table t1;
|
||||
|
||||
# This caused crash earlier
|
||||
set DEBUG_DBUG='+d,ib_os_aio_func_io_failure_28_2';
|
||||
--error 1114
|
||||
alter table t2 add testcol int;
|
||||
--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
|
||||
alter table t1 add testcol int;
|
||||
show create table t1;
|
||||
|
||||
set DEBUG_DBUG=NULL;
|
||||
--error 0,1051
|
||||
drop table t2;
|
||||
--error 1114
|
||||
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 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_partition.inc
|
||||
# Test causes OS error printout
|
||||
--source include/not_windows.inc
|
||||
|
||||
--disable_query_log
|
||||
--disable_result_log
|
||||
|
@ -5,6 +5,11 @@
|
||||
|
||||
-- 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_result_log
|
||||
|
||||
|
@ -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
|
||||
# on big texts, removing a lot of text before + after makes it much faster.
|
||||
#/.*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;
|
||||
set @old_sql_mode = @@sql_mode;
|
||||
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;
|
||||
set @@sql_mode = @old_sql_mode;
|
||||
--echo # con1
|
||||
|
@ -942,5 +942,34 @@ set optimizer_use_condition_selectivity=@save_optimizer_use_condition_selectivit
|
||||
|
||||
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;
|
||||
|
||||
|
@ -461,6 +461,26 @@ DROP EVENT teste_bug11763507;
|
||||
--echo # -- End of 5.1 tests
|
||||
--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.
|
||||
#
|
||||
|
@ -371,6 +371,9 @@ int init_slave()
|
||||
if (run_slave_init_thread())
|
||||
return 1;
|
||||
|
||||
if (global_rpl_thread_pool.init(opt_slave_parallel_threads))
|
||||
return 1;
|
||||
|
||||
/*
|
||||
This is called when mysqld starts. Before client connections are
|
||||
accepted. However bootstrap may conflict with us if it does START SLAVE.
|
||||
@ -404,9 +407,6 @@ int init_slave()
|
||||
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
|
||||
system variable has not been set up yet. Do it now.
|
||||
|
@ -9840,7 +9840,6 @@ bool sp_grant_privileges(THD *thd, const char *sp_db, const char *sp_name,
|
||||
List<LEX_USER> user_list;
|
||||
bool result;
|
||||
ACL_USER *au;
|
||||
char passwd_buff[SCRAMBLED_PASSWORD_CHAR_LENGTH+1];
|
||||
Dummy_error_handler error_handler;
|
||||
DBUG_ENTER("sp_grant_privileges");
|
||||
|
||||
@ -9881,33 +9880,10 @@ bool sp_grant_privileges(THD *thd, const char *sp_db, const char *sp_name,
|
||||
|
||||
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 &&
|
||||
au->plugin.str != old_password_plugin_name.str)
|
||||
{
|
||||
combo->plugin= au->plugin;
|
||||
combo->auth= au->auth_string;
|
||||
}
|
||||
combo->auth= au->auth_string;
|
||||
}
|
||||
|
||||
if (user_list.push_back(combo))
|
||||
|
@ -7462,8 +7462,12 @@ double table_cond_selectivity(JOIN *join, uint idx, JOIN_TAB *s,
|
||||
else
|
||||
fldno= table->key_info[key].key_part[keyparts-1].fieldnr - 1;
|
||||
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:
|
||||
1. cond_selectivity might be =1 (the default) because quick
|
||||
@ -7517,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 (field->cond_selectivity > 0)
|
||||
{
|
||||
sel/= field->cond_selectivity;
|
||||
set_if_smaller(sel, 1.0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -21,9 +21,9 @@ ha_connect.cc connect.cc user_connect.cc mycat.cc
|
||||
fmdlex.c osutil.c plugutil.c rcmsg.c rcmsg.h
|
||||
array.cpp blkfil.cpp colblk.cpp csort.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
|
||||
tabdos.cpp tabfix.cpp tabfmt.cpp tabjson.cpp table.cpp tabmul.cpp taboccur.cpp
|
||||
tabpivot.cpp tabsys.cpp tabtbl.cpp tabutil.cpp tabvct.cpp tabvir.cpp
|
||||
filter.cpp json.cpp jsonudf.cpp maputil.cpp myutil.cpp plgdbutl.cpp reldef.cpp
|
||||
tabcol.cpp tabdos.cpp tabfix.cpp tabfmt.cpp tabjson.cpp table.cpp tabmul.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
|
||||
|
||||
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;}
|
||||
|
||||
// Methods
|
||||
using XOBJECT::GetIntValue;
|
||||
virtual void Reset(void) {Bot = -1;}
|
||||
virtual int Qcompare(int *, int *);
|
||||
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_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_
|
||||
|
@ -469,9 +469,12 @@ RCODE CntReadNext(PGLOBAL g, PTDB tdbp)
|
||||
|
||||
} while (rc == RC_NF);
|
||||
|
||||
if (rc == RC_OK)
|
||||
rc= EvalColumns(g, tdbp, false);
|
||||
|
||||
err:
|
||||
g->jump_level--;
|
||||
return (rc != RC_OK) ? rc : EvalColumns(g, tdbp, false);
|
||||
return rc;
|
||||
} // end of CntReadNext
|
||||
|
||||
/***********************************************************************/
|
||||
|
@ -170,18 +170,18 @@
|
||||
#define SZWMIN 4194304 // Minimum work area size 4M
|
||||
|
||||
extern "C" {
|
||||
char version[]= "Version 1.03.0006 January 13, 2015";
|
||||
char compver[]= "Version 1.03.0006 " __DATE__ " " __TIME__;
|
||||
char version[]= "Version 1.03.0006 February 06, 2015";
|
||||
|
||||
#if defined(WIN32)
|
||||
char compver[]= "Version 1.03.0006 " __DATE__ " " __TIME__;
|
||||
char slash= '\\';
|
||||
#else // !WIN32
|
||||
char slash= '/';
|
||||
#endif // !WIN32
|
||||
|
||||
// int trace= 0; // The general trace value
|
||||
ulong xconv= 0; // The type conversion option
|
||||
int zconv= 0; // The text conversion size
|
||||
// ulong xconv= 0; // The type conversion option
|
||||
// int zconv= 0; // The text conversion size
|
||||
} // extern "C"
|
||||
|
||||
#if defined(XMAP)
|
||||
@ -215,6 +215,8 @@ bool CheckSelf(PGLOBAL g, TABLE_SHARE *s, const char *host,
|
||||
const char *db, char *tab, const char *src, int port);
|
||||
bool ExactInfo(void);
|
||||
USETEMP UseTemp(void);
|
||||
int GetConvSize(void);
|
||||
TYPCONV GetTypeConv(void);
|
||||
uint GetWorkSize(void);
|
||||
void SetWorkSize(uint);
|
||||
extern "C" const char *msglang(void);
|
||||
@ -289,6 +291,38 @@ static MYSQL_THDVAR_UINT(work_size,
|
||||
"Size of the CONNECT work area.",
|
||||
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
|
||||
|
||||
#if defined(XMSG) || defined(NEWMSG)
|
||||
const char *language_names[]=
|
||||
{
|
||||
@ -317,6 +351,8 @@ static MYSQL_THDVAR_ENUM(
|
||||
extern "C" int GetTraceValue(void) {return THDVAR(current_thd, xtrace);}
|
||||
bool ExactInfo(void) {return THDVAR(current_thd, exact_info);}
|
||||
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 GetWorkSize(void) {return THDVAR(current_thd, work_size);}
|
||||
void SetWorkSize(uint n)
|
||||
{
|
||||
@ -598,7 +634,11 @@ static int connect_init_func(void *p)
|
||||
}
|
||||
#endif // 0 (LINUX)
|
||||
|
||||
#if defined(WIN32)
|
||||
sql_print_information("CONNECT: %s", compver);
|
||||
#else // !WIN32
|
||||
sql_print_information("CONNECT: %s", version);
|
||||
#endif // !WIN32
|
||||
|
||||
#ifdef LIBXML2_SUPPORT
|
||||
XmlInitParserLib();
|
||||
@ -934,6 +974,9 @@ ulonglong ha_connect::table_flags() const
|
||||
char *GetListOption(PGLOBAL g, const char *opname,
|
||||
const char *oplist, const char *def)
|
||||
{
|
||||
if (!oplist)
|
||||
return (char*)def;
|
||||
|
||||
char key[16], val[256];
|
||||
char *pk, *pv, *pn;
|
||||
char *opval= (char*) def;
|
||||
@ -997,8 +1040,12 @@ char *ha_connect::GetRealString(const char *s)
|
||||
char *sv;
|
||||
|
||||
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);
|
||||
PlugSubAlloc(xp->g, NULL, strlen(sv) + 1);
|
||||
} else
|
||||
sv= (char*)s;
|
||||
|
||||
@ -1064,9 +1111,16 @@ char *ha_connect::GetStringOption(char *opname, char *sdef)
|
||||
|
||||
} // endif Table_charset
|
||||
|
||||
if (!opval && options && options->oplist)
|
||||
if (!opval && options && 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 (sdef && !strcmp(sdef, "*")) {
|
||||
// Return the handler default value
|
||||
@ -2467,6 +2521,8 @@ PCFIL ha_connect::CheckCond(PGLOBAL g, PCFIL filp, AMT tty, Item *cond)
|
||||
char *body= filp->Body;
|
||||
unsigned int i;
|
||||
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;
|
||||
|
||||
if (!cond)
|
||||
@ -2484,7 +2540,7 @@ PCFIL ha_connect::CheckCond(PGLOBAL g, PCFIL filp, AMT tty, Item *cond)
|
||||
|
||||
if (trace)
|
||||
htrc("Cond: Ftype=%d name=%s\n", cond_item->functype(),
|
||||
cond_item->func_name());
|
||||
cond_item->func_name());
|
||||
|
||||
switch (cond_item->functype()) {
|
||||
case Item_func::COND_AND_FUNC: vop= OP_AND; break;
|
||||
@ -2503,7 +2559,7 @@ PCFIL ha_connect::CheckCond(PGLOBAL g, PCFIL filp, AMT tty, Item *cond)
|
||||
for (i= 0; i < arglist->elements; i++)
|
||||
if ((subitem= li++)) {
|
||||
if (!CheckCond(g, filp, tty, subitem)) {
|
||||
if (vop == OP_OR)
|
||||
if (vop == OP_OR || nonul)
|
||||
return NULL;
|
||||
else
|
||||
*p2= 0;
|
||||
@ -2599,6 +2655,8 @@ PCFIL ha_connect::CheckCond(PGLOBAL g, PCFIL filp, AMT tty, Item *cond)
|
||||
if (trace) {
|
||||
htrc("Field index=%d\n", pField->field->field_index);
|
||||
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
|
||||
|
||||
// IN and BETWEEN clauses should be col VOP list
|
||||
@ -2618,8 +2676,9 @@ PCFIL ha_connect::CheckCond(PGLOBAL g, PCFIL filp, AMT tty, Item *cond)
|
||||
char buff[256];
|
||||
String *res, tmp(buff, sizeof(buff), &my_charset_bin);
|
||||
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::INT_ITEM:
|
||||
case COND::REAL_ITEM:
|
||||
@ -2644,10 +2703,64 @@ PCFIL ha_connect::CheckCond(PGLOBAL g, PCFIL filp, AMT tty, Item *cond)
|
||||
|
||||
if (!x) {
|
||||
// Append the value to the filter
|
||||
if (args[i]->field_type() == MYSQL_TYPE_VARCHAR)
|
||||
strcat(strncat(strcat(body, "'"), res->ptr(), res->length()), "'");
|
||||
else
|
||||
strncat(body, res->ptr(), res->length());
|
||||
switch (args[i]->field_type()) {
|
||||
case MYSQL_TYPE_TIMESTAMP:
|
||||
case MYSQL_TYPE_DATETIME:
|
||||
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 {
|
||||
if (args[i]->field_type() == MYSQL_TYPE_VARCHAR) {
|
||||
@ -2753,7 +2866,7 @@ const COND *ha_connect::cond_push(const COND *cond)
|
||||
} else if (x && cond)
|
||||
tdbp->SetCondFil(filp); // Wrong filter
|
||||
|
||||
} else
|
||||
} else if (tty != TYPE_AM_JSN && tty != TYPE_AM_JSON)
|
||||
tdbp->SetFilter(CondFilter(g, (Item *)cond));
|
||||
|
||||
fin:
|
||||
@ -4620,7 +4733,7 @@ static bool add_field(String *sql, const char *field_name, int typ,
|
||||
char *dft, char *xtra, int flag, bool dbf, char v)
|
||||
{
|
||||
char var = (len > 255) ? 'V' : v;
|
||||
bool error= false;
|
||||
bool q, error= false;
|
||||
const char *type= PLGtoMYSQLtype(typ, dbf, var);
|
||||
|
||||
error|= sql->append('`');
|
||||
@ -4661,7 +4774,12 @@ static bool add_field(String *sql, const char *field_name, int typ,
|
||||
if (dft && *dft) {
|
||||
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_for_single_quote(dft, strlen(dft));
|
||||
error|= sql->append("'");
|
||||
@ -4831,6 +4949,9 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
|
||||
int port= 0, hdr= 0, mxr __attribute__((unused))= 0, mxe= 0, rc= 0;
|
||||
int cop __attribute__((unused)) = 0;
|
||||
#if defined(ODBC_SUPPORT)
|
||||
POPARM sop = NULL;
|
||||
char *ucnc = NULL;
|
||||
bool cnc= false;
|
||||
int cto= -1, qto= -1;
|
||||
#endif // ODBC_SUPPORT
|
||||
uint tm, fnc= FNC_NO, supfnc= (FNC_NO | FNC_COL);
|
||||
@ -4875,7 +4996,8 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
|
||||
|
||||
if (topt->oplist) {
|
||||
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.
|
||||
db= GetListOption(g, "database", topt->oplist, db);
|
||||
col= GetListOption(g, "colist", topt->oplist, col);
|
||||
@ -4894,6 +5016,9 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
|
||||
mxr= atoi(GetListOption(g,"maxres", topt->oplist, "0"));
|
||||
cto= atoi(GetListOption(g,"ConnectTimeout", 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
|
||||
mxe= atoi(GetListOption(g,"maxerr", topt->oplist, "0"));
|
||||
#if defined(PROMPT_OK)
|
||||
@ -4901,7 +5026,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
|
||||
#endif // PROMPT_OK
|
||||
} else {
|
||||
host= "localhost";
|
||||
user= "root";
|
||||
user= (ttp == TAB_ODBC ? NULL : "root");
|
||||
} // endif option_list
|
||||
|
||||
if (!(shm= (char*)db))
|
||||
@ -4978,10 +5103,18 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
|
||||
} // endif dsn
|
||||
#endif // PROMPT_OK
|
||||
|
||||
} else if (!dsn)
|
||||
} else if (!dsn) {
|
||||
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;
|
||||
} // endif's
|
||||
|
||||
supfnc |= (FNC_TABLE | FNC_DSN | FNC_DRIVER);
|
||||
break;
|
||||
@ -5112,15 +5245,15 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
|
||||
case FNC_NO:
|
||||
case FNC_COL:
|
||||
if (src) {
|
||||
qrp= ODBCSrcCols(g, dsn, (char*)src, cto, qto);
|
||||
qrp= ODBCSrcCols(g, dsn, (char*)src, sop);
|
||||
src= NULL; // for next tests
|
||||
} else
|
||||
qrp= ODBCColumns(g, dsn, shm, tab, NULL,
|
||||
mxr, cto, qto, fnc == FNC_COL);
|
||||
qrp= ODBCColumns(g, dsn, shm, tab, NULL,
|
||||
mxr, fnc == FNC_COL, sop);
|
||||
|
||||
break;
|
||||
case FNC_TABLE:
|
||||
qrp= ODBCTables(g, dsn, shm, tab, mxr, cto, qto, true);
|
||||
qrp= ODBCTables(g, dsn, shm, tab, mxr, true, sop);
|
||||
break;
|
||||
case FNC_DSN:
|
||||
qrp= ODBCDataSources(g, mxr, true);
|
||||
@ -5237,9 +5370,10 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
|
||||
for (crp= qrp->Colresp; crp; crp= crp->Next)
|
||||
switch (crp->Fld) {
|
||||
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, "UTF-8")))
|
||||
!stricmp(topt->data_charset, "UTF-8"))))
|
||||
cnm= crp->Kdata->GetCharValue(i);
|
||||
else
|
||||
cnm= encode(g, crp->Kdata->GetCharValue(i));
|
||||
@ -5299,9 +5433,18 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
|
||||
|
||||
// typ must be PLG type, not SQL type
|
||||
if (!(plgtyp= TranslateSQLType(typ, dec, prec, v))) {
|
||||
sprintf(g->Message, "Unsupported SQL type %d", typ);
|
||||
my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0));
|
||||
goto err;
|
||||
if (GetTypeConv() == TPC_SKIP) {
|
||||
// Skip this column
|
||||
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
|
||||
typ= plgtyp;
|
||||
|
||||
@ -6341,58 +6484,6 @@ struct st_mysql_storage_engine connect_storage_engine=
|
||||
/***********************************************************************/
|
||||
/* 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)
|
||||
// Using file mapping for indexes if true
|
||||
static MYSQL_SYSVAR_BOOL(indx_map, xmap, PLUGIN_VAR_RQCMDARG,
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -18,7 +18,8 @@ enum JTYP {TYPE_STRG = 1,
|
||||
TYPE_BOOL = 4,
|
||||
TYPE_INTG = 7,
|
||||
TYPE_JSON = 12,
|
||||
TYPE_JAR, TYPE_JOB,
|
||||
TYPE_JAR,
|
||||
TYPE_JOB,
|
||||
TYPE_JVAL};
|
||||
|
||||
class JOUT;
|
||||
@ -156,6 +157,9 @@ class JSON : public BLOCK {
|
||||
virtual void SetValue(PGLOBAL g, PJVAL jvp, PSZ key) {X}
|
||||
virtual void SetValue(PVAL valp) {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;}
|
||||
|
||||
protected:
|
||||
@ -171,6 +175,8 @@ class JOBJECT : public JSON {
|
||||
public:
|
||||
JOBJECT(void) : JSON() {First = Last = NULL;}
|
||||
|
||||
using JSON::GetValue;
|
||||
using JSON::SetValue;
|
||||
virtual void Clear(void) {First = Last = NULL; Size = 0;}
|
||||
virtual JTYP GetType(void) {return TYPE_JOB;}
|
||||
virtual PJPR AddPair(PGLOBAL g, PSZ key);
|
||||
@ -192,6 +198,8 @@ class JARRAY : public JSON {
|
||||
public:
|
||||
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 JTYP GetType(void) {return TYPE_JAR;}
|
||||
virtual PJAR GetArray(void) {return this;}
|
||||
@ -223,6 +231,8 @@ class JVALUE : public JSON {
|
||||
{Jsp = jsp; Value = NULL; Next = NULL; Del = false;}
|
||||
JVALUE(PGLOBAL g, PVAL valp);
|
||||
|
||||
using JSON::GetValue;
|
||||
using JSON::SetValue;
|
||||
virtual void Clear(void)
|
||||
{Jsp = NULL; Value = NULL; Next = NULL; Del = false; Size = 0;}
|
||||
virtual JTYP GetType(void) {return TYPE_JVAL;}
|
||||
@ -236,6 +246,9 @@ class JVALUE : public JSON {
|
||||
virtual PSZ GetString(void);
|
||||
virtual void SetValue(PVAL valp) {Value = valp;}
|
||||
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:
|
||||
PJSON Jsp; // To the json value
|
||||
|
494
storage/connect/jsonudf.cpp
Normal file
494
storage/connect/jsonudf.cpp
Normal file
@ -0,0 +1,494 @@
|
||||
/************* 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 <mysql.h>
|
||||
|
||||
#include "global.h"
|
||||
#include "plgdbsem.h"
|
||||
#include "json.h"
|
||||
|
||||
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_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 = 1024 + 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];
|
||||
PJVAL jvp = new(g) JVALUE;
|
||||
|
||||
if (sap) switch (args->arg_type[i]) {
|
||||
case STRING_RESULT:
|
||||
if (args->lengths[i]) {
|
||||
if (IsJson(args, i))
|
||||
jvp->SetValue(ParseJson(g, sap, args->lengths[i], 0));
|
||||
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
|
||||
|
||||
/***********************************************************************/
|
||||
/* 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 = 10;
|
||||
|
||||
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 *= n;
|
||||
|
||||
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;
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
} // 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 = 10;
|
||||
|
||||
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 *= n;
|
||||
|
||||
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;
|
||||
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;
|
||||
|
||||
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 (!(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;
|
||||
} // 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
|
||||
#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 char *mysqld_unix_port;
|
||||
|
||||
@ -265,7 +266,7 @@ PQRYRES MyColumns(PGLOBAL g, THD *thd, const char *host, const char *db,
|
||||
return NULL;
|
||||
} else if (type == TYPE_STRING) {
|
||||
if (v == 'X') {
|
||||
len = zconv;
|
||||
len = GetConvSize();
|
||||
sprintf(g->Message, "Column %s converted to varchar(%d)",
|
||||
colname, len);
|
||||
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';
|
||||
SELECT * FROM t1 WHERE ISBN = '9782212090819';
|
||||
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 Knab Construire une application XML Eyrolles Paris 1999
|
||||
9782212090819 fr applications Philippe Bernadac Construire une application XML Eyrolles Paris 1999
|
||||
9782212090819 fr applications François Knab Construire une application XML Eyrolles Paris 1999
|
||||
#
|
||||
# To add an author a new table must be created
|
||||
#
|
||||
@ -104,8 +104,8 @@ William J. Pardi
|
||||
INSERT INTO t2 VALUES('Charles','Dickens');
|
||||
SELECT * FROM t1;
|
||||
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 Knab Construire une application XML Eyrolles Paris 1999
|
||||
9782212090819 fr applications Philippe Bernadac Construire une application XML Eyrolles Paris 1999
|
||||
9782212090819 fr applications François Knab Construire une application XML Eyrolles Paris 1999
|
||||
9782840825685 fr applications William J. Pardi XML en Action adapté de l'anglais par James Guerin Microsoft Press Paris 1999
|
||||
9782840825685 fr applications Charles Dickens XML en Action adapté de l'anglais par James Guerin Microsoft Press Paris 1999
|
||||
DROP TABLE t1;
|
||||
@ -127,11 +127,11 @@ line
|
||||
"SUBJECT": "applications",
|
||||
"AUTHOR": [
|
||||
{
|
||||
"FIRSTNAME": "Jean-Christophe",
|
||||
"FIRSTNAME": "Philippe",
|
||||
"LASTNAME": "Bernadac"
|
||||
},
|
||||
{
|
||||
"FIRSTNAME": "Philippe",
|
||||
"FIRSTNAME": "François",
|
||||
"LASTNAME": "Knab"
|
||||
}
|
||||
],
|
||||
@ -192,7 +192,7 @@ Janet 4 Car 17.00
|
||||
Janet 5 Beer+Car+Beer+Food 57.00
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# Cannot be fully expanded
|
||||
# Now it can be fully expanded
|
||||
#
|
||||
CREATE TABLE t1 (
|
||||
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')
|
||||
ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='expense.jsn';
|
||||
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;
|
||||
#
|
||||
# Expand expense in 3 one week tables
|
||||
|
@ -128,7 +128,7 @@ SELECT * FROM t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
--echo #
|
||||
--echo # Cannot be fully expanded
|
||||
--echo # Now it can be fully expanded
|
||||
--echo #
|
||||
CREATE TABLE t1 (
|
||||
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',
|
||||
AMOUNT DOUBLE(8,2) FIELD_FORMAT='WEEK:[X]:EXPENSE:[X]:AMOUNT')
|
||||
ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='expense.jsn';
|
||||
--error ER_GET_ERRMSG
|
||||
#--error ER_GET_ERRMSG
|
||||
SELECT * FROM t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
|
@ -26,14 +26,16 @@
|
||||
#include "myutil.h"
|
||||
#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 */
|
||||
/************************************************************************/
|
||||
int MYSQLtoPLG(char *typname, char *var)
|
||||
{
|
||||
int type;
|
||||
int type;
|
||||
TYPCONV xconv = GetTypeConv();
|
||||
|
||||
if (!stricmp(typname, "int") || !stricmp(typname, "mediumint") ||
|
||||
!stricmp(typname, "integer"))
|
||||
@ -57,13 +59,13 @@ int MYSQLtoPLG(char *typname, char *var)
|
||||
type = TYPE_TINY;
|
||||
else if (!stricmp(typname, "text") && var) {
|
||||
switch (xconv) {
|
||||
case 1:
|
||||
case TPC_YES:
|
||||
type = TYPE_STRING;
|
||||
*var = 'X';
|
||||
break;
|
||||
case 2:
|
||||
case TPC_SKIP:
|
||||
*var = 'K';
|
||||
default:
|
||||
default: // TPC_NO
|
||||
type = TYPE_ERROR;
|
||||
} // endswitch xconv
|
||||
|
||||
@ -88,7 +90,7 @@ int MYSQLtoPLG(char *typname, char *var)
|
||||
} else if (type == TYPE_STRING && !stricmp(typname, "varchar"))
|
||||
// This is to make the difference between CHAR and VARCHAR
|
||||
*var = 'V';
|
||||
else if (type == TYPE_ERROR && xconv == 2)
|
||||
else if (type == TYPE_ERROR && xconv == TPC_SKIP)
|
||||
*var = 'K';
|
||||
else
|
||||
*var = 0;
|
||||
@ -174,7 +176,7 @@ const char *PLGtoMYSQLtype(int type, bool dbf, char v)
|
||||
/************************************************************************/
|
||||
int MYSQLtoPLG(int mytype, char *var)
|
||||
{
|
||||
int type;
|
||||
int type, xconv = GetTypeConv();
|
||||
|
||||
switch (mytype) {
|
||||
case MYSQL_TYPE_SHORT:
|
||||
@ -221,7 +223,7 @@ int MYSQLtoPLG(int mytype, char *var)
|
||||
case MYSQL_TYPE_LONG_BLOB:
|
||||
if (var) {
|
||||
switch (xconv) {
|
||||
case 1:
|
||||
case TPC_YES:
|
||||
if (*var != 'B') {
|
||||
// This is a TEXT column
|
||||
type = TYPE_STRING;
|
||||
@ -230,9 +232,9 @@ int MYSQLtoPLG(int mytype, char *var)
|
||||
type = TYPE_ERROR;
|
||||
|
||||
break;
|
||||
case 2:
|
||||
case TPC_SKIP:
|
||||
*var = 'K'; // Skip
|
||||
default:
|
||||
default: // TPC_NO
|
||||
type = TYPE_ERROR;
|
||||
} // endswitch xconv
|
||||
|
||||
|
@ -2,6 +2,14 @@
|
||||
#define DEFAULT_LOGIN_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. */
|
||||
/***********************************************************************/
|
||||
@ -10,8 +18,8 @@ char *ODBCCheckConnection(PGLOBAL g, char *dsn, int cop);
|
||||
#endif // PROMPT_OK
|
||||
PQRYRES ODBCDataSources(PGLOBAL g, int maxres, bool info);
|
||||
PQRYRES ODBCColumns(PGLOBAL g, char *dsn, char *db, char *table,
|
||||
char *colpat, int maxres, int cto, int qto, bool info);
|
||||
PQRYRES ODBCSrcCols(PGLOBAL g, char *dsn, char *src, int cto, int qto);
|
||||
char *colpat, int maxres, bool info, POPARM sop);
|
||||
PQRYRES ODBCSrcCols(PGLOBAL g, char *dsn, char *src, POPARM sop);
|
||||
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);
|
||||
|
@ -37,8 +37,8 @@
|
||||
#include "xobject.h"
|
||||
//#include "kindex.h"
|
||||
#include "xtable.h"
|
||||
#include "tabodbc.h"
|
||||
#include "odbccat.h"
|
||||
#include "tabodbc.h"
|
||||
#include "plgcnx.h" // For DB types
|
||||
#include "resource.h"
|
||||
#include "valblk.h"
|
||||
@ -53,6 +53,8 @@
|
||||
extern "C" HINSTANCE s_hModule; // Saved module handle
|
||||
#endif // WIN32
|
||||
|
||||
int GetConvSize();
|
||||
|
||||
/***********************************************************************/
|
||||
/* 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)
|
||||
v = 'V';
|
||||
type = TYPE_STRING;
|
||||
len = MY_MIN(abs(len), 256);
|
||||
len = MY_MIN(abs(len), GetConvSize());
|
||||
break;
|
||||
case SQL_NUMERIC: // 2
|
||||
case SQL_DECIMAL: // 3
|
||||
@ -291,7 +293,7 @@ static void ResetNullValues(CATPARM *cap)
|
||||
/* of an ODBC table that will be retrieved by GetData commands. */
|
||||
/***********************************************************************/
|
||||
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,
|
||||
TYPE_SHORT, TYPE_STRING, TYPE_INT, TYPE_INT,
|
||||
@ -310,10 +312,8 @@ PQRYRES ODBCColumns(PGLOBAL g, char *dsn, char *db, char *table,
|
||||
/************************************************************************/
|
||||
if (!info) {
|
||||
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;
|
||||
|
||||
if (table && !strchr(table, '%')) {
|
||||
@ -342,7 +342,7 @@ PQRYRES ODBCColumns(PGLOBAL g, char *dsn, char *db, char *table,
|
||||
} // endif ocp
|
||||
|
||||
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]);
|
||||
|
||||
/************************************************************************/
|
||||
@ -388,12 +388,13 @@ PQRYRES ODBCColumns(PGLOBAL g, char *dsn, char *db, char *table,
|
||||
/* ODBCSrcCols: constructs the result blocks containing the */
|
||||
/* 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);
|
||||
|
||||
ocp->SetLoginTimeout((DWORD)cto);
|
||||
ocp->SetQueryTimeout((DWORD)qto);
|
||||
if (ocp->Open(dsn, sop, 10) < 1) // openReadOnly + noOdbcDialog
|
||||
return NULL;
|
||||
|
||||
return ocp->GetMetaData(g, dsn, src);
|
||||
} // 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. */
|
||||
/**************************************************************************/
|
||||
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,
|
||||
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. */
|
||||
/**********************************************************************/
|
||||
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;
|
||||
|
||||
if (!maxres)
|
||||
@ -925,11 +924,14 @@ ODBConn::ODBConn(PGLOBAL g, TDBODBC *tdbp)
|
||||
m_Catver = (tdbp) ? tdbp->Catver : 0;
|
||||
m_Rows = 0;
|
||||
m_Connect = NULL;
|
||||
m_User = NULL;
|
||||
m_Pwd = NULL;
|
||||
m_Updatable = true;
|
||||
m_Transact = false;
|
||||
m_Scrollable = (tdbp) ? tdbp->Scrollable : false;
|
||||
m_First = true;
|
||||
m_Full = false;
|
||||
m_UseCnc = false;
|
||||
m_IDQuoteChar[0] = '"';
|
||||
m_IDQuoteChar[1] = 0;
|
||||
//*m_ErrMsg = '\0';
|
||||
@ -1061,7 +1063,7 @@ void ODBConn::OnSetOptions(HSTMT hstmt)
|
||||
/***********************************************************************/
|
||||
/* 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;
|
||||
//ASSERT_VALID(this);
|
||||
@ -1070,6 +1072,11 @@ int ODBConn::Open(PSZ ConnectString, DWORD options)
|
||||
|
||||
m_Updatable = !(options & openReadOnly);
|
||||
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
|
||||
try {
|
||||
@ -1078,10 +1085,14 @@ int ODBConn::Open(PSZ ConnectString, DWORD options)
|
||||
AllocConnect(options);
|
||||
/*ver = GetStringInfo(SQL_ODBC_VER);*/
|
||||
|
||||
if (Connect(options)) {
|
||||
strcpy(g->Message, MSG(CONNECT_CANCEL));
|
||||
return 0;
|
||||
} // endif
|
||||
if (!m_UseCnc) {
|
||||
if (DriverConnect(options)) {
|
||||
strcpy(g->Message, MSG(CONNECT_CANCEL));
|
||||
return 0;
|
||||
} // endif
|
||||
|
||||
} else // Connect using SQLConnect
|
||||
Connect();
|
||||
|
||||
/*ver = GetStringInfo(SQL_DRIVER_ODBC_VER);*/
|
||||
// Verify support for required functionality and cache info
|
||||
@ -1163,10 +1174,27 @@ void ODBConn::AllocConnect(DWORD Options)
|
||||
return;
|
||||
} // 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. */
|
||||
/***********************************************************************/
|
||||
bool ODBConn::Connect(DWORD Options)
|
||||
bool ODBConn::DriverConnect(DWORD Options)
|
||||
{
|
||||
RETCODE rc;
|
||||
SWORD nResult;
|
||||
@ -1213,7 +1241,7 @@ bool ODBConn::Connect(DWORD Options)
|
||||
|
||||
// All done
|
||||
return false;
|
||||
} // end of Connect
|
||||
} // end of DriverConnect
|
||||
|
||||
void ODBConn::VerifyConnect()
|
||||
{
|
||||
@ -1712,6 +1740,8 @@ bool ODBConn::BindParam(ODBCCOL *colp)
|
||||
strcpy(m_G->Message, x->GetErrorMessage(0));
|
||||
colsize = colp->GetPrecision();
|
||||
sqlt = GetSQLType(buftype);
|
||||
dec = IsTypeChar(buftype) ? 0 : colp->GetScale();
|
||||
nul = SQL_NULLABLE_UNKNOWN;
|
||||
} // end try/catch
|
||||
|
||||
buf = colp->GetBuffer(0);
|
||||
@ -1865,9 +1895,6 @@ PQRYRES ODBConn::GetMetaData(PGLOBAL g, char *dsn, char *src)
|
||||
RETCODE rc;
|
||||
HSTMT hstmt;
|
||||
|
||||
if (Open(dsn, 10) < 1) // openReadOnly + noOdbcDialog
|
||||
return NULL;
|
||||
|
||||
try {
|
||||
rc = SQLAllocStmt(m_hdbc, &hstmt);
|
||||
|
||||
|
@ -119,7 +119,7 @@ class ODBConn : public BLOCK {
|
||||
noOdbcDialog = 0x0008, // Don't 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);
|
||||
void Close(void);
|
||||
PQRYRES AllocateResult(PGLOBAL g);
|
||||
@ -135,8 +135,10 @@ class ODBConn : public BLOCK {
|
||||
|
||||
public:
|
||||
// Operations
|
||||
void SetLoginTimeout(DWORD sec) {m_LoginTimeout = sec;}
|
||||
void SetQueryTimeout(DWORD sec) {m_QueryTimeout = sec;}
|
||||
//void SetLoginTimeout(DWORD sec) {m_LoginTimeout = 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 ExecDirectSQL(char *sql, ODBCCOL *tocols);
|
||||
int Fetch(void);
|
||||
@ -155,7 +157,7 @@ class ODBConn : public BLOCK {
|
||||
|
||||
// Implementation
|
||||
public:
|
||||
// virtual ~ODBConn();
|
||||
//virtual ~ODBConn();
|
||||
|
||||
// ODBC operations
|
||||
protected:
|
||||
@ -163,7 +165,8 @@ class ODBConn : public BLOCK {
|
||||
void ThrowDBX(RETCODE rc, PSZ msg, HSTMT hstmt = SQL_NULL_HSTMT);
|
||||
void ThrowDBX(PSZ msg);
|
||||
void AllocConnect(DWORD dwOptions);
|
||||
bool Connect(DWORD Options);
|
||||
void Connect(void);
|
||||
bool DriverConnect(DWORD Options);
|
||||
void VerifyConnect(void);
|
||||
void GetConnectInfo(void);
|
||||
void Free(void);
|
||||
@ -185,11 +188,14 @@ class ODBConn : public BLOCK {
|
||||
DWORD m_RowsetSize;
|
||||
char m_IDQuoteChar[2];
|
||||
PSZ m_Connect;
|
||||
PSZ m_User;
|
||||
PSZ m_Pwd;
|
||||
int m_Catver;
|
||||
int m_Rows;
|
||||
bool m_Updatable;
|
||||
bool m_Transact;
|
||||
bool m_Scrollable;
|
||||
bool m_UseCnc;
|
||||
bool m_First;
|
||||
bool m_Full;
|
||||
}; // end of ODBConn class definition
|
||||
|
@ -222,6 +222,7 @@ class DllExport DOSCOL : public COLBLK {
|
||||
virtual PVBLK GetDval(void) {return Dval;}
|
||||
|
||||
// Methods
|
||||
using COLBLK::Print;
|
||||
virtual bool VarSize(void);
|
||||
virtual bool SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check);
|
||||
virtual void ReadColumn(PGLOBAL g);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/************* 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 */
|
||||
/* This program are the JSON class DB execution routines. */
|
||||
/***********************************************************************/
|
||||
@ -119,12 +119,12 @@ TDBJSN::TDBJSN(PJDEF tdp, PTXF txfp) : TDBDOS(tdp, txfp)
|
||||
Fpos = -1;
|
||||
Spos = N = 0;
|
||||
Limit = tdp->Limit;
|
||||
Pretty = tdp->Pretty;
|
||||
Strict = tdp->Strict;
|
||||
NextSame = false;
|
||||
Comma = false;
|
||||
NextSame = 0;
|
||||
SameRow = 0;
|
||||
Xval = -1;
|
||||
Pretty = tdp->Pretty;
|
||||
Strict = tdp->Strict;
|
||||
Comma = false;
|
||||
} // end of TDBJSN standard constructor
|
||||
|
||||
TDBJSN::TDBJSN(TDBJSN *tdbp) : TDBDOS(NULL, tdbp)
|
||||
@ -137,12 +137,12 @@ TDBJSN::TDBJSN(TDBJSN *tdbp) : TDBDOS(NULL, tdbp)
|
||||
Spos = tdbp->Spos;
|
||||
N = tdbp->N;
|
||||
Limit = tdbp->Limit;
|
||||
Pretty = tdbp->Pretty;
|
||||
Strict = tdbp->Strict;
|
||||
NextSame = tdbp->NextSame;
|
||||
Comma = tdbp->Comma;
|
||||
SameRow = tdbp->SameRow;
|
||||
Xval = tdbp->Xval;
|
||||
Pretty = tdbp->Pretty;
|
||||
Strict = tdbp->Strict;
|
||||
Comma = tdbp->Comma;
|
||||
} // end of TDBJSN copy constructor
|
||||
|
||||
// Used for update
|
||||
@ -221,14 +221,9 @@ bool TDBJSN::OpenDB(PGLOBAL g)
|
||||
/*******************************************************************/
|
||||
/* 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;
|
||||
Spos = 0;
|
||||
NextSame = false;
|
||||
NextSame = 0;
|
||||
SameRow = 0;
|
||||
} else {
|
||||
/*******************************************************************/
|
||||
@ -292,7 +287,8 @@ int TDBJSN::ReadDB(PGLOBAL g)
|
||||
N++;
|
||||
|
||||
if (NextSame) {
|
||||
SameRow++;
|
||||
SameRow = NextSame;
|
||||
NextSame = 0;
|
||||
return RC_OK;
|
||||
} else if ((rc = TDBDOS::ReadDB(g)) == RC_OK)
|
||||
if (!IsRead() && ((rc = ReadBuffer(g)) != RC_OK)) {
|
||||
@ -333,21 +329,20 @@ int TDBJSN::ReadDB(PGLOBAL g)
|
||||
|
||||
} // end of PrepareWriting
|
||||
|
||||
/* ----------------------------- JSNCOL ------------------------------- */
|
||||
/* ---------------------------- JSONCOL ------------------------------ */
|
||||
|
||||
/***********************************************************************/
|
||||
/* JSNCOL public constructor. */
|
||||
/* JSONCOL public constructor. */
|
||||
/***********************************************************************/
|
||||
JSONCOL::JSONCOL(PGLOBAL g, PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i)
|
||||
: DOSCOL(g, cdp, tdbp, cprec, i, "DOS")
|
||||
{
|
||||
Tjp = (TDBJSN *)(tdbp->GetOrig() ? tdbp->GetOrig() : tdbp);
|
||||
Arp = NULL;
|
||||
Jpath = cdp->GetFmt();
|
||||
MulVal = NULL;
|
||||
Nodes = NULL;
|
||||
Nod = Nx =0;
|
||||
Ival = -1;
|
||||
Nod = 0;
|
||||
Xnod = -1;
|
||||
Xpd = false;
|
||||
Parsed = false;
|
||||
} // 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)
|
||||
{
|
||||
Tjp = col1->Tjp;
|
||||
Arp = col1->Arp;
|
||||
Jpath = col1->Jpath;
|
||||
MulVal = col1->MulVal;
|
||||
Nodes = col1->Nodes;
|
||||
Nod = col1->Nod;
|
||||
Ival = col1->Ival;
|
||||
Nx = col1->Nx;
|
||||
Xnod = col1->Xnod;
|
||||
Xpd = col1->Xpd;
|
||||
Parsed = col1->Parsed;
|
||||
} // end of JSONCOL copy constructor
|
||||
@ -387,17 +380,16 @@ bool JSONCOL::SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check)
|
||||
} // end of SetBuffer
|
||||
|
||||
/***********************************************************************/
|
||||
/* Analyse array processing options. */
|
||||
/* Check whether this object is expanded. */
|
||||
/***********************************************************************/
|
||||
bool JSONCOL::CheckExpand(PGLOBAL g, int i, PSZ nm, bool b)
|
||||
{
|
||||
if (Tjp->Xcol && nm && !strcmp(nm, Tjp->Xcol) &&
|
||||
(Tjp->Xval < 0 || Tjp->Xval == i)) {
|
||||
if ((Tjp->Xcol && nm && !strcmp(nm, Tjp->Xcol) &&
|
||||
(Tjp->Xval < 0 || Tjp->Xval == i)) || Xpd) {
|
||||
Xpd = true; // Expandable object
|
||||
Nodes[i].Op = OP_XX;
|
||||
Tjp->Xval = i;
|
||||
Nodes[i].Op = OP_EXP;
|
||||
} else if (b) {
|
||||
strcpy(g->Message, "Cannot expand more than one array");
|
||||
strcpy(g->Message, "Cannot expand more than one branch");
|
||||
return true;
|
||||
} // endif Xcol
|
||||
|
||||
@ -434,7 +426,7 @@ bool JSONCOL::SetArrayOptions(PGLOBAL g, char *p, int i, PSZ nm)
|
||||
// Default specifications
|
||||
if (CheckExpand(g, i, nm, false))
|
||||
return true;
|
||||
else if (jnp->Op != OP_XX)
|
||||
else if (jnp->Op != OP_EXP)
|
||||
if (!Value->IsTypeNum()) {
|
||||
jnp->CncVal = AllocateValue(g, (void*)", ", TYPE_STRING);
|
||||
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_MAX; break;
|
||||
case '<': jnp->Op = OP_MIN; break;
|
||||
case '#': jnp->Op = OP_NUM; break;
|
||||
case '!': jnp->Op = OP_SEP; break; // Average
|
||||
case '#': jnp->Op = OP_NUM; break;
|
||||
case 'x':
|
||||
case 'X': // Expand this array
|
||||
if (!Tjp->Xcol && nm) {
|
||||
Xpd = true;
|
||||
jnp->Op = OP_XX;
|
||||
jnp->Op = OP_EXP;
|
||||
Tjp->Xval = i;
|
||||
Tjp->Xcol = nm;
|
||||
} else if (CheckExpand(g, i, nm, true))
|
||||
@ -490,6 +482,38 @@ bool JSONCOL::SetArrayOptions(PGLOBAL g, char *p, int i, PSZ nm)
|
||||
return true;
|
||||
} // 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;
|
||||
} // end of SetArrayOptions
|
||||
|
||||
@ -533,6 +557,9 @@ bool JSONCOL::ParseJpath(PGLOBAL g)
|
||||
if (SetArrayOptions(g, p, i, Nodes[i-1].Key))
|
||||
return true;
|
||||
|
||||
} else if (*p == '*') {
|
||||
// Return JSON
|
||||
Nodes[i].Op = OP_XX;
|
||||
} else {
|
||||
Nodes[i].Key = p;
|
||||
Nodes[i].Op = OP_EXIST;
|
||||
@ -545,60 +572,262 @@ bool JSONCOL::ParseJpath(PGLOBAL g)
|
||||
return false;
|
||||
} // 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. */
|
||||
/***********************************************************************/
|
||||
void JSONCOL::SetJsonValue(PGLOBAL g, PVAL vp, PJVAL val, int n)
|
||||
{
|
||||
if (val) {
|
||||
if (Nodes[n].Op == OP_NUM)
|
||||
vp->SetValue(1);
|
||||
else {
|
||||
again:
|
||||
switch (val->GetValType()) {
|
||||
case TYPE_STRG:
|
||||
case TYPE_INTG:
|
||||
case TYPE_DBL:
|
||||
vp->SetValue_pval(val->GetValue());
|
||||
switch (val->GetValType()) {
|
||||
case TYPE_STRG:
|
||||
case TYPE_INTG:
|
||||
case TYPE_DBL:
|
||||
vp->SetValue_pval(val->GetValue());
|
||||
break;
|
||||
case TYPE_BOOL:
|
||||
if (vp->IsTypeNum())
|
||||
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;
|
||||
case TYPE_BOOL:
|
||||
if (vp->IsTypeNum())
|
||||
vp->SetValue(val->GetInteger() ? 1 : 0);
|
||||
else
|
||||
vp->SetValue_psz((PSZ)(val->GetInteger() ? "true" : "false"));
|
||||
// } // endif Type
|
||||
|
||||
break;
|
||||
case TYPE_JAR:
|
||||
val = val->GetArray()->GetValue(0);
|
||||
goto again;
|
||||
case TYPE_JOB:
|
||||
if (!vp->IsTypeNum()) {
|
||||
vp->SetValue_psz(val->GetObject()->GetText(g));
|
||||
break;
|
||||
} // endif Type
|
||||
|
||||
default:
|
||||
vp->Reset();
|
||||
} // endswitch Type
|
||||
|
||||
} // endelse
|
||||
default:
|
||||
vp->Reset();
|
||||
} // endswitch Type
|
||||
|
||||
} else
|
||||
vp->Reset();
|
||||
|
||||
} // 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. */
|
||||
/***********************************************************************/
|
||||
PJSON JSONCOL::GetRow(PGLOBAL g, int mode)
|
||||
PJSON JSONCOL::GetRow(PGLOBAL g)
|
||||
{
|
||||
PJVAL val;
|
||||
PJAR arp;
|
||||
PJSON nwr, row = Tjp->Row;
|
||||
|
||||
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:
|
||||
if (!Nodes[i].Key)
|
||||
// Expected Array was not there
|
||||
@ -609,21 +838,13 @@ PJSON JSONCOL::GetRow(PGLOBAL g, int mode)
|
||||
case TYPE_JAR:
|
||||
if (!Nodes[i].Key) {
|
||||
if (Nodes[i].Op != OP_NULL) {
|
||||
Ival = i;
|
||||
arp = (PJAR)row;
|
||||
|
||||
if (mode < 2) // First pass
|
||||
Arp = arp;
|
||||
if (Nodes[i].Rank)
|
||||
val = arp->GetValue(Nodes[i].Rank - 1);
|
||||
else
|
||||
val = arp->GetValue(Nodes[i].Nx);
|
||||
|
||||
if (Nodes[i].Op != OP_XX) {
|
||||
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
|
||||
val = NULL;
|
||||
|
||||
@ -643,15 +864,16 @@ PJSON JSONCOL::GetRow(PGLOBAL g, int mode)
|
||||
|
||||
if (val) {
|
||||
row = val->GetJson();
|
||||
} else if (mode == 1) { // mode write
|
||||
} else {
|
||||
// Construct missing objects
|
||||
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
|
||||
nwr = new(g) JARRAY;
|
||||
} else {
|
||||
else
|
||||
nwr = new(g) JOBJECT;
|
||||
} // endif Nodes
|
||||
|
||||
if (row->GetType() == TYPE_JOB) {
|
||||
((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
|
||||
|
||||
break;
|
||||
} else
|
||||
row = NULL;
|
||||
} // endelse
|
||||
|
||||
} // endfor i
|
||||
|
||||
return row;
|
||||
} // 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: */
|
||||
/***********************************************************************/
|
||||
@ -817,10 +913,11 @@ void JSONCOL::WriteColumn(PGLOBAL g)
|
||||
if (Value->IsNull() && Tjp->Mode == MODE_INSERT)
|
||||
return;
|
||||
|
||||
char *s;
|
||||
PJOB objp = NULL;
|
||||
PJAR arp = NULL;
|
||||
PJVAL jvp = NULL;
|
||||
PJSON row = GetRow(g, 1);
|
||||
PJSON jsp, row = GetRow(g);
|
||||
JTYP type = row->GetType();
|
||||
|
||||
switch (row->GetType()) {
|
||||
@ -832,6 +929,28 @@ void JSONCOL::WriteColumn(PGLOBAL g)
|
||||
|
||||
if (row) switch (Buf_Type) {
|
||||
case TYPE_STRING:
|
||||
if (Nodes[Nod-1].Op == OP_XX) {
|
||||
s = Value->GetCharValue();
|
||||
jsp = ParseJson(g, s, (int)strlen(s), 0);
|
||||
|
||||
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_INT:
|
||||
case TYPE_DOUBLE:
|
||||
@ -1175,11 +1294,6 @@ bool TDBJSON::OpenDB(PGLOBAL g)
|
||||
/*******************************************************************/
|
||||
/* 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;
|
||||
Spos = 0;
|
||||
NextSame = false;
|
||||
@ -1217,7 +1331,8 @@ int TDBJSON::ReadDB(PGLOBAL g)
|
||||
N++;
|
||||
|
||||
if (NextSame) {
|
||||
SameRow++;
|
||||
SameRow = NextSame;
|
||||
NextSame = false;
|
||||
rc = RC_OK;
|
||||
} else if (++Fpos < (signed)Doc->size()) {
|
||||
Row = Doc->GetValue(Fpos);
|
||||
@ -1257,9 +1372,10 @@ int TDBJSON::WriteDB(PGLOBAL g)
|
||||
return RC_FX;
|
||||
|
||||
} else { // if (Jmode == MODE_VALUE)
|
||||
if (Mode == MODE_INSERT)
|
||||
if (Mode == MODE_INSERT) {
|
||||
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;
|
||||
|
||||
} // endif Jmode
|
||||
|
@ -16,8 +16,6 @@ typedef class JSONDEF *PJDEF;
|
||||
typedef class TDBJSON *PJTDB;
|
||||
typedef class JSONCOL *PJCOL;
|
||||
|
||||
class TDBJSN;
|
||||
|
||||
/***********************************************************************/
|
||||
/* 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
|
||||
OPVAL Op; // Operator used for this node
|
||||
PVAL CncVal; // To cont value used for OP_CNC
|
||||
PVAL Valp; // The internal array VALUE
|
||||
int Rank; // The rank in array
|
||||
int Nx; // Same row number
|
||||
} JNODE, *PJNODE;
|
||||
|
||||
/***********************************************************************/
|
||||
@ -77,7 +77,7 @@ class TDBJSN : public TDBDOS {
|
||||
virtual PTDB CopyOne(PTABS t);
|
||||
virtual PCOL MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n);
|
||||
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;}
|
||||
|
||||
// Database routines
|
||||
@ -98,11 +98,11 @@ class TDBJSN : public TDBDOS {
|
||||
int N; // The current Rownum
|
||||
int Limit; // Limit of multiple values
|
||||
int Pretty; // Depends on file structure
|
||||
bool Strict; // Strict syntax checking
|
||||
bool NextSame; // Same next row
|
||||
bool Comma; // Row has final comma
|
||||
int NextSame; // Same next row
|
||||
int SameRow; // Same row nb
|
||||
int Xval; // Index of expandable array
|
||||
bool Strict; // Strict syntax checking
|
||||
bool Comma; // Row has final comma
|
||||
}; // end of class TDBJSN
|
||||
|
||||
/* -------------------------- JSONCOL class -------------------------- */
|
||||
@ -130,8 +130,12 @@ class JSONCOL : public DOSCOL {
|
||||
protected:
|
||||
bool CheckExpand(PGLOBAL g, int i, PSZ nm, bool b);
|
||||
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);
|
||||
PJSON GetRow(PGLOBAL g);
|
||||
|
||||
// Default constructor not to be used
|
||||
JSONCOL(void) {}
|
||||
@ -139,12 +143,10 @@ class JSONCOL : public DOSCOL {
|
||||
// Members
|
||||
TDBJSN *Tjp; // To the JSN table block
|
||||
PVAL MulVal; // To value used by multiple column
|
||||
PJAR Arp; // The intermediate array
|
||||
char *Jpath; // The json path
|
||||
JNODE *Nodes ; // The intermediate objects
|
||||
JNODE *Nodes; // The intermediate objects
|
||||
int Nod; // The number of intermediate objects
|
||||
int Ival; // Index of multiple values
|
||||
int Nx; // The last read sub-row
|
||||
int Xnod; // Index of multiple values
|
||||
bool Xpd; // True for expandable column
|
||||
bool Parsed; // True when parsed
|
||||
}; // end of class JSONCOL
|
||||
|
@ -1141,19 +1141,16 @@ int TDBMYSQL::WriteDB(PGLOBAL g)
|
||||
int rc;
|
||||
uint len = Query->GetLength();
|
||||
char buf[64];
|
||||
bool b, oom = false;
|
||||
bool oom = false;
|
||||
|
||||
// Make the Insert command value list
|
||||
for (PCOL colp = Columns; colp; colp = colp->GetNext()) {
|
||||
if (!colp->GetValue()->IsNull()) {
|
||||
if ((b = colp->GetResultType() == TYPE_STRING ||
|
||||
colp->GetResultType() == TYPE_DATE))
|
||||
oom |= Query->Append('\'');
|
||||
|
||||
oom |= Query->Append(colp->GetValue()->GetCharString(buf));
|
||||
|
||||
if (b)
|
||||
oom |= Query->Append('\'');
|
||||
if (colp->GetResultType() == TYPE_STRING ||
|
||||
colp->GetResultType() == TYPE_DATE)
|
||||
oom |= Query->Append_quoted(colp->GetValue()->GetCharString(buf));
|
||||
else
|
||||
oom |= Query->Append(colp->GetValue()->GetCharString(buf));
|
||||
|
||||
} else
|
||||
oom |= Query->Append("NULL");
|
||||
|
@ -355,7 +355,7 @@ bool TDBOCCUR::MakeColumnList(PGLOBAL g)
|
||||
|
||||
for (colp = Columns; colp; colp = colp->GetNext())
|
||||
if (colp->GetAmType() == TYPE_AM_PRX)
|
||||
if (((PPRXCOL)colp)->Init(g))
|
||||
if (((PPRXCOL)colp)->Init(g, NULL))
|
||||
return true;
|
||||
|
||||
Col = (PCOL*)PlugSubAlloc(g, NULL, Mult * sizeof(PCOL));
|
||||
|
@ -66,8 +66,8 @@
|
||||
#include "plgdbsem.h"
|
||||
#include "mycat.h"
|
||||
#include "xtable.h"
|
||||
#include "tabodbc.h"
|
||||
#include "odbccat.h"
|
||||
#include "tabodbc.h"
|
||||
#include "tabmul.h"
|
||||
#include "reldef.h"
|
||||
#include "tabcol.h"
|
||||
@ -93,9 +93,10 @@ bool ExactInfo(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;
|
||||
Scrollable = Memory = Xsrc = false;
|
||||
Scrollable = Memory = Xsrc = UseCnc = false;
|
||||
} // end of ODBCDEF constructor
|
||||
|
||||
/***********************************************************************/
|
||||
@ -117,6 +118,8 @@ bool ODBCDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
|
||||
Tabschema = GetStringCatInfo(g, "Schema", Tabschema);
|
||||
Tabcat = GetStringCatInfo(g, "Qualifier", NULL);
|
||||
Tabcat = GetStringCatInfo(g, "Catalog", Tabcat);
|
||||
Username = GetStringCatInfo(g, "User", NULL);
|
||||
Password = GetStringCatInfo(g, "Password", NULL);
|
||||
|
||||
if ((Srcdef = GetStringCatInfo(g, "Srcdef", NULL)))
|
||||
Read_Only = true;
|
||||
@ -133,6 +136,7 @@ bool ODBCDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
|
||||
Cto= GetIntCatInfo("ConnectTimeout", DEFAULT_LOGIN_TIMEOUT);
|
||||
Qto= GetIntCatInfo("QueryTimeout", DEFAULT_QUERY_TIMEOUT);
|
||||
Scrollable = GetBoolCatInfo("Scrollable", false);
|
||||
UseCnc = GetBoolCatInfo("UseDSN", false);
|
||||
Memory = GetBoolCatInfo("Memory", false);
|
||||
Pseudo = 2; // FILID is Ok but not ROWID
|
||||
return false;
|
||||
@ -190,34 +194,40 @@ TDBODBC::TDBODBC(PODEF tdp) : TDBASE(tdp)
|
||||
Connect = tdp->Connect;
|
||||
TableName = tdp->Tabname;
|
||||
Schema = tdp->Tabschema;
|
||||
Ops.User = tdp->Username;
|
||||
Ops.Pwd = tdp->Password;
|
||||
Catalog = tdp->Tabcat;
|
||||
Srcdef = tdp->Srcdef;
|
||||
Qrystr = tdp->Qrystr;
|
||||
Sep = tdp->GetSep();
|
||||
Options = tdp->Options;
|
||||
Cto = tdp->Cto;
|
||||
Qto = tdp->Qto;
|
||||
Ops.Cto = tdp->Cto;
|
||||
Ops.Qto = tdp->Qto;
|
||||
Quoted = MY_MAX(0, tdp->GetQuoted());
|
||||
Rows = tdp->GetElemt();
|
||||
Catver = tdp->Catver;
|
||||
Memory = (tdp->Memory) ? 1 : 0;
|
||||
Scrollable = tdp->Scrollable;
|
||||
Ops.UseCnc = tdp->UseCnc;
|
||||
} else {
|
||||
Connect = NULL;
|
||||
TableName = NULL;
|
||||
Schema = NULL;
|
||||
Ops.User = NULL;
|
||||
Ops.Pwd = NULL;
|
||||
Catalog = NULL;
|
||||
Srcdef = NULL;
|
||||
Qrystr = NULL;
|
||||
Sep = 0;
|
||||
Options = 0;
|
||||
Cto = DEFAULT_LOGIN_TIMEOUT;
|
||||
Qto = DEFAULT_QUERY_TIMEOUT;
|
||||
Ops.Cto = DEFAULT_LOGIN_TIMEOUT;
|
||||
Ops.Qto = DEFAULT_QUERY_TIMEOUT;
|
||||
Quoted = 0;
|
||||
Rows = 0;
|
||||
Catver = 0;
|
||||
Memory = 0;
|
||||
Scrollable = false;
|
||||
Ops.UseCnc = false;
|
||||
} // endif tdp
|
||||
|
||||
Quote = NULL;
|
||||
@ -242,6 +252,7 @@ TDBODBC::TDBODBC(PTDBODBC tdbp) : TDBASE(tdbp)
|
||||
Connect = tdbp->Connect;
|
||||
TableName = tdbp->TableName;
|
||||
Schema = tdbp->Schema;
|
||||
Ops = tdbp->Ops;
|
||||
Catalog = tdbp->Catalog;
|
||||
Srcdef = tdbp->Srcdef;
|
||||
Qrystr = tdbp->Qrystr;
|
||||
@ -254,8 +265,6 @@ TDBODBC::TDBODBC(PTDBODBC tdbp) : TDBASE(tdbp)
|
||||
MulConn = tdbp->MulConn;
|
||||
DBQ = tdbp->DBQ;
|
||||
Options = tdbp->Options;
|
||||
Cto = tdbp->Cto;
|
||||
Qto = tdbp->Qto;
|
||||
Quoted = tdbp->Quoted;
|
||||
Rows = tdbp->Rows;
|
||||
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 *colist, *tabname, *sql, buf[64];
|
||||
char *colist, *tabname, *sql, buf[NAM_LEN * 3];
|
||||
LPCSTR schmp = NULL, catp = NULL;
|
||||
int len, ncol = 0;
|
||||
bool first = true;
|
||||
@ -474,6 +483,9 @@ char *TDBODBC::MakeSQL(PGLOBAL g, bool cnt)
|
||||
|
||||
if (To_CondFil)
|
||||
strcat(strcat(sql, " WHERE "), To_CondFil->Body);
|
||||
|
||||
if (trace)
|
||||
htrc("sql: '%s'\n", sql);
|
||||
|
||||
return sql;
|
||||
} // end of MakeSQL
|
||||
@ -483,7 +495,7 @@ char *TDBODBC::MakeSQL(PGLOBAL g, bool cnt)
|
||||
/***********************************************************************/
|
||||
char *TDBODBC::MakeInsert(PGLOBAL g)
|
||||
{
|
||||
char *stmt, *colist, *valist;
|
||||
char *stmt, *colist, *valist, buf[NAM_LEN * 3];
|
||||
// char *tk = "`";
|
||||
int len = 0;
|
||||
bool b = FALSE;
|
||||
@ -510,10 +522,13 @@ char *TDBODBC::MakeInsert(PGLOBAL g)
|
||||
} else
|
||||
b = true;
|
||||
|
||||
// Column name can be in UTF-8 encoding
|
||||
Decode(colp->GetName(), buf, sizeof(buf));
|
||||
|
||||
if (Quote)
|
||||
strcat(strcat(strcat(colist, Quote), colp->GetName()), Quote);
|
||||
strcat(strcat(strcat(colist, Quote), buf), Quote);
|
||||
else
|
||||
strcat(colist, colp->GetName());
|
||||
strcat(colist, buf);
|
||||
|
||||
strcat(valist, "?"); // Parameter marker
|
||||
} // endfor colp
|
||||
@ -558,8 +573,7 @@ bool TDBODBC::BindParameters(PGLOBAL g)
|
||||
/***********************************************************************/
|
||||
char *TDBODBC::MakeCommand(PGLOBAL g)
|
||||
{
|
||||
char *p, name[68], *qc = Ocp->GetQuoteChar();
|
||||
char *stmt = (char*)PlugSubAlloc(g, NULL, strlen(Qrystr) + 64);
|
||||
char *p, *stmt, name[68], *body = NULL, *qc = Ocp->GetQuoteChar();
|
||||
char *qrystr = (char*)PlugSubAlloc(g, NULL, strlen(Qrystr) + 1);
|
||||
bool qtd = Quoted > 0;
|
||||
int i = 0, k = 0;
|
||||
@ -570,6 +584,15 @@ char *TDBODBC::MakeCommand(PGLOBAL g)
|
||||
qrystr[i] = (Qrystr[i] == '`') ? *qc : tolower(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
|
||||
// If so, it must be quoted in the original query
|
||||
strlwr(strcat(strcat(strcpy(name, " "), Name), " "));
|
||||
@ -597,6 +620,9 @@ char *TDBODBC::MakeCommand(PGLOBAL g)
|
||||
stmt[i++] = (Qrystr[k] == '`') ? *qc : Qrystr[k];
|
||||
} while (Qrystr[k++]);
|
||||
|
||||
if (body)
|
||||
strcat(stmt, body);
|
||||
|
||||
} else {
|
||||
sprintf(g->Message, "Cannot use this %s command",
|
||||
(Mode == MODE_UPDATE) ? "UPDATE" : "DELETE");
|
||||
@ -698,10 +724,7 @@ int TDBODBC::Cardinality(PGLOBAL g)
|
||||
char qry[96], tbn[64];
|
||||
ODBConn *ocp = new(g) ODBConn(g, this);
|
||||
|
||||
ocp->SetLoginTimeout((DWORD)Cto);
|
||||
ocp->SetQueryTimeout((DWORD)Qto);
|
||||
|
||||
if (ocp->Open(Connect, Options) < 1)
|
||||
if (ocp->Open(Connect, &Ops, Options) < 1)
|
||||
return -1;
|
||||
|
||||
// Table name can be encoded in UTF-8
|
||||
@ -762,7 +785,7 @@ int TDBODBC::GetProgMax(PGLOBAL g)
|
||||
/***********************************************************************/
|
||||
bool TDBODBC::OpenDB(PGLOBAL g)
|
||||
{
|
||||
bool rc = false;
|
||||
bool rc = true;
|
||||
|
||||
if (g->Trace)
|
||||
htrc("ODBC OpenDB: tdbp=%p tdb=R%d use=%dmode=%d\n",
|
||||
@ -802,14 +825,12 @@ bool TDBODBC::OpenDB(PGLOBAL g)
|
||||
/* and if so to allocate just a new result set. But this only for */
|
||||
/* drivers allowing concurency in getting results ??? */
|
||||
/*********************************************************************/
|
||||
if (!Ocp) {
|
||||
if (!Ocp)
|
||||
Ocp = new(g) ODBConn(g, this);
|
||||
Ocp->SetLoginTimeout((DWORD)Cto);
|
||||
Ocp->SetQueryTimeout((DWORD)Qto);
|
||||
} else if (Ocp->IsOpen())
|
||||
else if (Ocp->IsOpen())
|
||||
Ocp->Close();
|
||||
|
||||
if (Ocp->Open(Connect, Options) < 1)
|
||||
if (Ocp->Open(Connect, &Ops, Options) < 1)
|
||||
return true;
|
||||
else if (Quoted)
|
||||
Quote = Ocp->GetQuoteChar();
|
||||
@ -839,12 +860,12 @@ bool TDBODBC::OpenDB(PGLOBAL g)
|
||||
|
||||
} // endif Query
|
||||
|
||||
} else if (Mode == MODE_UPDATE || Mode == MODE_DELETE)
|
||||
Query = MakeCommand(g);
|
||||
else
|
||||
} else if (Mode == MODE_UPDATE || Mode == MODE_DELETE) {
|
||||
rc = false; // wait for CheckCond before calling MakeCommand(g);
|
||||
} else
|
||||
sprintf(g->Message, "Invalid mode %d", Mode);
|
||||
|
||||
if (!Query || rc) {
|
||||
if (rc) {
|
||||
Ocp->Close();
|
||||
return true;
|
||||
} // endif rc
|
||||
@ -876,6 +897,9 @@ int TDBODBC::ReadDB(PGLOBAL g)
|
||||
GetTdb_No(), Mode, To_Key_Col, To_Link, To_Kindex);
|
||||
|
||||
if (Mode == MODE_UPDATE || Mode == MODE_DELETE) {
|
||||
if (!Query && !(Query = MakeCommand(g)))
|
||||
return RC_FX;
|
||||
|
||||
// Send the UPDATE/DELETE command to the remote table
|
||||
if (!Ocp->ExecSQLcommand(Query)) {
|
||||
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)
|
||||
{
|
||||
if (irc == RC_FX) {
|
||||
if (!Query && !(Query = MakeCommand(g)))
|
||||
return RC_FX;
|
||||
|
||||
// Send the DELETE (all) command to the remote table
|
||||
if (!Ocp->ExecSQLcommand(Query)) {
|
||||
sprintf(g->Message, "%s: %d affected rows", TableName, AftRows);
|
||||
@ -1415,12 +1442,10 @@ bool TDBXDBC::OpenDB(PGLOBAL g)
|
||||
/*********************************************************************/
|
||||
if (!Ocp) {
|
||||
Ocp = new(g) ODBConn(g, this);
|
||||
Ocp->SetLoginTimeout((DWORD)Cto);
|
||||
Ocp->SetQueryTimeout((DWORD)Qto);
|
||||
} else if (Ocp->IsOpen())
|
||||
Ocp->Close();
|
||||
|
||||
if (Ocp->Open(Connect, Options) < 1)
|
||||
if (Ocp->Open(Connect, &Ops, Options) < 1)
|
||||
return true;
|
||||
|
||||
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();
|
||||
Schema = tdp->GetTabschema();
|
||||
Tab = tdp->GetTabname();
|
||||
Cto = tdp->Cto;
|
||||
Qto = tdp->Qto;
|
||||
Ops.User = tdp->Username;
|
||||
Ops.Pwd = tdp->Password;
|
||||
Ops.Cto = tdp->Cto;
|
||||
Ops.Qto = tdp->Qto;
|
||||
Ops.UseCnc = tdp->UseCnc;
|
||||
} // end of TDBOTB constructor
|
||||
|
||||
/***********************************************************************/
|
||||
@ -1563,7 +1591,7 @@ TDBOTB::TDBOTB(PODEF tdp) : TDBDRV(tdp)
|
||||
/***********************************************************************/
|
||||
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
|
||||
|
||||
/* ---------------------------TDBOCL class --------------------------- */
|
||||
@ -1573,7 +1601,7 @@ PQRYRES TDBOTB::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 Tabodbc --------------------------- */
|
||||
|
@ -50,6 +50,8 @@ class DllExport ODBCDEF : public TABDEF { /* Logical table description */
|
||||
PSZ Connect; /* ODBC connection string */
|
||||
PSZ Tabname; /* External table name */
|
||||
PSZ Tabschema; /* External table schema */
|
||||
PSZ Username; /* User connect name */
|
||||
PSZ Password; /* Password connect info */
|
||||
PSZ Tabcat; /* External table catalog */
|
||||
PSZ Srcdef; /* The source table SQL definition */
|
||||
PSZ Qchar; /* Identifier quoting character */
|
||||
@ -65,6 +67,7 @@ class DllExport ODBCDEF : public TABDEF { /* Logical table description */
|
||||
bool Scrollable; /* Use scrollable cursor */
|
||||
bool Memory; /* Put result set in memory */
|
||||
bool Xsrc; /* Execution type */
|
||||
bool UseCnc; /* Use SQLConnect (!SQLDriverConnect) */
|
||||
}; // end of ODBCDEF
|
||||
|
||||
#if !defined(NODBC)
|
||||
@ -124,9 +127,12 @@ class TDBODBC : public TDBASE {
|
||||
// Members
|
||||
ODBConn *Ocp; // Points to an ODBC connection class
|
||||
ODBCCOL *Cnp; // Points to count(*) column
|
||||
ODBCPARM Ops; // Additional parameters
|
||||
char *Connect; // Points to connection string
|
||||
char *TableName; // Points to ODBC table name
|
||||
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 *Srcdef; // The source table SQL definition
|
||||
char *Query; // Points to SQL statement
|
||||
@ -151,6 +157,7 @@ class TDBODBC : public TDBASE {
|
||||
int Nparm; // The number of statement parameters
|
||||
int Memory; // 0: No 1: Alloc 2: Put 3: Get
|
||||
bool Scrollable; // Use scrollable cursor
|
||||
bool UseCnc; // Use SQLConnect (!SQLDriverConnect)
|
||||
PQRYRES Qrp; // Points to storage result
|
||||
}; // end of class TDBODBC
|
||||
|
||||
@ -316,8 +323,7 @@ class TDBOTB : public TDBDRV {
|
||||
char *Dsn; // Points to connection string
|
||||
char *Schema; // Points to schema name or NULL
|
||||
char *Tab; // Points to ODBC table name or pattern
|
||||
int Cto; // Connect timeout
|
||||
int Qto; // Query timeout
|
||||
ODBCPARM Ops; // Additional parameters
|
||||
}; // end of class TDBOTB
|
||||
|
||||
/***********************************************************************/
|
||||
|
@ -558,7 +558,7 @@ bool TDBPIVOT::MakePivotColumns(PGLOBAL g)
|
||||
// Check and initialize the subtable columns
|
||||
for (PCOL cp = Columns; cp; cp = cp->GetNext())
|
||||
if (cp->GetAmType() == TYPE_AM_SRC) {
|
||||
if (((PSRCCOL)cp)->Init(g))
|
||||
if (((PSRCCOL)cp)->Init(g, NULL))
|
||||
return TRUE;
|
||||
|
||||
} 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. */
|
||||
/***********************************************************************/
|
||||
bool SRCCOL::Init(PGLOBAL g)
|
||||
bool SRCCOL::Init(PGLOBAL g, PTDBASE tp)
|
||||
{
|
||||
if (PRXCOL::Init(g))
|
||||
if (PRXCOL::Init(g, tp))
|
||||
return true;
|
||||
|
||||
AddStatus(BUF_READ); // All is done here
|
||||
|
@ -180,9 +180,10 @@ class SRCCOL : public PRXCOL {
|
||||
virtual int GetAmType(void) {return TYPE_AM_SRC;}
|
||||
|
||||
// Methods
|
||||
using PRXCOL::Init;
|
||||
virtual void Reset(void) {}
|
||||
void SetColumn(void);
|
||||
bool Init(PGLOBAL g);
|
||||
virtual bool Init(PGLOBAL g, PTDBASE tp);
|
||||
bool CompareLast(void);
|
||||
|
||||
protected:
|
||||
|
@ -266,7 +266,7 @@ bool TDBTBL::InitTableList(PGLOBAL g)
|
||||
// Real initialization will be done later.
|
||||
for (colp = Columns; colp; colp = colp->GetNext())
|
||||
if (!colp->IsSpecial())
|
||||
if (((PPRXCOL)colp)->Init(g) && !Accept)
|
||||
if (((PPRXCOL)colp)->Init(g, NULL) && !Accept)
|
||||
return TRUE;
|
||||
|
||||
if (Tablist)
|
||||
@ -352,7 +352,9 @@ bool TDBTBL::TestFil(PGLOBAL g, PCFIL filp, PTABLE tabp)
|
||||
/***********************************************************************/
|
||||
int TDBTBL::Cardinality(PGLOBAL g)
|
||||
{
|
||||
if (Cardinal < 0) {
|
||||
if (!g)
|
||||
return 0; // Cannot make the table list
|
||||
else if (Cardinal < 0) {
|
||||
int tsz;
|
||||
|
||||
if (!Tablist && InitTableList(g))
|
||||
@ -468,7 +470,7 @@ bool TDBTBL::OpenDB(PGLOBAL g)
|
||||
for (PCOL cp = Columns; cp; cp = cp->GetNext())
|
||||
if (cp->GetAmType() == TYPE_AM_TABID)
|
||||
cp->COLBLK::Reset();
|
||||
else if (((PPRXCOL)cp)->Init(g) && !Accept)
|
||||
else if (((PPRXCOL)cp)->Init(g, NULL) && !Accept)
|
||||
return TRUE;
|
||||
|
||||
if (trace)
|
||||
@ -523,7 +525,7 @@ int TDBTBL::ReadDB(PGLOBAL g)
|
||||
if (cp->GetAmType() == TYPE_AM_TABID ||
|
||||
cp->GetAmType() == TYPE_AM_SRVID)
|
||||
cp->COLBLK::Reset();
|
||||
else if (((PPRXCOL)cp)->Init(g) && !Accept)
|
||||
else if (((PPRXCOL)cp)->Init(g, NULL) && !Accept)
|
||||
return RC_FX;
|
||||
|
||||
if (trace)
|
||||
@ -716,7 +718,7 @@ bool TDBTBM::OpenDB(PGLOBAL g)
|
||||
for (PCOL cp = Columns; cp; cp = cp->GetNext())
|
||||
if (cp->GetAmType() == TYPE_AM_TABID)
|
||||
cp->COLBLK::Reset();
|
||||
else if (((PPRXCOL)cp)->Init(g) && !Accept)
|
||||
else if (((PPRXCOL)cp)->Init(g, NULL) && !Accept)
|
||||
return TRUE;
|
||||
|
||||
if (trace)
|
||||
@ -807,7 +809,7 @@ int TDBTBM::ReadNextRemote(PGLOBAL g)
|
||||
for (PCOL cp = Columns; cp; cp = cp->GetNext())
|
||||
if (cp->GetAmType() == TYPE_AM_TABID)
|
||||
cp->COLBLK::Reset();
|
||||
else if (((PPRXCOL)cp)->Init(g) && !Accept)
|
||||
else if (((PPRXCOL)cp)->Init(g, NULL) && !Accept)
|
||||
return RC_FX;
|
||||
|
||||
if (trace)
|
||||
|
@ -54,7 +54,8 @@
|
||||
#include "tabutil.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 */
|
||||
@ -132,6 +133,7 @@ PQRYRES TabColumns(PGLOBAL g, THD *thd, const char *db,
|
||||
char *fld, *colname, *chset, *fmt, v;
|
||||
int i, n, ncol = sizeof(buftyp) / sizeof(int);
|
||||
int prec, len, type, scale;
|
||||
int zconv = GetConvSize();
|
||||
bool mysql;
|
||||
TABLE_SHARE *s = NULL;
|
||||
Field* *field;
|
||||
@ -668,6 +670,22 @@ PRXCOL::PRXCOL(PRXCOL *col1, PTDB tdbp) : COLBLK(col1, tdbp)
|
||||
Colnum = col1->Colnum;
|
||||
} // 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. */
|
||||
/* Look for the matching column in the object table. */
|
||||
@ -683,6 +701,9 @@ bool PRXCOL::Init(PGLOBAL g, PTDBASE tp)
|
||||
if (Colp) {
|
||||
MODE mode = To_Tdb->GetMode();
|
||||
|
||||
// Needed for MYSQL subtables
|
||||
((XCOLBLK*)Colp)->Name = Decode(g, Colp->GetName());
|
||||
|
||||
// May not have been done elsewhere
|
||||
Colp->InitValue(g);
|
||||
To_Val = Colp->GetValue();
|
||||
|
@ -108,15 +108,18 @@ class DllExport PRXCOL : public COLBLK {
|
||||
virtual int GetAmType(void) {return TYPE_AM_PRX;}
|
||||
|
||||
// Methods
|
||||
using COLBLK::Init;
|
||||
virtual void Reset(void);
|
||||
virtual bool IsSpecial(void) {return Pseudo;}
|
||||
virtual bool SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check)
|
||||
{return false;}
|
||||
virtual void ReadColumn(PGLOBAL g);
|
||||
virtual void WriteColumn(PGLOBAL g);
|
||||
virtual bool Init(PGLOBAL g, PTDBASE tp = NULL);
|
||||
virtual bool Init(PGLOBAL g, PTDBASE tp);
|
||||
|
||||
protected:
|
||||
char *Decode(PGLOBAL g, const char *cnm);
|
||||
|
||||
// Default constructor not to be used
|
||||
PRXCOL(void) {}
|
||||
|
||||
@ -144,4 +147,8 @@ class TDBTBC : public TDBCAT {
|
||||
PSZ Tab; // Table name
|
||||
}; // end of class TDBMCL
|
||||
|
||||
class XCOLBLK : public COLBLK {
|
||||
friend class PRXCOL;
|
||||
}; // end of class XCOLBLK
|
||||
|
||||
#endif // TABUTIL
|
||||
|
@ -183,7 +183,7 @@ bool TDBXCL::OpenDB(PGLOBAL g)
|
||||
/*********************************************************************/
|
||||
for (PCOL cp = Columns; cp; cp = cp->GetNext())
|
||||
if (!cp->IsSpecial())
|
||||
if (((PPRXCOL)cp)->Init(g))
|
||||
if (((PPRXCOL)cp)->Init(g, NULL))
|
||||
return TRUE;
|
||||
|
||||
/*********************************************************************/
|
||||
|
@ -88,6 +88,7 @@ class XCLCOL : public PRXCOL {
|
||||
XCLCOL(PGLOBAL g, PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i);
|
||||
|
||||
// Methods
|
||||
using PRXCOL::Init;
|
||||
virtual void Reset(void) {} // Evaluated only by TDBXCL
|
||||
virtual void ReadColumn(PGLOBAL g);
|
||||
virtual bool Init(PGLOBAL g, PTDBASE tp = NULL);
|
||||
|
@ -163,6 +163,7 @@ class TYPBLK : public VALBLK {
|
||||
virtual void Reset(int n) {Typp[n] = 0;}
|
||||
|
||||
// Methods
|
||||
using VALBLK::SetValue;
|
||||
virtual void SetValue(PSZ sp, int n);
|
||||
virtual void SetValue(char *sp, uint len, int n);
|
||||
virtual void SetValue(short sval, int n)
|
||||
@ -233,6 +234,7 @@ class CHRBLK : public VALBLK {
|
||||
virtual bool IsCi(void) {return Ci;}
|
||||
|
||||
// Methods
|
||||
using VALBLK::SetValue;
|
||||
virtual void SetValue(PSZ sp, int n);
|
||||
virtual void SetValue(char *sp, uint len, 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;}
|
||||
|
||||
// Methods
|
||||
using VALBLK::SetValue;
|
||||
virtual void SetValue(PSZ sp, int n);
|
||||
virtual void SetValue(char *sp, uint len, 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);
|
||||
|
||||
// Methods
|
||||
using TYPBLK<int>::SetValue;
|
||||
virtual void SetValue(PSZ sp, int n);
|
||||
|
||||
protected:
|
||||
@ -345,6 +349,8 @@ class PTRBLK : public STRBLK {
|
||||
// Implementation
|
||||
|
||||
// Methods
|
||||
using STRBLK::SetValue;
|
||||
using STRBLK::CompVal;
|
||||
virtual void SetValue(PSZ p, int n) {Strp[n] = p;}
|
||||
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();
|
||||
PVAL vp;
|
||||
|
||||
if (!valp)
|
||||
return NULL;
|
||||
|
||||
if (newtype == TYPE_VOID) // Means allocate a value of the same type
|
||||
newtype = valp->GetType();
|
||||
|
||||
@ -443,8 +446,8 @@ PVAL AllocateValue(PGLOBAL g, PVAL valp, int newtype, int uns)
|
||||
case TYPE_STRING:
|
||||
p = (PSZ)PlugSubAlloc(g, NULL, 1 + valp->GetValLen());
|
||||
|
||||
if ((sp = valp->GetCharString(p)) != p)
|
||||
strcpy (p, sp);
|
||||
if ((sp = valp->GetCharString(p)) != p && sp)
|
||||
strcpy(p, sp);
|
||||
|
||||
vp = new(g) TYPVAL<PSZ>(g, p, valp->GetValLen(), valp->GetValPrec());
|
||||
break;
|
||||
@ -1216,12 +1219,12 @@ TYPVAL<PSZ>::TYPVAL(PSZ s) : VALUE(TYPE_STRING)
|
||||
TYPVAL<PSZ>::TYPVAL(PGLOBAL g, PSZ s, int n, int c)
|
||||
: VALUE(TYPE_STRING)
|
||||
{
|
||||
Len = (g) ? n : strlen(s);
|
||||
Len = (g) ? n : (s) ? strlen(s) : 0;
|
||||
|
||||
if (!s) {
|
||||
if (g) {
|
||||
if ((Strp = (char *)PlgDBSubAlloc(g, NULL, Len + 1)))
|
||||
Strp[Len] = '\0';
|
||||
memset(Strp, 0, Len + 1);
|
||||
else
|
||||
Len = 0;
|
||||
|
||||
|
@ -391,6 +391,7 @@ class DllExport XHUGE : public XLOAD {
|
||||
XHUGE(void) : XLOAD() {}
|
||||
|
||||
// Methods
|
||||
using XLOAD::Close;
|
||||
virtual bool Open(PGLOBAL g, char *filename, int id, MODE mode);
|
||||
virtual bool Seek(PGLOBAL g, int low, int high, int origin);
|
||||
virtual bool Read(PGLOBAL g, void *buf, int n, int size);
|
||||
|
@ -346,6 +346,31 @@ bool STRING::Append(char c)
|
||||
return false;
|
||||
} // 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. */
|
||||
/* New size should be greater than string length. */
|
||||
|
@ -138,6 +138,7 @@ class DllExport STRING : public BLOCK {
|
||||
bool Append(STRING &str);
|
||||
bool Append(char c);
|
||||
bool Resize(uint n);
|
||||
bool Append_quoted(PSZ s);
|
||||
inline void Trim(void) {(void)Resize(Length + 1);}
|
||||
inline void Chop(void) {if (Length) Strp[--Length] = 0;}
|
||||
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 */
|
||||
new_block = btr_page_alloc(cursor->index, hint_page_no, direction,
|
||||
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_zip = buf_block_get_page_zip(new_block);
|
||||
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%
|
||||
of the total redo log size. This constraint on the blob length is to
|
||||
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
|
||||
dberr_t
|
||||
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
|
||||
* UNIV_PAGE_SIZE;
|
||||
const ulint redo_10p = redo_size / 10;
|
||||
ulint total_blob_len = 0;
|
||||
const ib_uint64_t redo_10p = redo_size / 10;
|
||||
ib_uint64_t total_blob_len = 0;
|
||||
dberr_t err = DB_SUCCESS;
|
||||
|
||||
/* 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) {
|
||||
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
|
||||
"). Please increase total redo log size.",
|
||||
total_blob_len, redo_size);
|
||||
err = DB_TOO_BIG_RECORD;
|
||||
err = DB_TOO_BIG_FOR_REDO;
|
||||
}
|
||||
|
||||
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.
|
||||
The fields are stored on pages allocated from leaf node
|
||||
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
|
||||
dberr_t
|
||||
btr_store_big_rec_extern_fields(
|
||||
|
@ -2427,10 +2427,10 @@ too_big:
|
||||
dict_mem_index_free(new_index);
|
||||
dict_mem_index_free(index);
|
||||
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);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -319,6 +319,9 @@ dict_mem_table_col_rename_low(
|
||||
ut_ad(from_len <= NAME_LEN);
|
||||
ut_ad(to_len <= NAME_LEN);
|
||||
|
||||
char from[NAME_LEN];
|
||||
strncpy(from, s, NAME_LEN);
|
||||
|
||||
if (from_len == to_len) {
|
||||
/* The easy case: simply replace the column name in
|
||||
table->col_names. */
|
||||
@ -386,14 +389,53 @@ dict_mem_table_col_rename_low(
|
||||
|
||||
foreign = *it;
|
||||
|
||||
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;
|
||||
if (foreign->foreign_index == NULL) {
|
||||
/* We may go here when we set foreign_key_checks to 0,
|
||||
and then try to rename a column and modify the
|
||||
corresponding foreign key constraint. The index
|
||||
would have been dropped, we have to find an equivalent
|
||||
one */
|
||||
for (unsigned f = 0; f < foreign->n_fields; f++) {
|
||||
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;
|
||||
|
||||
ut_ad(foreign->referenced_index != NULL);
|
||||
|
||||
for (unsigned f = 0; f < foreign->n_fields; f++) {
|
||||
/* foreign->referenced_col_names[] need to be
|
||||
copies, because the constraint may become
|
||||
|
@ -4957,6 +4957,9 @@ retry:
|
||||
success = TRUE;
|
||||
}
|
||||
|
||||
DBUG_EXECUTE_IF("ib_os_aio_func_io_failure_28",
|
||||
success = FALSE; errno = 28; os_has_said_disk_full = TRUE;);
|
||||
|
||||
mutex_enter(&fil_system->mutex);
|
||||
if (success) {
|
||||
node->size += n_pages;
|
||||
@ -4998,6 +5001,11 @@ retry:
|
||||
offset, page_size * n_pages,
|
||||
NULL, NULL);
|
||||
#endif /* UNIV_HOTBACKUP */
|
||||
|
||||
|
||||
DBUG_EXECUTE_IF("ib_os_aio_func_io_failure_28",
|
||||
success = FALSE; errno = 28; os_has_said_disk_full = TRUE;);
|
||||
|
||||
if (success) {
|
||||
os_has_said_disk_full = FALSE;
|
||||
} else {
|
||||
|
@ -694,3 +694,51 @@ fts_ast_string_print(
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
const char*
|
||||
fts_ast_oper_name_get(fts_ast_oper_t oper)
|
||||
{
|
||||
switch(oper) {
|
||||
case FTS_NONE:
|
||||
return("FTS_NONE");
|
||||
case FTS_IGNORE:
|
||||
return("FTS_IGNORE");
|
||||
case FTS_EXIST:
|
||||
return("FTS_EXIST");
|
||||
case FTS_NEGATE:
|
||||
return("FTS_NEGATE");
|
||||
case FTS_INCR_RATING:
|
||||
return("FTS_INCR_RATING");
|
||||
case FTS_DECR_RATING:
|
||||
return("FTS_DECR_RATING");
|
||||
case FTS_DISTANCE:
|
||||
return("FTS_DISTANCE");
|
||||
case FTS_IGNORE_SKIP:
|
||||
return("FTS_IGNORE_SKIP");
|
||||
case FTS_EXIST_SKIP:
|
||||
return("FTS_EXIST_SKIP");
|
||||
}
|
||||
ut_ad(0);
|
||||
}
|
||||
|
||||
const char*
|
||||
fts_ast_node_type_get(fts_ast_type_t type)
|
||||
{
|
||||
switch (type) {
|
||||
case FTS_AST_OPER:
|
||||
return("FTS_AST_OPER");
|
||||
case FTS_AST_NUMB:
|
||||
return("FTS_AST_NUMB");
|
||||
case FTS_AST_TERM:
|
||||
return("FTS_AST_TERM");
|
||||
case FTS_AST_TEXT:
|
||||
return("FTS_AST_TEXT");
|
||||
case FTS_AST_LIST:
|
||||
return("FTS_AST_LIST");
|
||||
case FTS_AST_SUBEXP_LIST:
|
||||
return("FTS_AST_SUBEXP_LIST");
|
||||
}
|
||||
ut_ad(0);
|
||||
}
|
||||
#endif /* UNIV_DEBUG */
|
||||
|
@ -2577,8 +2577,6 @@ fts_optimize_add_table(
|
||||
return;
|
||||
}
|
||||
|
||||
ut_ad(table->cached && table->fts != NULL);
|
||||
|
||||
/* Make sure table with FTS index cannot be evicted */
|
||||
if (table->can_be_evicted) {
|
||||
dict_table_move_from_lru_to_non_lru(table);
|
||||
|
@ -1534,7 +1534,8 @@ fts_merge_doc_ids(
|
||||
{
|
||||
const ib_rbt_node_t* node;
|
||||
|
||||
ut_a(!rbt_empty(doc_ids));
|
||||
DBUG_ENTER("fts_merge_doc_ids");
|
||||
|
||||
ut_a(!query->intersection);
|
||||
|
||||
/* To process FTS_EXIST operation (intersection), we need
|
||||
@ -1559,7 +1560,7 @@ fts_merge_doc_ids(
|
||||
query, ranking->doc_id, ranking->rank);
|
||||
|
||||
if (query->error != DB_SUCCESS) {
|
||||
return(query->error);
|
||||
DBUG_RETURN(query->error);
|
||||
}
|
||||
|
||||
/* Merge words. Don't need to take operator into account. */
|
||||
@ -1578,7 +1579,7 @@ fts_merge_doc_ids(
|
||||
query->intersection = NULL;
|
||||
}
|
||||
|
||||
return(DB_SUCCESS);
|
||||
DBUG_RETURN(DB_SUCCESS);
|
||||
}
|
||||
|
||||
/*****************************************************************//**
|
||||
@ -2839,11 +2840,11 @@ fts_query_visitor(
|
||||
fts_query_t* query = static_cast<fts_query_t*>(arg);
|
||||
|
||||
ut_a(node);
|
||||
DBUG_ENTER("fts_query_visitor");
|
||||
DBUG_PRINT("fts", ("nodetype: %s", fts_ast_node_type_get(node->type)));
|
||||
|
||||
token.f_n_char = 0;
|
||||
|
||||
query->oper = oper;
|
||||
|
||||
query->cur_node = node;
|
||||
|
||||
switch (node->type) {
|
||||
@ -2905,7 +2906,7 @@ fts_query_visitor(
|
||||
query->multi_exist = true;
|
||||
}
|
||||
|
||||
return(query->error);
|
||||
DBUG_RETURN(query->error);
|
||||
}
|
||||
|
||||
/*****************************************************************//**
|
||||
@ -2929,6 +2930,8 @@ fts_ast_visit_sub_exp(
|
||||
bool will_be_ignored = false;
|
||||
bool multi_exist;
|
||||
|
||||
DBUG_ENTER("fts_ast_visit_sub_exp");
|
||||
|
||||
ut_a(node->type == FTS_AST_SUBEXP_LIST);
|
||||
|
||||
cur_oper = query->oper;
|
||||
@ -2957,14 +2960,14 @@ fts_ast_visit_sub_exp(
|
||||
/* Merge the sub-expression result with the parent result set. */
|
||||
subexpr_doc_ids = query->doc_ids;
|
||||
query->doc_ids = parent_doc_ids;
|
||||
if (error == DB_SUCCESS && !rbt_empty(subexpr_doc_ids)) {
|
||||
if (error == DB_SUCCESS) {
|
||||
error = fts_merge_doc_ids(query, subexpr_doc_ids);
|
||||
}
|
||||
|
||||
/* Free current result set. Result already merged into parent. */
|
||||
fts_query_free_doc_ids(query, subexpr_doc_ids);
|
||||
|
||||
return(error);
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
|
||||
#if 0
|
||||
@ -3440,8 +3443,10 @@ fts_retrieve_ranking(
|
||||
ib_rbt_bound_t parent;
|
||||
fts_ranking_t new_ranking;
|
||||
|
||||
DBUG_ENTER("fts_retrieve_ranking");
|
||||
|
||||
if (!result || !result->rankings_by_id) {
|
||||
return(0);
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
new_ranking.doc_id = doc_id;
|
||||
@ -3452,10 +3457,10 @@ fts_retrieve_ranking(
|
||||
|
||||
ranking = rbt_value(fts_ranking_t, parent.last);
|
||||
|
||||
return(ranking->rank);
|
||||
DBUG_RETURN(ranking->rank);
|
||||
}
|
||||
|
||||
return(0);
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
/*****************************************************************//**
|
||||
@ -3472,6 +3477,8 @@ fts_query_prepare_result(
|
||||
const ib_rbt_node_t* node;
|
||||
bool result_is_null = false;
|
||||
|
||||
DBUG_ENTER("fts_query_prepare_result");
|
||||
|
||||
if (result == NULL) {
|
||||
result = static_cast<fts_result_t*>(ut_malloc(sizeof(*result)));
|
||||
|
||||
@ -3520,7 +3527,7 @@ fts_query_prepare_result(
|
||||
if (query->total_size > fts_result_cache_limit) {
|
||||
query->error = DB_FTS_EXCEED_RESULT_CACHE_LIMIT;
|
||||
fts_query_free_result(result);
|
||||
return(NULL);
|
||||
DBUG_RETURN(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3543,7 +3550,7 @@ fts_query_prepare_result(
|
||||
ranking->rank * word_freq->idf * word_freq->idf);
|
||||
}
|
||||
|
||||
return(result);
|
||||
DBUG_RETURN(result);
|
||||
}
|
||||
|
||||
ut_a(rbt_size(query->doc_ids) > 0);
|
||||
@ -3570,7 +3577,7 @@ fts_query_prepare_result(
|
||||
if (query->total_size > fts_result_cache_limit) {
|
||||
query->error = DB_FTS_EXCEED_RESULT_CACHE_LIMIT;
|
||||
fts_query_free_result(result);
|
||||
return(NULL);
|
||||
DBUG_RETURN(NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3582,7 +3589,7 @@ fts_query_prepare_result(
|
||||
query->doc_ids = NULL;
|
||||
}
|
||||
|
||||
return(result);
|
||||
DBUG_RETURN(result);
|
||||
}
|
||||
|
||||
/*****************************************************************//**
|
||||
@ -3594,6 +3601,8 @@ fts_query_get_result(
|
||||
fts_query_t* query, /*!< in: query instance */
|
||||
fts_result_t* result) /*!< in: result */
|
||||
{
|
||||
DBUG_ENTER("fts_query_get_result");
|
||||
|
||||
if (rbt_size(query->doc_ids) > 0 || query->flags == FTS_OPT_RANKING) {
|
||||
/* Copy the doc ids to the result. */
|
||||
result = fts_query_prepare_result(query, result);
|
||||
@ -3603,7 +3612,7 @@ fts_query_get_result(
|
||||
memset(result, 0, sizeof(*result));
|
||||
}
|
||||
|
||||
return(result);
|
||||
DBUG_RETURN(result);
|
||||
}
|
||||
|
||||
/*****************************************************************//**
|
||||
@ -3681,6 +3690,7 @@ fts_query_parse(
|
||||
int error;
|
||||
fts_ast_state_t state;
|
||||
bool mode = query->boolean_mode;
|
||||
DBUG_ENTER("fts_query_parse");
|
||||
|
||||
memset(&state, 0x0, sizeof(state));
|
||||
|
||||
@ -3699,7 +3709,7 @@ fts_query_parse(
|
||||
query->root = state.root;
|
||||
}
|
||||
|
||||
return(state.root);
|
||||
DBUG_RETURN(state.root);
|
||||
}
|
||||
|
||||
/*******************************************************************//**
|
||||
|
@ -1531,6 +1531,15 @@ convert_error_code_to_mysql(
|
||||
return(HA_ERR_TO_BIG_ROW);
|
||||
}
|
||||
|
||||
|
||||
case DB_TOO_BIG_FOR_REDO:
|
||||
my_printf_error(ER_TOO_BIG_ROWSIZE, "%s" , MYF(0),
|
||||
"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.");
|
||||
return(HA_ERR_TO_BIG_ROW);
|
||||
|
||||
case DB_TOO_BIG_INDEX_COL:
|
||||
my_error(ER_INDEX_COLUMN_TOO_LONG, MYF(0),
|
||||
DICT_MAX_FIELD_LEN_BY_FORMAT_FLAG(flags));
|
||||
@ -13857,10 +13866,8 @@ ha_innobase::cmp_ref(
|
||||
len1 = innobase_read_from_2_little_endian(ref1);
|
||||
len2 = innobase_read_from_2_little_endian(ref2);
|
||||
|
||||
ref1 += 2;
|
||||
ref2 += 2;
|
||||
result = ((Field_blob*) field)->cmp(
|
||||
ref1, len1, ref2, len2);
|
||||
ref1 + 2, len1, ref2 + 2, len2);
|
||||
} else {
|
||||
result = field->key_cmp(ref1, ref2);
|
||||
}
|
||||
|
@ -4435,11 +4435,15 @@ err_exit:
|
||||
rename_foreign:
|
||||
trx->op_info = "renaming column in SYS_FOREIGN_COLS";
|
||||
|
||||
std::list<dict_foreign_t*> fk_evict;
|
||||
bool foreign_modified;
|
||||
|
||||
for (dict_foreign_set::const_iterator it = user_table->foreign_set.begin();
|
||||
it != user_table->foreign_set.end();
|
||||
++it) {
|
||||
|
||||
dict_foreign_t* foreign = *it;
|
||||
foreign_modified = false;
|
||||
|
||||
for (unsigned i = 0; i < foreign->n_fields; i++) {
|
||||
if (strcmp(foreign->foreign_col_names[i], from)) {
|
||||
@ -4467,6 +4471,11 @@ rename_foreign:
|
||||
if (error != DB_SUCCESS) {
|
||||
goto err_exit;
|
||||
}
|
||||
foreign_modified = true;
|
||||
}
|
||||
|
||||
if (foreign_modified) {
|
||||
fk_evict.push_back(foreign);
|
||||
}
|
||||
}
|
||||
|
||||
@ -4475,7 +4484,9 @@ rename_foreign:
|
||||
it != user_table->referenced_set.end();
|
||||
++it) {
|
||||
|
||||
foreign_modified = false;
|
||||
dict_foreign_t* foreign = *it;
|
||||
|
||||
for (unsigned i = 0; i < foreign->n_fields; i++) {
|
||||
if (strcmp(foreign->referenced_col_names[i], from)) {
|
||||
continue;
|
||||
@ -4502,7 +4513,17 @@ rename_foreign:
|
||||
if (error != DB_SUCCESS) {
|
||||
goto err_exit;
|
||||
}
|
||||
foreign_modified = true;
|
||||
}
|
||||
|
||||
if (foreign_modified) {
|
||||
fk_evict.push_back(foreign);
|
||||
}
|
||||
}
|
||||
|
||||
if (new_clustered) {
|
||||
std::for_each(fk_evict.begin(), fk_evict.end(),
|
||||
dict_foreign_remove_from_cache);
|
||||
}
|
||||
|
||||
trx->op_info = "";
|
||||
|
@ -3893,7 +3893,7 @@ check_watch:
|
||||
{
|
||||
buf_page_t* bpage;
|
||||
buf_pool_t* buf_pool = buf_pool_get(space, page_no);
|
||||
bpage = buf_page_hash_get(buf_pool, space, page_no);
|
||||
bpage = buf_page_get_also_watch(buf_pool, space, page_no);
|
||||
|
||||
if (UNIV_LIKELY_NULL(bpage)) {
|
||||
/* A buffer pool watch has been set or the
|
||||
|
@ -1268,7 +1268,7 @@ page_hash lock is acquired in the specified lock mode. Otherwise,
|
||||
mode value is ignored. It is up to the caller to release the
|
||||
lock. If the block is found and the lock is NULL then the page_hash
|
||||
lock is released by this function.
|
||||
@return block, NULL if not found */
|
||||
@return block, NULL if not found, or watch sentinel (if watch is true) */
|
||||
UNIV_INLINE
|
||||
buf_page_t*
|
||||
buf_page_hash_get_locked(
|
||||
@ -1284,9 +1284,11 @@ buf_page_hash_get_locked(
|
||||
found. NULL otherwise. If NULL
|
||||
is passed then the hash_lock
|
||||
is released by this function */
|
||||
ulint lock_mode); /*!< in: RW_LOCK_EX or
|
||||
ulint lock_mode, /*!< in: RW_LOCK_EX or
|
||||
RW_LOCK_SHARED. Ignored if
|
||||
lock == NULL */
|
||||
bool watch = false); /*!< in: if true, return watch
|
||||
sentinel also. */
|
||||
/******************************************************************//**
|
||||
Returns the control block of a file page, NULL if not found.
|
||||
If the block is found and lock is not NULL then the appropriate
|
||||
@ -1326,6 +1328,8 @@ buf_page_hash_get_low() function.
|
||||
buf_page_hash_get_locked(b, s, o, l, RW_LOCK_EX)
|
||||
#define buf_page_hash_get(b, s, o) \
|
||||
buf_page_hash_get_locked(b, s, o, NULL, 0)
|
||||
#define buf_page_get_also_watch(b, s, o) \
|
||||
buf_page_hash_get_locked(b, s, o, NULL, 0, true)
|
||||
|
||||
#define buf_block_hash_get_s_locked(b, s, o, l) \
|
||||
buf_block_hash_get_locked(b, s, o, l, RW_LOCK_SHARED)
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1995, 2013, Oracle and/or its affiliates. All Rights Reserved.
|
||||
Copyright (c) 1995, 2014, Oracle and/or its affiliates. All Rights Reserved.
|
||||
Copyright (c) 2008, Google Inc.
|
||||
|
||||
Portions of this file contain modifications contributed and copyrighted by
|
||||
@ -1172,7 +1172,7 @@ page_hash lock is acquired in the specified lock mode. Otherwise,
|
||||
mode value is ignored. It is up to the caller to release the
|
||||
lock. If the block is found and the lock is NULL then the page_hash
|
||||
lock is released by this function.
|
||||
@return block, NULL if not found */
|
||||
@return block, NULL if not found, or watch sentinel (if watch is true) */
|
||||
UNIV_INLINE
|
||||
buf_page_t*
|
||||
buf_page_hash_get_locked(
|
||||
@ -1188,9 +1188,11 @@ buf_page_hash_get_locked(
|
||||
found. NULL otherwise. If NULL
|
||||
is passed then the hash_lock
|
||||
is released by this function */
|
||||
ulint lock_mode) /*!< in: RW_LOCK_EX or
|
||||
ulint lock_mode, /*!< in: RW_LOCK_EX or
|
||||
RW_LOCK_SHARED. Ignored if
|
||||
lock == NULL */
|
||||
bool watch) /*!< in: if true, return watch
|
||||
sentinel also. */
|
||||
{
|
||||
buf_page_t* bpage = NULL;
|
||||
ulint fold;
|
||||
@ -1221,7 +1223,9 @@ buf_page_hash_get_locked(
|
||||
bpage = buf_page_hash_get_low(buf_pool, space, offset, fold);
|
||||
|
||||
if (!bpage || buf_pool_watch_is_sentinel(buf_pool, bpage)) {
|
||||
bpage = NULL;
|
||||
if (!watch) {
|
||||
bpage = NULL;
|
||||
}
|
||||
goto unlock_and_exit;
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1996, 2012, Oracle and/or its affiliates. All Rights Reserved.
|
||||
Copyright (c) 1996, 2014, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
@ -130,7 +130,8 @@ enum dberr_t {
|
||||
DB_TEMP_FILE_WRITE_FAILURE, /*!< Temp file write failure */
|
||||
DB_FTS_TOO_MANY_WORDS_IN_PHRASE,
|
||||
/*< Too many words in a phrase */
|
||||
|
||||
DB_TOO_BIG_FOR_REDO, /* Record length greater than 10%
|
||||
of redo log */
|
||||
/* The following are partial failure codes */
|
||||
DB_FAIL = 1000,
|
||||
DB_OVERFLOW,
|
||||
|
@ -329,4 +329,11 @@ struct fts_ast_state_t {
|
||||
tokenization */
|
||||
};
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
const char*
|
||||
fts_ast_oper_name_get(fts_ast_oper_t oper);
|
||||
const char*
|
||||
fts_ast_node_type_get(fts_ast_type_t type);
|
||||
#endif /* UNIV_DEBUG */
|
||||
|
||||
#endif /* INNOBASE_FSTS0AST_H */
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 2006, 2013, Oracle and/or its affiliates. All Rights Reserved.
|
||||
Copyright (c) 2006, 2014, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
|
@ -1,6 +1,6 @@
|
||||
/***********************************************************************
|
||||
|
||||
Copyright (c) 1995, 2013, Oracle and/or its affiliates. All Rights Reserved.
|
||||
Copyright (c) 1995, 2014, Oracle and/or its affiliates. All Rights Reserved.
|
||||
Copyright (c) 2009, Percona Inc.
|
||||
|
||||
Portions of this file contain modifications contributed and copyrighted
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 2005, 2013, Oracle and/or its affiliates. All Rights Reserved.
|
||||
Copyright (c) 2005, 2014, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1996, 2012, Oracle and/or its affiliates. All Rights Reserved.
|
||||
Copyright (c) 1996, 2014, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
@ -32,6 +32,8 @@ Created 3/26/1996 Heikki Tuuri
|
||||
#include "mtr0mtr.h"
|
||||
#include "trx0sys.h"
|
||||
|
||||
extern bool trx_rollback_or_clean_is_active;
|
||||
|
||||
/*******************************************************************//**
|
||||
Determines if this transaction is rolling back an incomplete transaction
|
||||
in crash recovery.
|
||||
|
@ -44,7 +44,7 @@ Created 1/20/1994 Heikki Tuuri
|
||||
|
||||
#define INNODB_VERSION_MAJOR 5
|
||||
#define INNODB_VERSION_MINOR 6
|
||||
#define INNODB_VERSION_BUGFIX 22
|
||||
#define INNODB_VERSION_BUGFIX 23
|
||||
|
||||
/* The following is the InnoDB version as shown in
|
||||
SELECT plugin_version FROM information_schema.plugins;
|
||||
|
@ -2066,7 +2066,8 @@ lock_rec_add_to_queue(
|
||||
|
||||
ut_ad(lock_mutex_own());
|
||||
ut_ad(caller_owns_trx_mutex == trx_mutex_own(trx));
|
||||
ut_ad(dict_index_is_clust(index) || !dict_index_is_online_ddl(index));
|
||||
ut_ad(dict_index_is_clust(index)
|
||||
|| dict_index_get_online_status(index) != ONLINE_INDEX_CREATION);
|
||||
#ifdef UNIV_DEBUG
|
||||
switch (type_mode & LOCK_MODE_MASK) {
|
||||
case LOCK_X:
|
||||
@ -5163,7 +5164,14 @@ lock_rec_print(
|
||||
fprintf(file, "RECORD LOCKS space id %lu page no %lu n bits %lu ",
|
||||
(ulong) space, (ulong) page_no,
|
||||
(ulong) lock_rec_get_n_bits(lock));
|
||||
|
||||
dict_index_name_print(file, lock->trx, lock->index);
|
||||
|
||||
/* Print number of table locks */
|
||||
fprintf(file, " trx table locks %lu total table locks %lu ",
|
||||
ib_vector_size(lock->trx->lock.table_locks),
|
||||
UT_LIST_GET_LEN(lock->index->table->locks));
|
||||
|
||||
fprintf(file, " trx id " TRX_ID_FMT, lock->trx->id);
|
||||
|
||||
if (lock_get_mode(lock) == LOCK_S) {
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1995, 2013, Oracle and/or its affiliates. All Rights Reserved.
|
||||
Copyright (c) 1995, 2014, Oracle and/or its affiliates. All Rights Reserved.
|
||||
Copyright (c) 2009, Google Inc.
|
||||
|
||||
Portions of this file contain modifications contributed and copyrighted by
|
||||
@ -48,7 +48,7 @@ Created 12/9/1995 Heikki Tuuri
|
||||
#include "srv0start.h"
|
||||
#include "trx0sys.h"
|
||||
#include "trx0trx.h"
|
||||
#include "ha_prototypes.h"
|
||||
#include "trx0roll.h"
|
||||
#include "srv0mon.h"
|
||||
|
||||
/*
|
||||
@ -3212,6 +3212,12 @@ logs_empty_and_mark_files_at_shutdown(void)
|
||||
|
||||
ib_logf(IB_LOG_LEVEL_INFO, "Starting shutdown...");
|
||||
|
||||
while (srv_fast_shutdown == 0 && trx_rollback_or_clean_is_active) {
|
||||
/* we should wait until rollback after recovery end
|
||||
for slow shutdown */
|
||||
os_thread_sleep(100000);
|
||||
}
|
||||
|
||||
/* Wait until the master thread and all other operations are idle: our
|
||||
algorithm only works if the server is idle at shutdown */
|
||||
|
||||
|
@ -3486,6 +3486,7 @@ recv_recovery_rollback_active(void)
|
||||
/* Rollback the uncommitted transactions which have no user
|
||||
session */
|
||||
|
||||
trx_rollback_or_clean_is_active = true;
|
||||
os_thread_create(trx_rollback_or_clean_all_recovered, 0, 0);
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/***********************************************************************
|
||||
|
||||
Copyright (c) 1995, 2013, Oracle and/or its affiliates. All Rights Reserved.
|
||||
Copyright (c) 1995, 2014, Oracle and/or its affiliates. All Rights Reserved.
|
||||
Copyright (c) 2009, Percona Inc.
|
||||
|
||||
Portions of this file contain modifications contributed and copyrighted
|
||||
@ -2651,13 +2651,18 @@ try_again:
|
||||
ret = os_file_pread(file, buf, n, offset);
|
||||
|
||||
if ((ulint) ret == n) {
|
||||
|
||||
return(TRUE);
|
||||
} else if (ret == -1) {
|
||||
ib_logf(IB_LOG_LEVEL_ERROR,
|
||||
"Error in system call pread(). The operating"
|
||||
" system error number is %lu.",(ulint) errno);
|
||||
} else {
|
||||
/* Partial read occured */
|
||||
ib_logf(IB_LOG_LEVEL_ERROR,
|
||||
"Tried to read " ULINTPF " bytes at offset "
|
||||
UINT64PF ". Was only able to read %ld.",
|
||||
n, offset, (lint) ret);
|
||||
}
|
||||
|
||||
ib_logf(IB_LOG_LEVEL_ERROR,
|
||||
"Tried to read " ULINTPF " bytes at offset " UINT64PF ". "
|
||||
"Was only able to read %ld.", n, offset, (lint) ret);
|
||||
#endif /* __WIN__ */
|
||||
#ifdef __WIN__
|
||||
error_handling:
|
||||
@ -2777,8 +2782,17 @@ try_again:
|
||||
ret = os_file_pread(file, buf, n, offset);
|
||||
|
||||
if ((ulint) ret == n) {
|
||||
|
||||
return(TRUE);
|
||||
} else if (ret == -1) {
|
||||
ib_logf(IB_LOG_LEVEL_ERROR,
|
||||
"Error in system call pread(). The operating"
|
||||
" system error number is %lu.",(ulint) errno);
|
||||
} else {
|
||||
/* Partial read occured */
|
||||
ib_logf(IB_LOG_LEVEL_ERROR,
|
||||
"Tried to read " ULINTPF " bytes at offset "
|
||||
UINT64PF ". Was only able to read %ld.",
|
||||
n, offset, (lint) ret);
|
||||
}
|
||||
#endif /* __WIN__ */
|
||||
#ifdef __WIN__
|
||||
@ -2997,18 +3011,26 @@ retry:
|
||||
if (!os_has_said_disk_full) {
|
||||
ut_print_timestamp(stderr);
|
||||
|
||||
fprintf(stderr,
|
||||
" InnoDB: Error: Write to file %s failed"
|
||||
" at offset " UINT64PF ".\n"
|
||||
"InnoDB: %lu bytes should have been written,"
|
||||
" only %ld were written.\n"
|
||||
"InnoDB: Operating system error number %lu.\n"
|
||||
"InnoDB: Check that your OS and file system"
|
||||
" support files of this size.\n"
|
||||
"InnoDB: Check also that the disk is not full"
|
||||
" or a disk quota exceeded.\n",
|
||||
name, offset, n, (lint) ret,
|
||||
(ulint) errno);
|
||||
if(ret == -1) {
|
||||
ib_logf(IB_LOG_LEVEL_ERROR,
|
||||
"Failure of system call pwrite(). Operating"
|
||||
" system error number is %lu.",
|
||||
(ulint) errno);
|
||||
} else {
|
||||
fprintf(stderr,
|
||||
" InnoDB: Error: Write to file %s failed"
|
||||
" at offset " UINT64PF ".\n"
|
||||
"InnoDB: %lu bytes should have been written,"
|
||||
" only %ld were written.\n"
|
||||
"InnoDB: Operating system error number %lu.\n"
|
||||
"InnoDB: Check that your OS and file system"
|
||||
" support files of this size.\n"
|
||||
"InnoDB: Check also that the disk is not full"
|
||||
" or a disk quota exceeded.\n",
|
||||
name, offset, n, (lint) ret,
|
||||
(ulint) errno);
|
||||
}
|
||||
|
||||
if (strerror(errno) != NULL) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: Error number %d means '%s'.\n",
|
||||
@ -4585,7 +4607,7 @@ os_aio_func(
|
||||
mode = mode & (~OS_AIO_SIMULATED_WAKE_LATER);
|
||||
|
||||
DBUG_EXECUTE_IF("ib_os_aio_func_io_failure_28",
|
||||
mode = OS_AIO_SYNC;);
|
||||
mode = OS_AIO_SYNC; os_has_said_disk_full = TRUE;);
|
||||
|
||||
if (mode == OS_AIO_SYNC
|
||||
#ifdef WIN_ASYNC_IO
|
||||
@ -4615,14 +4637,10 @@ os_aio_func(
|
||||
ut_a(type == OS_FILE_WRITE);
|
||||
|
||||
ret = os_file_write_func(name, file, buf, offset, n);
|
||||
}
|
||||
|
||||
DBUG_EXECUTE_IF("ib_os_aio_func_io_failure_28",
|
||||
os_has_said_disk_full = FALSE;);
|
||||
DBUG_EXECUTE_IF("ib_os_aio_func_io_failure_28",
|
||||
ret = 0;);
|
||||
DBUG_EXECUTE_IF("ib_os_aio_func_io_failure_28",
|
||||
errno = 28;);
|
||||
DBUG_EXECUTE_IF("ib_os_aio_func_io_failure_28",
|
||||
os_has_said_disk_full = TRUE; ret = 0; errno = 28;);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -5443,19 +5461,17 @@ consecutive_loop:
|
||||
ret = os_file_write(
|
||||
aio_slot->name, aio_slot->file, combined_buf,
|
||||
aio_slot->offset, total_len);
|
||||
|
||||
DBUG_EXECUTE_IF("ib_os_aio_func_io_failure_28",
|
||||
os_has_said_disk_full = TRUE;
|
||||
ret = 0;
|
||||
errno = 28;);
|
||||
} else {
|
||||
ret = os_file_read(
|
||||
aio_slot->file, combined_buf,
|
||||
aio_slot->offset, total_len);
|
||||
}
|
||||
|
||||
if (aio_slot->type == OS_FILE_WRITE) {
|
||||
DBUG_EXECUTE_IF("ib_os_aio_func_io_failure_28",
|
||||
os_has_said_disk_full = FALSE;
|
||||
ret = 0;
|
||||
errno = 28;);
|
||||
}
|
||||
|
||||
srv_set_io_thread_op_info(global_segment, "file i/o done");
|
||||
|
||||
if (aio_slot->type == OS_FILE_READ && n_consecutive > 1) {
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 2010, 2013, Oracle and/or its affiliates. All Rights Reserved.
|
||||
Copyright (c) 2010, 2014, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 2005, 2013, Oracle and/or its affiliates. All Rights Reserved.
|
||||
Copyright (c) 2005, 2014, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 2000, 2014, Oracle and/or its affiliates. All Rights Reserved.
|
||||
Copyright (c) 2000, 2015, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
@ -610,6 +610,7 @@ handle_new_error:
|
||||
case DB_DUPLICATE_KEY:
|
||||
case DB_FOREIGN_DUPLICATE_KEY:
|
||||
case DB_TOO_BIG_RECORD:
|
||||
case DB_TOO_BIG_FOR_REDO:
|
||||
case DB_UNDO_RECORD_TOO_BIG:
|
||||
case DB_ROW_IS_REFERENCED:
|
||||
case DB_NO_REFERENCED_ROW:
|
||||
@ -4373,7 +4374,7 @@ row_drop_table_for_mysql(
|
||||
|
||||
case DB_OUT_OF_FILE_SPACE:
|
||||
err = DB_MUST_GET_MORE_FILE_SPACE;
|
||||
|
||||
trx->error_state = err;
|
||||
row_mysql_handle_errors(&err, trx, NULL, NULL);
|
||||
|
||||
/* raise error */
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 2012, 2013, Oracle and/or its affiliates. All Rights Reserved.
|
||||
Copyright (c) 2012, 2014, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
@ -680,7 +680,6 @@ row_quiesce_set_state(
|
||||
|
||||
switch (state) {
|
||||
case QUIESCE_START:
|
||||
ut_a(table->quiesce == QUIESCE_NONE);
|
||||
break;
|
||||
|
||||
case QUIESCE_COMPLETE:
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 2010, 2013, Oracle and/or its affiliates. All Rights Reserved.
|
||||
Copyright (c) 2010, 2014, Oracle and/or its affiliates. All Rights Reserved.
|
||||
Copyright (c) 2012, Facebook Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
@ -925,7 +925,8 @@ static monitor_info_t innodb_counter_info[] =
|
||||
|
||||
{"adaptive_hash_searches_btree", "adaptive_hash_index",
|
||||
"Number of searches using B-tree on an index search",
|
||||
MONITOR_NONE,
|
||||
static_cast<monitor_type_t>(
|
||||
MONITOR_EXISTING | MONITOR_DEFAULT_ON),
|
||||
MONITOR_DEFAULT_START, MONITOR_OVLD_ADAPTIVE_HASH_SEARCH_BTREE},
|
||||
|
||||
{"adaptive_hash_pages_added", "adaptive_hash_index",
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1995, 2013, Oracle and/or its affiliates. All Rights Reserved.
|
||||
Copyright (c) 1995, 2014, Oracle and/or its affiliates. All Rights Reserved.
|
||||
Copyright (c) 2008, 2009 Google Inc.
|
||||
Copyright (c) 2009, Percona Inc.
|
||||
Copyright (c) 2013, 2014, SkySQL Ab. All Rights Reserved.
|
||||
@ -2657,7 +2657,9 @@ srv_do_purge(
|
||||
|
||||
*n_total_purged += n_pages_purged;
|
||||
|
||||
} while (!srv_purge_should_exit(n_pages_purged) && n_pages_purged > 0);
|
||||
} while (!srv_purge_should_exit(n_pages_purged)
|
||||
&& n_pages_purged > 0
|
||||
&& purge_sys->state == PURGE_STATE_RUN);
|
||||
|
||||
return(rseg_history_len);
|
||||
}
|
||||
|
@ -50,6 +50,9 @@ Created 3/26/1996 Heikki Tuuri
|
||||
rollback */
|
||||
#define TRX_ROLL_TRUNC_THRESHOLD 1
|
||||
|
||||
/** true if trx_rollback_or_clean_all_recovered() thread is active */
|
||||
bool trx_rollback_or_clean_is_active;
|
||||
|
||||
/** In crash recovery, the current trx to be rolled back; NULL otherwise */
|
||||
static const trx_t* trx_roll_crash_recv_trx = NULL;
|
||||
|
||||
@ -805,6 +808,8 @@ DECLARE_THREAD(trx_rollback_or_clean_all_recovered)(
|
||||
|
||||
trx_rollback_or_clean_recovered(TRUE);
|
||||
|
||||
trx_rollback_or_clean_is_active = false;
|
||||
|
||||
/* We count the number of threads in os_thread_exit(). A created
|
||||
thread should always use that to exit and not use return() to exit. */
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1994, 2012, Oracle and/or its affiliates. All Rights Reserved.
|
||||
Copyright (c) 1994, 2014, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
@ -822,6 +822,8 @@ ut_strerr(
|
||||
return("Temp file write failure");
|
||||
case DB_FTS_TOO_MANY_WORDS_IN_PHRASE:
|
||||
return("Too many words in a FTS phrase or proximity search");
|
||||
case DB_TOO_BIG_FOR_REDO:
|
||||
return("BLOB record length is greater than 10%% of redo log");
|
||||
|
||||
/* do not add default: in order to produce a warning if new code
|
||||
is added to the enum but not added here */
|
||||
|
@ -1,6 +1,6 @@
|
||||
# -*- indent-tabs-mode: nil -*-
|
||||
#
|
||||
# Copyright(C) 2012-2014 Kouhei Sutou <kou@clear-code.com>
|
||||
# Copyright(C) 2012-2015 Kouhei Sutou <kou@clear-code.com>
|
||||
# Copyright(C) 2013 Kentoku SHIBA
|
||||
#
|
||||
# This library is free software; you can redistribute it and/or
|
||||
@ -46,6 +46,11 @@ if(MRN_BUNDLED)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
IF(HAVE_WVLA)
|
||||
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Wno-vla")
|
||||
SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -Wno-vla")
|
||||
ENDIF()
|
||||
|
||||
set(MRN_BUNDLED_GROONGA_RELATIVE_DIR "vendor/groonga")
|
||||
set(MRN_BUNDLED_GROONGA_DIR
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/${MRN_BUNDLED_GROONGA_RELATIVE_DIR}")
|
||||
@ -75,6 +80,28 @@ file(READ ${MRN_SOURCE_DIR}/version_in_hex MRN_VERSION_IN_HEX)
|
||||
file(READ ${MRN_SOURCE_DIR}/plugin_version MRN_PLUGIN_VERSION)
|
||||
|
||||
if(MRN_GROONGA_BUNDLED)
|
||||
option(MRN_GROONGA_EMBED
|
||||
"Embed libgroonga"
|
||||
ON)
|
||||
if(MRN_GROONGA_EMBED)
|
||||
set(GRN_EMBED ON)
|
||||
endif()
|
||||
|
||||
set(MRN_BUNDLED_GROONGA_NORMALIZER_MYSQL_DIR
|
||||
"${MRN_BUNDLED_GROONGA_DIR}/vendor/plugins/groonga-normalizer-mysql")
|
||||
option(MRN_GROONGA_NORMALIZER_MYSQL_EMBED
|
||||
"Embed groonga-normalizer-mysql Groonga plugin"
|
||||
ON)
|
||||
if(EXISTS ${MRN_BUNDLED_GROONGA_NORMALIZER_MYSQL_DIR})
|
||||
set(GROONGA_NORMALIZER_MYSQL_FOUND ON)
|
||||
else()
|
||||
set(GROONGA_NORMALIZER_MYSQL_FOUND OFF)
|
||||
set(MRN_GROONGA_NORMALIZER_MYSQL_EMBED OFF)
|
||||
endif()
|
||||
if(MRN_GROONGA_NORMALIZER_MYSQL_EMBED)
|
||||
set(GROONGA_NORMALIZER_MYSQL_EMBED ON)
|
||||
endif()
|
||||
|
||||
add_subdirectory("${MRN_BUNDLED_GROONGA_RELATIVE_DIR}")
|
||||
else()
|
||||
file(READ ${MRN_SOURCE_DIR}/required_groonga_version REQUIRED_GROONGA_VERSION)
|
||||
@ -98,15 +125,21 @@ set(MRN_C_COMPILE_FLAGS "")
|
||||
set(MRN_CXX_COMPILE_FLAGS "")
|
||||
|
||||
macro(mrn_check_cflag flag)
|
||||
check_c_compiler_flag(${flag} "HAVE_C_${flag}")
|
||||
if(HAVE_C_${flag})
|
||||
string(REGEX REPLACE "[-=]" "_" temporary_variable_name ${flag})
|
||||
string(TOUPPER "${temporary_variable_name}" temporary_variable_name)
|
||||
set(temporary_variable_name "CFLAG${temporary_variable_name}")
|
||||
check_c_compiler_flag(${flag} ${temporary_variable_name})
|
||||
if(${temporary_variable_name})
|
||||
set(MRN_C_COMPILE_FLAGS "${MRN_C_COMPILE_FLAGS} ${flag}")
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
macro(mrn_check_cxxflag flag)
|
||||
check_cxx_compiler_flag(${flag} "HAVE_CXX_${flag}")
|
||||
if(HAVE_CXX_${flag})
|
||||
string(REGEX REPLACE "[-=]" "_" temporary_variable_name ${flag})
|
||||
string(TOUPPER "${temporary_variable_name}" temporary_variable_name)
|
||||
set(temporary_variable_name "CXXFLAG${temporary_variable_name}")
|
||||
check_cxx_compiler_flag(${flag} ${temporary_variable_name})
|
||||
if(${temporary_variable_name})
|
||||
set(MRN_CXX_COMPILE_FLAGS "${MRN_CXX_COMPILE_FLAGS} ${flag}")
|
||||
endif()
|
||||
endmacro()
|
||||
@ -122,7 +155,7 @@ else()
|
||||
set(MRN_RELATIVE_DIR_PREFIX "")
|
||||
endif()
|
||||
|
||||
read_file_list(${CMAKE_CURRENT_SOURCE_DIR}/sources.am MROONGA_SOURCES)
|
||||
read_file_list(${CMAKE_CURRENT_SOURCE_DIR}/sources.am MRN_SOURCES)
|
||||
read_file_list(${CMAKE_CURRENT_SOURCE_DIR}/lib/libmrn_no_mysql_sources.am
|
||||
LIBMRN_NO_MYSQL_SOURCES)
|
||||
string(REGEX REPLACE "([^;]+)" "${MRN_RELATIVE_DIR_PREFIX}lib/\\1"
|
||||
@ -157,11 +190,18 @@ else()
|
||||
set(MYSQL_REGEX_INCLUDE_DIR "${MYSQL_SOURCE_DIR}/regex")
|
||||
endif()
|
||||
|
||||
if(EXISTS "${MYSQL_SOURCE_DIR}/extra/rapidjson")
|
||||
set(MYSQL_RAPIDJSON_INCLUDE_DIR "${MYSQL_SOURCE_DIR}/extra/rapidjson/include")
|
||||
else()
|
||||
set(MYSQL_RAPIDJSON_INCLUDE_DIR)
|
||||
endif()
|
||||
|
||||
set(MYSQL_INCLUDE_DIRS
|
||||
"${MYSQL_BUILD_DIR}/include"
|
||||
"${MYSQL_SOURCE_DIR}/sql"
|
||||
"${MYSQL_SOURCE_DIR}/include"
|
||||
"${MYSQL_REGEX_INCLUDE_DIR}"
|
||||
"${MYSQL_RAPIDJSON_INCLUDE_DIR}"
|
||||
"${MYSQL_SOURCE_DIR}")
|
||||
|
||||
if(MRN_BUNDLED)
|
||||
@ -190,6 +230,12 @@ else()
|
||||
set_mysql_config_value("--version" MYSQL_VERSION)
|
||||
endif()
|
||||
|
||||
if(${MYSQL_VERSION} VERSION_LESS "5.5.0")
|
||||
message(FATAL_ERROR
|
||||
"Mroonga doesn't support MySQL < 5.5.0: <${MYSQL_VERSION}>")
|
||||
return()
|
||||
endif()
|
||||
|
||||
if(${MYSQL_VERSION} VERSION_GREATER "10.0.0" AND
|
||||
${MYSQL_VERSION} VERSION_LESS "10.0.9")
|
||||
message(FATAL_ERROR
|
||||
@ -201,10 +247,14 @@ if(MRN_GROONGA_BUNDLED)
|
||||
set(GROONGA_INCLUDE_DIRS "${MRN_BUNDLED_GROONGA_DIR}/include")
|
||||
set(GROONGA_LIBRARY_DIRS "${MRN_BUNDLED_GROONGA_DIR}/lib")
|
||||
set(GROONGA_LIBRARIES "libgroonga")
|
||||
if(EXISTS "${MRN_BUNDLED_GROONGA_DIR}/vendor/plugins/groonga-normalizer-mysql")
|
||||
set(GROONGA_NORMALIZER_MYSQL_FOUND TRUE)
|
||||
else()
|
||||
set(GROONGA_NORMALIZER_MYSQL_FOUND FALSE)
|
||||
|
||||
set(MRN_LIBRARY_DIRS ${GROONGA_LIBRARY_DIRS})
|
||||
set(MRN_LIBRARIES ${GROONGA_LIBRARIES})
|
||||
if(MRN_GROONGA_NORMALIZER_MYSQL_EMBED)
|
||||
set(MRN_LIBRARY_DIRS
|
||||
${MRN_LIBRARY_DIRS}
|
||||
"${MRN_BUNDLED_GROONGA_NORMALIZER_MYSQL_DIR}/normalizers")
|
||||
set(MRN_LIBRARIES ${MRN_LIBRARIES} mysql_normalizer)
|
||||
endif()
|
||||
else()
|
||||
include(FindPkgConfig)
|
||||
@ -213,12 +263,6 @@ else()
|
||||
"groonga-normalizer-mysql >= ${REQUIRED_GROONGA_NORMALIZER_MYSQL_VERSION}")
|
||||
endif()
|
||||
|
||||
if(GROONGA_NORMALIZER_MYSQL_FOUND AND MRN_GROONGA_BUNDLED)
|
||||
read_file_list(${MRN_BUNDLED_GROONGA_DIR}/vendor/plugins/groonga-normalizer-mysql/normalizers/mysql_sources.am MRN_GRN_NORMALIZER_MYSQL_SOURCES)
|
||||
string(REGEX REPLACE "([^;]+)" "${MRN_BUNDLED_GROONGA_DIR}/vendor/plugins/groonga-normalizer-mysql/normalizers/\\1"
|
||||
MRN_GRN_NORMALIZER_MYSQL_SOURCES "${MRN_GRN_NORMALIZER_MYSQL_SOURCES}")
|
||||
endif()
|
||||
|
||||
include_directories(
|
||||
"${PROJECT_BINARY_DIR}"
|
||||
"${PROJECT_SOURCE_DIR}"
|
||||
@ -235,28 +279,22 @@ else()
|
||||
"${MYSQL_SERVICES_LIB_DIR}")
|
||||
endif()
|
||||
link_directories(
|
||||
${GROONGA_LIBRARY_DIRS}
|
||||
${MRN_LIBRARY_DIRS}
|
||||
${MYSQL_LIBRARY_DIRS})
|
||||
|
||||
set(MRN_ALL_SOURCES
|
||||
${MRN_SOURCES}
|
||||
${MRN_UDF_SOURCES}
|
||||
${LIBMRN_NO_MYSQL_SOURCES}
|
||||
${LIBMRN_NEED_MYSQL_SOURCES})
|
||||
|
||||
if(MRN_BUNDLED)
|
||||
if(GROONGA_NORMALIZER_MYSQL_FOUND AND MRN_GROONGA_BUNDLED)
|
||||
mysql_add_plugin(mroonga
|
||||
"${MROONGA_SOURCES};${MRN_UDF_SOURCES};${MRN_GRN_NORMALIZER_MYSQL_SOURCES};${LIBMRN_NEED_MYSQL_SOURCES};${LIBMRN_NO_MYSQL_SOURCES}"
|
||||
STORAGE_ENGINE MODULE_ONLY
|
||||
LINK_LIBRARIES ${GROONGA_LIBRARIES})
|
||||
else()
|
||||
mysql_add_plugin(mroonga
|
||||
"${MROONGA_SOURCES};${MRN_UDF_SOURCES};${LIBMRN_NEED_MYSQL_SOURCES};${LIBMRN_NO_MYSQL_SOURCES}"
|
||||
STORAGE_ENGINE MODULE_ONLY
|
||||
LINK_LIBRARIES ${GROONGA_LIBRARIES})
|
||||
endif()
|
||||
else()
|
||||
mysql_add_plugin(mroonga
|
||||
${MRN_ALL_SOURCES}
|
||||
STORAGE_ENGINE MODULE_ONLY
|
||||
LINK_LIBRARIES ${MRN_LIBRARIES})
|
||||
else()
|
||||
add_library(mroonga MODULE
|
||||
${MROONGA_SOURCES}
|
||||
${MRN_UDF_SOURCES}
|
||||
${LIBMRN_NO_MYSQL_SOURCES}
|
||||
${LIBMRN_NEED_MYSQL_SOURCES})
|
||||
add_library(mroonga MODULE ${MRN_ALL_SOURCES})
|
||||
|
||||
set(MYSQL_LIBRARIES "mysqlservices")
|
||||
target_link_libraries(mroonga ${GROONGA_LIBRARIES} ${MYSQL_LIBRARIES})
|
||||
@ -303,14 +341,14 @@ else()
|
||||
mrn_check_cxxflag("-fno-rtti")
|
||||
mrn_check_cxxflag("-felide-constructors")
|
||||
endif()
|
||||
set_source_files_properties(${MROONGA_SOURCES} PROPERTIES
|
||||
set_source_files_properties(${MRN_SOURCES} PROPERTIES
|
||||
COMPILE_FLAGS "${MYSQL_CFLAGS} ${MRN_CXX_COMPILE_FLAGS}")
|
||||
set_source_files_properties(${LIBMRN_NEED_MYSQL_SOURCES} PROPERTIES
|
||||
COMPILE_FLAGS "${MYSQL_CFLAGS} ${MRN_CXX_COMPILE_FLAGS}")
|
||||
set_source_files_properties(${MRN_UDF_SOURCES} PROPERTIES
|
||||
COMPILE_FLAGS "${MRN_C_COMPILE_FLAGS}")
|
||||
COMPILE_FLAGS "${MRN_CXX_COMPILE_FLAGS}")
|
||||
set_source_files_properties(${LIBMRN_NO_MYSQL_SOURCES} PROPERTIES
|
||||
COMPILE_FLAGS "${MRN_C_COMPILE_FLAGS}")
|
||||
COMPILE_FLAGS "${MRN_CXX_COMPILE_FLAGS}")
|
||||
set_property(TARGET mroonga APPEND PROPERTY
|
||||
COMPILE_DEFINITIONS "MYSQL_DYNAMIC_PLUGIN")
|
||||
set_target_properties(mroonga PROPERTIES
|
||||
@ -321,19 +359,20 @@ else()
|
||||
endif()
|
||||
|
||||
if(GROONGA_NORMALIZER_MYSQL_FOUND)
|
||||
set(WITH_GROONGA_NORMALIZER_MYSQL 1)
|
||||
ADD_DEFINITIONS(-DWITH_GROONGA_NORMALIZER_MYSQL=1)
|
||||
if(MRN_GROONGA_BUNDLED)
|
||||
ADD_DEFINITIONS(-DGROONGA_NORMALIZER_MYSQL_PLUGIN_IS_BUNDLED_STATIC=1)
|
||||
set_property(TARGET mroonga APPEND PROPERTY
|
||||
COMPILE_DEFINITIONS "WITH_GROONGA_NORMALIZER_MYSQL=1")
|
||||
if(MRN_GROONGA_NORMALIZER_MYSQL_EMBED)
|
||||
set_property(TARGET mroonga APPEND PROPERTY
|
||||
COMPILE_DEFINITIONS "MRN_GROONGA_NORMALIZER_MYSQL_EMBED")
|
||||
else()
|
||||
set(GROONGA_NORMALIZER_MYSQL_PLUGIN_NAME \"normalizers/mysql\")
|
||||
set_property(TARGET mroonga APPEND PROPERTY
|
||||
COMPILE_DEFINITIONS "GROONGA_NORMALIZER_MYSQL_PLUGIN_NAME=\"normalizers/mysql\"")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(MRN_DEFAULT_PARSER "TokenBigram" CACHE STRING "The default fulltext parser")
|
||||
ADD_DEFINITIONS(-DMRN_PARSER_DEFAULT="${MRN_DEFAULT_PARSER}")
|
||||
set_property(TARGET mroonga APPEND PROPERTY
|
||||
COMPILE_DEFINITIONS "MRN_PARSER_DEFAULT=\"${MRN_DEFAULT_PARSER}\"")
|
||||
|
||||
configure_file(
|
||||
"${PROJECT_SOURCE_DIR}/mrn_version.h.in"
|
||||
|
@ -67,8 +67,6 @@ update-latest-release: misc
|
||||
misc/update-latest-release.rb \
|
||||
$(PACKAGE) $(OLD_RELEASE) $(OLD_RELEASE_DATE) \
|
||||
$(VERSION) $(NEW_RELEASE_DATE) \
|
||||
packages/rpm/fedora/mysql-mroonga.spec.in \
|
||||
packages/rpm/fedora/mariadb-mroonga.spec.in \
|
||||
packages/rpm/centos/mariadb-mroonga.spec.in \
|
||||
packages/rpm/centos/mysql55-mroonga.spec.in \
|
||||
packages/rpm/centos/mysql56-community-mroonga.spec.in \
|
||||
|
51
storage/mroonga/appveyor.yml
Normal file
51
storage/mroonga/appveyor.yml
Normal file
@ -0,0 +1,51 @@
|
||||
version: "{build}"
|
||||
clone_depth: 10
|
||||
install:
|
||||
- cd ..
|
||||
- choco install curl 7zip.commandline
|
||||
- curl -O http://mirror.jmu.edu/pub/mariadb/mariadb-10.0.16/source/mariadb-10.0.16.tar.gz
|
||||
- 7z x mariadb-10.0.16.tar.gz
|
||||
- 7z x mariadb-10.0.16.tar > nul
|
||||
- cd mariadb-10.0.16
|
||||
- rmdir /S /Q storage\mroonga\
|
||||
- move ..\mroonga storage\mroonga
|
||||
- git clone --quiet --depth 1 https://github.com/groonga/groonga.git ..\groonga
|
||||
- rmdir /S /Q ..\groonga\test\
|
||||
- mkdir storage\mroonga\vendor
|
||||
- move ..\groonga storage\mroonga\vendor\groonga
|
||||
- git clone --quiet --depth 1 https://github.com/groonga/groonga-normalizer-mysql.git storage\mroonga\vendor\groonga\vendor\plugins\groonga-normalizer-mysql
|
||||
build_script:
|
||||
- "echo # > win\\packaging\\CMakeLists.txt"
|
||||
- cmake . -G "Visual Studio 12 Win64"
|
||||
-DCMAKE_BUILD_TYPE=Debug
|
||||
-DWITHOUT_ARCHIVE=ON
|
||||
-DWITHOUT_BLACKHOLE=ON
|
||||
-DWITHOUT_CASSANDRA=ON
|
||||
-DWITHOUT_CONNECT=ON
|
||||
-DWITHOUT_CSV=ON
|
||||
-DWITHOUT_EXAMPLE=ON
|
||||
-DWITHOUT_FEDERATED=ON
|
||||
-DWITHOUT_FEDERATEDX=ON
|
||||
-DWITHOUT_HEAP=ON
|
||||
-DWITHOUT_INNOBASE=ON
|
||||
-DWITHOUT_MYISAM=ON
|
||||
-DWITHOUT_MYISAMMRG=ON
|
||||
-DWITHOUT_OQGRAPH=ON
|
||||
-DWITHOUT_PERFSCHEMA=OFF
|
||||
-DWITHOUT_SEQUENCE=ON
|
||||
-DWITHOUT_SPHINX=ON
|
||||
-DWITHOUT_SPIDER=ON
|
||||
-DWITHOUT_TEST_SQL_DISCOVERY=ON
|
||||
-DWITHOUT_TOKUDB=ON
|
||||
-DWITHOUT_XTRADB=ON
|
||||
-DWITH_UNIT_TESTS=OFF
|
||||
- cmake --build . --config Debug
|
||||
|
||||
notifications:
|
||||
- provider: Email
|
||||
to:
|
||||
- groonga-mysql-commit@lists.sourceforge.jp
|
||||
- kou@clear-code.com
|
||||
on_build_status_changed: true
|
||||
|
||||
test: off
|
@ -174,6 +174,10 @@ AC_DEFUN([CONFIG_OPTION_MYSQL],[
|
||||
MYSQL_INCLUDES="$MYSQL_INCLUDES -I$ac_mysql_build_dir/include"
|
||||
MYSQL_INCLUDES="$MYSQL_INCLUDES -I$ac_mysql_source_dir/sql"
|
||||
MYSQL_INCLUDES="$MYSQL_INCLUDES -I$ac_mysql_source_dir/include"
|
||||
if test -d "$ac_mysql_source_dir/extra/rapidjson"; then
|
||||
mysql_rapidjson_include_dir="$ac_mysql_source_dir/extra/rapidjson/include"
|
||||
MYSQL_INCLUDES="$MYSQL_INCLUDES -I$mysql_rapidjson_include_dir"
|
||||
fi
|
||||
if test -d "$ac_mysql_source_dir/pcre"; then
|
||||
mysql_regex_include_dir="$ac_mysql_source_dir/pcre"
|
||||
else
|
||||
@ -461,7 +465,6 @@ AC_CONFIG_FILES([
|
||||
packages/Makefile
|
||||
packages/rpm/Makefile
|
||||
packages/rpm/centos/Makefile
|
||||
packages/rpm/fedora/Makefile
|
||||
packages/yum/Makefile
|
||||
packages/apt/Makefile
|
||||
packages/source/Makefile
|
||||
@ -486,8 +489,6 @@ AC_OUTPUT([
|
||||
packages/rpm/centos/mysql55-mroonga.spec
|
||||
packages/rpm/centos/mysql56-community-mroonga.spec
|
||||
packages/rpm/centos/mariadb-mroonga.spec
|
||||
packages/rpm/fedora/mysql-mroonga.spec
|
||||
packages/rpm/fedora/mariadb-mroonga.spec
|
||||
packages/yum/env.sh
|
||||
data/install.sql
|
||||
])
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -263,7 +263,6 @@ private:
|
||||
grn_obj **grn_column_ranges;
|
||||
grn_obj **grn_index_tables;
|
||||
grn_obj **grn_index_columns;
|
||||
bool grn_table_is_referenced;
|
||||
|
||||
// buffers
|
||||
grn_obj encoded_key_buffer;
|
||||
@ -349,7 +348,7 @@ public:
|
||||
|
||||
uint max_supported_record_length() const;
|
||||
uint max_supported_keys() const;
|
||||
uint max_supported_key_parts();
|
||||
uint max_supported_key_parts() const;
|
||||
uint max_supported_key_length() const;
|
||||
uint max_supported_key_part_length() const;
|
||||
|
||||
@ -641,7 +640,7 @@ private:
|
||||
void storage_store_field_geometry(Field *field,
|
||||
const char *value, uint value_length);
|
||||
void storage_store_field(Field *field, const char *value, uint value_length);
|
||||
void storage_store_field_column(Field *field,
|
||||
void storage_store_field_column(Field *field, bool is_primary_key,
|
||||
int nth_column, grn_id record_id);
|
||||
void storage_store_fields(uchar *buf, grn_id record_id);
|
||||
void storage_store_fields_for_prep_update(const uchar *old_data,
|
||||
@ -742,7 +741,6 @@ private:
|
||||
int wrapper_open(const char *name, int mode, uint test_if_locked);
|
||||
int wrapper_open_indexes(const char *name);
|
||||
int storage_open(const char *name, int mode, uint test_if_locked);
|
||||
void update_grn_table_is_referenced();
|
||||
int open_table(const char *name);
|
||||
int storage_open_columns(void);
|
||||
int storage_open_indexes(const char *name);
|
||||
@ -785,7 +783,9 @@ private:
|
||||
grn_obj *index_column);
|
||||
int storage_write_row_multiple_column_indexes(uchar *buf, grn_id record_id);
|
||||
int storage_write_row_unique_index(uchar *buf,
|
||||
KEY *key_info, grn_obj *index_table,
|
||||
KEY *key_info,
|
||||
grn_obj *index_table,
|
||||
grn_obj *index_column,
|
||||
grn_id *key_id);
|
||||
int storage_write_row_unique_indexes(uchar *buf);
|
||||
int wrapper_get_record_id(uchar *data, grn_id *record_id, const char *context);
|
||||
@ -812,8 +812,8 @@ private:
|
||||
uint storage_max_supported_record_length() const;
|
||||
uint wrapper_max_supported_keys() const;
|
||||
uint storage_max_supported_keys() const;
|
||||
uint wrapper_max_supported_key_parts();
|
||||
uint storage_max_supported_key_parts();
|
||||
uint wrapper_max_supported_key_parts() const;
|
||||
uint storage_max_supported_key_parts() const;
|
||||
uint wrapper_max_supported_key_length() const;
|
||||
uint storage_max_supported_key_length() const;
|
||||
uint wrapper_max_supported_key_part_length() const;
|
||||
@ -904,6 +904,7 @@ private:
|
||||
grn_obj *match_columns,
|
||||
uint *consumed_keyword_length,
|
||||
grn_obj *tmp_objects);
|
||||
grn_expr_flags expr_flags_in_boolean_mode();
|
||||
grn_rc generic_ft_init_ext_prepare_expression_in_boolean_mode(
|
||||
struct st_mrn_ft_info *info,
|
||||
String *key,
|
||||
@ -1029,6 +1030,7 @@ private:
|
||||
bool storage_is_crashed() const;
|
||||
bool wrapper_auto_repair(int error) const;
|
||||
bool storage_auto_repair(int error) const;
|
||||
int generic_disable_index(int i, KEY *key_info);
|
||||
int wrapper_disable_indexes(uint mode);
|
||||
int storage_disable_indexes(uint mode);
|
||||
int wrapper_enable_indexes(uint mode);
|
||||
|
@ -26,6 +26,8 @@
|
||||
#include "mrn_lock.hpp"
|
||||
#include "mrn_path_mapper.hpp"
|
||||
|
||||
#include <groonga/plugin.h>
|
||||
|
||||
// for debug
|
||||
#define MRN_CLASS_NAME "mrn::DatabaseManager"
|
||||
|
||||
@ -38,19 +40,19 @@
|
||||
# define MRN_MKDIR(pathname, mode) mkdir((pathname), (mode))
|
||||
#endif
|
||||
|
||||
extern "C" {
|
||||
grn_rc GRN_PLUGIN_IMPL_NAME_TAGGED(init, normalizers_mysql)(grn_ctx *ctx);
|
||||
grn_rc GRN_PLUGIN_IMPL_NAME_TAGGED(register, normalizers_mysql)(grn_ctx *ctx);
|
||||
}
|
||||
|
||||
namespace mrn {
|
||||
DatabaseManager::DatabaseManager(grn_ctx *ctx)
|
||||
DatabaseManager::DatabaseManager(grn_ctx *ctx, mysql_mutex_t *mutex)
|
||||
: ctx_(ctx),
|
||||
cache_(NULL),
|
||||
mutex_(),
|
||||
mutex_initialized_(false) {
|
||||
mutex_(mutex) {
|
||||
}
|
||||
|
||||
DatabaseManager::~DatabaseManager(void) {
|
||||
if (mutex_initialized_) {
|
||||
pthread_mutex_destroy(&mutex_);
|
||||
}
|
||||
|
||||
if (cache_) {
|
||||
void *db_address;
|
||||
GRN_HASH_EACH(ctx_, cache_, id, NULL, 0, &db_address, {
|
||||
@ -75,13 +77,6 @@ namespace mrn {
|
||||
DBUG_RETURN(false);
|
||||
}
|
||||
|
||||
if (pthread_mutex_init(&mutex_, NULL) != 0) {
|
||||
GRN_LOG(ctx_, GRN_LOG_ERROR,
|
||||
"failed to initialize mutex for opened database cache hash table");
|
||||
DBUG_RETURN(false);
|
||||
}
|
||||
|
||||
mutex_initialized_ = true;
|
||||
DBUG_RETURN(true);
|
||||
}
|
||||
|
||||
@ -92,7 +87,7 @@ namespace mrn {
|
||||
*db = NULL;
|
||||
|
||||
mrn::PathMapper mapper(path);
|
||||
mrn::Lock lock(&mutex_);
|
||||
mrn::Lock lock(mutex_);
|
||||
|
||||
error = mrn::encoding::set(ctx_, system_charset_info);
|
||||
if (error) {
|
||||
@ -145,7 +140,7 @@ namespace mrn {
|
||||
MRN_DBUG_ENTER_METHOD();
|
||||
|
||||
mrn::PathMapper mapper(path);
|
||||
mrn::Lock lock(&mutex_);
|
||||
mrn::Lock lock(mutex_);
|
||||
|
||||
grn_id id;
|
||||
void *db_address;
|
||||
@ -171,7 +166,7 @@ namespace mrn {
|
||||
MRN_DBUG_ENTER_METHOD();
|
||||
|
||||
mrn::PathMapper mapper(path);
|
||||
mrn::Lock lock(&mutex_);
|
||||
mrn::Lock lock(mutex_);
|
||||
|
||||
grn_id id;
|
||||
void *db_address;
|
||||
@ -211,7 +206,7 @@ namespace mrn {
|
||||
|
||||
int error = 0;
|
||||
|
||||
mrn::Lock lock(&mutex_);
|
||||
mrn::Lock lock(mutex_);
|
||||
|
||||
grn_hash_cursor *cursor;
|
||||
cursor = grn_hash_cursor_open(ctx_, cache_,
|
||||
@ -323,15 +318,12 @@ namespace mrn {
|
||||
if (mysql_normalizer) {
|
||||
grn_obj_unlink(ctx_, mysql_normalizer);
|
||||
} else {
|
||||
#ifdef GROONGA_NORMALIZER_MYSQL_PLUGIN_IS_BUNDLED_STATIC
|
||||
char ref_path[FN_REFLEN + 1], *tmp;
|
||||
tmp = strmov(ref_path, opt_plugin_dir);
|
||||
tmp = strmov(tmp, "/ha_mroonga");
|
||||
strcpy(tmp, SO_EXT);
|
||||
grn_plugin_register_by_path(ctx_, ref_path);
|
||||
#else
|
||||
# ifdef MRN_GROONGA_NORMALIZER_MYSQL_EMBED
|
||||
GRN_PLUGIN_IMPL_NAME_TAGGED(init, normalizers_mysql)(ctx_);
|
||||
GRN_PLUGIN_IMPL_NAME_TAGGED(register, normalizers_mysql)(ctx_);
|
||||
# else
|
||||
grn_plugin_register(ctx_, GROONGA_NORMALIZER_MYSQL_PLUGIN_NAME);
|
||||
#endif
|
||||
# endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -27,7 +27,7 @@
|
||||
namespace mrn {
|
||||
class DatabaseManager {
|
||||
public:
|
||||
DatabaseManager(grn_ctx *ctx);
|
||||
DatabaseManager(grn_ctx *ctx, mysql_mutex_t *mutex);
|
||||
~DatabaseManager(void);
|
||||
bool init(void);
|
||||
int open(const char *path, grn_obj **db);
|
||||
@ -38,8 +38,7 @@ namespace mrn {
|
||||
private:
|
||||
grn_ctx *ctx_;
|
||||
grn_hash *cache_;
|
||||
pthread_mutex_t mutex_;
|
||||
bool mutex_initialized_;
|
||||
mysql_mutex_t *mutex_;
|
||||
|
||||
void mkdir_p(const char *directory);
|
||||
void ensure_database_directory(void);
|
||||
|
@ -20,12 +20,12 @@
|
||||
#include "mrn_lock.hpp"
|
||||
|
||||
namespace mrn {
|
||||
Lock::Lock(pthread_mutex_t *mutex)
|
||||
Lock::Lock(mysql_mutex_t *mutex)
|
||||
: mutex_(mutex) {
|
||||
pthread_mutex_lock(mutex_);
|
||||
mysql_mutex_lock(mutex_);
|
||||
}
|
||||
|
||||
Lock::~Lock() {
|
||||
pthread_mutex_unlock(mutex_);
|
||||
mysql_mutex_unlock(mutex_);
|
||||
}
|
||||
}
|
||||
|
@ -26,10 +26,10 @@
|
||||
namespace mrn {
|
||||
class Lock {
|
||||
public:
|
||||
Lock(pthread_mutex_t *mutex);
|
||||
Lock(mysql_mutex_t *mutex);
|
||||
~Lock();
|
||||
private:
|
||||
pthread_mutex_t *mutex_;
|
||||
mysql_mutex_t *mutex_;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -35,10 +35,10 @@ namespace mrn {
|
||||
};
|
||||
~Parameter() {
|
||||
if (key_) {
|
||||
my_free(key_, MYF(0));
|
||||
my_free(key_);
|
||||
}
|
||||
if (value_) {
|
||||
my_free(value_, MYF(0));
|
||||
my_free(value_);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
@ -2,7 +2,7 @@
|
||||
/*
|
||||
Copyright(C) 2010 Tetsuro IKEDA
|
||||
Copyright(C) 2011-2013 Kentoku SHIBA
|
||||
Copyright(C) 2011-2012 Kouhei Sutou <kou@clear-code.com>
|
||||
Copyright(C) 2011-2015 Kouhei Sutou <kou@clear-code.com>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
@ -184,6 +184,9 @@ namespace mrn {
|
||||
int i = len, j = 0;
|
||||
for (; mysql_path_[--i] != FN_LIBCHAR ;) {}
|
||||
for (; i < len ;) {
|
||||
if (len - i - 1 >= 3 && strncmp(mysql_path_ + i + 1, "#P#", 3) == 0) {
|
||||
break;
|
||||
}
|
||||
mysql_table_name_[j++] = mysql_path_[++i];
|
||||
}
|
||||
mysql_table_name_[j] = '\0';
|
||||
|
@ -28,5 +28,11 @@
|
||||
#define ER_MRN_ERROR_FROM_GROONGA_STR "Error from Groonga [%s]"
|
||||
#define ER_MRN_INVALID_NULL_VALUE_NUM 16505
|
||||
#define ER_MRN_INVALID_NULL_VALUE_STR "NULL value can't be used for %s"
|
||||
#define ER_MRN_UNSUPPORTED_COLUMN_FLAG_NUM 16506
|
||||
#define ER_MRN_UNSUPPORTED_COLUMN_FLAG_STR \
|
||||
"The column flag '%-.64s' is unsupported. It is ignored"
|
||||
#define ER_MRN_INVALID_COLUMN_FLAG_NUM 16507
|
||||
#define ER_MRN_INVALID_COLUMN_FLAG_STR \
|
||||
"The column flag '%-.64s' is invalid. '%-64s' is used instead"
|
||||
|
||||
#endif /* MRN_ERR_H_ */
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* -*- c-basic-offset: 2 -*- */
|
||||
/*
|
||||
Copyright(C) 2011-2013 Kouhei Sutou <kou@clear-code.com>
|
||||
Copyright(C) 2011-2014 Kouhei Sutou <kou@clear-code.com>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
@ -22,15 +22,6 @@
|
||||
|
||||
#include "mrn_mysql.h"
|
||||
|
||||
#if MYSQL_VERSION_ID >= 50500
|
||||
# define my_free(PTR, FLAG) my_free(PTR)
|
||||
#endif
|
||||
|
||||
#if MYSQL_VERSION_ID < 50500
|
||||
# define mysql_mutex_lock(mutex) pthread_mutex_lock(mutex)
|
||||
# define mysql_mutex_unlock(mutex) pthread_mutex_unlock(mutex)
|
||||
#endif
|
||||
|
||||
#if MYSQL_VERSION_ID >= 50604
|
||||
# define MRN_HAVE_MYSQL_TYPE_TIMESTAMP2
|
||||
# define MRN_HAVE_MYSQL_TYPE_DATETIME2
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user