Merge remote-tracking branch 'origin/10.0' into 10.0

This commit is contained in:
Sergei Golubchik 2015-02-22 21:45:24 +01:00
commit f2cb45daf3
537 changed files with 49583 additions and 8860 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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

View File

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

View File

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

View File

@ -0,0 +1,2 @@
--innodb_ft_default_stopword

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

View File

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

View File

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

View File

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

View File

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

View File

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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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);
}
/*******************************************************************//**

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View 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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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