summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2017-05-19 13:59:43 +0300
committerMarko Mäkelä <marko.makela@mariadb.com>2017-05-20 08:41:20 +0300
commit65e1399e64a306f1ce1d920e66206954f8630da8 (patch)
treea3c22c1f76d15721e982f34e1ac9e6b828e711a2
parent13a350ac29eeb43153c7bca65b73b5dfa9f8ffb5 (diff)
parent335c4ab790254462753ba4ed8b074c5847b2708f (diff)
downloadmariadb-git-65e1399e64a306f1ce1d920e66206954f8630da8.tar.gz
Merge 10.0 into 10.1
Significantly reduce the amount of InnoDB, XtraDB and Mariabackup code changes by defining pfs_os_file_t as something that is transparently compatible with os_file_t.
-rw-r--r--extra/mariabackup/backup_copy.cc2
-rw-r--r--extra/mariabackup/changed_page_bitmap.cc2
-rw-r--r--extra/mariabackup/crc/crc_glue.c2
-rw-r--r--extra/mariabackup/fil_cur.h2
-rw-r--r--extra/mariabackup/xb0xb.h2
-rw-r--r--extra/mariabackup/xtrabackup.cc18
-rw-r--r--extra/mariabackup/xtrabackup.h4
-rw-r--r--mysql-test/r/derived_view.result38
-rw-r--r--mysql-test/r/limit_rows_examined.result5
-rw-r--r--mysql-test/r/subselect_mat_cost_bugs.result43
-rw-r--r--mysql-test/r/subselect_sj.result41
-rw-r--r--mysql-test/r/subselect_sj2_mat.result23
-rw-r--r--mysql-test/r/subselect_sj_jcl6.result41
-rw-r--r--mysql-test/suite/perfschema/r/start_server_1_digest.result7
-rw-r--r--mysql-test/suite/perfschema/t/start_server_1_digest-master.opt1
-rw-r--r--mysql-test/suite/perfschema/t/start_server_1_digest.test15
-rw-r--r--mysql-test/suite/sys_vars/r/innodb_empty_free_list_algorithm_basic.result2
-rw-r--r--mysql-test/suite/sys_vars/r/sysvars_innodb,xtradb.rdiff4
-rw-r--r--mysql-test/suite/sys_vars/r/sysvars_innodb.result2
-rw-r--r--mysql-test/t/derived_view.test30
-rw-r--r--mysql-test/t/subselect_mat_cost_bugs.test44
-rw-r--r--mysql-test/t/subselect_sj.test32
-rw-r--r--mysql-test/t/subselect_sj2_mat.test20
-rw-r--r--mysys/ma_dyncol.c1
-rw-r--r--sql/item_subselect.cc26
-rw-r--r--sql/item_subselect.h8
-rw-r--r--sql/item_sum.h1
-rw-r--r--sql/mysqld.h2
-rw-r--r--sql/opt_subselect.cc80
-rw-r--r--sql/opt_sum.cc9
-rw-r--r--sql/rpl_mi.cc6
-rw-r--r--sql/sql_lex.cc1
-rw-r--r--sql/sql_lex.h5
-rw-r--r--sql/sql_select.cc18
-rw-r--r--storage/connect/CMakeLists.txt8
-rw-r--r--storage/connect/array.cpp14
-rw-r--r--storage/connect/blkfil.cpp8
-rw-r--r--storage/connect/catalog.h11
-rw-r--r--storage/connect/colblk.cpp22
-rw-r--r--storage/connect/colblk.h8
-rw-r--r--storage/connect/connect.cc601
-rw-r--r--storage/connect/domdoc.cpp20
-rw-r--r--storage/connect/domdoc.h8
-rw-r--r--storage/connect/filamap.cpp21
-rw-r--r--storage/connect/filamdbf.cpp6
-rw-r--r--storage/connect/filamdbf.h4
-rw-r--r--storage/connect/filamfix.cpp3
-rw-r--r--storage/connect/filamgz.cpp4
-rw-r--r--storage/connect/filamtxt.cpp35
-rw-r--r--storage/connect/filamtxt.h2
-rwxr-xr-xstorage/connect/filamvct.cpp106
-rw-r--r--storage/connect/filamvct.h6
-rw-r--r--storage/connect/filamzip.cpp162
-rw-r--r--storage/connect/filamzip.h47
-rw-r--r--storage/connect/filter.cpp12
-rw-r--r--storage/connect/filter.h2
-rw-r--r--storage/connect/global.h9
-rw-r--r--storage/connect/ha_connect.cc1442
-rw-r--r--storage/connect/ha_connect.h34
-rw-r--r--storage/connect/jdbccat.h20
-rw-r--r--storage/connect/jdbconn.cpp39
-rw-r--r--storage/connect/jdbconn.h30
-rw-r--r--storage/connect/json.cpp335
-rw-r--r--storage/connect/json.h20
-rw-r--r--storage/connect/jsonudf.cpp387
-rw-r--r--storage/connect/jsonudf.h2
-rw-r--r--storage/connect/libdoc.cpp27
-rw-r--r--storage/connect/macutil.cpp2
-rw-r--r--storage/connect/mycat.cc35
-rw-r--r--storage/connect/mycat.h5
-rw-r--r--storage/connect/myconn.cpp48
-rw-r--r--storage/connect/mysql-test/connect/disabled.def4
-rw-r--r--storage/connect/mysql-test/connect/r/jdbc_new.result4
-rw-r--r--storage/connect/mysql-test/connect/t/jdbc_new.test4
-rw-r--r--storage/connect/myutil.cpp21
-rw-r--r--storage/connect/myutil.h8
-rw-r--r--storage/connect/odbccat.h18
-rw-r--r--storage/connect/odbconn.cpp114
-rw-r--r--storage/connect/odbconn.h32
-rw-r--r--storage/connect/os.h3
-rw-r--r--storage/connect/osutil.c52
-rw-r--r--storage/connect/plgdbsem.h19
-rw-r--r--storage/connect/plgdbutl.cpp192
-rw-r--r--storage/connect/plgxml.cpp4
-rw-r--r--storage/connect/plgxml.h12
-rw-r--r--storage/connect/plugutil.cpp (renamed from storage/connect/plugutil.c)39
-rw-r--r--storage/connect/preparse.h4
-rw-r--r--storage/connect/reldef.cpp44
-rw-r--r--storage/connect/reldef.h18
-rw-r--r--storage/connect/tabdos.cpp90
-rw-r--r--storage/connect/tabdos.h19
-rw-r--r--storage/connect/tabext.cpp103
-rw-r--r--storage/connect/tabext.h36
-rw-r--r--storage/connect/tabfix.cpp42
-rw-r--r--storage/connect/tabfix.h4
-rw-r--r--storage/connect/tabfmt.cpp24
-rw-r--r--storage/connect/tabfmt.h6
-rw-r--r--storage/connect/tabjdbc.cpp202
-rw-r--r--storage/connect/tabjdbc.h58
-rw-r--r--storage/connect/tabjson.cpp145
-rw-r--r--storage/connect/tabjson.h55
-rw-r--r--storage/connect/table.cpp4
-rw-r--r--storage/connect/tabmac.cpp2
-rw-r--r--storage/connect/tabmul.cpp695
-rw-r--r--storage/connect/tabmul.h66
-rw-r--r--storage/connect/tabmysql.cpp150
-rw-r--r--storage/connect/tabmysql.h24
-rw-r--r--storage/connect/tabodbc.cpp469
-rw-r--r--storage/connect/tabodbc.h68
-rw-r--r--storage/connect/tabpivot.cpp389
-rw-r--r--storage/connect/tabpivot.h18
-rw-r--r--storage/connect/tabsys.cpp44
-rw-r--r--storage/connect/tabsys.h6
-rw-r--r--storage/connect/tabutil.cpp18
-rw-r--r--storage/connect/tabutil.h4
-rw-r--r--storage/connect/tabvct.cpp18
-rw-r--r--storage/connect/tabvir.cpp10
-rw-r--r--storage/connect/tabvir.h2
-rw-r--r--storage/connect/tabwmi.cpp4
-rw-r--r--storage/connect/tabwmi.h2
-rw-r--r--storage/connect/tabxml.cpp79
-rw-r--r--storage/connect/tabxml.h12
-rw-r--r--storage/connect/tabzip.cpp4
-rw-r--r--storage/connect/tabzip.h6
-rw-r--r--storage/connect/valblk.cpp60
-rw-r--r--storage/connect/valblk.h24
-rw-r--r--storage/connect/value.cpp323
-rw-r--r--storage/connect/value.h51
-rwxr-xr-xstorage/connect/xindex.cpp24
-rw-r--r--storage/connect/xobject.cpp25
-rw-r--r--storage/connect/xobject.h10
-rw-r--r--storage/connect/xtable.h70
-rw-r--r--storage/innobase/btr/btr0sea.cc2
-rw-r--r--storage/innobase/buf/buf0buf.cc2
-rw-r--r--storage/innobase/buf/buf0dblwr.cc6
-rw-r--r--storage/innobase/buf/buf0dump.cc4
-rw-r--r--storage/innobase/buf/buf0flu.cc4
-rw-r--r--storage/innobase/dict/dict0stats.cc5
-rw-r--r--storage/innobase/dict/dict0stats_bg.cc4
-rw-r--r--storage/innobase/fil/fil0fil.cc24
-rw-r--r--storage/innobase/handler/ha_innodb.cc5
-rw-r--r--storage/innobase/include/buf0dblwr.h4
-rw-r--r--storage/innobase/include/fil0fil.h16
-rw-r--r--storage/innobase/include/ha0ha.h6
-rw-r--r--storage/innobase/include/os0file.h110
-rw-r--r--storage/innobase/include/os0file.ic116
-rw-r--r--storage/innobase/include/srv0srv.h9
-rw-r--r--storage/innobase/include/srv0start.h4
-rw-r--r--storage/innobase/include/trx0xa.h15
-rw-r--r--storage/innobase/include/univ.i12
-rw-r--r--storage/innobase/log/log0recv.cc4
-rw-r--r--storage/innobase/os/os0file.cc95
-rw-r--r--storage/innobase/row/row0log.cc17
-rw-r--r--storage/innobase/row/row0merge.cc36
-rw-r--r--storage/innobase/row/row0sel.cc79
-rw-r--r--storage/innobase/srv/srv0srv.cc27
-rw-r--r--storage/innobase/srv/srv0start.cc66
-rw-r--r--storage/innobase/trx/trx0purge.cc5
-rw-r--r--storage/innobase/trx/trx0roll.cc4
-rw-r--r--storage/innobase/trx/trx0sys.cc18
-rw-r--r--storage/perfschema/ha_perfschema.cc2
-rw-r--r--storage/perfschema/pfs.cc3
-rw-r--r--storage/perfschema/pfs_digest.cc5
-rw-r--r--storage/perfschema/unittest/pfs-t.cc46
-rw-r--r--storage/perfschema/unittest/pfs_account-oom-t.cc4
-rw-r--r--storage/perfschema/unittest/pfs_connect_attr-t.cc4
-rw-r--r--storage/perfschema/unittest/pfs_host-oom-t.cc4
-rw-r--r--storage/perfschema/unittest/pfs_instr-oom-t.cc29
-rw-r--r--storage/perfschema/unittest/pfs_instr-t.cc9
-rw-r--r--storage/perfschema/unittest/pfs_instr_class-oom-t.cc4
-rw-r--r--storage/perfschema/unittest/pfs_instr_class-t.cc4
-rw-r--r--storage/perfschema/unittest/pfs_misc-t.cc4
-rw-r--r--storage/perfschema/unittest/pfs_timer-t.cc4
-rw-r--r--storage/perfschema/unittest/pfs_user-oom-t.cc4
-rw-r--r--storage/tokudb/CMakeLists.txt5
-rw-r--r--storage/tokudb/PerconaFT/buildheader/make_tdb.cc3
-rw-r--r--storage/tokudb/PerconaFT/ft/ft-ops.cc393
-rw-r--r--storage/tokudb/PerconaFT/src/ydb.cc162
-rw-r--r--storage/tokudb/ha_tokudb.cc28
-rw-r--r--storage/tokudb/mysql-test/tokudb/r/bug-1657908.result70
-rw-r--r--storage/tokudb/mysql-test/tokudb/r/dir_cmd.result58
-rw-r--r--storage/tokudb/mysql-test/tokudb/t/background_job_manager.opt1
-rw-r--r--storage/tokudb/mysql-test/tokudb/t/background_job_manager.test1
-rw-r--r--storage/tokudb/mysql-test/tokudb/t/bug-1657908.test73
-rw-r--r--storage/tokudb/mysql-test/tokudb/t/card_auto_analyze_lots.test1
-rw-r--r--storage/tokudb/mysql-test/tokudb/t/dir_cmd.test52
-rw-r--r--storage/tokudb/mysql-test/tokudb/t/i_s_tokudb_lock_waits_timeout.test1
-rw-r--r--storage/tokudb/mysql-test/tokudb/t/i_s_tokudb_locks.test1
-rw-r--r--storage/tokudb/mysql-test/tokudb/t/i_s_tokudb_trx.test1
-rw-r--r--storage/tokudb/mysql-test/tokudb_backup/r/backup_master_info.result26
-rw-r--r--storage/tokudb/mysql-test/tokudb_backup/r/backup_master_state.result36
-rw-r--r--storage/tokudb/mysql-test/tokudb_backup/r/empty_slave_info_file.result1
-rw-r--r--storage/tokudb/mysql-test/tokudb_backup/r/innodb_use_native_aio_enabled.result5
-rw-r--r--storage/tokudb/mysql-test/tokudb_backup/r/rpl_safe_slave.result77
-rw-r--r--storage/tokudb/mysql-test/tokudb_backup/r/rpl_tokudb_commit_sync.result59
-rw-r--r--storage/tokudb/mysql-test/tokudb_backup/t/backup_master_info.test94
-rw-r--r--storage/tokudb/mysql-test/tokudb_backup/t/backup_master_state.test87
-rw-r--r--storage/tokudb/mysql-test/tokudb_backup/t/empty_slave_info_file.test23
-rw-r--r--storage/tokudb/mysql-test/tokudb_backup/t/innodb_use_native_aio_enabled-master.opt1
-rw-r--r--storage/tokudb/mysql-test/tokudb_backup/t/innodb_use_native_aio_enabled.test19
-rw-r--r--storage/tokudb/mysql-test/tokudb_backup/t/rpl_safe_slave-master.opt1
-rw-r--r--storage/tokudb/mysql-test/tokudb_backup/t/rpl_safe_slave-slave.opt1
-rw-r--r--storage/tokudb/mysql-test/tokudb_backup/t/rpl_safe_slave.cnf14
-rw-r--r--storage/tokudb/mysql-test/tokudb_backup/t/rpl_safe_slave.inc112
-rw-r--r--storage/tokudb/mysql-test/tokudb_backup/t/rpl_safe_slave.test49
-rw-r--r--storage/tokudb/mysql-test/tokudb_backup/t/rpl_tokudb_commit_sync-slave.opt1
-rw-r--r--storage/tokudb/mysql-test/tokudb_backup/t/rpl_tokudb_commit_sync.test72
-rw-r--r--storage/tokudb/mysql-test/tokudb_backup/t/suite.opt2
-rw-r--r--storage/tokudb/mysql-test/tokudb_bugs/r/db233.result10
-rw-r--r--storage/tokudb/mysql-test/tokudb_bugs/t/db233.test18
-rw-r--r--storage/tokudb/mysql-test/tokudb_bugs/t/db397_delete_trigger.test1
-rw-r--r--storage/tokudb/mysql-test/tokudb_bugs/t/db397_insert_trigger.test1
-rw-r--r--storage/tokudb/mysql-test/tokudb_bugs/t/db397_update_trigger.test1
-rw-r--r--storage/tokudb/mysql-test/tokudb_bugs/t/db938.test1
-rw-r--r--storage/tokudb/mysql-test/tokudb_bugs/t/db945.test1
-rw-r--r--storage/tokudb/mysql-test/tokudb_bugs/t/leak172.test2
-rw-r--r--storage/tokudb/mysql-test/tokudb_bugs/t/tokudb718.test1
-rw-r--r--storage/tokudb/tokudb_dir_cmd.cc331
-rw-r--r--storage/tokudb/tokudb_dir_cmd.h46
-rw-r--r--storage/tokudb/tokudb_sysvars.cc7
-rw-r--r--storage/xtradb/btr/btr0sea.cc2
-rw-r--r--storage/xtradb/buf/buf0buf.cc2
-rw-r--r--storage/xtradb/buf/buf0dblwr.cc6
-rw-r--r--storage/xtradb/buf/buf0dump.cc4
-rw-r--r--storage/xtradb/buf/buf0flu.cc40
-rw-r--r--storage/xtradb/dict/dict0dict.cc6
-rw-r--r--storage/xtradb/dict/dict0stats.cc5
-rw-r--r--storage/xtradb/dict/dict0stats_bg.cc4
-rw-r--r--storage/xtradb/fil/fil0fil.cc24
-rw-r--r--storage/xtradb/fts/fts0que.cc20
-rw-r--r--storage/xtradb/handler/ha_innodb.cc129
-rw-r--r--storage/xtradb/include/buf0dblwr.h4
-rw-r--r--storage/xtradb/include/dict0dict.h4
-rw-r--r--storage/xtradb/include/fil0fil.h16
-rw-r--r--storage/xtradb/include/ha0ha.h6
-rw-r--r--storage/xtradb/include/log0online.h2
-rw-r--r--storage/xtradb/include/os0file.h288
-rw-r--r--storage/xtradb/include/os0file.ic203
-rw-r--r--storage/xtradb/include/row0mysql.h2
-rw-r--r--storage/xtradb/include/srv0srv.h9
-rw-r--r--storage/xtradb/include/srv0start.h4
-rw-r--r--storage/xtradb/include/trx0xa.h15
-rw-r--r--storage/xtradb/include/univ.i14
-rw-r--r--storage/xtradb/log/log0log.cc7
-rw-r--r--storage/xtradb/log/log0online.cc60
-rw-r--r--storage/xtradb/log/log0recv.cc4
-rw-r--r--storage/xtradb/os/os0file.cc179
-rw-r--r--storage/xtradb/row/row0log.cc17
-rw-r--r--storage/xtradb/row/row0merge.cc36
-rw-r--r--storage/xtradb/row/row0sel.cc103
-rw-r--r--storage/xtradb/srv/srv0srv.cc30
-rw-r--r--storage/xtradb/srv/srv0start.cc68
-rw-r--r--storage/xtradb/trx/trx0purge.cc5
-rw-r--r--storage/xtradb/trx/trx0roll.cc4
-rw-r--r--storage/xtradb/trx/trx0sys.cc18
255 files changed, 7289 insertions, 4965 deletions
diff --git a/extra/mariabackup/backup_copy.cc b/extra/mariabackup/backup_copy.cc
index 1565e20d732..306009e2139 100644
--- a/extra/mariabackup/backup_copy.cc
+++ b/extra/mariabackup/backup_copy.cc
@@ -450,7 +450,7 @@ datadir_iter_free(datadir_iter_t *it)
/************************************************************************
Holds the state needed to copy single data file. */
struct datafile_cur_t {
- os_file_t file;
+ pfs_os_file_t file;
char rel_path[FN_REFLEN];
char abs_path[FN_REFLEN];
MY_STAT statinfo;
diff --git a/extra/mariabackup/changed_page_bitmap.cc b/extra/mariabackup/changed_page_bitmap.cc
index 435b7fb6172..86a873ef69c 100644
--- a/extra/mariabackup/changed_page_bitmap.cc
+++ b/extra/mariabackup/changed_page_bitmap.cc
@@ -35,7 +35,7 @@ Remove these on the first opportunity, i.e. single-binary XtraBackup. */
/** Single bitmap file information */
struct log_online_bitmap_file_t {
char name[FN_REFLEN]; /*!< Name with full path */
- os_file_t file; /*!< Handle to opened file */
+ pfs_os_file_t file; /*!< Handle to opened file */
ib_uint64_t size; /*!< Size of the file */
ib_uint64_t offset; /*!< Offset of the next read,
or count of already-read bytes
diff --git a/extra/mariabackup/crc/crc_glue.c b/extra/mariabackup/crc/crc_glue.c
index ae3fa91c1b0..c301cb01e2e 100644
--- a/extra/mariabackup/crc/crc_glue.c
+++ b/extra/mariabackup/crc/crc_glue.c
@@ -17,7 +17,7 @@ along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*******************************************************/
-
+#include "my_config.h"
#include "crc_glue.h"
#include "crc-intel-pclmul.h"
#include <stdint.h>
diff --git a/extra/mariabackup/fil_cur.h b/extra/mariabackup/fil_cur.h
index 88239efd2bb..f3601823a5a 100644
--- a/extra/mariabackup/fil_cur.h
+++ b/extra/mariabackup/fil_cur.h
@@ -29,7 +29,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
#include "read_filt.h"
struct xb_fil_cur_t {
- os_file_t file; /*!< source file handle */
+ pfs_os_file_t file; /*!< source file handle */
fil_node_t* node; /*!< source tablespace node */
char rel_path[FN_REFLEN];
/*!< normalized file path */
diff --git a/extra/mariabackup/xb0xb.h b/extra/mariabackup/xb0xb.h
index 659ab8ea5d0..c6e4ae22de6 100644
--- a/extra/mariabackup/xb0xb.h
+++ b/extra/mariabackup/xb0xb.h
@@ -23,7 +23,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
extern void os_io_init_simple(void);
-extern os_file_t files[1000];
+extern pfs_os_file_t files[1000];
extern const char *innodb_checksum_algorithm_names[];
extern TYPELIB innodb_checksum_algorithm_typelib;
extern dberr_t open_or_create_data_files(
diff --git a/extra/mariabackup/xtrabackup.cc b/extra/mariabackup/xtrabackup.cc
index 4fe80819622..c55466c07c1 100644
--- a/extra/mariabackup/xtrabackup.cc
+++ b/extra/mariabackup/xtrabackup.cc
@@ -2412,7 +2412,7 @@ check_if_skip_table(
Reads the space flags from a given data file and returns the compressed
page size, or 0 if the space is not compressed. */
ulint
-xb_get_zip_size(os_file_t file)
+xb_get_zip_size(pfs_os_file_t file)
{
byte *buf;
byte *page;
@@ -4856,7 +4856,7 @@ end:
static my_bool
xtrabackup_init_temp_log(void)
{
- os_file_t src_file = XB_FILE_UNDEFINED;
+ pfs_os_file_t src_file;
char src_path[FN_REFLEN];
char dst_path[FN_REFLEN];
ibool success;
@@ -5183,7 +5183,7 @@ xb_space_create_file(
ulint space_id, /*!<in: space id */
ulint flags __attribute__((unused)),/*!<in: tablespace
flags */
- os_file_t* file) /*!<out: file handle */
+ pfs_os_file_t* file) /*!<out: file handle */
{
ibool ret;
byte* buf;
@@ -5262,7 +5262,7 @@ mismatching ID, renames it to xtrabackup_tmp_#ID.ibd. If there was no
matching file, creates a new tablespace.
@return file handle of matched or created file */
static
-os_file_t
+pfs_os_file_t
xb_delta_open_matching_space(
const char* dbname, /* in: path to destination database dir */
const char* name, /* in: name of delta file (without .delta) */
@@ -5276,7 +5276,7 @@ xb_delta_open_matching_space(
char dest_space_name[FN_REFLEN];
ibool ok;
fil_space_t* fil_space;
- os_file_t file = 0;
+ pfs_os_file_t file;
ulint tablespace_flags;
xb_filter_entry_t* table;
@@ -5440,8 +5440,8 @@ xtrabackup_apply_delta(
including the .delta extension */
void* /*data*/)
{
- os_file_t src_file = XB_FILE_UNDEFINED;
- os_file_t dst_file = XB_FILE_UNDEFINED;
+ pfs_os_file_t src_file;
+ pfs_os_file_t dst_file;
char src_path[FN_REFLEN];
char dst_path[FN_REFLEN];
char meta_path[FN_REFLEN];
@@ -5815,7 +5815,7 @@ xtrabackup_apply_deltas()
static my_bool
xtrabackup_close_temp_log(my_bool clear_flag)
{
- os_file_t src_file = XB_FILE_UNDEFINED;
+ pfs_os_file_t src_file;
char src_path[FN_REFLEN];
char dst_path[FN_REFLEN];
ibool success;
@@ -6597,7 +6597,7 @@ skip_check:
if (xtrabackup_export) {
msg("xtrabackup: export option is specified.\n");
- os_file_t info_file = XB_FILE_UNDEFINED;
+ pfs_os_file_t info_file;
char info_file_path[FN_REFLEN];
ibool success;
char table_name[FN_REFLEN];
diff --git a/extra/mariabackup/xtrabackup.h b/extra/mariabackup/xtrabackup.h
index 51491ce1f00..d3c4c486d9f 100644
--- a/extra/mariabackup/xtrabackup.h
+++ b/extra/mariabackup/xtrabackup.h
@@ -27,7 +27,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
#include "changed_page_bitmap.h"
#ifdef __WIN__
-#define XB_FILE_UNDEFINED NULL
+#define XB_FILE_UNDEFINED INVALID_HANDLE_VALUE
#else
#define XB_FILE_UNDEFINED (-1)
#endif
@@ -194,7 +194,7 @@ void xb_data_files_close(void);
/***********************************************************************
Reads the space flags from a given data file and returns the compressed
page size, or 0 if the space is not compressed. */
-ulint xb_get_zip_size(os_file_t file);
+ulint xb_get_zip_size(pfs_os_file_t file);
/************************************************************************
Checks if a table specified as a name in the form "database/name" (InnoDB 5.6)
diff --git a/mysql-test/r/derived_view.result b/mysql-test/r/derived_view.result
index bd07fba6d4f..d60ed34d927 100644
--- a/mysql-test/r/derived_view.result
+++ b/mysql-test/r/derived_view.result
@@ -2590,5 +2590,43 @@ Handler_read_rnd_deleted 0
Handler_read_rnd_next 27
deallocate prepare stmt1;
drop table t1,t2;
+#
+# Bug mdev-12670: mergeable derived / view with subqueries
+# subject to semi-join optimizations
+# (actually this is a 5.3 bug.)
+#
+create table t1 (a int) engine=myisam;
+insert into t1 values (5),(3),(2),(7),(2),(5),(1);
+create table t2 (b int, index idx(b)) engine=myisam;
+insert into t2 values (2),(3),(2),(1),(3),(4);
+insert into t2 select b+10 from t2;
+insert into t2 select b+10 from t2;
+insert into t2 select b+10 from t2;
+insert into t2 select b+10 from t2;
+insert into t2 select b+10 from t2;
+insert into t2 select b+10 from t2;
+insert into t2 select b+10 from t2;
+insert into t2 select b+10 from t2;
+insert into t2 select b+10 from t2;
+insert into t2 select b+10 from t2;
+analyze table t1,t2;
+Table Op Msg_type Msg_text
+test.t1 analyze status OK
+test.t2 analyze status OK
+explain select a from t1 where a in (select b from t2);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 7 Using where
+1 PRIMARY t2 ref idx idx 5 test.t1.a 140 Using index; FirstMatch(t1)
+explain select * from (select a from t1 where a in (select b from t2)) t;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 7 Using where
+1 PRIMARY t2 ref idx idx 5 test.t1.a 140 Using index; FirstMatch(t1)
+create view v1 as select a from t1 where a in (select b from t2);
+explain select * from v1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 7 Using where
+1 PRIMARY t2 ref idx idx 5 test.t1.a 140 Using index; FirstMatch(t1)
+drop view v1;
+drop table t1,t2;
set optimizer_switch=@exit_optimizer_switch;
set join_cache_level=@exit_join_cache_level;
diff --git a/mysql-test/r/limit_rows_examined.result b/mysql-test/r/limit_rows_examined.result
index 1f829d545f6..0b3bc196a31 100644
--- a/mysql-test/r/limit_rows_examined.result
+++ b/mysql-test/r/limit_rows_examined.result
@@ -426,7 +426,7 @@ c1
bb
cc
Warnings:
-Warning 1931 Query execution was interrupted. The query examined at least 18 rows, which exceeds LIMIT ROWS EXAMINED (16). The query result may be incomplete.
+Warning 1931 Query execution was interrupted. The query examined at least 17 rows, which exceeds LIMIT ROWS EXAMINED (16). The query result may be incomplete.
select * from v1 LIMIT ROWS EXAMINED 11;
c1
bb
@@ -439,7 +439,8 @@ from (select * from t1
where c1 IN (select * from t2 where c2 > ' ' LIMIT ROWS EXAMINED 0)) as tmp
LIMIT ROWS EXAMINED 11;
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using where
+1 PRIMARY t1 ALL NULL NULL NULL NULL 4
+1 PRIMARY <subquery3> eq_ref distinct_key distinct_key 2 func 1
3 MATERIALIZED t2 ALL NULL NULL NULL NULL 4 Using where
select *
from (select * from t1
diff --git a/mysql-test/r/subselect_mat_cost_bugs.result b/mysql-test/r/subselect_mat_cost_bugs.result
index 9bfd5bd67b5..dba4d049da3 100644
--- a/mysql-test/r/subselect_mat_cost_bugs.result
+++ b/mysql-test/r/subselect_mat_cost_bugs.result
@@ -379,6 +379,7 @@ drop table t3, t4, t5;
#
# LP BUG#858038 The result of a query with NOT IN subquery depends on the state of the optimizer switch
#
+set @optimizer_switch_save= @@optimizer_switch;
create table t1 (c1 char(2) not null, c2 char(2));
create table t2 (c3 char(2), c4 char(2));
insert into t1 values ('a1', 'b1');
@@ -400,6 +401,7 @@ id select_type table type possible_keys key key_len ref rows Extra
select * from t1 where c1 = 'a2' and (c1, c2) not in (select * from t2);
c1 c2
drop table t1, t2;
+set optimizer_switch= @optimizer_switch_save;
#
# MDEV-12673: cost-based choice between materialization and in-to-exists
#
@@ -442,3 +444,44 @@ id select_type table type possible_keys key key_len ref rows Extra
2 DEPENDENT SUBQUERY t3 const PRIMARY PRIMARY 4 const 1
2 DEPENDENT SUBQUERY t2 index NULL i2 11 NULL 2 Using where; Using index
DROP TABLE t1,t2,t3;
+#
+# MDEV-7599: in-to-exists chosen after min/max optimization
+#
+set @optimizer_switch_save= @@optimizer_switch;
+CREATE TABLE t1 (a INT, KEY(a)) ENGINE=MyISAM;
+INSERT INTO t1 VALUES (1),(2);
+CREATE TABLE t2 (b INT, c INT) ENGINE=MyISAM;
+INSERT INTO t2 VALUES (1,6),(2,4), (8,9);
+SELECT * FROM t2 WHERE b != ALL (SELECT MIN(a) FROM t1, t2 WHERE t2.c = t2.b);
+b c
+EXPLAIN EXTENDED SELECT * FROM t2 WHERE b != ALL (SELECT MIN(a) FROM t1, t2 WHERE t2.c = t2.b);
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY t2 ALL NULL NULL NULL NULL 3 100.00 Using where
+2 MATERIALIZED t1 index NULL a 5 NULL 2 100.00 Using index
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 100.00 Using where; Using join buffer (flat, BNL join)
+Warnings:
+Note 1003 select `test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c` from `test`.`t2` where (not(<expr_cache><`test`.`t2`.`b`>(<in_optimizer>(`test`.`t2`.`b`,`test`.`t2`.`b` in ( <materialize> (select min(`test`.`t1`.`a`) from `test`.`t1` join `test`.`t2` where (`test`.`t2`.`c` = `test`.`t2`.`b`) ), <primary_index_lookup>(`test`.`t2`.`b` in <temporary table> on distinct_key where ((`test`.`t2`.`b` = `<subquery2>`.`MIN(a)`))))))))
+set optimizer_switch= 'materialization=off';
+SELECT * FROM t2 WHERE b != ALL (SELECT MIN(a) FROM t1, t2 WHERE t2.c = t2.b);
+b c
+EXPLAIN EXTENDED SELECT * FROM t2 WHERE b != ALL (SELECT MIN(a) FROM t1, t2 WHERE t2.c = t2.b);
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY t2 ALL NULL NULL NULL NULL 3 100.00 Using where
+2 DEPENDENT SUBQUERY t1 index NULL a 5 NULL 2 100.00 Using index
+2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 3 100.00 Using where; Using join buffer (flat, BNL join)
+Warnings:
+Note 1003 select `test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c` from `test`.`t2` where (not(<expr_cache><`test`.`t2`.`b`>(<in_optimizer>(`test`.`t2`.`b`,<exists>(select min(`test`.`t1`.`a`) from `test`.`t1` join `test`.`t2` where (`test`.`t2`.`c` = `test`.`t2`.`b`) having trigcond((<cache>(`test`.`t2`.`b`) = <ref_null_helper>(min(`test`.`t1`.`a`)))))))))
+set optimizer_switch= @optimizer_switch_save;
+DROP TABLE t1,t2;
+CREATE TABLE t1 (f1 varchar(10)) ENGINE=MyISAM;
+INSERT INTO t1 VALUES ('foo'),('bar');
+CREATE TABLE t2 (f2 varchar(10), key(f2)) ENGINE=MyISAM;
+INSERT INTO t2 VALUES ('baz'),('qux');
+CREATE TABLE t3 (f3 varchar(10)) ENGINE=MyISAM;
+INSERT INTO t3 VALUES ('abc'),('def');
+SELECT * FROM t1
+WHERE f1 = ALL( SELECT MAX(t2a.f2)
+FROM t2 AS t2a INNER JOIN t2 t2b INNER JOIN t3
+ON (f3 = t2b.f2) );
+f1
+DROP TABLE t1,t2,t3;
diff --git a/mysql-test/r/subselect_sj.result b/mysql-test/r/subselect_sj.result
index 1de2b5fe01c..cc0f3b27e38 100644
--- a/mysql-test/r/subselect_sj.result
+++ b/mysql-test/r/subselect_sj.result
@@ -1652,9 +1652,9 @@ CREATE VIEW v1 AS SELECT 1;
EXPLAIN
SELECT * FROM t1 INNER JOIN t2 ON t2.a != 0 AND t2.a IN (SELECT * FROM v1);
id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY <derived3> system NULL NULL NULL NULL 1
1 PRIMARY t1 ALL NULL NULL NULL NULL 2
1 PRIMARY t2 ALL NULL NULL NULL NULL 2 Using where; Using join buffer (flat, BNL join)
-2 MATERIALIZED <derived3> system NULL NULL NULL NULL 1
3 DERIVED NULL NULL NULL NULL NULL NULL NULL No tables used
SELECT * FROM t1 INNER JOIN t2 ON t2.a != 0 AND t2.a IN (SELECT * FROM v1);
a a
@@ -3068,4 +3068,43 @@ project_number
aaa
drop table t1, t2, t3;
set optimizer_switch= @tmp_mdev6859;
+#
+# MDEV-12675: subquery subject to semi-join optimizations
+# in ON expression of INNER JOIN
+#
+set @tmp_mdev12675=@@optimizer_switch;
+set optimizer_switch=default;
+create table t1 (a int) engine=myisam;
+insert into t1 values (5),(3),(2),(7),(2),(5),(1);
+create table t2 (b int, index idx(b)) engine=myisam;
+insert into t2 values (2),(3),(2),(1),(3),(4);
+insert into t2 select b+10 from t2;
+insert into t2 select b+10 from t2;
+insert into t2 select b+10 from t2;
+insert into t2 select b+10 from t2;
+insert into t2 select b+10 from t2;
+insert into t2 select b+10 from t2;
+insert into t2 select b+10 from t2;
+insert into t2 select b+10 from t2;
+insert into t2 select b+10 from t2;
+insert into t2 select b+10 from t2;
+insert into t2 select b+10 from t2;
+analyze table t1,t2;
+Table Op Msg_type Msg_text
+test.t1 analyze status OK
+test.t2 analyze status OK
+explain
+select a from t1, t2 where b between 1 and 2 and a in (select b from t2);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 7 Using where
+1 PRIMARY t2 ref idx idx 5 test.t1.a 256 Using index; FirstMatch(t1)
+1 PRIMARY t2 range idx idx 5 NULL 2 Using where; Using index; Using join buffer (flat, BNL join)
+explain
+select a from t1 join t2 on b between 1 and 2 and a in (select b from t2);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 7 Using where
+1 PRIMARY t2 ref idx idx 5 test.t1.a 256 Using index; FirstMatch(t1)
+1 PRIMARY t2 range idx idx 5 NULL 2 Using where; Using index; Using join buffer (flat, BNL join)
+drop table t1,t2;
+set optimizer_switch= @tmp_mdev12675;
set optimizer_switch=@subselect_sj_tmp;
diff --git a/mysql-test/r/subselect_sj2_mat.result b/mysql-test/r/subselect_sj2_mat.result
index 16e8f88168d..ec7e881ac32 100644
--- a/mysql-test/r/subselect_sj2_mat.result
+++ b/mysql-test/r/subselect_sj2_mat.result
@@ -1610,3 +1610,26 @@ i1
DROP TABLE t1,t2,t3;
set join_cache_level= @save_join_cache_level;
set optimizer_switch=@save_optimizer_switch;
+#
+# mdev-7791: materialization of a semi-join subquery +
+# RAND() in WHERE
+# (materialized table is accessed last)
+#
+set @save_optimizer_switch=@@optimizer_switch;
+set optimizer_switch='materialization=on';
+create table t1(i int);
+insert into t1 values (1), (2), (3), (7), (9), (10);
+create table t2(i int);
+insert into t2 values (1), (2), (3), (4), (5), (6), (7), (8), (9), (10);
+select * from t1 where (rand() < 0) and i in (select i from t2);
+i
+explain extended
+select * from t1 where (rand() < 0) and i in (select i from t2);
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 6 100.00 Using where
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 100.00
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 10 100.00
+Warnings:
+Note 1003 select `test`.`t1`.`i` AS `i` from `test`.`t1` semi join (`test`.`t2`) where ((rand() < 0))
+drop table t1,t2;
+set optimizer_switch=@save_optimizer_switch;
diff --git a/mysql-test/r/subselect_sj_jcl6.result b/mysql-test/r/subselect_sj_jcl6.result
index 923cee70ef4..44821d6d982 100644
--- a/mysql-test/r/subselect_sj_jcl6.result
+++ b/mysql-test/r/subselect_sj_jcl6.result
@@ -1665,9 +1665,9 @@ CREATE VIEW v1 AS SELECT 1;
EXPLAIN
SELECT * FROM t1 INNER JOIN t2 ON t2.a != 0 AND t2.a IN (SELECT * FROM v1);
id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY <derived3> system NULL NULL NULL NULL 1
1 PRIMARY t1 ALL NULL NULL NULL NULL 2
1 PRIMARY t2 ALL NULL NULL NULL NULL 2 Using where; Using join buffer (flat, BNL join)
-2 MATERIALIZED <derived3> system NULL NULL NULL NULL 1
3 DERIVED NULL NULL NULL NULL NULL NULL NULL No tables used
SELECT * FROM t1 INNER JOIN t2 ON t2.a != 0 AND t2.a IN (SELECT * FROM v1);
a a
@@ -3082,6 +3082,45 @@ project_number
aaa
drop table t1, t2, t3;
set optimizer_switch= @tmp_mdev6859;
+#
+# MDEV-12675: subquery subject to semi-join optimizations
+# in ON expression of INNER JOIN
+#
+set @tmp_mdev12675=@@optimizer_switch;
+set optimizer_switch=default;
+create table t1 (a int) engine=myisam;
+insert into t1 values (5),(3),(2),(7),(2),(5),(1);
+create table t2 (b int, index idx(b)) engine=myisam;
+insert into t2 values (2),(3),(2),(1),(3),(4);
+insert into t2 select b+10 from t2;
+insert into t2 select b+10 from t2;
+insert into t2 select b+10 from t2;
+insert into t2 select b+10 from t2;
+insert into t2 select b+10 from t2;
+insert into t2 select b+10 from t2;
+insert into t2 select b+10 from t2;
+insert into t2 select b+10 from t2;
+insert into t2 select b+10 from t2;
+insert into t2 select b+10 from t2;
+insert into t2 select b+10 from t2;
+analyze table t1,t2;
+Table Op Msg_type Msg_text
+test.t1 analyze status OK
+test.t2 analyze status OK
+explain
+select a from t1, t2 where b between 1 and 2 and a in (select b from t2);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 7 Using where
+1 PRIMARY t2 ref idx idx 5 test.t1.a 256 Using index; FirstMatch(t1)
+1 PRIMARY t2 range idx idx 5 NULL 2 Using where; Using index; Using join buffer (flat, BNL join)
+explain
+select a from t1 join t2 on b between 1 and 2 and a in (select b from t2);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 7 Using where
+1 PRIMARY t2 ref idx idx 5 test.t1.a 256 Using index; FirstMatch(t1)
+1 PRIMARY t2 range idx idx 5 NULL 2 Using where; Using index; Using join buffer (flat, BNL join)
+drop table t1,t2;
+set optimizer_switch= @tmp_mdev12675;
set optimizer_switch=@subselect_sj_tmp;
#
# BUG#49129: Wrong result with IN-subquery with join_cache_level=6 and firstmatch=off
diff --git a/mysql-test/suite/perfschema/r/start_server_1_digest.result b/mysql-test/suite/perfschema/r/start_server_1_digest.result
new file mode 100644
index 00000000000..cf07022d344
--- /dev/null
+++ b/mysql-test/suite/perfschema/r/start_server_1_digest.result
@@ -0,0 +1,7 @@
+SELECT "Digest table has a size 1 and is full already." as use_case;
+use_case
+Digest table has a size 1 and is full already.
+select SCHEMA_NAME, DIGEST, DIGEST_TEXT
+from performance_schema.events_statements_summary_by_digest;
+SCHEMA_NAME DIGEST DIGEST_TEXT
+NULL NULL NULL
diff --git a/mysql-test/suite/perfschema/t/start_server_1_digest-master.opt b/mysql-test/suite/perfschema/t/start_server_1_digest-master.opt
new file mode 100644
index 00000000000..e59be3eb02f
--- /dev/null
+++ b/mysql-test/suite/perfschema/t/start_server_1_digest-master.opt
@@ -0,0 +1 @@
+--performance-schema-digests-size=1
diff --git a/mysql-test/suite/perfschema/t/start_server_1_digest.test b/mysql-test/suite/perfschema/t/start_server_1_digest.test
new file mode 100644
index 00000000000..998d9a5eebe
--- /dev/null
+++ b/mysql-test/suite/perfschema/t/start_server_1_digest.test
@@ -0,0 +1,15 @@
+# -----------------------------------------------------------------------
+# Tests for the performance schema statement Digests.
+# -----------------------------------------------------------------------
+
+--source include/not_embedded.inc
+--source include/have_perfschema.inc
+--source include/no_protocol.inc
+
+SELECT "Digest table has a size 1 and is full already." as use_case;
+
+select SCHEMA_NAME, DIGEST, DIGEST_TEXT
+ from performance_schema.events_statements_summary_by_digest;
+
+
+
diff --git a/mysql-test/suite/sys_vars/r/innodb_empty_free_list_algorithm_basic.result b/mysql-test/suite/sys_vars/r/innodb_empty_free_list_algorithm_basic.result
index 0730055d104..6a1c6df9c89 100644
--- a/mysql-test/suite/sys_vars/r/innodb_empty_free_list_algorithm_basic.result
+++ b/mysql-test/suite/sys_vars/r/innodb_empty_free_list_algorithm_basic.result
@@ -1,7 +1,7 @@
SET @start_value = @@GLOBAL.innodb_empty_free_list_algorithm;
SELECT @@GLOBAL.innodb_empty_free_list_algorithm;
@@GLOBAL.innodb_empty_free_list_algorithm
-BACKOFF
+LEGACY
SELECT @@SESSION.innodb_empty_free_list_algorithm;
ERROR HY000: Variable 'innodb_empty_free_list_algorithm' is a GLOBAL variable
SET GLOBAL innodb_empty_free_list_algorithm='legacy';
diff --git a/mysql-test/suite/sys_vars/r/sysvars_innodb,xtradb.rdiff b/mysql-test/suite/sys_vars/r/sysvars_innodb,xtradb.rdiff
index d801270c6b6..6712ce9c586 100644
--- a/mysql-test/suite/sys_vars/r/sysvars_innodb,xtradb.rdiff
+++ b/mysql-test/suite/sys_vars/r/sysvars_innodb,xtradb.rdiff
@@ -661,8 +661,8 @@
COMMAND_LINE_ARGUMENT OPTIONAL
VARIABLE_NAME INNODB_VERSION
SESSION_VALUE NULL
--GLOBAL_VALUE 5.6.35
-+GLOBAL_VALUE 5.6.35-80.0
+-GLOBAL_VALUE 5.6.36
++GLOBAL_VALUE 5.6.36-80.0
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE NULL
VARIABLE_SCOPE GLOBAL
diff --git a/mysql-test/suite/sys_vars/r/sysvars_innodb.result b/mysql-test/suite/sys_vars/r/sysvars_innodb.result
index 981780c086f..76f8317b77a 100644
--- a/mysql-test/suite/sys_vars/r/sysvars_innodb.result
+++ b/mysql-test/suite/sys_vars/r/sysvars_innodb.result
@@ -2387,7 +2387,7 @@ READ_ONLY NO
COMMAND_LINE_ARGUMENT OPTIONAL
VARIABLE_NAME INNODB_VERSION
SESSION_VALUE NULL
-GLOBAL_VALUE 5.6.35
+GLOBAL_VALUE 5.6.36
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE NULL
VARIABLE_SCOPE GLOBAL
diff --git a/mysql-test/t/derived_view.test b/mysql-test/t/derived_view.test
index ba58fada7f7..503d00b94c3 100644
--- a/mysql-test/t/derived_view.test
+++ b/mysql-test/t/derived_view.test
@@ -1881,6 +1881,36 @@ deallocate prepare stmt1;
drop table t1,t2;
+--echo #
+--echo # Bug mdev-12670: mergeable derived / view with subqueries
+--echo # subject to semi-join optimizations
+--echo # (actually this is a 5.3 bug.)
+--echo #
+
+create table t1 (a int) engine=myisam;
+insert into t1 values (5),(3),(2),(7),(2),(5),(1);
+create table t2 (b int, index idx(b)) engine=myisam;
+insert into t2 values (2),(3),(2),(1),(3),(4);
+insert into t2 select b+10 from t2;
+insert into t2 select b+10 from t2;
+insert into t2 select b+10 from t2;
+insert into t2 select b+10 from t2;
+insert into t2 select b+10 from t2;
+insert into t2 select b+10 from t2;
+insert into t2 select b+10 from t2;
+insert into t2 select b+10 from t2;
+insert into t2 select b+10 from t2;
+insert into t2 select b+10 from t2;
+analyze table t1,t2;
+
+explain select a from t1 where a in (select b from t2);
+explain select * from (select a from t1 where a in (select b from t2)) t;
+create view v1 as select a from t1 where a in (select b from t2);
+explain select * from v1;
+
+drop view v1;
+drop table t1,t2;
+
# The following command must be the last one the file
set optimizer_switch=@exit_optimizer_switch;
set join_cache_level=@exit_join_cache_level;
diff --git a/mysql-test/t/subselect_mat_cost_bugs.test b/mysql-test/t/subselect_mat_cost_bugs.test
index 316ac707bef..9e3ac603ec6 100644
--- a/mysql-test/t/subselect_mat_cost_bugs.test
+++ b/mysql-test/t/subselect_mat_cost_bugs.test
@@ -406,6 +406,8 @@ drop table t3, t4, t5;
--echo # LP BUG#858038 The result of a query with NOT IN subquery depends on the state of the optimizer switch
--echo #
+set @optimizer_switch_save= @@optimizer_switch;
+
create table t1 (c1 char(2) not null, c2 char(2));
create table t2 (c3 char(2), c4 char(2));
@@ -425,6 +427,8 @@ select * from t1 where c1 = 'a2' and (c1, c2) not in (select * from t2);
drop table t1, t2;
+set optimizer_switch= @optimizer_switch_save;
+
--echo #
--echo # MDEV-12673: cost-based choice between materialization and in-to-exists
--echo #
@@ -463,3 +467,43 @@ SELECT * FROM t1 WHERE i1 NOT IN (
);
DROP TABLE t1,t2,t3;
+
+--echo #
+--echo # MDEV-7599: in-to-exists chosen after min/max optimization
+--echo #
+
+set @optimizer_switch_save= @@optimizer_switch;
+
+CREATE TABLE t1 (a INT, KEY(a)) ENGINE=MyISAM;
+INSERT INTO t1 VALUES (1),(2);
+
+CREATE TABLE t2 (b INT, c INT) ENGINE=MyISAM;
+INSERT INTO t2 VALUES (1,6),(2,4), (8,9);
+
+let $q=
+SELECT * FROM t2 WHERE b != ALL (SELECT MIN(a) FROM t1, t2 WHERE t2.c = t2.b);
+
+eval $q;
+eval EXPLAIN EXTENDED $q;
+set optimizer_switch= 'materialization=off';
+eval $q;
+eval EXPLAIN EXTENDED $q;
+set optimizer_switch= @optimizer_switch_save;
+
+DROP TABLE t1,t2;
+
+CREATE TABLE t1 (f1 varchar(10)) ENGINE=MyISAM;
+INSERT INTO t1 VALUES ('foo'),('bar');
+
+CREATE TABLE t2 (f2 varchar(10), key(f2)) ENGINE=MyISAM;
+INSERT INTO t2 VALUES ('baz'),('qux');
+
+CREATE TABLE t3 (f3 varchar(10)) ENGINE=MyISAM;
+INSERT INTO t3 VALUES ('abc'),('def');
+
+SELECT * FROM t1
+ WHERE f1 = ALL( SELECT MAX(t2a.f2)
+ FROM t2 AS t2a INNER JOIN t2 t2b INNER JOIN t3
+ ON (f3 = t2b.f2) );
+
+DROP TABLE t1,t2,t3;
diff --git a/mysql-test/t/subselect_sj.test b/mysql-test/t/subselect_sj.test
index b6d6e0a5172..071b135f740 100644
--- a/mysql-test/t/subselect_sj.test
+++ b/mysql-test/t/subselect_sj.test
@@ -2773,5 +2773,37 @@ WHERE ( SELECT z.country
drop table t1, t2, t3;
set optimizer_switch= @tmp_mdev6859;
+--echo #
+--echo # MDEV-12675: subquery subject to semi-join optimizations
+--echo # in ON expression of INNER JOIN
+--echo #
+
+set @tmp_mdev12675=@@optimizer_switch;
+set optimizer_switch=default;
+create table t1 (a int) engine=myisam;
+insert into t1 values (5),(3),(2),(7),(2),(5),(1);
+create table t2 (b int, index idx(b)) engine=myisam;
+insert into t2 values (2),(3),(2),(1),(3),(4);
+insert into t2 select b+10 from t2;
+insert into t2 select b+10 from t2;
+insert into t2 select b+10 from t2;
+insert into t2 select b+10 from t2;
+insert into t2 select b+10 from t2;
+insert into t2 select b+10 from t2;
+insert into t2 select b+10 from t2;
+insert into t2 select b+10 from t2;
+insert into t2 select b+10 from t2;
+insert into t2 select b+10 from t2;
+insert into t2 select b+10 from t2;
+analyze table t1,t2;
+
+explain
+select a from t1, t2 where b between 1 and 2 and a in (select b from t2);
+explain
+select a from t1 join t2 on b between 1 and 2 and a in (select b from t2);
+
+drop table t1,t2;
+set optimizer_switch= @tmp_mdev12675;
+
# The following command must be the last one the file
set optimizer_switch=@subselect_sj_tmp;
diff --git a/mysql-test/t/subselect_sj2_mat.test b/mysql-test/t/subselect_sj2_mat.test
index 61d9b09edff..0f2892ae2dc 100644
--- a/mysql-test/t/subselect_sj2_mat.test
+++ b/mysql-test/t/subselect_sj2_mat.test
@@ -263,3 +263,23 @@ DROP TABLE t1,t2,t3;
set join_cache_level= @save_join_cache_level;
set optimizer_switch=@save_optimizer_switch;
+--echo #
+--echo # mdev-7791: materialization of a semi-join subquery +
+--echo # RAND() in WHERE
+--echo # (materialized table is accessed last)
+--echo #
+
+set @save_optimizer_switch=@@optimizer_switch;
+set optimizer_switch='materialization=on';
+
+create table t1(i int);
+insert into t1 values (1), (2), (3), (7), (9), (10);
+create table t2(i int);
+insert into t2 values (1), (2), (3), (4), (5), (6), (7), (8), (9), (10);
+
+select * from t1 where (rand() < 0) and i in (select i from t2);
+explain extended
+select * from t1 where (rand() < 0) and i in (select i from t2);
+
+drop table t1,t2;
+set optimizer_switch=@save_optimizer_switch;
diff --git a/mysys/ma_dyncol.c b/mysys/ma_dyncol.c
index 1909c0fd9a3..be40052b561 100644
--- a/mysys/ma_dyncol.c
+++ b/mysys/ma_dyncol.c
@@ -4038,6 +4038,7 @@ mariadb_dyncol_val_double(double *dbl, DYNAMIC_COLUMN_VALUE *val)
*dbl= strtod(str, &end);
if (*end != '\0')
rc= ER_DYNCOL_TRUNCATED;
+ break;
}
case DYN_COL_DECIMAL:
if (decimal2double(&val->x.decimal.value, dbl) != E_DEC_OK)
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index 6330165702e..3ca7d3afa6c 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -1430,8 +1430,9 @@ Item_in_subselect::Item_in_subselect(THD *thd, Item * left_exp,
st_select_lex *select_lex):
Item_exists_subselect(thd), left_expr_cache(0), first_execution(TRUE),
in_strategy(SUBS_NOT_TRANSFORMED),
- pushed_cond_guards(NULL), is_jtbm_merged(FALSE), is_jtbm_const_tab(FALSE),
- is_flattenable_semijoin(FALSE), is_registered_semijoin(FALSE),
+ pushed_cond_guards(NULL), do_not_convert_to_sj(FALSE), is_jtbm_merged(FALSE),
+ is_jtbm_const_tab(FALSE), is_flattenable_semijoin(FALSE),
+ is_registered_semijoin(FALSE),
upper_item(0)
{
DBUG_ENTER("Item_in_subselect::Item_in_subselect");
@@ -2584,6 +2585,27 @@ bool Item_in_subselect::inject_in_to_exists_cond(JOIN *join_arg)
DBUG_ENTER("Item_in_subselect::inject_in_to_exists_cond");
DBUG_ASSERT(thd == join_arg->thd);
+ if (select_lex->min_max_opt_list.elements)
+ {
+ /*
+ MIN/MAX optimizations have been applied to Item_sum objects
+ of the subquery this subquery predicate in opt_sum_query().
+ Injection of new condition invalidates this optimizations.
+ Thus those optimizations must be rolled back.
+ */
+ List_iterator_fast<Item_sum> it(select_lex->min_max_opt_list);
+ Item_sum *item;
+ while ((item= it++))
+ {
+ item->clear();
+ item->reset_forced_const();
+ }
+ if (where_item)
+ where_item->update_used_tables();
+ if (having_item)
+ having_item->update_used_tables();
+ }
+
if (where_item)
{
List<Item> *and_args= NULL;
diff --git a/sql/item_subselect.h b/sql/item_subselect.h
index 60449e06323..009aff5ed80 100644
--- a/sql/item_subselect.h
+++ b/sql/item_subselect.h
@@ -489,6 +489,8 @@ public:
Item *left_expr_orig;
/* Priority of this predicate in the convert-to-semi-join-nest process. */
int sj_convert_priority;
+ /* May be TRUE only for the candidates to semi-join conversion */
+ bool do_not_convert_to_sj;
/*
Types of left_expr and subquery's select list allow to perform subquery
materialization. Currently, we set this to FALSE when it as well could
@@ -579,8 +581,8 @@ public:
Item_in_subselect(THD *thd_arg):
Item_exists_subselect(thd_arg), left_expr_cache(0), first_execution(TRUE),
in_strategy(SUBS_NOT_TRANSFORMED),
- pushed_cond_guards(NULL), func(NULL), is_jtbm_merged(FALSE),
- is_jtbm_const_tab(FALSE), upper_item(0) {}
+ pushed_cond_guards(NULL), func(NULL), do_not_convert_to_sj(FALSE),
+ is_jtbm_merged(FALSE), is_jtbm_const_tab(FALSE), upper_item(0) {}
void cleanup();
subs_type substype() { return IN_SUBS; }
void reset()
@@ -634,6 +636,8 @@ public:
*/
int get_identifier();
+ void block_conversion_to_sj () { do_not_convert_to_sj= TRUE; }
+
bool test_strategy(uchar strategy)
{ return MY_TEST(in_strategy & strategy); }
diff --git a/sql/item_sum.h b/sql/item_sum.h
index 7ad037c046b..d6ccfeb8529 100644
--- a/sql/item_sum.h
+++ b/sql/item_sum.h
@@ -458,6 +458,7 @@ public:
used_tables_cache= 0;
const_item_cache= true;
}
+ void reset_forced_const() { const_item_cache= false; }
virtual bool const_during_execution() const { return false; }
virtual void print(String *str, enum_query_type query_type);
void fix_num_length_and_dec();
diff --git a/sql/mysqld.h b/sql/mysqld.h
index 106db8176b6..419dbac1613 100644
--- a/sql/mysqld.h
+++ b/sql/mysqld.h
@@ -126,7 +126,7 @@ extern ulong slave_retried_transactions;
extern ulong slave_run_triggers_for_rbr;
extern ulonglong slave_type_conversions_options;
extern my_bool read_only, opt_readonly;
-extern my_bool lower_case_file_system;
+extern MYSQL_PLUGIN_IMPORT my_bool lower_case_file_system;
extern my_bool opt_enable_named_pipe, opt_sync_frm, opt_allow_suspicious_udfs;
extern my_bool opt_secure_auth;
extern const char *current_dbug_option;
diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc
index 042f8d4eac1..0335a663ec3 100644
--- a/sql/opt_subselect.cc
+++ b/sql/opt_subselect.cc
@@ -1003,6 +1003,25 @@ bool check_for_outer_joins(List<TABLE_LIST> *join_list)
}
+void find_and_block_conversion_to_sj(Item *to_find,
+ List_iterator_fast<Item_in_subselect> &li)
+{
+ if (to_find->type() != Item::SUBSELECT_ITEM ||
+ ((Item_subselect *) to_find)->substype() != Item_subselect::IN_SUBS)
+ return;
+ Item_in_subselect *in_subq;
+ li.rewind();
+ while ((in_subq= li++))
+ {
+ if (in_subq == to_find)
+ {
+ in_subq->block_conversion_to_sj();
+ return;
+ }
+ }
+}
+
+
/*
Convert semi-join subquery predicates into semi-join join nests
@@ -1055,7 +1074,6 @@ bool convert_join_subqueries_to_semijoins(JOIN *join)
Query_arena *arena, backup;
Item_in_subselect *in_subq;
THD *thd= join->thd;
- List_iterator<TABLE_LIST> ti(join->select_lex->leaf_tables);
DBUG_ENTER("convert_join_subqueries_to_semijoins");
if (join->select_lex->sj_subselects.is_empty())
@@ -1073,6 +1091,60 @@ bool convert_join_subqueries_to_semijoins(JOIN *join)
subq_sel->update_used_tables();
}
+ /*
+ Check all candidates to semi-join conversion that occur
+ in ON expressions of outer join. Set the flag blocking
+ this conversion for them.
+ */
+ TABLE_LIST *tbl;
+ List_iterator<TABLE_LIST> ti(join->select_lex->leaf_tables);
+ while ((tbl= ti++))
+ {
+ TABLE_LIST *embedded;
+ TABLE_LIST *embedding= tbl;
+ do
+ {
+ embedded= embedding;
+ if (MY_TEST(embedded->outer_join))
+ {
+ Item *cond= embedded->on_expr;
+ if (!cond)
+ ;
+ else if (cond->type() != Item::COND_ITEM)
+ find_and_block_conversion_to_sj(cond, li);
+ else if (((Item_cond*) cond)->functype() ==
+ Item_func::COND_AND_FUNC)
+ {
+ Item *item;
+ List_iterator<Item> it(*(((Item_cond*) cond)->argument_list()));
+ while ((item= it++))
+ {
+ find_and_block_conversion_to_sj(item, li);
+ }
+ }
+ }
+ embedding= embedded->embedding;
+ }
+ while (embedding &&
+ embedding->nested_join->join_list.head() == embedded);
+ }
+
+ /*
+ Block conversion to semi-joins for those candidates that
+ are encountered in the WHERE condition of the multi-table view
+ with CHECK OPTION if this view is used in UPDATE/DELETE.
+ (This limitation can be, probably, easily lifted.)
+ */
+ li.rewind();
+ while ((in_subq= li++))
+ {
+ if (in_subq->emb_on_expr_nest != NO_JOIN_NEST &&
+ in_subq->emb_on_expr_nest->effective_with_check)
+ {
+ in_subq->block_conversion_to_sj();
+ }
+ }
+
li.rewind();
/* First, convert child join's subqueries. We proceed bottom-up here */
while ((in_subq= li++))
@@ -1091,8 +1163,10 @@ bool convert_join_subqueries_to_semijoins(JOIN *join)
if (convert_join_subqueries_to_semijoins(child_join))
DBUG_RETURN(TRUE);
+
+
in_subq->sj_convert_priority=
- MY_TEST(in_subq->emb_on_expr_nest != NO_JOIN_NEST) * MAX_TABLES * 2 +
+ MY_TEST(in_subq->do_not_convert_to_sj) * MAX_TABLES * 2 +
in_subq->is_correlated * MAX_TABLES + child_join->outer_tables;
}
@@ -1125,7 +1199,7 @@ bool convert_join_subqueries_to_semijoins(JOIN *join)
bool remove_item= TRUE;
/* Stop processing if we've reached a subquery that's attached to the ON clause */
- if (in_subq->emb_on_expr_nest != NO_JOIN_NEST)
+ if (in_subq->do_not_convert_to_sj)
break;
if (in_subq->is_flattenable_semijoin)
diff --git a/sql/opt_sum.cc b/sql/opt_sum.cc
index e7d7c81b638..5d5132e7fee 100644
--- a/sql/opt_sum.cc
+++ b/sql/opt_sum.cc
@@ -254,6 +254,8 @@ int opt_sum_query(THD *thd,
int error= 0;
DBUG_ENTER("opt_sum_query");
+ thd->lex->current_select->min_max_opt_list.empty();
+
if (conds)
where_tables= conds->used_tables();
@@ -447,7 +449,14 @@ int opt_sum_query(THD *thd,
item_sum->aggregator_clear();
}
else
+ {
item_sum->reset_and_add();
+ /*
+ Save a reference to the item for possible rollback
+ of the min/max optimizations for this select
+ */
+ thd->lex->current_select->min_max_opt_list.push_back(item_sum);
+ }
item_sum->make_const();
recalc_const_item= 1;
break;
diff --git a/sql/rpl_mi.cc b/sql/rpl_mi.cc
index b03db07e443..c9dcf7b8fd7 100644
--- a/sql/rpl_mi.cc
+++ b/sql/rpl_mi.cc
@@ -664,7 +664,7 @@ file '%s')", fname);
mi->connect_retry= (uint) connect_retry;
mi->ssl= (my_bool) ssl;
mi->ssl_verify_server_cert= ssl_verify_server_cert;
- mi->heartbeat_period= master_heartbeat_period;
+ mi->heartbeat_period= MY_MIN(SLAVE_MAX_HEARTBEAT_PERIOD, master_heartbeat_period);
}
DBUG_PRINT("master_info",("log_file_name: %s position: %ld",
mi->master_log_name,
@@ -799,8 +799,8 @@ int flush_master_info(Master_info* mi,
contents of file). But because of number of lines in the first line
of file we don't care about this garbage.
*/
- char heartbeat_buf[sizeof(mi->heartbeat_period) * 4]; // buffer to suffice always
- sprintf(heartbeat_buf, "%.3f", mi->heartbeat_period);
+ char heartbeat_buf[FLOATING_POINT_BUFFER];
+ my_fcvt(mi->heartbeat_period, 3, heartbeat_buf, NULL);
my_b_seek(file, 0L);
my_b_printf(file,
"%u\n%s\n%s\n%s\n%s\n%s\n%d\n%d\n%d\n%s\n%s\n%s\n%s\n%s\n%d\n%s\n%s\n%s\n%s\n%d\n%s\n%s\n"
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 691adb4896c..b3a30c69a03 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -2095,6 +2095,7 @@ void st_select_lex::init_query()
leaf_tables_prep.empty();
leaf_tables.empty();
item_list.empty();
+ min_max_opt_list.empty();
join= 0;
having= prep_having= where= prep_where= 0;
olap= UNSPECIFIED_OLAP_TYPE;
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index 6f49ef145a2..240eb2373eb 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -751,6 +751,11 @@ public:
*/
List<Item_func_match> *ftfunc_list;
List<Item_func_match> ftfunc_list_alloc;
+ /*
+ The list of items to which MIN/MAX optimizations of opt_sum_query()
+ have been applied. Used to rollback those optimizations if it's needed.
+ */
+ List<Item_sum> min_max_opt_list;
JOIN *join; /* after JOIN::prepare it is pointer to corresponding JOIN */
List<TABLE_LIST> top_join_list; /* join list of the top level */
List<TABLE_LIST> *join_list; /* list for the currently parsed join */
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 0a282705e53..559473b8c19 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -9674,12 +9674,20 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
/*
Step #2: Extract WHERE/ON parts
*/
+ uint i;
+ for (i= join->top_join_tab_count - 1; i >= join->const_tables; i--)
+ {
+ if (!join->join_tab[i].bush_children)
+ break;
+ }
+ uint last_top_base_tab_idx= i;
+
table_map save_used_tables= 0;
used_tables=((select->const_tables=join->const_table_map) |
OUTER_REF_TABLE_BIT | RAND_TABLE_BIT);
JOIN_TAB *tab;
table_map current_map;
- uint i= join->const_tables;
+ i= join->const_tables;
for (tab= first_depth_first_tab(join); tab;
tab= next_depth_first_tab(join, tab), i++)
{
@@ -9717,7 +9725,7 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
Following force including random expression in last table condition.
It solve problem with select like SELECT * FROM t1 WHERE rand() > 0.5
*/
- if (tab == join->join_tab + join->top_join_tab_count - 1)
+ if (tab == join->join_tab + last_top_base_tab_idx)
current_map|= RAND_TABLE_BIT;
used_tables|=current_map;
@@ -9757,10 +9765,10 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
save_used_tables= 0;
}
else
- {
- tmp= make_cond_for_table(thd, cond, used_tables, current_map, i,
+ {
+ tmp= make_cond_for_table(thd, cond, used_tables, current_map, i,
FALSE, FALSE);
- }
+ }
/* Add conditions added by add_not_null_conds(). */
if (tab->select_cond)
add_cond_and_fix(thd, &tmp, tab->select_cond);
diff --git a/storage/connect/CMakeLists.txt b/storage/connect/CMakeLists.txt
index 840ccdfb0a8..81441892215 100644
--- a/storage/connect/CMakeLists.txt
+++ b/storage/connect/CMakeLists.txt
@@ -18,10 +18,10 @@ SET(CONNECT_PLUGIN_DYNAMIC "connect")
SET(CONNECT_SOURCES
ha_connect.cc connect.cc user_connect.cc mycat.cc
-fmdlex.c osutil.c plugutil.c rcmsg.c rcmsg.h
+fmdlex.c osutil.c rcmsg.c rcmsg.h
array.cpp blkfil.cpp colblk.cpp csort.cpp
-filamap.cpp filamdbf.cpp filamfix.cpp filamgz.cpp filamtxt.cpp
-filter.cpp json.cpp jsonudf.cpp maputil.cpp myconn.cpp myutil.cpp plgdbutl.cpp
+filamap.cpp filamdbf.cpp filamfix.cpp filamgz.cpp filamtxt.cpp filter.cpp
+json.cpp jsonudf.cpp maputil.cpp myconn.cpp myutil.cpp plgdbutl.cpp plugutil.cpp
reldef.cpp tabcol.cpp tabdos.cpp tabext.cpp tabfix.cpp tabfmt.cpp tabjson.cpp
table.cpp tabmul.cpp tabmysql.cpp taboccur.cpp tabpivot.cpp tabsys.cpp tabtbl.cpp
tabutil.cpp tabvir.cpp tabxcl.cpp valblk.cpp value.cpp xindex.cpp xobject.cpp
@@ -38,7 +38,7 @@ user_connect.h valblk.h value.h xindex.h xobject.h xtable.h)
# Definitions that are shared for all OSes
#
add_definitions( -DMARIADB -DFORCE_INIT_OF_VARS -Dconnect_EXPORTS)
-add_definitions( -DHUGE_SUPPORT -DGZ_SUPPORT -DPIVOT_SUPPORT )
+add_definitions( -DHUGE_SUPPORT -DGZ_SUPPORT -DPIVOT_SUPPORT -DUSE_TRY )
#
diff --git a/storage/connect/array.cpp b/storage/connect/array.cpp
index 88ab85d20eb..5cf15c5ac18 100644
--- a/storage/connect/array.cpp
+++ b/storage/connect/array.cpp
@@ -519,8 +519,8 @@ bool ARRAY::FilTest(PGLOBAL g, PVAL valp, OPVAL opc, int opm)
vp = valp;
} else if (opc != OP_EXIST) {
- sprintf(g->Message, MSG(MISSING_ARG), opc);
- longjmp(g->jumper[g->jump_level], TYPE_ARRAY);
+ sprintf(g->Message, MSG(MISSING_ARG), opc);
+ throw TYPE_ARRAY;
} else // OP_EXIST
return Nval > 0;
@@ -683,15 +683,15 @@ void ARRAY::SetPrecision(PGLOBAL g, int p)
{
if (Vblp == NULL) {
strcpy(g->Message, MSG(PREC_VBLP_NULL));
- longjmp(g->jumper[g->jump_level], TYPE_ARRAY);
+ throw TYPE_ARRAY;
} // endif Vblp
bool was = Vblp->IsCi();
if (was && !p) {
strcpy(g->Message, MSG(BAD_SET_CASE));
- longjmp(g->jumper[g->jump_level], TYPE_ARRAY);
- } // endif Vblp
+ throw TYPE_ARRAY;
+ } // endif Vblp
if (was || !p)
return;
@@ -701,7 +701,7 @@ void ARRAY::SetPrecision(PGLOBAL g, int p)
if (!was && Type == TYPE_STRING)
// Must be resorted to eliminate duplicate strings
if (Sort(g))
- longjmp(g->jumper[g->jump_level], TYPE_ARRAY);
+ throw TYPE_ARRAY;
} // end of SetPrecision
@@ -979,7 +979,7 @@ PSZ ARRAY::MakeArrayList(PGLOBAL g)
size_t z, len = 2;
if (Type == TYPE_LIST)
- return "(?" "?" "?)"; // To be implemented
+ return (PSZ)("(?" "?" "?)"); // To be implemented
z = MY_MAX(24, GetTypeSize(Type, Len) + 4);
tp = (char*)PlugSubAlloc(g, NULL, z);
diff --git a/storage/connect/blkfil.cpp b/storage/connect/blkfil.cpp
index 1f5a1a27ae5..e438e185e5d 100644
--- a/storage/connect/blkfil.cpp
+++ b/storage/connect/blkfil.cpp
@@ -1,11 +1,11 @@
/************* BlkFil C++ Program Source Code File (.CPP) **************/
/* PROGRAM NAME: BLKFIL */
/* ------------- */
-/* Version 2.5 */
+/* Version 2.6 */
/* */
/* COPYRIGHT: */
/* ---------- */
-/* (C) Copyright to the author Olivier BERTRAND 2004-2015 */
+/* (C) Copyright to the author Olivier BERTRAND 2004-2017 */
/* */
/* WHAT THIS PROGRAM DOES: */
/* ----------------------- */
@@ -595,8 +595,8 @@ BLKFILIN::BLKFILIN(PGLOBAL g, PTDBDOS tdbp, int op, int opm, PXOB *xp)
if (Colp->GetResultType() != Type) {
sprintf(g->Message, "BLKFILIN: %s", MSG(VALTYPE_NOMATCH));
- longjmp(g->jumper[g->jump_level], 99);
- } else if (Colp->GetValue()->IsCi())
+ throw g->Message;
+ } else if (Colp->GetValue()->IsCi())
Arap->SetPrecision(g, 1); // Case insensitive
Sorted = Colp->IsSorted() > 0;
diff --git a/storage/connect/catalog.h b/storage/connect/catalog.h
index 70304c410cc..48347d7519e 100644
--- a/storage/connect/catalog.h
+++ b/storage/connect/catalog.h
@@ -36,7 +36,7 @@ typedef struct _curtab {
/* Defines the structure used to get column catalog info. */
/***********************************************************************/
typedef struct _colinfo {
- char *Name;
+ PCSZ Name;
int Type;
int Offset;
int Length;
@@ -45,9 +45,9 @@ typedef struct _colinfo {
int Scale;
int Opt;
int Freq;
- char *Remark;
- char *Datefmt;
- char *Fieldfmt;
+ PCSZ Remark;
+ PCSZ Datefmt;
+ PCSZ Fieldfmt;
ushort Flags; // Used by MariaDB CONNECT handlers
} COLINFO, *PCOLINFO;
@@ -68,11 +68,9 @@ class DllExport CATALOG {
bool GetDefHuge(void) {return DefHuge;}
void SetDefHuge(bool b) {DefHuge = b;}
char *GetCbuf(void) {return Cbuf;}
-//char *GetDataPath(void) {return (char*)DataPath;}
// Methods
virtual void Reset(void) {}
-//virtual void SetDataPath(PGLOBAL g, const char *path) {}
virtual bool CheckName(PGLOBAL, char*) {return true;}
virtual bool ClearName(PGLOBAL, PSZ) {return true;}
virtual PRELDEF MakeOneTableDesc(PGLOBAL, LPCSTR, LPCSTR) {return NULL;}
@@ -102,7 +100,6 @@ class DllExport CATALOG {
int Cblen; /* Length of suballoc. buffer */
CURTAB Ctb; /* Used to enumerate tables */
bool DefHuge; /* true: tables default to huge */
-//LPCSTR DataPath; /* Is the Path of DB data dir */
}; // end of class CATALOG
#endif // __CATALOG__H
diff --git a/storage/connect/colblk.cpp b/storage/connect/colblk.cpp
index 58841387249..fa205b493a2 100644
--- a/storage/connect/colblk.cpp
+++ b/storage/connect/colblk.cpp
@@ -195,10 +195,10 @@ int COLBLK::GetLengthEx(void)
/* corresponding to this column and convert it to buffer type. */
/***********************************************************************/
void COLBLK::ReadColumn(PGLOBAL g)
- {
+{
sprintf(g->Message, MSG(UNDEFINED_AM), "ReadColumn");
- longjmp(g->jumper[g->jump_level], TYPE_COLBLK);
- } // end of ReadColumn
+ throw TYPE_COLBLK;
+} // end of ReadColumn
/***********************************************************************/
/* WriteColumn: what this routine does is to access the last line */
@@ -206,10 +206,10 @@ void COLBLK::ReadColumn(PGLOBAL g)
/* corresponding to this column from the column buffer and type. */
/***********************************************************************/
void COLBLK::WriteColumn(PGLOBAL g)
- {
+{
sprintf(g->Message, MSG(UNDEFINED_AM), "WriteColumn");
- longjmp(g->jumper[g->jump_level], TYPE_COLBLK);
- } // end of WriteColumn
+ throw TYPE_COLBLK;
+} // end of WriteColumn
/***********************************************************************/
/* Make file output of a column descriptor block. */
@@ -260,10 +260,10 @@ SPCBLK::SPCBLK(PCOLUMN cp)
/* corresponding to this column from the column buffer and type. */
/***********************************************************************/
void SPCBLK::WriteColumn(PGLOBAL g)
- {
+{
sprintf(g->Message, MSG(SPCOL_READONLY), Name);
- longjmp(g->jumper[g->jump_level], TYPE_COLBLK);
- } // end of WriteColumn
+ throw TYPE_COLBLK;
+} // end of WriteColumn
/***********************************************************************/
/* RIDBLK constructor for the ROWID special column. */
@@ -377,7 +377,7 @@ PRTBLK::PRTBLK(PCOLUMN cp) : SPCBLK(cp)
void PRTBLK::ReadColumn(PGLOBAL g)
{
if (Pname == NULL) {
- char *p;
+ const char *p;
Pname = To_Tdb->GetDef()->GetStringCatInfo(g, "partname", "?");
p = strrchr(Pname, '#');
@@ -407,7 +407,7 @@ SIDBLK::SIDBLK(PCOLUMN cp) : SPCBLK(cp)
void SIDBLK::ReadColumn(PGLOBAL)
{
//if (Sname == NULL) {
- Sname = (char*)To_Tdb->GetServer();
+ Sname = To_Tdb->GetServer();
Value->SetValue_psz(Sname);
// } // endif Sname
diff --git a/storage/connect/colblk.h b/storage/connect/colblk.h
index c64f9d95129..02c4f2361b7 100644
--- a/storage/connect/colblk.h
+++ b/storage/connect/colblk.h
@@ -154,7 +154,7 @@ class DllExport FIDBLK : public SPCBLK {
virtual void ReadColumn(PGLOBAL g);
protected:
- PSZ Fn; // The current To_File of the table
+ PCSZ Fn; // The current To_File of the table
OPVAL Op; // The file part operator
}; // end of class FIDBLK
@@ -178,7 +178,7 @@ class DllExport TIDBLK : public SPCBLK {
TIDBLK(void) {}
// Members
- PSZ Tname; // The current table name
+ PCSZ Tname; // The current table name
}; // end of class TIDBLK
/***********************************************************************/
@@ -201,7 +201,7 @@ class DllExport PRTBLK : public SPCBLK {
PRTBLK(void) {}
// Members
- PSZ Pname; // The current partition name
+ PCSZ Pname; // The current partition name
}; // end of class PRTBLK
/***********************************************************************/
@@ -224,7 +224,7 @@ class DllExport SIDBLK : public SPCBLK {
SIDBLK(void) {}
// Members
- PSZ Sname; // The current server name
+ PCSZ Sname; // The current server name
}; // end of class SIDBLK
#endif // __COLBLK__H
diff --git a/storage/connect/connect.cc b/storage/connect/connect.cc
index 098119e7be1..e15cc724b85 100644
--- a/storage/connect/connect.cc
+++ b/storage/connect/connect.cc
@@ -1,4 +1,4 @@
-/* Copyright (C) Olivier Bertrand 2004 - 2015
+/* Copyright (C) Olivier Bertrand 2004 - 2017
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
@@ -15,10 +15,10 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */
/***********************************************************************/
-/* Author Olivier BERTRAND bertrandop@gmail.com 2004-2015 */
+/* Author Olivier BERTRAND bertrandop@gmail.com 2004-2017 */
/* */
-/* WHAT THIS PROGRAM DOES: */
-/* ----------------------- */
+/* WHAT THIS PROGRAM DOES: */
+/* ----------------------- */
/* This program are the CONNECT general purpose semantic routines. */
/***********************************************************************/
#ifdef USE_PRAGMA_IMPLEMENTATION
@@ -117,11 +117,10 @@ bool CntCheckDB(PGLOBAL g, PHC handler, const char *pathname)
handler);
// Set the database path for this table
- handler->SetDataPath(g, pathname);
+ if (handler->SetDataPath(g, pathname))
+ return true;
if (dbuserp->Catalog) {
-// ((MYCAT *)dbuserp->Catalog)->SetHandler(handler); done later
-// ((MYCAT *)dbuserp->Catalog)->SetDataPath(g, pathname);
return false; // Nothing else to do
} // endif Catalog
@@ -138,9 +137,6 @@ bool CntCheckDB(PGLOBAL g, PHC handler, const char *pathname)
if (!(dbuserp->Catalog= new MYCAT(handler)))
return true;
-//((MYCAT *)dbuserp->Catalog)->SetDataPath(g, pathname);
-//dbuserp->UseTemp= TMP_AUTO;
-
/*********************************************************************/
/* All is correct. */
/*********************************************************************/
@@ -172,7 +168,7 @@ bool CntInfo(PGLOBAL g, PTDB tp, PXF info)
// info->mean_rec_length= tdbp->GetLrecl();
info->mean_rec_length= 0;
- info->data_file_name= (b) ? NULL : tdbp->GetFile(g);
+ info->data_file_name= (b) ? NULL : (char*)tdbp->GetFile(g);
return true;
} else {
info->data_file_length= 0;
@@ -188,49 +184,43 @@ bool CntInfo(PGLOBAL g, PTDB tp, PXF info)
/* GetTDB: Get the table description block of a CONNECT table. */
/***********************************************************************/
PTDB CntGetTDB(PGLOBAL g, LPCSTR name, MODE mode, PHC h)
- {
- int rc;
- PTDB tdbp;
- PTABLE tabp;
- PDBUSER dup= PlgGetUser(g);
- volatile PCATLG cat= (dup) ? dup->Catalog : NULL; // Safe over longjmp
-
- if (trace)
- printf("CntGetTDB: name=%s mode=%d cat=%p\n", name, mode, cat);
+{
+ PTDB tdbp;
+ PTABLE tabp;
+ PDBUSER dup = PlgGetUser(g);
+ volatile PCATLG cat = (dup) ? dup->Catalog : NULL; // Safe over longjmp
- if (!cat)
- return NULL;
+ if (trace)
+ printf("CntGetTDB: name=%s mode=%d cat=%p\n", name, mode, cat);
- // Save stack and allocation environment and prepare error return
- if (g->jump_level == MAX_JUMP) {
- strcpy(g->Message, MSG(TOO_MANY_JUMPS));
- return NULL;
- } // endif jump_level
+ if (!cat)
+ return NULL;
- if ((rc= setjmp(g->jumper[++g->jump_level])) != 0) {
- tdbp= NULL;
- goto err;
- } // endif rc
+ try {
+ // Get table object from the catalog
+ tabp = new(g) XTAB(name);
- // Get table object from the catalog
- tabp= new(g) XTAB(name);
+ if (trace)
+ printf("CntGetTDB: tabp=%p\n", tabp);
- if (trace)
- printf("CntGetTDB: tabp=%p\n", tabp);
+ // Perhaps this should be made thread safe
+ ((MYCAT*)cat)->SetHandler(h);
- // Perhaps this should be made thread safe
- ((MYCAT*)cat)->SetHandler(h);
+ if (!(tdbp = cat->GetTable(g, tabp, mode)))
+ printf("CntGetTDB: %s\n", g->Message);
- if (!(tdbp= cat->GetTable(g, tabp, mode)))
- printf("CntGetTDB: %s\n", g->Message);
+ } catch (int n) {
+ if (trace)
+ htrc("Exception %d: %s\n", n, g->Message);
+ } catch (const char *msg) {
+ strcpy(g->Message, msg);
+ } // end catch
- err:
if (trace)
printf("Returning tdbp=%p mode=%d\n", tdbp, mode);
- g->jump_level--;
return tdbp;
- } // end of CntGetTDB
+} // end of CntGetTDB
/***********************************************************************/
/* OPENTAB: Open a Table. */
@@ -239,7 +229,7 @@ bool CntOpenTable(PGLOBAL g, PTDB tdbp, MODE mode, char *c1, char *c2,
bool del, PHC)
{
char *p;
- int i, n, rc;
+ int i, n;
bool rcop= true;
PCOL colp;
//PCOLUMN cp;
@@ -254,120 +244,116 @@ bool CntOpenTable(PGLOBAL g, PTDB tdbp, MODE mode, char *c1, char *c2,
return true;
} // endif tdbp
- // Save stack and allocation environment and prepare error return
- if (g->jump_level == MAX_JUMP) {
- strcpy(g->Message, MSG(TOO_MANY_JUMPS));
- return true;
- } // endif jump_level
-
- if ((rc= setjmp(g->jumper[++g->jump_level])) != 0) {
- goto err;
- } // endif rc
-
- if (!c1) {
- if (mode == MODE_INSERT)
- // Allocate all column blocks for that table
- tdbp->ColDB(g, NULL, 0);
-
- } else for (p= c1; *p; p+= n) {
- // Allocate only used column blocks
- if (trace)
- printf("Allocating column %s\n", p);
-
- g->Message[0] = 0; // To check whether ColDB made an error message
- colp= tdbp->ColDB(g, p, 0);
-
- if (!colp && !(mode == MODE_INSERT && tdbp->IsSpecial(p))) {
- if (g->Message[0] == 0)
- sprintf(g->Message, MSG(COL_ISNOT_TABLE), p, tdbp->GetName());
-
- goto err;
- } // endif colp
-
- n= strlen(p) + 1;
- } // endfor p
-
- for (i= 0, colp= tdbp->GetColumns(); colp; i++, colp= colp->GetNext()) {
- if (colp->InitValue(g))
- goto err;
-
- if (mode == MODE_INSERT)
- // Allow type conversion
- if (colp->SetBuffer(g, colp->GetValue(), true, false))
- goto err;
-
- colp->AddColUse(U_P); // For PLG tables
- } // endfor colp
-
- /*********************************************************************/
- /* In Update mode, the updated column blocks must be distinct from */
- /* the read column blocks. So make a copy of the TDB and allocate */
- /* its column blocks in mode write (required by XML tables). */
- /*********************************************************************/
- if (mode == MODE_UPDATE) {
- PTDBASE utp;
-
- if (!(utp= (PTDBASE)tdbp->Duplicate(g))) {
- sprintf(g->Message, MSG(INV_UPDT_TABLE), tdbp->GetName());
- goto err;
- } // endif tp
-
- if (!c2)
- // Allocate all column blocks for that table
- utp->ColDB(g, NULL, 0);
- else for (p= c2; *p; p+= n) {
- // Allocate only used column blocks
- colp= utp->ColDB(g, p, 0);
- n= strlen(p) + 1;
- } // endfor p
-
- for (i= 0, colp= utp->GetColumns(); colp; i++, colp= colp->GetNext()) {
- if (colp->InitValue(g))
- goto err;
-
- if (colp->SetBuffer(g, colp->GetValue(), true, false))
- goto err;
-
- } // endfor colp
-
- // Attach the updated columns list to the main table
- tdbp->SetSetCols(utp->GetColumns());
- } else if (tdbp && mode == MODE_INSERT)
- tdbp->SetSetCols(tdbp->GetColumns());
-
- // Now do open the physical table
- if (trace)
- printf("Opening table %s in mode %d tdbp=%p\n",
- tdbp->GetName(), mode, tdbp);
-
-//tdbp->SetMode(mode);
-
- if (del/* && (tdbp->GetFtype() != RECFM_NAF*/) {
- // To avoid erasing the table when doing a partial delete
- // make a fake Next
+ try {
+ if (!c1) {
+ if (mode == MODE_INSERT)
+ // Allocate all column blocks for that table
+ tdbp->ColDB(g, NULL, 0);
+
+ } else for (p = c1; *p; p += n) {
+ // Allocate only used column blocks
+ if (trace)
+ printf("Allocating column %s\n", p);
+
+ g->Message[0] = 0; // To check whether ColDB made an error message
+ colp = tdbp->ColDB(g, p, 0);
+
+ if (!colp && !(mode == MODE_INSERT && tdbp->IsSpecial(p))) {
+ if (g->Message[0] == 0)
+ sprintf(g->Message, MSG(COL_ISNOT_TABLE), p, tdbp->GetName());
+
+ throw 1;
+ } // endif colp
+
+ n = strlen(p) + 1;
+ } // endfor p
+
+ for (i = 0, colp = tdbp->GetColumns(); colp; i++, colp = colp->GetNext()) {
+ if (colp->InitValue(g))
+ throw 2;
+
+ if (mode == MODE_INSERT)
+ // Allow type conversion
+ if (colp->SetBuffer(g, colp->GetValue(), true, false))
+ throw 3;
+
+ colp->AddColUse(U_P); // For PLG tables
+ } // endfor colp
+
+ /*******************************************************************/
+ /* In Update mode, the updated column blocks must be distinct from */
+ /* the read column blocks. So make a copy of the TDB and allocate */
+ /* its column blocks in mode write (required by XML tables). */
+ /*******************************************************************/
+ if (mode == MODE_UPDATE) {
+ PTDBASE utp;
+
+ if (!(utp = (PTDBASE)tdbp->Duplicate(g))) {
+ sprintf(g->Message, MSG(INV_UPDT_TABLE), tdbp->GetName());
+ throw 4;
+ } // endif tp
+
+ if (!c2)
+ // Allocate all column blocks for that table
+ utp->ColDB(g, NULL, 0);
+ else for (p = c2; *p; p += n) {
+ // Allocate only used column blocks
+ colp = utp->ColDB(g, p, 0);
+ n = strlen(p) + 1;
+ } // endfor p
+
+ for (i = 0, colp = utp->GetColumns(); colp; i++, colp = colp->GetNext()) {
+ if (colp->InitValue(g))
+ throw 5;
+
+ if (colp->SetBuffer(g, colp->GetValue(), true, false))
+ throw 6;
+
+ } // endfor colp
+
+ // Attach the updated columns list to the main table
+ tdbp->SetSetCols(utp->GetColumns());
+ } else if (tdbp && mode == MODE_INSERT)
+ tdbp->SetSetCols(tdbp->GetColumns());
+
+ // Now do open the physical table
+ if (trace)
+ printf("Opening table %s in mode %d tdbp=%p\n",
+ tdbp->GetName(), mode, tdbp);
+
+ //tdbp->SetMode(mode);
+
+ if (del/* && (tdbp->GetFtype() != RECFM_NAF*/) {
+ // To avoid erasing the table when doing a partial delete
+ // make a fake Next
// PDOSDEF ddp= new(g) DOSDEF;
// PTDB tp= new(g) TDBDOS(ddp, NULL);
- tdbp->SetNext((PTDB)1);
- dup->Check &= ~CHK_DELETE;
- } // endif del
+ tdbp->SetNext((PTDB)1);
+ dup->Check &= ~CHK_DELETE;
+ } // endif del
- if (trace)
- printf("About to open the table: tdbp=%p\n", tdbp);
+ if (trace)
+ printf("About to open the table: tdbp=%p\n", tdbp);
- if (mode != MODE_ANY && mode != MODE_ALTER) {
- if (tdbp->OpenDB(g)) {
- printf("%s\n", g->Message);
- goto err;
- } else
- tdbp->SetNext(NULL);
+ if (mode != MODE_ANY && mode != MODE_ALTER) {
+ if (tdbp->OpenDB(g)) {
+ printf("%s\n", g->Message);
+ throw 7;
+ } else
+ tdbp->SetNext(NULL);
+
+ } // endif mode
- } // endif mode
+ rcop = false;
- rcop= false;
+ } catch (int n) {
+ if (trace)
+ htrc("Exception %d: %s\n", n, g->Message);
+ } catch (const char *msg) {
+ strcpy(g->Message, msg);
+ } // end catch
- err:
- g->jump_level--;
return rcop;
} // end of CntOpenTable
@@ -387,50 +373,40 @@ bool CntRewindTable(PGLOBAL g, PTDB tdbp)
/* Evaluate all columns after a record is read. */
/***********************************************************************/
RCODE EvalColumns(PGLOBAL g, PTDB tdbp, bool reset, bool mrr)
- {
+{
RCODE rc= RC_OK;
PCOL colp;
- // Save stack and allocation environment and prepare error return
- if (g->jump_level == MAX_JUMP) {
- if (trace) {
- strcpy(g->Message, MSG(TOO_MANY_JUMPS));
- printf("EvalColumns: %s\n", g->Message);
- } // endif
-
- return RC_FX;
- } // endif jump_level
-
- if (setjmp(g->jumper[++g->jump_level]) != 0) {
- if (trace)
- printf("Error reading columns: %s\n", g->Message);
+ try {
+ for (colp = tdbp->GetColumns(); rc == RC_OK && colp;
+ colp = colp->GetNext()) {
+ if (reset)
+ colp->Reset();
- rc= RC_FX;
- goto err;
- } // endif rc
+ // Virtual columns are computed by MariaDB
+ if (!colp->GetColUse(U_VIRTUAL) && (!mrr || colp->GetKcol()))
+ if (colp->Eval(g))
+ rc = RC_FX;
- for (colp= tdbp->GetColumns(); rc == RC_OK && colp;
- colp= colp->GetNext()) {
- if (reset)
- colp->Reset();
+ } // endfor colp
- // Virtual columns are computed by MariaDB
- if (!colp->GetColUse(U_VIRTUAL) && (!mrr || colp->GetKcol()))
- if (colp->Eval(g))
- rc= RC_FX;
+ } catch (int n) {
+ if (trace)
+ printf("Error %d reading columns: %s\n", n, g->Message);
- } // endfor colp
+ rc = RC_FX;
+ } catch (const char *msg) {
+ strcpy(g->Message, msg);
+ } // end catch
- err:
- g->jump_level--;
return rc;
- } // end of EvalColumns
+} // end of EvalColumns
/***********************************************************************/
/* ReadNext: Read next record sequentially. */
/***********************************************************************/
RCODE CntReadNext(PGLOBAL g, PTDB tdbp)
- {
+{
RCODE rc;
if (!tdbp)
@@ -445,76 +421,66 @@ RCODE CntReadNext(PGLOBAL g, PTDB tdbp)
((PTDBASE)tdbp)->ResetKindex(g, NULL);
} // endif index
- // Save stack and allocation environment and prepare error return
- if (g->jump_level == MAX_JUMP) {
- strcpy(g->Message, MSG(TOO_MANY_JUMPS));
- return RC_FX;
- } // endif jump_level
-
- if ((setjmp(g->jumper[++g->jump_level])) != 0) {
- rc= RC_FX;
- goto err;
- } // endif rc
+ try {
+ // Do it now to avoid double eval when filtering
+ for (PCOL colp = tdbp->GetColumns(); colp; colp = colp->GetNext())
+ colp->Reset();
- // Do it now to avoid double eval when filtering
- for (PCOL colp= tdbp->GetColumns(); colp; colp= colp->GetNext())
- colp->Reset();
+ do {
+ if ((rc = (RCODE)tdbp->ReadDB(g)) == RC_OK)
+ if (!ApplyFilter(g, tdbp->GetFilter()))
+ rc = RC_NF;
- do {
- if ((rc= (RCODE)tdbp->ReadDB(g)) == RC_OK)
- if (!ApplyFilter(g, tdbp->GetFilter()))
- rc= RC_NF;
+ } while (rc == RC_NF);
- } while (rc == RC_NF);
+ if (rc == RC_OK)
+ rc = EvalColumns(g, tdbp, false);
- if (rc == RC_OK)
- rc= EvalColumns(g, tdbp, false);
+ } catch (int) {
+ rc = RC_FX;
+ } catch (const char *msg) {
+ strcpy(g->Message, msg);
+ rc = RC_FX;
+ } // end catch
- err:
- g->jump_level--;
return rc;
- } // end of CntReadNext
+} // end of CntReadNext
/***********************************************************************/
/* WriteRow: Insert a new row into a table. */
/***********************************************************************/
RCODE CntWriteRow(PGLOBAL g, PTDB tdbp)
- {
- RCODE rc;
- PCOL colp;
-//PTDBASE tp= (PTDBASE)tdbp;
-
- if (!tdbp)
- return RC_FX;
-
- // Save stack and allocation environment and prepare error return
- if (g->jump_level == MAX_JUMP) {
- strcpy(g->Message, MSG(TOO_MANY_JUMPS));
- return RC_FX;
- } // endif jump_level
-
- if (setjmp(g->jumper[++g->jump_level]) != 0) {
- printf("%s\n", g->Message);
- rc= RC_FX;
- goto err;
- } // endif rc
-
- // Store column values in table write buffer(s)
- for (colp= tdbp->GetSetCols(); colp; colp= colp->GetNext())
- if (!colp->GetColUse(U_VIRTUAL))
- colp->WriteColumn(g);
-
- if (tdbp->IsIndexed())
- // Index values must be sorted before updating
- rc= (RCODE)((PTDBDOS)tdbp)->GetTxfp()->StoreValues(g, true);
- else
- // Return result code from write operation
- rc= (RCODE)tdbp->WriteDB(g);
-
- err:
- g->jump_level--;
- return rc;
- } // end of CntWriteRow
+{
+ RCODE rc;
+ PCOL colp;
+ //PTDBASE tp= (PTDBASE)tdbp;
+
+ if (!tdbp)
+ return RC_FX;
+
+ try {
+ // Store column values in table write buffer(s)
+ for (colp = tdbp->GetSetCols(); colp; colp = colp->GetNext())
+ if (!colp->GetColUse(U_VIRTUAL))
+ colp->WriteColumn(g);
+
+ if (tdbp->IsIndexed())
+ // Index values must be sorted before updating
+ rc = (RCODE)((PTDBDOS)tdbp)->GetTxfp()->StoreValues(g, true);
+ else
+ // Return result code from write operation
+ rc = (RCODE)tdbp->WriteDB(g);
+
+ } catch (int n) {
+ printf("Exception %d: %s\n", n, g->Message);
+ rc = RC_FX;
+ } catch (const char *msg) {
+ strcpy(g->Message, msg);
+ rc = RC_FX;
+ } // end catch
+
+ return rc;
+} // end of CntWriteRow
/***********************************************************************/
/* UpdateRow: Update a row into a table. */
@@ -562,88 +528,78 @@ RCODE CntDeleteRow(PGLOBAL g, PTDB tdbp, bool all)
/* CLOSETAB: Close a table. */
/***********************************************************************/
int CntCloseTable(PGLOBAL g, PTDB tdbp, bool nox, bool abort)
- {
- int rc= RC_OK;
-//TDBASE *tbxp= (PTDBASE)tdbp;
-
- if (!tdbp)
- return rc; // Nothing to do
- else if (tdbp->GetUse() != USE_OPEN) {
- if (tdbp->GetAmType() == TYPE_AM_XML)
- tdbp->CloseDB(g); // Opened by GetMaxSize
-
- return rc;
- } // endif !USE_OPEN
-
- if (trace)
- printf("CntCloseTable: tdbp=%p mode=%d nox=%d abort=%d\n",
- tdbp, tdbp->GetMode(), nox, abort);
-
- if (tdbp->GetMode() == MODE_DELETE && tdbp->GetUse() == USE_OPEN) {
- if (tdbp->IsIndexed())
- rc= ((PTDBDOS)tdbp)->GetTxfp()->DeleteSortedRows(g);
-
- if (!rc)
- rc= tdbp->DeleteDB(g, RC_EF); // Specific A.M. delete routine
-
- } else if (tdbp->GetMode() == MODE_UPDATE && tdbp->IsIndexed())
- rc= ((PTDBDOX)tdbp)->Txfp->UpdateSortedRows(g);
-
- switch(rc) {
- case RC_FX:
- abort= true;
- break;
- case RC_INFO:
- PushWarning(g, tdbp);
- break;
- } // endswitch rc
-
- // Prepare error return
- if (g->jump_level == MAX_JUMP) {
- strcpy(g->Message, MSG(TOO_MANY_JUMPS));
- rc= RC_FX;
- goto err;
- } // endif
-
- if ((rc = setjmp(g->jumper[++g->jump_level])) != 0) {
- rc= RC_FX;
- g->jump_level--;
- goto err;
- } // endif
-
- // This will close the table file(s) and also finalize write
- // operations such as Insert, Update, or Delete.
- tdbp->SetAbort(abort);
- tdbp->CloseDB(g);
- tdbp->SetAbort(false);
- g->jump_level--;
-
- if (trace > 1)
- printf("Table %s closed\n", tdbp->GetName());
-
-//if (!((PTDBDOX)tdbp)->GetModified())
-// return 0;
-
- if (nox || tdbp->GetMode() == MODE_READ || tdbp->GetMode() == MODE_ANY)
- return 0;
-
- if (trace > 1)
- printf("About to reset opt\n");
-
- if (!tdbp->IsRemote()) {
- // Make all the eventual indexes
- PTDBDOX tbxp = (PTDBDOX)tdbp;
- tbxp->ResetKindex(g, NULL);
- tbxp->SetKey_Col(NULL);
- rc = tbxp->ResetTableOpt(g, true, tbxp->GetDef()->Indexable() == 1);
- } // endif remote
-
- err:
- if (trace > 1)
- printf("Done rc=%d\n", rc);
-
- return (rc == RC_OK || rc == RC_INFO) ? 0 : rc;
- } // end of CntCloseTable
+{
+ int rc = RC_OK;
+ //TDBASE *tbxp= (PTDBASE)tdbp;
+
+ if (!tdbp)
+ return rc; // Nothing to do
+ else if (tdbp->GetUse() != USE_OPEN) {
+ if (tdbp->GetAmType() == TYPE_AM_XML)
+ tdbp->CloseDB(g); // Opened by GetMaxSize
+
+ return rc;
+ } // endif !USE_OPEN
+
+ if (trace)
+ printf("CntCloseTable: tdbp=%p mode=%d nox=%d abort=%d\n",
+ tdbp, tdbp->GetMode(), nox, abort);
+
+ if (tdbp->GetMode() == MODE_DELETE && tdbp->GetUse() == USE_OPEN) {
+ if (tdbp->IsIndexed())
+ rc = ((PTDBDOS)tdbp)->GetTxfp()->DeleteSortedRows(g);
+
+ if (!rc)
+ rc = tdbp->DeleteDB(g, RC_EF); // Specific A.M. delete routine
+
+ } else if (tdbp->GetMode() == MODE_UPDATE && tdbp->IsIndexed())
+ rc = ((PTDBDOX)tdbp)->Txfp->UpdateSortedRows(g);
+
+ switch (rc) {
+ case RC_FX:
+ abort = true;
+ break;
+ case RC_INFO:
+ PushWarning(g, tdbp);
+ break;
+ } // endswitch rc
+
+ try {
+ // This will close the table file(s) and also finalize write
+ // operations such as Insert, Update, or Delete.
+ tdbp->SetAbort(abort);
+ tdbp->CloseDB(g);
+ tdbp->SetAbort(false);
+
+ if (trace > 1)
+ printf("Table %s closed\n", tdbp->GetName());
+
+ if (!nox && tdbp->GetMode() != MODE_READ && tdbp->GetMode() != MODE_ANY) {
+ if (trace > 1)
+ printf("About to reset opt\n");
+
+ if (!tdbp->IsRemote()) {
+ // Make all the eventual indexes
+ PTDBDOX tbxp = (PTDBDOX)tdbp;
+ tbxp->ResetKindex(g, NULL);
+ tbxp->SetKey_Col(NULL);
+ rc = tbxp->ResetTableOpt(g, true, tbxp->GetDef()->Indexable() == 1);
+ } // endif remote
+
+ } // endif nox
+
+ } catch (int) {
+ rc = RC_FX;
+ } catch (const char *msg) {
+ strcpy(g->Message, msg);
+ rc = RC_FX;
+ } // end catch
+
+ if (trace > 1)
+ htrc("Done rc=%d\n", rc);
+
+ return (rc == RC_OK || rc == RC_INFO) ? 0 : rc;
+} // end of CntCloseTable
/***********************************************************************/
/* Load and initialize the use of an index. */
@@ -752,8 +708,9 @@ RCODE CntIndexRead(PGLOBAL g, PTDB ptdb, OPVAL op,
sprintf(g->Message, MSG(TABLE_NO_INDEX), ptdb->GetName());
return RC_FX;
} else if (x == 2) {
- // Remote index
- if (op != OP_SAME && ptdb->ReadKey(g, op, kr))
+ // Remote index. Only used in read mode
+ if ((ptdb->GetMode() == MODE_READ || ptdb->GetMode() == MODE_READX)
+ && op != OP_SAME && ptdb->ReadKey(g, op, kr))
return RC_FX;
goto rnd;
diff --git a/storage/connect/domdoc.cpp b/storage/connect/domdoc.cpp
index 1622ec16c68..e24e10835c1 100644
--- a/storage/connect/domdoc.cpp
+++ b/storage/connect/domdoc.cpp
@@ -58,13 +58,15 @@ void CloseXMLFile(PGLOBAL g, PFBLOCK fp, bool all)
if (xp && xp->Count > 1 && !all) {
xp->Count--;
} else if (xp && xp->Count > 0) {
- try {
+ try {
if (xp->Docp)
xp->Docp->Release();
- } catch(_com_error e) {
- sprintf(g->Message, "%s %s", MSG(COM_ERROR), e.Description());
- } catch(...) {}
+ } catch(_com_error e) {
+ char *p = _com_util::ConvertBSTRToString(e.Description());
+ sprintf(g->Message, "%s %s", MSG(COM_ERROR), p);
+ delete[] p;
+ } catch(...) {}
CoUninitialize();
xp->Count = 0;
@@ -89,7 +91,7 @@ DOMDOC::DOMDOC(char *nsl, char *nsdf, char *enc, PFBLOCK fp)
/******************************************************************/
/* Initialize XML parser and check library compatibility. */
/******************************************************************/
-bool DOMDOC::Initialize(PGLOBAL g, char *entry, bool zipped)
+bool DOMDOC::Initialize(PGLOBAL g, PCSZ entry, bool zipped)
{
if (zipped && InitZip(g, entry))
return true;
@@ -155,7 +157,7 @@ PFBLOCK DOMDOC::LinkXblock(PGLOBAL g, MODE m, int rc, char *fn)
/******************************************************************/
/* Create the XML node. */
/******************************************************************/
-bool DOMDOC::NewDoc(PGLOBAL g, char *ver)
+bool DOMDOC::NewDoc(PGLOBAL g, PCSZ ver)
{
char buf[64];
MSXML2::IXMLDOMProcessingInstructionPtr pip;
@@ -490,9 +492,9 @@ PXATTR DOMNODE::GetAttribute(PGLOBAL g, char *name, PXATTR ap)
/******************************************************************/
/* Add a new element child node to this node and return it. */
/******************************************************************/
-PXNODE DOMNODE::AddChildNode(PGLOBAL g, char *name, PXNODE np)
+PXNODE DOMNODE::AddChildNode(PGLOBAL g, PCSZ name, PXNODE np)
{
- char *p, *pn;
+ const char *p, *pn;
// char *p, *pn, *epf, *pf = NULL;
MSXML2::IXMLDOMNodePtr ep;
// _bstr_t uri((wchar_t*)NULL);
@@ -585,7 +587,7 @@ PXATTR DOMNODE::AddProperty(PGLOBAL g, char *name, PXATTR ap)
/******************************************************************/
/* Add a new text node to this node. */
/******************************************************************/
-void DOMNODE::AddText(PGLOBAL g, char *txtp)
+void DOMNODE::AddText(PGLOBAL g, PCSZ txtp)
{
MSXML2::IXMLDOMTextPtr tp= Docp->createTextNode((_bstr_t)txtp);
diff --git a/storage/connect/domdoc.h b/storage/connect/domdoc.h
index 7f269002d59..dd8936097e2 100644
--- a/storage/connect/domdoc.h
+++ b/storage/connect/domdoc.h
@@ -37,9 +37,9 @@ class DOMDOC : public XMLDOCUMENT {
virtual void SetNofree(bool b) {} // Only libxml2
// Methods
- virtual bool Initialize(PGLOBAL g, char *entry, bool zipped);
+ virtual bool Initialize(PGLOBAL g, PCSZ entry, bool zipped);
virtual bool ParseFile(PGLOBAL g, char *fn);
- virtual bool NewDoc(PGLOBAL g, char *ver);
+ virtual bool NewDoc(PGLOBAL g, PCSZ ver);
virtual void AddComment(PGLOBAL g, char *com);
virtual PXNODE GetRoot(PGLOBAL g);
virtual PXNODE NewRoot(PGLOBAL g, char *name);
@@ -78,9 +78,9 @@ class DOMNODE : public XMLNODE {
virtual PXLIST SelectNodes(PGLOBAL g, char *xp, PXLIST lp);
virtual PXNODE SelectSingleNode(PGLOBAL g, char *xp, PXNODE np);
virtual PXATTR GetAttribute(PGLOBAL g, char *name, PXATTR ap);
- virtual PXNODE AddChildNode(PGLOBAL g, char *name, PXNODE np);
+ virtual PXNODE AddChildNode(PGLOBAL g, PCSZ name, PXNODE np);
virtual PXATTR AddProperty(PGLOBAL g, char *name, PXATTR ap);
- virtual void AddText(PGLOBAL g, char *txtp);
+ virtual void AddText(PGLOBAL g, PCSZ txtp);
virtual void DeleteChild(PGLOBAL g, PXNODE dnp);
protected:
diff --git a/storage/connect/filamap.cpp b/storage/connect/filamap.cpp
index 8fffaca3d06..84dff422db7 100644
--- a/storage/connect/filamap.cpp
+++ b/storage/connect/filamap.cpp
@@ -301,10 +301,9 @@ int MAPFAM::SkipRecord(PGLOBAL g, bool header)
PDBUSER dup = (PDBUSER)g->Activityp->Aptr;
// Skip this record
- while (*Mempos++ != '\n') ; // What about Unix ???
-
- if (Mempos >= Top)
- return RC_EF;
+ while (*Mempos++ != '\n') // What about Unix ???
+ if (Mempos == Top)
+ return RC_EF;
// Update progress information
dup->ProgCur = GetPos();
@@ -320,7 +319,7 @@ int MAPFAM::SkipRecord(PGLOBAL g, bool header)
/***********************************************************************/
int MAPFAM::ReadBuffer(PGLOBAL g)
{
- int rc, len;
+ int rc, len, n = 1;
// Are we at the end of the memory
if (Mempos >= Top) {
@@ -362,10 +361,14 @@ int MAPFAM::ReadBuffer(PGLOBAL g)
Placed = false;
// Immediately calculate next position (Used by DeleteDB)
- while (*Mempos++ != '\n') ; // What about Unix ???
+ while (*Mempos++ != '\n') // What about Unix ???
+ if (Mempos == Top) {
+ n = 0;
+ break;
+ } // endif Mempos
// Set caller line buffer
- len = (Mempos - Fpos) - 1;
+ len = (Mempos - Fpos) - n;
// Don't rely on ENDING setting
if (len > 0 && *(Mempos - 2) == '\r')
@@ -619,7 +622,9 @@ int MBKFAM::ReadBuffer(PGLOBAL g)
} // endif's
// Immediately calculate next position (Used by DeleteDB)
- while (*Mempos++ != '\n') ; // What about Unix ???
+ while (*Mempos++ != '\n') // What about Unix ???
+ if (Mempos == Top)
+ break;
// Set caller line buffer
len = (Mempos - Fpos) - Ending;
diff --git a/storage/connect/filamdbf.cpp b/storage/connect/filamdbf.cpp
index fec98a72544..44abd962c56 100644
--- a/storage/connect/filamdbf.cpp
+++ b/storage/connect/filamdbf.cpp
@@ -128,7 +128,7 @@ typedef struct _descriptor {
/* Moves file pointer to byte 32; fills buffer at buf with */
/* first 32 bytes of file. */
/****************************************************************************/
-static int dbfhead(PGLOBAL g, FILE *file, PSZ fn, DBFHEADER *buf)
+static int dbfhead(PGLOBAL g, FILE *file, PCSZ fn, DBFHEADER *buf)
{
char endmark[2];
int dbc = 2, rc = RC_OK;
@@ -186,7 +186,7 @@ static int dbfhead(PGLOBAL g, FILE *file, PSZ fn, DBFHEADER *buf)
/* DBFColumns: constructs the result blocks containing the description */
/* of all the columns of a DBF file that will be retrieved by #GetData. */
/****************************************************************************/
-PQRYRES DBFColumns(PGLOBAL g, char *dp, const char *fn, bool info)
+PQRYRES DBFColumns(PGLOBAL g, PCSZ dp, PCSZ fn, bool info)
{
int buftyp[] = {TYPE_STRING, TYPE_SHORT, TYPE_STRING,
TYPE_INT, TYPE_INT, TYPE_SHORT};
@@ -393,7 +393,7 @@ DBFBASE::DBFBASE(DBFBASE *txfp)
/* and header length. Set Records, check that Reclen is equal to lrecl and */
/* return the header length or 0 in case of error. */
/****************************************************************************/
-int DBFBASE::ScanHeader(PGLOBAL g, PSZ fn, int lrecl, int *rln, char *defpath)
+int DBFBASE::ScanHeader(PGLOBAL g, PCSZ fn, int lrecl, int *rln, PCSZ defpath)
{
int rc;
char filename[_MAX_PATH];
diff --git a/storage/connect/filamdbf.h b/storage/connect/filamdbf.h
index 66458a10eaa..640fc349b4c 100644
--- a/storage/connect/filamdbf.h
+++ b/storage/connect/filamdbf.h
@@ -19,7 +19,7 @@ typedef class DBMFAM *PDBMFAM;
/****************************************************************************/
/* Functions used externally. */
/****************************************************************************/
-PQRYRES DBFColumns(PGLOBAL g, char *dp, const char *fn, bool info);
+PQRYRES DBFColumns(PGLOBAL g, PCSZ dp, PCSZ fn, bool info);
/****************************************************************************/
/* This is the base class for dBASE file access methods. */
@@ -31,7 +31,7 @@ class DllExport DBFBASE {
DBFBASE(PDBF txfp);
// Implementation
- int ScanHeader(PGLOBAL g, PSZ fname, int lrecl, int *rlen, char *defpath);
+ int ScanHeader(PGLOBAL g, PCSZ fname, int lrecl, int *rlen, PCSZ defpath);
protected:
// Default constructor, not to be used
diff --git a/storage/connect/filamfix.cpp b/storage/connect/filamfix.cpp
index dcb677dc848..1d6194b154d 100644
--- a/storage/connect/filamfix.cpp
+++ b/storage/connect/filamfix.cpp
@@ -761,7 +761,8 @@ bool BGXFAM::BigWrite(PGLOBAL g, HANDLE h, void *inbuf, int req)
htrc("after write req=%d brc=%d nbw=%d\n", req, brc, nbw);
if (!brc || nbw != len) {
- char buf[256], *fn = (h == Hfile) ? To_File : "Tempfile";
+ char buf[256];
+ PCSZ fn = (h == Hfile) ? To_File : "Tempfile";
if (brc)
strcpy(buf, MSG(BAD_BYTE_NUM));
diff --git a/storage/connect/filamgz.cpp b/storage/connect/filamgz.cpp
index dc6f277ee27..df366ef15f9 100644
--- a/storage/connect/filamgz.cpp
+++ b/storage/connect/filamgz.cpp
@@ -920,8 +920,8 @@ int ZLBFAM::GetFileLength(PGLOBAL g)
/***********************************************************************/
bool ZLBFAM::AllocateBuffer(PGLOBAL g)
{
- char *msg;
- int n, zrc;
+ PCSZ msg;
+ int n, zrc;
#if 0
if (!Optimized && Tdbp->NeedIndexing(g)) {
diff --git a/storage/connect/filamtxt.cpp b/storage/connect/filamtxt.cpp
index 12c0a66ecad..c456ee9e9b7 100644
--- a/storage/connect/filamtxt.cpp
+++ b/storage/connect/filamtxt.cpp
@@ -1,11 +1,11 @@
/*********** File AM Txt C++ Program Source Code File (.CPP) ***********/
/* PROGRAM NAME: FILAMTXT */
/* ------------- */
-/* Version 1.6 */
+/* Version 1.7 */
/* */
/* COPYRIGHT: */
/* ---------- */
-/* (C) Copyright to the author Olivier BERTRAND 2005-2015 */
+/* (C) Copyright to the author Olivier BERTRAND 2005-2017 */
/* */
/* WHAT THIS PROGRAM DOES: */
/* ----------------------- */
@@ -71,8 +71,23 @@ TXTFAM::TXTFAM(PDOSDEF tdp)
{
Tdbp = NULL;
To_Fb = NULL;
- To_File = tdp->Fn;
- Lrecl = tdp->Lrecl;
+
+ if (tdp) {
+ To_File = tdp->Fn;
+ Lrecl = tdp->Lrecl;
+ Eof = tdp->Eof;
+ Ending = tdp->Ending;
+ } else {
+ To_File = NULL;
+ Lrecl = 0;
+ Eof = false;
+#if defined(__WIN__)
+ Ending = 2;
+#else
+ Ending = 1;
+#endif
+ } // endif tdp
+
Placed = false;
IsRead = true;
Blocked = false;
@@ -103,8 +118,6 @@ TXTFAM::TXTFAM(PDOSDEF tdp)
Blksize = 0;
Fpos = Spos = Tpos = 0;
Padded = false;
- Eof = tdp->Eof;
- Ending = tdp->Ending;
Abort = false;
CrLf = (char*)(Ending == 1 ? "\n" : "\r\n");
} // end of TXTFAM standard constructor
@@ -974,7 +987,7 @@ int DOSFAM::DeleteRecords(PGLOBAL g, int irc)
} else {
/*****************************************************************/
- /* Move of eventual preceding lines is not required here. */
+ /* Move of eventual preceding lines is not required here. */
/* Set the target file as being the source file itself. */
/* Set the future Tpos, and give Spos a value to block copying. */
/*****************************************************************/
@@ -1162,13 +1175,13 @@ int DOSFAM::RenameTempFile(PGLOBAL g)
if (rename(filename, filetemp)) { // Save file for security
sprintf(g->Message, MSG(RENAME_ERROR),
filename, filetemp, strerror(errno));
- longjmp(g->jumper[g->jump_level], 51);
- } else if (rename(tempname, filename)) {
+ throw 51;
+ } else if (rename(tempname, filename)) {
sprintf(g->Message, MSG(RENAME_ERROR),
tempname, filename, strerror(errno));
rc = rename(filetemp, filename); // Restore saved file
- longjmp(g->jumper[g->jump_level], 52);
- } else if (remove(filetemp)) {
+ throw 52;
+ } else if (remove(filetemp)) {
sprintf(g->Message, MSG(REMOVE_ERROR),
filetemp, strerror(errno));
rc = RC_INFO; // Acceptable
diff --git a/storage/connect/filamtxt.h b/storage/connect/filamtxt.h
index ae8f74a9830..1fdae8fcd37 100644
--- a/storage/connect/filamtxt.h
+++ b/storage/connect/filamtxt.h
@@ -80,7 +80,7 @@ class DllExport TXTFAM : public BLOCK {
protected:
// Members
PTDBDOS Tdbp; // To table class
- PSZ To_File; // Points to table file name
+ PCSZ To_File; // Points to table file name
PFBLOCK To_Fb; // Pointer to file block
PPARM To_Pos; // Pointer to position list
PPARM To_Sos; // Pointer to start position list
diff --git a/storage/connect/filamvct.cpp b/storage/connect/filamvct.cpp
index 71a8dd98c61..f8a7f2600f3 100755
--- a/storage/connect/filamvct.cpp
+++ b/storage/connect/filamvct.cpp
@@ -143,9 +143,9 @@ int VCTFAM::GetFileLength(PGLOBAL g)
{
if (Split) {
// Get the total file length
- char filename[_MAX_PATH];
- char *savfile = To_File;
- int i, len = 0;
+ char filename[_MAX_PATH];
+ PCSZ savfile = To_File;
+ int i, len = 0;
// Initialize the array of file structures
if (!Colfn) {
@@ -313,8 +313,8 @@ int VCTFAM::Cardinality(PGLOBAL g)
// and Last must be set from the file cardinality.
// Only happens when called by sub classes.
char filename[_MAX_PATH];
- PSZ savfn = To_File;
- int len, clen, card = -1;
+ PCSZ savfn = To_File;
+ int len, clen, card = -1;
PCOLDEF cdp = Tdbp->GetDef()->GetCols();
if (!Colfn) {
@@ -368,7 +368,7 @@ int VCTFAM::GetRowID(void)
/***********************************************************************/
/* VCT Create an empty file for Vector formatted tables. */
/***********************************************************************/
-bool VCTFAM::MakeEmptyFile(PGLOBAL g, char *fn)
+bool VCTFAM::MakeEmptyFile(PGLOBAL g, PCSZ fn)
{
// Vector formatted file: this will create an empty file of the
// required length if it does not exists yet.
@@ -560,7 +560,9 @@ bool VCTFAM::AllocateBuffer(PGLOBAL g)
/* Do initial action when inserting. */
/***********************************************************************/
bool VCTFAM::InitInsert(PGLOBAL g)
- {
+{
+ bool rc = false;
+
// We come here in MODE_INSERT only
if (Last == Nrec) {
CurBlk = Block;
@@ -574,27 +576,27 @@ bool VCTFAM::InitInsert(PGLOBAL g)
CurBlk = Block - 1;
CurNum = Last;
- // Prepare error return
- if (g->jump_level == MAX_JUMP) {
- strcpy(g->Message, MSG(TOO_MANY_JUMPS));
- return true;
- } // endif
+ try {
+ // Last block must be updated by new values
+ for (; cp; cp = (PVCTCOL)cp->Next)
+ cp->ReadBlock(g);
- if ((rc = setjmp(g->jumper[++g->jump_level])) != 0) {
- g->jump_level--;
- return true;
- } // endif
+ } catch (int n) {
+ if (trace)
+ htrc("Exception %d: %s\n", n, g->Message);
+ rc = true;
+ } catch (const char *msg) {
+ strcpy(g->Message, msg);
+ rc = true;
+ } // end catch
- // Last block must be updated by new values
- for (; cp; cp = (PVCTCOL)cp->Next)
- cp->ReadBlock(g);
-
- g->jump_level--;
} // endif Last
- // We are not currently using a temporary file for Insert
- T_Stream = Stream;
- return false;
+ if (!rc)
+ // We are not currently using a temporary file for Insert
+ T_Stream = Stream;
+
+ return rc;
} // end of InitInsert
/***********************************************************************/
@@ -879,8 +881,9 @@ int VCTFAM::DeleteRecords(PGLOBAL g, int irc)
/***********************************************************************/
bool VCTFAM::OpenTempFile(PGLOBAL g)
{
- char *opmode, tempname[_MAX_PATH];
- bool rc = false;
+ PCSZ opmode;
+ char tempname[_MAX_PATH];
+ bool rc = false;
/*********************************************************************/
/* Open the temporary file, Spos is at the beginning of file. */
@@ -1108,7 +1111,7 @@ void VCTFAM::CloseTableFile(PGLOBAL g, bool abort)
} else if (AddBlock) {
// Last block was not written
rc = ResetTableSize(g, CurBlk, Nrec);
- longjmp(g->jumper[g->jump_level], 44);
+ throw 44;
} // endif
} else if (mode == MODE_UPDATE) {
@@ -1528,8 +1531,8 @@ bool VCMFAM::AllocateBuffer(PGLOBAL g)
/* Do initial action when inserting. */
/***********************************************************************/
bool VCMFAM::InitInsert(PGLOBAL g)
- {
- int rc;
+{
+ bool rc = false;
volatile PVCTCOL cp = (PVCTCOL)Tdbp->GetColumns();
// We come here in MODE_INSERT only
@@ -1543,24 +1546,22 @@ bool VCMFAM::InitInsert(PGLOBAL g)
CurNum = Last;
} // endif Last
- // Prepare error return
- if (g->jump_level == MAX_JUMP) {
- strcpy(g->Message, MSG(TOO_MANY_JUMPS));
- return true;
- } // endif
-
- if ((rc = setjmp(g->jumper[++g->jump_level])) != 0) {
- g->jump_level--;
- return true;
- } // endif
+ try {
+ // Initialize the column block pointer
+ for (; cp; cp = (PVCTCOL)cp->Next)
+ cp->ReadBlock(g);
- // Initialize the column block pointer
- for (; cp; cp = (PVCTCOL)cp->Next)
- cp->ReadBlock(g);
+ } catch (int n) {
+ if (trace)
+ htrc("Exception %d: %s\n", n, g->Message);
+ rc = true;
+ } catch (const char *msg) {
+ strcpy(g->Message, msg);
+ rc = true;
+ } // end catch
- g->jump_level--;
- return false;
- } // end of InitInsert
+ return rc;
+} // end of InitInsert
/***********************************************************************/
/* Data Base write routine for VMP access method. */
@@ -2000,7 +2001,7 @@ bool VECFAM::OpenTableFile(PGLOBAL g)
/***********************************************************************/
/* Open the file corresponding to one column. */
/***********************************************************************/
-bool VECFAM::OpenColumnFile(PGLOBAL g, char *opmode, int i)
+bool VECFAM::OpenColumnFile(PGLOBAL g, PCSZ opmode, int i)
{
char filename[_MAX_PATH];
PDBUSER dup = PlgGetUser(g);
@@ -2505,7 +2506,7 @@ void VECFAM::CloseTableFile(PGLOBAL g, bool abort)
if (wrc != RC_FX)
rc = ResetTableSize(g, Block, Last);
else
- longjmp(g->jumper[g->jump_level], 44);
+ throw 44;
} else if (mode == MODE_UPDATE) {
if (UseTemp && !InitUpdate && !Abort) {
@@ -3145,7 +3146,8 @@ bool BGVFAM::BigWrite(PGLOBAL g, HANDLE h, void *inbuf, int req)
htrc("after write req=%d brc=%d nbw=%d\n", req, brc, nbw);
if (!brc || nbw != len) {
- char buf[256], *fn = (h == Hfile) ? To_File : "Tempfile";
+ char buf[256];
+ PCSZ fn = (h == Hfile) ? To_File : "Tempfile";
if (brc)
strcpy(buf, MSG(BAD_BYTE_NUM));
@@ -3321,7 +3323,7 @@ bool BGVFAM::SetBlockInfo(PGLOBAL g)
/***********************************************************************/
/* VEC Create an empty file for new Vector formatted tables. */
/***********************************************************************/
-bool BGVFAM::MakeEmptyFile(PGLOBAL g, char *fn)
+bool BGVFAM::MakeEmptyFile(PGLOBAL g, PCSZ fn)
{
// Vector formatted file this will create an empty file of the
// required length if it does not exists yet.
@@ -3331,7 +3333,7 @@ bool BGVFAM::MakeEmptyFile(PGLOBAL g, char *fn)
PlugSetPath(filename, fn, Tdbp->GetPath());
#if defined(__WIN__)
- char *p;
+ PCSZ p;
DWORD rc;
bool brc;
LARGE_INTEGER of;
@@ -4167,8 +4169,8 @@ void BGVFAM::CloseTableFile(PGLOBAL g, bool abort)
} else if (AddBlock) {
// Last block was not written
rc = ResetTableSize(g, CurBlk, Nrec);
- longjmp(g->jumper[g->jump_level], 44);
- } // endif
+ throw 44;
+ } // endif
} else if (mode == MODE_UPDATE) {
// Write back to file any pending modifications
diff --git a/storage/connect/filamvct.h b/storage/connect/filamvct.h
index be66232acfb..85982403270 100644
--- a/storage/connect/filamvct.h
+++ b/storage/connect/filamvct.h
@@ -61,7 +61,7 @@ class DllExport VCTFAM : public FIXFAM {
virtual bool WriteBlock(PGLOBAL g, PVCTCOL colp);
protected:
- virtual bool MakeEmptyFile(PGLOBAL g, char *fn);
+ virtual bool MakeEmptyFile(PGLOBAL g, PCSZ fn);
virtual bool OpenTempFile(PGLOBAL g);
virtual bool MoveLines(PGLOBAL g) {return false;}
virtual bool MoveIntermediateLines(PGLOBAL g, bool *b = NULL);
@@ -160,7 +160,7 @@ class DllExport VECFAM : public VCTFAM {
virtual bool MoveLines(PGLOBAL g);
virtual bool MoveIntermediateLines(PGLOBAL g, bool *b = NULL);
virtual int RenameTempFile(PGLOBAL g);
- bool OpenColumnFile(PGLOBAL g, char *opmode, int i);
+ bool OpenColumnFile(PGLOBAL g, PCSZ opmode, int i);
// Members
FILE* *Streams; // Points to Dos file structure array
@@ -235,7 +235,7 @@ class BGVFAM : public VCTFAM {
bool BigSeek(PGLOBAL g, HANDLE h, BIGINT pos, bool b = false);
bool BigRead(PGLOBAL g, HANDLE h, void *inbuf, int req);
bool BigWrite(PGLOBAL g, HANDLE h, void *inbuf, int req);
- virtual bool MakeEmptyFile(PGLOBAL g, char *fn);
+ virtual bool MakeEmptyFile(PGLOBAL g, PCSZ fn);
virtual bool OpenTempFile(PGLOBAL g);
virtual bool MoveIntermediateLines(PGLOBAL g, bool *b = NULL);
virtual bool CleanUnusedSpace(PGLOBAL g);
diff --git a/storage/connect/filamzip.cpp b/storage/connect/filamzip.cpp
index fa857837427..eb06ee7ad1e 100644
--- a/storage/connect/filamzip.cpp
+++ b/storage/connect/filamzip.cpp
@@ -1,7 +1,7 @@
/*********** File AM Zip C++ Program Source Code File (.CPP) ***********/
/* PROGRAM NAME: FILAMZIP */
/* ------------- */
-/* Version 1.1 */
+/* Version 1.3 */
/* */
/* COPYRIGHT: */
/* ---------- */
@@ -45,12 +45,12 @@
#define WRITEBUFFERSIZE (16384)
-bool ZipLoadFile(PGLOBAL g, char *zfn, char *fn, char *entry, bool append, bool mul);
+bool ZipLoadFile(PGLOBAL g, PCSZ zfn, PCSZ fn, PCSZ entry, bool append, bool mul);
/***********************************************************************/
/* Compress a file in zip when creating a table. */
/***********************************************************************/
-static bool ZipFile(PGLOBAL g, ZIPUTIL *zutp, char *fn, char *entry, char *buf)
+static bool ZipFile(PGLOBAL g, ZIPUTIL *zutp, PCSZ fn, PCSZ entry, char *buf)
{
int rc = RC_OK, size_read, size_buf = WRITEBUFFERSIZE;
FILE *fin;
@@ -88,7 +88,7 @@ static bool ZipFile(PGLOBAL g, ZIPUTIL *zutp, char *fn, char *entry, char *buf)
/***********************************************************************/
/* Find and Compress several files in zip when creating a table. */
/***********************************************************************/
-static bool ZipFiles(PGLOBAL g, ZIPUTIL *zutp, char *pat, char *buf)
+static bool ZipFiles(PGLOBAL g, ZIPUTIL *zutp, PCSZ pat, char *buf)
{
char filename[_MAX_PATH];
int rc;
@@ -203,7 +203,7 @@ static bool ZipFiles(PGLOBAL g, ZIPUTIL *zutp, char *pat, char *buf)
/***********************************************************************/
/* Load and Compress a file in zip when creating a table. */
/***********************************************************************/
-bool ZipLoadFile(PGLOBAL g, char *zfn, char *fn, char *entry, bool append, bool mul)
+bool ZipLoadFile(PGLOBAL g, PCSZ zfn, PCSZ fn, PCSZ entry, bool append, bool mul)
{
char *buf;
bool err;
@@ -228,7 +228,7 @@ bool ZipLoadFile(PGLOBAL g, char *zfn, char *fn, char *entry, bool append, bool
/***********************************************************************/
/* Constructors. */
/***********************************************************************/
-ZIPUTIL::ZIPUTIL(PSZ tgt)
+ZIPUTIL::ZIPUTIL(PCSZ tgt)
{
zipfile = NULL;
target = tgt;
@@ -269,7 +269,7 @@ void ZIPUTIL::getTime(tm_zip& tmZip)
/* append: set true to append the zip file */
/* return: true if open, false otherwise. */
/***********************************************************************/
-bool ZIPUTIL::open(PGLOBAL g, char *filename, bool append)
+bool ZIPUTIL::open(PGLOBAL g, PCSZ filename, bool append)
{
if (!zipfile && !(zipfile = zipOpen64(filename,
append ? APPEND_STATUS_ADDINZIP
@@ -295,7 +295,7 @@ void ZIPUTIL::close()
/***********************************************************************/
/* OpenTableFile: Open a DOS/UNIX table file from a ZIP file. */
/***********************************************************************/
-bool ZIPUTIL::OpenTable(PGLOBAL g, MODE mode, char *fn, bool append)
+bool ZIPUTIL::OpenTable(PGLOBAL g, MODE mode, PCSZ fn, bool append)
{
/*********************************************************************/
/* The file will be compressed. */
@@ -338,7 +338,7 @@ bool ZIPUTIL::OpenTable(PGLOBAL g, MODE mode, char *fn, bool append)
/***********************************************************************/
/* Add target in zip file. */
/***********************************************************************/
-bool ZIPUTIL::addEntry(PGLOBAL g, char *entry)
+bool ZIPUTIL::addEntry(PGLOBAL g, PCSZ entry)
{
//?? we dont need the stinking time
zip_fileinfo zi = { {0, 0, 0, 0, 0, 0}, 0, 0, 0 };
@@ -382,10 +382,11 @@ void ZIPUTIL::closeEntry()
/***********************************************************************/
/* Constructors. */
/***********************************************************************/
-UNZIPUTL::UNZIPUTL(PSZ tgt, bool mul)
+UNZIPUTL::UNZIPUTL(PCSZ tgt, bool mul)
{
zipfile = NULL;
target = tgt;
+ pwd = NULL;
fp = NULL;
memory = NULL;
size = 0;
@@ -401,6 +402,26 @@ UNZIPUTL::UNZIPUTL(PSZ tgt, bool mul)
#endif
} // end of UNZIPUTL standard constructor
+UNZIPUTL::UNZIPUTL(PDOSDEF tdp)
+{
+ zipfile = NULL;
+ target = tdp->GetEntry();
+ pwd = tdp->Pwd;
+ fp = NULL;
+ memory = NULL;
+ size = 0;
+ entryopen = false;
+ multiple = tdp->GetMul();
+ memset(fn, 0, sizeof(fn));
+
+ // Init the case mapping table.
+#if defined(__WIN__)
+ for (int i = 0; i < 256; ++i) mapCaseTable[i] = toupper(i);
+#else
+ for (int i = 0; i < 256; ++i) mapCaseTable[i] = i;
+#endif
+} // end of UNZIPUTL standard constructor
+
#if 0
UNZIPUTL::UNZIPUTL(PZIPUTIL zutp)
{
@@ -418,8 +439,8 @@ UNZIPUTL::UNZIPUTL(PZIPUTIL zutp)
/* This code is the copyright property of Alessandro Felice Cantatore. */
/* http://xoomer.virgilio.it/acantato/dev/wildcard/wildmatch.html */
/***********************************************************************/
-bool UNZIPUTL::WildMatch(PSZ pat, PSZ str) {
- PSZ s, p;
+bool UNZIPUTL::WildMatch(PCSZ pat, PCSZ str) {
+ PCSZ s, p;
bool star = FALSE;
loopStart:
@@ -453,7 +474,7 @@ starCheck:
/* param: filename path and the filename of the zip file to open. */
/* return: true if open, false otherwise. */
/***********************************************************************/
-bool UNZIPUTL::open(PGLOBAL g, char *filename)
+bool UNZIPUTL::open(PGLOBAL g, PCSZ filename)
{
if (!zipfile && !(zipfile = unzOpen64(filename)))
sprintf(g->Message, "Zipfile open error on %s", filename);
@@ -543,7 +564,7 @@ int UNZIPUTL::nextEntry(PGLOBAL g)
/***********************************************************************/
/* OpenTableFile: Open a DOS/UNIX table file from a ZIP file. */
/***********************************************************************/
-bool UNZIPUTL::OpenTable(PGLOBAL g, MODE mode, char *fn)
+bool UNZIPUTL::OpenTable(PGLOBAL g, MODE mode, PCSZ fn)
{
/*********************************************************************/
/* The file will be decompressed into virtual memory. */
@@ -581,7 +602,7 @@ bool UNZIPUTL::OpenTable(PGLOBAL g, MODE mode, char *fn)
if (openEntry(g))
return true;
- if (size > 0) {
+ if (size > 0) {
/*******************************************************************/
/* Link a Fblock. This make possible to automatically close it */
/* in case of error g->jump. */
@@ -613,6 +634,28 @@ bool UNZIPUTL::OpenTable(PGLOBAL g, MODE mode, char *fn)
} // end of OpenTableFile
/***********************************************************************/
+/* Insert only if the entry does not exist. */
+/***********************************************************************/
+bool UNZIPUTL::IsInsertOk(PGLOBAL g, PCSZ fn)
+{
+ bool ok = true, b = open(g, fn);
+
+ if (!b) {
+ if (!target || *target == 0) {
+ unz_global_info64 ginfo;
+ int err = unzGetGlobalInfo64(zipfile, &ginfo);
+
+ ok = !(err == UNZ_OK && ginfo.number_entry > 0);
+ } else // Check if the target exist
+ ok = (unzLocateFile(zipfile, target, 0) != UNZ_OK);
+
+ unzClose(zipfile);
+ } // endif b
+
+ return ok;
+} // end of IsInsertOk
+
+/***********************************************************************/
/* Open target in zip file. */
/***********************************************************************/
bool UNZIPUTL::openEntry(PGLOBAL g)
@@ -625,18 +668,24 @@ bool UNZIPUTL::openEntry(PGLOBAL g)
if (rc != UNZ_OK) {
sprintf(g->Message, "unzGetCurrentFileInfo64 rc=%d", rc);
return true;
- } else if ((rc = unzOpenCurrentFile(zipfile)) != UNZ_OK) {
+ } else if ((rc = unzOpenCurrentFilePassword(zipfile, pwd)) != UNZ_OK) {
sprintf(g->Message, "unzOpen fn=%s rc=%d", fn, rc);
return true;
} // endif rc
size = finfo.uncompressed_size;
- memory = new char[size + 1];
+
+ try {
+ memory = new char[size + 1];
+ } catch (...) {
+ strcpy(g->Message, "Out of memory");
+ return true;
+ } // end try/catch
if ((rc = unzReadCurrentFile(zipfile, memory, size)) < 0) {
sprintf(g->Message, "unzReadCurrentFile rc = %d", rc);
unzCloseCurrentFile(zipfile);
- free(memory);
+ delete[] memory;
memory = NULL;
entryopen = false;
} else {
@@ -661,7 +710,7 @@ void UNZIPUTL::closeEntry()
} // endif entryopen
if (memory) {
- free(memory);
+ delete[] memory;
memory = NULL;
} // endif memory
@@ -675,15 +724,17 @@ void UNZIPUTL::closeEntry()
UNZFAM::UNZFAM(PDOSDEF tdp) : MAPFAM(tdp)
{
zutp = NULL;
- target = tdp->GetEntry();
- mul = tdp->GetMul();
+ tdfp = tdp;
+ //target = tdp->GetEntry();
+ //mul = tdp->GetMul();
} // end of UNZFAM standard constructor
UNZFAM::UNZFAM(PUNZFAM txfp) : MAPFAM(txfp)
{
zutp = txfp->zutp;
- target = txfp->target;
- mul = txfp->mul;
+ tdfp = txfp->tdfp;
+ //target = txfp->target;
+ //mul = txfp->mul;
} // end of UNZFAM copy constructor
/***********************************************************************/
@@ -711,7 +762,13 @@ int UNZFAM::Cardinality(PGLOBAL g)
int card = -1;
int len = GetFileLength(g);
- card = (len / (int)Lrecl) * 2; // Estimated ???
+ if (len) {
+ // Estimated ???
+ card = (len / (int)Lrecl) * 2;
+ card = card ? card : 10; // Lrecl can be too big
+ } else
+ card = 0;
+
return card;
} // end of Cardinality
@@ -726,7 +783,7 @@ bool UNZFAM::OpenTableFile(PGLOBAL g)
/*********************************************************************/
/* Allocate the ZIP utility class. */
/*********************************************************************/
- zutp = new(g) UNZIPUTL(target, mul);
+ zutp = new(g) UNZIPUTL(tdfp);
// We used the file name relative to recorded datapath
PlugSetPath(filename, To_File, Tdbp->GetPath());
@@ -841,17 +898,19 @@ void UNZFAM::CloseTableFile(PGLOBAL g, bool)
UZXFAM::UZXFAM(PDOSDEF tdp) : MPXFAM(tdp)
{
zutp = NULL;
- target = tdp->GetEntry();
- mul = tdp->GetMul();
+ tdfp = tdp;
+ //target = tdp->GetEntry();
+ //mul = tdp->GetMul();
//Lrecl = tdp->GetLrecl();
} // end of UZXFAM standard constructor
UZXFAM::UZXFAM(PUZXFAM txfp) : MPXFAM(txfp)
{
zutp = txfp->zutp;
- target = txfp->target;
- mul = txfp->mul;
-//Lrecl = txfp->Lrecl;
+ tdfp = txfp->tdfp;
+ //target = txfp->target;
+ //mul = txfp->mul;
+ //Lrecl = txfp->Lrecl;
} // end of UZXFAM copy constructor
/***********************************************************************/
@@ -907,7 +966,7 @@ bool UZXFAM::OpenTableFile(PGLOBAL g)
/* Allocate the ZIP utility class. */
/*********************************************************************/
if (!zutp)
- zutp = new(g)UNZIPUTL(target, mul);
+ zutp = new(g)UNZIPUTL(tdfp);
// We used the file name relative to recorded datapath
PlugSetPath(filename, To_File, Tdbp->GetPath());
@@ -969,6 +1028,25 @@ bool ZIPFAM::OpenTableFile(PGLOBAL g)
{
char filename[_MAX_PATH];
MODE mode = Tdbp->GetMode();
+ int len = TXTFAM::GetFileLength(g);
+
+ // We used the file name relative to recorded datapath
+ PlugSetPath(filename, To_File, Tdbp->GetPath());
+
+ if (len < 0)
+ return true;
+ else if (!append && len > 0) {
+ strcpy(g->Message, "No insert into existing zip file");
+ return true;
+ } else if (append && len > 0) {
+ UNZIPUTL *zutp = new(g) UNZIPUTL(target, false);
+
+ if (!zutp->IsInsertOk(g, filename)) {
+ strcpy(g->Message, "No insert into existing entry");
+ return true;
+ } // endif Ok
+
+ } // endif's
/*********************************************************************/
/* Allocate the ZIP utility class. */
@@ -1028,15 +1106,31 @@ ZPXFAM::ZPXFAM(PDOSDEF tdp) : FIXFAM(tdp)
target = tdp->GetEntry();
append = tdp->GetAppend();
//Lrecl = tdp->GetLrecl();
-} // end of UZXFAM standard constructor
+} // end of ZPXFAM standard constructor
/***********************************************************************/
/* OpenTableFile: Open a DOS/UNIX table file from a ZIP file. */
/***********************************************************************/
bool ZPXFAM::OpenTableFile(PGLOBAL g)
{
- char filename[_MAX_PATH];
- MODE mode = Tdbp->GetMode();
+ char filename[_MAX_PATH];
+ MODE mode = Tdbp->GetMode();
+ int len = TXTFAM::GetFileLength(g);
+
+ if (len < 0)
+ return true;
+ else if (!append && len > 0) {
+ strcpy(g->Message, "No insert into existing zip file");
+ return true;
+ } else if (append && len > 0) {
+ UNZIPUTL *zutp = new(g) UNZIPUTL(target, false);
+
+ if (!zutp->IsInsertOk(g, filename)) {
+ strcpy(g->Message, "No insert into existing entry");
+ return true;
+ } // endif Ok
+
+ } // endif's
/*********************************************************************/
/* Allocate the ZIP utility class. */
diff --git a/storage/connect/filamzip.h b/storage/connect/filamzip.h
index 3160703bd20..be17d954728 100644
--- a/storage/connect/filamzip.h
+++ b/storage/connect/filamzip.h
@@ -1,5 +1,5 @@
/************** filamzip H Declares Source Code File (.H) **************/
-/* Name: filamzip.h Version 1.1 */
+/* Name: filamzip.h Version 1.2 */
/* */
/* (C) Copyright to the author Olivier BERTRAND 2016-2017 */
/* */
@@ -27,16 +27,13 @@ typedef class ZPXFAM *PZPXFAM;
class DllExport ZIPUTIL : public BLOCK {
public:
// Constructor
- ZIPUTIL(PSZ tgt);
+ ZIPUTIL(PCSZ tgt);
//ZIPUTIL(ZIPUTIL *zutp);
- // Implementation
- //PTXF Duplicate(PGLOBAL g) { return (PTXF) new(g)UNZFAM(this); }
-
// Methods
- bool OpenTable(PGLOBAL g, MODE mode, char *fn, bool append);
- bool open(PGLOBAL g, char *fn, bool append);
- bool addEntry(PGLOBAL g, char *entry);
+ bool OpenTable(PGLOBAL g, MODE mode, PCSZ fn, bool append);
+ bool open(PGLOBAL g, PCSZ fn, bool append);
+ bool addEntry(PGLOBAL g, PCSZ entry);
void close(void);
void closeEntry(void);
int writeEntry(PGLOBAL g, char *buf, int len);
@@ -44,15 +41,10 @@ class DllExport ZIPUTIL : public BLOCK {
// Members
zipFile zipfile; // The ZIP container file
- PSZ target; // The target file name
-//unz_file_info finfo; // The current file info
+ PCSZ target; // The target file name
+ PCSZ pwd; // The ZIP file password
PFBLOCK fp;
-//char *memory;
-//uint size;
-//int multiple; // Multiple targets
bool entryopen; // True when open current entry
-//char fn[FILENAME_MAX]; // The current entry file name
-//char mapCaseTable[256];
}; // end of ZIPUTIL
/***********************************************************************/
@@ -61,25 +53,27 @@ class DllExport ZIPUTIL : public BLOCK {
class DllExport UNZIPUTL : public BLOCK {
public:
// Constructor
- UNZIPUTL(PSZ tgt, bool mul);
-//UNZIPUTL(UNZIPUTL *zutp);
+ UNZIPUTL(PCSZ tgt, bool mul);
+ UNZIPUTL(PDOSDEF tdp);
// Implementation
//PTXF Duplicate(PGLOBAL g) { return (PTXF) new(g)UNZFAM(this); }
// Methods
- bool OpenTable(PGLOBAL g, MODE mode, char *fn);
- bool open(PGLOBAL g, char *fn);
+ bool OpenTable(PGLOBAL g, MODE mode, PCSZ fn);
+ bool open(PGLOBAL g, PCSZ fn);
bool openEntry(PGLOBAL g);
void close(void);
void closeEntry(void);
- bool WildMatch(PSZ pat, PSZ str);
+ bool WildMatch(PCSZ pat, PCSZ str);
int findEntry(PGLOBAL g, bool next);
int nextEntry(PGLOBAL g);
+ bool IsInsertOk(PGLOBAL g, PCSZ fn);
// Members
unzFile zipfile; // The ZIP container file
- PSZ target; // The target file name
+ PCSZ target; // The target file name
+ PCSZ pwd; // The ZIP file password
unz_file_info finfo; // The current file info
PFBLOCK fp;
char *memory;
@@ -119,8 +113,7 @@ class DllExport UNZFAM : public MAPFAM {
protected:
// Members
UNZIPUTL *zutp;
- PSZ target;
- bool mul;
+ PDOSDEF tdfp;
}; // end of UNZFAM
/***********************************************************************/
@@ -147,8 +140,7 @@ class DllExport UZXFAM : public MPXFAM {
protected:
// Members
UNZIPUTL *zutp;
- PSZ target;
- bool mul;
+ PDOSDEF tdfp;
}; // end of UZXFAM
/***********************************************************************/
@@ -175,8 +167,9 @@ class DllExport ZIPFAM : public DOSFAM {
protected:
// Members
ZIPUTIL *zutp;
- PSZ target;
+ PCSZ target;
bool append;
+//bool replace;
}; // end of ZIPFAM
/***********************************************************************/
@@ -200,7 +193,7 @@ class DllExport ZPXFAM : public FIXFAM {
protected:
// Members
ZIPUTIL *zutp;
- PSZ target;
+ PCSZ target;
bool append;
}; // end of ZPXFAM
diff --git a/storage/connect/filter.cpp b/storage/connect/filter.cpp
index 35840e9b5e3..863c9ca6571 100644
--- a/storage/connect/filter.cpp
+++ b/storage/connect/filter.cpp
@@ -1,7 +1,7 @@
/***************** Filter C++ Class Filter Code (.CPP) *****************/
-/* Name: FILTER.CPP Version 3.9 */
+/* Name: FILTER.CPP Version 4.0 */
/* */
-/* (C) Copyright to the author Olivier BERTRAND 1998-2014 */
+/* (C) Copyright to the author Olivier BERTRAND 1998-2017 */
/* */
/* This file contains the class FILTER function code. */
/***********************************************************************/
@@ -87,8 +87,8 @@ BYTE OpBmp(PGLOBAL g, OPVAL opc)
case OP_EXIST: bt = 0x00; break;
default:
sprintf(g->Message, MSG(BAD_FILTER_OP), opc);
- longjmp(g->jumper[g->jump_level], TYPE_ARRAY);
- } // endswitch opc
+ throw TYPE_ARRAY;
+ } // endswitch opc
return bt;
} // end of OpBmp
@@ -1712,7 +1712,7 @@ PFIL PrepareFilter(PGLOBAL g, PFIL fp, bool having)
break; // Remove eventual ending separator(s)
// if (fp->Convert(g, having))
-// longjmp(g->jumper[g->jump_level], TYPE_FILTER);
+// throw TYPE_ARRAY;
filp = fp;
fp = fp->Next;
@@ -1745,7 +1745,7 @@ DllExport bool ApplyFilter(PGLOBAL g, PFIL filp)
// return TRUE;
if (filp->Eval(g))
- longjmp(g->jumper[g->jump_level], TYPE_FILTER);
+ throw TYPE_FILTER;
if (trace > 1)
htrc("PlugFilter filp=%p result=%d\n",
diff --git a/storage/connect/filter.h b/storage/connect/filter.h
index 15730e2cc44..f4835d23a7c 100644
--- a/storage/connect/filter.h
+++ b/storage/connect/filter.h
@@ -61,7 +61,7 @@ class DllExport FILTER : public XOBJECT { /* Filter description block */
//virtual PXOB CheckSubQuery(PGLOBAL, PSQL);
//virtual bool CheckLocal(PTDB);
//virtual int CheckSpcCol(PTDB tdbp, int n);
- virtual void Print(PGLOBAL g, FILE *f, uint n);
+ virtual void Print(PGLOBAL g, FILE *f, uint n);
virtual void Print(PGLOBAL g, char *ps, uint z);
// PFIL Linearize(bool nosep);
// PFIL Link(PGLOBAL g, PFIL fil2);
diff --git a/storage/connect/global.h b/storage/connect/global.h
index 4d01a3ff05b..a2030fdb5d0 100644
--- a/storage/connect/global.h
+++ b/storage/connect/global.h
@@ -1,6 +1,6 @@
/***********************************************************************/
/* GLOBAL.H: Declaration file used by all CONNECT implementations. */
-/* (C) Copyright Olivier Bertrand 1993-2014 */
+/* (C) Copyright Olivier Bertrand 1993-2017 */
/***********************************************************************/
/***********************************************************************/
@@ -59,7 +59,7 @@
#define NO_IVAL -95684275 /* Used by GetIntegerOption */
#define VMLANG 370 /* Size of olf VM lang blocks */
#define MAX_JUMP 24 /* Maximum jump level number */
-#define MAX_STR 1024 /* Maximum string length */
+#define MAX_STR 4160 /* Maximum message length */
#define STR_SIZE 501 /* Length of char strings. */
#define STD_INPUT 0 /* Standard language input */
#define STD_OUTPUT 1 /* Standard language output */
@@ -229,9 +229,10 @@ typedef struct _parm {
typedef struct _global { /* Global structure */
void *Sarea; /* Points to work area */
uint Sarea_Size; /* Work area size */
- PACTIVITY Activityp, ActivityStart;
+ PACTIVITY Activityp;
char Message[MAX_STR];
- int Createas; /* To pass info to created table */
+ ulong More; /* Used by jsonudf */
+ int Createas; /* To pass info to created table */
void *Xchk; /* indexes in create/alter */
short Alchecked; /* Checked for ALTER */
short Mrr; /* True when doing mrr */
diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc
index d7476b44e7b..e525447fa03 100644
--- a/storage/connect/ha_connect.cc
+++ b/storage/connect/ha_connect.cc
@@ -172,9 +172,9 @@
#define JSONMAX 10 // JSON Default max grp size
extern "C" {
- char version[]= "Version 1.05.0003 February 27, 2017";
+ char version[]= "Version 1.06.0001 April 17, 2017";
#if defined(__WIN__)
- char compver[]= "Version 1.05.0003 " __DATE__ " " __TIME__;
+ char compver[]= "Version 1.06.0001 " __DATE__ " " __TIME__;
char slash= '\\';
#else // !__WIN__
char slash= '/';
@@ -213,10 +213,11 @@ PQRYRES JSONColumns(PGLOBAL g, char *db, PTOS topt, bool info);
PQRYRES XMLColumns(PGLOBAL g, char *db, char *tab, PTOS topt, bool info);
int TranslateJDBCType(int stp, char *tn, int prec, int& len, char& v);
void PushWarning(PGLOBAL g, THD *thd, int level);
-bool CheckSelf(PGLOBAL g, TABLE_SHARE *s, const char *host,
- const char *db, char *tab, const char *src, int port);
-bool ZipLoadFile(PGLOBAL, char*, char*, char*, bool, bool);
+bool CheckSelf(PGLOBAL g, TABLE_SHARE *s, PCSZ host, PCSZ db,
+ PCSZ tab, PCSZ src, int port);
+bool ZipLoadFile(PGLOBAL, PCSZ, PCSZ, PCSZ, bool, bool);
bool ExactInfo(void);
+void mongo_init(bool);
USETEMP UseTemp(void);
int GetConvSize(void);
TYPCONV GetTypeConv(void);
@@ -509,7 +510,7 @@ ha_create_table_option connect_table_option_list[]=
HA_TOPTION_NUMBER("LRECL", lrecl, 0, 0, INT_MAX32, 1),
HA_TOPTION_NUMBER("BLOCK_SIZE", elements, 0, 0, INT_MAX32, 1),
//HA_TOPTION_NUMBER("ESTIMATE", estimate, 0, 0, INT_MAX32, 1),
- HA_TOPTION_NUMBER("MULTIPLE", multiple, 0, 0, 2, 1),
+ HA_TOPTION_NUMBER("MULTIPLE", multiple, 0, 0, 3, 1),
HA_TOPTION_NUMBER("HEADER", header, 0, 0, 3, 1),
HA_TOPTION_NUMBER("QUOTED", quoted, (ulonglong) -1, 0, 3, 1),
HA_TOPTION_NUMBER("ENDING", ending, (ulonglong) -1, 0, INT_MAX32, 1),
@@ -670,7 +671,7 @@ static int connect_init_func(void *p)
sql_print_information("CONNECT: %s", version);
#endif // !__WIN__
-#ifdef LIBXML2_SUPPORT
+#if defined(LIBXML2_SUPPORT)
XmlInitParserLib();
#endif // LIBXML2_SUPPORT
@@ -1018,15 +1019,14 @@ ulonglong ha_connect::table_flags() const
/****************************************************************************/
/* Return the value of an option specified in an option list. */
/****************************************************************************/
-char *GetListOption(PGLOBAL g, const char *opname,
- const char *oplist, const char *def)
+PCSZ GetListOption(PGLOBAL g, PCSZ opname, PCSZ oplist, PCSZ def)
{
if (!oplist)
return (char*)def;
char key[16], val[256];
char *pk, *pv, *pn;
- char *opval= (char*)def;
+ PCSZ opval= def;
int n;
for (pk= (char*)oplist; pk; pk= ++pn) {
@@ -1062,9 +1062,9 @@ char *GetListOption(PGLOBAL g, const char *opname,
/****************************************************************************/
/* Return the value of a string option or NULL if not specified. */
/****************************************************************************/
-char *GetStringTableOption(PGLOBAL g, PTOS options, char *opname, char *sdef)
+PCSZ GetStringTableOption(PGLOBAL g, PTOS options, PCSZ opname, PCSZ sdef)
{
- const char *opval= NULL;
+ PCSZ opval= NULL;
if (!options)
return sdef;
@@ -1107,10 +1107,10 @@ char *GetStringTableOption(PGLOBAL g, PTOS options, char *opname, char *sdef)
/****************************************************************************/
/* Return the value of a Boolean option or bdef if not specified. */
/****************************************************************************/
-bool GetBooleanTableOption(PGLOBAL g, PTOS options, char *opname, bool bdef)
+bool GetBooleanTableOption(PGLOBAL g, PTOS options, PCSZ opname, bool bdef)
{
- bool opval= bdef;
- char *pv;
+ bool opval= bdef;
+ PCSZ pv;
if (!options)
return bdef;
@@ -1138,7 +1138,7 @@ bool GetBooleanTableOption(PGLOBAL g, PTOS options, char *opname, bool bdef)
/****************************************************************************/
/* Return the value of an integer option or NO_IVAL if not specified. */
/****************************************************************************/
-int GetIntegerTableOption(PGLOBAL g, PTOS options, char *opname, int idef)
+int GetIntegerTableOption(PGLOBAL g, PTOS options, PCSZ opname, int idef)
{
ulonglong opval= (ulonglong) NO_IVAL;
@@ -1160,10 +1160,10 @@ int GetIntegerTableOption(PGLOBAL g, PTOS options, char *opname, int idef)
opval= (options->compressed);
if ((ulonglong) opval == (ulonglong)NO_IVAL) {
- char *pv;
+ PCSZ pv;
if ((pv= GetListOption(g, opname, options->oplist)))
- opval= CharToNumber(pv, strlen(pv), ULONGLONG_MAX, true);
+ opval= CharToNumber((char*)pv, strlen(pv), ULONGLONG_MAX, true);
else
return idef;
@@ -1188,7 +1188,7 @@ PTOS ha_connect::GetTableOptionStruct(TABLE_SHARE *s)
/****************************************************************************/
/* Return the string eventually formatted with partition name. */
/****************************************************************************/
-char *ha_connect::GetRealString(const char *s)
+char *ha_connect::GetRealString(PCSZ s)
{
char *sv;
@@ -1205,10 +1205,10 @@ char *ha_connect::GetRealString(const char *s)
/****************************************************************************/
/* Return the value of a string option or sdef if not specified. */
/****************************************************************************/
-char *ha_connect::GetStringOption(char *opname, char *sdef)
+PCSZ ha_connect::GetStringOption(PCSZ opname, PCSZ sdef)
{
- char *opval= NULL;
- PTOS options= GetTableOptionStruct();
+ PCSZ opval= NULL;
+ PTOS options= GetTableOptionStruct();
if (!stricmp(opname, "Connect")) {
LEX_STRING cnc= (tshp) ? tshp->connect_string
@@ -1267,7 +1267,7 @@ char *ha_connect::GetStringOption(char *opname, char *sdef)
/****************************************************************************/
/* Return the value of a Boolean option or bdef if not specified. */
/****************************************************************************/
-bool ha_connect::GetBooleanOption(char *opname, bool bdef)
+bool ha_connect::GetBooleanOption(PCSZ opname, bool bdef)
{
bool opval;
PTOS options= GetTableOptionStruct();
@@ -1284,7 +1284,7 @@ bool ha_connect::GetBooleanOption(char *opname, bool bdef)
/* Set the value of the opname option (does not work for oplist options) */
/* Currently used only to set the Sepindex value. */
/****************************************************************************/
-bool ha_connect::SetBooleanOption(char *opname, bool b)
+bool ha_connect::SetBooleanOption(PCSZ opname, bool b)
{
PTOS options= GetTableOptionStruct();
@@ -1302,7 +1302,7 @@ bool ha_connect::SetBooleanOption(char *opname, bool b)
/****************************************************************************/
/* Return the value of an integer option or NO_IVAL if not specified. */
/****************************************************************************/
-int ha_connect::GetIntegerOption(char *opname)
+int ha_connect::GetIntegerOption(PCSZ opname)
{
int opval;
PTOS options= GetTableOptionStruct();
@@ -1322,7 +1322,7 @@ int ha_connect::GetIntegerOption(char *opname)
/* Set the value of the opname option (does not work for oplist options) */
/* Currently used only to set the Lrecl value. */
/****************************************************************************/
-bool ha_connect::SetIntegerOption(char *opname, int n)
+bool ha_connect::SetIntegerOption(PCSZ opname, int n)
{
PTOS options= GetTableOptionStruct();
@@ -1522,7 +1522,7 @@ PXOS ha_connect::GetIndexOptionStruct(KEY *kp)
/****************************************************************************/
/* Return a Boolean index option or false if not specified. */
/****************************************************************************/
-bool ha_connect::GetIndexOption(KEY *kp, char *opname)
+bool ha_connect::GetIndexOption(KEY *kp, PCSZ opname)
{
bool opval= false;
PXOS options= GetIndexOptionStruct(kp);
@@ -1534,7 +1534,7 @@ bool ha_connect::GetIndexOption(KEY *kp, char *opname)
opval= options->mapped;
} else if (kp->comment.str && kp->comment.length) {
- char *pv, *oplist= strz(xp->g, kp->comment);
+ PCSZ pv, oplist= strz(xp->g, kp->comment);
if ((pv= GetListOption(xp->g, opname, oplist)))
opval= (!*pv || *pv == 'y' || *pv == 'Y' || atoi(pv) != 0);
@@ -1739,9 +1739,9 @@ void ha_connect::AddColName(char *cp, Field *fp)
/***********************************************************************/
/* This function sets the current database path. */
/***********************************************************************/
-void ha_connect::SetDataPath(PGLOBAL g, const char *path)
+bool ha_connect::SetDataPath(PGLOBAL g, const char *path)
{
- datapath= SetPath(g, path);
+ return (!(datapath= SetPath(g, path)));
} // end of SetDataPath
/****************************************************************************/
@@ -1895,40 +1895,36 @@ int ha_connect::OpenTable(PGLOBAL g, bool del)
bool ha_connect::CheckColumnList(PGLOBAL g)
{
// Check the list of used fields (columns)
- int rc;
bool brc= false;
PCOL colp;
Field* *field;
Field* fp;
MY_BITMAP *map= table->read_set;
- // Save stack and allocation environment and prepare error return
- if (g->jump_level == MAX_JUMP) {
- strcpy(g->Message, MSG(TOO_MANY_JUMPS));
- return true;
- } // endif jump_level
-
- if ((rc= setjmp(g->jumper[++g->jump_level])) == 0) {
+ try {
for (field= table->field; fp= *field; field++)
if (bitmap_is_set(map, fp->field_index)) {
if (!(colp= tdbp->ColDB(g, (PSZ)fp->field_name, 0))) {
sprintf(g->Message, "Column %s not found in %s",
fp->field_name, tdbp->GetName());
- brc= true;
- goto fin;
- } // endif colp
+ throw 1;
+ } // endif colp
if ((brc= colp->InitValue(g)))
- goto fin;
+ throw 2;
colp->AddColUse(U_P); // For PLG tables
} // endif
- } else
- brc= true;
+ } catch (int n) {
+ if (trace)
+ htrc("Exception %d: %s\n", n, g->Message);
+ brc = true;
+ } catch (const char *msg) {
+ strcpy(g->Message, msg);
+ brc = true;
+ } // end catch
- fin:
- g->jump_level--;
return brc;
} // end of CheckColumnList
@@ -1965,7 +1961,8 @@ int ha_connect::CloseTable(PGLOBAL g)
/***********************************************************************/
int ha_connect::MakeRecord(char *buf)
{
- char *p, *fmt, val[32];
+ PCSZ fmt;
+ char *p, val[32];
int rc= 0;
Field* *field;
Field *fp;
@@ -2101,7 +2098,7 @@ int ha_connect::ScanRecord(PGLOBAL g, uchar *)
{
char attr_buffer[1024];
char data_buffer[1024];
- char *fmt;
+ PCSZ fmt;
int rc= 0;
PCOL colp;
PVAL value, sdvalin;
@@ -2275,7 +2272,7 @@ bool ha_connect::MakeKeyWhere(PGLOBAL g, PSTRG qry, OPVAL vop, char q,
const uchar *ptr;
//uint i, rem, len, klen, stlen;
uint i, rem, len, stlen;
- bool nq, both, oom= false;
+ bool nq, both, oom;
OPVAL op;
Field *fp;
const key_range *ranges[2];
@@ -2303,9 +2300,9 @@ bool ha_connect::MakeKeyWhere(PGLOBAL g, PSTRG qry, OPVAL vop, char q,
continue;
if (both && i > 0)
- oom|= qry->Append(") AND (");
+ qry->Append(") AND (");
else
- oom|= qry->Append(" WHERE (");
+ qry->Append(" WHERE (");
// klen= len= ranges[i]->length;
len= ranges[i]->length;
@@ -2318,14 +2315,14 @@ bool ha_connect::MakeKeyWhere(PGLOBAL g, PSTRG qry, OPVAL vop, char q,
nq= fp->str_needs_quotes();
if (kpart != kfp->key_part)
- oom|= qry->Append(" AND ");
+ qry->Append(" AND ");
if (q) {
- oom|= qry->Append(q);
- oom|= qry->Append((PSZ)fp->field_name);
- oom|= qry->Append(q);
+ qry->Append(q);
+ qry->Append((PSZ)fp->field_name);
+ qry->Append(q);
} else
- oom|= qry->Append((PSZ)fp->field_name);
+ qry->Append((PSZ)fp->field_name);
switch (ranges[i]->flag) {
case HA_READ_KEY_EXACT:
@@ -2350,10 +2347,10 @@ bool ha_connect::MakeKeyWhere(PGLOBAL g, PSTRG qry, OPVAL vop, char q,
goto err;
} // endswitch flag
- oom|= qry->Append((PSZ)GetValStr(op, false));
+ qry->Append((PSZ)GetValStr(op, false));
if (nq)
- oom|= qry->Append('\'');
+ qry->Append('\'');
if (kpart->key_part_flag & HA_VAR_LENGTH_PART) {
String varchar;
@@ -2361,17 +2358,17 @@ bool ha_connect::MakeKeyWhere(PGLOBAL g, PSTRG qry, OPVAL vop, char q,
varchar.set_quick((char*)ptr + HA_KEY_BLOB_LENGTH,
var_length, &my_charset_bin);
- oom|= qry->Append(varchar.ptr(), varchar.length(), nq);
+ qry->Append(varchar.ptr(), varchar.length(), nq);
} else {
char strbuff[MAX_FIELD_WIDTH];
String str(strbuff, sizeof(strbuff), kpart->field->charset()), *res;
res= fp->val_str(&str, ptr);
- oom|= qry->Append(res->ptr(), res->length(), nq);
+ qry->Append(res->ptr(), res->length(), nq);
} // endif flag
if (nq)
- oom |= qry->Append('\'');
+ qry->Append('\'');
if (stlen >= len)
break;
@@ -2386,7 +2383,9 @@ bool ha_connect::MakeKeyWhere(PGLOBAL g, PSTRG qry, OPVAL vop, char q,
} // endfor i
- if ((oom|= qry->Append(")")))
+ qry->Append(')');
+
+ if ((oom= qry->IsTruncated()))
strcpy(g->Message, "Out of memory");
dbug_tmp_restore_column_map(table->write_set, old_map);
@@ -2699,6 +2698,8 @@ PCFIL ha_connect::CheckCond(PGLOBAL g, PCFIL filp, const Item *cond)
if (x)
return NULL;
+ else
+ pb0= pb1= pb2= ph0= ph1= ph2= NULL;
if (trace)
htrc("Cond: Ftype=%d name=%s\n", cond_item->functype(),
@@ -3055,7 +3056,6 @@ const COND *ha_connect::cond_push(const COND *cond)
DBUG_ENTER("ha_connect::cond_push");
if (tdbp) {
- int rc;
PGLOBAL& g= xp->g;
AMT tty= tdbp->GetAmType();
bool x= (tty == TYPE_AM_MYX || tty == TYPE_AM_XDBC);
@@ -3063,58 +3063,66 @@ const COND *ha_connect::cond_push(const COND *cond)
tty == TYPE_AM_TBL || tty == TYPE_AM_MYSQL ||
tty == TYPE_AM_PLG || tty == TYPE_AM_JDBC || x);
- // Save stack and allocation environment and prepare error return
- if (g->jump_level == MAX_JUMP) {
- strcpy(g->Message, MSG(TOO_MANY_JUMPS));
- DBUG_RETURN(cond);
- } // endif jump_level
+ // This should never happen but is done to avoid crashing
+ try {
+ if (b) {
+ PCFIL filp;
+ int rc;
- // This should never happen but is done to avoid crashing
- if ((rc= setjmp(g->jumper[++g->jump_level])) != 0)
- goto fin;
+ if ((filp = tdbp->GetCondFil()) && tdbp->GetCond() == cond &&
+ filp->Idx == active_index && filp->Type == tty)
+ goto fin;
- if (b) {
- PCFIL filp;
- int rc;
+ filp = new(g) CONDFIL(active_index, tty);
+ rc = filp->Init(g, this);
- if ((filp= tdbp->GetCondFil()) && filp->Cond == cond &&
- filp->Idx == active_index && filp->Type == tty)
- goto fin; // Already done
+ if (rc == RC_INFO) {
+ filp->Having = (char*)PlugSubAlloc(g, NULL, 256);
+ *filp->Having = 0;
+ } else if (rc == RC_FX)
+ goto fin;
- filp= new(g) CONDFIL(cond, active_index, tty);
- rc = filp->Init(g, this);
+ filp->Body = (char*)PlugSubAlloc(g, NULL, (x) ? 128 : 0);
+ *filp->Body = 0;
- if (rc == RC_INFO) {
- filp->Having = (char*)PlugSubAlloc(g, NULL, 256);
- *filp->Having = 0;
- } else if (rc == RC_FX)
- goto fin;
+ if (CheckCond(g, filp, cond)) {
+ if (filp->Having && strlen(filp->Having) > 255)
+ goto fin; // Memory collapse
- filp->Body = (char*)PlugSubAlloc(g, NULL, (x) ? 128 : 0);
- *filp->Body = 0;
+ if (trace)
+ htrc("cond_push: %s\n", filp->Body);
- if (CheckCond(g, filp, cond)) {
- if (filp->Having && strlen(filp->Having) > 255)
- goto fin; // Memory collapse
+ tdbp->SetCond(cond);
- if (trace)
- htrc("cond_push: %s\n", filp->Body);
+ if (!x)
+ PlugSubAlloc(g, NULL, strlen(filp->Body) + 1);
+ else
+ cond = NULL; // Does this work?
- if (!x)
- PlugSubAlloc(g, NULL, strlen(filp->Body) + 1);
- else
- cond= NULL; // Does this work?
+ tdbp->SetCondFil(filp);
+ } else if (x && cond)
+ tdbp->SetCondFil(filp); // Wrong filter
- tdbp->SetCondFil(filp);
- } else if (x && cond)
- tdbp->SetCondFil(filp); // Wrong filter
+ } else if (tdbp->CanBeFiltered()) {
+ if (!tdbp->GetCond() || tdbp->GetCond() != cond) {
+ tdbp->SetFilter(CondFilter(g, (Item *)cond));
- } else if (tty != TYPE_AM_JSN && tty != TYPE_AM_JSON)
- tdbp->SetFilter(CondFilter(g, (Item *)cond));
+ if (tdbp->GetFilter())
+ tdbp->SetCond(cond);
- fin:
- g->jump_level--;
- } // endif tdbp
+ } // endif cond
+
+ } // endif tty
+
+ } catch (int n) {
+ if (trace)
+ htrc("Exception %d: %s\n", n, g->Message);
+ } catch (const char *msg) {
+ strcpy(g->Message, msg);
+ } // end catch
+
+ fin:;
+ } // endif tdbp
// Let MySQL do the filtering
DBUG_RETURN(cond);
@@ -3264,26 +3272,36 @@ int ha_connect::optimize(THD* thd, HA_CHECK_OPT*)
PGLOBAL& g= xp->g;
PDBUSER dup= PlgGetUser(g);
- // Ignore error on the opt file
- dup->Check &= ~CHK_OPT;
- tdbp= GetTDB(g);
- dup->Check |= CHK_OPT;
+ try {
+ // Ignore error on the opt file
+ dup->Check &= ~CHK_OPT;
+ tdbp = GetTDB(g);
+ dup->Check |= CHK_OPT;
- if (tdbp && !tdbp->IsRemote()) {
- bool dop= IsTypeIndexable(GetRealType(NULL));
- bool dox= (tdbp->GetDef()->Indexable() == 1);
+ if (tdbp && !tdbp->IsRemote()) {
+ bool dop = IsTypeIndexable(GetRealType(NULL));
+ bool dox = (tdbp->GetDef()->Indexable() == 1);
- if ((rc= ((PTDBASE)tdbp)->ResetTableOpt(g, dop, dox))) {
- if (rc == RC_INFO) {
- push_warning(thd, Sql_condition::WARN_LEVEL_WARN, 0, g->Message);
- rc= 0;
- } else
- rc= HA_ERR_INTERNAL_ERROR;
+ if ((rc = ((PTDBASE)tdbp)->ResetTableOpt(g, dop, dox))) {
+ if (rc == RC_INFO) {
+ push_warning(thd, Sql_condition::WARN_LEVEL_WARN, 0, g->Message);
+ rc = 0;
+ } else
+ rc = HA_ERR_INTERNAL_ERROR;
- } // endif rc
+ } // endif rc
- } else if (!tdbp)
- rc= HA_ERR_INTERNAL_ERROR;
+ } else if (!tdbp)
+ rc = HA_ERR_INTERNAL_ERROR;
+
+ } catch (int n) {
+ if (trace)
+ htrc("Exception %d: %s\n", n, g->Message);
+ rc = HA_ERR_INTERNAL_ERROR;
+ } catch (const char *msg) {
+ strcpy(g->Message, msg);
+ rc = HA_ERR_INTERNAL_ERROR;
+ } // end catch
return rc;
} // end of optimize
@@ -3978,8 +3996,12 @@ int ha_connect::rnd_pos(uchar *buf, uchar *pos)
tdbp->SetFilter(NULL);
rc= rnd_next(buf);
- } else
- rc= HA_ERR_KEY_NOT_FOUND;
+ } else {
+ PGLOBAL g = GetPlug((table) ? table->in_use : NULL, xp);
+ strcpy(g->Message, "Not supported by this table type");
+ my_message(ER_ILLEGAL_HA, g->Message, MYF(0));
+ rc= HA_ERR_INTERNAL_ERROR;
+ } // endif SetRecpos
DBUG_RETURN(rc);
} // end of rnd_pos
@@ -4045,9 +4067,13 @@ int ha_connect::info(uint flag)
} // endif xmod
// This is necessary for getting file length
- if (table)
- SetDataPath(g, table->s->db.str);
- else
+ if (table) {
+ if (SetDataPath(g, table->s->db.str)) {
+ my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0));
+ DBUG_RETURN(HA_ERR_INTERNAL_ERROR);
+ } // endif SetDataPath
+
+ } else
DBUG_RETURN(HA_ERR_INTERNAL_ERROR); // Should never happen
if (!(tdbp= GetTDB(g)))
@@ -4197,28 +4223,28 @@ bool ha_connect::check_privileges(THD *thd, PTOS options, char *dbn, bool quick)
case TAB_INI:
case TAB_VEC:
case TAB_JSON:
- if (options->filename && *options->filename) {
- if (!quick) {
- char *s, path[FN_REFLEN], dbpath[FN_REFLEN];
+ if (options->filename && *options->filename) {
+ if (!quick) {
+ char path[FN_REFLEN], dbpath[FN_REFLEN];
+
+ strcpy(dbpath, mysql_real_data_home);
+
+ if (db)
#if defined(__WIN__)
- s= "\\";
+ strcat(strcat(dbpath, db), "\\");
#else // !__WIN__
- s= "/";
+ strcat(strcat(dbpath, db), "/");
#endif // !__WIN__
- strcpy(dbpath, mysql_real_data_home);
-
- if (db)
- strcat(strcat(dbpath, db), s);
- (void) fn_format(path, options->filename, dbpath, "",
- MY_RELATIVE_PATH | MY_UNPACK_FILENAME);
+ (void)fn_format(path, options->filename, dbpath, "",
+ MY_RELATIVE_PATH | MY_UNPACK_FILENAME);
- if (!is_secure_file_path(path)) {
- my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--secure-file-priv");
- return true;
- } // endif path
- }
- } else
+ if (!is_secure_file_path(path)) {
+ my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--secure-file-priv");
+ return true;
+ } // endif path
+ }
+ } else
return false;
/* check FILE_ACL */
@@ -4226,7 +4252,7 @@ bool ha_connect::check_privileges(THD *thd, PTOS options, char *dbn, bool quick)
case TAB_ODBC:
case TAB_JDBC:
case TAB_MYSQL:
- case TAB_DIR:
+ case TAB_DIR:
case TAB_MAC:
case TAB_WMI:
case TAB_ZIP:
@@ -4531,9 +4557,11 @@ int ha_connect::external_lock(THD *thd, int lock_type)
DBUG_RETURN(0);
} else if (g->Xchk) {
if (!tdbp) {
- if (!(tdbp= GetTDB(g)))
- DBUG_RETURN(HA_ERR_INTERNAL_ERROR);
- else if (!tdbp->GetDef()->Indexable()) {
+ if (!(tdbp = GetTDB(g))) {
+// DBUG_RETURN(HA_ERR_INTERNAL_ERROR); causes assert error
+ push_warning(thd, Sql_condition::WARN_LEVEL_WARN, 0, g->Message);
+ DBUG_RETURN(0);
+ } else if (!tdbp->GetDef()->Indexable()) {
sprintf(g->Message, "external_lock: Table %s is not indexable", tdbp->GetName());
// DBUG_RETURN(HA_ERR_INTERNAL_ERROR); causes assert error
push_warning(thd, Sql_condition::WARN_LEVEL_WARN, 0, g->Message);
@@ -4617,7 +4645,9 @@ int ha_connect::external_lock(THD *thd, int lock_type)
push_warning(thd, Sql_condition::WARN_LEVEL_WARN,
0, g->Message);
rc= 0;
- } // endif MakeIndex
+ //my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0));
+ //rc= HA_ERR_INTERNAL_ERROR;
+ } // endif MakeIndex
} else if (tdbp->GetDef()->Indexable() == 3) {
if (CheckVirtualIndex(NULL)) {
@@ -4638,9 +4668,12 @@ int ha_connect::external_lock(THD *thd, int lock_type)
// Make it a warning to avoid crash
push_warning(thd, Sql_condition::WARN_LEVEL_WARN, 0, g->Message);
rc= 0;
- } // endif Close
+ //my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0));
+ //rc = HA_ERR_INTERNAL_ERROR;
+ } // endif Close
locked= 0;
+// m_lock_type= lock_type;
xmod= MODE_ANY; // For info commands
DBUG_RETURN(rc);
} // endif MODE_ANY
@@ -4998,8 +5031,8 @@ ha_rows ha_connect::records_in_range(uint inx, key_range *min_key,
} // end of records_in_range
// Used to check whether a MYSQL table is created on itself
-bool CheckSelf(PGLOBAL g, TABLE_SHARE *s, const char *host,
- const char *db, char *tab, const char *src, int port)
+bool CheckSelf(PGLOBAL g, TABLE_SHARE *s, PCSZ host,
+ PCSZ db, PCSZ tab, PCSZ src, int port)
{
if (src)
return false;
@@ -5235,41 +5268,41 @@ static int connect_assisted_discovery(handlerton *, THD* thd,
TABLE_SHARE *table_s,
HA_CREATE_INFO *create_info)
{
- char v=0;
- const char *fncn= "?";
- const char *user, *fn, *db, *host, *pwd, *sep, *tbl, *src;
- const char *col, *ocl, *rnk, *pic, *fcl, *skc, *zfn;
- char *tab, *dsn, *shm, *dpath;
+ char v=0;
+ PCSZ fncn= "?";
+ PCSZ user, fn, db, host, pwd, sep, tbl, src;
+ PCSZ col, ocl, rnk, pic, fcl, skc, zfn;
+ char *tab, *dsn, *shm, *dpath;
#if defined(__WIN__)
- char *nsp= NULL, *cls= NULL;
+ PCSZ nsp= NULL, cls= NULL;
#endif // __WIN__
-//int hdr, mxe;
- int port = 0, mxr = 0, rc = 0, mul = 0, lrecl = 0;
+//int hdr, mxe;
+ int port = 0, mxr = 0, rc = 0, mul = 0, lrecl = 0;
#if defined(ODBC_SUPPORT)
- POPARM sop= NULL;
- char *ucnc= NULL;
- bool cnc= false;
- int cto= -1, qto= -1;
+ POPARM sop= NULL;
+ PCSZ ucnc= NULL;
+ bool cnc= false;
+ int cto= -1, qto= -1;
#endif // ODBC_SUPPORT
#if defined(JDBC_SUPPORT)
- PJPARM sjp= NULL;
- char *driver= NULL;
- char *url= NULL;
-//char *prop= NULL;
- char *tabtyp= NULL;
+ PJPARM sjp= NULL;
+ PCSZ driver= NULL;
+ char *url= NULL;
+//char *prop= NULL;
+ PCSZ tabtyp= NULL;
#endif // JDBC_SUPPORT
- uint tm, fnc= FNC_NO, supfnc= (FNC_NO | FNC_COL);
- bool bif, ok= false, dbf= false;
- TABTYPE ttp= TAB_UNDEF;
- PQRYRES qrp= NULL;
- PCOLRES crp;
- PCONNECT xp= NULL;
- PGLOBAL g= GetPlug(thd, xp);
- PDBUSER dup= PlgGetUser(g);
- PCATLG cat= (dup) ? dup->Catalog : NULL;
- PTOS topt= table_s->option_struct;
- char buf[1024];
- String sql(buf, sizeof(buf), system_charset_info);
+ uint tm, fnc= FNC_NO, supfnc= (FNC_NO | FNC_COL);
+ bool bif, ok= false, dbf= false;
+ TABTYPE ttp= TAB_UNDEF;
+ PQRYRES qrp= NULL;
+ PCOLRES crp;
+ PCONNECT xp= NULL;
+ PGLOBAL g= GetPlug(thd, xp);
+ PDBUSER dup= PlgGetUser(g);
+ PCATLG cat= (dup) ? dup->Catalog : NULL;
+ PTOS topt= table_s->option_struct;
+ char buf[1024];
+ String sql(buf, sizeof(buf), system_charset_info);
sql.copy(STRING_WITH_LEN("CREATE TABLE whatever ("), system_charset_info);
@@ -5294,7 +5327,7 @@ static int connect_assisted_discovery(handlerton *, THD* thd,
if (topt->oplist) {
host= GetListOption(g, "host", topt->oplist, "localhost");
user= GetListOption(g, "user", topt->oplist,
- (ttp == TAB_ODBC ? NULL : "root"));
+ ((ttp == TAB_ODBC || ttp == TAB_JDBC) ? 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);
@@ -5331,128 +5364,118 @@ static int connect_assisted_discovery(handlerton *, THD* thd,
#endif // ZIP_SUPPORT
} else {
host= "localhost";
- user= (ttp == TAB_ODBC ? NULL : "root");
+ user= ((ttp == TAB_ODBC || ttp == TAB_JDBC) ? NULL : "root");
} // endif option_list
if (!(shm= (char*)db))
db= table_s->db.str; // Default value
- // Save stack and allocation environment and prepare error return
- if (g->jump_level == MAX_JUMP) {
- strcpy(g->Message, MSG(TOO_MANY_JUMPS));
- goto jer;
- } // endif jump_level
-
- if ((rc= setjmp(g->jumper[++g->jump_level])) != 0) {
- my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0));
- goto err;
- } // endif rc
-
- // Check table type
- if (ttp == TAB_UNDEF) {
- topt->type= (src) ? "MYSQL" : (tab) ? "PROXY" : "DOS";
- ttp= GetTypeID(topt->type);
- sprintf(g->Message, "No table_type. Was set to %s", topt->type);
- push_warning(thd, Sql_condition::WARN_LEVEL_WARN, 0, g->Message);
- } else if (ttp == TAB_NIY) {
- sprintf(g->Message, "Unsupported table type %s", topt->type);
- my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0));
- goto err;
- } // endif ttp
-
- if (!tab) {
- if (ttp == TAB_TBL) {
- // Make tab the first table of the list
- char *p;
-
- if (!tbl) {
- strcpy(g->Message, "Missing table list");
- my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0));
- goto err;
- } // endif tbl
-
- tab= PlugDup(g, tbl);
-
- if ((p= strchr(tab, ',')))
- *p= 0;
-
- if ((p=strchr(tab, '.'))) {
- *p= 0;
- db= tab;
- tab= p + 1;
- } // endif p
-
- } else if (ttp != TAB_ODBC || !(fnc & (FNC_TABLE | FNC_COL)))
- tab= table_s->table_name.str; // Default value
-
- } // endif tab
-
- switch (ttp) {
+ try {
+ // Check table type
+ if (ttp == TAB_UNDEF) {
+ topt->type = (src) ? "MYSQL" : (tab) ? "PROXY" : "DOS";
+ ttp = GetTypeID(topt->type);
+ sprintf(g->Message, "No table_type. Was set to %s", topt->type);
+ push_warning(thd, Sql_condition::WARN_LEVEL_WARN, 0, g->Message);
+ } else if (ttp == TAB_NIY) {
+ sprintf(g->Message, "Unsupported table type %s", topt->type);
+ rc = HA_ERR_INTERNAL_ERROR;
+ goto err;
+ } // endif ttp
+
+ if (!tab) {
+ if (ttp == TAB_TBL) {
+ // Make tab the first table of the list
+ char *p;
+
+ if (!tbl) {
+ strcpy(g->Message, "Missing table list");
+ rc = HA_ERR_INTERNAL_ERROR;
+ goto err;
+ } // endif tbl
+
+ tab = PlugDup(g, tbl);
+
+ if ((p = strchr(tab, ',')))
+ *p = 0;
+
+ if ((p = strchr(tab, '.'))) {
+ *p = 0;
+ db = tab;
+ tab = p + 1;
+ } // endif p
+
+ } else if (ttp != TAB_ODBC || !(fnc & (FNC_TABLE | FNC_COL)))
+ tab = table_s->table_name.str; // Default value
+
+ } // endif tab
+
+ switch (ttp) {
#if defined(ODBC_SUPPORT)
- case TAB_ODBC:
- dsn= strz(g, create_info->connect_string);
+ case TAB_ODBC:
+ dsn = strz(g, create_info->connect_string);
- if (fnc & (FNC_DSN | FNC_DRIVER)) {
- ok= true;
+ if (fnc & (FNC_DSN | FNC_DRIVER)) {
+ ok = true;
#if defined(PROMPT_OK)
- } else if (!stricmp(thd->main_security_ctx.host, "localhost")
- && cop == 1) {
- if ((dsn = ODBCCheckConnection(g, dsn, cop)) != NULL) {
- thd->make_lex_string(&create_info->connect_string, dsn, strlen(dsn));
- ok= true;
- } // endif dsn
+ } else if (!stricmp(thd->main_security_ctx.host, "localhost")
+ && cop == 1) {
+ if ((dsn = ODBCCheckConnection(g, dsn, cop)) != NULL) {
+ thd->make_lex_string(&create_info->connect_string, dsn, strlen(dsn));
+ ok = true;
+ } // endif dsn
#endif // PROMPT_OK
- } else if (!dsn) {
- sprintf(g->Message, "Missing %s connection string", topt->type);
- } 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;
+ } else if (!dsn) {
+ sprintf(g->Message, "Missing %s connection string", topt->type);
+ } 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;
#endif // ODBC_SUPPORT
#if defined(JDBC_SUPPORT)
- case TAB_JDBC:
- if (fnc & FNC_DRIVER) {
- ok= true;
- } else if (!(url= strz(g, create_info->connect_string))) {
- strcpy(g->Message, "Missing URL");
- } else {
- // Store JDBC additional parameters
- int rc;
- PJDBCDEF jdef= new(g) JDBCDEF();
-
- jdef->SetName(create_info->alias);
- sjp= (PJPARM)PlugSubAlloc(g, NULL, sizeof(JDBCPARM));
- sjp->Driver= driver;
-// sjp->Properties = prop;
- sjp->Fsize= 0;
- sjp->Scrollable= false;
-
- if ((rc = jdef->ParseURL(g, url, false)) == RC_OK) {
- sjp->Url= url;
- sjp->User= (char*)user;
- sjp->Pwd= (char*)pwd;
- ok= true;
- } else if (rc == RC_NF) {
- if (jdef->GetTabname())
- tab= jdef->GetTabname();
-
- ok= jdef->SetParms(sjp);
- } // endif rc
-
- } // endif's
-
- supfnc |= (FNC_DRIVER | FNC_TABLE);
- break;
+ case TAB_JDBC:
+ if (fnc & FNC_DRIVER) {
+ ok = true;
+ } else if (!(url = strz(g, create_info->connect_string))) {
+ strcpy(g->Message, "Missing URL");
+ } else {
+ // Store JDBC additional parameters
+ int rc;
+ PJDBCDEF jdef = new(g) JDBCDEF();
+
+ jdef->SetName(create_info->alias);
+ sjp = (PJPARM)PlugSubAlloc(g, NULL, sizeof(JDBCPARM));
+ sjp->Driver = driver;
+ // sjp->Properties = prop;
+ sjp->Fsize = 0;
+ sjp->Scrollable = false;
+
+ if ((rc = jdef->ParseURL(g, url, false)) == RC_OK) {
+ sjp->Url = url;
+ sjp->User = (char*)user;
+ sjp->Pwd = (char*)pwd;
+ ok = true;
+ } else if (rc == RC_NF) {
+ if (jdef->GetTabname())
+ tab = (char*)jdef->GetTabname();
+
+ ok = jdef->SetParms(sjp);
+ } // endif rc
+
+ } // endif's
+
+ supfnc |= (FNC_DRIVER | FNC_TABLE);
+ break;
#endif // JDBC_SUPPORT
case TAB_DBF:
dbf= true;
@@ -5465,415 +5488,372 @@ static int connect_assisted_discovery(handlerton *, THD* thd,
else
ok= true;
- break;
- case TAB_MYSQL:
- ok= true;
+ break;
+ case TAB_MYSQL:
+ ok = true;
- if (create_info->connect_string.str &&
- create_info->connect_string.length) {
- PMYDEF mydef= new(g) MYSQLDEF();
+ if (create_info->connect_string.str &&
+ create_info->connect_string.length) {
+ PMYDEF mydef = new(g) MYSQLDEF();
- dsn= strz(g, create_info->connect_string);
- mydef->SetName(create_info->alias);
+ dsn = strz(g, create_info->connect_string);
+ mydef->SetName(create_info->alias);
- if (!mydef->ParseURL(g, dsn, false)) {
- if (mydef->GetHostname())
- host= mydef->GetHostname();
+ if (!mydef->ParseURL(g, dsn, false)) {
+ if (mydef->GetHostname())
+ host = mydef->GetHostname();
- if (mydef->GetUsername())
- user= mydef->GetUsername();
+ if (mydef->GetUsername())
+ user = mydef->GetUsername();
- if (mydef->GetPassword())
- pwd= mydef->GetPassword();
+ if (mydef->GetPassword())
+ pwd = mydef->GetPassword();
- if (mydef->GetTabschema())
- db = mydef->GetTabschema();
+ if (mydef->GetTabschema())
+ db = mydef->GetTabschema();
- if (mydef->GetTabname())
- tab= mydef->GetTabname();
+ if (mydef->GetTabname())
+ tab = (char*)mydef->GetTabname();
- if (mydef->GetPortnumber())
- port= mydef->GetPortnumber();
+ if (mydef->GetPortnumber())
+ port = mydef->GetPortnumber();
- } else
- ok= false;
+ } else
+ ok = false;
- } else if (!user)
- user= "root";
+ } else if (!user)
+ user = "root";
- if (ok && CheckSelf(g, table_s, host, db, tab, src, port))
- ok= false;
+ if (ok && CheckSelf(g, table_s, host, db, tab, src, port))
+ ok = false;
- break;
+ break;
#if defined(__WIN__)
- case TAB_WMI:
- ok= true;
- break;
+ case TAB_WMI:
+ ok = true;
+ break;
#endif // __WIN__
#if defined(PIVOT_SUPPORT)
- case TAB_PIVOT:
- supfnc= FNC_NO;
+ case TAB_PIVOT:
+ supfnc = FNC_NO;
#endif // PIVOT_SUPPORT
- case TAB_PRX:
- case TAB_TBL:
- case TAB_XCL:
- case TAB_OCCUR:
- if (!src && !stricmp(tab, create_info->alias) &&
- (!db || !stricmp(db, table_s->db.str)))
- sprintf(g->Message, "A %s table cannot refer to itself", topt->type);
- else
- ok= true;
+ case TAB_PRX:
+ case TAB_TBL:
+ case TAB_XCL:
+ case TAB_OCCUR:
+ if (!src && !stricmp(tab, create_info->alias) &&
+ (!db || !stricmp(db, table_s->db.str)))
+ sprintf(g->Message, "A %s table cannot refer to itself", topt->type);
+ else
+ ok = true;
- break;
- case TAB_OEM:
- if (topt->module && topt->subtype)
- ok= true;
- else
- strcpy(g->Message, "Missing OEM module or subtype");
+ break;
+ case TAB_OEM:
+ if (topt->module && topt->subtype)
+ ok = true;
+ else
+ strcpy(g->Message, "Missing OEM module or subtype");
- break;
+ break;
#if defined(LIBXML2_SUPPORT) || defined(DOMDOC_SUPPORT)
- case TAB_XML:
+ case TAB_XML:
#endif // LIBXML2_SUPPORT || DOMDOC_SUPPORT
- case TAB_JSON:
- if (!fn && !zfn && !mul)
- sprintf(g->Message, "Missing %s file name", topt->type);
- else
- ok= true;
-
- break;
- case TAB_VIR:
- ok= true;
- break;
- default:
- sprintf(g->Message, "Cannot get column info for table type %s", topt->type);
- break;
- } // endif ttp
+ case TAB_JSON:
+ if (!fn && !zfn && !mul)
+ sprintf(g->Message, "Missing %s file name", topt->type);
+ else
+ ok = true;
- // Check for supported catalog function
- if (ok && !(supfnc & fnc)) {
- sprintf(g->Message, "Unsupported catalog function %s for table type %s",
- fncn, topt->type);
- ok= false;
- } // endif supfnc
-
- if (src && fnc != FNC_NO) {
- strcpy(g->Message, "Cannot make catalog table from srcdef");
- ok= false;
- } // endif src
-
- if (ok) {
- char *cnm, *rem, *dft, *xtra, *key, *fmt;
- int i, len, prec, dec, typ, flg;
-
-// if (cat)
-// cat->SetDataPath(g, table_s->db.str);
-// else
-// return HA_ERR_INTERNAL_ERROR; // Should never happen
-
- dpath= SetPath(g, table_s->db.str);
+ break;
+ case TAB_VIR:
+ ok = true;
+ break;
+ default:
+ sprintf(g->Message, "Cannot get column info for table type %s", topt->type);
+ break;
+ } // endif ttp
+
+ // Check for supported catalog function
+ if (ok && !(supfnc & fnc)) {
+ sprintf(g->Message, "Unsupported catalog function %s for table type %s",
+ fncn, topt->type);
+ ok = false;
+ } // endif supfnc
+
+ if (src && fnc != FNC_NO) {
+ strcpy(g->Message, "Cannot make catalog table from srcdef");
+ ok = false;
+ } // endif src
+
+ if (ok) {
+ const char *cnm, *rem;
+ char *dft, *xtra, *key, *fmt;
+ int i, len, prec, dec, typ, flg;
+
+ if (!(dpath = SetPath(g, table_s->db.str))) {
+ rc = HA_ERR_INTERNAL_ERROR;
+ goto err;
+ } // endif dpath
- if (src && ttp != TAB_PIVOT && ttp != TAB_ODBC && ttp != TAB_JDBC) {
- qrp= SrcColumns(g, host, db, user, pwd, src, port);
+ if (src && ttp != TAB_PIVOT && ttp != TAB_ODBC && ttp != TAB_JDBC) {
+ qrp = SrcColumns(g, host, db, user, pwd, src, port);
- if (qrp && ttp == TAB_OCCUR)
- if (OcrSrcCols(g, qrp, col, ocl, rnk)) {
- my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0));
- goto err;
- } // endif OcrSrcCols
+ if (qrp && ttp == TAB_OCCUR)
+ if (OcrSrcCols(g, qrp, col, ocl, rnk)) {
+ rc = HA_ERR_INTERNAL_ERROR;
+ goto err;
+ } // endif OcrSrcCols
- } else switch (ttp) {
- case TAB_DBF:
- qrp= DBFColumns(g, dpath, fn, fnc == FNC_COL);
- break;
+ } else switch (ttp) {
+ case TAB_DBF:
+ qrp = DBFColumns(g, dpath, fn, fnc == FNC_COL);
+ break;
#if defined(ODBC_SUPPORT)
- case TAB_ODBC:
- switch (fnc) {
- case FNC_NO:
- case FNC_COL:
- if (src) {
- qrp= ODBCSrcCols(g, dsn, (char*)src, sop);
- src= NULL; // for next tests
- } else
- qrp= ODBCColumns(g, dsn, shm, tab, NULL,
- mxr, fnc == FNC_COL, sop);
+ case TAB_ODBC:
+ switch (fnc) {
+ case FNC_NO:
+ case FNC_COL:
+ if (src) {
+ qrp = ODBCSrcCols(g, dsn, (char*)src, sop);
+ src = NULL; // for next tests
+ } else
+ qrp = ODBCColumns(g, dsn, shm, tab, NULL,
+ mxr, fnc == FNC_COL, sop);
- break;
- case FNC_TABLE:
- qrp= ODBCTables(g, dsn, shm, tab, NULL, mxr, true, sop);
- break;
- case FNC_DSN:
- qrp= ODBCDataSources(g, mxr, true);
- break;
- case FNC_DRIVER:
- qrp= ODBCDrivers(g, mxr, true);
- break;
- default:
- sprintf(g->Message, "invalid catfunc %s", fncn);
- break;
- } // endswitch info
+ break;
+ case FNC_TABLE:
+ qrp = ODBCTables(g, dsn, shm, tab, NULL, mxr, true, sop);
+ break;
+ case FNC_DSN:
+ qrp = ODBCDataSources(g, mxr, true);
+ break;
+ case FNC_DRIVER:
+ qrp = ODBCDrivers(g, mxr, true);
+ break;
+ default:
+ sprintf(g->Message, "invalid catfunc %s", fncn);
+ break;
+ } // endswitch info
- break;
+ break;
#endif // ODBC_SUPPORT
#if defined(JDBC_SUPPORT)
- case TAB_JDBC:
- switch (fnc) {
- case FNC_NO:
- case FNC_COL:
- if (src) {
- qrp= JDBCSrcCols(g, (char*)src, sjp);
- src= NULL; // for next tests
- } else
- qrp= JDBCColumns(g, shm, tab, NULL, mxr, fnc == FNC_COL, sjp);
+ case TAB_JDBC:
+ switch (fnc) {
+ case FNC_NO:
+ case FNC_COL:
+ if (src) {
+ qrp = JDBCSrcCols(g, (char*)src, sjp);
+ src = NULL; // for next tests
+ } else
+ qrp = JDBCColumns(g, shm, tab, NULL, mxr, fnc == FNC_COL, sjp);
- break;
- case FNC_TABLE:
- qrp= JDBCTables(g, shm, tab, tabtyp, mxr, true, sjp);
- break;
+ break;
+ case FNC_TABLE:
+ qrp = JDBCTables(g, shm, tab, tabtyp, mxr, true, sjp);
+ break;
#if 0
- case FNC_DSN:
- qrp= JDBCDataSources(g, mxr, true);
- break;
+ case FNC_DSN:
+ qrp = JDBCDataSources(g, mxr, true);
+ break;
#endif // 0
- case FNC_DRIVER:
- qrp= JDBCDrivers(g, mxr, true);
- break;
- default:
- sprintf(g->Message, "invalid catfunc %s", fncn);
- break;
- } // endswitch info
+ case FNC_DRIVER:
+ qrp = JDBCDrivers(g, mxr, true);
+ break;
+ default:
+ sprintf(g->Message, "invalid catfunc %s", fncn);
+ break;
+ } // endswitch info
- break;
+ break;
#endif // JDBC_SUPPORT
- case TAB_MYSQL:
- qrp= MyColumns(g, thd, host, db, user, pwd, tab,
- NULL, port, fnc == FNC_COL);
- break;
- case TAB_CSV:
- qrp = CSVColumns(g, dpath, topt, fnc == FNC_COL);
- break;
+ case TAB_MYSQL:
+ qrp = MyColumns(g, thd, host, db, user, pwd, tab,
+ NULL, port, fnc == FNC_COL);
+ break;
+ case TAB_CSV:
+ qrp = CSVColumns(g, dpath, topt, fnc == FNC_COL);
+ break;
#if defined(__WIN__)
- case TAB_WMI:
- qrp= WMIColumns(g, nsp, cls, fnc == FNC_COL);
- break;
+ case TAB_WMI:
+ qrp = WMIColumns(g, nsp, cls, fnc == FNC_COL);
+ break;
#endif // __WIN__
- case TAB_PRX:
- case TAB_TBL:
- case TAB_XCL:
- case TAB_OCCUR:
- bif= fnc == FNC_COL;
- qrp= TabColumns(g, thd, db, tab, bif);
-
- if (!qrp && bif && fnc != FNC_COL) // tab is a view
- qrp= MyColumns(g, thd, host, db, user, pwd, tab, NULL, port, false);
-
- if (qrp && ttp == TAB_OCCUR && fnc != FNC_COL)
- if (OcrColumns(g, qrp, col, ocl, rnk)) {
- my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0));
- goto err;
- } // endif OcrColumns
+ case TAB_PRX:
+ case TAB_TBL:
+ case TAB_XCL:
+ case TAB_OCCUR:
+ bif = fnc == FNC_COL;
+ qrp = TabColumns(g, thd, db, tab, bif);
+
+ if (!qrp && bif && fnc != FNC_COL) // tab is a view
+ qrp = MyColumns(g, thd, host, db, user, pwd, tab, NULL, port, false);
+
+ if (qrp && ttp == TAB_OCCUR && fnc != FNC_COL)
+ if (OcrColumns(g, qrp, col, ocl, rnk)) {
+ rc = HA_ERR_INTERNAL_ERROR;
+ goto err;
+ } // endif OcrColumns
- break;
+ break;
#if defined(PIVOT_SUPPORT)
- case TAB_PIVOT:
- qrp= PivotColumns(g, tab, src, pic, fcl, skc, host, db, user, pwd, port);
- break;
+ case TAB_PIVOT:
+ qrp = PivotColumns(g, tab, src, pic, fcl, skc, host, db, user, pwd, port);
+ break;
#endif // PIVOT_SUPPORT
- case TAB_VIR:
- qrp= VirColumns(g, fnc == FNC_COL);
- break;
- case TAB_JSON:
- qrp= JSONColumns(g, (char*)db, topt, fnc == FNC_COL);
- break;
+ case TAB_VIR:
+ qrp = VirColumns(g, fnc == FNC_COL);
+ break;
+ case TAB_JSON:
+ qrp = JSONColumns(g, (char*)db, topt, fnc == FNC_COL);
+ break;
#if defined(LIBXML2_SUPPORT) || defined(DOMDOC_SUPPORT)
- case TAB_XML:
- qrp= XMLColumns(g, (char*)db, tab, topt, fnc == FNC_COL);
- break;
+ case TAB_XML:
+ qrp = XMLColumns(g, (char*)db, tab, topt, fnc == FNC_COL);
+ break;
#endif // LIBXML2_SUPPORT || DOMDOC_SUPPORT
- case TAB_OEM:
- qrp= OEMColumns(g, topt, tab, (char*)db, fnc == FNC_COL);
- break;
- default:
- strcpy(g->Message, "System error during assisted discovery");
- break;
- } // endswitch ttp
-
- if (!qrp) {
- my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0));
- goto err;
- } // endif !qrp
-
- if (fnc != FNC_NO || src || ttp == TAB_PIVOT) {
- // Catalog like table
- for (crp= qrp->Colresp; !rc && crp; crp= crp->Next) {
- cnm= (ttp == TAB_PIVOT) ? crp->Name : encode(g, crp->Name);
- typ= crp->Type;
- len= crp->Length;
- dec= crp->Prec;
- flg= crp->Flag;
- v= (crp->Kdata->IsUnsigned()) ? 'U' : crp->Var;
- tm= (crp->Kdata->IsNullable()) ? 0 : NOT_NULL_FLAG;
-
- if (!len && typ == TYPE_STRING)
- len= 256; // STRBLK's have 0 length
-
- // Now add the field
- if (add_field(&sql, cnm, typ, len, dec, NULL, tm,
- NULL, NULL, NULL, NULL, flg, dbf, v))
- rc= HA_ERR_OUT_OF_MEM;
- } // endfor crp
-
- } else {
- char *schem= NULL;
- char *tn= NULL;
-
- // Not a catalog table
- if (!qrp->Nblin) {
- if (tab)
- sprintf(g->Message, "Cannot get columns from %s", tab);
- else
- strcpy(g->Message, "Fail to retrieve columns");
-
- my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0));
- goto err;
- } // endif !nblin
-
- for (i= 0; !rc && i < qrp->Nblin; i++) {
- typ= len= prec= dec= 0;
- tm= NOT_NULL_FLAG;
- cnm= (char*)"noname";
- dft= xtra= key= fmt= tn= NULL;
- v= ' ';
- rem= NULL;
-
- for (crp= qrp->Colresp; crp; crp= crp->Next)
- switch (crp->Fld) {
- case FLD_NAME:
- if (ttp == TAB_PRX ||
- (ttp == TAB_CSV && topt->data_charset &&
- (!stricmp(topt->data_charset, "UTF8") ||
- !stricmp(topt->data_charset, "UTF-8"))))
- cnm= crp->Kdata->GetCharValue(i);
- else
- cnm= encode(g, crp->Kdata->GetCharValue(i));
-
- break;
- case FLD_TYPE:
- typ= crp->Kdata->GetIntValue(i);
- v = (crp->Nulls) ? crp->Nulls[i] : 0;
- break;
- case FLD_TYPENAME:
- tn= crp->Kdata->GetCharValue(i);
- break;
- case FLD_PREC:
- // PREC must be always before LENGTH
- len= prec= crp->Kdata->GetIntValue(i);
- break;
- case FLD_LENGTH:
- len= crp->Kdata->GetIntValue(i);
- break;
- case FLD_SCALE:
- dec = (!crp->Kdata->IsNull(i)) ? crp->Kdata->GetIntValue(i) : -1;
- break;
- case FLD_NULL:
- if (crp->Kdata->GetIntValue(i))
- tm= 0; // Nullable
-
- break;
- case FLD_FORMAT:
- fmt= (crp->Kdata) ? crp->Kdata->GetCharValue(i) : NULL;
- break;
- case FLD_REM:
- rem= crp->Kdata->GetCharValue(i);
- break;
-// case FLD_CHARSET:
- // No good because remote table is already translated
-// if (*(csn= crp->Kdata->GetCharValue(i)))
-// cs= get_charset_by_name(csn, 0);
-
-// break;
- case FLD_DEFAULT:
- dft= crp->Kdata->GetCharValue(i);
- break;
- case FLD_EXTRA:
- xtra= crp->Kdata->GetCharValue(i);
-
- // Auto_increment is not supported yet
- if (!stricmp(xtra, "AUTO_INCREMENT"))
- xtra= NULL;
-
- break;
- case FLD_KEY:
- if (ttp == TAB_VIR)
- key= crp->Kdata->GetCharValue(i);
+ case TAB_OEM:
+ qrp = OEMColumns(g, topt, tab, (char*)db, fnc == FNC_COL);
+ break;
+ default:
+ strcpy(g->Message, "System error during assisted discovery");
+ break;
+ } // endswitch ttp
- break;
- case FLD_SCHEM:
+ if (!qrp) {
+ rc = HA_ERR_INTERNAL_ERROR;
+ goto err;
+ } // endif !qrp
+
+ if (fnc != FNC_NO || src || ttp == TAB_PIVOT) {
+ // Catalog like table
+ for (crp = qrp->Colresp; !rc && crp; crp = crp->Next) {
+ cnm = (ttp == TAB_PIVOT) ? crp->Name : encode(g, crp->Name);
+ typ = crp->Type;
+ len = crp->Length;
+ dec = crp->Prec;
+ flg = crp->Flag;
+ v = (crp->Kdata->IsUnsigned()) ? 'U' : crp->Var;
+ tm = (crp->Kdata->IsNullable()) ? 0 : NOT_NULL_FLAG;
+
+ if (!len && typ == TYPE_STRING)
+ len = 256; // STRBLK's have 0 length
+
+ // Now add the field
+ if (add_field(&sql, cnm, typ, len, dec, NULL, tm,
+ NULL, NULL, NULL, NULL, flg, dbf, v))
+ rc = HA_ERR_OUT_OF_MEM;
+ } // endfor crp
+
+ } else {
+ char *schem = NULL;
+ char *tn = NULL;
+
+ // Not a catalog table
+ if (!qrp->Nblin) {
+ if (tab)
+ sprintf(g->Message, "Cannot get columns from %s", tab);
+ else
+ strcpy(g->Message, "Fail to retrieve columns");
+
+ rc = HA_ERR_INTERNAL_ERROR;
+ goto err;
+ } // endif !nblin
+
+ for (i = 0; !rc && i < qrp->Nblin; i++) {
+ typ = len = prec = dec = 0;
+ tm = NOT_NULL_FLAG;
+ cnm = (char*)"noname";
+ dft = xtra = key = fmt = tn = NULL;
+ v = ' ';
+ rem = NULL;
+
+ for (crp = qrp->Colresp; crp; crp = crp->Next)
+ switch (crp->Fld) {
+ case FLD_NAME:
+ if (ttp == TAB_PRX ||
+ (ttp == TAB_CSV && topt->data_charset &&
+ (!stricmp(topt->data_charset, "UTF8") ||
+ !stricmp(topt->data_charset, "UTF-8"))))
+ cnm = crp->Kdata->GetCharValue(i);
+ else
+ cnm = encode(g, crp->Kdata->GetCharValue(i));
+
+ break;
+ case FLD_TYPE:
+ typ = crp->Kdata->GetIntValue(i);
+ v = (crp->Nulls) ? crp->Nulls[i] : 0;
+ break;
+ case FLD_TYPENAME:
+ tn = crp->Kdata->GetCharValue(i);
+ break;
+ case FLD_PREC:
+ // PREC must be always before LENGTH
+ len = prec = crp->Kdata->GetIntValue(i);
+ break;
+ case FLD_LENGTH:
+ len = crp->Kdata->GetIntValue(i);
+ break;
+ case FLD_SCALE:
+ dec = (!crp->Kdata->IsNull(i)) ? crp->Kdata->GetIntValue(i) : -1;
+ break;
+ case FLD_NULL:
+ if (crp->Kdata->GetIntValue(i))
+ tm = 0; // Nullable
+
+ break;
+ case FLD_FORMAT:
+ fmt = (crp->Kdata) ? crp->Kdata->GetCharValue(i) : NULL;
+ break;
+ case FLD_REM:
+ rem = crp->Kdata->GetCharValue(i);
+ break;
+ // case FLD_CHARSET:
+ // No good because remote table is already translated
+ // if (*(csn= crp->Kdata->GetCharValue(i)))
+ // cs= get_charset_by_name(csn, 0);
+
+ // break;
+ case FLD_DEFAULT:
+ dft = crp->Kdata->GetCharValue(i);
+ break;
+ case FLD_EXTRA:
+ xtra = crp->Kdata->GetCharValue(i);
+
+ // Auto_increment is not supported yet
+ if (!stricmp(xtra, "AUTO_INCREMENT"))
+ xtra = NULL;
+
+ break;
+ case FLD_KEY:
+ if (ttp == TAB_VIR)
+ key = crp->Kdata->GetCharValue(i);
+
+ break;
+ case FLD_SCHEM:
#if defined(ODBC_SUPPORT) || defined(JDBC_SUPPORT)
- if ((ttp == TAB_ODBC || ttp == TAB_JDBC) && crp->Kdata) {
- if (schem && stricmp(schem, crp->Kdata->GetCharValue(i))) {
- sprintf(g->Message,
- "Several %s tables found, specify DBNAME", tab);
- my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0));
- goto err;
- } else if (!schem)
- schem= crp->Kdata->GetCharValue(i);
-
- } // endif ttp
+ if ((ttp == TAB_ODBC || ttp == TAB_JDBC) && crp->Kdata) {
+ if (schem && stricmp(schem, crp->Kdata->GetCharValue(i))) {
+ sprintf(g->Message,
+ "Several %s tables found, specify DBNAME", tab);
+ rc = HA_ERR_INTERNAL_ERROR;
+ goto err;
+ } else if (!schem)
+ schem = crp->Kdata->GetCharValue(i);
+
+ } // endif ttp
#endif // ODBC_SUPPORT || JDBC_SUPPORT
- default:
- break; // Ignore
- } // endswitch Fld
+ default:
+ break; // Ignore
+ } // endswitch Fld
#if defined(ODBC_SUPPORT)
- if (ttp == TAB_ODBC) {
- int plgtyp;
- bool w= false; // Wide character type
-
- // typ must be PLG type, not SQL type
- if (!(plgtyp= TranslateSQLType(typ, dec, prec, v, w))) {
- 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;
-
- switch (typ) {
- case TYPE_STRING:
- if (w) {
- sprintf(g->Message, "Column %s is wide characters", cnm);
- push_warning(thd, Sql_condition::WARN_LEVEL_NOTE, 0, g->Message);
- } // endif w
-
- break;
- case TYPE_DOUBLE:
- // Some data sources do not count dec in length (prec)
- prec += (dec + 2); // To be safe
- break;
- case TYPE_DECIM:
- prec= len;
- break;
- default:
- dec= 0;
- } // endswitch typ
-
- } else
-#endif // ODBC_SUPPORT
-#if defined(JDBC_SUPPORT)
- if (ttp == TAB_JDBC) {
+ if (ttp == TAB_ODBC) {
int plgtyp;
+ bool w = false; // Wide character type
// typ must be PLG type, not SQL type
- if (!(plgtyp= TranslateJDBCType(typ, tn, dec, prec, v))) {
+ if (!(plgtyp = TranslateSQLType(typ, dec, prec, v, w))) {
if (GetTypeConv() == TPC_SKIP) {
// Skip this column
sprintf(g->Message, "Column %s skipped (unsupported type %d)",
@@ -5882,55 +5862,107 @@ static int connect_assisted_discovery(handlerton *, THD* thd,
continue;
} else {
sprintf(g->Message, "Unsupported SQL type %d", typ);
- my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0));
+ rc = HA_ERR_INTERNAL_ERROR;
goto err;
} // endif type_conv
} else
- typ= plgtyp;
+ typ = plgtyp;
switch (typ) {
- case TYPE_DOUBLE:
- case TYPE_DECIM:
- // Some data sources do not count dec in length (prec)
- prec += (dec + 2); // To be safe
- break;
- default:
- dec= 0;
+ case TYPE_STRING:
+ if (w) {
+ sprintf(g->Message, "Column %s is wide characters", cnm);
+ push_warning(thd, Sql_condition::WARN_LEVEL_NOTE, 0, g->Message);
+ } // endif w
+
+ break;
+ case TYPE_DOUBLE:
+ // Some data sources do not count dec in length (prec)
+ prec += (dec + 2); // To be safe
+ break;
+ case TYPE_DECIM:
+ prec = len;
+ break;
+ default:
+ dec = 0;
} // endswitch typ
} else
#endif // ODBC_SUPPORT
- // Make the arguments as required by add_fields
- if (typ == TYPE_DOUBLE)
- prec= len;
+#if defined(JDBC_SUPPORT)
+ if (ttp == TAB_JDBC) {
+ int plgtyp;
+
+ // typ must be PLG type, not SQL type
+ if (!(plgtyp = TranslateJDBCType(typ, tn, dec, prec, v))) {
+ 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);
+ rc = HA_ERR_INTERNAL_ERROR;
+ goto err;
+ } // endif type_conv
+
+ } else
+ typ = plgtyp;
+
+ switch (typ) {
+ case TYPE_DOUBLE:
+ case TYPE_DECIM:
+ // Some data sources do not count dec in length (prec)
+ prec += (dec + 2); // To be safe
+ break;
+ default:
+ dec = 0;
+ } // endswitch typ
- if (typ == TYPE_DATE)
- prec= 0;
+ } else
+#endif // ODBC_SUPPORT
+ // Make the arguments as required by add_fields
+ if (typ == TYPE_DOUBLE)
+ prec = len;
- // Now add the field
- if (add_field(&sql, cnm, typ, prec, dec, key, tm, rem, dft, xtra,
- fmt, 0, dbf, v))
- rc= HA_ERR_OUT_OF_MEM;
- } // endfor i
+ if (typ == TYPE_DATE)
+ prec = 0;
- } // endif fnc
+ // Now add the field
+ if (add_field(&sql, cnm, typ, prec, dec, key, tm, rem, dft, xtra,
+ fmt, 0, dbf, v))
+ rc = HA_ERR_OUT_OF_MEM;
+ } // endfor i
- if (!rc)
- rc= init_table_share(thd, table_s, create_info, &sql);
+ } // endif fnc
- g->jump_level--;
- PopUser(xp);
- return rc;
- } // endif ok
+ if (!rc)
+ rc = init_table_share(thd, table_s, create_info, &sql);
- my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0));
+ //g->jump_level--;
+ //PopUser(xp);
+ //return rc;
+ } else {
+ rc = HA_ERR_UNSUPPORTED;
+ } // endif ok
+
+ } catch (int n) {
+ if (trace)
+ htrc("Exception %d: %s\n", n, g->Message);
+ rc = HA_ERR_INTERNAL_ERROR;
+ } catch (const char *msg) {
+ strcpy(g->Message, msg);
+ rc = HA_ERR_INTERNAL_ERROR;
+ } // end catch
err:
- g->jump_level--;
- jer:
+ if (rc)
+ my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0));
+
PopUser(xp);
- return HA_ERR_INTERNAL_ERROR;
+ return rc;
} // end of connect_assisted_discovery
/**
@@ -6095,8 +6127,8 @@ int ha_connect::create(const char *name, TABLE *table_arg,
if (!part_info)
#endif // WITH_PARTITION_STORAGE_ENGINE
{const char *src= options->srcdef;
- char *host, *db, *tab= (char*)options->tabname;
- int port;
+ PCSZ host, db, tab= options->tabname;
+ int port;
host= GetListOption(g, "host", options->oplist, NULL);
db= GetStringOption("database", NULL);
@@ -6140,8 +6172,8 @@ int ha_connect::create(const char *name, TABLE *table_arg,
} // endswitch ttp
if (type == TAB_XML) {
- bool dom; // True: MS-DOM, False libxml2
- char *xsup= GetListOption(g, "Xmlsup", options->oplist, "*");
+ bool dom; // True: MS-DOM, False libxml2
+ PCSZ xsup= GetListOption(g, "Xmlsup", options->oplist, "*");
// Note that if no support is specified, the default is MS-DOM
// on Windows and libxml2 otherwise
@@ -6401,15 +6433,15 @@ int ha_connect::create(const char *name, TABLE *table_arg,
if (options->zipped) {
// Check whether the zip entry must be made from a file
- char *fn = GetListOption(g, "Load", options->oplist, NULL);
+ PCSZ fn = GetListOption(g, "Load", options->oplist, NULL);
if (fn) {
- char zbuf[_MAX_PATH], buf[_MAX_PATH], dbpath[_MAX_PATH];
- char *entry = GetListOption(g, "Entry", options->oplist, NULL);
- char *a = GetListOption(g, "Append", options->oplist, "NO");
- bool append = *a == '1' || *a == 'Y' || *a == 'y' || !stricmp(a, "ON");
- char *m = GetListOption(g, "Mulentries", options->oplist, "NO");
- bool mul = *m == '1' || *m == 'Y' || *m == 'y' || !stricmp(m, "ON");
+ char zbuf[_MAX_PATH], buf[_MAX_PATH], dbpath[_MAX_PATH];
+ PCSZ entry = GetListOption(g, "Entry", options->oplist, NULL);
+ PCSZ a = GetListOption(g, "Append", options->oplist, "NO");
+ bool append = *a == '1' || *a == 'Y' || *a == 'y' || !stricmp(a, "ON");
+ PCSZ m = GetListOption(g, "Mulentries", options->oplist, "NO");
+ bool mul = *m == '1' || *m == 'Y' || *m == 'y' || !stricmp(m, "ON");
if (!entry && !mul) {
my_message(ER_UNKNOWN_ERROR, "Missing entry name", MYF(0));
@@ -6477,11 +6509,10 @@ int ha_connect::create(const char *name, TABLE *table_arg,
PDBUSER dup= PlgGetUser(g);
PCATLG cat= (dup) ? dup->Catalog : NULL;
- SetDataPath(g, table_arg->s->db.str);
-
- if (cat) {
-// cat->SetDataPath(g, table_arg->s->db.str);
-
+ if (SetDataPath(g, table_arg->s->db.str)) {
+ my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0));
+ rc = HA_ERR_INTERNAL_ERROR;
+ } else if (cat) {
#if defined(WITH_PARTITION_STORAGE_ENGINE)
if (part_info)
strncpy(partname,
@@ -6537,8 +6568,9 @@ bool ha_connect::FileExists(const char *fn, bool bf)
return true;
if (table) {
- char *s, tfn[_MAX_PATH], filename[_MAX_PATH], path[_MAX_PATH];
- bool b= false;
+ const char *s;
+ char tfn[_MAX_PATH], filename[_MAX_PATH], path[_MAX_PATH];
+ bool b= false;
int n;
struct stat info;
@@ -6595,9 +6627,9 @@ bool ha_connect::CheckString(const char *str1, const char *str2)
/**
check whether a string option have changed
*/
-bool ha_connect::SameString(TABLE *tab, char *opn)
+bool ha_connect::SameString(TABLE *tab, PCSZ opn)
{
- char *str1, *str2;
+ PCSZ str1, str2;
tshp= tab->s; // The altered table
str1= GetStringOption(opn);
@@ -6609,7 +6641,7 @@ bool ha_connect::SameString(TABLE *tab, char *opn)
/**
check whether a Boolean option have changed
*/
-bool ha_connect::SameBool(TABLE *tab, char *opn)
+bool ha_connect::SameBool(TABLE *tab, PCSZ opn)
{
bool b1, b2;
@@ -6623,7 +6655,7 @@ bool ha_connect::SameBool(TABLE *tab, char *opn)
/**
check whether an integer option have changed
*/
-bool ha_connect::SameInt(TABLE *tab, char *opn)
+bool ha_connect::SameInt(TABLE *tab, PCSZ opn)
{
int i1, i2;
@@ -6802,7 +6834,7 @@ ha_connect::check_if_supported_inplace_alter(TABLE *altered_table,
// Conversion to outward table is only allowed for file based
// tables whose file does not exist.
tshp= altered_table->s;
- char *fn= GetStringOption("filename");
+ PCSZ fn= GetStringOption("filename");
tshp= NULL;
if (FileExists(fn, false)) {
@@ -7047,10 +7079,10 @@ maria_declare_plugin(connect)
PLUGIN_LICENSE_GPL,
connect_init_func, /* Plugin Init */
connect_done_func, /* Plugin Deinit */
- 0x0105, /* version number (1.05) */
+ 0x0106, /* version number (1.05) */
NULL, /* status variables */
connect_system_variables, /* system variables */
- "1.05.0003", /* string version */
- MariaDB_PLUGIN_MATURITY_GAMMA /* maturity */
+ "1.06.0001", /* string version */
+ MariaDB_PLUGIN_MATURITY_BETA /* maturity */
}
maria_declare_plugin_end;
diff --git a/storage/connect/ha_connect.h b/storage/connect/ha_connect.h
index cb15d371b5c..8d8307b4bd1 100644
--- a/storage/connect/ha_connect.h
+++ b/storage/connect/ha_connect.h
@@ -61,7 +61,7 @@ public:
oldopn= newopn= NULL;
oldpix= newpix= NULL;}
- inline char *SetName(PGLOBAL g, char *name) {return PlugDup(g, name);}
+ inline char *SetName(PGLOBAL g, PCSZ name) {return PlugDup(g, name);}
bool oldsep; // Sepindex before create/alter
bool newsep; // Sepindex after create/alter
@@ -168,18 +168,18 @@ public:
static bool connect_init(void);
static bool connect_end(void);
TABTYPE GetRealType(PTOS pos= NULL);
- char *GetRealString(const char *s);
- char *GetStringOption(char *opname, char *sdef= NULL);
+ char *GetRealString(PCSZ s);
+ PCSZ GetStringOption(PCSZ opname, PCSZ sdef= NULL);
PTOS GetTableOptionStruct(TABLE_SHARE *s= NULL);
- bool GetBooleanOption(char *opname, bool bdef);
- bool SetBooleanOption(char *opname, bool b);
- int GetIntegerOption(char *opname);
- bool GetIndexOption(KEY *kp, char *opname);
- bool CheckString(const char *str1, const char *str2);
- bool SameString(TABLE *tab, char *opn);
- bool SetIntegerOption(char *opname, int n);
- bool SameInt(TABLE *tab, char *opn);
- bool SameBool(TABLE *tab, char *opn);
+ bool GetBooleanOption(PCSZ opname, bool bdef);
+ bool SetBooleanOption(PCSZ opname, bool b);
+ int GetIntegerOption(PCSZ opname);
+ bool GetIndexOption(KEY *kp, PCSZ opname);
+ bool CheckString(PCSZ str1, PCSZ str2);
+ bool SameString(TABLE *tab, PCSZ opn);
+ bool SetIntegerOption(PCSZ opname, int n);
+ bool SameInt(TABLE *tab, PCSZ opn);
+ bool SameBool(TABLE *tab, PCSZ opn);
bool FileExists(const char *fn, bool bf);
bool NoFieldOptionChange(TABLE *tab);
PFOS GetFieldOptionStruct(Field *fp);
@@ -187,8 +187,8 @@ public:
PXOS GetIndexOptionStruct(KEY *kp);
PIXDEF GetIndexInfo(TABLE_SHARE *s= NULL);
bool CheckVirtualIndex(TABLE_SHARE *s);
- const char *GetDBName(const char *name);
- const char *GetTableName(void);
+ PCSZ GetDBName(PCSZ name);
+ PCSZ GetTableName(void);
char *GetPartName(void);
//int GetColNameLen(Field *fp);
//char *GetColName(Field *fp);
@@ -197,9 +197,9 @@ public:
bool IsSameIndex(PIXDEF xp1, PIXDEF xp2);
bool IsPartitioned(void);
bool IsUnique(uint n);
- char *GetDataPath(void) {return (char*)datapath;}
+ PCSZ GetDataPath(void) {return datapath;}
- void SetDataPath(PGLOBAL g, const char *path);
+ bool SetDataPath(PGLOBAL g, PCSZ path);
PTDB GetTDB(PGLOBAL g);
int OpenTable(PGLOBAL g, bool del= false);
bool CheckColumnList(PGLOBAL g);
@@ -513,7 +513,7 @@ protected:
ulong hnum; // The number of this handler
query_id_t valid_query_id; // The one when tdbp was allocated
query_id_t creat_query_id; // The one when handler was allocated
- char *datapath; // Is the Path of DB data directory
+ PCSZ datapath; // Is the Path of DB data directory
PTDB tdbp; // To table class object
PVAL sdvalin1; // Used to convert date values
PVAL sdvalin2; // Used to convert date values
diff --git a/storage/connect/jdbccat.h b/storage/connect/jdbccat.h
index 7108aa376ce..0b87df8bb51 100644
--- a/storage/connect/jdbccat.h
+++ b/storage/connect/jdbccat.h
@@ -4,10 +4,10 @@
typedef struct jdbc_parms {
int CheckSize(int rows);
- char *Driver; // JDBC driver
- char *Url; // Driver URL
- char *User; // User connect info
- char *Pwd; // Password connect info
+ PCSZ Driver; // JDBC driver
+ PCSZ Url; // Driver URL
+ PCSZ User; // User connect info
+ PCSZ Pwd; // Password connect info
//char *Properties; // Connection property list
//int Cto; // Connect timeout
//int Qto; // Query timeout
@@ -19,12 +19,12 @@ typedef struct jdbc_parms {
/* JDBC catalog function prototypes. */
/***********************************************************************/
#if defined(PROMPT_OK)
-char *JDBCCheckConnection(PGLOBAL g, char *dsn, int cop);
+char *JDBCCheckConnection(PGLOBAL g, PCSZ dsn, int cop);
#endif // PROMPT_OK
//PQRYRES JDBCDataSources(PGLOBAL g, int maxres, bool info);
-PQRYRES JDBCColumns(PGLOBAL g, char *db, char *table,
- char *colpat, int maxres, bool info, PJPARM sop);
-PQRYRES JDBCSrcCols(PGLOBAL g, char *src, PJPARM sop);
-PQRYRES JDBCTables(PGLOBAL g, char *db, char *tabpat,
- char *tabtyp, int maxres, bool info, PJPARM sop);
+PQRYRES JDBCColumns(PGLOBAL g, PCSZ db, PCSZ table,
+ PCSZ colpat, int maxres, bool info, PJPARM sop);
+PQRYRES JDBCSrcCols(PGLOBAL g, PCSZ src, PJPARM sop);
+PQRYRES JDBCTables(PGLOBAL g, PCSZ db, PCSZ tabpat,
+ PCSZ tabtyp, int maxres, bool info, PJPARM sop);
PQRYRES JDBCDrivers(PGLOBAL g, int maxres, bool info);
diff --git a/storage/connect/jdbconn.cpp b/storage/connect/jdbconn.cpp
index c1d077406b7..f162a7ae645 100644
--- a/storage/connect/jdbconn.cpp
+++ b/storage/connect/jdbconn.cpp
@@ -189,8 +189,8 @@ int TranslateJDBCType(int stp, char *tn, int prec, int& len, char& v)
/***********************************************************************/
/* Allocate the structure used to refer to the result set. */
/***********************************************************************/
-static JCATPARM *AllocCatInfo(PGLOBAL g, JCATINFO fid, char *db,
- char *tab, PQRYRES qrp)
+static JCATPARM *AllocCatInfo(PGLOBAL g, JCATINFO fid, PCSZ db,
+ PCSZ tab, PQRYRES qrp)
{
JCATPARM *cap;
@@ -213,7 +213,7 @@ static JCATPARM *AllocCatInfo(PGLOBAL g, JCATINFO fid, char *db,
/* JDBCColumns: constructs the result blocks containing all columns */
/* of a JDBC table that will be retrieved by GetData commands. */
/***********************************************************************/
-PQRYRES JDBCColumns(PGLOBAL g, char *db, char *table, char *colpat,
+PQRYRES JDBCColumns(PGLOBAL g, PCSZ db, PCSZ table, PCSZ colpat,
int maxres, bool info, PJPARM sjp)
{
int buftyp[] = {TYPE_STRING, TYPE_STRING, TYPE_STRING, TYPE_STRING,
@@ -316,7 +316,7 @@ PQRYRES JDBCColumns(PGLOBAL g, char *db, char *table, char *colpat,
/* JDBCSrcCols: constructs the result blocks containing the */
/* description of all the columns of a Srcdef option. */
/**************************************************************************/
-PQRYRES JDBCSrcCols(PGLOBAL g, char *src, PJPARM sjp)
+PQRYRES JDBCSrcCols(PGLOBAL g, PCSZ src, PJPARM sjp)
{
char *sqry;
PQRYRES qrp;
@@ -330,7 +330,7 @@ PQRYRES JDBCSrcCols(PGLOBAL g, char *src, PJPARM sjp)
sqry = (char*)PlugSubAlloc(g, NULL, strlen(src) + 2);
sprintf(sqry, src, "1=1"); // dummy where clause
} else
- sqry = src;
+ sqry = (char*)src;
qrp = jcp->GetMetaData(g, sqry);
jcp->Close();
@@ -341,7 +341,7 @@ PQRYRES JDBCSrcCols(PGLOBAL g, char *src, PJPARM sjp)
/* JDBCTables: constructs the result blocks containing all tables in */
/* an JDBC database that will be retrieved by GetData commands. */
/**************************************************************************/
-PQRYRES JDBCTables(PGLOBAL g, char *db, char *tabpat, char *tabtyp,
+PQRYRES JDBCTables(PGLOBAL g, PCSZ db, PCSZ tabpat, PCSZ tabtyp,
int maxres, bool info, PJPARM sjp)
{
int buftyp[] = {TYPE_STRING, TYPE_STRING, TYPE_STRING,
@@ -1059,7 +1059,7 @@ int JDBConn::Open(PJPARM sop)
/***********************************************************************/
/* Execute an SQL command. */
/***********************************************************************/
-int JDBConn::ExecSQLcommand(char *sql)
+int JDBConn::ExecSQLcommand(PCSZ sql)
{
int rc;
jint n;
@@ -1142,7 +1142,7 @@ int JDBConn::Fetch(int pos)
/***********************************************************************/
/* Restart from beginning of result set */
/***********************************************************************/
-int JDBConn::Rewind(char *sql)
+int JDBConn::Rewind(PCSZ sql)
{
int rbuf = -1;
@@ -1200,7 +1200,7 @@ void JDBConn::SetColumnValue(int rank, PSZ name, PVAL val)
if (rank == 0)
if (!name || (jn = env->NewStringUTF(name)) == nullptr) {
sprintf(g->Message, "Fail to allocate jstring %s", SVP(name));
- longjmp(g->jumper[g->jump_level], TYPE_AM_JDBC);
+ throw TYPE_AM_JDBC;
} // endif name
// Returns 666 is case of error
@@ -1208,7 +1208,7 @@ void JDBConn::SetColumnValue(int rank, PSZ name, PVAL val)
if (Check((ctyp == 666) ? -1 : 1)) {
sprintf(g->Message, "Getting ctyp: %s", Msg);
- longjmp(g->jumper[g->jump_level], TYPE_AM_JDBC);
+ throw TYPE_AM_JDBC;
} // endif Check
if (val->GetNullable())
@@ -1227,7 +1227,8 @@ void JDBConn::SetColumnValue(int rank, PSZ name, PVAL val)
case 12: // VARCHAR
case -1: // LONGVARCHAR
case 1: // CHAR
- if (jb)
+ case 3: // DECIMAL
+ if (jb && ctyp != 3)
cn = (jstring)jb;
else if (!gmID(g, chrfldid, "StringField", "(ILjava/lang/String;)Ljava/lang/String;"))
cn = (jstring)env->CallObjectMethod(job, chrfldid, (jint)rank, jn);
@@ -1253,7 +1254,7 @@ void JDBConn::SetColumnValue(int rank, PSZ name, PVAL val)
break;
case 8: // DOUBLE
case 2: // NUMERIC
- case 3: // DECIMAL
+//case 3: // DECIMAL
if (!gmID(g, dblfldid, "DoubleField", "(ILjava/lang/String;)D"))
val->SetValue((double)env->CallDoubleMethod(job, dblfldid, rank, jn));
else
@@ -1314,7 +1315,7 @@ void JDBConn::SetColumnValue(int rank, PSZ name, PVAL val)
env->DeleteLocalRef(jn);
sprintf(g->Message, "SetColumnValue: %s rank=%d ctyp=%d", Msg, rank, (int)ctyp);
- longjmp(g->jumper[g->jump_level], TYPE_AM_JDBC);
+ throw TYPE_AM_JDBC;
} // endif Check
if (rank == 0)
@@ -1325,7 +1326,7 @@ void JDBConn::SetColumnValue(int rank, PSZ name, PVAL val)
/***********************************************************************/
/* Prepare an SQL statement for insert. */
/***********************************************************************/
-bool JDBConn::PrepareSQL(char *sql)
+bool JDBConn::PrepareSQL(PCSZ sql)
{
bool b = true;
PGLOBAL& g = m_G;
@@ -1348,7 +1349,7 @@ bool JDBConn::PrepareSQL(char *sql)
/***********************************************************************/
/* Execute an SQL query that returns a result set. */
/***********************************************************************/
-int JDBConn::ExecuteQuery(char *sql)
+int JDBConn::ExecuteQuery(PCSZ sql)
{
int rc = RC_FX;
jint ncol;
@@ -1376,7 +1377,7 @@ int JDBConn::ExecuteQuery(char *sql)
/***********************************************************************/
/* Execute an SQL query and get the affected rows. */
/***********************************************************************/
-int JDBConn::ExecuteUpdate(char *sql)
+int JDBConn::ExecuteUpdate(PCSZ sql)
{
int rc = RC_FX;
jint n;
@@ -1404,7 +1405,7 @@ int JDBConn::ExecuteUpdate(char *sql)
/***********************************************************************/
/* Get the number of lines of the result set. */
/***********************************************************************/
-int JDBConn::GetResultSize(char *sql, JDBCCOL *colp)
+int JDBConn::GetResultSize(PCSZ sql, JDBCCOL *colp)
{
int rc, n = 0;
@@ -1642,7 +1643,7 @@ bool JDBConn::SetParam(JDBCCOL *colp)
/* GetMetaData: constructs the result blocks containing the */
/* description of all the columns of an SQL command. */
/**************************************************************************/
- PQRYRES JDBConn::GetMetaData(PGLOBAL g, char *src)
+ PQRYRES JDBConn::GetMetaData(PGLOBAL g, PCSZ src)
{
static int buftyp[] = {TYPE_STRING, TYPE_INT, TYPE_INT,
TYPE_INT, TYPE_INT};
@@ -1844,7 +1845,7 @@ bool JDBConn::SetParam(JDBCCOL *colp)
PGLOBAL& g = m_G;
// void *buffer;
int i, ncol;
- PSZ fnc = "Unknown";
+ PCSZ fnc = "Unknown";
uint n;
short len, tp;
int crow = 0;
diff --git a/storage/connect/jdbconn.h b/storage/connect/jdbconn.h
index 9d428142839..73271c8f5be 100644
--- a/storage/connect/jdbconn.h
+++ b/storage/connect/jdbconn.h
@@ -46,9 +46,9 @@ enum JCATINFO {
typedef struct tagJCATPARM {
JCATINFO Id; // Id to indicate function
PQRYRES Qrp; // Result set pointer
- char *DB; // Database (Schema)
- char *Tab; // Table name or pattern
- char *Pat; // Table type or column pattern
+ PCSZ DB; // Database (Schema)
+ PCSZ Tab; // Table name or pattern
+ PCSZ Pat; // Table type or column pattern
} JCATPARM;
typedef jint(JNICALL *CRTJVM) (JavaVM **, void **, void *);
@@ -77,7 +77,7 @@ public:
JDBConn(PGLOBAL g, TDBJDBC *tdbp);
int Open(PJPARM sop);
- int Rewind(char *sql);
+ int Rewind(PCSZ sql);
void Close(void);
PQRYRES AllocateResult(PGLOBAL g);
@@ -96,19 +96,19 @@ public:
//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, JDBCCOL *colp);
- int ExecuteQuery(char *sql);
- int ExecuteUpdate(char *sql);
+ int GetResultSize(PCSZ sql, JDBCCOL *colp);
+ int ExecuteQuery(PCSZ sql);
+ int ExecuteUpdate(PCSZ sql);
int Fetch(int pos = 0);
- bool PrepareSQL(char *sql);
+ bool PrepareSQL(PCSZ sql);
int ExecuteSQL(void);
bool SetParam(JDBCCOL *colp);
- int ExecSQLcommand(char *sql);
+ int ExecSQLcommand(PCSZ sql);
void SetColumnValue(int rank, PSZ name, PVAL val);
int GetCatInfo(JCATPARM *cap);
//bool GetDataSources(PQRYRES qrp);
bool GetDrivers(PQRYRES qrp);
- PQRYRES GetMetaData(PGLOBAL g, char *src);
+ PQRYRES GetMetaData(PGLOBAL g, PCSZ src);
public:
// Set static variables
@@ -174,16 +174,10 @@ protected:
jmethodID timfldid; // The TimeField method ID
jmethodID tspfldid; // The TimestampField method ID
jmethodID bigfldid; // The BigintField method ID
- //DWORD m_LoginTimeout;
-//DWORD m_QueryTimeout;
-//DWORD m_UpdateOptions;
- char *Msg;
+ PCSZ Msg;
char *m_Wrap;
char m_IDQuoteChar[2];
-//PSZ m_Driver;
-//PSZ m_Url;
-//PSZ m_User;
- PSZ m_Pwd;
+ PCSZ m_Pwd;
int m_Ncol;
int m_Aff;
int m_Rows;
diff --git a/storage/connect/json.cpp b/storage/connect/json.cpp
index 6904295066f..f8b1caa13e2 100644
--- a/storage/connect/json.cpp
+++ b/storage/connect/json.cpp
@@ -60,7 +60,7 @@ char *GetExceptionDesc(PGLOBAL g, unsigned int e);
/***********************************************************************/
PJSON ParseJson(PGLOBAL g, char *s, int len, int *ptyp, bool *comma)
{
- int i, rc, pretty = (ptyp) ? *ptyp : 3;
+ int i, pretty = (ptyp) ? *ptyp : 3;
bool b = false, pty[3] = {true, true, true};
PJSON jsp = NULL;
STRG src;
@@ -81,117 +81,91 @@ PJSON ParseJson(PGLOBAL g, char *s, int len, int *ptyp, bool *comma)
if (s[0] == '[' && (s[1] == '\n' || (s[1] == '\r' && s[2] == '\n')))
pty[0] = false;
-
- // Save stack and allocation environment and prepare error return
- if (g->jump_level == MAX_JUMP) {
- strcpy(g->Message, MSG(TOO_MANY_JUMPS));
- return NULL;
- } // endif jump_level
-
-#if defined(SE_CATCH)
- // Let's try to recover from any kind of interrupt
- _se_translator_function f = _set_se_translator(trans_func);
-
try {
-#endif // SE_CATCH --------------------- try section --------------------
- if ((rc = setjmp(g->jumper[++g->jump_level])) != 0) {
- goto err;
- } // endif rc
-
-#if defined(SE_CATCH) // ------------- end of try section -----------------
- } catch (SE_Exception e) {
- sprintf(g->Message, "ParseJson: exception doing setjmp: %s (rc=%hd)",
- GetExceptionDesc(g, e.nSE), e.nSE);
- _set_se_translator(f);
- goto err;
- } catch (...) {
- strcpy(g->Message, "Exception doing setjmp");
- _set_se_translator(f);
- goto err;
- } // end of try-catches
-
- _set_se_translator(f);
-#endif // SE_CATCH
-
- for (i = 0; i < len; i++)
- switch (s[i]) {
- case '[':
- if (jsp)
- goto tryit;
- else if (!(jsp = ParseArray(g, ++i, src, pty)))
- goto err;
-
- break;
- case '{':
- if (jsp)
- goto tryit;
- else if (!(jsp = ParseObject(g, ++i, src, pty)))
- goto err;
-
- break;
- case ' ':
- case '\t':
- case '\n':
- case '\r':
- break;
- case ',':
- if (jsp && (pretty == 1 || pretty == 3)) {
- if (comma)
- *comma = true;
-
- pty[0] = pty[2] = false;
- break;
- } // endif pretty
-
- sprintf(g->Message, "Unexpected ',' (pretty=%d)", pretty);
- goto err;
- case '(':
- b = true;
- break;
- case ')':
- if (b) {
- b = false;
- break;
- } // endif b
-
- default:
- if (jsp)
- goto tryit;
- else if (!(jsp = ParseValue(g, i, src, pty)))
- goto err;
-
- break;
- }; // endswitch s[i]
-
- if (!jsp)
- sprintf(g->Message, "Invalid Json string '%.*s'", 50, s);
- else if (ptyp && pretty == 3) {
- *ptyp = 3; // Not recognized pretty
-
- for (i = 0; i < 3; i++)
- if (pty[i]) {
- *ptyp = i;
- break;
- } // endif pty
-
- } // endif ptyp
-
- g->jump_level--;
- return jsp;
+ for (i = 0; i < len; i++)
+ switch (s[i]) {
+ case '[':
+ if (jsp)
+ goto tryit;
+ else if (!(jsp = ParseArray(g, ++i, src, pty)))
+ throw 1;
+
+ break;
+ case '{':
+ if (jsp)
+ goto tryit;
+ else if (!(jsp = ParseObject(g, ++i, src, pty)))
+ throw 2;
+
+ break;
+ case ' ':
+ case '\t':
+ case '\n':
+ case '\r':
+ break;
+ case ',':
+ if (jsp && (pretty == 1 || pretty == 3)) {
+ if (comma)
+ *comma = true;
+
+ pty[0] = pty[2] = false;
+ break;
+ } // endif pretty
+
+ sprintf(g->Message, "Unexpected ',' (pretty=%d)", pretty);
+ throw 3;
+ case '(':
+ b = true;
+ break;
+ case ')':
+ if (b) {
+ b = false;
+ break;
+ } // endif b
+
+ default:
+ if (jsp)
+ goto tryit;
+ else if (!(jsp = ParseValue(g, i, src, pty)))
+ throw 4;
+
+ break;
+ }; // endswitch s[i]
+
+ if (!jsp)
+ sprintf(g->Message, "Invalid Json string '%.*s'", 50, s);
+ else if (ptyp && pretty == 3) {
+ *ptyp = 3; // Not recognized pretty
+
+ for (i = 0; i < 3; i++)
+ if (pty[i]) {
+ *ptyp = i;
+ break;
+ } // endif pty
+
+ } // endif ptyp
+
+ } catch (int n) {
+ if (trace)
+ htrc("Exception %d: %s\n", n, g->Message);
+ jsp = NULL;
+ } catch (const char *msg) {
+ strcpy(g->Message, msg);
+ jsp = NULL;
+ } // end catch
+
+ return jsp;
tryit:
if (pty[0] && (!pretty || pretty > 2)) {
if ((jsp = ParseArray(g, (i = 0), src, pty)) && ptyp && pretty == 3)
*ptyp = (pty[0]) ? 0 : 3;
- g->jump_level--;
return jsp;
} else
strcpy(g->Message, "More than one item in file");
-err:
- g->jump_level--;
- return NULL;
+ return NULL;
} // end of ParseJson
/***********************************************************************/
@@ -335,16 +309,16 @@ PJVAL ParseValue(PGLOBAL g, int& i, STRG& src, bool *pty)
PJVAL jvp = new(g) JVALUE;
for (; i < len; i++)
- switch (s[i]) {
- case '\n':
- pty[0] = pty[1] = false;
- case '\r':
- case ' ':
- case '\t':
- break;
- default:
- goto suite;
- } // endswitch
+ switch (s[i]) {
+ case '\n':
+ pty[0] = pty[1] = false;
+ case '\r':
+ case ' ':
+ case '\t':
+ break;
+ default:
+ goto suite;
+ } // endswitch
suite:
switch (s[i]) {
@@ -585,78 +559,75 @@ PVAL ParseNumeric(PGLOBAL g, int& i, STRG& src)
PSZ Serialize(PGLOBAL g, PJSON jsp, char *fn, int pretty)
{
PSZ str = NULL;
- bool b = false, err = true;
- JOUT *jp;
+ bool b = false, err = true;
+ JOUT *jp;
FILE *fs = NULL;
g->Message[0] = 0;
- // Save stack and allocation environment and prepare error return
- if (g->jump_level == MAX_JUMP) {
- strcpy(g->Message, MSG(TOO_MANY_JUMPS));
- return NULL;
- } // endif jump_level
-
- if (setjmp(g->jumper[++g->jump_level])) {
- str = NULL;
- goto fin;
- } // endif jmp
-
- if (!jsp) {
- strcpy(g->Message, "Null json tree");
- goto fin;
- } else if (!fn) {
- // Serialize to a string
- jp = new(g) JOUTSTR(g);
- b = pretty == 1;
- } else {
- if (!(fs = fopen(fn, "wb"))) {
- sprintf(g->Message, MSG(OPEN_MODE_ERROR),
- "w", (int)errno, fn);
- strcat(strcat(g->Message, ": "), strerror(errno));
- goto fin;;
- } else if (pretty >= 2) {
- // Serialize to a pretty file
- jp = new(g)JOUTPRT(g, fs);
+ try {
+ if (!jsp) {
+ strcpy(g->Message, "Null json tree");
+ throw 1;
+ } else if (!fn) {
+ // Serialize to a string
+ jp = new(g) JOUTSTR(g);
+ b = pretty == 1;
} else {
- // Serialize to a flat file
- b = true;
- jp = new(g)JOUTFILE(g, fs, pretty);
- } // endif's
-
- } // endif's
-
- switch (jsp->GetType()) {
- case TYPE_JAR:
- err = SerializeArray(jp, (PJAR)jsp, b);
- break;
- case TYPE_JOB:
- err = ((b && jp->Prty()) && jp->WriteChr('\t'));
- err |= SerializeObject(jp, (PJOB)jsp);
- break;
- case TYPE_JVAL:
- err = SerializeValue(jp, (PJVAL)jsp);
- break;
- default:
- strcpy(g->Message, "Invalid json tree");
- } // endswitch Type
+ if (!(fs = fopen(fn, "wb"))) {
+ sprintf(g->Message, MSG(OPEN_MODE_ERROR),
+ "w", (int)errno, fn);
+ strcat(strcat(g->Message, ": "), strerror(errno));
+ throw 2;
+ } else if (pretty >= 2) {
+ // Serialize to a pretty file
+ jp = new(g)JOUTPRT(g, fs);
+ } else {
+ // Serialize to a flat file
+ b = true;
+ jp = new(g)JOUTFILE(g, fs, pretty);
+ } // endif's
+
+ } // endif's
+
+ switch (jsp->GetType()) {
+ case TYPE_JAR:
+ err = SerializeArray(jp, (PJAR)jsp, b);
+ break;
+ case TYPE_JOB:
+ err = ((b && jp->Prty()) && jp->WriteChr('\t'));
+ err |= SerializeObject(jp, (PJOB)jsp);
+ break;
+ case TYPE_JVAL:
+ err = SerializeValue(jp, (PJVAL)jsp);
+ break;
+ default:
+ strcpy(g->Message, "Invalid json tree");
+ } // endswitch Type
+
+ if (fs) {
+ fputs(EL, fs);
+ fclose(fs);
+ str = (err) ? NULL : strcpy(g->Message, "Ok");
+ } else if (!err) {
+ str = ((JOUTSTR*)jp)->Strp;
+ jp->WriteChr('\0');
+ PlugSubAlloc(g, NULL, ((JOUTSTR*)jp)->N);
+ } else {
+ if (!g->Message[0])
+ strcpy(g->Message, "Error in Serialize");
- if (fs) {
- fputs(EL, fs);
- fclose(fs);
- str = (err) ? NULL : strcpy(g->Message, "Ok");
- } else if (!err) {
- str = ((JOUTSTR*)jp)->Strp;
- jp->WriteChr('\0');
- PlugSubAlloc(g, NULL, ((JOUTSTR*)jp)->N);
- } else {
- if (!g->Message[0])
- strcpy(g->Message, "Error in Serialize");
+ } // endif's
- } // endif's
+ } catch (int n) {
+ if (trace)
+ htrc("Exception %d: %s\n", n, g->Message);
+ str = NULL;
+ } catch (const char *msg) {
+ strcpy(g->Message, msg);
+ str = NULL;
+ } // end catch
-fin:
- g->jump_level--;
return str;
} // end of Serialize
@@ -965,7 +936,7 @@ return false;
/***********************************************************************/
/* Add a new pair to an Object. */
/***********************************************************************/
-PJPR JOBJECT::AddPair(PGLOBAL g, PSZ key)
+PJPR JOBJECT::AddPair(PGLOBAL g, PCSZ key)
{
PJPR jpp = new(g) JPAIR(key);
@@ -1051,7 +1022,7 @@ bool JOBJECT::Merge(PGLOBAL g, PJSON jsp)
/***********************************************************************/
/* Set or add a value corresponding to the given key. */
/***********************************************************************/
-void JOBJECT::SetValue(PGLOBAL g, PJVAL jvp, PSZ key)
+void JOBJECT::SetValue(PGLOBAL g, PJVAL jvp, PCSZ key)
{
PJPR jp;
@@ -1071,7 +1042,7 @@ void JOBJECT::SetValue(PGLOBAL g, PJVAL jvp, PSZ key)
/***********************************************************************/
/* Delete a value corresponding to the given key. */
/***********************************************************************/
-void JOBJECT::DeleteKey(PSZ key)
+void JOBJECT::DeleteKey(PCSZ key)
{
PJPR jp, *pjp = &First;
@@ -1250,10 +1221,10 @@ JVALUE::JVALUE(PGLOBAL g, PVAL valp) : JSON()
/***********************************************************************/
/* Constructor for a given string. */
/***********************************************************************/
-JVALUE::JVALUE(PGLOBAL g, PSZ strp) : JSON()
+JVALUE::JVALUE(PGLOBAL g, PCSZ strp) : JSON()
{
Jsp = NULL;
- Value = AllocateValue(g, strp, TYPE_STRING);
+ Value = AllocateValue(g, (void*)strp, TYPE_STRING);
Next = NULL;
Del = false;
} // end of JVALUE constructor
@@ -1374,7 +1345,7 @@ void JVALUE::SetTiny(PGLOBAL g, char n)
{
Value = AllocateValue(g, &n, TYPE_TINY);
Jsp = NULL;
-} // end of SetInteger
+} // end of SetTiny
/***********************************************************************/
/* Set the Value's value as the given big integer. */
@@ -1408,6 +1379,6 @@ void JVALUE::SetString(PGLOBAL g, PSZ s, short c)
/***********************************************************************/
bool JVALUE::IsNull(void)
{
- return (Jsp) ? Jsp->IsNull() : (Value) ? Value->IsZero() : true;
+ return (Jsp) ? Jsp->IsNull() : (Value) ? Value->IsNull() : true;
} // end of IsNull
diff --git a/storage/connect/json.h b/storage/connect/json.h
index 4ea169e1b18..49675ce8559 100644
--- a/storage/connect/json.h
+++ b/storage/connect/json.h
@@ -125,14 +125,14 @@ class JPAIR : public BLOCK {
friend PJOB ParseObject(PGLOBAL, int&, STRG&, bool*);
friend bool SerializeObject(JOUT *, PJOB);
public:
- JPAIR(PSZ key) : BLOCK() {Key = key; Val = NULL; Next = NULL;}
+ JPAIR(PCSZ key) : BLOCK() {Key = key; Val = NULL; Next = NULL;}
- inline PSZ GetKey(void) {return Key;}
+ inline PCSZ GetKey(void) {return Key;}
inline PJVAL GetVal(void) {return Val;}
inline PJPR GetNext(void) {return Next;}
protected:
- PSZ Key; // This pair key name
+ PCSZ Key; // This pair key name
PJVAL Val; // To the value of the pair
PJPR Next; // To the next pair
}; // end of class JPAIR
@@ -150,7 +150,7 @@ class JSON : public BLOCK {
virtual JTYP GetValType(void) {X return TYPE_JSON;}
virtual void InitArray(PGLOBAL g) {X}
//virtual PJVAL AddValue(PGLOBAL g, PJVAL jvp = NULL, int *x = NULL) {X return NULL;}
- virtual PJPR AddPair(PGLOBAL g, PSZ key) {X return NULL;}
+ virtual PJPR AddPair(PGLOBAL g, PCSZ key) {X return NULL;}
virtual PJAR GetKeyList(PGLOBAL g) {X return NULL;}
virtual PJVAL GetValue(const char *key) {X return NULL;}
virtual PJOB GetObject(void) {return NULL;}
@@ -166,13 +166,13 @@ class JSON : public BLOCK {
virtual PSZ GetText(PGLOBAL g, PSZ text) {X return NULL;}
virtual bool Merge(PGLOBAL g, PJSON jsp) { X return true; }
virtual bool SetValue(PGLOBAL g, PJVAL jvp, int i) { X return true; }
- virtual void SetValue(PGLOBAL g, PJVAL jvp, PSZ key) {X}
+ virtual void SetValue(PGLOBAL g, PJVAL jvp, PCSZ key) {X}
virtual void SetValue(PVAL valp) {X}
virtual void SetValue(PJSON jsp) {X}
virtual void SetString(PGLOBAL g, PSZ s, short c) {X}
virtual void SetInteger(PGLOBAL g, int n) {X}
virtual void SetFloat(PGLOBAL g, double f) {X}
- virtual void DeleteKey(char *k) {X}
+ virtual void DeleteKey(PCSZ k) {X}
virtual bool DeleteValue(int i) {X return true;}
virtual bool IsNull(void) {X return true;}
@@ -195,14 +195,14 @@ class JOBJECT : public JSON {
virtual void Clear(void) {First = Last = NULL; Size = 0;}
virtual JTYP GetType(void) {return TYPE_JOB;}
virtual PJPR GetFirst(void) {return First;}
- virtual PJPR AddPair(PGLOBAL g, PSZ key);
+ virtual PJPR AddPair(PGLOBAL g, PCSZ key);
virtual PJOB GetObject(void) {return this;}
virtual PJVAL GetValue(const char* key);
virtual PJAR GetKeyList(PGLOBAL g);
virtual PSZ GetText(PGLOBAL g, PSZ text);
virtual bool Merge(PGLOBAL g, PJSON jsp);
- virtual void SetValue(PGLOBAL g, PJVAL jvp, PSZ key);
- virtual void DeleteKey(char *k);
+ virtual void SetValue(PGLOBAL g, PJVAL jvp, PCSZ key);
+ virtual void DeleteKey(PCSZ k);
virtual bool IsNull(void);
protected:
@@ -253,7 +253,7 @@ class JVALUE : public JSON {
JVALUE(PJSON jsp) : JSON()
{Jsp = jsp; Value = NULL; Next = NULL; Del = false;}
JVALUE(PGLOBAL g, PVAL valp);
- JVALUE(PGLOBAL g, PSZ strp);
+ JVALUE(PGLOBAL g, PCSZ strp);
using JSON::GetValue;
using JSON::SetValue;
diff --git a/storage/connect/jsonudf.cpp b/storage/connect/jsonudf.cpp
index 0f693c3c0d6..4e00703d9ef 100644
--- a/storage/connect/jsonudf.cpp
+++ b/storage/connect/jsonudf.cpp
@@ -1104,7 +1104,7 @@ static my_bool JsonInit(UDF_INIT *initid, UDF_ARGS *args,
} // endif g
g->Mrr = (args->arg_count && args->args[0]) ? 1 : 0;
- g->ActivityStart = (PACTIVITY)more;
+ g->More = more;
initid->maybe_null = mbn;
initid->max_length = reslen;
initid->ptr = (char*)g;
@@ -1449,13 +1449,13 @@ static my_bool CheckMemory(PGLOBAL g, UDF_INIT *initid, UDF_ARGS *args, uint n,
} // endif b
- ml += (unsigned long)g->ActivityStart; // more
+ ml += g->More;
if (ml > g->Sarea_Size) {
free(g->Sarea);
if (!(g->Sarea = PlugAllocMem(g, ml))) {
- char errmsg[256];
+ char errmsg[MAX_STR];
sprintf(errmsg, MSG(WORK_AREA), g->Message);
strcpy(g->Message, errmsg);
@@ -1496,7 +1496,7 @@ static PSZ MakePSZ(PGLOBAL g, UDF_ARGS *args, int i)
/*********************************************************************************/
/* Make a valid key from the passed argument. */
/*********************************************************************************/
-static PSZ MakeKey(PGLOBAL g, UDF_ARGS *args, int i)
+static PCSZ MakeKey(PGLOBAL g, UDF_ARGS *args, int i)
{
if (args->arg_count > (unsigned)i) {
int j = 0, n = args->attribute_lengths[i];
@@ -2253,7 +2253,8 @@ my_bool json_object_add_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
char *json_object_add(UDF_INIT *initid, UDF_ARGS *args, char *result,
unsigned long *res_length, char *is_null, char *error)
{
- char *key, *str = NULL;
+ PCSZ key;
+ char *str = NULL;
PGLOBAL g = (PGLOBAL)initid->ptr;
if (g->Xchk) {
@@ -2358,7 +2359,7 @@ char *json_object_delete(UDF_INIT *initid, UDF_ARGS *args, char *result,
} // endif Xchk
if (!CheckMemory(g, initid, args, 1, false, true, true)) {
- char *key;
+ PCSZ key;
PJOB jobp;
PJSON jsp, top;
PJVAL jvp = MakeValue(g, args, 0, &top);
@@ -2914,7 +2915,6 @@ char *jsonget_string(UDF_INIT *initid, UDF_ARGS *args, char *result,
unsigned long *res_length, char *is_null, char *)
{
char *p, *path, *str = NULL;
- int rc;
PJSON jsp;
PJSNX jsx;
PJVAL jvp;
@@ -2922,68 +2922,64 @@ char *jsonget_string(UDF_INIT *initid, UDF_ARGS *args, char *result,
if (g->N) {
str = (char*)g->Activityp;
- goto fin;
+ goto err;
} else if (initid->const_item)
g->N = 1;
- // Save stack and allocation environment and prepare error return
- if (g->jump_level == MAX_JUMP) {
- PUSH_WARNING(MSG(TOO_MANY_JUMPS));
- *is_null = 1;
- return NULL;
- } // endif jump_level
+ try {
+ if (!g->Xchk) {
+ if (CheckMemory(g, initid, args, 1, true)) {
+ PUSH_WARNING("CheckMemory error");
+ goto err;
+ } else
+ jvp = MakeValue(g, args, 0);
- if ((rc= setjmp(g->jumper[++g->jump_level])) != 0) {
- PUSH_WARNING(g->Message);
- str = NULL;
- goto err;
- } // endif rc
+ if ((p = jvp->GetString())) {
+ if (!(jsp = ParseJson(g, p, strlen(p)))) {
+ PUSH_WARNING(g->Message);
+ goto err;
+ } // endif jsp
- if (!g->Xchk) {
- if (CheckMemory(g, initid, args, 1, true)) {
- PUSH_WARNING("CheckMemory error");
- goto err;
- } else
- jvp = MakeValue(g, args, 0);
+ } else
+ jsp = jvp->GetJson();
- if ((p = jvp->GetString())) {
- if (!(jsp = ParseJson(g, p, strlen(p)))) {
- PUSH_WARNING(g->Message);
- goto err;
- } // endif jsp
+ if (g->Mrr) { // First argument is a constant
+ g->Xchk = jsp;
+ JsonMemSave(g);
+ } // endif Mrr
} else
- jsp = jvp->GetJson();
+ jsp = (PJSON)g->Xchk;
- if (g->Mrr) { // First argument is a constant
- g->Xchk = jsp;
- JsonMemSave(g);
- } // endif Mrr
+ path = MakePSZ(g, args, 1);
+ jsx = new(g) JSNX(g, jsp, TYPE_STRING, initid->max_length);
- } else
- jsp = (PJSON)g->Xchk;
+ if (jsx->SetJpath(g, path)) {
+ PUSH_WARNING(g->Message);
+ goto err;
+ } // endif SetJpath
- path = MakePSZ(g, args, 1);
- jsx = new(g) JSNX(g, jsp, TYPE_STRING, initid->max_length);
+ jsx->ReadValue(g);
- if (jsx->SetJpath(g, path)) {
- PUSH_WARNING(g->Message);
- goto err;
- } // endif SetJpath
+ if (!jsx->GetValue()->IsNull())
+ str = jsx->GetValue()->GetCharValue();
- jsx->ReadValue(g);
-
- if (!jsx->GetValue()->IsNull())
- str = jsx->GetValue()->GetCharValue();
+ if (initid->const_item)
+ // Keep result of constant function
+ g->Activityp = (PACTIVITY)str;
- if (initid->const_item)
- // Keep result of constant function
- g->Activityp = (PACTIVITY)str;
+ } catch (int n) {
+ if (trace)
+ htrc("Exception %d: %s\n", n, g->Message);
+ PUSH_WARNING(g->Message);
+ str = NULL;
+ } catch (const char *msg) {
+ strcpy(g->Message, msg);
+ PUSH_WARNING(g->Message);
+ str = NULL;
+ } // end catch
err:
- g->jump_level--;
-
- fin:
if (!str) {
*is_null = 1;
*res_length = 0;
@@ -3254,7 +3250,7 @@ char *jsonlocate(UDF_INIT *initid, UDF_ARGS *args, char *result,
unsigned long *res_length, char *is_null, char *error)
{
char *p, *path = NULL;
- int k, rc;
+ int k;
PJVAL jvp, jvp2;
PJSON jsp;
PJSNX jsx;
@@ -3274,61 +3270,58 @@ char *jsonlocate(UDF_INIT *initid, UDF_ARGS *args, char *result,
} else if (initid->const_item)
g->N = 1;
- // Save stack and allocation environment and prepare error return
- if (g->jump_level == MAX_JUMP) {
- PUSH_WARNING(MSG(TOO_MANY_JUMPS));
- *error = 1;
- *is_null = 1;
- return NULL;
- } // endif jump_level
+ try {
+ if (!g->Xchk) {
+ if (CheckMemory(g, initid, args, 1, !g->Xchk)) {
+ PUSH_WARNING("CheckMemory error");
+ *error = 1;
+ goto err;
+ } else
+ jvp = MakeValue(g, args, 0);
- if ((rc= setjmp(g->jumper[++g->jump_level])) != 0) {
- PUSH_WARNING(g->Message);
- *error = 1;
- path = NULL;
- goto err;
- } // endif rc
+ if ((p = jvp->GetString())) {
+ if (!(jsp = ParseJson(g, p, strlen(p)))) {
+ PUSH_WARNING(g->Message);
+ goto err;
+ } // endif jsp
- if (!g->Xchk) {
- if (CheckMemory(g, initid, args, 1, !g->Xchk)) {
- PUSH_WARNING("CheckMemory error");
- *error = 1;
- goto err;
- } else
- jvp = MakeValue(g, args, 0);
+ } else
+ jsp = jvp->GetJson();
- if ((p = jvp->GetString())) {
- if (!(jsp = ParseJson(g, p, strlen(p)))) {
- PUSH_WARNING(g->Message);
- goto err;
- } // endif jsp
+ if (g->Mrr) { // First argument is a constant
+ g->Xchk = jsp;
+ JsonMemSave(g);
+ } // endif Mrr
} else
- jsp = jvp->GetJson();
+ jsp = (PJSON)g->Xchk;
- if (g->Mrr) { // First argument is a constant
- g->Xchk = jsp;
- JsonMemSave(g);
- } // endif Mrr
-
- } else
- jsp = (PJSON)g->Xchk;
+ // The item to locate
+ jvp2 = MakeValue(g, args, 1);
- // The item to locate
- jvp2 = MakeValue(g, args, 1);
+ k = (args->arg_count > 2) ? (int)*(long long*)args->args[2] : 1;
- k = (args->arg_count > 2) ? (int)*(long long*)args->args[2] : 1;
+ jsx = new(g) JSNX(g, jsp, TYPE_STRING);
+ path = jsx->Locate(g, jsp, jvp2, k);
- jsx = new(g) JSNX(g, jsp, TYPE_STRING);
- path = jsx->Locate(g, jsp, jvp2, k);
+ if (initid->const_item)
+ // Keep result of constant function
+ g->Activityp = (PACTIVITY)path;
- if (initid->const_item)
- // Keep result of constant function
- g->Activityp = (PACTIVITY)path;
+ } catch (int n) {
+ if (trace)
+ htrc("Exception %d: %s\n", n, g->Message);
+ PUSH_WARNING(g->Message);
+ *error = 1;
+ path = NULL;
+ } catch (const char *msg) {
+ strcpy(g->Message, msg);
+ PUSH_WARNING(g->Message);
+ *error = 1;
+ path = NULL;
+ } // end catch
err:
- g->jump_level--;
-
if (!path) {
*res_length = 0;
*is_null = 1;
@@ -3379,7 +3372,7 @@ char *json_locate_all(UDF_INIT *initid, UDF_ARGS *args, char *result,
unsigned long *res_length, char *is_null, char *error)
{
char *p, *path = NULL;
- int rc, mx = 10;
+ int mx = 10;
PJVAL jvp, jvp2;
PJSON jsp;
PJSNX jsx;
@@ -3400,62 +3393,59 @@ char *json_locate_all(UDF_INIT *initid, UDF_ARGS *args, char *result,
} else if (initid->const_item)
g->N = 1;
- // Save stack and allocation environment and prepare error return
- if (g->jump_level == MAX_JUMP) {
- PUSH_WARNING(MSG(TOO_MANY_JUMPS));
- *error = 1;
- *is_null = 1;
- return NULL;
- } // endif jump_level
+ try {
+ if (!g->Xchk) {
+ if (CheckMemory(g, initid, args, 1, true)) {
+ PUSH_WARNING("CheckMemory error");
+ *error = 1;
+ goto err;
+ } else
+ jvp = MakeValue(g, args, 0);
- if ((rc= setjmp(g->jumper[++g->jump_level])) != 0) {
- PUSH_WARNING(g->Message);
- *error = 1;
- path = NULL;
- goto err;
- } // endif rc
+ if ((p = jvp->GetString())) {
+ if (!(jsp = ParseJson(g, p, strlen(p)))) {
+ PUSH_WARNING(g->Message);
+ goto err;
+ } // endif jsp
- if (!g->Xchk) {
- if (CheckMemory(g, initid, args, 1, true)) {
- PUSH_WARNING("CheckMemory error");
- *error = 1;
- goto err;
- } else
- jvp = MakeValue(g, args, 0);
+ } else
+ jsp = jvp->GetJson();
- if ((p = jvp->GetString())) {
- if (!(jsp = ParseJson(g, p, strlen(p)))) {
- PUSH_WARNING(g->Message);
- goto err;
- } // endif jsp
+ if (g->Mrr) { // First argument is a constant
+ g->Xchk = jsp;
+ JsonMemSave(g);
+ } // endif Mrr
} else
- jsp = jvp->GetJson();
-
- if (g->Mrr) { // First argument is a constant
- g->Xchk = jsp;
- JsonMemSave(g);
- } // endif Mrr
+ jsp = (PJSON)g->Xchk;
- } else
- jsp = (PJSON)g->Xchk;
+ // The item to locate
+ jvp2 = MakeValue(g, args, 1);
- // The item to locate
- jvp2 = MakeValue(g, args, 1);
+ if (args->arg_count > 2)
+ mx = (int)*(long long*)args->args[2];
- if (args->arg_count > 2)
- mx = (int)*(long long*)args->args[2];
+ jsx = new(g) JSNX(g, jsp, TYPE_STRING);
+ path = jsx->LocateAll(g, jsp, jvp2, mx);
- jsx = new(g) JSNX(g, jsp, TYPE_STRING);
- path = jsx->LocateAll(g, jsp, jvp2, mx);
+ if (initid->const_item)
+ // Keep result of constant function
+ g->Activityp = (PACTIVITY)path;
- if (initid->const_item)
- // Keep result of constant function
- g->Activityp = (PACTIVITY)path;
+ } catch (int n) {
+ if (trace)
+ htrc("Exception %d: %s\n", n, g->Message);
+ PUSH_WARNING(g->Message);
+ *error = 1;
+ path = NULL;
+ } catch (const char *msg) {
+ strcpy(g->Message, msg);
+ PUSH_WARNING(g->Message);
+ *error = 1;
+ path = NULL;
+ } // end catch
err:
- g->jump_level--;
-
if (!path) {
*res_length = 0;
*is_null = 1;
@@ -3637,7 +3627,7 @@ char *handle_item(UDF_INIT *initid, UDF_ARGS *args, char *result,
unsigned long *res_length, char *is_null, char *error)
{
char *p, *path, *str = NULL;
- int w, rc;
+ int w;
my_bool b = true;
PJSON jsp;
PJSNX jsx;
@@ -3659,78 +3649,73 @@ char *handle_item(UDF_INIT *initid, UDF_ARGS *args, char *result,
w = 2;
else {
PUSH_WARNING("Logical error, please contact CONNECT developer");
- goto err;
+ goto fin;
} // endelse
- // Save stack and allocation environment and prepare error return
- if (g->jump_level == MAX_JUMP) {
- PUSH_WARNING(MSG(TOO_MANY_JUMPS));
- *error = 1;
- goto fin;
- } // endif jump_level
+ try {
+ if (!g->Xchk) {
+ if (CheckMemory(g, initid, args, 1, true, false, true)) {
+ PUSH_WARNING("CheckMemory error");
+ throw 1;
+ } else
+ jvp = MakeValue(g, args, 0);
- if ((rc= setjmp(g->jumper[++g->jump_level])) != 0) {
- PUSH_WARNING(g->Message);
- str = NULL;
- goto err;
- } // endif rc
+ if ((p = jvp->GetString())) {
+ if (!(jsp = ParseJson(g, p, strlen(p)))) {
+ throw 2;
+ } // endif jsp
- if (!g->Xchk) {
- if (CheckMemory(g, initid, args, 1, true, false, true)) {
- PUSH_WARNING("CheckMemory error");
- goto err;
- } else
- jvp = MakeValue(g, args, 0);
+ } else
+ jsp = jvp->GetJson();
- if ((p = jvp->GetString())) {
- if (!(jsp = ParseJson(g, p, strlen(p)))) {
- PUSH_WARNING(g->Message);
- goto err;
- } // endif jsp
+ if (g->Mrr) { // First argument is a constant
+ g->Xchk = jsp;
+ JsonMemSave(g);
+ } // endif Mrr
} else
- jsp = jvp->GetJson();
+ jsp = (PJSON)g->Xchk;
- if (g->Mrr) { // First argument is a constant
- g->Xchk = jsp;
- JsonMemSave(g);
- } // endif Mrr
+ jsx = new(g)JSNX(g, jsp, TYPE_STRING, initid->max_length, 0, true);
- } else
- jsp = (PJSON)g->Xchk;
-
- jsx = new(g)JSNX(g, jsp, TYPE_STRING, initid->max_length, 0, true);
-
- for (uint i = 1; i+1 < args->arg_count; i += 2) {
- jvp = MakeValue(gb, args, i);
- path = MakePSZ(g, args, i+1);
+ for (uint i = 1; i + 1 < args->arg_count; i += 2) {
+ jvp = MakeValue(gb, args, i);
+ path = MakePSZ(g, args, i + 1);
- if (jsx->SetJpath(g, path, false)) {
- PUSH_WARNING(g->Message);
- continue;
- } // endif SetJpath
+ if (jsx->SetJpath(g, path, false)) {
+ PUSH_WARNING(g->Message);
+ continue;
+ } // endif SetJpath
- if (w) {
- jsx->ReadValue(g);
- b = jsx->GetValue()->IsNull();
- b = (w == 1) ? b : !b;
- } // endif w
+ if (w) {
+ jsx->ReadValue(g);
+ b = jsx->GetValue()->IsNull();
+ b = (w == 1) ? b : !b;
+ } // endif w
- if (b && jsx->WriteValue(gb, jvp))
- PUSH_WARNING(g->Message);
+ if (b && jsx->WriteValue(gb, jvp))
+ PUSH_WARNING(g->Message);
- } // endfor i
+ } // endfor i
- // In case of error or file, return unchanged argument
- if (!(str = MakeResult(g, args, jsp, INT_MAX32)))
- str = MakePSZ(g, args, 0);
+ // In case of error or file, return unchanged argument
+ if (!(str = MakeResult(g, args, jsp, INT_MAX32)))
+ str = MakePSZ(g, args, 0);
- if (g->N)
- // Keep result of constant function
- g->Activityp = (PACTIVITY)str;
+ if (g->N)
+ // Keep result of constant function
+ g->Activityp = (PACTIVITY)str;
-err:
- g->jump_level--;
+ } catch (int n) {
+ if (trace)
+ htrc("Exception %d: %s\n", n, g->Message);
+ PUSH_WARNING(g->Message);
+ str = NULL;
+ } catch (const char *msg) {
+ strcpy(g->Message, msg);
+ PUSH_WARNING(g->Message);
+ str = NULL;
+ } // end catch
fin:
if (!str) {
@@ -4557,7 +4542,7 @@ char *jbin_object_add(UDF_INIT *initid, UDF_ARGS *args, char *result,
} // endif bsp
if (!CheckMemory(g, initid, args, 2, false, true, true)) {
- char *key;
+ PCSZ key;
PJOB jobp;
PJVAL jvp = MakeValue(g, args, 0, &top);
PJSON jsp = jvp->GetJson();
@@ -4637,7 +4622,7 @@ char *jbin_object_delete(UDF_INIT *initid, UDF_ARGS *args, char *result,
} // endif bsp
if (!CheckMemory(g, initid, args, 1, false, true, true)) {
- char *key;
+ PCSZ key;
PJOB jobp;
PJVAL jvp = MakeValue(g, args, 0, &top);
PJSON jsp = jvp->GetJson();
diff --git a/storage/connect/jsonudf.h b/storage/connect/jsonudf.h
index d2890421c62..5f4b98a0652 100644
--- a/storage/connect/jsonudf.h
+++ b/storage/connect/jsonudf.h
@@ -232,7 +232,7 @@ extern "C" {
/*********************************************************************************/
typedef struct _jpn {
enum JTYP Type;
- PSZ Key;
+ PCSZ Key;
int N;
} JPN, *PJPN;
diff --git a/storage/connect/libdoc.cpp b/storage/connect/libdoc.cpp
index 2470d37c353..700d247da38 100644
--- a/storage/connect/libdoc.cpp
+++ b/storage/connect/libdoc.cpp
@@ -68,9 +68,9 @@ class LIBXMLDOC : public XMLDOCUMENT {
virtual void SetNofree(bool b) {Nofreelist = b;}
// Methods
- virtual bool Initialize(PGLOBAL g, char *entry, bool zipped);
+ virtual bool Initialize(PGLOBAL g, PCSZ entry, bool zipped);
virtual bool ParseFile(PGLOBAL g, char *fn);
- virtual bool NewDoc(PGLOBAL g, char *ver);
+ virtual bool NewDoc(PGLOBAL g, PCSZ ver);
virtual void AddComment(PGLOBAL g, char *com);
virtual PXNODE GetRoot(PGLOBAL g);
virtual PXNODE NewRoot(PGLOBAL g, char *name);
@@ -119,9 +119,9 @@ class XML2NODE : public XMLNODE {
virtual PXLIST SelectNodes(PGLOBAL g, char *xp, PXLIST lp);
virtual PXNODE SelectSingleNode(PGLOBAL g, char *xp, PXNODE np);
virtual PXATTR GetAttribute(PGLOBAL g, char *name, PXATTR ap);
- virtual PXNODE AddChildNode(PGLOBAL g, char *name, PXNODE np);
+ virtual PXNODE AddChildNode(PGLOBAL g, PCSZ name, PXNODE np);
virtual PXATTR AddProperty(PGLOBAL g, char *name, PXATTR ap);
- virtual void AddText(PGLOBAL g, char *txtp);
+ virtual void AddText(PGLOBAL g, PCSZ txtp);
virtual void DeleteChild(PGLOBAL g, PXNODE dnp);
protected:
@@ -373,7 +373,7 @@ LIBXMLDOC::LIBXMLDOC(char *nsl, char *nsdf, char *enc, PFBLOCK fp)
/******************************************************************/
/* Initialize XML parser and check library compatibility. */
/******************************************************************/
-bool LIBXMLDOC::Initialize(PGLOBAL g, char *entry, bool zipped)
+bool LIBXMLDOC::Initialize(PGLOBAL g, PCSZ entry, bool zipped)
{
if (zipped && InitZip(g, entry))
return true;
@@ -434,7 +434,7 @@ PFBLOCK LIBXMLDOC::LinkXblock(PGLOBAL g, MODE m, int rc, char *fn)
/******************************************************************/
/* Construct and add the XML processing instruction node. */
/******************************************************************/
-bool LIBXMLDOC::NewDoc(PGLOBAL g, char *ver)
+bool LIBXMLDOC::NewDoc(PGLOBAL g, PCSZ ver)
{
if (trace)
htrc("NewDoc\n");
@@ -863,14 +863,13 @@ RCODE XML2NODE::GetContent(PGLOBAL g, char *buf, int len)
xmlFree(Content);
if ((Content = xmlNodeGetContent(Nodep))) {
- char *extra = " \t\r\n";
char *p1 = (char*)Content, *p2 = buf;
bool b = false;
// Copy content eliminating extra characters
for (; *p1; p1++)
if ((p2 - buf) < len) {
- if (strchr(extra, *p1)) {
+ if (strchr(" \t\r\n", *p1)) {
if (b) {
// This to have one blank between sub-nodes
*p2++ = ' ';
@@ -1020,19 +1019,19 @@ PXATTR XML2NODE::GetAttribute(PGLOBAL g, char *name, PXATTR ap)
/******************************************************************/
/* Add a new child node to this node and return it. */
/******************************************************************/
-PXNODE XML2NODE::AddChildNode(PGLOBAL g, char *name, PXNODE np)
+PXNODE XML2NODE::AddChildNode(PGLOBAL g, PCSZ name, PXNODE np)
{
- char *p, *pn, *pf = NULL;
+ char *p, *pn, *pf = NULL, *nmp = PlugDup(g, name);
if (trace)
htrc("AddChildNode: %s\n", name);
// Is a prefix specified
- if ((pn = strchr(name, ':'))) {
- pf = name;
+ if ((pn = strchr(nmp, ':'))) {
+ pf = nmp;
*pn++ = '\0'; // Separate name from prefix
} else
- pn = name;
+ pn = nmp;
// If name has the format m[n] only m is taken as node name
if ((p = strchr(pn, '[')))
@@ -1096,7 +1095,7 @@ PXATTR XML2NODE::AddProperty(PGLOBAL g, char *name, PXATTR ap)
/******************************************************************/
/* Add a new text node to this node. */
/******************************************************************/
-void XML2NODE::AddText(PGLOBAL g, char *txtp)
+void XML2NODE::AddText(PGLOBAL g, PCSZ txtp)
{
if (trace)
htrc("AddText: %s\n", txtp);
diff --git a/storage/connect/macutil.cpp b/storage/connect/macutil.cpp
index f5d3bb11fe9..b9600bdac2e 100644
--- a/storage/connect/macutil.cpp
+++ b/storage/connect/macutil.cpp
@@ -192,7 +192,7 @@ bool MACINFO::GetOneInfo(PGLOBAL g, int flag, void *v, int lv)
case 23:
break;
default:
- p = "";
+ p = PlugDup(g, "");
} // endswitch flag
} else switch (flag) {
diff --git a/storage/connect/mycat.cc b/storage/connect/mycat.cc
index 1fcd8ac78da..750cf3c0639 100644
--- a/storage/connect/mycat.cc
+++ b/storage/connect/mycat.cc
@@ -161,7 +161,7 @@ TABTYPE GetTypeID(const char *type)
#ifdef ZIP_SUPPORT
: (!stricmp(type, "ZIP")) ? TAB_ZIP
#endif
- : (!stricmp(type, "OEM")) ? TAB_OEM : TAB_NIY;
+ : (!stricmp(type, "OEM")) ? TAB_OEM : TAB_NIY;
} // end of GetTypeID
/***********************************************************************/
@@ -477,39 +477,6 @@ void MYCAT::Reset(void)
{
} // end of Reset
-#if 0
-/***********************************************************************/
-/* This function sets the current database path. */
-/***********************************************************************/
-void MYCAT::SetPath(PGLOBAL g, LPCSTR *datapath, const char *path)
- {
- if (path) {
- size_t len= strlen(path) + (*path != '.' ? 4 : 1);
- char *buf= (char*)PlugSubAlloc(g, NULL, len);
-
- if (PlugIsAbsolutePath(path))
- {
- strcpy(buf, path);
- *datapath= buf;
- return;
- }
-
- if (*path != '.') {
-#if defined(__WIN__)
- char *s= "\\";
-#else // !__WIN__
- char *s= "/";
-#endif // !__WIN__
- strcat(strcat(strcat(strcpy(buf, "."), s), path), s);
- } else
- strcpy(buf, path);
-
- *datapath= buf;
- } // endif path
-
- } // end of SetDataPath
-#endif // 0
-
/***********************************************************************/
/* GetTableDesc: retrieve a table descriptor. */
/* Look for a table descriptor matching the name and type. */
diff --git a/storage/connect/mycat.h b/storage/connect/mycat.h
index a3682b31f17..b6bdd5e5e11 100644
--- a/storage/connect/mycat.h
+++ b/storage/connect/mycat.h
@@ -98,10 +98,7 @@ class MYCAT : public CATALOG {
// Methods
void Reset(void);
-//void SetDataPath(PGLOBAL g, const char *path)
-// {SetPath(g, &DataPath, path);}
bool StoreIndex(PGLOBAL, PTABDEF) {return false;} // Temporary
-// PRELDEF GetTableDesc(PGLOBAL g, LPCSTR name,
PRELDEF GetTableDesc(PGLOBAL g, PTABLE tablep,
LPCSTR type, PRELDEF *prp = NULL);
PTDB GetTable(PGLOBAL g, PTABLE tablep,
@@ -109,9 +106,7 @@ class MYCAT : public CATALOG {
void ClearDB(PGLOBAL g);
protected:
-// PRELDEF MakeTableDesc(PGLOBAL g, LPCSTR name, LPCSTR am);
PRELDEF MakeTableDesc(PGLOBAL g, PTABLE tablep, LPCSTR am);
- //void SetPath(PGLOBAL g, LPCSTR *datapath, const char *path);
// Members
ha_connect *Hc; // The Connect handler
diff --git a/storage/connect/myconn.cpp b/storage/connect/myconn.cpp
index d05254a32a6..e68489faad5 100644
--- a/storage/connect/myconn.cpp
+++ b/storage/connect/myconn.cpp
@@ -135,10 +135,13 @@ PQRYRES MyColumns(PGLOBAL g, THD *thd, const char *host, const char *db,
FLD_KEY, FLD_SCALE, FLD_RADIX, FLD_NULL,
FLD_REM, FLD_NO, FLD_DEFAULT, FLD_EXTRA,
FLD_CHARSET};
- unsigned int length[] = {0, 4, 16, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0};
- char *fld, *colname, *chset, *fmt, v, buf[128], uns[16], zero[16];
+ //unsigned int length[] = {0, 4, 16, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0};
+ unsigned int length[] = {0, 4, 0, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0};
+ PCSZ fmt;
+ char *fld, *colname, *chset, v, buf[128], uns[16], zero[16];
int i, n, nf, ncol = sizeof(buftyp) / sizeof(int);
int len, type, prec, rc, k = 0;
+ bool b;
PQRYRES qrp;
PCOLRES crp;
MYSQLC myc;
@@ -157,7 +160,7 @@ PQRYRES MyColumns(PGLOBAL g, THD *thd, const char *host, const char *db,
/* Do an evaluation of the result size. */
/********************************************************************/
STRING cmd(g, 64, "SHOW FULL COLUMNS FROM ");
- bool b = cmd.Append((PSZ)table);
+ b = cmd.Append((PSZ)table);
b |= cmd.Append(" FROM ");
b |= cmd.Append((PSZ)(db ? db : PlgGetUser(g)->DBName));
@@ -232,11 +235,31 @@ PQRYRES MyColumns(PGLOBAL g, THD *thd, const char *host, const char *db,
fld = myc.GetCharField(1);
prec = 0;
len = 0;
- v = (chset && !strcmp(chset, "binary")) ? 'B' : 0;
+// v = (chset && !strcmp(chset, "binary")) ? 'B' : 0;
+ v = 0;
*uns = 0;
*zero = 0;
-
- switch ((nf = sscanf(fld, "%[^(](%d,%d", buf, &len, &prec))) {
+ b = false;
+
+ if (!strnicmp(fld, "enum", 4)) {
+ char *p2, *p1 = fld + 6; // to skip enum('
+
+ while (true) {
+ p2 = strchr(p1, '\'');
+ len = MY_MAX(len, p2 - p1);
+ if (*++p2 != ',') break;
+ p1 = p2 + 2;
+ } // endwhile
+
+ v = (len > 255) ? 'V' : 0;
+ strcpy(buf, "enum");
+ b = true;
+ } else if (!strnicmp(fld, "set", 3)) {
+ len = (int)strlen(fld) - 2;
+ v = 'V';
+ strcpy(buf, "set");
+ b = true;
+ } else switch ((nf = sscanf(fld, "%[^(](%d,%d", buf, &len, &prec))) {
case 3:
nf = sscanf(fld, "%[^(](%d,%d) %s %s", buf, &len, &prec, uns, zero);
break;
@@ -271,7 +294,7 @@ PQRYRES MyColumns(PGLOBAL g, THD *thd, const char *host, const char *db,
colname, len);
PushWarning(g, thd);
v = 'V';
- } else
+ } else
len = MY_MIN(len, 4096);
} // endif type
@@ -286,6 +309,9 @@ PQRYRES MyColumns(PGLOBAL g, THD *thd, const char *host, const char *db,
default: crp->Nulls[i] = v; break;
} // endswitch nf
+ if (b) // enum or set
+ nf = sscanf(fld, "%s ", buf); // get values
+
crp = crp->Next; // Type_Name
crp->Kdata->SetValue(buf, i);
@@ -849,7 +875,8 @@ MYSQL_FIELD *MYSQLC::GetNextField(void)
/***********************************************************************/
PQRYRES MYSQLC::GetResult(PGLOBAL g, bool pdb)
{
- char *fmt, v;
+ PCSZ fmt;
+ char *name, v;
int n;
bool uns;
PCOLRES *pcrp, crp;
@@ -887,8 +914,9 @@ PQRYRES MYSQLC::GetResult(PGLOBAL g, bool pdb)
memset(crp, 0, sizeof(COLRES));
crp->Ncol = ++qrp->Nbcol;
- crp->Name = (char*)PlugSubAlloc(g, NULL, fld->name_length + 1);
- strcpy(crp->Name, fld->name);
+ name = (char*)PlugSubAlloc(g, NULL, fld->name_length + 1);
+ strcpy(name, fld->name);
+ crp->Name = name;
if ((crp->Type = MYSQLtoPLG(fld->type, &v)) == TYPE_ERROR) {
sprintf(g->Message, "Type %d not supported for column %s",
diff --git a/storage/connect/mysql-test/connect/disabled.def b/storage/connect/mysql-test/connect/disabled.def
index 5e15e0806ba..4e07b5c0576 100644
--- a/storage/connect/mysql-test/connect/disabled.def
+++ b/storage/connect/mysql-test/connect/disabled.def
@@ -9,7 +9,7 @@
# Do not use any TAB characters for whitespace.
#
##############################################################################
-#jdbc : Variable settings depend on machine configuration
-#jdbc_new : Variable settings depend on machine configuration
+jdbc : Variable settings depend on machine configuration
+jdbc_new : Variable settings depend on machine configuration
jdbc_oracle : Variable settings depend on machine configuration
jdbc_postgresql : Variable settings depend on machine configuration
diff --git a/storage/connect/mysql-test/connect/r/jdbc_new.result b/storage/connect/mysql-test/connect/r/jdbc_new.result
index 5cc4826213d..6f977166598 100644
--- a/storage/connect/mysql-test/connect/r/jdbc_new.result
+++ b/storage/connect/mysql-test/connect/r/jdbc_new.result
@@ -14,9 +14,7 @@ NULL NULL
SET GLOBAL time_zone='+1:00';
CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=JDBC
CONNECTION='jdbc:mysql://127.0.0.1:SLAVE_PORT/test?user=unknown';
-SELECT * FROM t1;
-ERROR HY000: Got error 174 'Connecting: java.sql.SQLException: Access denied for user 'unknown'@'localhost' (using password: NO) rc=-2' from CONNECT
-DROP TABLE t1;
+ERROR HY000: Connecting: java.sql.SQLException: Access denied for user 'unknown'@'localhost' (using password: NO) rc=-2
CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=JDBC
CONNECTION='jdbc:mysql://127.0.0.1:SLAVE_PORT/unknown?user=root';
ERROR HY000: Connecting: java.sql.SQLSyntaxErrorException: Unknown database 'unknown' rc=-2
diff --git a/storage/connect/mysql-test/connect/t/jdbc_new.test b/storage/connect/mysql-test/connect/t/jdbc_new.test
index 5586cf8c027..86c4ad57c5f 100644
--- a/storage/connect/mysql-test/connect/t/jdbc_new.test
+++ b/storage/connect/mysql-test/connect/t/jdbc_new.test
@@ -24,11 +24,9 @@ SET GLOBAL time_zone='+1:00';
# Bad user name
# Suppress "mysql_real_connect failed:" (printed in _DEBUG build)
--replace_result $SLAVE_MYPORT SLAVE_PORT "mysql_real_connect failed: " ""
+--error ER_UNKNOWN_ERROR
eval CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=JDBC
CONNECTION='jdbc:mysql://127.0.0.1:$SLAVE_MYPORT/test?user=unknown';
---error ER_GET_ERRMSG
-SELECT * FROM t1;
-DROP TABLE t1;
# Bad database name
--replace_result $SLAVE_MYPORT SLAVE_PORT "mysql_real_connect failed: " ""
diff --git a/storage/connect/myutil.cpp b/storage/connect/myutil.cpp
index d4416e188c8..c2053f1c832 100644
--- a/storage/connect/myutil.cpp
+++ b/storage/connect/myutil.cpp
@@ -42,7 +42,8 @@ int MYSQLtoPLG(char *typname, char *var)
type = TYPE_INT;
else if (!stricmp(typname, "smallint"))
type = TYPE_SHORT;
- else if (!stricmp(typname, "char") || !stricmp(typname, "varchar"))
+ else if (!stricmp(typname, "char") || !stricmp(typname, "varchar") ||
+ !stricmp(typname, "enum") || !stricmp(typname, "set"))
type = TYPE_STRING;
else if (!stricmp(typname, "double") || !stricmp(typname, "float") ||
!stricmp(typname, "real"))
@@ -87,10 +88,12 @@ int MYSQLtoPLG(char *typname, char *var)
else if (!stricmp(typname, "year"))
*var = 'Y';
- } 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 == TPC_SKIP)
+ } else if (type == TYPE_STRING) {
+ if (!stricmp(typname, "varchar"))
+ // This is to make the difference between CHAR and VARCHAR
+ *var = 'V';
+
+ } else if (type == TYPE_ERROR && xconv == TPC_SKIP)
*var = 'K';
else
*var = 0;
@@ -266,9 +269,9 @@ int MYSQLtoPLG(int mytype, char *var)
/************************************************************************/
/* Returns the format corresponding to a MySQL date type number. */
/************************************************************************/
-char *MyDateFmt(int mytype)
+PCSZ MyDateFmt(int mytype)
{
- char *fmt;
+ PCSZ fmt;
switch (mytype) {
case MYSQL_TYPE_TIMESTAMP:
@@ -294,9 +297,9 @@ char *MyDateFmt(int mytype)
/************************************************************************/
/* Returns the format corresponding to a MySQL date type name. */
/************************************************************************/
-char *MyDateFmt(char *typname)
+PCSZ MyDateFmt(char *typname)
{
- char *fmt;
+ PCSZ fmt;
if (!stricmp(typname, "datetime") || !stricmp(typname, "timestamp"))
fmt = "YYYY-MM-DD hh:mm:ss";
diff --git a/storage/connect/myutil.h b/storage/connect/myutil.h
index 9c22cfef118..6991172b39e 100644
--- a/storage/connect/myutil.h
+++ b/storage/connect/myutil.h
@@ -6,9 +6,9 @@
enum enum_field_types PLGtoMYSQL(int type, bool dbf, char var = 0);
const char *PLGtoMYSQLtype(int type, bool dbf, char var = 0);
-int MYSQLtoPLG(char *typname, char *var = NULL);
-int MYSQLtoPLG(int mytype, char *var = NULL);
-char *MyDateFmt(int mytype);
-char *MyDateFmt(char *typname);
+int MYSQLtoPLG(char *typname, char *var = NULL);
+int MYSQLtoPLG(int mytype, char *var = NULL);
+PCSZ MyDateFmt(int mytype);
+PCSZ MyDateFmt(char *typname);
#endif // __MYUTIL__H
diff --git a/storage/connect/odbccat.h b/storage/connect/odbccat.h
index 3b729bcb4bb..05b82e49727 100644
--- a/storage/connect/odbccat.h
+++ b/storage/connect/odbccat.h
@@ -3,11 +3,11 @@
#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)
+ PCSZ User; // User connect info
+ PCSZ Pwd; // Password connect info
+ int Cto; // Connect timeout
+ int Qto; // Query timeout
+ bool UseCnc; // Use SQLConnect (!SQLDriverConnect)
} ODBCPARM, *POPARM;
/***********************************************************************/
@@ -17,9 +17,9 @@ typedef struct odbc_parms {
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, bool info, POPARM sop);
+PQRYRES ODBCColumns(PGLOBAL g, PCSZ dsn, PCSZ db, PCSZ table,
+ PCSZ 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,
- char *tabtyp, int maxres, bool info, POPARM sop);
+PQRYRES ODBCTables(PGLOBAL g, PCSZ dsn, PCSZ db, PCSZ tabpat,
+ PCSZ tabtyp, int maxres, bool info, POPARM sop);
PQRYRES ODBCDrivers(PGLOBAL g, int maxres, bool info);
diff --git a/storage/connect/odbconn.cpp b/storage/connect/odbconn.cpp
index 433e392eace..3dbc2d577d5 100644
--- a/storage/connect/odbconn.cpp
+++ b/storage/connect/odbconn.cpp
@@ -1,7 +1,7 @@
-/************ Odbconn C++ Functions Source Code File (.CPP) ************/
-/* Name: ODBCONN.CPP Version 2.2 */
+/***********************************************************************/
+/* Name: ODBCONN.CPP Version 2.3 */
/* */
-/* (C) Copyright to the author Olivier BERTRAND 1998-2016 */
+/* (C) Copyright to the author Olivier BERTRAND 1998-2017 */
/* */
/* This file contains the ODBC connection classes functions. */
/***********************************************************************/
@@ -239,47 +239,43 @@ char *ODBCCheckConnection(PGLOBAL g, char *dsn, int cop)
/***********************************************************************/
/* Allocate the structure used to refer to the result set. */
/***********************************************************************/
-static CATPARM *AllocCatInfo(PGLOBAL g, CATINFO fid, char *db,
- char *tab, PQRYRES qrp)
- {
- size_t i, m, n;
- CATPARM *cap;
+static CATPARM *AllocCatInfo(PGLOBAL g, CATINFO fid, PCSZ db,
+ PCSZ tab, PQRYRES qrp)
+{
+ size_t i, m, n;
+ CATPARM *cap;
#if defined(_DEBUG)
- assert(qrp);
+ assert(qrp);
#endif
- // Save stack and allocation environment and prepare error return
- if (g->jump_level == MAX_JUMP) {
- strcpy(g->Message, MSG(TOO_MANY_JUMPS));
- return NULL;
- } // endif jump_level
-
- if (setjmp(g->jumper[++g->jump_level]) != 0) {
- printf("%s\n", g->Message);
- cap = NULL;
- goto fin;
- } // endif rc
-
- m = (size_t)qrp->Maxres;
- n = (size_t)qrp->Nbcol;
- cap = (CATPARM *)PlugSubAlloc(g, NULL, sizeof(CATPARM));
- memset(cap, 0, sizeof(CATPARM));
- cap->Id = fid;
- cap->Qrp = qrp;
- cap->DB = (PUCHAR)db;
- cap->Tab = (PUCHAR)tab;
- cap->Vlen = (SQLLEN* *)PlugSubAlloc(g, NULL, n * sizeof(SQLLEN *));
-
- for (i = 0; i < n; i++)
- cap->Vlen[i] = (SQLLEN *)PlugSubAlloc(g, NULL, m * sizeof(SQLLEN));
-
- cap->Status = (UWORD *)PlugSubAlloc(g, NULL, m * sizeof(UWORD));
-
- fin:
- g->jump_level--;
- return cap;
- } // end of AllocCatInfo
+ try {
+ m = (size_t)qrp->Maxres;
+ n = (size_t)qrp->Nbcol;
+ cap = (CATPARM *)PlugSubAlloc(g, NULL, sizeof(CATPARM));
+ memset(cap, 0, sizeof(CATPARM));
+ cap->Id = fid;
+ cap->Qrp = qrp;
+ cap->DB = db;
+ cap->Tab = tab;
+ cap->Vlen = (SQLLEN* *)PlugSubAlloc(g, NULL, n * sizeof(SQLLEN *));
+
+ for (i = 0; i < n; i++)
+ cap->Vlen[i] = (SQLLEN *)PlugSubAlloc(g, NULL, m * sizeof(SQLLEN));
+
+ cap->Status = (UWORD *)PlugSubAlloc(g, NULL, m * sizeof(UWORD));
+
+ } catch (int n) {
+ htrc("Exeption %d: %s\n", n, g->Message);
+ cap = NULL;
+ } catch (const char *msg) {
+ htrc(g->Message, msg);
+ printf("%s\n", g->Message);
+ cap = NULL;
+ } // end catch
+
+ return cap;
+} // end of AllocCatInfo
#if 0
/***********************************************************************/
@@ -309,8 +305,8 @@ static void ResetNullValues(CATPARM *cap)
/* ODBCColumns: constructs the result blocks containing all columns */
/* 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, bool info, POPARM sop)
+PQRYRES ODBCColumns(PGLOBAL g, PCSZ dsn, PCSZ db, PCSZ table,
+ PCSZ 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,
@@ -383,7 +379,7 @@ PQRYRES ODBCColumns(PGLOBAL g, char *dsn, char *db, char *table,
if (!(cap = AllocCatInfo(g, CAT_COL, db, table, qrp)))
return NULL;
- cap->Pat = (PUCHAR)colpat;
+ cap->Pat = colpat;
/************************************************************************/
/* Now get the results into blocks. */
@@ -618,8 +614,8 @@ PQRYRES ODBCDataSources(PGLOBAL g, int maxres, bool info)
/* ODBCTables: constructs the result blocks containing all tables in */
/* an ODBC database that will be retrieved by GetData commands. */
/**************************************************************************/
-PQRYRES ODBCTables(PGLOBAL g, char *dsn, char *db, char *tabpat,
- char *tabtyp, int maxres, bool info, POPARM sop)
+PQRYRES ODBCTables(PGLOBAL g, PCSZ dsn, PCSZ db, PCSZ tabpat, PCSZ tabtyp,
+ int maxres, bool info, POPARM sop)
{
int buftyp[] = {TYPE_STRING, TYPE_STRING, TYPE_STRING,
TYPE_STRING, TYPE_STRING};
@@ -681,7 +677,7 @@ PQRYRES ODBCTables(PGLOBAL g, char *dsn, char *db, char *tabpat,
if (!(cap = AllocCatInfo(g, CAT_TAB, db, tabpat, qrp)))
return NULL;
- cap->Pat = (PUCHAR)tabtyp;
+ cap->Pat = tabtyp;
if (trace)
htrc("Getting table results ncol=%d\n", cap->Qrp->Nbcol);
@@ -879,7 +875,7 @@ PQRYRES ODBCStatistics(PGLOBAL g, ODBConn *op, char *dsn, char *pat,
/***********************************************************************/
/* Implementation of DBX class. */
/***********************************************************************/
-DBX::DBX(RETCODE rc, PSZ msg)
+DBX::DBX(RETCODE rc, PCSZ msg)
{
m_RC = rc;
m_Msg = msg;
@@ -1020,7 +1016,7 @@ bool ODBConn::Check(RETCODE rc)
/***********************************************************************/
/* DB exception throw routines. */
/***********************************************************************/
-void ODBConn::ThrowDBX(RETCODE rc, PSZ msg, HSTMT hstmt)
+void ODBConn::ThrowDBX(RETCODE rc, PCSZ msg, HSTMT hstmt)
{
DBX* xp = new(m_G) DBX(rc, msg);
@@ -1030,7 +1026,7 @@ void ODBConn::ThrowDBX(RETCODE rc, PSZ msg, HSTMT hstmt)
} // end of ThrowDBX
-void ODBConn::ThrowDBX(PSZ msg)
+void ODBConn::ThrowDBX(PCSZ msg)
{
DBX* xp = new(m_G) DBX(0, "Error");
@@ -1110,7 +1106,7 @@ void ODBConn::OnSetOptions(HSTMT hstmt)
/***********************************************************************/
/* Open: connect to a data source. */
/***********************************************************************/
-int ODBConn::Open(PSZ ConnectString, POPARM sop, DWORD options)
+int ODBConn::Open(PCSZ ConnectString, POPARM sop, DWORD options)
{
PGLOBAL& g = m_G;
//ASSERT_VALID(this);
@@ -1192,7 +1188,7 @@ void ODBConn::AllocConnect(DWORD Options)
#if defined(_DEBUG)
if (Options & traceSQL) {
- SQLSetConnectOption(m_hdbc, SQL_OPT_TRACEFILE, (DWORD)"xodbc.out");
+ SQLSetConnectOption(m_hdbc, SQL_OPT_TRACEFILE, (SQLULEN)"xodbc.out");
SQLSetConnectOption(m_hdbc, SQL_OPT_TRACE, 1);
} // endif
#endif // _DEBUG
@@ -1215,7 +1211,7 @@ void ODBConn::AllocConnect(DWORD Options)
// Turn on cursor lib support
if (Options & useCursorLib)
- rc = SQLSetConnectOption(m_hdbc, SQL_ODBC_CURSORS, SQL_CUR_USE_ODBC);
+ rc = SQLSetConnectOption(m_hdbc, SQL_ODBC_CURSORS, SQL_CUR_USE_DRIVER);
return;
} // end of AllocConnect
@@ -1921,7 +1917,7 @@ bool ODBConn::ExecSQLcommand(char *sql)
/* GetMetaData: constructs the result blocks containing the */
/* description of all the columns of an SQL command. */
/**************************************************************************/
-PQRYRES ODBConn::GetMetaData(PGLOBAL g, char *dsn, char *src)
+PQRYRES ODBConn::GetMetaData(PGLOBAL g, PCSZ dsn, PCSZ src)
{
static int buftyp[] = {TYPE_STRING, TYPE_SHORT, TYPE_INT,
TYPE_SHORT, TYPE_SHORT};
@@ -2244,7 +2240,7 @@ int ODBConn::GetCatInfo(CATPARM *cap)
void *buffer;
int i, irc;
bool b;
- PSZ fnc = "Unknown";
+ PCSZ fnc = "Unknown";
UWORD n;
SWORD ncol, len, tp;
SQLULEN crow = 0;
@@ -2283,22 +2279,20 @@ int ODBConn::GetCatInfo(CATPARM *cap)
// Now do call the proper ODBC API
switch (cap->Id) {
case CAT_TAB:
-// rc = SQLSetStmtAttr(hstmt, SQL_ATTR_METADATA_ID,
-// (SQLPOINTER)false, 0);
fnc = "SQLTables";
rc = SQLTables(hstmt, name.ptr(2), name.length(2),
name.ptr(1), name.length(1),
name.ptr(0), name.length(0),
- cap->Pat, cap->Pat ? SQL_NTS : 0);
+ (SQLCHAR *)cap->Pat,
+ cap->Pat ? SQL_NTS : 0);
break;
case CAT_COL:
-// rc = SQLSetStmtAttr(hstmt, SQL_ATTR_METADATA_ID,
-// (SQLPOINTER)true, 0);
fnc = "SQLColumns";
rc = SQLColumns(hstmt, name.ptr(2), name.length(2),
name.ptr(1), name.length(1),
name.ptr(0), name.length(0),
- cap->Pat, cap->Pat ? SQL_NTS : 0);
+ (SQLCHAR *)cap->Pat,
+ cap->Pat ? SQL_NTS : 0);
break;
case CAT_KEY:
fnc = "SQLPrimaryKeys";
diff --git a/storage/connect/odbconn.h b/storage/connect/odbconn.h
index 063985218ec..5abb8354160 100644
--- a/storage/connect/odbconn.h
+++ b/storage/connect/odbconn.h
@@ -54,9 +54,9 @@ enum CATINFO {CAT_TAB = 1, /* SQLTables */
typedef struct tagCATPARM {
CATINFO Id; // Id to indicate function
PQRYRES Qrp; // Result set pointer
- PUCHAR DB; // Database (Schema)
- PUCHAR Tab; // Table name or pattern
- PUCHAR Pat; // Table type or column pattern
+ PCSZ DB; // Database (Schema)
+ PCSZ Tab; // Table name or pattern
+ PCSZ Pat; // Table type or column pattern
SQLLEN* *Vlen; // To array of indicator values
UWORD *Status; // To status block
// For SQLStatistics
@@ -80,23 +80,23 @@ class DBX : public BLOCK {
friend class ODBConn;
// Construction (by ThrowDBX only) -- destruction
protected:
- DBX(RETCODE rc, PSZ msg = NULL);
+ DBX(RETCODE rc, PCSZ msg = NULL);
public:
//virtual ~DBX() {}
//void operator delete(void*, PGLOBAL, void*) {};
// Implementation (use ThrowDBX to create)
RETCODE GetRC(void) {return m_RC;}
- PSZ GetMsg(void) {return m_Msg;}
- const char *GetErrorMessage(int i);
+ PCSZ GetMsg(void) {return m_Msg;}
+ PCSZ GetErrorMessage(int i);
protected:
bool BuildErrorMessage(ODBConn* pdb, HSTMT hstmt = SQL_NULL_HSTMT);
// Attributes
RETCODE m_RC;
- PSZ m_Msg;
- PSZ m_ErrMsg[MAX_NUM_OF_MSG];
+ PCSZ m_Msg;
+ PCSZ m_ErrMsg[MAX_NUM_OF_MSG];
}; // end of DBX class definition
/***********************************************************************/
@@ -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, POPARM sop, DWORD Options = 0);
+ int Open(PCSZ ConnectString, POPARM sop, DWORD Options = 0);
int Rewind(char *sql, ODBCCOL *tocols);
void Close(void);
PQRYRES AllocateResult(PGLOBAL g);
@@ -131,7 +131,7 @@ class ODBConn : public BLOCK {
bool IsOpen(void) {return m_hdbc != SQL_NULL_HDBC;}
PSZ GetStringInfo(ushort infotype);
int GetMaxValue(ushort infotype);
- PSZ GetConnect(void) {return m_Connect;}
+ PCSZ GetConnect(void) {return m_Connect;}
public:
// Operations
@@ -149,7 +149,7 @@ class ODBConn : public BLOCK {
int GetCatInfo(CATPARM *cap);
bool GetDataSources(PQRYRES qrp);
bool GetDrivers(PQRYRES qrp);
- PQRYRES GetMetaData(PGLOBAL g, char *dsn, char *src);
+ PQRYRES GetMetaData(PGLOBAL g, PCSZ dsn, PCSZ src);
public:
// Set special options
@@ -162,8 +162,8 @@ class ODBConn : public BLOCK {
// ODBC operations
protected:
bool Check(RETCODE rc);
- void ThrowDBX(RETCODE rc, PSZ msg, HSTMT hstmt = SQL_NULL_HSTMT);
- void ThrowDBX(PSZ msg);
+ void ThrowDBX(RETCODE rc, PCSZ msg, HSTMT hstmt = SQL_NULL_HSTMT);
+ void ThrowDBX(PCSZ msg);
void AllocConnect(DWORD dwOptions);
void Connect(void);
bool DriverConnect(DWORD Options);
@@ -187,9 +187,9 @@ class ODBConn : public BLOCK {
DWORD m_UpdateOptions;
DWORD m_RowsetSize;
char m_IDQuoteChar[2];
- PSZ m_Connect;
- PSZ m_User;
- PSZ m_Pwd;
+ PCSZ m_Connect;
+ PCSZ m_User;
+ PCSZ m_Pwd;
int m_Catver;
int m_Rows;
int m_Fetch;
diff --git a/storage/connect/os.h b/storage/connect/os.h
index 2dc603fdcda..8056a272990 100644
--- a/storage/connect/os.h
+++ b/storage/connect/os.h
@@ -17,13 +17,16 @@ typedef off_t off64_t;
#if defined(__WIN__)
typedef __int64 BIGINT;
+typedef _Null_terminated_ const char *PCSZ;
#else // !__WIN__
typedef longlong BIGINT;
#define FILE_BEGIN SEEK_SET
#define FILE_CURRENT SEEK_CUR
#define FILE_END SEEK_END
+typedef const char *PCSZ;
#endif // !__WIN__
+
#if !defined(__WIN__)
typedef const void *LPCVOID;
typedef const char *LPCTSTR;
diff --git a/storage/connect/osutil.c b/storage/connect/osutil.c
index 2e9e120b0c8..66743c7403b 100644
--- a/storage/connect/osutil.c
+++ b/storage/connect/osutil.c
@@ -43,34 +43,6 @@ PSZ strlwr(PSZ p)
return (p);
} /* end of strlwr */
-#if defined(NOT_USED) /*&& !defined(sun) && !defined(LINUX) && !defined(AIX)*/
-/***********************************************************************/
-/* Define stricmp function not existing in some UNIX libraries. */
-/***********************************************************************/
-int stricmp(char *str1, char *str2)
- {
- register int i;
- int n;
- char c;
- char *sup1 = malloc(strlen(str1) + 1);
- char *sup2 = malloc(strlen(str2) + 1);
-
- for (i = 0; c = str1[i]; i++)
- sup1[i] = toupper(c);
-
- sup1[i] = 0;
-
- for (i = 0; c = str2[i]; i++)
- sup2[i] = toupper(c);
-
- sup2[i] = 0;
- n = strcmp(sup1, sup2);
- free(sup1);
- free(sup2);
- return (n);
- } /* end of stricmp */
-#endif /* sun */
-
/***********************************************************************/
/* Define the splitpath function not existing in the UNIX library. */
/***********************************************************************/
@@ -143,13 +115,6 @@ my_bool CloseFileHandle(HANDLE h)
return (close(h)) ? TRUE : FALSE;
} /* end of CloseFileHandle */
-#if 0
-void Sleep(DWORD time)
- {
- //FIXME: TODO
- } /* end of Sleep */
-#endif
-
int GetLastError()
{
return errno;
@@ -210,21 +175,4 @@ BOOL MessageBeep(uint i __attribute__((unused)))
return TRUE;
} /* end of MessageBeep */
-#if 0
-/* This function is ridiculous and should be revisited */
-DWORD FormatMessage(DWORD dwFlags, LPCVOID lpSource, DWORD dwMessageId,
- DWORD dwLanguageId, LPSTR lpBuffer, DWORD nSize, ...)
- {
- char buff[32];
- int n;
-
-//if (dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER)
-// return 0; /* means error */
-
- n = sprintf(buff, "Error code: %d", (int) dwMessageId);
- strncpy(lpBuffer, buff, nSize);
- return min(n, nSize);
- } /* end of FormatMessage */
-#endif
-
#endif // UNIX
diff --git a/storage/connect/plgdbsem.h b/storage/connect/plgdbsem.h
index 800b1098d50..2198c44c200 100644
--- a/storage/connect/plgdbsem.h
+++ b/storage/connect/plgdbsem.h
@@ -80,7 +80,8 @@ enum TABTYPE {TAB_UNDEF = 0, /* Table of undefined type */
TAB_DMY = 25, /* DMY Dummy tables NIY */
TAB_JDBC = 26, /* Table accessed via JDBC */
TAB_ZIP = 27, /* ZIP file info table */
- TAB_NIY = 28}; /* Table not implemented yet */
+// TAB_MONGO = 28, /* Table retrieved from MongoDB */
+ TAB_NIY = 30}; /* Table not implemented yet */
enum AMT {TYPE_AM_ERROR = 0, /* Type not defined */
TYPE_AM_ROWID = 1, /* ROWID type (special column) */
@@ -143,7 +144,8 @@ enum AMT {TYPE_AM_ERROR = 0, /* Type not defined */
TYPE_AM_MYX = 193, /* MYSQL EXEC access method type */
TYPE_AM_CAT = 195, /* Catalog access method type no */
TYPE_AM_ZIP = 198, /* ZIP access method type no */
- TYPE_AM_OUT = 200}; /* Output relations (storage) */
+ TYPE_AM_MGO = 199, /* MGO access method type no */
+ TYPE_AM_OUT = 200}; /* Output relations (storage) */
enum RECFM {RECFM_NAF = -2, /* Not a file */
RECFM_OEM = -1, /* OEM file access method */
@@ -553,7 +555,7 @@ typedef struct _qryres {
typedef struct _colres {
PCOLRES Next; /* To next result column */
PCOL Colp; /* To matching column block */
- PSZ Name; /* Column header */
+ PCSZ Name; /* Column header */
PVBLK Kdata; /* Column block of values */
char *Nulls; /* Column null value array */
int Type; /* Internal type */
@@ -583,7 +585,7 @@ void PlugLineDB(PGLOBAL, PSZ, short, void *, uint);
char *SetPath(PGLOBAL g, const char *path);
char *ExtractFromPath(PGLOBAL, char *, char *, OPVAL);
void AddPointer(PTABS, void *);
-PDTP MakeDateFormat(PGLOBAL, PSZ, bool, bool, int);
+PDTP MakeDateFormat(PGLOBAL, PCSZ, bool, bool, int);
int ExtractDate(char *, PDTP, int, int val[6]);
/**************************************************************************/
@@ -615,11 +617,10 @@ DllExport void *PlgDBrealloc(PGLOBAL, void *, MBLOCK&, size_t);
DllExport void NewPointer(PTABS, void *, void *);
//lExport char *GetIni(int n= 0); // Not used anymore
DllExport void SetTrc(void);
-DllExport char *GetListOption(PGLOBAL, const char *, const char *,
- const char *def=NULL);
-DllExport char *GetStringTableOption(PGLOBAL, PTOS, char *, char *);
-DllExport bool GetBooleanTableOption(PGLOBAL, PTOS, char *, bool);
-DllExport int GetIntegerTableOption(PGLOBAL, PTOS, char *, int);
+DllExport PCSZ GetListOption(PGLOBAL, PCSZ, PCSZ, PCSZ def=NULL);
+DllExport PCSZ GetStringTableOption(PGLOBAL, PTOS, PCSZ, PCSZ);
+DllExport bool GetBooleanTableOption(PGLOBAL, PTOS, PCSZ, bool);
+DllExport int GetIntegerTableOption(PGLOBAL, PTOS, PCSZ, int);
#define MSGID_NONE 0
#define MSGID_CANNOT_OPEN 1
diff --git a/storage/connect/plgdbutl.cpp b/storage/connect/plgdbutl.cpp
index 52c6058393f..d990f082e5b 100644
--- a/storage/connect/plgdbutl.cpp
+++ b/storage/connect/plgdbutl.cpp
@@ -238,88 +238,84 @@ void ptrc(char const *fmt, ...)
PQRYRES PlgAllocResult(PGLOBAL g, int ncol, int maxres, int ids,
int *buftyp, XFLD *fldtyp,
unsigned int *length, bool blank, bool nonull)
- {
+{
char cname[NAM_LEN+1];
int i;
PCOLRES *pcrp, crp;
PQRYRES qrp;
- // Save stack and allocation environment and prepare error return
- if (g->jump_level == MAX_JUMP) {
- strcpy(g->Message, MSG(TOO_MANY_JUMPS));
- return NULL;
- } // endif jump_level
-
- if (setjmp(g->jumper[++g->jump_level]) != 0) {
- printf("%s\n", g->Message);
- qrp = NULL;
- goto fin;
- } // endif rc
-
- /************************************************************************/
- /* Allocate the structure used to contain the result set. */
- /************************************************************************/
- qrp = (PQRYRES)PlugSubAlloc(g, NULL, sizeof(QRYRES));
- pcrp = &qrp->Colresp;
- qrp->Continued = false;
- qrp->Truncated = false;
- qrp->Info = false;
- qrp->Suball = true;
- qrp->Maxres = maxres;
- qrp->Maxsize = 0;
- qrp->Nblin = 0;
- qrp->Nbcol = 0; // will be ncol
- qrp->Cursor = 0;
- qrp->BadLines = 0;
-
- for (i = 0; i < ncol; i++) {
- *pcrp = (PCOLRES)PlugSubAlloc(g, NULL, sizeof(COLRES));
- crp = *pcrp;
- pcrp = &crp->Next;
- memset(crp, 0, sizeof(COLRES));
- crp->Colp = NULL;
- crp->Ncol = ++qrp->Nbcol;
- crp->Type = buftyp[i];
- crp->Length = length[i];
- crp->Clen = GetTypeSize(crp->Type, length[i]);
- crp->Prec = 0;
-
- if (ids > 0) {
+ try {
+ /**********************************************************************/
+ /* Allocate the structure used to contain the result set. */
+ /**********************************************************************/
+ qrp = (PQRYRES)PlugSubAlloc(g, NULL, sizeof(QRYRES));
+ pcrp = &qrp->Colresp;
+ qrp->Continued = false;
+ qrp->Truncated = false;
+ qrp->Info = false;
+ qrp->Suball = true;
+ qrp->Maxres = maxres;
+ qrp->Maxsize = 0;
+ qrp->Nblin = 0;
+ qrp->Nbcol = 0; // will be ncol
+ qrp->Cursor = 0;
+ qrp->BadLines = 0;
+
+ for (i = 0; i < ncol; i++) {
+ *pcrp = (PCOLRES)PlugSubAlloc(g, NULL, sizeof(COLRES));
+ crp = *pcrp;
+ pcrp = &crp->Next;
+ memset(crp, 0, sizeof(COLRES));
+ crp->Colp = NULL;
+ crp->Ncol = ++qrp->Nbcol;
+ crp->Type = buftyp[i];
+ crp->Length = length[i];
+ crp->Clen = GetTypeSize(crp->Type, length[i]);
+ crp->Prec = 0;
+
+ if (ids > 0) {
#if defined(XMSG)
- // Get header from message file
- strncpy(cname, PlugReadMessage(g, ids + crp->Ncol, NULL), NAM_LEN);
- cname[NAM_LEN] = 0; // for truncated long names
+ // Get header from message file
+ strncpy(cname, PlugReadMessage(g, ids + crp->Ncol, NULL), NAM_LEN);
+ cname[NAM_LEN] = 0; // for truncated long names
#else // !XMSG
- GetRcString(ids + crp->Ncol, cname, sizeof(cname));
+ GetRcString(ids + crp->Ncol, cname, sizeof(cname));
#endif // !XMSG
- crp->Name = (PSZ)PlugDup(g, cname);
- } else
- crp->Name = NULL; // Will be set by caller
+ crp->Name = (PSZ)PlugDup(g, cname);
+ } else
+ crp->Name = NULL; // Will be set by caller
- if (fldtyp)
- crp->Fld = fldtyp[i];
- else
- crp->Fld = FLD_NO;
+ if (fldtyp)
+ crp->Fld = fldtyp[i];
+ else
+ crp->Fld = FLD_NO;
- // Allocate the Value Block that will contain data
- if (crp->Length || nonull)
- crp->Kdata = AllocValBlock(g, NULL, crp->Type, maxres,
- crp->Length, 0, true, blank, false);
- else
- crp->Kdata = NULL;
+ // Allocate the Value Block that will contain data
+ if (crp->Length || nonull)
+ crp->Kdata = AllocValBlock(g, NULL, crp->Type, maxres,
+ crp->Length, 0, true, blank, false);
+ else
+ crp->Kdata = NULL;
- if (trace)
- htrc("Column(%d) %s type=%d len=%d value=%p\n",
- crp->Ncol, crp->Name, crp->Type, crp->Length, crp->Kdata);
+ if (trace)
+ htrc("Column(%d) %s type=%d len=%d value=%p\n",
+ crp->Ncol, crp->Name, crp->Type, crp->Length, crp->Kdata);
- } // endfor i
+ } // endfor i
- *pcrp = NULL;
+ *pcrp = NULL;
- fin:
- g->jump_level--;
- return qrp;
- } // end of PlgAllocResult
+ } catch (int n) {
+ htrc("Exception %d: %s\n", n, g->Message);
+ qrp = NULL;
+ } catch (const char *msg) {
+ strcpy(g->Message, msg);
+ htrc("%s\n", g->Message);
+ qrp = NULL;
+ } // end catch
+
+ return qrp;
+} // end of PlgAllocResult
/***********************************************************************/
/* Allocate and initialize the new DB User Block. */
@@ -365,8 +361,8 @@ PCATLG PlgGetCatalog(PGLOBAL g, bool jump)
if (!cat && jump) {
// Raise exception so caller doesn't have to check return value
strcpy(g->Message, MSG(NO_ACTIVE_DB));
- longjmp(g->jumper[g->jump_level], 1);
- } // endif cat
+ throw 1;
+ } // endif cat
return cat;
} // end of PlgGetCatalog
@@ -391,26 +387,27 @@ char *SetPath(PGLOBAL g, const char *path)
char *buf= NULL;
if (path) {
- size_t len= strlen(path) + (*path != '.' ? 4 : 1);
+ size_t len = strlen(path) + (*path != '.' ? 4 : 1);
+
+ if (!(buf = (char*)PlgDBSubAlloc(g, NULL, len)))
+ return NULL;
- buf= (char*)PlugSubAlloc(g, NULL, len);
-
if (PlugIsAbsolutePath(path)) {
- strcpy(buf, path);
- return buf;
- } // endif path
+ strcpy(buf, path);
+ return buf;
+ } // endif path
if (*path != '.') {
#if defined(__WIN__)
- char *s= "\\";
+ const char *s = "\\";
#else // !__WIN__
- char *s= "/";
+ const char *s = "/";
#endif // !__WIN__
strcat(strcat(strcat(strcpy(buf, "."), s), path), s);
} else
strcpy(buf, path);
- } // endif path
+ } // endif path
return buf;
} // end of SetPath
@@ -448,7 +445,7 @@ char *ExtractFromPath(PGLOBAL g, char *pBuff, char *FileName, OPVAL op)
static bool PlugCheckPattern(PGLOBAL g, LPCSTR string, LPCSTR pat)
{
if (pat && strlen(pat)) {
- // This leaves 512 bytes (MAX_STR / 2) for each components
+ // This leaves 2048 bytes (MAX_STR / 2) for each components
LPSTR name = g->Message + MAX_STR / 2;
strlwr(strcpy(name, string));
@@ -476,8 +473,8 @@ bool PlugEvalLike(PGLOBAL g, LPCSTR strg, LPCSTR pat, bool ci)
tp = g->Message;
else if (!(tp = new char[strlen(pat) + strlen(strg) + 2])) {
strcpy(g->Message, MSG(NEW_RETURN_NULL));
- longjmp(g->jumper[g->jump_level], OP_LIKE);
- } /* endif tp */
+ throw OP_LIKE;
+ } /* endif tp */
sp = tp + strlen(pat) + 1;
strlwr(strcpy(tp, pat)); /* Make a lower case copy of pat */
@@ -487,8 +484,8 @@ bool PlugEvalLike(PGLOBAL g, LPCSTR strg, LPCSTR pat, bool ci)
tp = g->Message; /* Use this as temporary work space. */
else if (!(tp = new char[strlen(pat) + 1])) {
strcpy(g->Message, MSG(NEW_RETURN_NULL));
- longjmp(g->jumper[g->jump_level], OP_LIKE);
- } /* endif tp */
+ throw OP_LIKE;
+ } /* endif tp */
strcpy(tp, pat); /* Make a copy to be worked into */
sp = (char*)strg;
@@ -676,7 +673,7 @@ void PlugConvertConstant(PGLOBAL g, void* & value, short& type)
/* format and a Strftime output format. Flag if not 0 indicates that */
/* non quoted blanks are not included in the output format. */
/***********************************************************************/
-PDTP MakeDateFormat(PGLOBAL g, PSZ dfmt, bool in, bool out, int flag)
+PDTP MakeDateFormat(PGLOBAL g, PCSZ dfmt, bool in, bool out, int flag)
{
int rc;
PDTP pdp = (PDTP)PlugSubAlloc(g, NULL, sizeof(DATPAR));
@@ -685,7 +682,7 @@ PDTP MakeDateFormat(PGLOBAL g, PSZ dfmt, bool in, bool out, int flag)
htrc("MakeDateFormat: dfmt=%s\n", dfmt);
memset(pdp, 0, sizeof(DATPAR));
- pdp->Format = pdp->Curp = dfmt;
+ pdp->Format = pdp->Curp = PlugDup(g, dfmt);
pdp->Outsize = 2 * strlen(dfmt) + 1;
if (in)
@@ -727,10 +724,11 @@ PDTP MakeDateFormat(PGLOBAL g, PSZ dfmt, bool in, bool out, int flag)
/***********************************************************************/
int ExtractDate(char *dts, PDTP pdp, int defy, int val[6])
{
- char *fmt, c, d, e, W[8][12];
- int i, k, m, numval;
- int n, y = 30;
- bool b = true; // true for null dates
+ PCSZ fmt;
+ char c, d, e, W[8][12];
+ int i, k, m, numval;
+ int n, y = 30;
+ bool b = true; // true for null dates
if (pdp)
fmt = pdp->InFmt;
@@ -1255,7 +1253,7 @@ void *PlgDBalloc(PGLOBAL g, void *area, MBLOCK& mp)
// in the area, do allocate from virtual storage.
#if defined(__WIN__)
if (mp.Size >= BIGMEM)
- mp.Memp = VirtualAlloc(NULL, mp.Size, MEM_COMMIT, PAGE_READWRITE);
+ mp.Memp = VirtualAlloc(NULL, mp.Size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
else
#endif
mp.Memp = malloc(mp.Size);
@@ -1520,8 +1518,8 @@ DllExport void NewPointer(PTABS t, void *oldv, void *newv)
PGLOBAL g = t->G;
sprintf(g->Message, "NewPointer: %s", MSG(MEM_ALLOC_ERROR));
- longjmp(g->jumper[g->jump_level], 3);
- } else {
+ throw 3;
+ } else {
tp->Next = t->P1;
tp->Num = 0;
t->P1 = tp;
@@ -1557,15 +1555,15 @@ int FileComp(PGLOBAL g, char *file1, char *file2)
sprintf(g->Message, MSG(OPEN_MODE_ERROR),
"rb", (int)errno, fn[i]);
strcat(strcat(g->Message, ": "), strerror(errno));
- longjmp(g->jumper[g->jump_level], 666);
-// } else
+ throw 666;
+ // } else
// len[i] = 0; // File does not exist yet
} else {
if ((len[i] = _filelength(h[i])) < 0) {
sprintf(g->Message, MSG(FILELEN_ERROR), "_filelength", fn[i]);
- longjmp(g->jumper[g->jump_level], 666);
- } // endif len
+ throw 666;
+ } // endif len
} // endif h
diff --git a/storage/connect/plgxml.cpp b/storage/connect/plgxml.cpp
index eb31e24235b..f3d3a010266 100644
--- a/storage/connect/plgxml.cpp
+++ b/storage/connect/plgxml.cpp
@@ -45,7 +45,7 @@ XMLDOCUMENT::XMLDOCUMENT(char *nsl, char *nsdf, char *enc)
/******************************************************************/
/* Initialize zipped file processing. */
/******************************************************************/
-bool XMLDOCUMENT::InitZip(PGLOBAL g, char *entry)
+bool XMLDOCUMENT::InitZip(PGLOBAL g, PCSZ entry)
{
#if defined(ZIP_SUPPORT)
bool mul = (entry) ? strchr(entry, '*') || strchr(entry, '?') : false;
@@ -173,7 +173,7 @@ void XMLNODE::Delete(PXNODE dnp)
/******************************************************************/
/* Store a string in Buf, enventually reallocating it. */
/******************************************************************/
-char *XMLNODE::BufAlloc(PGLOBAL g, char *p, int n)
+char *XMLNODE::BufAlloc(PGLOBAL g, const char *p, int n)
{
if (Len < n) {
Len = n;
diff --git a/storage/connect/plgxml.h b/storage/connect/plgxml.h
index 6870764c503..82629e4c7db 100644
--- a/storage/connect/plgxml.h
+++ b/storage/connect/plgxml.h
@@ -76,9 +76,9 @@ class XMLDOCUMENT : public BLOCK {
virtual void SetNofree(bool b) = 0;
// Methods
- virtual bool Initialize(PGLOBAL, char *, bool) = 0;
+ virtual bool Initialize(PGLOBAL, PCSZ, bool) = 0;
virtual bool ParseFile(PGLOBAL, char *) = 0;
- virtual bool NewDoc(PGLOBAL, char *) = 0;
+ virtual bool NewDoc(PGLOBAL, PCSZ) = 0;
virtual void AddComment(PGLOBAL, char *) = 0;
virtual PXNODE GetRoot(PGLOBAL) = 0;
virtual PXNODE NewRoot(PGLOBAL, char *) = 0;
@@ -95,7 +95,7 @@ class XMLDOCUMENT : public BLOCK {
// Utility
bool MakeNSlist(PGLOBAL g);
- bool InitZip(PGLOBAL g, char *entry);
+ bool InitZip(PGLOBAL g, PCSZ entry);
char *GetMemDoc(PGLOBAL g, char *fn);
void CloseZip(void);
@@ -131,15 +131,15 @@ class XMLNODE : public BLOCK {
virtual PXLIST SelectNodes(PGLOBAL, char *, PXLIST = NULL) = 0;
virtual PXNODE SelectSingleNode(PGLOBAL, char *, PXNODE = NULL) = 0;
virtual PXATTR GetAttribute(PGLOBAL, char *, PXATTR = NULL) = 0;
- virtual PXNODE AddChildNode(PGLOBAL, char *, PXNODE = NULL) = 0;
+ virtual PXNODE AddChildNode(PGLOBAL, PCSZ, PXNODE = NULL) = 0;
virtual PXATTR AddProperty(PGLOBAL, char *, PXATTR = NULL) = 0;
- virtual void AddText(PGLOBAL, char *) = 0;
+ virtual void AddText(PGLOBAL, PCSZ) = 0;
virtual void DeleteChild(PGLOBAL, PXNODE) = 0;
protected:
PXNODE NewChild(PXNODE ncp);
void Delete(PXNODE dnp);
- char *BufAlloc(PGLOBAL g, char *p, int n);
+ char *BufAlloc(PGLOBAL g, const char *p, int n);
// Constructor
XMLNODE(PXDOC dp);
diff --git a/storage/connect/plugutil.c b/storage/connect/plugutil.cpp
index bfac8a5fd99..f0822526b98 100644
--- a/storage/connect/plugutil.c
+++ b/storage/connect/plugutil.cpp
@@ -139,31 +139,39 @@ PGLOBAL PlugInit(LPCSTR Language, uint worksize)
htrc("PlugInit: Language='%s'\n",
((!Language) ? "Null" : (char*)Language));
- if (!(g = malloc(sizeof(GLOBAL)))) {
- fprintf(stderr, MSG(GLOBAL_ERROR), (int)sizeof(GLOBAL));
- return NULL;
- } else {
+ try {
+ g = new GLOBAL;
+ } catch (...) {
+ fprintf(stderr, MSG(GLOBAL_ERROR), (int)sizeof(GLOBAL));
+ return NULL;
+ } // end try/catch
+
+ //if (!(g = (PGLOBAL)malloc(sizeof(GLOBAL)))) {
+ // fprintf(stderr, MSG(GLOBAL_ERROR), (int)sizeof(GLOBAL));
+ // return NULL;
+ // } else {
g->Sarea = NULL;
g->Createas = 0;
g->Alchecked = 0;
g->Mrr = 0;
- g->Activityp = g->ActivityStart = NULL;
+ g->Activityp = NULL;
g->Xchk = NULL;
g->N = 0;
+ g->More = 0;
strcpy(g->Message, "");
/*******************************************************************/
/* Allocate the main work segment. */
/*******************************************************************/
if (worksize && !(g->Sarea = PlugAllocMem(g, worksize))) {
- char errmsg[256];
+ char errmsg[MAX_STR];
sprintf(errmsg, MSG(WORK_AREA), g->Message);
strcpy(g->Message, errmsg);
g->Sarea_Size = 0;
} else
g->Sarea_Size = worksize;
- } /* endif g */
+ //} /* endif g */
g->jump_level = -1; /* New setting to allow recursive call of Plug */
return(g);
@@ -182,7 +190,7 @@ int PlugExit(PGLOBAL g)
if (g->Sarea)
free(g->Sarea);
- free(g);
+ delete g;
return rc;
} /* end of PlugExit */
@@ -475,7 +483,7 @@ void *PlugAllocMem(PGLOBAL g, uint size)
/***********************************************************************/
BOOL PlugSubSet(PGLOBAL g __attribute__((unused)), void *memp, uint size)
{
- PPOOLHEADER pph = memp;
+ PPOOLHEADER pph = (PPOOLHEADER)memp;
pph->To_Free = (OFFSET)sizeof(POOLHEADER);
pph->FreeBlk = size - pph->To_Free;
@@ -501,7 +509,6 @@ void *PlugSubAlloc(PGLOBAL g, void *memp, size_t size)
/*******************************************************************/
memp = g->Sarea;
-//size = ((size + 3) / 4) * 4; /* Round up size to multiple of 4 */
size = ((size + 7) / 8) * 8; /* Round up size to multiple of 8 */
pph = (PPOOLHEADER)memp;
@@ -510,26 +517,24 @@ void *PlugSubAlloc(PGLOBAL g, void *memp, size_t size)
memp, size, pph->To_Free, pph->FreeBlk);
if ((uint)size > pph->FreeBlk) { /* Not enough memory left in pool */
- char *pname = "Work";
+ PCSZ pname = "Work";
sprintf(g->Message,
"Not enough memory in %s area for request of %u (used=%d free=%d)",
- pname, (uint) size, pph->To_Free, pph->FreeBlk);
+ pname, (uint)size, pph->To_Free, pph->FreeBlk);
if (trace)
htrc("PlugSubAlloc: %s\n", g->Message);
- /* Nothing we can do if longjmp is not initialized. */
- assert(g->jump_level >= 0);
- longjmp(g->jumper[g->jump_level], 1);
+ throw 1234;
} /* endif size OS32 code */
/*********************************************************************/
/* Do the suballocation the simplest way. */
/*********************************************************************/
memp = MakePtr(memp, pph->To_Free); /* Points to suballocated block */
- pph->To_Free += size; /* New offset of pool free block */
- pph->FreeBlk -= size; /* New size of pool free block */
+ pph->To_Free += (OFFSET)size; /* New offset of pool free block */
+ pph->FreeBlk -= (uint)size; /* New size of pool free block */
if (trace > 3)
htrc("Done memp=%p used=%d free=%d\n",
diff --git a/storage/connect/preparse.h b/storage/connect/preparse.h
index 2892a958bdd..f16624548fb 100644
--- a/storage/connect/preparse.h
+++ b/storage/connect/preparse.h
@@ -7,14 +7,14 @@
/* Struct of variables used by the date format pre-parser. */
/***********************************************************************/
typedef struct _datpar {
- char *Format; // Points to format to decode
+ const char *Format; // Points to format to decode
char *Curp; // Points to current parsing position
char *InFmt; // Start of input format
char *OutFmt; // Start of output format
int Index[8]; // Indexes of date values
int Num; // Number of values to retrieve
int Flag; // 1: Input, 2: Output, 4: no output blank
- int Outsize; // Size of output buffers
+ int Outsize; // Size of output buffers
} DATPAR, *PDTP;
/***********************************************************************/
diff --git a/storage/connect/reldef.cpp b/storage/connect/reldef.cpp
index 0bb7adcce83..50c8b1ffc29 100644
--- a/storage/connect/reldef.cpp
+++ b/storage/connect/reldef.cpp
@@ -88,7 +88,7 @@ PTOS RELDEF::GetTopt(void)
/***********************************************************************/
/* This function sets an integer table information. */
/***********************************************************************/
-bool RELDEF::SetIntCatInfo(PSZ what, int n)
+bool RELDEF::SetIntCatInfo(PCSZ what, int n)
{
return Hc->SetIntegerOption(what, n);
} // end of SetIntCatInfo
@@ -96,7 +96,7 @@ bool RELDEF::SetIntCatInfo(PSZ what, int n)
/***********************************************************************/
/* This function returns integer table information. */
/***********************************************************************/
-int RELDEF::GetIntCatInfo(PSZ what, int idef)
+int RELDEF::GetIntCatInfo(PCSZ what, int idef)
{
int n= Hc->GetIntegerOption(what);
@@ -106,7 +106,7 @@ int RELDEF::GetIntCatInfo(PSZ what, int idef)
/***********************************************************************/
/* This function returns Boolean table information. */
/***********************************************************************/
-bool RELDEF::GetBoolCatInfo(PSZ what, bool bdef)
+bool RELDEF::GetBoolCatInfo(PCSZ what, bool bdef)
{
bool b= Hc->GetBooleanOption(what, bdef);
@@ -116,9 +116,10 @@ bool RELDEF::GetBoolCatInfo(PSZ what, bool bdef)
/***********************************************************************/
/* This function returns size catalog information. */
/***********************************************************************/
-int RELDEF::GetSizeCatInfo(PSZ what, PSZ sdef)
+int RELDEF::GetSizeCatInfo(PCSZ what, PCSZ sdef)
{
- char * s, c;
+ char c;
+ PCSZ s;
int i, n= 0;
if (!(s= Hc->GetStringOption(what)))
@@ -139,9 +140,9 @@ int RELDEF::GetSizeCatInfo(PSZ what, PSZ sdef)
/***********************************************************************/
/* This function sets char table information in buf. */
/***********************************************************************/
-int RELDEF::GetCharCatInfo(PSZ what, PSZ sdef, char *buf, int size)
+int RELDEF::GetCharCatInfo(PCSZ what, PCSZ sdef, char *buf, int size)
{
- char *s= Hc->GetStringOption(what);
+ PCSZ s= Hc->GetStringOption(what);
strncpy(buf, ((s) ? s : sdef), size);
return size;
@@ -159,9 +160,10 @@ bool RELDEF::Partitioned(void)
/* This function returns string table information. */
/* Default parameter is "*" to get the handler default. */
/***********************************************************************/
-char *RELDEF::GetStringCatInfo(PGLOBAL g, PSZ what, PSZ sdef)
+char *RELDEF::GetStringCatInfo(PGLOBAL g, PCSZ what, PCSZ sdef)
{
- char *name, *sval= NULL, *s= Hc->GetStringOption(what, sdef);
+ char *sval = NULL;
+ PCSZ name, s= Hc->GetStringOption(what, sdef);
if (s) {
if (!Hc->IsPartitioned() ||
@@ -169,12 +171,12 @@ char *RELDEF::GetStringCatInfo(PGLOBAL g, PSZ what, PSZ sdef)
&& stricmp(what, "connect")))
sval= PlugDup(g, s);
else
- sval= s;
+ sval= (char*)s;
} else if (!stricmp(what, "filename")) {
// Return default file name
- char *ftype= Hc->GetStringOption("Type", "*");
- int i, n;
+ PCSZ ftype= Hc->GetStringOption("Type", "*");
+ int i, n;
if (IsFileType(GetTypeID(ftype))) {
name= Hc->GetPartName();
@@ -252,9 +254,9 @@ bool TABDEF::Define(PGLOBAL g, PCATLG cat,
/***********************************************************************/
/* This function returns the database data path. */
/***********************************************************************/
-PSZ TABDEF::GetPath(void)
+PCSZ TABDEF::GetPath(void)
{
- return (Database) ? (PSZ)Database : (Hc) ? Hc->GetDataPath() : NULL;
+ return (Database) ? Database : (Hc) ? Hc->GetDataPath() : NULL;
} // end of GetPath
/***********************************************************************/
@@ -278,8 +280,13 @@ int TABDEF::GetColCatInfo(PGLOBAL g)
// Take care of the column definitions
i= poff= nof= nlg= 0;
+#if defined(__WIN__)
// Offsets of HTML and DIR tables start from 0, DBF at 1
- loff= (tc == TAB_DBF) ? 1 : (tc == TAB_XML || tc == TAB_DIR) ? -1 : 0;
+ loff= (tc == TAB_DBF) ? 1 : (tc == TAB_XML || tc == TAB_DIR) ? -1 : 0;
+#else // !__WIN__
+ // Offsets of HTML tables start from 0, DIR and DBF at 1
+ loff = (tc == TAB_DBF || tc == TAB_DIR) ? 1 : (tc == TAB_XML) ? -1 : 0;
+#endif // !__WIN__
while (true) {
// Default Offset depends on table type
@@ -611,9 +618,10 @@ bool OEMDEF::DefineAM(PGLOBAL g, LPCSTR, int)
if (!*Module)
Module = Subtype;
- Desc = (char*)PlugSubAlloc(g, NULL, strlen(Module)
- + strlen(Subtype) + 3);
- sprintf(Desc, "%s(%s)", Module, Subtype);
+ char *desc = (char*)PlugSubAlloc(g, NULL, strlen(Module)
+ + strlen(Subtype) + 3);
+ sprintf(desc, "%s(%s)", Module, Subtype);
+ Desc = desc;
return false;
} // end of DefineAM
diff --git a/storage/connect/reldef.h b/storage/connect/reldef.h
index 52a131dbf3d..8b19a413ade 100644
--- a/storage/connect/reldef.h
+++ b/storage/connect/reldef.h
@@ -42,13 +42,13 @@ class DllExport RELDEF : public BLOCK { // Relation definition block
// Methods
PTOS GetTopt(void);
- bool GetBoolCatInfo(PSZ what, bool bdef);
- bool SetIntCatInfo(PSZ what, int ival);
+ bool GetBoolCatInfo(PCSZ what, bool bdef);
+ bool SetIntCatInfo(PCSZ what, int ival);
bool Partitioned(void);
- int GetIntCatInfo(PSZ what, int idef);
- int GetSizeCatInfo(PSZ what, PSZ sdef);
- int GetCharCatInfo(PSZ what, PSZ sdef, char *buf, int size);
- char *GetStringCatInfo(PGLOBAL g, PSZ what, PSZ sdef);
+ int GetIntCatInfo(PCSZ what, int idef);
+ int GetSizeCatInfo(PCSZ what, PCSZ sdef);
+ int GetCharCatInfo(PCSZ what, PCSZ sdef, char *buf, int size);
+ char *GetStringCatInfo(PGLOBAL g, PCSZ what, PCSZ sdef);
virtual int Indexable(void) {return 0;}
virtual bool Define(PGLOBAL g, PCATLG cat,
LPCSTR name, LPCSTR schema, LPCSTR am) = 0;
@@ -84,7 +84,7 @@ public:
void SetNext(PTABDEF tdfp) {Next = tdfp;}
int GetMultiple(void) {return Multiple;}
int GetPseudo(void) {return Pseudo;}
- PSZ GetPath(void);
+ PCSZ GetPath(void);
//PSZ GetPath(void)
// {return (Database) ? (PSZ)Database : Cat->GetDataPath();}
bool SepIndex(void) {return GetBoolCatInfo("SepIndex", false);}
@@ -105,8 +105,8 @@ public:
protected:
// Members
- PSZ Schema; /* Table schema (for ODBC) */
- PSZ Desc; /* Table description */
+ PCSZ Schema; /* Table schema (for ODBC) */
+ PCSZ Desc; /* Table description */
uint Catfunc; /* Catalog function ID */
int Card; /* (max) number of rows in table */
int Elemt; /* Number of rows in blocks or rowset */
diff --git a/storage/connect/tabdos.cpp b/storage/connect/tabdos.cpp
index 2da92741e4f..21b64a41684 100644
--- a/storage/connect/tabdos.cpp
+++ b/storage/connect/tabdos.cpp
@@ -1,11 +1,11 @@
/************* TabDos C++ Program Source Code File (.CPP) **************/
/* PROGRAM NAME: TABDOS */
/* ------------- */
-/* Version 4.9.2 */
+/* Version 4.9.3 */
/* */
/* COPYRIGHT: */
/* ---------- */
-/* (C) Copyright to the author Olivier BERTRAND 1998-2016 */
+/* (C) Copyright to the author Olivier BERTRAND 1998-2017 */
/* */
/* WHAT THIS PROGRAM DOES: */
/* ----------------------- */
@@ -98,6 +98,7 @@ DOSDEF::DOSDEF(void)
Ofn = NULL;
Entry = NULL;
To_Indx = NULL;
+ Pwd = NULL;
Recfm = RECFM_VAR;
Mapped = false;
Zipped = false;
@@ -131,7 +132,7 @@ bool DOSDEF::DefineAM(PGLOBAL g, LPCSTR am, int)
bool map = (am && (*am == 'M' || *am == 'm'));
LPCSTR dfm = (am && (*am == 'F' || *am == 'f')) ? "F"
: (am && (*am == 'B' || *am == 'b')) ? "B"
- : (am && !stricmp(am, "DBF")) ? "D" : "V";
+ : (am && !stricmp(am, "DBF")) ? "D" : "V";
if ((Zipped = GetBoolCatInfo("Zipped", false))) {
Entry = GetStringCatInfo(g, "Entry", NULL);
@@ -139,14 +140,15 @@ bool DOSDEF::DefineAM(PGLOBAL g, LPCSTR am, int)
: false;
Mulentries = GetBoolCatInfo("Mulentries", Mulentries);
Append = GetBoolCatInfo("Append", false);
- }
+ Pwd = GetStringCatInfo(g, "Password", NULL);
+ } // endif Zipped
Desc = Fn = GetStringCatInfo(g, "Filename", NULL);
Ofn = GetStringCatInfo(g, "Optname", Fn);
GetCharCatInfo("Recfm", (PSZ)dfm, buf, sizeof(buf));
Recfm = (toupper(*buf) == 'F') ? RECFM_FIX :
(toupper(*buf) == 'B') ? RECFM_BIN :
- (toupper(*buf) == 'D') ? RECFM_DBF : RECFM_VAR;
+ (toupper(*buf) == 'D') ? RECFM_DBF : RECFM_VAR;
Lrecl = GetIntCatInfo("Lrecl", 0);
if (Recfm != RECFM_DBF)
@@ -180,7 +182,7 @@ bool DOSDEF::DefineAM(PGLOBAL g, LPCSTR am, int)
/***********************************************************************/
bool DOSDEF::GetOptFileName(PGLOBAL g, char *filename)
{
- char *ftype;
+ PCSZ ftype;
switch (Recfm) {
case RECFM_VAR: ftype = ".dop"; break;
@@ -237,9 +239,9 @@ void DOSDEF::RemoveOptValues(PGLOBAL g)
/***********************************************************************/
bool DOSDEF::DeleteIndexFile(PGLOBAL g, PIXDEF pxdf)
{
- char *ftype;
- char filename[_MAX_PATH];
- bool sep, rc = false;
+ PCSZ ftype;
+ char filename[_MAX_PATH];
+ bool sep, rc = false;
if (!To_Indx)
return false; // No index
@@ -351,7 +353,7 @@ PTDB DOSDEF::GetTable(PGLOBAL g, MODE mode)
if (Zipped) {
#if defined(ZIP_SUPPORT)
if (Recfm == RECFM_VAR) {
- if (mode == MODE_READ || mode == MODE_ANY) {
+ if (mode == MODE_READ || mode == MODE_ANY || mode == MODE_ALTER) {
txfp = new(g) UNZFAM(this);
} else if (mode == MODE_INSERT) {
txfp = new(g) ZIPFAM(this);
@@ -362,7 +364,7 @@ PTDB DOSDEF::GetTable(PGLOBAL g, MODE mode)
tdbp = new(g) TDBDOS(this, txfp);
} else {
- if (mode == MODE_READ || mode == MODE_ANY) {
+ if (mode == MODE_READ || mode == MODE_ANY || mode == MODE_ALTER) {
txfp = new(g) UZXFAM(this);
} else if (mode == MODE_INSERT) {
txfp = new(g) ZPXFAM(this);
@@ -1510,8 +1512,8 @@ PBF TDBDOS::CheckBlockFilari(PGLOBAL g, PXOB *arg, int op, bool *cnv)
if (n == 8 && ctype != TYPE_LIST) {
// Should never happen
strcpy(g->Message, "Block opt: bad constant");
- longjmp(g->jumper[g->jump_level], 99);
- } // endif Conv
+ throw 99;
+ } // endif Conv
if (type[0] == 1) {
// Make it always as Column-op-Value
@@ -1791,8 +1793,8 @@ err:
/* Make a dynamic index. */
/***********************************************************************/
bool TDBDOS::InitialyzeIndex(PGLOBAL g, volatile PIXDEF xdp, bool sorted)
- {
- int k, rc;
+{
+ int k;
volatile bool dynamic;
bool brc;
PCOL colp;
@@ -1862,13 +1864,7 @@ bool TDBDOS::InitialyzeIndex(PGLOBAL g, volatile PIXDEF xdp, bool sorted)
} else // Column contains same values as ROWID
kxp = new(g) XXROW(this);
- // Prepare error return
- if (g->jump_level == MAX_JUMP) {
- strcpy(g->Message, MSG(TOO_MANY_JUMPS));
- return true;
- } // endif
-
- if (!(rc = setjmp(g->jumper[++g->jump_level])) != 0) {
+ try {
if (dynamic) {
ResetBlockFilter(g);
kxp->SetDynamic(dynamic);
@@ -1893,12 +1889,17 @@ bool TDBDOS::InitialyzeIndex(PGLOBAL g, volatile PIXDEF xdp, bool sorted)
} // endif brc
- } else
- brc = true;
+ } catch (int n) {
+ if (trace)
+ htrc("Exception %d: %s\n", n, g->Message);
+ brc = true;
+ } catch (const char *msg) {
+ strcpy(g->Message, msg);
+ brc = true;
+ } // end catch
- g->jump_level--;
- return brc;
- } // end of InitialyzeIndex
+ return brc;
+} // end of InitialyzeIndex
/***********************************************************************/
/* DOS GetProgMax: get the max value for progress information. */
@@ -2119,7 +2120,8 @@ bool TDBDOS::OpenDB(PGLOBAL g)
return false;
} // endif use
- if (Mode == MODE_DELETE && !Next && Txfp->GetAmType() != TYPE_AM_DOS) {
+ if (Mode == MODE_DELETE && !Next && Txfp->GetAmType() != TYPE_AM_DOS
+ && Txfp->GetAmType() != TYPE_AM_MGO) {
// Delete all lines. Not handled in MAP or block mode
Txfp = new(g) DOSFAM((PDOSDEF)To_Def);
Txfp->SetTdbp(this);
@@ -2157,16 +2159,18 @@ bool TDBDOS::OpenDB(PGLOBAL g)
To_BlkFil = InitBlockFilter(g, To_Filter);
/*********************************************************************/
- /* Allocate the line buffer plus a null character. */
- /*********************************************************************/
- To_Line = (char*)PlugSubAlloc(g, NULL, Lrecl + 1);
+ /* Lrecl does not include line ending */
+ /*********************************************************************/
+ size_t linelen = Lrecl + ((PDOSDEF)To_Def)->Ending + 1;
+
+ To_Line = (char*)PlugSubAlloc(g, NULL, linelen);
if (Mode == MODE_INSERT) {
// Spaces between fields must be filled with blanks
memset(To_Line, ' ', Lrecl);
To_Line[Lrecl] = '\0';
} else
- memset(To_Line, 0, Lrecl + 1);
+ memset(To_Line, 0, linelen);
if (trace)
htrc("OpenDos: R%hd mode=%d To_Line=%p\n", Tdb_No, Mode, To_Line);
@@ -2305,8 +2309,8 @@ void TDBDOS::CloseDB(PGLOBAL g)
/***********************************************************************/
/* DOSCOL public constructor (also called by MAPCOL). */
/***********************************************************************/
-DOSCOL::DOSCOL(PGLOBAL g, PCOLDEF cdp, PTDB tp, PCOL cp, int i, PSZ am)
- : COLBLK(cdp, tp, i)
+DOSCOL::DOSCOL(PGLOBAL g, PCOLDEF cdp, PTDB tp, PCOL cp, int i, PCSZ am)
+ : COLBLK(cdp, tp, i)
{
char *p;
int prec = Format.Prec;
@@ -2336,7 +2340,7 @@ DOSCOL::DOSCOL(PGLOBAL g, PCOLDEF cdp, PTDB tp, PCOL cp, int i, PSZ am)
Dval = NULL;
Buf = NULL;
- if (txfp->Blocked && Opt && (cdp->GetMin() || cdp->GetDval())) {
+ if (txfp && txfp->Blocked && Opt && (cdp->GetMin() || cdp->GetDval())) {
int nblk = txfp->GetBlock();
Clustered = (cdp->GetXdb2()) ? 2 : 1;
@@ -2515,8 +2519,8 @@ void DOSCOL::ReadColumn(PGLOBAL g)
if (rc == RC_EF)
sprintf(g->Message, MSG(INV_DEF_READ), rc);
- longjmp(g->jumper[g->jump_level], 11);
- } // endif
+ throw 11;
+ } // endif
p = tdbp->To_Line + Deplac;
field = Long;
@@ -2571,8 +2575,8 @@ void DOSCOL::ReadColumn(PGLOBAL g)
break;
default:
sprintf(g->Message, MSG(BAD_RECFM), tdbp->Ftype);
- longjmp(g->jumper[g->jump_level], 34);
- } // endswitch Ftype
+ throw 34;
+ } // endswitch Ftype
// Set null when applicable
if (Nullable)
@@ -2680,8 +2684,8 @@ void DOSCOL::WriteColumn(PGLOBAL g)
break;
default:
sprintf(g->Message, "Invalid field format for column %s", Name);
- longjmp(g->jumper[g->jump_level], 31);
- } // endswitch BufType
+ throw 31;
+ } // endswitch BufType
p2 = Buf;
} else // Standard CONNECT format
@@ -2692,8 +2696,8 @@ void DOSCOL::WriteColumn(PGLOBAL g)
if ((len = strlen(p2)) > field) {
sprintf(g->Message, MSG(VALUE_TOO_LONG), p2, Name, field);
- longjmp(g->jumper[g->jump_level], 31);
- } else if (Dsp)
+ throw 31;
+ } else if (Dsp)
for (i = 0; i < len; i++)
if (p2[i] == '.')
p2[i] = Dsp;
diff --git a/storage/connect/tabdos.h b/storage/connect/tabdos.h
index 922d52ee399..d175cc2da4d 100644
--- a/storage/connect/tabdos.h
+++ b/storage/connect/tabdos.h
@@ -39,9 +39,9 @@ class DllExport DOSDEF : public TABDEF { /* Logical table description */
virtual PIXDEF GetIndx(void) {return To_Indx;}
virtual void SetIndx(PIXDEF xdp) {To_Indx = xdp;}
virtual bool IsHuge(void) {return Huge;}
- PSZ GetFn(void) {return Fn;}
- PSZ GetOfn(void) {return Ofn;}
- PSZ GetEntry(void) {return Entry;}
+ PCSZ GetFn(void) {return Fn;}
+ PCSZ GetOfn(void) {return Ofn;}
+ PCSZ GetEntry(void) {return Entry;}
bool GetMul(void) {return Mulentries;}
bool GetAppend(void) {return Append;}
void SetBlock(int block) { Block = block; }
@@ -74,9 +74,10 @@ class DllExport DOSDEF : public TABDEF { /* Logical table description */
//virtual bool Erase(char *filename);
// Members
- PSZ Fn; /* Path/Name of corresponding file */
- PSZ Ofn; /* Base Path/Name of matching index files*/
- PSZ Entry; /* Zip entry name or pattern */
+ PCSZ Fn; /* Path/Name of corresponding file */
+ PCSZ Ofn; /* Base Path/Name of matching index files*/
+ PCSZ Entry; /* Zip entry name or pattern */
+ PCSZ Pwd; /* Zip password */
PIXDEF To_Indx; /* To index definitions blocks */
RECFM Recfm; /* 0:VAR, 1:FIX, 2:BIN, 3:VCT, 6:DBF */
bool Mapped; /* 0: disk file, 1: memory mapped file */
@@ -132,8 +133,8 @@ class DllExport TDBDOS : public TDBASE {
// Implementation
virtual AMT GetAmType(void) {return Txfp->GetAmType();}
- virtual PSZ GetFile(PGLOBAL) {return Txfp->To_File;}
- virtual void SetFile(PGLOBAL, PSZ fn) {Txfp->To_File = fn;}
+ virtual PCSZ GetFile(PGLOBAL) {return Txfp->To_File;}
+ virtual void SetFile(PGLOBAL, PCSZ fn) {Txfp->To_File = fn;}
virtual void SetAbort(bool b) {Abort = b;}
virtual RECFM GetFtype(void) {return Ftype;}
virtual bool SkipHeader(PGLOBAL) {return false;}
@@ -213,7 +214,7 @@ class DllExport DOSCOL : public COLBLK {
friend class TDBFIX;
public:
// Constructors
- DOSCOL(PGLOBAL g, PCOLDEF cdp, PTDB tp, PCOL cp, int i, PSZ am = "DOS");
+ DOSCOL(PGLOBAL g, PCOLDEF cdp, PTDB tp, PCOL cp, int i, PCSZ am = "DOS");
DOSCOL(DOSCOL *colp, PTDB tdbp); // Constructor used in copy process
// Implementation
diff --git a/storage/connect/tabext.cpp b/storage/connect/tabext.cpp
index e3518126a49..ab79b1861de 100644
--- a/storage/connect/tabext.cpp
+++ b/storage/connect/tabext.cpp
@@ -35,9 +35,9 @@
/***********************************************************************/
/* CONDFIL Constructor. */
/***********************************************************************/
-CONDFIL::CONDFIL(const Item *cond, uint idx, AMT type)
+CONDFIL::CONDFIL(uint idx, AMT type)
{
- Cond = cond;
+//Cond = cond;
Idx = idx;
Type = type;
Op = OP_XX;
@@ -61,7 +61,7 @@ int CONDFIL::Init(PGLOBAL g, PHC hc)
bool h;
if (options)
- alt = GetListOption(g, "Alias", options->oplist, NULL);
+ alt = (char*)GetListOption(g, "Alias", options->oplist, NULL);
while (alt) {
if (!(p = strchr(alt, '='))) {
@@ -267,7 +267,7 @@ TDBEXT::TDBEXT(PTDBEXT tdbp) : TDB(tdbp)
/******************************************************************/
/* Convert an UTF-8 string to latin characters. */
/******************************************************************/
-int TDBEXT::Decode(char *txt, char *buf, size_t n)
+int TDBEXT::Decode(PCSZ txt, char *buf, size_t n)
{
uint dummy_errors;
uint32 len = copy_and_convert(buf, n, &my_charset_latin1,
@@ -285,16 +285,17 @@ int TDBEXT::Decode(char *txt, char *buf, size_t n)
/***********************************************************************/
bool TDBEXT::MakeSQL(PGLOBAL g, bool cnt)
{
- char *schmp = NULL, *catp = NULL, buf[NAM_LEN * 3];
+ PCSZ schmp = NULL;
+ char *catp = NULL, buf[NAM_LEN * 3];
int len;
- bool oom = false, first = true;
+ bool first = true;
PTABLE tablep = To_Table;
PCOL colp;
if (Srcdef) {
if ((catp = strstr(Srcdef, "%s"))) {
char *fil1, *fil2;
- PSZ ph = ((EXTDEF*)To_Def)->Phpos;
+ PCSZ ph = ((EXTDEF*)To_Def)->Phpos;
if (!ph)
ph = (strstr(catp + 2, "%s")) ? const_cast<char*>("WH") :
@@ -342,7 +343,7 @@ bool TDBEXT::MakeSQL(PGLOBAL g, bool cnt)
for (colp = Columns; colp; colp = colp->GetNext())
if (!colp->IsSpecial()) {
if (!first)
- oom |= Query->Append(", ");
+ Query->Append(", ");
else
first = false;
@@ -351,11 +352,11 @@ bool TDBEXT::MakeSQL(PGLOBAL g, bool cnt)
if (Quote) {
// Put column name between identifier quotes in case in contains blanks
- oom |= Query->Append(Quote);
- oom |= Query->Append(buf);
- oom |= Query->Append(Quote);
+ Query->Append(Quote);
+ Query->Append(buf);
+ Query->Append(Quote);
} else
- oom |= Query->Append(buf);
+ Query->Append(buf);
((PEXTCOL)colp)->SetRank(++Ncol);
} // endif colp
@@ -363,13 +364,13 @@ bool TDBEXT::MakeSQL(PGLOBAL g, bool cnt)
} else
// !Columns can occur for queries such that sql count(*) from...
// for which we will count the rows from sql * from...
- oom |= Query->Append('*');
+ Query->Append('*');
} else
// SQL statement used to retrieve the size of the result
- oom |= Query->Append("count(*)");
+ Query->Append("count(*)");
- oom |= Query->Append(" FROM ");
+ Query->Append(" FROM ");
if (Catalog && *Catalog)
catp = Catalog;
@@ -381,17 +382,17 @@ bool TDBEXT::MakeSQL(PGLOBAL g, bool cnt)
schmp = Schema;
if (catp) {
- oom |= Query->Append(catp);
+ Query->Append(catp);
if (schmp) {
- oom |= Query->Append('.');
- oom |= Query->Append(schmp);
+ Query->Append('.');
+ Query->Append(schmp);
} // endif schmp
- oom |= Query->Append('.');
+ Query->Append('.');
} else if (schmp) {
- oom |= Query->Append(schmp);
- oom |= Query->Append('.');
+ Query->Append(schmp);
+ Query->Append('.');
} // endif schmp
// Table name can be encoded in UTF-8
@@ -399,18 +400,18 @@ bool TDBEXT::MakeSQL(PGLOBAL g, bool cnt)
if (Quote) {
// Put table name between identifier quotes in case in contains blanks
- oom |= Query->Append(Quote);
- oom |= Query->Append(buf);
- oom |= Query->Append(Quote);
+ Query->Append(Quote);
+ Query->Append(buf);
+ Query->Append(Quote);
} else
- oom |= Query->Append(buf);
+ Query->Append(buf);
len = Query->GetLength();
if (To_CondFil) {
if (Mode == MODE_READ) {
- oom |= Query->Append(" WHERE ");
- oom |= Query->Append(To_CondFil->Body);
+ Query->Append(" WHERE ");
+ Query->Append(To_CondFil->Body);
len = Query->GetLength() + 1;
} else
len += (strlen(To_CondFil->Body) + 256);
@@ -418,10 +419,11 @@ bool TDBEXT::MakeSQL(PGLOBAL g, bool cnt)
} else
len += ((Mode == MODE_READX) ? 256 : 1);
- if (oom || Query->Resize(len)) {
+ if (Query->IsTruncated()) {
strcpy(g->Message, "MakeSQL: Out of memory");
return true;
- } // endif oom
+ } else
+ Query->Resize(len);
if (trace)
htrc("Query=%s\n", Query->GetStr());
@@ -435,15 +437,17 @@ bool TDBEXT::MakeSQL(PGLOBAL g, bool cnt)
/***********************************************************************/
bool TDBEXT::MakeCommand(PGLOBAL g)
{
- char *p, *stmt, name[68], *body = NULL;
+ PCSZ schmp = NULL;
+ char *p, *stmt, name[132], *body = NULL;
char *qrystr = (char*)PlugSubAlloc(g, NULL, strlen(Qrystr) + 1);
bool qtd = Quoted > 0;
+ char q = qtd ? *Quote : ' ';
int i = 0, k = 0;
// Make a lower case copy of the originale query and change
// back ticks to the data source identifier quoting character
do {
- qrystr[i] = (Qrystr[i] == '`') ? *Quote : tolower(Qrystr[i]);
+ qrystr[i] = (Qrystr[i] == '`') ? q : tolower(Qrystr[i]);
} while (Qrystr[i++]);
if (To_CondFil && (p = strstr(qrystr, " where "))) {
@@ -460,27 +464,50 @@ bool TDBEXT::MakeCommand(PGLOBAL g)
strlwr(strcat(strcat(strcpy(name, " "), Name), " "));
if (strstr(" update delete low_priority ignore quick from ", name)) {
- strlwr(strcat(strcat(strcpy(name, Quote), Name), Quote));
- k += 2;
+ if (Quote) {
+ strlwr(strcat(strcat(strcpy(name, Quote), Name), Quote));
+ k += 2;
+ } else {
+ strcpy(g->Message, "Quoted must be specified");
+ return true;
+ } // endif Quote
+
} else
strlwr(strcpy(name, Name)); // Not a keyword
if ((p = strstr(qrystr, name))) {
for (i = 0; i < p - qrystr; i++)
- stmt[i] = (Qrystr[i] == '`') ? *Quote : Qrystr[i];
+ stmt[i] = (Qrystr[i] == '`') ? q : Qrystr[i];
stmt[i] = 0;
+
k += i + (int)strlen(Name);
- if (qtd && *(p - 1) == ' ')
+ if (Schema && *Schema)
+ schmp = Schema;
+
+ if (qtd && *(p - 1) == ' ') {
+ if (schmp)
+ strcat(strcat(stmt, schmp), ".");
+
strcat(strcat(strcat(stmt, Quote), TableName), Quote);
- else
+ } else {
+ if (schmp) {
+ if (qtd && *(p - 1) != ' ') {
+ stmt[i - 1] = 0;
+ strcat(strcat(strcat(stmt, schmp), "."), Quote);
+ } else
+ strcat(strcat(stmt, schmp), ".");
+
+ } // endif schmp
+
strcat(stmt, TableName);
+ } // endif's
i = (int)strlen(stmt);
do {
- stmt[i++] = (Qrystr[k] == '`') ? *Quote : Qrystr[k];
+ stmt[i++] = (Qrystr[k] == '`') ? q : Qrystr[k];
} while (Qrystr[k++]);
if (body)
@@ -539,7 +566,7 @@ int TDBEXT::GetProgMax(PGLOBAL g)
/***********************************************************************/
/* EXTCOL public constructor. */
/***********************************************************************/
-EXTCOL::EXTCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am)
+EXTCOL::EXTCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PCSZ am)
: COLBLK(cdp, tdbp, i)
{
if (cprec) {
diff --git a/storage/connect/tabext.h b/storage/connect/tabext.h
index 5133bd9dd5f..497b6074d48 100644
--- a/storage/connect/tabext.h
+++ b/storage/connect/tabext.h
@@ -28,14 +28,14 @@ class ALIAS : public BLOCK {
class CONDFIL : public BLOCK {
public:
// Constructor
- CONDFIL(const Item *cond, uint idx, AMT type);
+ CONDFIL(uint idx, AMT type);
// Functions
int Init(PGLOBAL g, PHC hc);
const char *Chk(const char *cln, bool *h);
// Members
- const Item *Cond;
+//const Item *Cond;
AMT Type;
uint Idx;
OPVAL Op;
@@ -60,10 +60,10 @@ public:
// Implementation
virtual const char *GetType(void) { return "EXT"; }
- inline PSZ GetTabname(void) { return Tabname; }
- inline PSZ GetTabschema(void) { return Tabschema; }
- inline PSZ GetUsername(void) { return Username; };
- inline PSZ GetPassword(void) { return Password; };
+ inline PCSZ GetTabname(void) { return Tabname; }
+ inline PCSZ GetTabschema(void) { return Tabschema; }
+ inline PCSZ GetUsername(void) { return Username; };
+ inline PCSZ GetPassword(void) { return Password; };
inline PSZ GetTabcat(void) { return Tabcat; }
inline PSZ GetSrcdef(void) { return Srcdef; }
inline char GetSep(void) { return (Sep) ? *Sep : 0; }
@@ -76,10 +76,10 @@ public:
protected:
// Members
- PSZ Tabname; /* External table name */
- PSZ Tabschema; /* External table schema */
- PSZ Username; /* User connect name */
- PSZ Password; /* Password connect info */
+ PCSZ Tabname; /* External table name */
+ PCSZ Tabschema; /* External table schema */
+ PCSZ Username; /* User connect name */
+ PCSZ Password; /* Password connect info */
PSZ Tabcat; /* External table catalog */
PSZ Tabtyp; /* Catalog table type */
PSZ Colpat; /* Catalog column pattern */
@@ -115,7 +115,7 @@ public:
virtual bool IsRemote(void) { return true; }
// Methods
- virtual PSZ GetServer(void) { return "Remote"; }
+ virtual PCSZ GetServer(void) { return "Remote"; }
virtual int GetRecpos(void);
// Database routines
@@ -127,19 +127,19 @@ protected:
virtual bool MakeSQL(PGLOBAL g, bool cnt);
//virtual bool MakeInsert(PGLOBAL g);
virtual bool MakeCommand(PGLOBAL g);
- int Decode(char *utf, char *buf, size_t n);
+ int Decode(PCSZ utf, char *buf, size_t n);
// Members
PQRYRES Qrp; // Points to storage result
PSTRG Query; // Constructed SQL query
- char *TableName; // Points to ODBC table name
- char *Schema; // Points to ODBC table Schema
- char *User; // User connect info
- char *Pwd; // Password connect info
+ PCSZ TableName; // Points to ODBC table name
+ PCSZ Schema; // Points to ODBC table Schema
+ PCSZ User; // User connect info
+ PCSZ Pwd; // Password connect info
char *Catalog; // Points to ODBC table Catalog
char *Srcdef; // The source table SQL definition
char *Count; // Points to count(*) SQL statement
- //char *Where; // Points to local where clause
+ //char *Where; // Points to local where clause
char *Quote; // The identifier quoting character
char *MulConn; // Used for multiple ODBC tables
char *DBQ; // The address part of Connect string
@@ -170,7 +170,7 @@ class DllExport EXTCOL : public COLBLK {
friend class TDBEXT;
public:
// Constructor
- EXTCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am);
+ EXTCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PCSZ am);
EXTCOL(PEXTCOL colp, PTDB tdbp); // Constructor used in copy process
// Implementation
diff --git a/storage/connect/tabfix.cpp b/storage/connect/tabfix.cpp
index bf123cd36c8..a78d5861e53 100644
--- a/storage/connect/tabfix.cpp
+++ b/storage/connect/tabfix.cpp
@@ -1,11 +1,11 @@
/************* TabFix C++ Program Source Code File (.CPP) **************/
/* PROGRAM NAME: TABFIX */
/* ------------- */
-/* Version 4.9.1 */
+/* Version 4.9.2 */
/* */
/* COPYRIGHT: */
/* ---------- */
-/* (C) Copyright to the author Olivier BERTRAND 1998-2016 */
+/* (C) Copyright to the author Olivier BERTRAND 1998-2017 */
/* */
/* WHAT THIS PROGRAM DOES: */
/* ----------------------- */
@@ -373,7 +373,7 @@ int TDBFIX::WriteDB(PGLOBAL g)
/***********************************************************************/
/* BINCOL public constructor. */
/***********************************************************************/
-BINCOL::BINCOL(PGLOBAL g, PCOLDEF cdp, PTDB tp, PCOL cp, int i, PSZ am)
+BINCOL::BINCOL(PGLOBAL g, PCOLDEF cdp, PTDB tp, PCOL cp, int i, PCSZ am)
: DOSCOL(g, cdp, tp, cp, i, am)
{
char c, *fmt = cdp->GetFmt();
@@ -411,8 +411,8 @@ BINCOL::BINCOL(PGLOBAL g, PCOLDEF cdp, PTDB tp, PCOL cp, int i, PSZ am)
case 'D': M = sizeof(double); break;
default:
sprintf(g->Message, MSG(BAD_BIN_FMT), Fmt, Name);
- longjmp(g->jumper[g->jump_level], 11);
- } // endswitch Fmt
+ throw 11;
+ } // endswitch Fmt
} else if (IsTypeChar(Buf_Type))
Eds = 0;
@@ -486,8 +486,8 @@ void BINCOL::ReadColumn(PGLOBAL g)
if (rc == RC_EF)
sprintf(g->Message, MSG(INV_DEF_READ), rc);
- longjmp(g->jumper[g->jump_level], 11);
- } // endif
+ throw 11;
+ } // endif
p = tdbp->To_Line + Deplac;
@@ -545,8 +545,8 @@ void BINCOL::ReadColumn(PGLOBAL g)
break;
default:
sprintf(g->Message, MSG(BAD_BIN_FMT), Fmt, Name);
- longjmp(g->jumper[g->jump_level], 11);
- } // endswitch Fmt
+ throw 11;
+ } // endswitch Fmt
// Set null when applicable
if (Nullable)
@@ -595,8 +595,8 @@ void BINCOL::WriteColumn(PGLOBAL g)
} else if (Value->GetBinValue(p, Long, Status)) {
sprintf(g->Message, MSG(BIN_F_TOO_LONG),
Name, Value->GetSize(), Long);
- longjmp(g->jumper[g->jump_level], 31);
- } // endif p
+ throw 31;
+ } // endif p
break;
case 'S': // Short integer
@@ -604,8 +604,8 @@ void BINCOL::WriteColumn(PGLOBAL g)
if (n > 32767LL || n < -32768LL) {
sprintf(g->Message, MSG(VALUE_TOO_BIG), n, Name);
- longjmp(g->jumper[g->jump_level], 31);
- } else if (Status)
+ throw 31;
+ } else if (Status)
Value->GetValueNonAligned<short>(p, (short)n);
break;
@@ -614,8 +614,8 @@ void BINCOL::WriteColumn(PGLOBAL g)
if (n > 255LL || n < -256LL) {
sprintf(g->Message, MSG(VALUE_TOO_BIG), n, Name);
- longjmp(g->jumper[g->jump_level], 31);
- } else if (Status)
+ throw 31;
+ } else if (Status)
*p = (char)n;
break;
@@ -624,8 +624,8 @@ void BINCOL::WriteColumn(PGLOBAL g)
if (n > INT_MAX || n < INT_MIN) {
sprintf(g->Message, MSG(VALUE_TOO_BIG), n, Name);
- longjmp(g->jumper[g->jump_level], 31);
- } else if (Status)
+ throw 31;
+ } else if (Status)
Value->GetValueNonAligned<int>(p, (int)n);
break;
@@ -648,8 +648,8 @@ void BINCOL::WriteColumn(PGLOBAL g)
case 'C': // Characters
if ((n = (signed)strlen(Value->GetCharString(Buf))) > Long) {
sprintf(g->Message, MSG(BIN_F_TOO_LONG), Name, (int) n, Long);
- longjmp(g->jumper[g->jump_level], 31);
- } // endif n
+ throw 31;
+ } // endif n
if (Status) {
s = Value->GetCharString(Buf);
@@ -660,8 +660,8 @@ void BINCOL::WriteColumn(PGLOBAL g)
break;
default:
sprintf(g->Message, MSG(BAD_BIN_FMT), Fmt, Name);
- longjmp(g->jumper[g->jump_level], 11);
- } // endswitch Fmt
+ throw 31;
+ } // endswitch Fmt
if (Eds && Status) {
p = tdbp->To_Line + Deplac;
diff --git a/storage/connect/tabfix.h b/storage/connect/tabfix.h
index 4b9f9689992..53c0af1c422 100644
--- a/storage/connect/tabfix.h
+++ b/storage/connect/tabfix.h
@@ -65,7 +65,7 @@ class DllExport BINCOL : public DOSCOL {
friend class TDBFIX;
public:
// Constructors
- BINCOL(PGLOBAL g, PCOLDEF cdp, PTDB tp, PCOL cp, int i, PSZ am = "BIN");
+ BINCOL(PGLOBAL g, PCOLDEF cdp, PTDB tp, PCOL cp, int i, PCSZ am = "BIN");
BINCOL(BINCOL *colp, PTDB tdbp); // Constructor used in copy process
// Implementation
@@ -108,7 +108,7 @@ class TDBDCL : public TDBCAT {
{return DBFColumns(g, ((PTABDEF)To_Def)->GetPath(), Fn, false);}
// Members
- char *Fn; // The DBF file (path) name
+ PCSZ Fn; // The DBF file (path) name
}; // end of class TDBOCL
diff --git a/storage/connect/tabfmt.cpp b/storage/connect/tabfmt.cpp
index 0da67ef5e7f..516601a5eb4 100644
--- a/storage/connect/tabfmt.cpp
+++ b/storage/connect/tabfmt.cpp
@@ -81,7 +81,7 @@ USETEMP UseTemp(void);
/* of types (TYPE_STRING < TYPE_DOUBLE < TYPE_INT) (1 < 2 < 7). */
/* If these values are changed, this will have to be revisited. */
/***********************************************************************/
-PQRYRES CSVColumns(PGLOBAL g, char *dp, PTOS topt, bool info)
+PQRYRES CSVColumns(PGLOBAL g, PCSZ dp, PTOS topt, bool info)
{
static int buftyp[] = {TYPE_STRING, TYPE_SHORT, TYPE_STRING,
TYPE_INT, TYPE_INT, TYPE_SHORT};
@@ -153,7 +153,7 @@ PQRYRES CSVColumns(PGLOBAL g, char *dp, PTOS topt, bool info)
tdp->Lrecl = 4096;
tdp->Multiple = GetIntegerTableOption(g, topt, "Multiple", 0);
- p = GetStringTableOption(g, topt, "Separator", ",");
+ p = (char*)GetStringTableOption(g, topt, "Separator", ",");
tdp->Sep = (strlen(p) == 2 && p[0] == '\\' && p[1] == 't') ? '\t' : *p;
#if defined(__WIN__)
@@ -167,7 +167,7 @@ PQRYRES CSVColumns(PGLOBAL g, char *dp, PTOS topt, bool info)
sep = tdp->Sep;
tdp->Quoted = GetIntegerTableOption(g, topt, "Quoted", -1);
- p = GetStringTableOption(g, topt, "Qchar", "");
+ p = (char*)GetStringTableOption(g, topt, "Qchar", "");
tdp->Qot = *p;
if (tdp->Qot && tdp->Quoted < 0)
@@ -517,7 +517,7 @@ PTDB CSVDEF::GetTable(PGLOBAL g, MODE mode)
/*******************************************************************/
if (Zipped) {
#if defined(ZIP_SUPPORT)
- if (mode == MODE_READ || mode == MODE_ANY) {
+ if (mode == MODE_READ || mode == MODE_ANY || mode == MODE_ALTER) {
txfp = new(g) UNZFAM(this);
} else if (mode == MODE_INSERT) {
txfp = new(g) ZIPFAM(this);
@@ -1435,8 +1435,8 @@ void CSVCOL::ReadColumn(PGLOBAL g)
if (rc == RC_EF)
sprintf(g->Message, MSG(INV_DEF_READ), rc);
- longjmp(g->jumper[g->jump_level], 34);
- } // endif
+ throw 34;
+ } // endif
if (tdbp->Mode != MODE_UPDATE) {
int colen = Long; // Column length
@@ -1453,8 +1453,8 @@ void CSVCOL::ReadColumn(PGLOBAL g)
Long = colen; // Restore column length
sprintf(g->Message, MSG(FLD_TOO_LNG_FOR),
Fldnum + 1, Name, To_Tdb->RowNumber(g), tdbp->GetFile(g));
- longjmp(g->jumper[g->jump_level], 34);
- } // endif Long
+ throw 34;
+ } // endif Long
// Now do the reading
DOSCOL::ReadColumn(g);
@@ -1516,8 +1516,8 @@ void CSVCOL::WriteColumn(PGLOBAL g)
if ((signed)strlen(p) > flen) {
sprintf(g->Message, MSG(BAD_FLD_LENGTH), Name, p, flen,
tdbp->RowNumber(g), tdbp->GetFile(g));
- longjmp(g->jumper[g->jump_level], 34);
- } else if (Dsp)
+ throw 34;
+ } else if (Dsp)
for (int i = 0; p[i]; i++)
if (p[i] == '.')
p[i] = Dsp;
@@ -1532,8 +1532,8 @@ void CSVCOL::WriteColumn(PGLOBAL g)
if (Fldnum < 0) {
// This can happen for wrong offset value in XDB files
sprintf(g->Message, MSG(BAD_FIELD_RANK), Fldnum + 1, Name);
- longjmp(g->jumper[g->jump_level], 34);
- } else
+ throw 34;
+ } else
strncpy(tdbp->Field[Fldnum], p, flen);
if (trace > 1)
diff --git a/storage/connect/tabfmt.h b/storage/connect/tabfmt.h
index e5655435be7..396bba568ff 100644
--- a/storage/connect/tabfmt.h
+++ b/storage/connect/tabfmt.h
@@ -13,7 +13,7 @@ typedef class TDBFMT *PTDBFMT;
/***********************************************************************/
/* Functions used externally. */
/***********************************************************************/
-PQRYRES CSVColumns(PGLOBAL g, char *dp, PTOS topt, bool info);
+PQRYRES CSVColumns(PGLOBAL g, PCSZ dp, PTOS topt, bool info);
/***********************************************************************/
/* CSV table. */
@@ -21,7 +21,7 @@ PQRYRES CSVColumns(PGLOBAL g, char *dp, PTOS topt, bool info);
class DllExport CSVDEF : public DOSDEF { /* Logical table description */
friend class TDBCSV;
friend class TDBCCL;
- friend PQRYRES CSVColumns(PGLOBAL, char *, PTOS, bool);
+ friend PQRYRES CSVColumns(PGLOBAL, PCSZ, PTOS, bool);
public:
// Constructor
CSVDEF(void);
@@ -53,7 +53,7 @@ public:
class DllExport TDBCSV : public TDBDOS {
friend class CSVCOL;
friend class MAPFAM;
- friend PQRYRES CSVColumns(PGLOBAL, char *, PTOS, bool);
+ friend PQRYRES CSVColumns(PGLOBAL, PCSZ, PTOS, bool);
public:
// Constructor
TDBCSV(PCSVDEF tdp, PTXF txfp);
diff --git a/storage/connect/tabjdbc.cpp b/storage/connect/tabjdbc.cpp
index 5431e35e0ec..7c82a2fc138 100644
--- a/storage/connect/tabjdbc.cpp
+++ b/storage/connect/tabjdbc.cpp
@@ -227,41 +227,8 @@ bool JDBCDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
if (rc == RC_FX) // Error
return true;
-//else if (rc == RC_OK) { // Url was not a server name
-// Tabname = GetStringCatInfo(g, "Name",
-// (Catfunc & (FNC_TABLE | FNC_COL)) ? NULL : Name);
-// Tabname = GetStringCatInfo(g, "Tabname", Tabname);
-// Username = GetStringCatInfo(g, "User", NULL);
-// Password = GetStringCatInfo(g, "Password", NULL);
-//} // endif rc
-
-//if ((Srcdef = GetStringCatInfo(g, "Srcdef", NULL)))
-// Read_Only = true;
Wrapname = GetStringCatInfo(g, "Wrapper", NULL);
-//Prop = GetStringCatInfo(g, "Properties", NULL);
-//Tabcat = GetStringCatInfo(g, "Qualifier", NULL);
-//Tabcat = GetStringCatInfo(g, "Catalog", Tabcat);
-//Tabschema = GetStringCatInfo(g, "Dbname", NULL);
-//Tabschema = GetStringCatInfo(g, "Schema", Tabschema);
-
-//if (Catfunc == FNC_COL)
-// Colpat = GetStringCatInfo(g, "Colpat", NULL);
-
-//if (Catfunc == FNC_TABLE)
-// Tabtyp = GetStringCatInfo(g, "Tabtype", NULL);
-
-//Qrystr = GetStringCatInfo(g, "Query_String", "?");
-//Sep = GetStringCatInfo(g, "Separator", NULL);
-//Xsrc = GetBoolCatInfo("Execsrc", FALSE);
-//Maxerr = GetIntCatInfo("Maxerr", 0);
-//Maxres = GetIntCatInfo("Maxres", 0);
-//Quoted = GetIntCatInfo("Quoted", 0);
-// Cto= GetIntCatInfo("ConnectTimeout", DEFAULT_LOGIN_TIMEOUT);
-// Qto= GetIntCatInfo("QueryTimeout", DEFAULT_QUERY_TIMEOUT);
-//Scrollable = GetBoolCatInfo("Scrollable", false);
-//Memory = GetIntCatInfo("Memory", 0);
-//Pseudo = 2; // FILID is Ok but not ROWID
return false;
} // end of DefineAM
@@ -341,9 +308,6 @@ TDBJDBC::TDBJDBC(PJDBCDEF tdp) : TDBEXT(tdp)
WrapName = tdp->Wrapname;
Ops.User = tdp->Username;
Ops.Pwd = tdp->Password;
-// Ops.Properties = tdp->Prop;
-// Ops.Cto = tdp->Cto;
-// Ops.Qto = tdp->Qto;
Ops.Scrollable = tdp->Scrollable;
} else {
WrapName = NULL;
@@ -351,13 +315,9 @@ TDBJDBC::TDBJDBC(PJDBCDEF tdp) : TDBEXT(tdp)
Ops.Url = NULL;
Ops.User = NULL;
Ops.Pwd = NULL;
-// Ops.Properties = NULL;
-// Ops.Cto = DEFAULT_LOGIN_TIMEOUT;
-// Ops.Qto = DEFAULT_QUERY_TIMEOUT;
Ops.Scrollable = false;
} // endif tdp
-//Ncol = 0;
Prepared = false;
Werr = false;
Rerr = false;
@@ -370,7 +330,6 @@ TDBJDBC::TDBJDBC(PTDBJDBC tdbp) : TDBEXT(tdbp)
Cnp = tdbp->Cnp;
WrapName = tdbp->WrapName;
Ops = tdbp->Ops;
-//Ncol = tdbp->Ncol;
Prepared = tdbp->Prepared;
Werr = tdbp->Werr;
Rerr = tdbp->Rerr;
@@ -406,10 +365,11 @@ PCOL TDBJDBC::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n)
/***********************************************************************/
bool TDBJDBC::MakeInsert(PGLOBAL g)
{
- char *schmp = NULL, *catp = NULL, buf[NAM_LEN * 3];
+ PCSZ schmp = NULL;
+ char *catp = NULL, buf[NAM_LEN * 3];
int len = 0;
uint pos;
- bool b = false, oom = false;
+ bool b = false;
PTABLE tablep = To_Table;
PCOL colp;
@@ -446,32 +406,32 @@ bool TDBJDBC::MakeInsert(PGLOBAL g)
Query = new(g)STRING(g, len, "INSERT INTO ");
if (catp) {
- oom |= Query->Append(catp);
+ Query->Append(catp);
if (schmp) {
- oom |= Query->Append('.');
- oom |= Query->Append(schmp);
+ Query->Append('.');
+ Query->Append(schmp);
} // endif schmp
- oom |= Query->Append('.');
+ Query->Append('.');
} else if (schmp) {
- oom |= Query->Append(schmp);
- oom |= Query->Append('.');
+ Query->Append(schmp);
+ Query->Append('.');
} // endif schmp
if (Quote) {
// Put table name between identifier quotes in case in contains blanks
- oom |= Query->Append(Quote);
- oom |= Query->Append(buf);
- oom |= Query->Append(Quote);
+ Query->Append(Quote);
+ Query->Append(buf);
+ Query->Append(Quote);
} else
- oom |= Query->Append(buf);
+ Query->Append(buf);
- oom |= Query->Append('(');
+ Query->Append('(');
for (colp = Columns; colp; colp = colp->GetNext()) {
if (b)
- oom |= Query->Append(", ");
+ Query->Append(", ");
else
b = true;
@@ -480,15 +440,15 @@ bool TDBJDBC::MakeInsert(PGLOBAL g)
if (Quote) {
// Put column name between identifier quotes in case in contains blanks
- oom |= Query->Append(Quote);
- oom |= Query->Append(buf);
- oom |= Query->Append(Quote);
+ Query->Append(Quote);
+ Query->Append(buf);
+ Query->Append(Quote);
} else
- oom |= Query->Append(buf);
+ Query->Append(buf);
} // endfor colp
- if ((oom |= Query->Append(") VALUES ("))) {
+ if ((Query->Append(") VALUES ("))) {
strcpy(g->Message, "MakeInsert: Out of memory");
return true;
} else // in case prepared statement fails
@@ -496,9 +456,9 @@ bool TDBJDBC::MakeInsert(PGLOBAL g)
// Make prepared statement
for (int i = 0; i < Nparm; i++)
- oom |= Query->Append("?,");
+ Query->Append("?,");
- if (oom) {
+ if (Query->IsTruncated()) {
strcpy(g->Message, "MakeInsert: Out of memory");
return true;
} else
@@ -737,18 +697,12 @@ bool TDBJDBC::SetRecpos(PGLOBAL g, int recpos)
{
if (Jcp->m_Full) {
Fpos = 0;
-// CurNum = 0;
CurNum = 1;
} else if (Memory == 3) {
-// Fpos = recpos;
-// CurNum = -1;
Fpos = 0;
CurNum = recpos;
} else if (Ops.Scrollable) {
// Is new position in the current row set?
-// if (recpos >= Curpos && recpos < Curpos + Rbuf) {
-// CurNum = recpos - Curpos;
-// Fpos = 0;
if (recpos > 0 && recpos <= Rbuf) {
CurNum = recpos;
Fpos = recpos;
@@ -797,7 +751,7 @@ bool TDBJDBC::ReadKey(PGLOBAL g, OPVAL op, const key_range *kr)
To_CondFil->Body= (char*)PlugSubAlloc(g, NULL, 0);
*To_CondFil->Body= 0;
- if ((To_CondFil = hc->CheckCond(g, To_CondFil, To_CondFil->Cond)))
+ if ((To_CondFil = hc->CheckCond(g, To_CondFil, Cond)))
PlugSubAlloc(g, NULL, strlen(To_CondFil->Body) + 1);
} // endif active_index
@@ -911,7 +865,6 @@ int TDBJDBC::WriteDB(PGLOBAL g)
// an insert query for each line to insert
uint len = Query->GetLength();
char buf[64];
- bool oom = false;
// Make the Insert command value list
for (PCOL colp = Columns; colp; colp = colp->GetNext()) {
@@ -919,28 +872,28 @@ int TDBJDBC::WriteDB(PGLOBAL g)
char *s = colp->GetValue()->GetCharString(buf);
if (colp->GetResultType() == TYPE_STRING)
- oom |= Query->Append_quoted(s);
+ Query->Append_quoted(s);
else if (colp->GetResultType() == TYPE_DATE) {
DTVAL *dtv = (DTVAL*)colp->GetValue();
if (dtv->IsFormatted())
- oom |= Query->Append_quoted(s);
+ Query->Append_quoted(s);
else
- oom |= Query->Append(s);
+ Query->Append(s);
} else
- oom |= Query->Append(s);
+ Query->Append(s);
} else
- oom |= Query->Append("NULL");
+ Query->Append("NULL");
- oom |= Query->Append(',');
+ Query->Append(',');
} // endfor colp
- if (unlikely(oom)) {
+ if (unlikely(Query->IsTruncated())) {
strcpy(g->Message, "WriteDB: Out of memory");
return RC_FX;
- } // endif oom
+ } // endif Query
Query->RepLast(')');
@@ -990,11 +943,6 @@ int TDBJDBC::DeleteDB(PGLOBAL g, int irc)
/***********************************************************************/
void TDBJDBC::CloseDB(PGLOBAL g)
{
- //if (To_Kindex) {
- // To_Kindex->Close();
- // To_Kindex = NULL;
- // } // endif
-
if (Jcp)
Jcp->Close();
@@ -1019,7 +967,7 @@ void TDBJDBC::CloseDB(PGLOBAL g)
/***********************************************************************/
/* JDBCCOL public constructor. */
/***********************************************************************/
-JDBCCOL::JDBCCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am)
+JDBCCOL::JDBCCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PCSZ am)
: EXTCOL(cdp, tdbp, cprec, i, am)
{
} // end of JDBCCOL constructor
@@ -1039,54 +987,6 @@ JDBCCOL::JDBCCOL(JDBCCOL *col1, PTDB tdbp) : EXTCOL(col1, tdbp)
{
} // end of JDBCCOL copy constructor
-#if 0
-/***********************************************************************/
-/* SetBuffer: prepare a column block for write operation. */
-/***********************************************************************/
-bool JDBCCOL::SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check)
-{
- if (!(To_Val = value)) {
- sprintf(g->Message, MSG(VALUE_ERROR), Name);
- return true;
- } else if (Buf_Type == value->GetType()) {
- // Values are of the (good) column type
- if (Buf_Type == TYPE_DATE) {
- // If any of the date values is formatted
- // output format must be set for the receiving table
- if (GetDomain() || ((DTVAL *)value)->IsFormatted())
- goto newval; // This will make a new value;
-
- } else if (Buf_Type == TYPE_DOUBLE)
- // Float values must be written with the correct (column) precision
- // Note: maybe this should be forced by ShowValue instead of this ?
- value->SetPrec(GetScale());
-
- Value = value; // Directly access the external value
- } else {
- // Values are not of the (good) column type
- if (check) {
- sprintf(g->Message, MSG(TYPE_VALUE_ERR), Name,
- GetTypeName(Buf_Type), GetTypeName(value->GetType()));
- return true;
- } // endif check
-
- newval:
- if (InitValue(g)) // Allocate the matching value block
- return true;
-
- } // endif's Value, Buf_Type
-
- // Because Colblk's have been made from a copy of the original TDB in
- // case of Update, we must reset them to point to the original one.
- if (To_Tdb->GetOrig())
- To_Tdb = (PTDB)To_Tdb->GetOrig();
-
- // Set the Column
- Status = (ok) ? BUF_EMPTY : BUF_NO;
- return false;
-} // end of SetBuffer
-#endif // 0
-
/***********************************************************************/
/* ReadColumn: when SQLFetch is used there is nothing to do as the */
/* column buffer was bind to the record set. This is also the case */
@@ -1196,26 +1096,6 @@ PCMD TDBXJDC::MakeCMD(PGLOBAL g)
return xcmd;
} // end of MakeCMD
-#if 0
-/***********************************************************************/
-/* JDBC Bind Parameter function. */
-/***********************************************************************/
-bool TDBXJDC::BindParameters(PGLOBAL g)
-{
- PJDBCCOL colp;
-
- for (colp = (PJDBCCOL)Columns; colp; colp = (PJDBCCOL)colp->Next) {
- colp->AllocateBuffers(g, 0);
-
- if (Jcp->BindParam(colp))
- return true;
-
- } // endfor colp
-
- return false;
-} // end of BindParameters
-#endif // 0
-
/***********************************************************************/
/* XDBC GetMaxSize: returns table size (not always one row). */
/***********************************************************************/
@@ -1332,8 +1212,8 @@ int TDBXJDC::DeleteDB(PGLOBAL g, int irc)
/***********************************************************************/
/* JSRCCOL public constructor. */
/***********************************************************************/
-JSRCCOL::JSRCCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am)
- : JDBCCOL(cdp, tdbp, cprec, i, am)
+JSRCCOL::JSRCCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PCSZ am)
+ : JDBCCOL(cdp, tdbp, cprec, i, am)
{
// Set additional JDBC access method information for column.
Flag = cdp->GetOffset();
@@ -1416,17 +1296,3 @@ PQRYRES TDBJDBCL::GetResult(PGLOBAL g)
{
return JDBCColumns(g, Schema, Tab, Colpat, Maxres, false, &Ops);
} // end of GetResult
-
-#if 0
-/* ---------------------------TDBJSRC class -------------------------- */
-
-/***********************************************************************/
-/* GetResult: Get the list of JDBC data sources. */
-/***********************************************************************/
-PQRYRES TDBJSRC::GetResult(PGLOBAL g)
-{
- return JDBCDataSources(g, Maxres, false);
-} // end of GetResult
-
-/* ------------------------ End of TabJDBC --------------------------- */
-#endif // 0
diff --git a/storage/connect/tabjdbc.h b/storage/connect/tabjdbc.h
index 46d2073e923..7c14783285f 100644
--- a/storage/connect/tabjdbc.h
+++ b/storage/connect/tabjdbc.h
@@ -1,7 +1,7 @@
/*************** Tabjdbc H Declares Source Code File (.H) **************/
-/* Name: TABJDBC.H Version 1.0 */
+/* Name: TABJDBC.H Version 1.1 */
/* */
-/* (C) Copyright to the author Olivier BERTRAND 2016 */
+/* (C) Copyright to the author Olivier BERTRAND 2016-2017 */
/* */
/* This file contains the TDBJDBC classes declares. */
/***********************************************************************/
@@ -14,9 +14,6 @@ typedef class TDBJDBC *PTDBJDBC;
typedef class JDBCCOL *PJDBCCOL;
typedef class TDBXJDC *PTDBXJDC;
typedef class JSRCCOL *PJSRCCOL;
-//typedef class TDBOIF *PTDBOIF;
-//typedef class OIFCOL *POIFCOL;
-//typedef class TDBJSRC *PTDBJSRC;
/***********************************************************************/
/* JDBC table. */
@@ -68,20 +65,14 @@ public:
// Methods
virtual PTDB Clone(PTABS t);
-//virtual int GetRecpos(void);
virtual bool SetRecpos(PGLOBAL g, int recpos);
-//virtual PSZ GetFile(PGLOBAL g);
-//virtual void SetFile(PGLOBAL g, PSZ fn);
virtual void ResetSize(void);
-//virtual int GetAffectedRows(void) {return AftRows;}
- virtual PSZ GetServer(void) { return "JDBC"; }
+ virtual PCSZ GetServer(void) { return "JDBC"; }
virtual int Indexable(void) { return 2; }
// Database routines
virtual PCOL MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n);
virtual int Cardinality(PGLOBAL g);
-//virtual int GetMaxSize(PGLOBAL g);
-//virtual int GetProgMax(PGLOBAL g);
virtual bool OpenDB(PGLOBAL g);
virtual int ReadDB(PGLOBAL g);
virtual int WriteDB(PGLOBAL g);
@@ -91,21 +82,14 @@ public:
protected:
// Internal functions
-//int Decode(char *utf, char *buf, size_t n);
-//bool MakeSQL(PGLOBAL g, bool cnt);
bool MakeInsert(PGLOBAL g);
-//virtual bool MakeCommand(PGLOBAL g);
-//bool MakeFilter(PGLOBAL g, bool c);
bool SetParameters(PGLOBAL g);
-//char *MakeUpdate(PGLOBAL g);
-//char *MakeDelete(PGLOBAL g);
// Members
JDBConn *Jcp; // Points to a JDBC connection class
JDBCCOL *Cnp; // Points to count(*) column
JDBCPARM Ops; // Additional parameters
char *WrapName; // Points to Java wrapper name
-//int Ncol; // The column number
bool Prepared; // True when using prepared statement
bool Werr; // Write error
bool Rerr; // Rewind error
@@ -119,7 +103,7 @@ class JDBCCOL : public EXTCOL {
friend class TDBJDBC;
public:
// Constructors
- JDBCCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am = "JDBC");
+ JDBCCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PCSZ am = "JDBC");
JDBCCOL(JDBCCOL *colp, PTDB tdbp); // Constructor used in copy process
// Implementation
@@ -152,12 +136,6 @@ public:
virtual AMT GetAmType(void) {return TYPE_AM_XDBC;}
// Methods
- //virtual int GetRecpos(void);
- //virtual PSZ GetFile(PGLOBAL g);
- //virtual void SetFile(PGLOBAL g, PSZ fn);
- //virtual void ResetSize(void);
- //virtual int GetAffectedRows(void) {return AftRows;}
- //virtual PSZ GetServer(void) {return "JDBC";}
// Database routines
virtual PCOL MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n);
@@ -172,7 +150,6 @@ public:
protected:
// Internal functions
PCMD MakeCMD(PGLOBAL g);
- //bool BindParameters(PGLOBAL g);
// Members
PCMD Cmdlist; // The commands to execute
@@ -188,7 +165,7 @@ class JSRCCOL : public JDBCCOL {
friend class TDBXJDC;
public:
// Constructors
- JSRCCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am = "JDBC");
+ JSRCCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PCSZ am = "JDBC");
// Implementation
virtual int GetAmType(void) {return TYPE_AM_JDBC;}
@@ -233,9 +210,9 @@ protected:
virtual PQRYRES GetResult(PGLOBAL g);
// Members
- char *Schema; // Points to schema name or NULL
- char *Tab; // Points to JDBC table name or pattern
- char *Tabtype; // Points to JDBC table type
+ PCSZ Schema; // Points to schema name or NULL
+ PCSZ Tab; // Points to JDBC table name or pattern
+ PCSZ Tabtype; // Points to JDBC table type
JDBCPARM Ops; // Additional parameters
}; // end of class TDBJTB
@@ -252,24 +229,7 @@ protected:
virtual PQRYRES GetResult(PGLOBAL g);
// Members
- char *Colpat; // Points to catalog column pattern
+ PCSZ Colpat; // Points to catalog column pattern
}; // end of class TDBJDBCL
-#if 0
-/***********************************************************************/
-/* This is the class declaration for the Data Sources catalog table. */
-/***********************************************************************/
-class TDBJSRC : public TDBJDRV {
-public:
- // Constructor
- TDBJSRC(PJDBCDEF tdp) : TDBJDRV(tdp) {}
-
-protected:
- // Specific routines
- virtual PQRYRES GetResult(PGLOBAL g);
-
- // No additional Members
-}; // end of class TDBJSRC
-#endif // 0
-
#endif // !NJDBC
diff --git a/storage/connect/tabjson.cpp b/storage/connect/tabjson.cpp
index 2addcc139fb..063115c7a60 100644
--- a/storage/connect/tabjson.cpp
+++ b/storage/connect/tabjson.cpp
@@ -1,6 +1,6 @@
/************* tabjson C++ Program Source Code File (.CPP) *************/
-/* PROGRAM NAME: tabjson Version 1.3 */
-/* (C) Copyright to the author Olivier BERTRAND 2014 - 2016 */
+/* PROGRAM NAME: tabjson Version 1.4 */
+/* (C) Copyright to the author Olivier BERTRAND 2014 - 2017 */
/* This program are the JSON class DB execution routines. */
/***********************************************************************/
@@ -117,7 +117,9 @@ PQRYRES JSONColumns(PGLOBAL g, char *db, PTOS topt, bool info)
return NULL;
} // endif Fn
- tdp->Database = SetPath(g, db);
+ if (!(tdp->Database = SetPath(g, db)))
+ return NULL;
+
tdp->Objname = GetStringTableOption(g, topt, "Object", NULL);
tdp->Base = GetIntegerTableOption(g, topt, "Base", 0) ? 1 : 0;
tdp->Pretty = GetIntegerTableOption(g, topt, "Pretty", 2);
@@ -151,7 +153,7 @@ PQRYRES JSONColumns(PGLOBAL g, char *db, PTOS topt, bool info)
if (tdp->Zipped) {
#if defined(ZIP_SUPPORT)
- tjnp = new(g)TDBJSN(tdp, new(g)UNZFAM(tdp));
+ tjnp = new(g)TDBJSN(tdp, new(g) UNZFAM(tdp));
#else // !ZIP_SUPPORT
sprintf(g->Message, MSG(NO_FEAT_SUPPORT), "ZIP");
return NULL;
@@ -168,7 +170,7 @@ PQRYRES JSONColumns(PGLOBAL g, char *db, PTOS topt, bool info)
G->Sarea_Size = tdp->Lrecl * 10;
G->Sarea = PlugSubAlloc(g, NULL, G->Sarea_Size);
PlugSubSet(G, G->Sarea, G->Sarea_Size);
- G->jump_level = -1;
+ G->jump_level = 0;
tjnp->SetG(G);
#else
tjnp->SetG(g);
@@ -262,8 +264,13 @@ PQRYRES JSONColumns(PGLOBAL g, char *db, PTOS topt, bool info)
break;
if (jcp) {
- if (jcp->Type != jcol.Type)
- jcp->Type = TYPE_STRING;
+ if (jcp->Type != jcol.Type) {
+ if (jcp->Type == TYPE_UNKNOWN)
+ jcp->Type = jcol.Type;
+ else if (jcol.Type != TYPE_UNKNOWN)
+ jcp->Type = TYPE_STRING;
+
+ } // endif Type
if (*fmt && (!jcp->Fmt || strlen(jcp->Fmt) < strlen(fmt))) {
jcp->Fmt = PlugDup(g, fmt);
@@ -336,7 +343,7 @@ PQRYRES JSONColumns(PGLOBAL g, char *db, PTOS topt, bool info)
skipit:
if (trace)
- htrc("CSVColumns: n=%d len=%d\n", n, length[0]);
+ htrc("JSONColumns: n=%d len=%d\n", n, length[0]);
/*********************************************************************/
/* Allocate the structures used to refer to the result set. */
@@ -417,7 +424,7 @@ bool JSONDEF::DefineAM(PGLOBAL g, LPCSTR, int poff)
Pretty = GetIntCatInfo("Pretty", 2);
Limit = GetIntCatInfo("Limit", 10);
Base = GetIntCatInfo("Base", 0) ? 1 : 0;
- return DOSDEF::DefineAM(g, "DOS", poff);
+ return DOSDEF::DefineAM(g, "DOS", poff);
} // end of DefineAM
/***********************************************************************/
@@ -441,7 +448,7 @@ PTDB JSONDEF::GetTable(PGLOBAL g, MODE m)
if (Zipped) {
#if defined(ZIP_SUPPORT)
- if (m == MODE_READ || m == MODE_UPDATE) {
+ if (m == MODE_READ || m == MODE_ANY || m == MODE_ALTER) {
txfp = new(g) UNZFAM(this);
} else if (m == MODE_INSERT) {
txfp = new(g) ZIPFAM(this);
@@ -463,7 +470,7 @@ PTDB JSONDEF::GetTable(PGLOBAL g, MODE m)
sprintf(g->Message, MSG(NO_FEAT_SUPPORT), "GZ");
return NULL;
#endif // !GZ_SUPPORT
- } else if (map)
+ } else if (map)
txfp = new(g) MAPFAM(this);
else
txfp = new(g) DOSFAM(this);
@@ -478,7 +485,7 @@ PTDB JSONDEF::GetTable(PGLOBAL g, MODE m)
G->Sarea_Size = Lrecl * 10;
G->Sarea = PlugSubAlloc(g, NULL, G->Sarea_Size);
PlugSubSet(G, G->Sarea, G->Sarea_Size);
- G->jump_level = -1;
+ G->jump_level = 0;
((TDBJSN*)tdbp)->G = G;
#else
((TDBJSN*)tdbp)->G = g;
@@ -486,7 +493,7 @@ PTDB JSONDEF::GetTable(PGLOBAL g, MODE m)
} else {
if (Zipped) {
#if defined(ZIP_SUPPORT)
- if (m == MODE_READ || m == MODE_UPDATE) {
+ if (m == MODE_READ || m == MODE_ANY || m == MODE_ALTER) {
txfp = new(g) UNZFAM(this);
} else if (m == MODE_INSERT) {
strcpy(g->Message, "INSERT supported only for zipped JSON when pretty=0");
@@ -535,7 +542,7 @@ TDBJSN::TDBJSN(PJDEF tdp, PTXF txfp) : TDBDOS(tdp, txfp)
} else {
Jmode = MODE_OBJECT;
Objname = NULL;
- Xcol = NULL;
+ Xcol = NULL;
Limit = 1;
Pretty = 0;
B = 0;
@@ -695,6 +702,9 @@ bool TDBJSN::OpenDB(PGLOBAL g)
return true;
} // endswitch Jmode
+ if (Xcol && Txfp->GetAmType() != TYPE_AM_MGO)
+ To_Filter = NULL; // Imcompatible
+
} // endif Use
return TDBDOS::OpenDB(g);
@@ -865,24 +875,21 @@ int TDBJSN::MakeTopTree(PGLOBAL g, PJSON jsp)
} // end of PrepareWriting
- /***********************************************************************/
- /* WriteDB: Data Base write routine for DOS access method. */
- /***********************************************************************/
- int TDBJSN::WriteDB(PGLOBAL g)
+/***********************************************************************/
+/* WriteDB: Data Base write routine for DOS access method. */
+/***********************************************************************/
+int TDBJSN::WriteDB(PGLOBAL g)
{
int rc = TDBDOS::WriteDB(g);
#if USE_G
- if (rc == RC_FX)
- strcpy(g->Message, G->Message);
-
PlugSubSet(G, G->Sarea, G->Sarea_Size);
#endif
Row->Clear();
return rc;
} // end of WriteDB
- /* ---------------------------- JSONCOL ------------------------------ */
+/* ---------------------------- JSONCOL ------------------------------ */
/***********************************************************************/
/* JSONCOL public constructor. */
@@ -1147,11 +1154,61 @@ bool JSONCOL::ParseJpath(PGLOBAL g)
} // end of ParseJpath
/***********************************************************************/
+/* Get Jpath converted to Mongo path. */
+/***********************************************************************/
+char *JSONCOL::GetJpath(PGLOBAL g, bool proj)
+{
+ if (Jpath) {
+ char *p1, *p2, *mgopath;
+ int i = 0;
+
+ if (strcmp(Jpath, "*"))
+ mgopath = PlugDup(g, Jpath);
+ else
+ return NULL;
+
+ for (p1 = p2 = mgopath; *p1; p1++)
+ if (i) { // Inside []
+ if (isdigit(*p1)) {
+ if (!proj)
+ *p2++ = *p1;
+
+ i = 2;
+ } else if (*p1 == ']' && i == 2) {
+ if (proj && *(p1 + 1) == ':')
+ p1++;
+
+ i = 0;
+ } else if (proj)
+ i = 2;
+ else
+ return NULL;
+
+ } else switch (*p1) {
+ case ':': *p2++ = '.'; break;
+ case '[': i = 1; break;
+ case '*':
+ if (*(p2 - 1) == '.' && !*(p1 + 1)) {
+ p2--; // Suppress last :*
+ break;
+ } // endif p2
+
+ default: *p2++ = *p1; break;
+ } // endswitch p1;
+
+ *p2 = 0;
+ return mgopath;
+ } else
+ return NULL;
+
+} // end of GetJpath
+
+/***********************************************************************/
/* MakeJson: Serialize the json item and set value to it. */
/***********************************************************************/
PVAL JSONCOL::MakeJson(PGLOBAL g, PJSON jsp)
- {
- if (Value->IsTypeNum()) {
+{
+ if (Value->IsTypeNum()) {
strcpy(g->Message, "Cannot make Json for a numeric column");
Value->Reset();
} else
@@ -1171,7 +1228,8 @@ void JSONCOL::SetJsonValue(PGLOBAL g, PVAL vp, PJVAL val, int n)
case TYPE_INTG:
case TYPE_BINT:
case TYPE_DBL:
- vp->SetValue_pval(val->GetValue());
+ case TYPE_DATE:
+ vp->SetValue_pval(val->GetValue());
break;
case TYPE_BOOL:
if (vp->IsTypeNum())
@@ -1190,11 +1248,14 @@ void JSONCOL::SetJsonValue(PGLOBAL g, PVAL vp, PJVAL val, int n)
// } // endif Type
default:
- vp->Reset();
- } // endswitch Type
+ vp->Reset();
+ vp->SetNull(true);
+ } // endswitch Type
- } else
- vp->Reset();
+ } else {
+ vp->Reset();
+ vp->SetNull(true);
+ } // endif val
} // end of SetJsonValue
@@ -1207,8 +1268,8 @@ void JSONCOL::ReadColumn(PGLOBAL g)
Value->SetValue_pval(GetColumnValue(g, Tjp->Row, 0));
// Set null when applicable
- if (Nullable)
- Value->SetNull(Value->IsZero());
+ if (!Nullable)
+ Value->SetNull(false);
} // end of ReadColumn
@@ -1289,8 +1350,8 @@ PVAL JSONCOL::ExpandArray(PGLOBAL g, PJAR arp, int n)
if (!(jvp = arp->GetValue((Nodes[n].Rx = Nodes[n].Nx)))) {
strcpy(g->Message, "Logical error expanding array");
- longjmp(g->jumper[g->jump_level], 666);
- } // endif jvp
+ throw 666;
+ } // endif jvp
if (n < Nod - 1 && jvp->GetJson()) {
jval.SetValue(GetColumnValue(g, jvp->GetJson(), n + 1));
@@ -1475,8 +1536,8 @@ void JSONCOL::WriteColumn(PGLOBAL g)
{
if (Xpd && Tjp->Pretty < 2) {
strcpy(g->Message, "Cannot write expanded column when Pretty is not 2");
- longjmp(g->jumper[g->jump_level], 666);
- } // endif Xpd
+ throw 666;
+ } // endif Xpd
/*********************************************************************/
/* Check whether this node must be written. */
@@ -1510,8 +1571,8 @@ void JSONCOL::WriteColumn(PGLOBAL g)
if (!(jsp = ParseJson(G, s, (int)strlen(s)))) {
strcpy(g->Message, s);
- longjmp(g->jumper[g->jump_level], 666);
- } // endif jsp
+ throw 666;
+ } // endif jsp
if (arp) {
if (Nod > 1 && Nodes[Nod-2].Op == OP_EQ)
@@ -1533,6 +1594,7 @@ void JSONCOL::WriteColumn(PGLOBAL g)
// fall through
case TYPE_DATE:
case TYPE_INT:
+ case TYPE_TINY:
case TYPE_SHORT:
case TYPE_BIGINT:
case TYPE_DOUBLE:
@@ -1860,8 +1922,11 @@ bool TDBJSON::OpenDB(PGLOBAL g)
return true;
} // endswitch Jmode
- Use = USE_OPEN;
- return false;
+ if (Xcol)
+ To_Filter = NULL; // Imcompatible
+
+ Use = USE_OPEN;
+ return false;
} // end of OpenDB
/***********************************************************************/
@@ -1871,7 +1936,7 @@ int TDBJSON::ReadDB(PGLOBAL)
{
int rc;
- N++;
+ N++;
if (NextSame) {
SameRow = NextSame;
diff --git a/storage/connect/tabjson.h b/storage/connect/tabjson.h
index 924ce387900..c16cf6846b6 100644
--- a/storage/connect/tabjson.h
+++ b/storage/connect/tabjson.h
@@ -1,7 +1,7 @@
/*************** tabjson H Declares Source Code File (.H) **************/
-/* Name: tabjson.h Version 1.1 */
+/* Name: tabjson.h Version 1.3 */
/* */
-/* (C) Copyright to the author Olivier BERTRAND 2014 - 2015 */
+/* (C) Copyright to the author Olivier BERTRAND 2014 - 2017 */
/* */
/* This file contains the JSON classes declares. */
/***********************************************************************/
@@ -32,12 +32,12 @@ typedef struct _jnode {
/***********************************************************************/
/* JSON table. */
/***********************************************************************/
-class JSONDEF : public DOSDEF { /* Table description */
+class DllExport JSONDEF : public DOSDEF { /* Table description */
friend class TDBJSON;
friend class TDBJSN;
friend class TDBJCL;
friend PQRYRES JSONColumns(PGLOBAL, char*, PTOS, bool);
- public:
+public:
// Constructor
JSONDEF(void);
@@ -51,12 +51,12 @@ class JSONDEF : public DOSDEF { /* Table description */
protected:
// Members
JMODE Jmode; /* MODE_OBJECT by default */
- char *Objname; /* Name of first level object */
- char *Xcol; /* Name of expandable column */
+ PCSZ Objname; /* Name of first level object */
+ PCSZ Xcol; /* Name of expandable column */
int Limit; /* Limit of multiple values */
int Pretty; /* Depends on file structure */
int Level; /* Used for catalog table */
- int Base; /* Tne array index base */
+ int Base; /* The array index base */
bool Strict; /* Strict syntax checking */
}; // end of JSONDEF
@@ -66,7 +66,7 @@ class JSONDEF : public DOSDEF { /* Table description */
/* This is the JSN Access Method class declaration. */
/* The table is a DOS file, each record being a JSON object. */
/***********************************************************************/
-class TDBJSN : public TDBDOS {
+class DllExport TDBJSN : public TDBDOS {
friend class JSONCOL;
friend class JSONDEF;
public:
@@ -87,6 +87,8 @@ public:
virtual PCOL InsertSpecialColumn(PCOL colp);
virtual int RowNumber(PGLOBAL g, bool b = FALSE)
{return (b) ? M : N;}
+ virtual bool CanBeFiltered(void)
+ {return Txfp->GetAmType() == TYPE_AM_MGO || !Xcol;}
// Database routines
virtual int Cardinality(PGLOBAL g);
@@ -107,8 +109,8 @@ public:
PJSON Val; // The value of the current row
PJCOL Colp; // The multiple column
JMODE Jmode; // MODE_OBJECT by default
- char *Objname; // The table object name
- char *Xcol; // Name of expandable column
+ PCSZ Objname; // The table object name
+ PCSZ Xcol; // Name of expandable column
int Fpos; // The current row index
int N; // The current Rownum
int M; // Index of multiple value
@@ -127,9 +129,10 @@ public:
/***********************************************************************/
/* Class JSONCOL: JSON access method column descriptor. */
/***********************************************************************/
-class JSONCOL : public DOSCOL {
+class DllExport JSONCOL : public DOSCOL {
friend class TDBJSN;
friend class TDBJSON;
+ friend class MGOFAM;
public:
// Constructors
JSONCOL(PGLOBAL g, PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i);
@@ -139,20 +142,21 @@ class JSONCOL : public DOSCOL {
virtual int GetAmType(void) {return Tjp->GetAmType();}
// Methods
- virtual bool SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check);
- bool ParseJpath(PGLOBAL g);
- virtual void ReadColumn(PGLOBAL g);
- virtual void WriteColumn(PGLOBAL g);
+ virtual bool SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check);
+ bool ParseJpath(PGLOBAL g);
+ char *GetJpath(PGLOBAL g, bool proj);
+ virtual void ReadColumn(PGLOBAL g);
+ virtual void WriteColumn(PGLOBAL g);
protected:
- bool CheckExpand(PGLOBAL g, int i, PSZ nm, bool b);
- bool SetArrayOptions(PGLOBAL g, char *p, int i, PSZ nm);
- 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);
+ bool CheckExpand(PGLOBAL g, int i, PSZ nm, bool b);
+ bool SetArrayOptions(PGLOBAL g, char *p, int i, PSZ nm);
+ 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) {}
@@ -174,7 +178,7 @@ class JSONCOL : public DOSCOL {
/***********************************************************************/
/* This is the JSON Access Method class declaration. */
/***********************************************************************/
-class TDBJSON : public TDBJSN {
+class DllExport TDBJSON : public TDBJSN {
friend class JSONDEF;
friend class JSONCOL;
public:
@@ -221,7 +225,7 @@ class TDBJSON : public TDBJSN {
/***********************************************************************/
/* This is the class declaration for the JSON catalog table. */
/***********************************************************************/
-class TDBJCL : public TDBCAT {
+class DllExport TDBJCL : public TDBCAT {
public:
// Constructor
TDBJCL(PJDEF tdp);
@@ -233,4 +237,5 @@ class TDBJCL : public TDBCAT {
// Members
PTOS Topt;
char *Db;
+ char *Dsn;
}; // end of class TDBJCL
diff --git a/storage/connect/table.cpp b/storage/connect/table.cpp
index 916449be6c6..22fb09dbb86 100644
--- a/storage/connect/table.cpp
+++ b/storage/connect/table.cpp
@@ -47,6 +47,7 @@ TDB::TDB(PTABDEF tdp) : Tdb_No(++Tnum)
To_Orig = NULL;
To_Filter = NULL;
To_CondFil = NULL;
+ Cond = NULL;
Next = NULL;
Name = (tdp) ? tdp->GetName() : NULL;
To_Table = NULL;
@@ -68,6 +69,7 @@ TDB::TDB(PTDB tdbp) : Tdb_No(++Tnum)
To_Orig = tdbp;
To_Filter = NULL;
To_CondFil = NULL;
+ Cond = NULL;
Next = NULL;
Name = tdbp->Name;
To_Table = tdbp->To_Table;
@@ -97,7 +99,7 @@ CHARSET_INFO *TDB::data_charset(void)
/***********************************************************************/
/* Return the datapath of the DB this table belongs to. */
/***********************************************************************/
-PSZ TDB::GetPath(void)
+PCSZ TDB::GetPath(void)
{
return To_Def->GetPath();
} // end of GetPath
diff --git a/storage/connect/tabmac.cpp b/storage/connect/tabmac.cpp
index bbaba591540..a28b5d7108c 100644
--- a/storage/connect/tabmac.cpp
+++ b/storage/connect/tabmac.cpp
@@ -329,7 +329,7 @@ void MACCOL::ReadColumn(PGLOBAL g)
n = 0;
break;
default:
- p = "";
+ p = PlugDup(g, "");
} // endswitch Flag
} else switch (Flag) {
diff --git a/storage/connect/tabmul.cpp b/storage/connect/tabmul.cpp
index 78adde81d12..5c41f9094ac 100644
--- a/storage/connect/tabmul.cpp
+++ b/storage/connect/tabmul.cpp
@@ -1,7 +1,7 @@
/************* TabMul C++ Program Source Code File (.CPP) **************/
/* PROGRAM NAME: TABMUL */
/* ------------- */
-/* Version 1.8 */
+/* Version 1.9 */
/* */
/* COPYRIGHT: */
/* ---------- */
@@ -44,6 +44,11 @@
#define __MFC_COMPAT__ // To define min/max as macro
#endif
//#include <windows.h>
+#if defined(PATHMATCHSPEC)
+#include "Shlwapi.h"
+//using namespace std;
+#pragma comment(lib,"shlwapi.lib")
+#endif // PATHMATCHSPEC
#else
#if defined(UNIX)
#include <fnmatch.h>
@@ -124,9 +129,10 @@ bool TDBMUL::InitFileNames(PGLOBAL g)
{
#define PFNZ 4096
#define FNSZ (_MAX_DRIVE+_MAX_DIR+_MAX_FNAME+_MAX_EXT)
- char *pfn[PFNZ];
- char *filename;
- int rc, n = 0;
+ PTDBDIR dirp;
+ PSZ pfn[PFNZ];
+ PSZ filename;
+ int rc, n = 0;
if (trace)
htrc("in InitFileName: fn[]=%d\n", FNSZ);
@@ -141,115 +147,39 @@ bool TDBMUL::InitFileNames(PGLOBAL g)
if (trace)
htrc("InitFileName: fn='%s'\n", filename);
- if (Mul == 1) {
+ if (Mul != 2) {
/*******************************************************************/
/* To_File is a multiple name with special characters */
/*******************************************************************/
-#if defined(__WIN__)
- char drive[_MAX_DRIVE], direc[_MAX_DIR];
- WIN32_FIND_DATA FileData;
- HANDLE hSearch;
-
- _splitpath(filename, drive, direc, NULL, NULL);
-
- // Start searching files in the target directory.
- hSearch = FindFirstFile(filename, &FileData);
-
- if (hSearch == INVALID_HANDLE_VALUE) {
- rc = GetLastError();
-
- if (rc != ERROR_FILE_NOT_FOUND) {
- FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
- FORMAT_MESSAGE_IGNORE_INSERTS,
- NULL, GetLastError(), 0,
- (LPTSTR)&filename, sizeof(filename), NULL);
- sprintf(g->Message, MSG(BAD_FILE_HANDLE), filename);
- return true;
- } // endif rc
-
- goto suite;
- } // endif hSearch
+ if (Mul == 1)
+ dirp = new(g) TDBDIR(PlugDup(g, filename));
+ else // Mul == 3 (Subdir)
+ dirp = new(g) TDBSDR(PlugDup(g, filename));
- while (n < PFNZ) {
- if (!(FileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
- strcat(strcat(strcpy(filename, drive), direc), FileData.cFileName);
- pfn[n++] = PlugDup(g, filename);
- } // endif dwFileAttributes
-
- if (!FindNextFile(hSearch, &FileData)) {
- rc = GetLastError();
-
- if (rc != ERROR_NO_MORE_FILES) {
- sprintf(g->Message, MSG(NEXT_FILE_ERROR), rc);
- FindClose(hSearch);
- return true;
- } // endif rc
-
- break;
- } // endif FindNextFile
-
- } // endwhile n
+ if (dirp->OpenDB(g))
+ return true;
- // Close the search handle.
- if (!FindClose(hSearch)) {
- strcpy(g->Message, MSG(SRCH_CLOSE_ERR));
- return true;
- } // endif FindClose
+ if (trace && Mul == 3) {
+ int nf = ((PTDBSDR)dirp)->FindInDir(g);
+ htrc("Number of files = %d\n", nf);
+ } // endif trace
+ while (true)
+ if ((rc = dirp->ReadDB(g)) == RC_OK) {
+#if defined(__WIN__)
+ strcat(strcpy(filename, dirp->Drive), dirp->Direc);
#else // !__WIN__
- struct stat fileinfo;
- char fn[FN_REFLEN], direc[FN_REFLEN], pattern[FN_HEADLEN], ftype[FN_EXTLEN];
- DIR *dir;
- struct dirent *entry;
-
- _splitpath(filename, NULL, direc, pattern, ftype);
- strcat(pattern, ftype);
-
- if (trace)
- htrc("direc=%s pattern=%s ftype=%s\n", direc, pattern, ftype);
-
- // Start searching files in the target directory.
- if (!(dir = opendir(direc))) {
- sprintf(g->Message, MSG(BAD_DIRECTORY), direc, strerror(errno));
-
- if (trace)
- htrc("%s\n", g->Message);
-
- return true;
- } // endif dir
-
- if (trace)
- htrc("dir opened: reading files\n");
-
- while ((entry = readdir(dir)) && n < PFNZ) {
- strcat(strcpy(fn, direc), entry->d_name);
-
- if (trace)
- htrc("%s read\n", fn);
-
- if (lstat(fn, &fileinfo) < 0) {
- sprintf(g->Message, "%s: %s", fn, strerror(errno));
- return true;
- } else if (!S_ISREG(fileinfo.st_mode))
- continue; // Not a regular file (should test for links)
-
- /*******************************************************************/
- /* Test whether the file name matches the table name filter. */
- /*******************************************************************/
- if (fnmatch(pattern, entry->d_name, 0))
- continue; // Not a match
-
- strcat(strcpy(filename, direc), entry->d_name);
- pfn[n++] = PlugDup(g, filename);
-
- if (trace)
- htrc("Adding pfn[%d] %s\n", n, filename);
+ strcpy(filename, dirp->Direc);
+#endif // !__WIN__
+ strcat(strcat(filename, dirp->Fname), dirp->Ftype);
+ pfn[n++] = PlugDup(g, filename);
+ } else
+ break;
- } // endwhile readdir
+ dirp->CloseDB(g);
- // Close the dir handle.
- closedir(dir);
-#endif // !__WIN__
+ if (rc == RC_FX)
+ return true;
} else {
/*******************************************************************/
@@ -297,10 +227,6 @@ bool TDBMUL::InitFileNames(PGLOBAL g)
} // endif Mul
-#if defined(__WIN__)
- suite:
-#endif
-
if (n) {
Filenames = (char**)PlugSubAlloc(g, NULL, n * sizeof(char*));
@@ -581,7 +507,95 @@ void TDBMUL::CloseDB(PGLOBAL g)
} // end of CloseDB
-/* --------------------------- Class DIRDEF -------------------------- */
+#if 0
+/* ------------------------- Class TDBMSD ---------------------------- */
+
+ // Method
+PTDB TDBMSD::Clone(PTABS t)
+{
+ PTDBMSD tp;
+ PGLOBAL g = t->G; // Is this really useful ???
+
+ tp = new(g) TDBMSD(this);
+ tp->Tdbp = Tdbp->Clone(t);
+ tp->Columns = tp->Tdbp->GetColumns();
+ return tp;
+} // end of Clone
+
+PTDB TDBMSD::Duplicate(PGLOBAL g)
+{
+ PTDBMSD tmup = new(g) TDBMSD(this);
+
+ tmup->Tdbp = Tdbp->Duplicate(g);
+ return tmup;
+} // end of Duplicate
+
+/***********************************************************************/
+/* Initializes the table filename list. */
+/* Note: tables created by concatenating the file components without */
+/* specifying the LRECL value (that should be restricted to _MAX_PATH)*/
+/* have a LRECL that is the sum of the lengths of all components. */
+/* This is why we use a big filename array to take care of that. */
+/***********************************************************************/
+bool TDBMSD::InitFileNames(PGLOBAL g)
+{
+#define PFNZ 4096
+#define FNSZ (_MAX_DRIVE+_MAX_DIR+_MAX_FNAME+_MAX_EXT)
+ PTDBSDR dirp;
+ PSZ pfn[PFNZ];
+ PSZ filename;
+ int rc, n = 0;
+
+ if (trace)
+ htrc("in InitFileName: fn[]=%d\n", FNSZ);
+
+ filename = (char*)PlugSubAlloc(g, NULL, FNSZ);
+
+ // The sub table may need to refer to the Table original block
+ Tdbp->SetTable(To_Table); // Was not set at construction
+
+ PlugSetPath(filename, Tdbp->GetFile(g), Tdbp->GetPath());
+
+ if (trace)
+ htrc("InitFileName: fn='%s'\n", filename);
+
+ dirp = new(g) TDBSDR(filename);
+
+ if (dirp->OpenDB(g))
+ return true;
+
+ while (true)
+ if ((rc = dirp->ReadDB(g)) == RC_OK) {
+#if defined(__WIN__)
+ strcat(strcpy(filename, dirp->Drive), dirp->Direc);
+#else // !__WIN__
+ strcpy(filename, dirp->Direc);
+#endif // !__WIN__
+ strcat(strcat(filename, dirp->Fname), dirp->Ftype);
+ pfn[n++] = PlugDup(g, filename);
+ } else
+ break;
+
+ if (rc == RC_FX)
+ return true;
+
+ if (n) {
+ Filenames = (char**)PlugSubAlloc(g, NULL, n * sizeof(char*));
+
+ for (int i = 0; i < n; i++)
+ Filenames[i] = pfn[i];
+
+ } else {
+ Filenames = (char**)PlugSubAlloc(g, NULL, sizeof(char*));
+ Filenames[0] = NULL;
+ } // endif n
+
+ NumFiles = n;
+ return false;
+} // end of InitFileNames
+#endif // 0
+
+ /* --------------------------- Class DIRDEF -------------------------- */
/***********************************************************************/
/* DefineAM: define specific AM block values from XDB file. */
@@ -589,8 +603,9 @@ void TDBMUL::CloseDB(PGLOBAL g)
bool DIRDEF::DefineAM(PGLOBAL g, LPCSTR, int)
{
Desc = Fn = GetStringCatInfo(g, "Filename", NULL);
- Incl = (GetIntCatInfo("Subdir", 0) != 0);
- Huge = (GetIntCatInfo("Huge", 0) != 0);
+ Incl = GetBoolCatInfo("Subdir", false);
+ Huge = GetBoolCatInfo("Huge", false);
+ Nodir = GetBoolCatInfo("Nodir", true);
return false;
} // end of DefineAM
@@ -616,57 +631,40 @@ PTDB DIRDEF::GetTable(PGLOBAL g, MODE)
/***********************************************************************/
/* TABDIR constructors. */
/***********************************************************************/
-TDBDIR::TDBDIR(PDIRDEF tdp) : TDBASE(tdp)
- {
- To_File = tdp->Fn;
- iFile = 0;
+void TDBDIR::Init(void)
+{
+ iFile = 0;
#if defined(__WIN__)
- memset(&FileData, 0, sizeof(_finddata_t));
- Hsearch = -1;
- *Drive = '\0';
-#else // !__WIN__
- memset(&Fileinfo, 0, sizeof(struct stat));
- Entry = NULL;
- Dir = NULL;
- Done = false;
- *Pattern = '\0';
-#endif // !__WIN__
- *Fpath = '\0';
- *Direc = '\0';
- *Fname = '\0';
- *Ftype = '\0';
- } // end of TDBDIR standard constructor
-
-TDBDIR::TDBDIR(PTDBDIR tdbp) : TDBASE(tdbp)
- {
- To_File = tdbp->To_File;
- iFile = tdbp->iFile;
-#if defined(__WIN__)
- FileData = tdbp->FileData;
- Hsearch = tdbp->Hsearch;
- strcpy(Drive, tdbp->Drive);
+ Dvalp = NULL;
+ memset(&FileData, 0, sizeof(_finddata_t));
+ hSearch = INVALID_HANDLE_VALUE;
+ *Drive = '\0';
#else // !__WIN__
- Fileinfo = tdbp->Fileinfo;
- Entry = tdbp->Entry;
- Dir = tdbp->Dir;
- Done = tdbp->Done;
- strcpy(Pattern, tdbp->Pattern);
+ memset(&Fileinfo, 0, sizeof(struct stat));
+ Entry = NULL;
+ Dir = NULL;
+ Done = false;
+ *Pattern = '\0';
#endif // !__WIN__
- strcpy(Direc, tdbp->Direc);
- strcpy(Fname, tdbp->Fname);
- strcpy(Ftype, tdbp->Ftype);
- } // end of TDBDIR copy constructor
+ *Fpath = '\0';
+ *Direc = '\0';
+ *Fname = '\0';
+ *Ftype = '\0';
+} // end of Init
-// Method
-PTDB TDBDIR::Clone(PTABS t)
- {
- PTDB tp;
- PGLOBAL g = t->G; // Is this really useful ???
+TDBDIR::TDBDIR(PDIRDEF tdp) : TDBASE(tdp)
+{
+ To_File = tdp->Fn;
+ Nodir = tdp->Nodir;
+ Init();
+} // end of TDBDIR standard constructor
- tp = new(g) TDBDIR(this);
- tp->SetColumns(Columns);
- return tp;
- } // end of Clone
+TDBDIR::TDBDIR(PSZ fpat) : TDBASE((PTABDEF)NULL)
+{
+ To_File = fpat;
+ Nodir = true;
+ Init();
+} // end of TDBDIR constructor
/***********************************************************************/
/* Initialize/get the components of the search file pattern. */
@@ -674,18 +672,19 @@ PTDB TDBDIR::Clone(PTABS t)
char* TDBDIR::Path(PGLOBAL g)
{
PCATLG cat = PlgGetCatalog(g);
+ PTABDEF defp = (PTABDEF)To_Def;
#if defined(__WIN__)
if (!*Drive) {
- PlugSetPath(Fpath, To_File, ((PTABDEF)To_Def)->GetPath());
+ PlugSetPath(Fpath, To_File, defp ? defp->GetPath() : NULL);
_splitpath(Fpath, Drive, Direc, Fname, Ftype);
} else
- _makepath(Fpath, Drive, Direc, Fname, Ftype); // Usefull ???
+ _makepath(Fpath, Drive, Direc, Fname, Ftype); // Usefull for TDBSDR
return Fpath;
#else // !__WIN__
if (!Done) {
- PlugSetPath(Fpath, To_File, ((PTABDEF)To_Def)->GetPath());
+ PlugSetPath(Fpath, To_File, defp ? defp->GetPath() : NULL);
_splitpath(Fpath, NULL, Direc, Fname, Ftype);
strcat(strcpy(Pattern, Fname), Ftype);
Done = true;
@@ -709,23 +708,48 @@ PCOL TDBDIR::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n)
int TDBDIR::GetMaxSize(PGLOBAL g)
{
if (MaxSize < 0) {
- int n = -1;
+ int rc, n = -1;
#if defined(__WIN__)
- int h;
// Start searching files in the target directory.
- h = _findfirst(Path(g), &FileData);
+ hSearch = FindFirstFile(Path(g), &FileData);
- if (h != -1) {
- for (n = 1;; n++)
- if (_findnext(h, &FileData))
- break;
+ if (hSearch == INVALID_HANDLE_VALUE) {
+ rc = GetLastError();
- // Close the search handle.
- _findclose(h);
- } else
- n = 0;
+ if (rc != ERROR_FILE_NOT_FOUND) {
+ char buf[512];
+
+ FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL, GetLastError(), 0, (LPTSTR)&buf, sizeof(buf), NULL);
+ sprintf(g->Message, MSG(BAD_FILE_HANDLE), buf);
+ return -1;
+ } // endif rc
+
+ return 0;
+ } // endif hSearch
+
+ while (true) {
+ if (!(FileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
+ n++;
+
+ if (!FindNextFile(hSearch, &FileData)) {
+ rc = GetLastError();
+
+ if (rc != ERROR_NO_MORE_FILES) {
+ sprintf(g->Message, MSG(NEXT_FILE_ERROR), rc);
+ FindClose(hSearch);
+ return -1;
+ } // endif rc
+
+ break;
+ } // endif Next
+
+ } // endwhile
+ // Close the search handle.
+ FindClose(hSearch);
#else // !__WIN__
Path(g);
@@ -791,30 +815,35 @@ int TDBDIR::ReadDB(PGLOBAL g)
int rc = RC_OK;
#if defined(__WIN__)
- if (Hsearch == -1) {
- /*******************************************************************/
- /* Start searching files in the target directory. The use of the */
- /* Path function is required when called from TDBSDR. */
- /*******************************************************************/
- Hsearch = _findfirst(Path(g), &FileData);
-
- if (Hsearch == -1)
- rc = RC_EF;
- else
- iFile++;
-
- } else {
- if (_findnext(Hsearch, &FileData)) {
- // Restore file name and type pattern
- _splitpath(To_File, NULL, NULL, Fname, Ftype);
- rc = RC_EF;
- } else
- iFile++;
-
- } // endif Hsearch
+ do {
+ if (hSearch == INVALID_HANDLE_VALUE) {
+ /*****************************************************************/
+ /* Start searching files in the target directory. The use of */
+ /* the Path function is required when called from TDBSDR. */
+ /*****************************************************************/
+ hSearch = FindFirstFile(Path(g), &FileData);
+
+ if (hSearch == INVALID_HANDLE_VALUE) {
+ rc = RC_EF;
+ break;
+ } else
+ iFile++;
+
+ } else {
+ if (!FindNextFile(hSearch, &FileData)) {
+ // Restore file name and type pattern
+ _splitpath(To_File, NULL, NULL, Fname, Ftype);
+ rc = RC_EF;
+ break;
+ } else
+ iFile++;
+
+ } // endif hSearch
+
+ } while (Nodir && FileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
if (rc == RC_OK)
- _splitpath(FileData.name, NULL, NULL, Fname, Ftype);
+ _splitpath(FileData.cFileName, NULL, NULL, Fname, Ftype);
#else // !Win32
rc = RC_NF;
@@ -878,8 +907,8 @@ void TDBDIR::CloseDB(PGLOBAL)
{
#if defined(__WIN__)
// Close the search handle.
- _findclose(Hsearch);
- Hsearch = -1;
+ FindClose(hSearch);
+ hSearch = INVALID_HANDLE_VALUE;
#else // !__WIN__
// Close the DIR handle
if (Dir) {
@@ -895,7 +924,7 @@ void TDBDIR::CloseDB(PGLOBAL)
/***********************************************************************/
/* DIRCOL public constructor. */
/***********************************************************************/
-DIRCOL::DIRCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ)
+DIRCOL::DIRCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PCSZ)
: COLBLK(cdp, tdbp, i)
{
if (cprec) {
@@ -907,6 +936,7 @@ DIRCOL::DIRCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ)
} // endif cprec
// Set additional DIR access method information for column.
+ Tdbp = (PTDBDIR)tdbp;
N = cdp->GetOffset();
} // end of DIRCOL constructor
@@ -916,75 +946,84 @@ DIRCOL::DIRCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ)
/***********************************************************************/
DIRCOL::DIRCOL(DIRCOL *col1, PTDB tdbp) : COLBLK(col1, tdbp)
{
- N = col1->N;
+ Tdbp = (PTDBDIR)tdbp;
+ N = col1->N;
} // end of DIRCOL copy constructor
+#if defined(__WIN__)
+/***********************************************************************/
+/* Retrieve time information from FileData. */
+/***********************************************************************/
+void DIRCOL::SetTimeValue(PGLOBAL g, FILETIME& ftime)
+{
+ char tsp[24];
+ SYSTEMTIME stp;
+
+ if (FileTimeToSystemTime(&ftime, &stp)) {
+ sprintf(tsp, "%04d-%02d-%02d %02d:%02d:%02d",
+ stp.wYear, stp.wMonth, stp.wDay, stp.wHour, stp.wMinute, stp.wSecond);
+
+ if (Value->GetType() != TYPE_STRING) {
+ if (!Tdbp->Dvalp)
+ Tdbp->Dvalp = AllocateValue(g, TYPE_DATE, 20, 0, false,
+ "YYYY-MM-DD hh:mm:ss");
+
+ Tdbp->Dvalp->SetValue_psz(tsp);
+ Value->SetValue_pval(Tdbp->Dvalp);
+ } else
+ Value->SetValue_psz(tsp);
+
+ } else
+ Value->Reset();
+
+} // end of SetTimeValue
+#endif // __WIN__
+
/***********************************************************************/
/* ReadColumn: what this routine does is to access the information */
/* corresponding to this column and convert it to buffer type. */
/***********************************************************************/
void DIRCOL::ReadColumn(PGLOBAL g)
- {
- PTDBDIR tdbp = (PTDBDIR)To_Tdb;
-
+ {
if (trace)
htrc("DIR ReadColumn: col %s R%d use=%.4X status=%.4X type=%d N=%d\n",
- Name, tdbp->GetTdb_No(), ColUse, Status, Buf_Type, N);
+ Name, Tdbp->GetTdb_No(), ColUse, Status, Buf_Type, N);
/*********************************************************************/
/* Retrieve the information corresponding to the column number. */
/*********************************************************************/
switch (N) {
#if defined(__WIN__)
- case 0: Value->SetValue_psz(tdbp->Drive); break;
+ case 0: Value->SetValue_psz(Tdbp->Drive); break;
#endif // __WIN__
- case 1: Value->SetValue_psz(tdbp->Direc); break;
- case 2: Value->SetValue_psz(tdbp->Fname); break;
- case 3: Value->SetValue_psz(tdbp->Ftype); break;
+ case 1: Value->SetValue_psz(Tdbp->Direc); break;
+ case 2: Value->SetValue_psz(Tdbp->Fname); break;
+ case 3: Value->SetValue_psz(Tdbp->Ftype); break;
#if defined(__WIN__)
- case 4: Value->SetValue((int)tdbp->FileData.attrib); break;
- case 5: Value->SetValue((int)tdbp->FileData.size); break;
- case 6: Value->SetValue((int)tdbp->FileData.time_write); break;
- case 7: Value->SetValue((int)tdbp->FileData.time_create); break;
- case 8: Value->SetValue((int)tdbp->FileData.time_access); break;
+ case 4: Value->SetValue((int)Tdbp->FileData.dwFileAttributes); break;
+ case 5: Value->SetValue((int)Tdbp->FileData.nFileSizeLow); break;
+ case 6: SetTimeValue(g, Tdbp->FileData.ftLastWriteTime); break;
+ case 7: SetTimeValue(g, Tdbp->FileData.ftCreationTime); break;
+ case 8: SetTimeValue(g, Tdbp->FileData.ftLastAccessTime); break;
#else // !__WIN__
- case 4: Value->SetValue((int)tdbp->Fileinfo.st_mode); break;
- case 5: Value->SetValue((int)tdbp->Fileinfo.st_size); break;
- case 6: Value->SetValue((int)tdbp->Fileinfo.st_mtime); break;
- case 7: Value->SetValue((int)tdbp->Fileinfo.st_ctime); break;
- case 8: Value->SetValue((int)tdbp->Fileinfo.st_atime); break;
- case 9: Value->SetValue((int)tdbp->Fileinfo.st_uid); break;
- case 10: Value->SetValue((int)tdbp->Fileinfo.st_gid); break;
+ case 4: Value->SetValue((int)Tdbp->Fileinfo.st_mode); break;
+ case 5: Value->SetValue((int)Tdbp->Fileinfo.st_size); break;
+ case 6: Value->SetValue((int)Tdbp->Fileinfo.st_mtime); break;
+ case 7: Value->SetValue((int)Tdbp->Fileinfo.st_ctime); break;
+ case 8: Value->SetValue((int)Tdbp->Fileinfo.st_atime); break;
+ case 9: Value->SetValue((int)Tdbp->Fileinfo.st_uid); break;
+ case 10: Value->SetValue((int)Tdbp->Fileinfo.st_gid); break;
#endif // !__WIN__
default:
sprintf(g->Message, MSG(INV_DIRCOL_OFST), N);
- longjmp(g->jumper[g->jump_level], GetAmType());
- } // endswitch N
+ throw GetAmType();
+ } // endswitch N
} // end of ReadColumn
/* ------------------------- Class TDBSDR ---------------------------- */
/***********************************************************************/
-/* TABSDR copy constructors. */
-/***********************************************************************/
-TDBSDR::TDBSDR(PTDBSDR tdbp) : TDBDIR(tdbp)
- {
- Sub = tdbp->Sub;
- } // end of TDBSDR copy constructor
-
-// Method
-PTDB TDBSDR::Clone(PTABS t)
- {
- PTDB tp;
- PGLOBAL g = t->G; // Is this really useful ???
-
- tp = new(g) TDBSDR(this);
- tp->SetColumns(Columns);
- return tp;
- } // end of Clone
-
-/***********************************************************************/
/* SDR GetMaxSize: returns the number of retrieved files. */
/***********************************************************************/
int TDBSDR::GetMaxSize(PGLOBAL g)
@@ -998,47 +1037,124 @@ int TDBSDR::GetMaxSize(PGLOBAL g)
} // end of GetMaxSize
/***********************************************************************/
-/* SDR GetMaxSize: returns the number of retrieved files. */
+/* SDR FindInDir: returns the number of retrieved files. */
/***********************************************************************/
int TDBSDR::FindInDir(PGLOBAL g)
{
- int n = 0;
+ int rc, n = 0;
size_t m = strlen(Direc);
// Start searching files in the target directory.
#if defined(__WIN__)
- int h = _findfirst(Path(g), &FileData);
+ HANDLE h;
- if (h != -1) {
- for (n = 1;; n++)
- if (_findnext(h, &FileData))
- break;
+#if defined(PATHMATCHSPEC)
+ if (!*Drive)
+ Path(g);
- // Close the search handle.
- _findclose(h);
- } // endif h
+ _makepath(Fpath, Drive, Direc, "*", "*");
- // Now search files in sub-directories.
- _makepath(Fpath, Drive, Direc, "*", "");
- h = _findfirst(Fpath, &FileData);
+ h = FindFirstFile(Fpath, &FileData);
- if (h != -1) {
- while (true) {
- if (FileData.attrib & _A_SUBDIR && *FileData.name != '.') {
- // Look in the name sub-directory
- strcat(strcat(Direc, FileData.name), "\\");
- n += FindInDir(g);
- Direc[m] = '\0'; // Restore path
- } // endif SUBDIR
+ if (h == INVALID_HANDLE_VALUE) {
+ rc = GetLastError();
- if (_findnext(h, &FileData))
- break;
+ if (rc != ERROR_FILE_NOT_FOUND) {
+ char buf[512];
- } // endwhile
+ FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL, GetLastError(), 0, (LPTSTR)&buf, sizeof(buf), NULL);
+ sprintf(g->Message, MSG(BAD_FILE_HANDLE), buf);
+ return -1;
+ } // endif rc
- // Close the search handle.
- _findclose(h);
- } // endif h
+ return 0;
+ } // endif h
+
+ while (true) {
+ if ((FileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) &&
+ *FileData.cFileName != '.') {
+ // Look in the name sub-directory
+ strcat(strcat(Direc, FileData.cFileName), "/");
+ n += FindInDir(g);
+ Direc[m] = '\0'; // Restore path
+ } else if (PathMatchSpec(FileData.cFileName, Fpath))
+ n++;
+
+ if (!FindNextFile(h, &FileData)) {
+ rc = GetLastError();
+
+ if (rc != ERROR_NO_MORE_FILES) {
+ sprintf(g->Message, MSG(NEXT_FILE_ERROR), rc);
+ FindClose(h);
+ return -1;
+ } // endif rc
+
+ break;
+ } // endif Next
+
+ } // endwhile
+#else // !PATHMATCHSPEC
+ h = FindFirstFile(Path(g), &FileData);
+
+ if (h == INVALID_HANDLE_VALUE) {
+ rc = GetLastError();
+
+ if (rc != ERROR_FILE_NOT_FOUND) {
+ char buf[512];
+
+ FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL, GetLastError(), 0, (LPTSTR)&buf, sizeof(buf), NULL);
+ sprintf(g->Message, MSG(BAD_FILE_HANDLE), buf);
+ return -1;
+ } // endif rc
+
+ return 0;
+ } // endif hSearch
+
+ while (true) {
+ n++;
+
+ if (!FindNextFile(h, &FileData)) {
+ rc = GetLastError();
+
+ if (rc != ERROR_NO_MORE_FILES) {
+ sprintf(g->Message, MSG(NEXT_FILE_ERROR), rc);
+ FindClose(h);
+ return -1;
+ } // endif rc
+
+ break;
+ } // endif Next
+
+ } // endwhile
+
+ // Now search files in sub-directories.
+ _makepath(Fpath, Drive, Direc, "*", ".");
+ h = FindFirstFile(Fpath, &FileData);
+
+ if (h != INVALID_HANDLE_VALUE) {
+ while (true) {
+ if ((FileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) &&
+ *FileData.cFileName != '.') {
+ // Look in the name sub-directory
+ strcat(strcat(Direc, FileData.cFileName), "/");
+ n += FindInDir(g);
+ Direc[m] = '\0'; // Restore path
+ } // endif SUBDIR
+
+ if (!FindNextFile(h, &FileData))
+ break;
+
+ } // endwhile
+
+ } // endif h
+#endif // !PATHMATCHSPEC
+
+ // Close the search handle.
+ FindClose(h);
#else // !__WIN__
int k;
DIR *dir = opendir(Direc);
@@ -1090,7 +1206,7 @@ bool TDBSDR::OpenDB(PGLOBAL g)
Sub->Next = NULL;
Sub->Prev = NULL;
#if defined(__WIN__)
- Sub->H = -1;
+ Sub->H = INVALID_HANDLE_VALUE;
Sub->Len = strlen(Direc);
#else // !__WIN__
Sub->D = NULL;
@@ -1116,18 +1232,22 @@ int TDBSDR::ReadDB(PGLOBAL g)
// Are there more files in sub-directories
retry:
do {
- if (Sub->H == -1) {
- _makepath(Fpath, Drive, Direc, "*", "");
- Sub->H = _findfirst(Fpath, &FileData);
- } else if (_findnext(Sub->H, &FileData)) {
- _findclose(Sub->H);
- Sub->H = -1;
- *FileData.name = '\0';
- } // endif findnext
-
- } while(*FileData.name == '.');
-
- if (Sub->H == -1) {
+ if (Sub->H == INVALID_HANDLE_VALUE) {
+// _makepath(Fpath, Drive, Direc, "*", "."); why was this made?
+ _makepath(Fpath, Drive, Direc, "*", NULL);
+ Sub->H = FindFirstFile(Fpath, &FileData);
+ } else if (!FindNextFile(Sub->H, &FileData)) {
+ FindClose(Sub->H);
+ Sub->H = INVALID_HANDLE_VALUE;
+ *FileData.cFileName= '\0';
+ break;
+ } // endif findnext
+
+ } while(!(FileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ||
+ (*FileData.cFileName == '.' &&
+ (!FileData.cFileName[1] || FileData.cFileName[1] == '.')));
+
+ if (Sub->H == INVALID_HANDLE_VALUE) {
// No more sub-directories. Are we in a sub-directory?
if (!Sub->Prev)
return rc; // No, all is finished
@@ -1145,17 +1265,17 @@ int TDBSDR::ReadDB(PGLOBAL g)
sup = (PSUBDIR)PlugSubAlloc(g, NULL, sizeof(SUBDIR));
sup->Next = NULL;
sup->Prev = Sub;
- sup->H = -1;
+ sup->H = INVALID_HANDLE_VALUE;
Sub->Next = sup;
} // endif Next
Sub = Sub->Next;
- strcat(strcat(Direc, FileData.name), "\\");
+ strcat(strcat(Direc, FileData.cFileName), "/");
Sub->Len = strlen(Direc);
// Reset Hsearch used by TDBDIR::ReadDB
- _findclose(Hsearch);
- Hsearch = -1;
+ FindClose(hSearch);
+ hSearch = INVALID_HANDLE_VALUE;
goto again;
} // endif H
@@ -1179,7 +1299,8 @@ int TDBSDR::ReadDB(PGLOBAL g)
if (lstat(Fpath, &Fileinfo) < 0) {
sprintf(g->Message, "%s: %s", Fpath, strerror(errno));
rc = RC_FX;
- } else if (S_ISDIR(Fileinfo.st_mode) && *Entry->d_name != '.') {
+ } else if (S_ISDIR(Fileinfo.st_mode) && strcmp(Entry->d_name, ".")
+ && strcmp(Entry->d_name, "..")) {
// Look in the name sub-directory
if (!Sub->Next) {
PSUBDIR sup;
@@ -1423,8 +1544,8 @@ void TDBDHR::CloseDB(PGLOBAL g)
// Close the search handle.
if (!FindClose(Hsearch)) {
strcpy(g->Message, MSG(SRCH_CLOSE_ERR));
- longjmp(g->jumper[g->jump_level], GetAmType());
- } // endif FindClose
+ throw GetAmType();
+ } // endif FindClose
iFile = 0;
Hsearch = INVALID_HANDLE_VALUE;
@@ -1435,8 +1556,8 @@ void TDBDHR::CloseDB(PGLOBAL g)
/***********************************************************************/
/* DHRCOL public constructor. */
/***********************************************************************/
-DHRCOL::DHRCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am)
- : COLBLK(cdp, tdbp, i)
+DHRCOL::DHRCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PCSZ am)
+ : COLBLK(cdp, tdbp, i)
{
if (cprec) {
Next = cprec->GetNext();
diff --git a/storage/connect/tabmul.h b/storage/connect/tabmul.h
index 51fa7f9000a..8a95a772c41 100644
--- a/storage/connect/tabmul.h
+++ b/storage/connect/tabmul.h
@@ -39,7 +39,7 @@ class DllExport TDBMUL : public TDBASE {
virtual void ResetDB(void);
virtual PTDB Clone(PTABS t);
virtual bool IsSame(PTDB tp) {return tp == (PTDB)Tdbp;}
- virtual PSZ GetFile(PGLOBAL g) {return Tdbp->GetFile(g);}
+ virtual PCSZ GetFile(PGLOBAL g) {return Tdbp->GetFile(g);}
virtual int GetRecpos(void) {return 0;}
virtual PCOL ColDB(PGLOBAL g, PSZ name, int num);
bool InitFileNames(PGLOBAL g);
@@ -69,6 +69,34 @@ class DllExport TDBMUL : public TDBASE {
int iFile; // Index of currently processed file
}; // end of class TDBMUL
+#if 0
+/***********************************************************************/
+/* This is the MSD Access Method class declaration for files that are */
+/* physically split in multiple files having the same format. */
+/* This sub-class also include files of the sub-directories. */
+/***********************************************************************/
+class DllExport TDBMSD : public TDBMUL {
+ //friend class MULCOL;
+public:
+ // Constructor
+ TDBMSD(PTDB tdbp) : TDBMUL(tdbp) {}
+ TDBMSD(PTDBMSD tdbp) : TDBMUL(tdbp) {}
+
+ // Implementation
+ virtual PTDB Duplicate(PGLOBAL g);
+
+ // Methods
+ virtual PTDB Clone(PTABS t);
+ bool InitFileNames(PGLOBAL g);
+
+ // Database routines
+
+protected:
+
+ // Members
+}; // end of class TDBMSD
+#endif
+
/***********************************************************************/
/* Directory listing table. */
/***********************************************************************/
@@ -90,7 +118,8 @@ class DllExport DIRDEF : public TABDEF { /* Directory listing table */
// Members
PSZ Fn; /* Path/Name of file search */
bool Incl; /* true to include sub-directories */
- bool Huge; /* true if files can be larger than 2GB */
+ bool Huge; /* true if files can be larger than 2GB */
+ bool Nodir; /* true to exclude directories */
}; // end of DIRDEF
/***********************************************************************/
@@ -101,18 +130,16 @@ class DllExport DIRDEF : public TABDEF { /* Directory listing table */
/***********************************************************************/
class TDBDIR : public TDBASE {
friend class DIRCOL;
- public:
+ friend class TDBMUL;
+public:
// Constructor
TDBDIR(PDIRDEF tdp);
- TDBDIR(PTDBDIR tdbp);
+ TDBDIR(PSZ fpat);
// Implementation
virtual AMT GetAmType(void) {return TYPE_AM_DIR;}
- virtual PTDB Duplicate(PGLOBAL g)
- {return (PTDB)new(g) TDBDIR(this);}
// Methods
- virtual PTDB Clone(PTABS t);
virtual int GetRecpos(void) {return iFile;}
// Database routines
@@ -127,14 +154,16 @@ class TDBDIR : public TDBASE {
virtual void CloseDB(PGLOBAL g);
protected:
+ void Init(void);
char *Path(PGLOBAL g);
// Members
PSZ To_File; // Points to file search pathname
int iFile; // Index of currently retrieved file
#if defined(__WIN__)
- _finddata_t FileData; // Find data structure
- intptr_t Hsearch; // Search handle
+ PVAL Dvalp; // Used to retrieve file date values
+ WIN32_FIND_DATA FileData; // Find data structure
+ HANDLE hSearch; // Search handle
char Drive[_MAX_DRIVE]; // Drive name
#else // !__WIN__
struct stat Fileinfo; // File info structure
@@ -147,6 +176,7 @@ class TDBDIR : public TDBASE {
char Direc[_MAX_DIR]; // Search path
char Fname[_MAX_FNAME]; // File name
char Ftype[_MAX_EXT]; // File extention
+ bool Nodir; // Exclude directories from file list
}; // end of class TDBDIR
/***********************************************************************/
@@ -158,17 +188,11 @@ class TDBDIR : public TDBASE {
/***********************************************************************/
class TDBSDR : public TDBDIR {
friend class DIRCOL;
+ friend class TDBMUL;
public:
// Constructors
TDBSDR(PDIRDEF tdp) : TDBDIR(tdp) {Sub = NULL;}
- TDBSDR(PTDBSDR tdbp);
-
- // Implementation
- virtual PTDB Duplicate(PGLOBAL g)
- {return (PTDB)new(g) TDBSDR(this);}
-
- // Methods
- virtual PTDB Clone(PTABS t);
+ TDBSDR(PSZ fpat) : TDBDIR(fpat) {Sub = NULL;}
// Database routines
virtual int GetMaxSize(PGLOBAL g);
@@ -184,7 +208,7 @@ class TDBSDR : public TDBDIR {
struct _Sub_Dir *Next;
struct _Sub_Dir *Prev;
#if defined(__WIN__)
- intptr_t H; // Search handle
+ HANDLE H; // Search handle
#else // !__WIN__
DIR *D;
#endif // !__WIN__
@@ -202,7 +226,7 @@ class TDBSDR : public TDBDIR {
class DIRCOL : public COLBLK {
public:
// Constructors
- DIRCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am = "DIR");
+ DIRCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PCSZ am = "DIR");
DIRCOL(DIRCOL *colp, PTDB tdbp); // Constructor used in copy process
// Implementation
@@ -214,7 +238,11 @@ class DIRCOL : public COLBLK {
protected:
// Default constructor not to be used
DIRCOL(void) {}
+#if defined(__WIN__)
+ void SetTimeValue(PGLOBAL g, FILETIME& ftime);
+#endif // __WIN__
// Members
+ PTDBDIR Tdbp; // To DIR table
int N; // Column number
}; // end of class DIRCOL
diff --git a/storage/connect/tabmysql.cpp b/storage/connect/tabmysql.cpp
index 1a715819fc8..bdddcf64ca8 100644
--- a/storage/connect/tabmysql.cpp
+++ b/storage/connect/tabmysql.cpp
@@ -68,8 +68,8 @@ void PrintResult(PGLOBAL, PSEM, PQRYRES);
#endif // _CONSOLE
// Used to check whether a MYSQL table is created on itself
-bool CheckSelf(PGLOBAL g, TABLE_SHARE *s, const char *host,
- const char *db, char *tab, const char *src, int port);
+bool CheckSelf(PGLOBAL g, TABLE_SHARE *s, PCSZ host, PCSZ db,
+ PCSZ tab, PCSZ src, int port);
/***********************************************************************/
/* External function. */
@@ -125,7 +125,7 @@ bool MYSQLDEF::GetServerInfo(PGLOBAL g, const char *server_name)
} // endif server
DBUG_PRINT("info", ("get_server_by_name returned server at %lx",
- (long unsigned int) server));
+ (size_t) server));
// TODO: We need to examine which of these can really be NULL
Hostname = PlugDup(g, server->host);
@@ -183,19 +183,22 @@ bool MYSQLDEF::GetServerInfo(PGLOBAL g, const char *server_name)
/***********************************************************************/
bool MYSQLDEF::ParseURL(PGLOBAL g, char *url, bool b)
{
+ char *tabn, *pwd, *schema;
+
if ((!strstr(url, "://") && (!strchr(url, '@')))) {
// No :// or @ in connection string. Must be a straight
// connection name of either "server" or "server/table"
// ok, so we do a little parsing, but not completely!
- if ((Tabname= strchr(url, '/'))) {
+ if ((tabn= strchr(url, '/'))) {
// If there is a single '/' in the connection string,
// this means the user is specifying a table name
- *Tabname++= '\0';
+ *tabn++= '\0';
// there better not be any more '/'s !
- if (strchr(Tabname, '/'))
+ if (strchr(tabn, '/'))
return true;
+ Tabname = tabn;
} else
// Otherwise, straight server name,
Tabname = (b) ? GetStringCatInfo(g, "Tabname", Name) : NULL;
@@ -223,7 +226,7 @@ bool MYSQLDEF::ParseURL(PGLOBAL g, char *url, bool b)
Username += 3;
- if (!(Hostname = strchr(Username, '@'))) {
+ if (!(Hostname = (char*)strchr(Username, '@'))) {
strcpy(g->Message, "No host specified in URL");
return true;
} else {
@@ -231,11 +234,11 @@ bool MYSQLDEF::ParseURL(PGLOBAL g, char *url, bool b)
Server = Hostname;
} // endif Hostname
- if ((Password = strchr(Username, ':'))) {
- *Password++ = 0; // End username
+ if ((pwd = (char*)strchr(Username, ':'))) {
+ *pwd++ = 0; // End username
- // Make sure there isn't an extra / or @
- if ((strchr(Password, '/') || strchr(Hostname, '@'))) {
+ // Make sure there isn't an extra /
+ if (strchr(pwd, '/')) {
strcpy(g->Message, "Syntax error in URL");
return true;
} // endif
@@ -243,8 +246,10 @@ bool MYSQLDEF::ParseURL(PGLOBAL g, char *url, bool b)
// Found that if the string is:
// user:@hostname:port/db/table
// Then password is a null string, so set to NULL
- if ((Password[0] == 0))
- Password = NULL;
+ if ((pwd[0] == 0))
+ Password = NULL;
+ else
+ Password = pwd;
} // endif password
@@ -254,21 +259,23 @@ bool MYSQLDEF::ParseURL(PGLOBAL g, char *url, bool b)
return true;
} // endif
- if ((Tabschema = strchr(Hostname, '/'))) {
- *Tabschema++ = 0;
+ if ((schema = strchr(Hostname, '/'))) {
+ *schema++ = 0;
- if ((Tabname = strchr(Tabschema, '/'))) {
- *Tabname++ = 0;
+ if ((tabn = strchr(schema, '/'))) {
+ *tabn++ = 0;
// Make sure there's not an extra /
- if ((strchr(Tabname, '/'))) {
+ if ((strchr(tabn, '/'))) {
strcpy(g->Message, "Syntax error in URL");
return true;
} // endif /
+ Tabname = tabn;
} // endif TableName
- } // endif database
+ Tabschema = schema;
+ } // endif database
if ((sport = strchr(Hostname, ':')))
*sport++ = 0;
@@ -349,7 +356,7 @@ bool MYSQLDEF::DefineAM(PGLOBAL g, LPCSTR am, int)
Portnumber = GetIntCatInfo("Port", GetDefaultPort());
Server = Hostname;
} else {
- char *locdb = Tabschema;
+ PCSZ locdb = Tabschema;
if (ParseURL(g, url))
return true;
@@ -495,11 +502,11 @@ PCOL TDBMYSQL::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n)
/* filter should be removed from column list. */
/***********************************************************************/
bool TDBMYSQL::MakeSelect(PGLOBAL g, bool mx)
- {
+{
//char *tk = "`";
char tk = '`';
int len = 0, rank = 0;
- bool b = false, oom = false;
+ bool b = false;
PCOL colp;
//PDBUSER dup = PlgGetUser(g);
@@ -526,13 +533,13 @@ bool TDBMYSQL::MakeSelect(PGLOBAL g, bool mx)
for (colp = Columns; colp; colp = colp->GetNext())
if (!colp->IsSpecial()) {
if (b)
- oom |= Query->Append(", ");
+ Query->Append(", ");
else
b = true;
- oom |= Query->Append(tk);
- oom |= Query->Append(colp->GetName());
- oom |= Query->Append(tk);
+ Query->Append(tk);
+ Query->Append(colp->GetName());
+ Query->Append(tk);
((PMYCOL)colp)->Rank = rank++;
} // endif colp
@@ -542,22 +549,22 @@ bool TDBMYSQL::MakeSelect(PGLOBAL g, bool mx)
// Query '*' from...
// (the use of a char constant minimize the result storage)
if (Isview)
- oom |= Query->Append('*');
+ Query->Append('*');
else
- oom |= Query->Append("'*'");
+ Query->Append("'*'");
} // endif ncol
- oom |= Query->Append(" FROM ");
- oom |= Query->Append(tk);
- oom |= Query->Append(TableName);
- oom |= Query->Append(tk);
+ Query->Append(" FROM ");
+ Query->Append(tk);
+ Query->Append(TableName);
+ Query->Append(tk);
len = Query->GetLength();
if (To_CondFil) {
if (!mx) {
- oom |= Query->Append(" WHERE ");
- oom |= Query->Append(To_CondFil->Body);
+ Query->Append(" WHERE ");
+ Query->Append(To_CondFil->Body);
len = Query->GetLength() + 1;
} else
len += (strlen(To_CondFil->Body) + 256);
@@ -565,25 +572,25 @@ bool TDBMYSQL::MakeSelect(PGLOBAL g, bool mx)
} else
len += (mx ? 256 : 1);
- if (oom || Query->Resize(len)) {
+ if (Query->IsTruncated() || Query->Resize(len)) {
strcpy(g->Message, "MakeSelect: Out of memory");
return true;
- } // endif oom
+ } // endif Query
if (trace)
htrc("Query=%s\n", Query->GetStr());
return false;
- } // end of MakeSelect
+} // end of MakeSelect
/***********************************************************************/
/* MakeInsert: make the Insert statement used with MySQL connection. */
/***********************************************************************/
bool TDBMYSQL::MakeInsert(PGLOBAL g)
{
- char *tk = "`";
+ const char *tk = "`";
uint len = 0;
- bool b = false, oom;
+ bool oom, b = false;
PCOL colp;
if (Query)
@@ -622,38 +629,38 @@ bool TDBMYSQL::MakeInsert(PGLOBAL g)
Query = new(g) STRING(g, len);
if (Delayed)
- oom = Query->Set("INSERT DELAYED INTO ");
+ Query->Set("INSERT DELAYED INTO ");
else
- oom = Query->Set("INSERT INTO ");
+ Query->Set("INSERT INTO ");
- oom |= Query->Append(tk);
- oom |= Query->Append(TableName);
- oom |= Query->Append("` (");
+ Query->Append(tk);
+ Query->Append(TableName);
+ Query->Append("` (");
for (colp = Columns; colp; colp = colp->GetNext()) {
if (b)
- oom |= Query->Append(", ");
+ Query->Append(", ");
else
b = true;
- oom |= Query->Append(tk);
- oom |= Query->Append(colp->GetName());
- oom |= Query->Append(tk);
+ Query->Append(tk);
+ Query->Append(colp->GetName());
+ Query->Append(tk);
} // endfor colp
- oom |= Query->Append(") VALUES (");
+ Query->Append(") VALUES (");
#if defined(MYSQL_PREPARED_STATEMENTS)
if (Prep) {
for (int i = 0; i < Nparm; i++)
- oom |= Query->Append("?,");
+ Query->Append("?,");
Query->RepLast(')');
Query->Trim();
} // endif Prep
#endif // MYSQL_PREPARED_STATEMENTS
- if (oom)
+ if ((oom = Query->IsTruncated()))
strcpy(g->Message, "MakeInsert: Out of memory");
return oom;
@@ -684,18 +691,18 @@ bool TDBMYSQL::MakeCommand(PGLOBAL g)
strlwr(strcpy(name, Name)); // Not a keyword
if ((p = strstr(qrystr, name))) {
- bool oom = Query->Set(Qrystr, p - qrystr);
+ Query->Set(Qrystr, p - qrystr);
if (qtd && *(p-1) == ' ') {
- oom |= Query->Append('`');
- oom |= Query->Append(TableName);
- oom |= Query->Append('`');
+ Query->Append('`');
+ Query->Append(TableName);
+ Query->Append('`');
} else
- oom |= Query->Append(TableName);
+ Query->Append(TableName);
- oom |= Query->Append(Qrystr + (p - qrystr) + strlen(name));
+ Query->Append(Qrystr + (p - qrystr) + strlen(name));
- if (oom) {
+ if (Query->IsTruncated()) {
strcpy(g->Message, "MakeCommand: Out of memory");
return true;
} else
@@ -1096,7 +1103,7 @@ bool TDBMYSQL::ReadKey(PGLOBAL g, OPVAL op, const key_range *kr)
To_CondFil->Body= (char*)PlugSubAlloc(g, NULL, 0);
*To_CondFil->Body= 0;
- if ((To_CondFil = hc->CheckCond(g, To_CondFil, To_CondFil->Cond)))
+ if ((To_CondFil = hc->CheckCond(g, To_CondFil, Cond)))
PlugSubAlloc(g, NULL, strlen(To_CondFil->Body) + 1);
} // endif active_index
@@ -1161,24 +1168,23 @@ int TDBMYSQL::WriteDB(PGLOBAL g)
int rc;
uint len = Query->GetLength();
char buf[64];
- bool oom = false;
// Make the Insert command value list
for (PCOL colp = Columns; colp; colp = colp->GetNext()) {
if (!colp->GetValue()->IsNull()) {
if (colp->GetResultType() == TYPE_STRING ||
colp->GetResultType() == TYPE_DATE)
- oom |= Query->Append_quoted(colp->GetValue()->GetCharString(buf));
+ Query->Append_quoted(colp->GetValue()->GetCharString(buf));
else
- oom |= Query->Append(colp->GetValue()->GetCharString(buf));
+ Query->Append(colp->GetValue()->GetCharString(buf));
} else
- oom |= Query->Append("NULL");
+ Query->Append("NULL");
- oom |= Query->Append(',');
+ Query->Append(',');
} // endfor colp
- if (unlikely(oom)) {
+ if (unlikely(Query->IsTruncated())) {
strcpy(g->Message, "WriteDB: Out of memory");
rc = RC_FX;
} else {
@@ -1186,7 +1192,7 @@ int TDBMYSQL::WriteDB(PGLOBAL g)
Myc.m_Rows = -1; // To execute the query
rc = Myc.ExecSQL(g, Query->GetStr());
Query->Truncate(len); // Restore query
- } // endif oom
+ } // endif Query
return (rc == RC_NF) ? RC_OK : rc; // RC_NF is Ok
} // end of WriteDB
@@ -1234,7 +1240,7 @@ void TDBMYSQL::CloseDB(PGLOBAL g)
/***********************************************************************/
/* MYSQLCOL public constructor. */
/***********************************************************************/
-MYSQLCOL::MYSQLCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am)
+MYSQLCOL::MYSQLCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PCSZ am)
: COLBLK(cdp, tdbp, i)
{
if (cprec) {
@@ -1260,7 +1266,7 @@ MYSQLCOL::MYSQLCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am)
/***********************************************************************/
/* MYSQLCOL public constructor. */
/***********************************************************************/
-MYSQLCOL::MYSQLCOL(MYSQL_FIELD *fld, PTDB tdbp, int i, PSZ am)
+MYSQLCOL::MYSQLCOL(MYSQL_FIELD *fld, PTDB tdbp, int i, PCSZ am)
: COLBLK(NULL, tdbp, i)
{
const char *chset = get_charset_name(fld->charsetnr);
@@ -1407,8 +1413,8 @@ void MYSQLCOL::ReadColumn(PGLOBAL g)
if (rc == RC_EF)
sprintf(g->Message, MSG(INV_DEF_READ), rc);
- longjmp(g->jumper[g->jump_level], 11);
- } else
+ throw 11;
+ } else
tdbp->Fetched = true;
if ((buf = ((PTDBMY)To_Tdb)->Myc.GetCharField(Rank))) {
@@ -1669,7 +1675,7 @@ int TDBMYEXC::WriteDB(PGLOBAL g)
/***********************************************************************/
/* MYXCOL public constructor. */
/***********************************************************************/
-MYXCOL::MYXCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am)
+MYXCOL::MYXCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PCSZ am)
: MYSQLCOL(cdp, tdbp, cprec, i, am)
{
// Set additional EXEC MYSQL access method information for column.
@@ -1679,7 +1685,7 @@ MYXCOL::MYXCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am)
/***********************************************************************/
/* MYSQLCOL public constructor. */
/***********************************************************************/
-MYXCOL::MYXCOL(MYSQL_FIELD *fld, PTDB tdbp, int i, PSZ am)
+MYXCOL::MYXCOL(MYSQL_FIELD *fld, PTDB tdbp, int i, PCSZ am)
: MYSQLCOL(fld, tdbp, i, am)
{
if (trace)
diff --git a/storage/connect/tabmysql.h b/storage/connect/tabmysql.h
index 050fa59259b..3c37ae5bf3b 100644
--- a/storage/connect/tabmysql.h
+++ b/storage/connect/tabmysql.h
@@ -86,7 +86,7 @@ class TDBMYSQL : public TDBEXT {
virtual void ResetDB(void) {N = 0;}
virtual int RowNumber(PGLOBAL g, bool b = false);
virtual bool IsView(void) {return Isview;}
- virtual PSZ GetServer(void) {return Server;}
+ virtual PCSZ GetServer(void) {return Server;}
void SetDatabase(LPCSTR db) {Schema = (char*)db;}
// Schema routines
@@ -109,7 +109,7 @@ class TDBMYSQL : public TDBEXT {
// Internal functions
bool MakeSelect(PGLOBAL g, bool mx);
bool MakeInsert(PGLOBAL g);
- int BindColumns(PGLOBAL g);
+ int BindColumns(PGLOBAL g __attribute__((unused)));
virtual bool MakeCommand(PGLOBAL g);
//int MakeUpdate(PGLOBAL g);
//int MakeDelete(PGLOBAL g);
@@ -146,8 +146,8 @@ class MYSQLCOL : public COLBLK {
friend class TDBMYSQL;
public:
// Constructors
- MYSQLCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am = "MYSQL");
- MYSQLCOL(MYSQL_FIELD *fld, PTDB tdbp, int i, PSZ am = "MYSQL");
+ MYSQLCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PCSZ am = "MYSQL");
+ MYSQLCOL(MYSQL_FIELD *fld, PTDB tdbp, int i, PCSZ am = "MYSQL");
MYSQLCOL(MYSQLCOL *colp, PTDB tdbp); // Constructor used in copy process
// Implementation
@@ -215,8 +215,8 @@ class MYXCOL : public MYSQLCOL {
friend class TDBMYEXC;
public:
// Constructors
- MYXCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am = "MYSQL");
- MYXCOL(MYSQL_FIELD *fld, PTDB tdbp, int i, PSZ am = "MYSQL");
+ MYXCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PCSZ am = "MYSQL");
+ MYXCOL(MYSQL_FIELD *fld, PTDB tdbp, int i, PCSZ am = "MYSQL");
MYXCOL(MYXCOL *colp, PTDB tdbp); // Constructor used in copy process
// Methods
@@ -242,10 +242,10 @@ class TDBMCL : public TDBCAT {
virtual PQRYRES GetResult(PGLOBAL g);
// Members
- PSZ Host; // Host machine to use
- PSZ Db; // Database to be used by server
- PSZ Tab; // External table name
- PSZ User; // User logon name
- PSZ Pwd; // Password logon info
- int Port; // MySQL port number (0 = default)
+ PCSZ Host; // Host machine to use
+ PCSZ Db; // Database to be used by server
+ PCSZ Tab; // External table name
+ PCSZ User; // User logon name
+ PCSZ Pwd; // Password logon info
+ int Port; // MySQL port number (0 = default)
}; // end of class TDBMCL
diff --git a/storage/connect/tabodbc.cpp b/storage/connect/tabodbc.cpp
index 488acdd330d..34711d584f1 100644
--- a/storage/connect/tabodbc.cpp
+++ b/storage/connect/tabodbc.cpp
@@ -1,11 +1,11 @@
/************* Tabodbc C++ Program Source Code File (.CPP) *************/
/* PROGRAM NAME: TABODBC */
/* ------------- */
-/* Version 3.1 */
+/* Version 3.2 */
/* */
/* COPYRIGHT: */
/* ---------- */
-/* (C) Copyright to the author Olivier BERTRAND 2000-2016 */
+/* (C) Copyright to the author Olivier BERTRAND 2000-2017 */
/* */
/* WHAT THIS PROGRAM DOES: */
/* ----------------------- */
@@ -116,47 +116,12 @@ bool ODBCDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
if (EXTDEF::DefineAM(g, am, poff))
return true;
- // Tabname = GetStringCatInfo(g, "Name",
- // (Catfunc & (FNC_TABLE | FNC_COL)) ? NULL : Name);
- // Tabname = GetStringCatInfo(g, "Tabname", Tabname);
- // Tabschema = GetStringCatInfo(g, "Dbname", NULL);
- // 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;
-
- // Qrystr = GetStringCatInfo(g, "Query_String", "?");
- // Sep = GetStringCatInfo(g, "Separator", NULL);
Catver = GetIntCatInfo("Catver", 2);
- //Xsrc = GetBoolCatInfo("Execsrc", FALSE);
- //Maxerr = GetIntCatInfo("Maxerr", 0);
- //Maxres = GetIntCatInfo("Maxres", 0);
- //Quoted = GetIntCatInfo("Quoted", 0);
Options = ODBConn::noOdbcDialog;
//Options = ODBConn::noOdbcDialog | ODBConn::useCursorLib;
Cto= GetIntCatInfo("ConnectTimeout", DEFAULT_LOGIN_TIMEOUT);
Qto= GetIntCatInfo("QueryTimeout", DEFAULT_QUERY_TIMEOUT);
-
- //if ((Scrollable = GetBoolCatInfo("Scrollable", false)) && !Elemt)
- // Elemt = 1; // Cannot merge SQLFetch and SQLExtendedFetch
-
- //if (Catfunc == FNC_COL)
- // Colpat = GetStringCatInfo(g, "Colpat", NULL);
-
- //if (Catfunc == FNC_TABLE)
- // Tabtyp = GetStringCatInfo(g, "Tabtype", NULL);
-
UseCnc = GetBoolCatInfo("UseDSN", false);
-
- // Memory was Boolean, it is now integer
- //if (!(Memory = GetIntCatInfo("Memory", 0)))
- // Memory = GetBoolCatInfo("Memory", false) ? 1 : 0;
-
- //Pseudo = 2; // FILID is Ok but not ROWID
return false;
} // end of DefineAM
@@ -210,59 +175,22 @@ TDBODBC::TDBODBC(PODEF tdp) : TDBEXT(tdp)
if (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;
Ops.Cto = tdp->Cto;
Ops.Qto = tdp->Qto;
- //Quoted = MY_MAX(0, tdp->GetQuoted());
- //Rows = tdp->GetElemt();
Catver = tdp->Catver;
- //Memory = tdp->Memory;
- //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;
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;
- //Query = NULL;
- //Count = NULL;
-//Where = NULL;
- //MulConn = NULL;
- //DBQ = NULL;
- //Qrp = NULL;
- //Fpos = 0;
- //Curpos = 0;
- //AftRows = 0;
- //CurNum = 0;
- //Rbuf = 0;
- //BufSize = 0;
- //Nparm = 0;
- //Placed = false;
} // end of TDBODBC standard constructor
TDBODBC::TDBODBC(PTDBODBC tdbp) : TDBEXT(tdbp)
@@ -270,32 +198,7 @@ TDBODBC::TDBODBC(PTDBODBC tdbp) : TDBEXT(tdbp)
Ocp = tdbp->Ocp; // is that right ?
Cnp = tdbp->Cnp;
Connect = tdbp->Connect;
- //TableName = tdbp->TableName;
- //Schema = tdbp->Schema;
Ops = tdbp->Ops;
- //Catalog = tdbp->Catalog;
- //Srcdef = tdbp->Srcdef;
- //Qrystr = tdbp->Qrystr;
- //Memory = tdbp->Memory;
- //Scrollable = tdbp->Scrollable;
- //Quote = tdbp->Quote;
- //Query = tdbp->Query;
- //Count = tdbp->Count;
-//Where = tdbp->Where;
- //MulConn = tdbp->MulConn;
- //DBQ = tdbp->DBQ;
- //Options = tdbp->Options;
- //Quoted = tdbp->Quoted;
- //Rows = tdbp->Rows;
- //Fpos = 0;
- //Curpos = 0;
- //AftRows = 0;
- //CurNum = 0;
- //Rbuf = 0;
- //BufSize = tdbp->BufSize;
- //Nparm = tdbp->Nparm;
- //Qrp = tdbp->Qrp;
- //Placed = false;
} // end of TDBODBC copy constructor
// Method
@@ -328,7 +231,7 @@ PCOL TDBODBC::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n)
/* This used for Multiple(1) tables. Also prepare a connect string */
/* with a place holder to be used by SetFile. */
/***********************************************************************/
-PSZ TDBODBC::GetFile(PGLOBAL g)
+PCSZ TDBODBC::GetFile(PGLOBAL g)
{
if (Connect) {
char *p1, *p2;
@@ -389,152 +292,15 @@ void TDBODBC::SetFile(PGLOBAL g, PSZ fn)
DBQ = fn;
} // end of SetFile
-#if 0
-/******************************************************************/
-/* Convert an UTF-8 string to latin characters. */
-/******************************************************************/
-int TDBODBC::Decode(char *txt, char *buf, size_t n)
-{
- uint dummy_errors;
- uint32 len= copy_and_convert(buf, n, &my_charset_latin1,
- txt, strlen(txt),
- &my_charset_utf8_general_ci,
- &dummy_errors);
- buf[len]= '\0';
- return 0;
-} // end of Decode
-
-/***********************************************************************/
-/* MakeSQL: make the SQL statement use with ODBC connection. */
-/* Note: when implementing EOM filtering, column only used in local */
-/* filter should be removed from column list. */
-/***********************************************************************/
-bool TDBODBC::MakeSQL(PGLOBAL g, bool cnt)
- {
- char *schmp = NULL, *catp = NULL, buf[NAM_LEN * 3];
- int len;
- bool oom = false, first = true;
- PTABLE tablep = To_Table;
- PCOL colp;
-
- if (Srcdef) {
- if (strstr(Srcdef, "%s")) {
- char *fil;
-
- fil = (To_CondFil) ? To_CondFil->Body : PlugDup(g, "1=1");
- Query = new(g)STRING(g, strlen(Srcdef) + strlen(fil));
- Query->SetLength(sprintf(Query->GetStr(), Srcdef, fil));
- } else
- Query = new(g)STRING(g, 0, Srcdef);
-
- return false;
- } // endif Srcdef
-
- // Allocate the string used to contain the Query
- Query = new(g)STRING(g, 1023, "SELECT ");
-
- if (!cnt) {
- if (Columns) {
- // Normal SQL statement to retrieve results
- for (colp = Columns; colp; colp = colp->GetNext())
- if (!colp->IsSpecial()) {
- if (!first)
- oom |= Query->Append(", ");
- else
- first = false;
-
- // Column name can be encoded in UTF-8
- Decode(colp->GetName(), buf, sizeof(buf));
-
- if (Quote) {
- // Put column name between identifier quotes in case in contains blanks
- oom |= Query->Append(Quote);
- oom |= Query->Append(buf);
- oom |= Query->Append(Quote);
- } else
- oom |= Query->Append(buf);
-
- ((PEXTCOL)colp)->SetRank(++Ncol);
- } // endif colp
-
- } else
- // !Columns can occur for queries such that sql count(*) from...
- // for which we will count the rows from sql * from...
- oom |= Query->Append('*');
-
- } else
- // SQL statement used to retrieve the size of the result
- oom |= Query->Append("count(*)");
-
- oom |= Query->Append(" FROM ");
-
- if (Catalog && *Catalog)
- catp = Catalog;
-
- //if (tablep->GetSchema())
- // schmp = (char*)tablep->GetSchema();
- //else
- if (Schema && *Schema)
- schmp = Schema;
-
- if (catp) {
- oom |= Query->Append(catp);
-
- if (schmp) {
- oom |= Query->Append('.');
- oom |= Query->Append(schmp);
- } // endif schmp
-
- oom |= Query->Append('.');
- } else if (schmp) {
- oom |= Query->Append(schmp);
- oom |= Query->Append('.');
- } // endif schmp
-
- // Table name can be encoded in UTF-8
- Decode(TableName, buf, sizeof(buf));
-
- if (Quote) {
- // Put table name between identifier quotes in case in contains blanks
- oom |= Query->Append(Quote);
- oom |= Query->Append(buf);
- oom |= Query->Append(Quote);
- } else
- oom |= Query->Append(buf);
-
- len = Query->GetLength();
-
- if (To_CondFil) {
- if (Mode == MODE_READ) {
- oom |= Query->Append(" WHERE ");
- oom |= Query->Append(To_CondFil->Body);
- len = Query->GetLength() + 1;
- } else
- len += (strlen(To_CondFil->Body) + 256);
-
- } else
- len += ((Mode == MODE_READX) ? 256 : 1);
-
- if (oom || Query->Resize(len)) {
- strcpy(g->Message, "MakeSQL: Out of memory");
- return true;
- } // endif oom
-
- if (trace)
- htrc("Query=%s\n", Query->GetStr());
-
- return false;
- } // end of MakeSQL
-#endif // 0
-
/***********************************************************************/
/* MakeInsert: make the Insert statement used with ODBC connection. */
/***********************************************************************/
bool TDBODBC::MakeInsert(PGLOBAL g)
{
- char *schmp = NULL, *catp = NULL, buf[NAM_LEN * 3];
+ PCSZ schmp = NULL;
+ char *catp = NULL, buf[NAM_LEN * 3];
int len = 0;
- bool b = false, oom = false;
+ bool oom, b = false;
PTABLE tablep = To_Table;
PCOL colp;
@@ -571,32 +337,32 @@ bool TDBODBC::MakeInsert(PGLOBAL g)
Query = new(g) STRING(g, len, "INSERT INTO ");
if (catp) {
- oom |= Query->Append(catp);
+ Query->Append(catp);
if (schmp) {
- oom |= Query->Append('.');
- oom |= Query->Append(schmp);
+ Query->Append('.');
+ Query->Append(schmp);
} // endif schmp
- oom |= Query->Append('.');
+ Query->Append('.');
} else if (schmp) {
- oom |= Query->Append(schmp);
- oom |= Query->Append('.');
+ Query->Append(schmp);
+ Query->Append('.');
} // endif schmp
if (Quote) {
// Put table name between identifier quotes in case in contains blanks
- oom |= Query->Append(Quote);
- oom |= Query->Append(buf);
- oom |= Query->Append(Quote);
+ Query->Append(Quote);
+ Query->Append(buf);
+ Query->Append(Quote);
} else
- oom |= Query->Append(buf);
+ Query->Append(buf);
- oom |= Query->Append('(');
+ Query->Append('(');
for (colp = Columns; colp; colp = colp->GetNext()) {
if (b)
- oom |= Query->Append(", ");
+ Query->Append(", ");
else
b = true;
@@ -605,20 +371,20 @@ bool TDBODBC::MakeInsert(PGLOBAL g)
if (Quote) {
// Put column name between identifier quotes in case in contains blanks
- oom |= Query->Append(Quote);
- oom |= Query->Append(buf);
- oom |= Query->Append(Quote);
+ Query->Append(Quote);
+ Query->Append(buf);
+ Query->Append(Quote);
} else
- oom |= Query->Append(buf);
+ Query->Append(buf);
} // endfor colp
- oom |= Query->Append(") VALUES (");
+ Query->Append(") VALUES (");
for (int i = 0; i < Nparm; i++)
- oom |= Query->Append("?,");
+ Query->Append("?,");
- if (oom)
+ if ((oom = Query->IsTruncated()))
strcpy(g->Message, "MakeInsert: Out of memory");
else
Query->RepLast(')');
@@ -646,73 +412,6 @@ bool TDBODBC::BindParameters(PGLOBAL g)
#if 0
/***********************************************************************/
-/* MakeCommand: make the Update or Delete statement to send to the */
-/* MySQL server. Limited to remote values and filtering. */
-/***********************************************************************/
-bool TDBODBC::MakeCommand(PGLOBAL g)
- {
- 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;
-
- // Make a lower case copy of the originale query and change
- // back ticks to the data source identifier quoting character
- do {
- 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), " "));
-
- if (strstr(" update delete low_priority ignore quick from ", name)) {
- strlwr(strcat(strcat(strcpy(name, qc), Name), qc));
- k += 2;
- } else
- strlwr(strcpy(name, Name)); // Not a keyword
-
- if ((p = strstr(qrystr, name))) {
- for (i = 0; i < p - qrystr; i++)
- stmt[i] = (Qrystr[i] == '`') ? *qc : Qrystr[i];
-
- stmt[i] = 0;
- k += i + (int)strlen(Name);
-
- if (qtd && *(p - 1) == ' ')
- strcat(strcat(strcat(stmt, qc), TableName), qc);
- else
- strcat(stmt, TableName);
-
- i = (int)strlen(stmt);
-
- do {
- 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");
- return true;
- } // endif p
-
- Query = new(g) STRING(g, 0, stmt);
- return (!Query->GetSize());
- } // end of MakeCommand
-
-/***********************************************************************/
/* MakeUpdate: make the SQL statement to send to ODBC connection. */
/***********************************************************************/
char *TDBODBC::MakeUpdate(PGLOBAL g)
@@ -829,35 +528,6 @@ int TDBODBC::Cardinality(PGLOBAL g)
return Cardinal;
} // end of Cardinality
-#if 0
-/***********************************************************************/
-/* ODBC GetMaxSize: returns table size estimate in number of lines. */
-/***********************************************************************/
-int TDBODBC::GetMaxSize(PGLOBAL g)
- {
- if (MaxSize < 0) {
- if (Mode == MODE_DELETE)
- // Return 0 in mode DELETE in case of delete all.
- MaxSize = 0;
- else if (!Cardinality(NULL))
- MaxSize = 10; // To make MySQL happy
- else if ((MaxSize = Cardinality(g)) < 0)
- MaxSize = 12; // So we can see an error occurred
-
- } // endif MaxSize
-
- return MaxSize;
- } // end of GetMaxSize
-
-/***********************************************************************/
-/* Return max size value. */
-/***********************************************************************/
-int TDBODBC::GetProgMax(PGLOBAL g)
- {
- return GetMaxSize(g);
- } // end of GetProgMax
-#endif // 0
-
/***********************************************************************/
/* ODBC Access Method opening routine. */
/* New method now that this routine is called recursively (last table */
@@ -1064,7 +734,7 @@ bool TDBODBC::ReadKey(PGLOBAL g, OPVAL op, const key_range *kr)
To_CondFil->Body= (char*)PlugSubAlloc(g, NULL, 0);
*To_CondFil->Body= 0;
- if ((To_CondFil = hc->CheckCond(g, To_CondFil, To_CondFil->Cond)))
+ if ((To_CondFil = hc->CheckCond(g, To_CondFil, Cond)))
PlugSubAlloc(g, NULL, strlen(To_CondFil->Body) + 1);
} // endif active_index
@@ -1097,8 +767,6 @@ int TDBODBC::ReadDB(PGLOBAL g)
if (trace > 1)
htrc("ODBC ReadDB: R%d Mode=%d\n", GetTdb_No(), Mode);
- //htrc("ODBC ReadDB: R%d Mode=%d key=%p link=%p Kindex=%p\n",
- // GetTdb_No(), Mode, To_Key_Col, To_Link, To_Kindex);
if (Mode == MODE_UPDATE || Mode == MODE_DELETE) {
if (!Query && MakeCommand(g))
@@ -1118,12 +786,6 @@ int TDBODBC::ReadDB(PGLOBAL g)
} // endif Mode
- //if (To_Kindex) {
- // // Direct access of ODBC tables is not implemented yet
- // strcpy(g->Message, MSG(NO_ODBC_DIRECT));
- // return RC_FX;
- // } // endif To_Kindex
-
/*********************************************************************/
/* Now start the reading process. */
/* Here is the place to fetch the line(s). */
@@ -1208,11 +870,6 @@ int TDBODBC::DeleteDB(PGLOBAL g, int irc)
/***********************************************************************/
void TDBODBC::CloseDB(PGLOBAL g)
{
-//if (To_Kindex) {
-// To_Kindex->Close();
-// To_Kindex = NULL;
-// } // endif
-
if (Ocp)
Ocp->Close();
@@ -1227,20 +884,13 @@ void TDBODBC::CloseDB(PGLOBAL g)
/***********************************************************************/
/* ODBCCOL public constructor. */
/***********************************************************************/
-ODBCCOL::ODBCCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am)
+ODBCCOL::ODBCCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PCSZ am)
: EXTCOL(cdp, tdbp, cprec, i, am)
{
// Set additional ODBC access method information for column.
-//Crp = NULL;
-//Long = Precision;
-//strcpy(F_Date, cdp->F_Date);
-//To_Val = NULL;
Slen = 0;
StrLen = &Slen;
Sqlbuf = NULL;
-//Bufp = NULL;
-//Blkp = NULL;
-//Rank = 0; // Not known yet
} // end of ODBCCOL constructor
/***********************************************************************/
@@ -1248,17 +898,9 @@ ODBCCOL::ODBCCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am)
/***********************************************************************/
ODBCCOL::ODBCCOL(void) : EXTCOL()
{
-//Crp = NULL;
-//Buf_Type = TYPE_INT; // This is a count(*) column
-//// Set additional Dos access method information for column.
-//Long = sizeof(int);
-//To_Val = NULL;
Slen = 0;
StrLen = &Slen;
Sqlbuf = NULL;
-//Bufp = NULL;
-//Blkp = NULL;
-//Rank = 1;
} // end of ODBCCOL constructor
/***********************************************************************/
@@ -1267,66 +909,11 @@ ODBCCOL::ODBCCOL(void) : EXTCOL()
/***********************************************************************/
ODBCCOL::ODBCCOL(ODBCCOL *col1, PTDB tdbp) : EXTCOL(col1, tdbp)
{
-//Crp = col1->Crp;
-//Long = col1->Long;
-//strcpy(F_Date, col1->F_Date);
-//To_Val = col1->To_Val;
Slen = col1->Slen;
StrLen = col1->StrLen;
Sqlbuf = col1->Sqlbuf;
-//Bufp = col1->Bufp;
-//Blkp = col1->Blkp;
-//Rank = col1->Rank;
} // end of ODBCCOL copy constructor
-#if 0
-/***********************************************************************/
-/* SetBuffer: prepare a column block for write operation. */
-/***********************************************************************/
-bool ODBCCOL::SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check)
- {
- if (!(To_Val = value)) {
- sprintf(g->Message, MSG(VALUE_ERROR), Name);
- return true;
- } else if (Buf_Type == value->GetType()) {
- // Values are of the (good) column type
- if (Buf_Type == TYPE_DATE) {
- // If any of the date values is formatted
- // output format must be set for the receiving table
- if (GetDomain() || ((DTVAL *)value)->IsFormatted())
- goto newval; // This will make a new value;
-
- } else if (Buf_Type == TYPE_DOUBLE)
- // Float values must be written with the correct (column) precision
- // Note: maybe this should be forced by ShowValue instead of this ?
- value->SetPrec(GetScale());
-
- Value = value; // Directly access the external value
- } else {
- // Values are not of the (good) column type
- if (check) {
- sprintf(g->Message, MSG(TYPE_VALUE_ERR), Name,
- GetTypeName(Buf_Type), GetTypeName(value->GetType()));
- return true;
- } // endif check
-
- newval:
- if (InitValue(g)) // Allocate the matching value block
- return true;
-
- } // endif's Value, Buf_Type
-
- // Because Colblk's have been made from a copy of the original TDB in
- // case of Update, we must reset them to point to the original one.
- if (To_Tdb->GetOrig())
- To_Tdb = (PTDB)To_Tdb->GetOrig();
-
- // Set the Column
- Status = (ok) ? BUF_EMPTY : BUF_NO;
- return false;
- } // end of SetBuffer
-#endif // 0
-
/***********************************************************************/
/* ReadColumn: when SQLFetch is used there is nothing to do as the */
/* column buffer was bind to the record set. This is also the case */
@@ -1715,7 +1302,7 @@ int TDBXDBC::DeleteDB(PGLOBAL g, int irc)
/***********************************************************************/
/* XSRCCOL public constructor. */
/***********************************************************************/
-XSRCCOL::XSRCCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am)
+XSRCCOL::XSRCCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PCSZ am)
: ODBCCOL(cdp, tdbp, cprec, i, am)
{
// Set additional ODBC access method information for column.
diff --git a/storage/connect/tabodbc.h b/storage/connect/tabodbc.h
index fcefad5647b..487a5073559 100644
--- a/storage/connect/tabodbc.h
+++ b/storage/connect/tabodbc.h
@@ -1,7 +1,7 @@
/*************** Tabodbc H Declares Source Code File (.H) **************/
-/* Name: TABODBC.H Version 1.8 */
+/* Name: TABODBC.H Version 1.9 */
/* */
-/* (C) Copyright to the author Olivier BERTRAND 2000-2015 */
+/* (C) Copyright to the author Olivier BERTRAND 2000-2017 */
/* */
/* This file contains the TDBODBC classes declares. */
/***********************************************************************/
@@ -33,14 +33,7 @@ public:
// Implementation
virtual const char *GetType(void) {return "ODBC";}
PSZ GetConnect(void) {return Connect;}
- //PSZ GetTabname(void) {return Tabname;}
- //PSZ GetTabschema(void) {return Tabschema;}
- //PSZ GetTabcat(void) {return Tabcat;}
- //PSZ GetSrcdef(void) {return Srcdef;}
- //char GetSep(void) {return (Sep) ? *Sep : 0;}
- //int GetQuoted(void) {return Quoted;}
int GetCatver(void) {return Catver;}
- //int GetOptions(void) {return Options;}
// Methods
virtual int Indexable(void) {return 2;}
@@ -50,27 +43,7 @@ public:
protected:
// Members
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 Tabtyp; /* Catalog table type */
- //PSZ Colpat; /* Catalog column pattern */
- //PSZ Srcdef; /* The source table SQL definition */
- //PSZ Qchar; /* Identifier quoting character */
- //PSZ Qrystr; /* The original query */
- //PSZ Sep; /* Decimal separator */
int Catver; /* ODBC version for catalog functions */
- //int Options; /* Open connection options */
- //int Cto; /* Open connection timeout */
- //int Qto; /* Query (command) timeout */
- //int Quoted; /* Identifier quoting level */
- //int Maxerr; /* Maxerr for an Exec table */
- //int Maxres; /* Maxres for a catalog table */
- //int Memory; /* Put result set in memory */
- //bool Scrollable; /* Use scrollable cursor */
- //bool Xsrc; /* Execution type */
bool UseCnc; /* Use SQLConnect (!SQLDriverConnect) */
}; // end of ODBCDEF
@@ -96,20 +69,16 @@ class TDBODBC : public TDBEXT {
// Methods
virtual PTDB Clone(PTABS t);
-//virtual int GetRecpos(void);
virtual bool SetRecpos(PGLOBAL g, int recpos);
- virtual PSZ GetFile(PGLOBAL g);
+ virtual PCSZ GetFile(PGLOBAL g);
virtual void SetFile(PGLOBAL g, PSZ fn);
virtual void ResetSize(void);
-//virtual int GetAffectedRows(void) {return AftRows;}
- virtual PSZ GetServer(void) {return "ODBC";}
+ virtual PCSZ GetServer(void) {return "ODBC";}
virtual int Indexable(void) {return 2;}
// Database routines
virtual PCOL MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n);
virtual int Cardinality(PGLOBAL g);
-//virtual int GetMaxSize(PGLOBAL g);
-//virtual int GetProgMax(PGLOBAL g);
virtual bool OpenDB(PGLOBAL g);
virtual int ReadDB(PGLOBAL g);
virtual int WriteDB(PGLOBAL g);
@@ -119,14 +88,8 @@ class TDBODBC : public TDBEXT {
protected:
// Internal functions
-//int Decode(char *utf, char *buf, size_t n);
-//bool MakeSQL(PGLOBAL g, bool cnt);
bool MakeInsert(PGLOBAL g);
-//virtual bool MakeCommand(PGLOBAL g);
-//bool MakeFilter(PGLOBAL g, bool c);
bool BindParameters(PGLOBAL g);
-//char *MakeUpdate(PGLOBAL g);
-//char *MakeDelete(PGLOBAL g);
// Members
ODBConn *Ocp; // Points to an ODBC connection class
@@ -145,15 +108,12 @@ class ODBCCOL : public EXTCOL {
friend class TDBODBC;
public:
// Constructors
- ODBCCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am = "ODBC");
+ ODBCCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PCSZ am = "ODBC");
ODBCCOL(ODBCCOL *colp, PTDB tdbp); // Constructor used in copy process
// Implementation
virtual int GetAmType(void) {return TYPE_AM_ODBC;}
SQLLEN *GetStrLen(void) {return StrLen;}
-// int GetRank(void) {return Rank;}
-// PVBLK GetBlkp(void) {return Blkp;}
-// void SetCrp(PCOLRES crp) {Crp = crp;}
// Methods
//virtual bool SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check);
@@ -162,7 +122,6 @@ class ODBCCOL : public EXTCOL {
void AllocateBuffers(PGLOBAL g, int rows);
void *GetBuffer(DWORD rows);
SWORD GetBuflen(void);
-// void Print(PGLOBAL g, FILE *, uint);
protected:
// Constructor for count(*) column
@@ -170,14 +129,8 @@ class ODBCCOL : public EXTCOL {
// Members
TIMESTAMP_STRUCT *Sqlbuf; // To get SQL_TIMESTAMP's
-//PCOLRES Crp; // To storage result
-//void *Bufp; // To extended buffer
-//PVBLK Blkp; // To Value Block
-//char F_Date[12]; // Internal Date format
-//PVAL To_Val; // To value used for Insert
SQLLEN *StrLen; // As returned by ODBC
SQLLEN Slen; // Used with Fetch
-//int Rank; // Rank (position) number in the query
}; // end of class ODBCCOL
/***********************************************************************/
@@ -226,11 +179,10 @@ class XSRCCOL : public ODBCCOL {
friend class TDBXDBC;
public:
// Constructors
- XSRCCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am = "ODBC");
+ XSRCCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PCSZ am = "ODBC");
XSRCCOL(XSRCCOL *colp, PTDB tdbp); // Constructor used in copy process
// Implementation
-//virtual int GetAmType(void) {return TYPE_AM_ODBC;}
// Methods
virtual void ReadColumn(PGLOBAL g);
@@ -287,10 +239,10 @@ class TDBOTB : public TDBDRV {
virtual PQRYRES GetResult(PGLOBAL g);
// Members
- char *Dsn; // Points to connection string
- char *Schema; // Points to schema name or NULL
- char *Tab; // Points to ODBC table name or pattern
- char *Tabtyp; // Points to ODBC table type
+ PCSZ Dsn; // Points to connection string
+ PCSZ Schema; // Points to schema name or NULL
+ PCSZ Tab; // Points to ODBC table name or pattern
+ PCSZ Tabtyp; // Points to ODBC table type
ODBCPARM Ops; // Additional parameters
}; // end of class TDBOTB
diff --git a/storage/connect/tabpivot.cpp b/storage/connect/tabpivot.cpp
index c6d32884417..76a46e6899b 100644
--- a/storage/connect/tabpivot.cpp
+++ b/storage/connect/tabpivot.cpp
@@ -106,214 +106,211 @@ bool PIVAID::SkipColumn(PCOLRES crp, char *skc)
/* Make the Pivot table column list. */
/***********************************************************************/
PQRYRES PIVAID::MakePivotColumns(PGLOBAL g)
- {
+{
char *p, *query, *colname, *skc, buf[64];
- int rc, ndif, nblin, w = 0;
+ int ndif, nblin, w = 0;
bool b = false;
PVAL valp;
PQRYRES qrp;
PCOLRES *pcrp, crp, fncrp = NULL;
- // Save stack and allocation environment and prepare error return
- if (g->jump_level == MAX_JUMP) {
- strcpy(g->Message, MSG(TOO_MANY_JUMPS));
- return NULL;
- } // endif jump_level
-
- if ((rc= setjmp(g->jumper[++g->jump_level])) != 0) {
- goto err;
- } // endif rc
-
- // Are there columns to skip?
- if (Skcol) {
- uint n = strlen(Skcol);
-
- skc = (char*)PlugSubAlloc(g, NULL, n + 2);
- strcpy(skc, Skcol);
- skc[n + 1] = 0;
-
- // Replace ; by nulls in skc
- for (p = strchr(skc, ';'); p; p = strchr(p, ';'))
- *p++ = 0;
-
- } else
- skc = NULL;
-
- if (!Tabsrc && Tabname) {
- // Locate the query
- query = (char*)PlugSubAlloc(g, NULL, strlen(Tabname) + 26);
- sprintf(query, "SELECT * FROM `%s` LIMIT 1", Tabname);
- } else if (!Tabsrc) {
- strcpy(g->Message, MSG(SRC_TABLE_UNDEF));
- return NULL;
- } else
- query = Tabsrc;
-
- // Open a MySQL connection for this table
- if (!Myc.Open(g, Host, Database, User, Pwd, Port)) {
- b = true;
-
- // Returned values must be in their original character set
- if (Myc.ExecSQL(g, "SET character_set_results=NULL", &w) == RC_FX)
- goto err;
- else
- Myc.FreeResult();
-
- } else
- return NULL;
-
- // Send the source command to MySQL
- if (Myc.ExecSQL(g, query, &w) == RC_FX)
- goto err;
-
- // We must have a storage query to get pivot column values
- if (!(Qryp = Myc.GetResult(g, true)))
- goto err;
-
- if (!Fncol) {
- for (crp = Qryp->Colresp; crp; crp = crp->Next)
- if ((!Picol || stricmp(Picol, crp->Name)) && !SkipColumn(crp, skc))
- Fncol = crp->Name;
-
- if (!Fncol) {
- strcpy(g->Message, MSG(NO_DEF_FNCCOL));
- goto err;
- } // endif Fncol
-
- } // endif Fncol
-
- if (!Picol) {
- // Find default Picol as the last one not equal to Fncol
- for (crp = Qryp->Colresp; crp; crp = crp->Next)
- if (stricmp(Fncol, crp->Name) && !SkipColumn(crp, skc))
- Picol = crp->Name;
-
- if (!Picol) {
- strcpy(g->Message, MSG(NO_DEF_PIVOTCOL));
- goto err;
- } // endif Picol
-
- } // endif picol
-
- // Prepare the column list
- for (pcrp = &Qryp->Colresp; crp = *pcrp; )
- if (SkipColumn(crp, skc)) {
- // Ignore this column
- *pcrp = crp->Next;
- } else if (!stricmp(Picol, crp->Name)) {
- if (crp->Nulls) {
- sprintf(g->Message, "Pivot column %s cannot be nullable", Picol);
- goto err;
- } // endif Nulls
-
- Rblkp = crp->Kdata;
- *pcrp = crp->Next;
- } else if (!stricmp(Fncol, crp->Name)) {
- fncrp = crp;
- *pcrp = crp->Next;
- } else
- pcrp = &crp->Next;
-
- if (!Rblkp) {
- strcpy(g->Message, MSG(NO_DEF_PIVOTCOL));
- goto err;
- } else if (!fncrp) {
- strcpy(g->Message, MSG(NO_DEF_FNCCOL));
- goto err;
- } // endif
-
- if (Tabsrc) {
- Myc.Close();
- b = false;
-
- // Before calling sort, initialize all
- nblin = Qryp->Nblin;
-
- Index.Size = nblin * sizeof(int);
- Index.Sub = TRUE; // Should be small enough
-
- if (!PlgDBalloc(g, NULL, Index))
- return NULL;
-
- Offset.Size = (nblin + 1) * sizeof(int);
- Offset.Sub = TRUE; // Should be small enough
-
- if (!PlgDBalloc(g, NULL, Offset))
- return NULL;
-
- ndif = Qsort(g, nblin);
-
- if (ndif < 0) // error
- return NULL;
-
- } else {
- // The query was limited, we must get pivot column values
- // Returned values must be in their original character set
-// if (Myc.ExecSQL(g, "SET character_set_results=NULL", &w) == RC_FX)
-// goto err;
-
- query = (char*)PlugSubAlloc(g, NULL, 0);
- sprintf(query, "SELECT DISTINCT `%s` FROM `%s`", Picol, Tabname);
- PlugSubAlloc(g, NULL, strlen(query) + 1);
- Myc.FreeResult();
-
- // Send the source command to MySQL
- if (Myc.ExecSQL(g, query, &w) == RC_FX)
- goto err;
-
- // We must have a storage query to get pivot column values
- if (!(qrp = Myc.GetResult(g, true)))
- goto err;
-
- Myc.Close();
- b = false;
-
- // Get the column list
- crp = qrp->Colresp;
- Rblkp = crp->Kdata;
- ndif = qrp->Nblin;
- } // endif Tabsrc
-
- // Allocate the Value used to retieve column names
- if (!(valp = AllocateValue(g, Rblkp->GetType(),
- Rblkp->GetVlen(),
- Rblkp->GetPrec())))
- return NULL;
-
- // Now make the functional columns
- for (int i = 0; i < ndif; i++) {
- if (i) {
- crp = (PCOLRES)PlugSubAlloc(g, NULL, sizeof(COLRES));
- memcpy(crp, fncrp, sizeof(COLRES));
- } else
- crp = fncrp;
-
- // Get the value that will be the generated column name
- if (Tabsrc)
- valp->SetValue_pvblk(Rblkp, Pex[Pof[i]]);
- else
- valp->SetValue_pvblk(Rblkp, i);
-
- colname = valp->GetCharString(buf);
- crp->Name = PlugDup(g, colname);
- crp->Flag = 1;
-
- // Add this column
- *pcrp = crp;
- crp->Next = NULL;
- pcrp = &crp->Next;
- } // endfor i
-
- // We added ndif columns and removed 2 (picol and fncol)
- Qryp->Nbcol += (ndif - 2);
- return Qryp;
+ try {
+ // Are there columns to skip?
+ if (Skcol) {
+ uint n = strlen(Skcol);
+
+ skc = (char*)PlugSubAlloc(g, NULL, n + 2);
+ strcpy(skc, Skcol);
+ skc[n + 1] = 0;
+
+ // Replace ; by nulls in skc
+ for (p = strchr(skc, ';'); p; p = strchr(p, ';'))
+ *p++ = 0;
+
+ } else
+ skc = NULL;
+
+ if (!Tabsrc && Tabname) {
+ // Locate the query
+ query = (char*)PlugSubAlloc(g, NULL, strlen(Tabname) + 26);
+ sprintf(query, "SELECT * FROM `%s` LIMIT 1", Tabname);
+ } else if (!Tabsrc) {
+ strcpy(g->Message, MSG(SRC_TABLE_UNDEF));
+ goto err;
+ } else
+ query = (char*)Tabsrc;
+
+ // Open a MySQL connection for this table
+ if (!Myc.Open(g, Host, Database, User, Pwd, Port)) {
+ b = true;
+
+ // Returned values must be in their original character set
+ if (Myc.ExecSQL(g, "SET character_set_results=NULL", &w) == RC_FX)
+ goto err;
+ else
+ Myc.FreeResult();
+
+ } else
+ goto err;
+
+ // Send the source command to MySQL
+ if (Myc.ExecSQL(g, query, &w) == RC_FX)
+ goto err;
+
+ // We must have a storage query to get pivot column values
+ if (!(Qryp = Myc.GetResult(g, true)))
+ goto err;
+
+ if (!Fncol) {
+ for (crp = Qryp->Colresp; crp; crp = crp->Next)
+ if ((!Picol || stricmp(Picol, crp->Name)) && !SkipColumn(crp, skc))
+ Fncol = crp->Name;
+
+ if (!Fncol) {
+ strcpy(g->Message, MSG(NO_DEF_FNCCOL));
+ goto err;
+ } // endif Fncol
+
+ } // endif Fncol
+
+ if (!Picol) {
+ // Find default Picol as the last one not equal to Fncol
+ for (crp = Qryp->Colresp; crp; crp = crp->Next)
+ if (stricmp(Fncol, crp->Name) && !SkipColumn(crp, skc))
+ Picol = crp->Name;
+
+ if (!Picol) {
+ strcpy(g->Message, MSG(NO_DEF_PIVOTCOL));
+ goto err;
+ } // endif Picol
+
+ } // endif picol
+
+ // Prepare the column list
+ for (pcrp = &Qryp->Colresp; crp = *pcrp; )
+ if (SkipColumn(crp, skc)) {
+ // Ignore this column
+ *pcrp = crp->Next;
+ } else if (!stricmp(Picol, crp->Name)) {
+ if (crp->Nulls) {
+ sprintf(g->Message, "Pivot column %s cannot be nullable", Picol);
+ goto err;
+ } // endif Nulls
+
+ Rblkp = crp->Kdata;
+ *pcrp = crp->Next;
+ } else if (!stricmp(Fncol, crp->Name)) {
+ fncrp = crp;
+ *pcrp = crp->Next;
+ } else
+ pcrp = &crp->Next;
+
+ if (!Rblkp) {
+ strcpy(g->Message, MSG(NO_DEF_PIVOTCOL));
+ goto err;
+ } else if (!fncrp) {
+ strcpy(g->Message, MSG(NO_DEF_FNCCOL));
+ goto err;
+ } // endif
+
+ if (Tabsrc) {
+ Myc.Close();
+ b = false;
+
+ // Before calling sort, initialize all
+ nblin = Qryp->Nblin;
+
+ Index.Size = nblin * sizeof(int);
+ Index.Sub = TRUE; // Should be small enough
+
+ if (!PlgDBalloc(g, NULL, Index))
+ goto err;
+
+ Offset.Size = (nblin + 1) * sizeof(int);
+ Offset.Sub = TRUE; // Should be small enough
+
+ if (!PlgDBalloc(g, NULL, Offset))
+ goto err;
+
+ ndif = Qsort(g, nblin);
+
+ if (ndif < 0) // error
+ goto err;
+
+ } else {
+ // The query was limited, we must get pivot column values
+ // Returned values must be in their original character set
+ // if (Myc.ExecSQL(g, "SET character_set_results=NULL", &w) == RC_FX)
+ // goto err;
+
+ query = (char*)PlugSubAlloc(g, NULL, 0);
+ sprintf(query, "SELECT DISTINCT `%s` FROM `%s`", Picol, Tabname);
+ PlugSubAlloc(g, NULL, strlen(query) + 1);
+ Myc.FreeResult();
+
+ // Send the source command to MySQL
+ if (Myc.ExecSQL(g, query, &w) == RC_FX)
+ goto err;
+
+ // We must have a storage query to get pivot column values
+ if (!(qrp = Myc.GetResult(g, true)))
+ goto err;
+
+ Myc.Close();
+ b = false;
+
+ // Get the column list
+ crp = qrp->Colresp;
+ Rblkp = crp->Kdata;
+ ndif = qrp->Nblin;
+ } // endif Tabsrc
+
+ // Allocate the Value used to retieve column names
+ if (!(valp = AllocateValue(g, Rblkp->GetType(),
+ Rblkp->GetVlen(),
+ Rblkp->GetPrec())))
+ goto err;
+
+ // Now make the functional columns
+ for (int i = 0; i < ndif; i++) {
+ if (i) {
+ crp = (PCOLRES)PlugSubAlloc(g, NULL, sizeof(COLRES));
+ memcpy(crp, fncrp, sizeof(COLRES));
+ } else
+ crp = fncrp;
+
+ // Get the value that will be the generated column name
+ if (Tabsrc)
+ valp->SetValue_pvblk(Rblkp, Pex[Pof[i]]);
+ else
+ valp->SetValue_pvblk(Rblkp, i);
+
+ colname = valp->GetCharString(buf);
+ crp->Name = PlugDup(g, colname);
+ crp->Flag = 1;
+
+ // Add this column
+ *pcrp = crp;
+ crp->Next = NULL;
+ pcrp = &crp->Next;
+ } // endfor i
+
+ // We added ndif columns and removed 2 (picol and fncol)
+ Qryp->Nbcol += (ndif - 2);
+ return Qryp;
+ } catch (int n) {
+ if (trace)
+ htrc("Exception %d: %s\n", n, g->Message);
+ } catch (const char *msg) {
+ strcpy(g->Message, msg);
+ } // end catch
err:
if (b)
Myc.Close();
return NULL;
- } // end of MakePivotColumns
+} // end of MakePivotColumns
/***********************************************************************/
/* PIVAID: Compare routine for sorting pivot column values. */
diff --git a/storage/connect/tabpivot.h b/storage/connect/tabpivot.h
index 07d5c3e456b..6c2d53e9527 100644
--- a/storage/connect/tabpivot.h
+++ b/storage/connect/tabpivot.h
@@ -32,16 +32,16 @@ class PIVAID : public CSORT {
protected:
// Members
MYSQLC Myc; // MySQL connection class
- char *Host; // Host machine to use
- char *User; // User logon info
- char *Pwd; // Password logon info
- char *Database; // Database to be used by server
+ PCSZ Host; // Host machine to use
+ PCSZ User; // User logon info
+ PCSZ Pwd; // Password logon info
+ PCSZ Database; // Database to be used by server
PQRYRES Qryp; // Points to Query result block
- char *Tabname; // Name of source table
- char *Tabsrc; // SQL of source table
- char *Picol; // Pivot column name
- char *Fncol; // Function column name
- char *Skcol; // Skipped columns
+ PCSZ Tabname; // Name of source table
+ PCSZ Tabsrc; // SQL of source table
+ PCSZ Picol; // Pivot column name
+ PCSZ Fncol; // Function column name
+ PCSZ Skcol; // Skipped columns
PVBLK Rblkp; // The value block of the pivot column
int Port; // MySQL port number
}; // end of class PIVAID
diff --git a/storage/connect/tabsys.cpp b/storage/connect/tabsys.cpp
index 2ddd1c3c753..7f0d9881298 100644
--- a/storage/connect/tabsys.cpp
+++ b/storage/connect/tabsys.cpp
@@ -1,9 +1,9 @@
/************* TabSys C++ Program Source Code File (.CPP) **************/
/* PROGRAM NAME: TABSYS */
/* ------------- */
-/* Version 2.3 */
+/* Version 2.4 */
/* */
-/* Author Olivier BERTRAND 2004-2015 */
+/* Author Olivier BERTRAND 2004-2017 */
/* */
/* This program are the INI/CFG tables classes. */
/***********************************************************************/
@@ -355,7 +355,7 @@ void TDBINI::CloseDB(PGLOBAL)
/***********************************************************************/
/* INICOL public constructor. */
/***********************************************************************/
-INICOL::INICOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ)
+INICOL::INICOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PCSZ)
: COLBLK(cdp, tdbp, i)
{
if (cprec) {
@@ -511,12 +511,12 @@ void INICOL::WriteColumn(PGLOBAL g)
if (strlen(p) > (unsigned)Long) {
sprintf(g->Message, MSG(VALUE_TOO_LONG), p, Name, Long);
- longjmp(g->jumper[g->jump_level], 31);
- } else if (Flag == 1) {
+ throw 31;
+ } else if (Flag == 1) {
if (tdbp->Mode == MODE_UPDATE) {
strcpy(g->Message, MSG(NO_SEC_UPDATE));
- longjmp(g->jumper[g->jump_level], 31);
- } else if (*p) {
+ throw 31;
+ } else if (*p) {
tdbp->Section = p;
} else
tdbp->Section = NULL;
@@ -524,8 +524,8 @@ void INICOL::WriteColumn(PGLOBAL g)
return;
} else if (!tdbp->Section) {
strcpy(g->Message, MSG(SEC_NAME_FIRST));
- longjmp(g->jumper[g->jump_level], 31);
- } // endif's
+ throw 31;
+ } // endif's
/*********************************************************************/
/* Updating must be done only when not in checking pass. */
@@ -536,8 +536,8 @@ void INICOL::WriteColumn(PGLOBAL g)
if (!rc) {
sprintf(g->Message, "Error %d writing to %s",
GetLastError(), tdbp->Ifile);
- longjmp(g->jumper[g->jump_level], 31);
- } // endif rc
+ throw 31;
+ } // endif rc
} // endif Status
@@ -769,7 +769,7 @@ int TDBXIN::DeleteDB(PGLOBAL g, int irc)
/***********************************************************************/
/* XINCOL public constructor. */
/***********************************************************************/
-XINCOL::XINCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am)
+XINCOL::XINCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PCSZ am)
: INICOL(cdp, tdbp, cprec, i, am)
{
} // end of XINCOL constructor
@@ -837,12 +837,12 @@ void XINCOL::WriteColumn(PGLOBAL g)
if (strlen(p) > (unsigned)Long) {
sprintf(g->Message, MSG(VALUE_TOO_LONG), p, Name, Long);
- longjmp(g->jumper[g->jump_level], 31);
- } else if (Flag == 1) {
+ throw 31;
+ } else if (Flag == 1) {
if (tdbp->Mode == MODE_UPDATE) {
strcpy(g->Message, MSG(NO_SEC_UPDATE));
- longjmp(g->jumper[g->jump_level], 31);
- } else if (*p) {
+ throw 31;
+ } else if (*p) {
tdbp->Section = p;
} else
tdbp->Section = NULL;
@@ -851,8 +851,8 @@ void XINCOL::WriteColumn(PGLOBAL g)
} else if (Flag == 2) {
if (tdbp->Mode == MODE_UPDATE) {
strcpy(g->Message, MSG(NO_KEY_UPDATE));
- longjmp(g->jumper[g->jump_level], 31);
- } else if (*p) {
+ throw 31;
+ } else if (*p) {
tdbp->Keycur = p;
} else
tdbp->Keycur = NULL;
@@ -860,8 +860,8 @@ void XINCOL::WriteColumn(PGLOBAL g)
return;
} else if (!tdbp->Section || !tdbp->Keycur) {
strcpy(g->Message, MSG(SEC_KEY_FIRST));
- longjmp(g->jumper[g->jump_level], 31);
- } // endif's
+ throw 31;
+ } // endif's
/*********************************************************************/
/* Updating must be done only when not in checking pass. */
@@ -872,8 +872,8 @@ void XINCOL::WriteColumn(PGLOBAL g)
if (!rc) {
sprintf(g->Message, "Error %d writing to %s",
GetLastError(), tdbp->Ifile);
- longjmp(g->jumper[g->jump_level], 31);
- } // endif rc
+ throw 31;
+ } // endif rc
} // endif Status
diff --git a/storage/connect/tabsys.h b/storage/connect/tabsys.h
index ff1b8335690..44b5a137a70 100644
--- a/storage/connect/tabsys.h
+++ b/storage/connect/tabsys.h
@@ -61,7 +61,7 @@ class TDBINI : public TDBASE {
virtual int GetRecpos(void) {return N;}
virtual int GetProgCur(void) {return N;}
//virtual int GetAffectedRows(void) {return 0;}
- virtual PSZ GetFile(PGLOBAL g) {return Ifile;}
+ virtual PCSZ GetFile(PGLOBAL g) {return Ifile;}
virtual void SetFile(PGLOBAL g, PSZ fn) {Ifile = fn;}
virtual void ResetDB(void) {Seclist = Section = NULL; N = 0;}
virtual void ResetSize(void) {MaxSize = -1; Seclist = NULL;}
@@ -93,7 +93,7 @@ class TDBINI : public TDBASE {
class INICOL : public COLBLK {
public:
// Constructors
- INICOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am = "INI");
+ INICOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PCSZ am = "INI");
INICOL(INICOL *colp, PTDB tdbp); // Constructor used in copy process
// Implementation
@@ -165,7 +165,7 @@ class TDBXIN : public TDBINI {
class XINCOL : public INICOL {
public:
// Constructors
- XINCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am = "INI");
+ XINCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PCSZ am = "INI");
XINCOL(XINCOL *colp, PTDB tdbp); // Constructor used in copy process
// Implementation
diff --git a/storage/connect/tabutil.cpp b/storage/connect/tabutil.cpp
index 762c61bd1a1..574cef28ea3 100644
--- a/storage/connect/tabutil.cpp
+++ b/storage/connect/tabutil.cpp
@@ -119,7 +119,8 @@ PQRYRES TabColumns(PGLOBAL g, THD *thd, const char *db,
FLD_LENGTH, FLD_SCALE, FLD_RADIX, FLD_NULL,
FLD_REM, FLD_NO, FLD_CHARSET};
unsigned int length[] = {0, 4, 16, 4, 4, 4, 4, 4, 0, 32, 32};
- char *pn, *tn, *fld, *colname, *chset, *fmt, v;
+ PCSZ fmt;
+ char *pn, *tn, *fld, *colname, *chset, v;
int i, n, ncol = sizeof(buftyp) / sizeof(int);
int prec, len, type, scale;
int zconv = GetConvSize();
@@ -227,7 +228,7 @@ PQRYRES TabColumns(PGLOBAL g, THD *thd, const char *db,
fmt = MyDateFmt(fp->type());
prec = len = strlen(fmt);
} else {
- fmt = (char*)fp->option_struct->dateformat;
+ fmt = (PCSZ)fp->option_struct->dateformat;
prec = len = fp->field_length;
} // endif mysql
@@ -314,7 +315,7 @@ bool PRXDEF::DefineAM(PGLOBAL g, LPCSTR, int)
strcpy(g->Message, "Missing object table definition");
return true;
} else
- tab = "Noname";
+ tab = PlugDup(g, "Noname");
} else
// Analyze the table name, it may have the format: [dbname.]tabname
@@ -626,7 +627,7 @@ void TDBPRX::RemoveNext(PTABLE tp)
/***********************************************************************/
/* PRXCOL public constructor. */
/***********************************************************************/
-PRXCOL::PRXCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am)
+PRXCOL::PRXCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PCSZ am)
: COLBLK(cdp, tdbp, i)
{
if (cprec) {
@@ -741,7 +742,14 @@ void PRXCOL::ReadColumn(PGLOBAL g)
if (Nullable)
Value->SetNull(Value->IsNull());
- } // endif Colp
+ } else {
+ Value->Reset();
+
+ // Set null when applicable
+ if (Nullable)
+ Value->SetNull(true);
+
+ } // endif Colp
} // end of ReadColumn
diff --git a/storage/connect/tabutil.h b/storage/connect/tabutil.h
index 8e56aecff86..62678508ca1 100644
--- a/storage/connect/tabutil.h
+++ b/storage/connect/tabutil.h
@@ -71,7 +71,7 @@ class DllExport TDBPRX : public TDBASE {
virtual int GetRecpos(void) {return Tdbp->GetRecpos();}
virtual void ResetDB(void) {Tdbp->ResetDB();}
virtual int RowNumber(PGLOBAL g, bool b = FALSE);
- virtual PSZ GetServer(void) {return (Tdbp) ? Tdbp->GetServer() : (PSZ)"?";}
+ virtual PCSZ GetServer(void) {return (Tdbp) ? Tdbp->GetServer() : (PSZ)"?";}
// Database routines
virtual PCOL MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n);
@@ -101,7 +101,7 @@ class DllExport PRXCOL : public COLBLK {
friend class TDBOCCUR;
public:
// Constructors
- PRXCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am = "PRX");
+ PRXCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PCSZ am = "PRX");
PRXCOL(PRXCOL *colp, PTDB tdbp); // Constructor used in copy process
// Implementation
diff --git a/storage/connect/tabvct.cpp b/storage/connect/tabvct.cpp
index 282fb55a43c..533986e44da 100644
--- a/storage/connect/tabvct.cpp
+++ b/storage/connect/tabvct.cpp
@@ -1,11 +1,11 @@
/************* TabVct C++ Program Source Code File (.CPP) **************/
/* PROGRAM NAME: TABVCT */
/* ------------- */
-/* Version 3.8 */
+/* Version 3.9 */
/* */
/* COPYRIGHT: */
/* ---------- */
-/* (C) Copyright to the author Olivier BERTRAND 1999-2015 */
+/* (C) Copyright to the author Olivier BERTRAND 1999-2017 */
/* */
/* WHAT THIS PROGRAM DOES: */
/* ----------------------- */
@@ -174,7 +174,7 @@ bool VCTDEF::Erase(char *filename)
/***********************************************************************/
int VCTDEF::MakeFnPattern(char *fpat)
{
- char pat[8];
+ char pat[16];
#if defined(__WIN__)
char drive[_MAX_DRIVE];
#else
@@ -490,15 +490,15 @@ void VCTCOL::ReadBlock(PGLOBAL g)
#if defined(_DEBUG)
if (!Blk) {
strcpy(g->Message, MSG(TO_BLK_IS_NULL));
- longjmp(g->jumper[g->jump_level], 58);
- } // endif
+ throw 58;
+ } // endif
#endif
/*********************************************************************/
/* Read column block according to used access method. */
/*********************************************************************/
if (txfp->ReadBlock(g, this))
- longjmp(g->jumper[g->jump_level], 6);
+ throw 6;
ColBlk = txfp->CurBlk;
ColPos = -1; // Any invalid position
@@ -518,15 +518,15 @@ void VCTCOL::WriteBlock(PGLOBAL g)
#if defined(_DEBUG)
if (!Blk) {
strcpy(g->Message, MSG(BLK_IS_NULL));
- longjmp(g->jumper[g->jump_level], 56);
- } // endif
+ throw 56;
+ } // endif
#endif
/*******************************************************************/
/* Write column block according to used access method. */
/*******************************************************************/
if (txfp->WriteBlock(g, this))
- longjmp(g->jumper[g->jump_level], 6);
+ throw 6;
Modif = 0;
} // endif Modif
diff --git a/storage/connect/tabvir.cpp b/storage/connect/tabvir.cpp
index 155c71fe268..84b3dd1787b 100644
--- a/storage/connect/tabvir.cpp
+++ b/storage/connect/tabvir.cpp
@@ -1,6 +1,6 @@
/************* tdbvir C++ Program Source Code File (.CPP) **************/
-/* PROGRAM NAME: tdbvir.cpp Version 1.1 */
-/* (C) Copyright to the author Olivier BERTRAND 2014 */
+/* PROGRAM NAME: tdbvir.cpp Version 1.2 */
+/* (C) Copyright to the author Olivier BERTRAND 2014-2017 */
/* This program are the VIR classes DB execution routines. */
/***********************************************************************/
@@ -269,7 +269,7 @@ int TDBVIR::DeleteDB(PGLOBAL g, int)
/***********************************************************************/
/* VIRCOL public constructor. */
/***********************************************************************/
-VIRCOL::VIRCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ)
+VIRCOL::VIRCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PCSZ)
: COLBLK(cdp, tdbp, i)
{
if (cprec) {
@@ -289,8 +289,8 @@ void VIRCOL::ReadColumn(PGLOBAL g)
{
// This should never be called
sprintf(g->Message, "ReadColumn: Column %s is not virtual", Name);
- longjmp(g->jumper[g->jump_level], TYPE_COLBLK);
- } // end of ReadColumn
+ throw TYPE_COLBLK;
+} // end of ReadColumn
/* ---------------------------TDBVICL class -------------------------- */
diff --git a/storage/connect/tabvir.h b/storage/connect/tabvir.h
index a53aceaeceb..e7313bbae67 100644
--- a/storage/connect/tabvir.h
+++ b/storage/connect/tabvir.h
@@ -76,7 +76,7 @@ class VIRCOL : public COLBLK {
friend class TDBVIR;
public:
// Constructors
- VIRCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am = "VIRTUAL");
+ VIRCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PCSZ am = "VIRTUAL");
// Implementation
virtual int GetAmType(void) {return TYPE_AM_VIR;}
diff --git a/storage/connect/tabwmi.cpp b/storage/connect/tabwmi.cpp
index 4871a1d66dc..335ffce5d7f 100644
--- a/storage/connect/tabwmi.cpp
+++ b/storage/connect/tabwmi.cpp
@@ -27,7 +27,7 @@
/***********************************************************************/
/* Initialize WMI operations. */
/***********************************************************************/
-PWMIUT InitWMI(PGLOBAL g, char *nsp, char *classname)
+PWMIUT InitWMI(PGLOBAL g, PCSZ nsp, PCSZ classname)
{
IWbemLocator *loc;
char *p;
@@ -132,7 +132,7 @@ PWMIUT InitWMI(PGLOBAL g, char *nsp, char *classname)
/* WMIColumns: constructs the result blocks containing the description */
/* of all the columns of a WMI table of a specified class. */
/***********************************************************************/
-PQRYRES WMIColumns(PGLOBAL g, char *nsp, char *cls, bool info)
+PQRYRES WMIColumns(PGLOBAL g, PCSZ nsp, PCSZ cls, bool info)
{
static int buftyp[] = {TYPE_STRING, TYPE_SHORT, TYPE_STRING,
TYPE_INT, TYPE_INT, TYPE_SHORT};
diff --git a/storage/connect/tabwmi.h b/storage/connect/tabwmi.h
index 6abb85453a1..7a18453374e 100644
--- a/storage/connect/tabwmi.h
+++ b/storage/connect/tabwmi.h
@@ -27,7 +27,7 @@ typedef struct _WMIutil {
/***********************************************************************/
/* Functions used externally. */
/***********************************************************************/
-PQRYRES WMIColumns(PGLOBAL g, char *nsp, char *cls, bool info);
+PQRYRES WMIColumns(PGLOBAL g, PCSZ nsp, PCSZ cls, bool info);
/* -------------------------- WMI classes ---------------------------- */
diff --git a/storage/connect/tabxml.cpp b/storage/connect/tabxml.cpp
index 52cf3d3812f..80d4395058e 100644
--- a/storage/connect/tabxml.cpp
+++ b/storage/connect/tabxml.cpp
@@ -1,9 +1,9 @@
/************* Tabxml C++ Program Source Code File (.CPP) **************/
/* PROGRAM NAME: TABXML */
/* ------------- */
-/* Version 2.9 */
+/* Version 3.0 */
/* */
-/* Author Olivier BERTRAND 2007 - 2016 */
+/* Author Olivier BERTRAND 2007 - 2017 */
/* */
/* This program are the XML tables classes using MS-DOM or libxml2. */
/***********************************************************************/
@@ -118,10 +118,11 @@ PQRYRES XMLColumns(PGLOBAL g, char *db, char *tab, PTOS topt, bool info)
static XFLD fldtyp[] = {FLD_NAME, FLD_TYPE, FLD_TYPENAME, FLD_PREC,
FLD_LENGTH, FLD_SCALE, FLD_NULL, FLD_FORMAT};
static unsigned int length[] = {0, 6, 8, 10, 10, 6, 6, 0};
- char *fn, *op, colname[65], fmt[129], buf[512];
+ char colname[65], fmt[129], buf[512];
int i, j, lvl, n = 0;
int ncol = sizeof(buftyp) / sizeof(int);
bool ok = true;
+ PCSZ fn, op;
PXCL xcol, xcp, fxcp = NULL, pxcp = NULL;
PLVL *lvlp, vp;
PXNODE node = NULL;
@@ -157,7 +158,10 @@ PQRYRES XMLColumns(PGLOBAL g, char *db, char *tab, PTOS topt, bool info)
tdp = new(g) XMLDEF;
tdp->Fn = fn;
- tdp->Database = SetPath(g, db);
+
+ if (!(tdp->Database = SetPath(g, db)))
+ return NULL;
+
tdp->Tabname = tab;
tdp->Zipped = GetBooleanTableOption(g, topt, "Zipped", false);
tdp->Entry = GetStringTableOption(g, topt, "Entry", NULL);
@@ -359,7 +363,7 @@ PQRYRES XMLColumns(PGLOBAL g, char *db, char *tab, PTOS topt, bool info)
skipit:
if (trace)
- htrc("CSVColumns: n=%d len=%d\n", n, length[0]);
+ htrc("XMLColumns: n=%d len=%d\n", n, length[0]);
/*********************************************************************/
/* Allocate the structures used to refer to the result set. */
@@ -448,7 +452,8 @@ XMLDEF::XMLDEF(void)
/***********************************************************************/
bool XMLDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
{
- char *defrow, *defcol, buf[10];
+ PCSZ defrow, defcol;
+ char buf[10];
Fn = GetStringCatInfo(g, "Filename", NULL);
Encoding = GetStringCatInfo(g, "Encoding", "UTF-8");
@@ -1314,8 +1319,8 @@ void TDBXML::CloseDB(PGLOBAL g)
Docp->CloseDoc(g, To_Xb);
// This causes a crash in Diagnostics_area::set_error_status
-// longjmp(g->jumper[g->jump_level], TYPE_AM_XML);
- } // endif DumpDoc
+// throw TYPE_AM_XML;
+ } // endif DumpDoc
} // endif Changed
@@ -1357,8 +1362,8 @@ void TDBXML::CloseDB(PGLOBAL g)
/***********************************************************************/
/* XMLCOL public constructor. */
/***********************************************************************/
-XMLCOL::XMLCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am)
- : COLBLK(cdp, tdbp, i)
+XMLCOL::XMLCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PCSZ am)
+ : COLBLK(cdp, tdbp, i)
{
if (cprec) {
Next = cprec->GetNext();
@@ -1637,8 +1642,8 @@ void XMLCOL::ReadColumn(PGLOBAL g)
if (ValNode->GetType() != XML_ELEMENT_NODE &&
ValNode->GetType() != XML_ATTRIBUTE_NODE) {
sprintf(g->Message, MSG(BAD_VALNODE), ValNode->GetType(), Name);
- longjmp(g->jumper[g->jump_level], TYPE_AM_XML);
- } // endif type
+ throw TYPE_AM_XML;
+ } // endif type
// Get the Xname value from the XML file
switch (ValNode->GetContent(g, Valbuf, Long + 1)) {
@@ -1648,8 +1653,8 @@ void XMLCOL::ReadColumn(PGLOBAL g)
PushWarning(g, Tdbp);
break;
default:
- longjmp(g->jumper[g->jump_level], TYPE_AM_XML);
- } // endswitch
+ throw TYPE_AM_XML;
+ } // endswitch
Value->SetValue_psz(Valbuf);
} else {
@@ -1699,7 +1704,7 @@ void XMLCOL::WriteColumn(PGLOBAL g)
/* For columns having an Xpath, the Clist must be updated. */
/*********************************************************************/
if (Tdbp->CheckRow(g, Nod || Tdbp->Colname))
- longjmp(g->jumper[g->jump_level], TYPE_AM_XML);
+ throw TYPE_AM_XML;
/*********************************************************************/
/* Null values are represented by no node. */
@@ -1771,8 +1776,8 @@ void XMLCOL::WriteColumn(PGLOBAL g)
if (ColNode == NULL) {
strcpy(g->Message, MSG(COL_ALLOC_ERR));
- longjmp(g->jumper[g->jump_level], TYPE_AM_XML);
- } // endif ColNode
+ throw TYPE_AM_XML;
+ } // endif ColNode
} // endif ColNode
@@ -1800,8 +1805,8 @@ void XMLCOL::WriteColumn(PGLOBAL g)
if (strlen(p) > (unsigned)Long) {
sprintf(g->Message, MSG(VALUE_TOO_LONG), p, Name, Long);
- longjmp(g->jumper[g->jump_level], TYPE_AM_XML);
- } else
+ throw TYPE_AM_XML;
+ } else
strcpy(Valbuf, p);
/*********************************************************************/
@@ -1850,8 +1855,8 @@ void XMULCOL::ReadColumn(PGLOBAL g)
if (ValNode->GetType() != XML_ELEMENT_NODE &&
ValNode->GetType() != XML_ATTRIBUTE_NODE) {
sprintf(g->Message, MSG(BAD_VALNODE), ValNode->GetType(), Name);
- longjmp(g->jumper[g->jump_level], TYPE_AM_XML);
- } // endif type
+ throw TYPE_AM_XML;
+ } // endif type
// Get the Xname value from the XML file
switch (ValNode->GetContent(g, p, (b ? Long : len))) {
@@ -1936,7 +1941,7 @@ void XMULCOL::WriteColumn(PGLOBAL g)
/* For columns having an Xpath, the Clist must be updated. */
/*********************************************************************/
if (Tdbp->CheckRow(g, Nod))
- longjmp(g->jumper[g->jump_level], TYPE_AM_XML);
+ throw TYPE_AM_XML;
/*********************************************************************/
/* Find the column and value nodes to update or insert. */
@@ -1985,8 +1990,8 @@ void XMULCOL::WriteColumn(PGLOBAL g)
if (len > 1 && !Tdbp->Xpand) {
sprintf(g->Message, MSG(BAD_VAL_UPDATE), Name);
- longjmp(g->jumper[g->jump_level], TYPE_AM_XML);
- } else
+ throw TYPE_AM_XML;
+ } else
ValNode = Nlx->GetItem(g, Tdbp->Nsub, Vxnp);
} else // Inod != Nod
@@ -2027,8 +2032,8 @@ void XMULCOL::WriteColumn(PGLOBAL g)
if (ColNode == NULL) {
strcpy(g->Message, MSG(COL_ALLOC_ERR));
- longjmp(g->jumper[g->jump_level], TYPE_AM_XML);
- } // endif ColNode
+ throw TYPE_AM_XML;
+ } // endif ColNode
} // endif ColNode
@@ -2056,8 +2061,8 @@ void XMULCOL::WriteColumn(PGLOBAL g)
if (strlen(p) > (unsigned)Long) {
sprintf(g->Message, MSG(VALUE_TOO_LONG), p, Name, Long);
- longjmp(g->jumper[g->jump_level], TYPE_AM_XML);
- } else
+ throw TYPE_AM_XML;
+ } else
strcpy(Valbuf, p);
/*********************************************************************/
@@ -2088,8 +2093,8 @@ void XPOSCOL::ReadColumn(PGLOBAL g)
if (Tdbp->Clist == NULL) {
strcpy(g->Message, MSG(MIS_TAG_LIST));
- longjmp(g->jumper[g->jump_level], TYPE_AM_XML);
- } // endif Clist
+ throw TYPE_AM_XML;
+ } // endif Clist
if ((ValNode = Tdbp->Clist->GetItem(g, Rank, Vxnp))) {
// Get the column value from the XML file
@@ -2100,8 +2105,8 @@ void XPOSCOL::ReadColumn(PGLOBAL g)
PushWarning(g, Tdbp);
break;
default:
- longjmp(g->jumper[g->jump_level], TYPE_AM_XML);
- } // endswitch
+ throw TYPE_AM_XML;
+ } // endswitch
Value->SetValue_psz(Valbuf);
} else {
@@ -2151,15 +2156,15 @@ void XPOSCOL::WriteColumn(PGLOBAL g)
/* For all columns the Clist must be updated. */
/*********************************************************************/
if (Tdbp->CheckRow(g, true))
- longjmp(g->jumper[g->jump_level], TYPE_AM_XML);
+ throw TYPE_AM_XML;
/*********************************************************************/
/* Find the column and value nodes to update or insert. */
/*********************************************************************/
if (Tdbp->Clist == NULL) {
strcpy(g->Message, MSG(MIS_TAG_LIST));
- longjmp(g->jumper[g->jump_level], TYPE_AM_XML);
- } // endif Clist
+ throw TYPE_AM_XML;
+ } // endif Clist
n = Tdbp->Clist->GetLength();
k = Rank;
@@ -2183,8 +2188,8 @@ void XPOSCOL::WriteColumn(PGLOBAL g)
if (strlen(p) > (unsigned)Long) {
sprintf(g->Message, MSG(VALUE_TOO_LONG), p, Name, Long);
- longjmp(g->jumper[g->jump_level], TYPE_AM_XML);
- } else
+ throw TYPE_AM_XML;
+ } else
strcpy(Valbuf, p);
/*********************************************************************/
diff --git a/storage/connect/tabxml.h b/storage/connect/tabxml.h
index 65b353072cb..6b18eb645f0 100644
--- a/storage/connect/tabxml.h
+++ b/storage/connect/tabxml.h
@@ -31,7 +31,7 @@ class DllExport XMLDEF : public TABDEF { /* Logical table description */
protected:
// Members
- char *Fn; /* Path/Name of corresponding file */
+ PCSZ Fn; /* Path/Name of corresponding file */
char *Encoding; /* New XML table file encoding */
char *Tabname; /* Name of Table node */
char *Rowname; /* Name of first level nodes */
@@ -42,7 +42,7 @@ class DllExport XMLDEF : public TABDEF { /* Logical table description */
char *DefNs; /* Dummy name of default namespace */
char *Attrib; /* Table node attributes */
char *Hdattr; /* Header node attributes */
- char *Entry; /* Zip entry name or pattern */
+ PCSZ Entry; /* Zip entry name or pattern */
int Coltype; /* Default column type */
int Limit; /* Limit of multiple values */
int Header; /* n first rows are header rows */
@@ -74,7 +74,7 @@ class DllExport TDBXML : public TDBASE {
virtual PTDB Clone(PTABS t);
virtual int GetRecpos(void);
virtual int GetProgCur(void) {return N;}
- virtual PSZ GetFile(PGLOBAL g) {return Xfile;}
+ virtual PCSZ GetFile(PGLOBAL g) {return Xfile;}
virtual void SetFile(PGLOBAL g, PSZ fn) {Xfile = fn;}
virtual void ResetDB(void) {N = 0;}
virtual void ResetSize(void) {MaxSize = -1;}
@@ -127,7 +127,7 @@ class DllExport TDBXML : public TDBASE {
bool Void; // True if the file does not exist
bool Zipped; // True if Zipped XML file(s)
bool Mulentries; // True if multiple entries in zip file
- char *Xfile; // The XML file
+ PCSZ Xfile; // The XML file
char *Enc; // New XML table file encoding
char *Tabname; // Name of Table node
char *Rowname; // Name of first level nodes
@@ -138,7 +138,7 @@ class DllExport TDBXML : public TDBASE {
char *DefNs; // Dummy name of default namespace
char *Attrib; // Table node attribut(s)
char *Hdattr; // Header node attribut(s)
- char *Entry; // Zip entry name or pattern
+ PCSZ Entry; // Zip entry name or pattern
int Coltype; // Default column type
int Limit; // Limit of multiple values
int Header; // n first rows are header rows
@@ -155,7 +155,7 @@ class DllExport TDBXML : public TDBASE {
class XMLCOL : public COLBLK {
public:
// Constructors
- XMLCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am = "XML");
+ XMLCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PCSZ am = "XML");
XMLCOL(XMLCOL *colp, PTDB tdbp); // Constructor used in copy process
// Implementation
diff --git a/storage/connect/tabzip.cpp b/storage/connect/tabzip.cpp
index b91059a3843..c026744dba8 100644
--- a/storage/connect/tabzip.cpp
+++ b/storage/connect/tabzip.cpp
@@ -195,8 +195,8 @@ void TDBZIP::CloseDB(PGLOBAL g)
/***********************************************************************/
/* ZIPCOL public constructor. */
/***********************************************************************/
-ZIPCOL::ZIPCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am)
- : COLBLK(cdp, tdbp, i)
+ZIPCOL::ZIPCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PCSZ am)
+ : COLBLK(cdp, tdbp, i)
{
if (cprec) {
Next = cprec->GetNext();
diff --git a/storage/connect/tabzip.h b/storage/connect/tabzip.h
index dcec3475371..32b15281f81 100644
--- a/storage/connect/tabzip.h
+++ b/storage/connect/tabzip.h
@@ -34,7 +34,7 @@ public:
protected:
// Members
- PSZ target; // The inside file to query
+ PCSZ target; // The inside file to query
}; // end of ZIPDEF
/***********************************************************************/
@@ -68,7 +68,7 @@ protected:
// Members
unzFile zipfile; // The ZIP container file
- PSZ zfn; // The ZIP file name
+ PCSZ zfn; // The ZIP file name
//PSZ target;
unz_file_info64 finfo; // The current file info
char fn[FILENAME_MAX]; // The current file name
@@ -82,7 +82,7 @@ class DllExport ZIPCOL : public COLBLK {
friend class TDBZIP;
public:
// Constructors
- ZIPCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am = "ZIP");
+ ZIPCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PCSZ am = "ZIP");
// Implementation
virtual int GetAmType(void) { return TYPE_AM_ZIP; }
diff --git a/storage/connect/valblk.cpp b/storage/connect/valblk.cpp
index 5fefcba5856..5b98f3eb425 100644
--- a/storage/connect/valblk.cpp
+++ b/storage/connect/valblk.cpp
@@ -1,7 +1,7 @@
/************ Valblk C++ Functions Source Code File (.CPP) *************/
-/* Name: VALBLK.CPP Version 2.1 */
+/* Name: VALBLK.CPP Version 2.3 */
/* */
-/* (C) Copyright to the author Olivier BERTRAND 2005-2015 */
+/* (C) Copyright to the author Olivier BERTRAND 2005-2017 */
/* */
/* This file contains the VALBLK and derived classes functions. */
/* Second family is VALBLK, representing simple suballocated arrays */
@@ -138,14 +138,14 @@ PSZ VALBLK::GetCharValue(int)
assert(g);
sprintf(g->Message, MSG(NO_CHAR_FROM), Type);
- longjmp(g->jumper[g->jump_level], Type);
- return NULL;
+ throw Type;
+ return NULL;
} // end of GetCharValue
/***********************************************************************/
/* Set format so formatted dates can be converted on input. */
/***********************************************************************/
-bool VALBLK::SetFormat(PGLOBAL g, PSZ, int, int)
+bool VALBLK::SetFormat(PGLOBAL g, PCSZ, int, int)
{
sprintf(g->Message, MSG(NO_DATE_FMT), Type);
return true;
@@ -206,8 +206,8 @@ void VALBLK::ChkIndx(int n)
if (n < 0 || n >= Nval) {
PGLOBAL& g = Global;
strcpy(g->Message, MSG(BAD_VALBLK_INDX));
- longjmp(g->jumper[g->jump_level], Type);
- } // endif n
+ throw Type;
+ } // endif n
} // end of ChkIndx
@@ -216,8 +216,8 @@ void VALBLK::ChkTyp(PVAL v)
if (Check && (Type != v->GetType() || Unsigned != v->IsUnsigned())) {
PGLOBAL& g = Global;
strcpy(g->Message, MSG(VALTYPE_NOMATCH));
- longjmp(g->jumper[g->jump_level], Type);
- } // endif Type
+ throw Type;
+ } // endif Type
} // end of ChkTyp
@@ -226,8 +226,8 @@ void VALBLK::ChkTyp(PVBLK vb)
if (Check && (Type != vb->GetType() || Unsigned != vb->IsUnsigned())) {
PGLOBAL& g = Global;
strcpy(g->Message, MSG(VALTYPE_NOMATCH));
- longjmp(g->jumper[g->jump_level], Type);
- } // endif Type
+ throw Type;
+ } // endif Type
} // end of ChkTyp
@@ -335,15 +335,15 @@ uchar TYPBLK<uchar>::GetTypedValue(PVAL valp)
/* Set one value in a block from a zero terminated string. */
/***********************************************************************/
template <class TYPE>
-void TYPBLK<TYPE>::SetValue(PSZ p, int n)
+void TYPBLK<TYPE>::SetValue(PCSZ p, int n)
{
ChkIndx(n);
if (Check) {
PGLOBAL& g = Global;
strcpy(g->Message, MSG(BAD_SET_STRING));
- longjmp(g->jumper[g->jump_level], Type);
- } // endif Check
+ throw Type;
+ } // endif Check
bool minus;
ulonglong maxval = MaxVal();
@@ -385,15 +385,15 @@ template <>
ulonglong TYPBLK<ulonglong>::MaxVal(void) {return ULONGLONG_MAX;}
template <>
-void TYPBLK<double>::SetValue(PSZ p, int n)
+void TYPBLK<double>::SetValue(PCSZ p, int n)
{
ChkIndx(n);
if (Check) {
PGLOBAL& g = Global;
strcpy(g->Message, MSG(BAD_SET_STRING));
- longjmp(g->jumper[g->jump_level], Type);
- } // endif Check
+ throw Type;
+ } // endif Check
Typp[n] = atof(p);
SetNull(n, false);
@@ -403,7 +403,7 @@ void TYPBLK<double>::SetValue(PSZ p, int n)
/* Set one value in a block from an array of characters. */
/***********************************************************************/
template <class TYPE>
-void TYPBLK<TYPE>::SetValue(char *sp, uint len, int n)
+void TYPBLK<TYPE>::SetValue(PCSZ sp, uint len, int n)
{
PGLOBAL& g = Global;
PSZ spz = (PSZ)PlugSubAlloc(g, NULL, 0); // Temporary
@@ -778,7 +778,7 @@ void CHRBLK::SetValue(PVAL valp, int n)
/***********************************************************************/
/* Set one value in a block from a zero terminated string. */
/***********************************************************************/
-void CHRBLK::SetValue(PSZ sp, int n)
+void CHRBLK::SetValue(PCSZ sp, int n)
{
uint len = (sp) ? strlen(sp) : 0;
SetValue(sp, len, n);
@@ -787,7 +787,7 @@ void CHRBLK::SetValue(PSZ sp, int n)
/***********************************************************************/
/* Set one value in a block from an array of characters. */
/***********************************************************************/
-void CHRBLK::SetValue(char *sp, uint len, int n)
+void CHRBLK::SetValue(const char *sp, uint len, int n)
{
char *p = Chrp + n * Long;
@@ -795,8 +795,8 @@ void CHRBLK::SetValue(char *sp, uint len, int n)
if (Check && (signed)len > Long) {
PGLOBAL& g = Global;
strcpy(g->Message, MSG(SET_STR_TRUNC));
- longjmp(g->jumper[g->jump_level], Type);
- } // endif Check
+ throw Type;
+ } // endif Check
#endif // _DEBUG
if (sp)
@@ -823,8 +823,8 @@ void CHRBLK::SetValue(PVBLK pv, int n1, int n2)
if (Type != pv->GetType() || Long != ((CHRBLK*)pv)->Long) {
PGLOBAL& g = Global;
strcpy(g->Message, MSG(BLKTYPLEN_MISM));
- longjmp(g->jumper[g->jump_level], Type);
- } // endif Type
+ throw Type;
+ } // endif Type
if (!(b = pv->IsNull(n2)))
memcpy(Chrp + n1 * Long, ((CHRBLK*)pv)->Chrp + n2 * Long, Long);
@@ -874,8 +874,8 @@ void CHRBLK::SetValues(PVBLK pv, int k, int n)
if (Type != pv->GetType() || Long != ((CHRBLK*)pv)->Long) {
PGLOBAL& g = Global;
strcpy(g->Message, MSG(BLKTYPLEN_MISM));
- longjmp(g->jumper[g->jump_level], Type);
- } // endif Type
+ throw Type;
+ } // endif Type
#endif // _DEBUG
char *p = ((CHRBLK*)pv)->Chrp;
@@ -1152,7 +1152,7 @@ void STRBLK::SetValue(PVAL valp, int n)
/***********************************************************************/
/* Set one value in a block from a zero terminated string. */
/***********************************************************************/
-void STRBLK::SetValue(PSZ p, int n)
+void STRBLK::SetValue(PCSZ p, int n)
{
if (p) {
if (!Sorted || !n || !Strp[n-1] || strcmp(p, Strp[n-1]))
@@ -1168,7 +1168,7 @@ void STRBLK::SetValue(PSZ p, int n)
/***********************************************************************/
/* Set one value in a block from an array of characters. */
/***********************************************************************/
-void STRBLK::SetValue(char *sp, uint len, int n)
+void STRBLK::SetValue(const char *sp, uint len, int n)
{
PSZ p;
@@ -1316,7 +1316,7 @@ DATBLK::DATBLK(void *mp, int nval) : TYPBLK<int>(mp, nval, TYPE_INT)
/***********************************************************************/
/* Set format so formatted dates can be converted on input. */
/***********************************************************************/
-bool DATBLK::SetFormat(PGLOBAL g, PSZ fmt, int len, int year)
+bool DATBLK::SetFormat(PGLOBAL g, PCSZ fmt, int len, int year)
{
if (!(Dvalp = AllocateValue(g, TYPE_DATE, len, year, false, fmt)))
return true;
@@ -1343,7 +1343,7 @@ char *DATBLK::GetCharString(char *p, int n)
/***********************************************************************/
/* Set one value in a block from a char string. */
/***********************************************************************/
-void DATBLK::SetValue(PSZ p, int n)
+void DATBLK::SetValue(PCSZ p, int n)
{
if (Dvalp) {
// Decode the string according to format
diff --git a/storage/connect/valblk.h b/storage/connect/valblk.h
index c3cad79b234..38a73424985 100644
--- a/storage/connect/valblk.h
+++ b/storage/connect/valblk.h
@@ -91,7 +91,7 @@ class VALBLK : public BLOCK {
virtual char *GetCharString(char *p, int n) = 0;
virtual void ReAlloc(void *mp, int n) {Blkp = mp; Nval = n;}
virtual void Reset(int n) = 0;
- virtual bool SetFormat(PGLOBAL g, PSZ fmt, int len, int year = 0);
+ virtual bool SetFormat(PGLOBAL g, PCSZ fmt, int len, int year = 0);
virtual void SetPrec(int p) {}
virtual bool IsCi(void) {return false;}
@@ -105,8 +105,8 @@ class VALBLK : public BLOCK {
virtual void SetValue(double, int) {assert(false);}
virtual void SetValue(char, int) {assert(false);}
virtual void SetValue(uchar, int) {assert(false);}
- virtual void SetValue(PSZ, int) {assert(false);}
- virtual void SetValue(char *, uint, int) {assert(false);}
+ virtual void SetValue(PCSZ, int) {assert(false);}
+ virtual void SetValue(const char *, uint, int) {assert(false);}
virtual void SetValue(PVAL valp, int n) = 0;
virtual void SetValue(PVBLK pv, int n1, int n2) = 0;
virtual void SetMin(PVAL valp, int n) = 0;
@@ -165,8 +165,8 @@ class TYPBLK : public VALBLK {
// Methods
using VALBLK::SetValue;
- virtual void SetValue(PSZ sp, int n);
- virtual void SetValue(char *sp, uint len, int n);
+ virtual void SetValue(PCSZ sp, int n);
+ virtual void SetValue(const char *sp, uint len, int n);
virtual void SetValue(short sval, int n)
{Typp[n] = (TYPE)sval; SetNull(n, false);}
virtual void SetValue(ushort sval, int n)
@@ -236,8 +236,8 @@ class CHRBLK : public VALBLK {
// Methods
using VALBLK::SetValue;
- virtual void SetValue(PSZ sp, int n);
- virtual void SetValue(char *sp, uint len, int n);
+ virtual void SetValue(PCSZ sp, int n);
+ virtual void SetValue(const char *sp, uint len, int n);
virtual void SetValue(PVAL valp, int n);
virtual void SetValue(PVBLK pv, int n1, int n2);
virtual void SetMin(PVAL valp, int n);
@@ -290,8 +290,8 @@ class STRBLK : public VALBLK {
// Methods
using VALBLK::SetValue;
- virtual void SetValue(PSZ sp, int n);
- virtual void SetValue(char *sp, uint len, int n);
+ virtual void SetValue(PCSZ sp, int n);
+ virtual void SetValue(const char *sp, uint len, int n);
virtual void SetValue(PVAL valp, int n);
virtual void SetValue(PVBLK pv, int n1, int n2);
virtual void SetMin(PVAL valp, int n);
@@ -322,12 +322,12 @@ class DATBLK : public TYPBLK<int> {
DATBLK(void *mp, int size);
// Implementation
- virtual bool SetFormat(PGLOBAL g, PSZ fmt, int len, int year = 0);
+ virtual bool SetFormat(PGLOBAL g, PCSZ fmt, int len, int year = 0);
virtual char *GetCharString(char *p, int n);
// Methods
using TYPBLK<int>::SetValue;
- virtual void SetValue(PSZ sp, int n);
+ virtual void SetValue(PCSZ sp, int n);
protected:
// Members
@@ -352,7 +352,7 @@ class PTRBLK : public STRBLK {
// Methods
using STRBLK::SetValue;
using STRBLK::CompVal;
- virtual void SetValue(PSZ p, int n) {Strp[n] = p;}
+ virtual void SetValue(PCSZ p, int n) {Strp[n] = (char*)p;}
virtual int CompVal(int i1, int i2);
protected:
diff --git a/storage/connect/value.cpp b/storage/connect/value.cpp
index 7660ee0a630..429593f07d9 100644
--- a/storage/connect/value.cpp
+++ b/storage/connect/value.cpp
@@ -1,7 +1,7 @@
/************* Value C++ Functions Source Code File (.CPP) *************/
-/* Name: VALUE.CPP Version 2.6 */
+/* Name: VALUE.CPP Version 2.8 */
/* */
-/* (C) Copyright to the author Olivier BERTRAND 2001-2016 */
+/* (C) Copyright to the author Olivier BERTRAND 2001-2017 */
/* */
/* This file contains the VALUE and derived classes family functions. */
/* These classes contain values of different types. They are used so */
@@ -60,7 +60,7 @@
#define CheckType(V) if (Type != V->GetType()) { \
PGLOBAL& g = Global; \
strcpy(g->Message, MSG(VALTYPE_NOMATCH)); \
- longjmp(g->jumper[g->jump_level], Type); }
+ throw Type;
#else
#define CheckType(V)
#endif
@@ -94,12 +94,12 @@ PSZ strlwr(PSZ s);
/* OUT minus: Set to true if the number is negative */
/* Returned val: The resulting number */
/***********************************************************************/
-ulonglong CharToNumber(char *p, int n, ulonglong maxval,
+ulonglong CharToNumber(const char *p, int n, ulonglong maxval,
bool un, bool *minus, bool *rc)
{
- char *p2;
- uchar c;
- ulonglong val;
+ const char *p2;
+ uchar c;
+ ulonglong val;
if (minus) *minus = false;
if (rc) *rc = false;
@@ -138,9 +138,9 @@ ulonglong CharToNumber(char *p, int n, ulonglong maxval,
/***********************************************************************/
/* GetTypeName: returns the PlugDB internal type name. */
/***********************************************************************/
-PSZ GetTypeName(int type)
+PCSZ GetTypeName(int type)
{
- PSZ name;
+ PCSZ name;
switch (type) {
case TYPE_STRING: name = "CHAR"; break;
@@ -184,9 +184,9 @@ int GetTypeSize(int type, int len)
/***********************************************************************/
/* GetFormatType: returns the FORMAT character(s) according to type. */
/***********************************************************************/
-char *GetFormatType(int type)
+const char *GetFormatType(int type)
{
- char *c = "X";
+ const char *c = "X";
switch (type) {
case TYPE_STRING: c = "C"; break;
@@ -370,7 +370,7 @@ PVAL AllocateValue(PGLOBAL g, void *value, short type, short prec)
/* Allocate a variable Value according to type, length and precision. */
/***********************************************************************/
PVAL AllocateValue(PGLOBAL g, int type, int len, int prec,
- bool uns, PSZ fmt)
+ bool uns, PCSZ fmt)
{
PVAL valp;
@@ -558,6 +558,38 @@ bool VALUE::Compute(PGLOBAL g, PVAL *, int, OPVAL)
return true;
} // end of Compute
+/***********************************************************************/
+/* Make file output of an object value. */
+/***********************************************************************/
+void VALUE::Print(PGLOBAL g, FILE *f, uint n)
+{
+ char m[64], buf[64];
+
+ memset(m, ' ', n); /* Make margin string */
+ m[n] = '\0';
+
+ if (Null)
+ fprintf(f, "%s<null>\n", m);
+ else
+ fprintf(f, strcat(strcat(GetCharString(buf), "\n"), m));
+
+} /* end of Print */
+
+/***********************************************************************/
+/* Make string output of an object value. */
+/***********************************************************************/
+void VALUE::Print(PGLOBAL g, char *ps, uint z)
+{
+ char *p, buf[64];
+
+ if (Null)
+ p = strcpy(buf, "<null>");
+ else
+ p = GetCharString(buf);
+
+ strncpy(ps, p, z);
+} // end of Print
+
/* -------------------------- Class TYPVAL ---------------------------- */
/***********************************************************************/
@@ -682,7 +714,7 @@ uchar TYPVAL<uchar>::GetTypedValue(PVAL valp)
/* TYPVAL SetValue: convert chars extracted from a line to TYPE value.*/
/***********************************************************************/
template <class TYPE>
-bool TYPVAL<TYPE>::SetValue_char(char *p, int n)
+bool TYPVAL<TYPE>::SetValue_char(const char *p, int n)
{
bool rc, minus;
ulonglong maxval = MaxVal();
@@ -704,7 +736,7 @@ bool TYPVAL<TYPE>::SetValue_char(char *p, int n)
} // end of SetValue
template <>
-bool TYPVAL<double>::SetValue_char(char *p, int n)
+bool TYPVAL<double>::SetValue_char(const char *p, int n)
{
if (p && n > 0) {
char buf[64];
@@ -732,7 +764,7 @@ bool TYPVAL<double>::SetValue_char(char *p, int n)
/* TYPVAL SetValue: fill a typed value from a string. */
/***********************************************************************/
template <class TYPE>
-void TYPVAL<TYPE>::SetValue_psz(PSZ s)
+void TYPVAL<TYPE>::SetValue_psz(PCSZ s)
{
if (s) {
SetValue_char(s, (int)strlen(s));
@@ -1019,12 +1051,12 @@ TYPE TYPVAL<TYPE>::SafeAdd(TYPE n1, TYPE n2)
if ((n2 > 0) && (n < n1)) {
// Overflow
strcpy(g->Message, MSG(FIX_OVFLW_ADD));
- longjmp(g->jumper[g->jump_level], 138);
- } else if ((n2 < 0) && (n > n1)) {
+ throw 138;
+ } else if ((n2 < 0) && (n > n1)) {
// Underflow
strcpy(g->Message, MSG(FIX_UNFLW_ADD));
- longjmp(g->jumper[g->jump_level], 138);
- } // endif's n2
+ throw 138;
+ } // endif's n2
return n;
} // end of SafeAdd
@@ -1047,12 +1079,12 @@ TYPE TYPVAL<TYPE>::SafeMult(TYPE n1, TYPE n2)
if (n > MinMaxVal(true)) {
// Overflow
strcpy(g->Message, MSG(FIX_OVFLW_TIMES));
- longjmp(g->jumper[g->jump_level], 138);
- } else if (n < MinMaxVal(false)) {
+ throw 138;
+ } else if (n < MinMaxVal(false)) {
// Underflow
strcpy(g->Message, MSG(FIX_UNFLW_TIMES));
- longjmp(g->jumper[g->jump_level], 138);
- } // endif's n2
+ throw 138;
+ } // endif's n2
return (TYPE)n;
} // end of SafeMult
@@ -1170,7 +1202,7 @@ bool TYPVAL<TYPE>::Compall(PGLOBAL g, PVAL *vp, int np, OPVAL op)
/* This function assumes that the format matches the value type. */
/***********************************************************************/
template <class TYPE>
-bool TYPVAL<TYPE>::FormatValue(PVAL vp, char *fmt)
+bool TYPVAL<TYPE>::FormatValue(PVAL vp, PCSZ fmt)
{
char *buf = (char*)vp->GetTo_Val(); // Should be big enough
int n = sprintf(buf, fmt, Tval);
@@ -1192,37 +1224,6 @@ bool TYPVAL<TYPE>::SetConstFormat(PGLOBAL g, FORMAT& fmt)
return false;
} // end of SetConstFormat
-/***********************************************************************/
-/* Make file output of a typed object. */
-/***********************************************************************/
-template <class TYPE>
-void TYPVAL<TYPE>::Print(PGLOBAL g, FILE *f, uint n)
- {
- char m[64], buf[12];
-
- memset(m, ' ', n); /* Make margin string */
- m[n] = '\0';
-
- if (Null)
- fprintf(f, "%s<null>\n", m);
- else
- fprintf(f, strcat(strcat(strcpy(buf, "%s"), Fmt), "\n"), m, Tval);
-
- } /* end of Print */
-
-/***********************************************************************/
-/* Make string output of a int object. */
-/***********************************************************************/
-template <class TYPE>
-void TYPVAL<TYPE>::Print(PGLOBAL g, char *ps, uint z)
- {
- if (Null)
- strcpy(ps, "<null>");
- else
- sprintf(ps, Fmt, Tval);
-
- } /* end of Print */
-
/* -------------------------- Class STRING --------------------------- */
/***********************************************************************/
@@ -1361,25 +1362,25 @@ bool TYPVAL<PSZ>::SetValue_pval(PVAL valp, bool chktype)
/***********************************************************************/
/* STRING SetValue: fill string with chars extracted from a line. */
/***********************************************************************/
-bool TYPVAL<PSZ>::SetValue_char(char *p, int n)
+bool TYPVAL<PSZ>::SetValue_char(const char *cp, int n)
{
bool rc = false;
- if (!p || n == 0) {
+ if (!cp || n == 0) {
Reset();
Null = Nullable;
- } else if (p != Strp) {
- rc = n > Len;
+ } else if (cp != Strp) {
+ const char *p = cp + n - 1;
- if ((n = MY_MIN(n, Len))) {
- strncpy(Strp, p, n);
+ for (p; p >= cp; p--, n--)
+ if (*p && *p != ' ')
+ break;
-// for (p = Strp + n - 1; p >= Strp && (*p == ' ' || *p == '\0'); p--) ;
- for (p = Strp + n - 1; p >= Strp; p--)
- if (*p && *p != ' ')
- break;
+ rc = n > Len;
- *(++p) = '\0';
+ if ((n = MY_MIN(n, Len))) {
+ strncpy(Strp, cp, n);
+ Strp[n] = '\0';
if (trace > 1)
htrc(" Setting string to: '%s'\n", Strp);
@@ -1396,7 +1397,7 @@ bool TYPVAL<PSZ>::SetValue_char(char *p, int n)
/***********************************************************************/
/* STRING SetValue: fill string with another string. */
/***********************************************************************/
-void TYPVAL<PSZ>::SetValue_psz(PSZ s)
+void TYPVAL<PSZ>::SetValue_psz(PCSZ s)
{
if (!s) {
Reset();
@@ -1432,8 +1433,8 @@ void TYPVAL<PSZ>::SetValue(int n)
if (k > Len) {
sprintf(g->Message, MSG(VALSTR_TOO_LONG), buf, Len);
- longjmp(g->jumper[g->jump_level], 138);
- } else
+ throw 138;
+ } else
SetValue_psz(buf);
Null = false;
@@ -1486,8 +1487,8 @@ void TYPVAL<PSZ>::SetValue(longlong n)
if (k > Len) {
sprintf(g->Message, MSG(VALSTR_TOO_LONG), buf, Len);
- longjmp(g->jumper[g->jump_level], 138);
- } else
+ throw 138;
+ } else
SetValue_psz(buf);
Null = false;
@@ -1529,8 +1530,8 @@ void TYPVAL<PSZ>::SetValue(double f)
if (k > Len) {
sprintf(g->Message, MSG(VALSTR_TOO_LONG), buf, Len);
- longjmp(g->jumper[g->jump_level], 138);
- } else
+ throw 138;
+ } else
SetValue_psz(buf);
Null = false;
@@ -1559,7 +1560,7 @@ void TYPVAL<PSZ>::SetValue(uchar c)
/***********************************************************************/
void TYPVAL<PSZ>::SetBinValue(void *p)
{
- SetValue_char((char *)p, Len);
+ SetValue_char((const char *)p, Len);
} // end of SetBinValue
/***********************************************************************/
@@ -1689,7 +1690,7 @@ bool TYPVAL<PSZ>::Compute(PGLOBAL g, PVAL *vp, int np, OPVAL op)
/* constructed from its own value formated using the fmt format. */
/* This function assumes that the format matches the value type. */
/***********************************************************************/
-bool TYPVAL<PSZ>::FormatValue(PVAL vp, char *fmt)
+bool TYPVAL<PSZ>::FormatValue(PVAL vp, PCSZ fmt)
{
char *buf = (char*)vp->GetTo_Val(); // Should be big enough
int n = sprintf(buf, fmt, Strp);
@@ -1708,6 +1709,18 @@ bool TYPVAL<PSZ>::SetConstFormat(PGLOBAL, FORMAT& fmt)
return false;
} // end of SetConstFormat
+/***********************************************************************/
+/* Make string output of an object value. */
+/***********************************************************************/
+void TYPVAL<PSZ>::Print(PGLOBAL g, char *ps, uint z)
+{
+ if (Null)
+ strncpy(ps, "null", z);
+ else
+ strcat(strncat(strncpy(ps, "\"", z), Strp, z-2), "\"");
+
+} // end of Print
+
/* -------------------------- Class DECIMAL -------------------------- */
/***********************************************************************/
@@ -1797,102 +1810,6 @@ bool DECVAL::GetBinValue(void *buf, int buflen, bool go)
return false;
} // end of GetBinValue
-#if 0
-/***********************************************************************/
-/* DECIMAL SetValue: copy the value of another Value object. */
-/***********************************************************************/
-bool DECVAL::SetValue_pval(PVAL valp, bool chktype)
- {
- if (chktype && (valp->GetType() != Type || valp->GetSize() > Len))
- return true;
-
- char buf[64];
-
- if (!(Null = valp->IsNull() && Nullable))
- strncpy(Strp, valp->GetCharString(buf), Len);
- else
- Reset();
-
- return false;
- } // end of SetValue_pval
-
-/***********************************************************************/
-/* DECIMAL SetValue: fill string with chars extracted from a line. */
-/***********************************************************************/
-bool DECVAL::SetValue_char(char *p, int n)
- {
- bool rc;
-
- if (p && n > 0) {
- rc = n > Len;
-
- if ((n = MY_MIN(n, Len))) {
- strncpy(Strp, p, n);
-
-// for (p = Strp + n - 1; p >= Strp && (*p == ' ' || *p == '\0'); p--) ;
- for (p = Strp + n - 1; p >= Strp; p--)
- if (*p && *p != ' ')
- break;
-
- *(++p) = '\0';
-
- if (trace > 1)
- htrc(" Setting string to: '%s'\n", Strp);
-
- } else
- Reset();
-
- Null = false;
- } else {
- rc = false;
- Reset();
- Null = Nullable;
- } // endif p
-
- return rc;
- } // end of SetValue_char
-
-/***********************************************************************/
-/* DECIMAL SetValue: fill string with another string. */
-/***********************************************************************/
-void DECVAL::SetValue_psz(PSZ s)
- {
- if (s) {
- strncpy(Strp, s, Len);
- Null = false;
- } else {
- Reset();
- Null = Nullable;
- } // endif s
-
- } // end of SetValue_psz
-
-/***********************************************************************/
-/* DECIMAL SetValue: fill string with a string extracted from a block.*/
-/***********************************************************************/
-void DECVAL::SetValue_pvblk(PVBLK blk, int n)
- {
- // STRBLK's can return a NULL pointer
- SetValue_psz(blk->GetCharValue(n));
- } // end of SetValue_pvblk
-
-/***********************************************************************/
-/* DECIMAL SetBinValue: fill string with chars extracted from a line. */
-/***********************************************************************/
-void DECVAL::SetBinValue(void *p)
- {
- SetValue_char((char *)p, Len);
- } // end of SetBinValue
-
-/***********************************************************************/
-/* DECIMAL GetCharString: get string representation of a char value. */
-/***********************************************************************/
-char *DECVAL::GetCharString(char *p)
- {
- return Strp;
- } // end of GetCharString
-#endif // 0
-
/***********************************************************************/
/* DECIMAL compare value with another Value. */
/***********************************************************************/
@@ -1927,32 +1844,6 @@ int DECVAL::CompareValue(PVAL vp)
return (f > n) ? 1 : (f < n) ? (-1) : 0;
} // end of CompareValue
-#if 0
-/***********************************************************************/
-/* FormatValue: This function set vp (a STRING value) to the string */
-/* constructed from its own value formated using the fmt format. */
-/* This function assumes that the format matches the value type. */
-/***********************************************************************/
-bool DECVAL::FormatValue(PVAL vp, char *fmt)
- {
- char *buf = (char*)vp->GetTo_Val(); // Should be big enough
- int n = sprintf(buf, fmt, Strp);
-
- return (n > vp->GetValLen());
- } // end of FormatValue
-
-/***********************************************************************/
-/* DECIMAL SetFormat function (used to set SELECT output format). */
-/***********************************************************************/
-bool DECVAL::SetConstFormat(PGLOBAL g, FORMAT& fmt)
- {
- fmt.Type[0] = 'C';
- fmt.Length = Len;
- fmt.Prec = 0;
- return false;
- } // end of SetConstFormat
-#endif // 0
-
/* -------------------------- Class BINVAL --------------------------- */
/***********************************************************************/
@@ -2110,7 +2001,7 @@ bool BINVAL::SetValue_pval(PVAL valp, bool chktype)
/***********************************************************************/
/* BINVAL SetValue: fill value with chars extracted from a line. */
/***********************************************************************/
-bool BINVAL::SetValue_char(char *p, int n)
+bool BINVAL::SetValue_char(const char *p, int n)
{
bool rc;
@@ -2131,7 +2022,7 @@ bool BINVAL::SetValue_char(char *p, int n)
/***********************************************************************/
/* BINVAL SetValue: fill value with another string. */
/***********************************************************************/
-void BINVAL::SetValue_psz(PSZ s)
+void BINVAL::SetValue_psz(PCSZ s)
{
if (s) {
Len = MY_MIN(Clen, (signed)strlen(s));
@@ -2357,7 +2248,7 @@ bool BINVAL::IsEqual(PVAL vp, bool chktype)
/* constructed from its own value formated using the fmt format. */
/* This function assumes that the format matches the value type. */
/***********************************************************************/
-bool BINVAL::FormatValue(PVAL vp, char *fmt)
+bool BINVAL::FormatValue(PVAL vp, PCSZ fmt)
{
char *buf = (char*)vp->GetTo_Val(); // Should be big enough
int n = sprintf(buf, fmt, Len, Binp);
@@ -2381,7 +2272,7 @@ bool BINVAL::SetConstFormat(PGLOBAL, FORMAT& fmt)
/***********************************************************************/
/* DTVAL public constructor for new void values. */
/***********************************************************************/
-DTVAL::DTVAL(PGLOBAL g, int n, int prec, PSZ fmt)
+DTVAL::DTVAL(PGLOBAL g, int n, int prec, PCSZ fmt)
: TYPVAL<int>((int)0, TYPE_DATE)
{
if (!fmt) {
@@ -2410,7 +2301,7 @@ DTVAL::DTVAL(int n) : TYPVAL<int>(n, TYPE_DATE)
/***********************************************************************/
/* Set format so formatted dates can be converted on input/output. */
/***********************************************************************/
-bool DTVAL::SetFormat(PGLOBAL g, PSZ fmt, int len, int year)
+bool DTVAL::SetFormat(PGLOBAL g, PCSZ fmt, int len, int year)
{
Pdtp = MakeDateFormat(g, fmt, true, true, (year > 9999) ? 1 : 0);
Sdate = (char*)PlugSubAlloc(g, NULL, len + 1);
@@ -2668,7 +2559,11 @@ bool DTVAL::SetValue_pval(PVAL valp, bool chktype)
ndv = ExtractDate(valp->GetCharValue(), Pdtp, DefYear, dval);
MakeDate(NULL, dval, ndv);
- } else
+ } else if (valp->GetType() == TYPE_BIGINT &&
+ !(valp->GetBigintValue() % 1000)) {
+ // Assuming that this timestamp is in milliseconds
+ Tval = valp->GetBigintValue() / 1000;
+ } else
Tval = valp->GetIntValue();
} else
@@ -2682,14 +2577,14 @@ bool DTVAL::SetValue_pval(PVAL valp, bool chktype)
/***********************************************************************/
/* SetValue: convert chars extracted from a line to date value. */
/***********************************************************************/
-bool DTVAL::SetValue_char(char *p, int n)
+bool DTVAL::SetValue_char(const char *p, int n)
{
bool rc= 0;
if (Pdtp) {
- char *p2;
- int ndv;
- int dval[6];
+ const char *p2;
+ int ndv;
+ int dval[6];
if (n > 0) {
// Trim trailing blanks
@@ -2721,11 +2616,11 @@ bool DTVAL::SetValue_char(char *p, int n)
/***********************************************************************/
/* SetValue: convert a char string to date value. */
/***********************************************************************/
-void DTVAL::SetValue_psz(PSZ p)
+void DTVAL::SetValue_psz(PCSZ p)
{
if (Pdtp) {
- int ndv;
- int dval[6];
+ int ndv;
+ int dval[6];
strncpy(Sdate, p, Len);
Sdate[Len] = '\0';
@@ -2815,8 +2710,10 @@ char *DTVAL::ShowValue(char *buf, int len)
strncat(p, "Error", m);
} // endif n
- } else
- p = ""; // DEFAULT VALUE ???
+ } else {
+ p = buf;
+ *p = '\0'; // DEFAULT VALUE ???
+ } // endif Null
return p;
} else
@@ -2881,7 +2778,7 @@ bool DTVAL::WeekNum(PGLOBAL g, int& nval)
/* constructed from its own value formated using the fmt format. */
/* This function assumes that the format matches the value type. */
/***********************************************************************/
-bool DTVAL::FormatValue(PVAL vp, char *fmt)
+bool DTVAL::FormatValue(PVAL vp, PCSZ fmt)
{
char *buf = (char*)vp->GetTo_Val(); // Should be big enough
struct tm tm, *ptm = GetGmTime(&tm);
diff --git a/storage/connect/value.h b/storage/connect/value.h
index 14a568c3549..cf6682f56f2 100644
--- a/storage/connect/value.h
+++ b/storage/connect/value.h
@@ -1,7 +1,7 @@
/**************** Value H Declares Source Code File (.H) ***************/
-/* Name: VALUE.H Version 2.2 */
+/* Name: VALUE.H Version 2.3 */
/* */
-/* (C) Copyright to the author Olivier BERTRAND 2001-2016 */
+/* (C) Copyright to the author Olivier BERTRAND 2001-2017 */
/* */
/* This file contains the VALUE and derived classes declares. */
/***********************************************************************/
@@ -40,14 +40,14 @@ typedef struct _datpar *PDTP; // For DTVAL
/* Utilities used to test types and to allocated values. */
/***********************************************************************/
// Exported functions
-DllExport PSZ GetTypeName(int);
+DllExport PCSZ GetTypeName(int);
DllExport int GetTypeSize(int, int);
#ifdef ODBC_SUPPORT
/* This function is exported for use in OEM table type DLLs */
DllExport int TranslateSQLType(int stp, int prec,
int& len, char& v, bool& w);
#endif
-DllExport char *GetFormatType(int);
+DllExport const char *GetFormatType(int);
DllExport int GetFormatType(char);
DllExport bool IsTypeChar(int type);
DllExport bool IsTypeNum(int type);
@@ -55,8 +55,8 @@ DllExport int ConvertType(int, int, CONV, bool match = false);
DllExport PVAL AllocateValue(PGLOBAL, void *, short, short = 2);
DllExport PVAL AllocateValue(PGLOBAL, PVAL, int = TYPE_VOID, int = 0);
DllExport PVAL AllocateValue(PGLOBAL, int, int len = 0, int prec = 0,
- bool uns = false, PSZ fmt = NULL);
-DllExport ulonglong CharToNumber(char *, int, ulonglong, bool,
+ bool uns = false, PCSZ fmt = NULL);
+DllExport ulonglong CharToNumber(PCSZ, int, ulonglong, bool,
bool *minus = NULL, bool *rc = NULL);
DllExport BYTE OpBmp(PGLOBAL g, OPVAL opc);
@@ -100,8 +100,8 @@ class DllExport VALUE : public BLOCK {
// Methods
virtual bool SetValue_pval(PVAL valp, bool chktype = false) = 0;
- virtual bool SetValue_char(char *p, int n) = 0;
- virtual void SetValue_psz(PSZ s) = 0;
+ virtual bool SetValue_char(const char *p, int n) = 0;
+ virtual void SetValue_psz(PCSZ s) = 0;
virtual void SetValue_bool(bool) {assert(FALSE);}
virtual int CompareValue(PVAL vp) = 0;
virtual BYTE TestValue(PVAL vp);
@@ -121,7 +121,9 @@ class DllExport VALUE : public BLOCK {
virtual char *GetCharString(char *p) = 0;
virtual bool IsEqual(PVAL vp, bool chktype) = 0;
virtual bool Compute(PGLOBAL g, PVAL *vp, int np, OPVAL op);
- virtual bool FormatValue(PVAL vp, char *fmt) = 0;
+ virtual bool FormatValue(PVAL vp, PCSZ fmt) = 0;
+ virtual void Print(PGLOBAL g, FILE *, uint);
+ virtual void Print(PGLOBAL g, char *ps, uint z);
/**
Set value from a non-aligned in-memory value in the machine byte order.
@@ -211,8 +213,8 @@ class DllExport TYPVAL : public VALUE {
// Methods
virtual bool SetValue_pval(PVAL valp, bool chktype);
- virtual bool SetValue_char(char *p, int n);
- virtual void SetValue_psz(PSZ s);
+ virtual bool SetValue_char(const char *p, int n);
+ virtual void SetValue_psz(PCSZ s);
virtual void SetValue_bool(bool b) {Tval = (b) ? 1 : 0;}
virtual int CompareValue(PVAL vp);
virtual void SetValue(char c) {Tval = (TYPE)c; Null = false;}
@@ -232,9 +234,7 @@ class DllExport TYPVAL : public VALUE {
virtual bool IsEqual(PVAL vp, bool chktype);
virtual bool Compute(PGLOBAL g, PVAL *vp, int np, OPVAL op);
virtual bool SetConstFormat(PGLOBAL, FORMAT&);
- virtual bool FormatValue(PVAL vp, char *fmt);
- virtual void Print(PGLOBAL g, FILE *, uint);
- virtual void Print(PGLOBAL g, char *, uint);
+ virtual bool FormatValue(PVAL vp, PCSZ fmt);
protected:
static TYPE MinMaxVal(bool b);
@@ -287,8 +287,8 @@ class DllExport TYPVAL<PSZ>: public VALUE {
// Methods
virtual bool SetValue_pval(PVAL valp, bool chktype);
- virtual bool SetValue_char(char *p, int n);
- virtual void SetValue_psz(PSZ s);
+ virtual bool SetValue_char(const char *p, int n);
+ virtual void SetValue_psz(PCSZ s);
virtual void SetValue_pvblk(PVBLK blk, int n);
virtual void SetValue(char c);
virtual void SetValue(uchar c);
@@ -306,8 +306,9 @@ class DllExport TYPVAL<PSZ>: public VALUE {
virtual char *GetCharString(char *p);
virtual bool IsEqual(PVAL vp, bool chktype);
virtual bool Compute(PGLOBAL g, PVAL *vp, int np, OPVAL op);
- virtual bool FormatValue(PVAL vp, char *fmt);
+ virtual bool FormatValue(PVAL vp, PCSZ fmt);
virtual bool SetConstFormat(PGLOBAL, FORMAT&);
+ virtual void Print(PGLOBAL g, char *ps, uint z);
protected:
// Members
@@ -371,8 +372,8 @@ class DllExport BINVAL: public VALUE {
// Methods
virtual bool SetValue_pval(PVAL valp, bool chktype);
- virtual bool SetValue_char(char *p, int n);
- virtual void SetValue_psz(PSZ s);
+ virtual bool SetValue_char(const char *p, int n);
+ virtual void SetValue_psz(PCSZ s);
virtual void SetValue_pvblk(PVBLK blk, int n);
virtual void SetValue(char c);
virtual void SetValue(uchar c);
@@ -389,7 +390,7 @@ class DllExport BINVAL: public VALUE {
virtual char *ShowValue(char *buf, int);
virtual char *GetCharString(char *p);
virtual bool IsEqual(PVAL vp, bool chktype);
- virtual bool FormatValue(PVAL vp, char *fmt);
+ virtual bool FormatValue(PVAL vp, PCSZ fmt);
virtual bool SetConstFormat(PGLOBAL, FORMAT&);
protected:
@@ -405,18 +406,18 @@ class DllExport BINVAL: public VALUE {
class DllExport DTVAL : public TYPVAL<int> {
public:
// Constructors
- DTVAL(PGLOBAL g, int n, int p, PSZ fmt);
+ DTVAL(PGLOBAL g, int n, int p, PCSZ fmt);
DTVAL(int n);
// Implementation
virtual bool SetValue_pval(PVAL valp, bool chktype);
- virtual bool SetValue_char(char *p, int n);
- virtual void SetValue_psz(PSZ s);
+ virtual bool SetValue_char(const char *p, int n);
+ virtual void SetValue_psz(PCSZ s);
virtual void SetValue_pvblk(PVBLK blk, int n);
virtual char *GetCharString(char *p);
virtual char *ShowValue(char *buf, int);
- virtual bool FormatValue(PVAL vp, char *fmt);
- bool SetFormat(PGLOBAL g, PSZ fmt, int len, int year = 0);
+ virtual bool FormatValue(PVAL vp, PCSZ fmt);
+ bool SetFormat(PGLOBAL g, PCSZ fmt, int len, int year = 0);
bool SetFormat(PGLOBAL g, PVAL valp);
bool IsFormatted(void) {return Pdtp != NULL;}
bool MakeTime(struct tm *ptm);
diff --git a/storage/connect/xindex.cpp b/storage/connect/xindex.cpp
index ae210cb900c..a34d2e1c847 100755
--- a/storage/connect/xindex.cpp
+++ b/storage/connect/xindex.cpp
@@ -1,7 +1,7 @@
/***************** Xindex C++ Class Xindex Code (.CPP) *****************/
-/* Name: XINDEX.CPP Version 2.9 */
+/* Name: XINDEX.CPP Version 3.0 */
/* */
-/* (C) Copyright to the author Olivier BERTRAND 2004-2015 */
+/* (C) Copyright to the author Olivier BERTRAND 2004-2017 */
/* */
/* This file contains the class XINDEX implementation code. */
/***********************************************************************/
@@ -446,8 +446,8 @@ bool XINDEX::Make(PGLOBAL g, PIXDEF sxp)
#if 0
if (!dup->Step) {
strcpy(g->Message, MSG(QUERY_CANCELLED));
- longjmp(g->jumper[g->jump_level], 99);
- } // endif Step
+ throw 99;
+ } // endif Step
#endif // 0
/*******************************************************************/
@@ -819,7 +819,7 @@ bool XINDEX::Reorder(PGLOBAL g __attribute__((unused)))
/***********************************************************************/
bool XINDEX::SaveIndex(PGLOBAL g, PIXDEF sxp)
{
- char *ftype;
+ PCSZ ftype;
char fn[_MAX_PATH];
int n[NZ], nof = (Mul) ? (Ndif + 1) : 0;
int id = -1, size = 0;
@@ -948,7 +948,7 @@ bool XINDEX::Init(PGLOBAL g)
/* Table will be accessed through an index table. */
/* If sorting is required, this will be done later. */
/*********************************************************************/
- char *ftype;
+ PCSZ ftype;
char fn[_MAX_PATH];
int k, n, nv[NZ], id = -1;
bool estim = false;
@@ -965,7 +965,7 @@ bool XINDEX::Init(PGLOBAL g)
// For DBF tables, Cardinality includes bad or soft deleted lines
// that are not included in the index, and can be larger then the
// index size.
- estim = (Tdbp->Ftype == RECFM_DBF);
+ estim = (Tdbp->Ftype == RECFM_DBF || Tdbp->Txfp->GetAmType() == TYPE_AM_ZIP);
n = Tdbp->Cardinality(g); // n is exact table size
} else {
// Variable table not optimized
@@ -1412,7 +1412,7 @@ err:
/***********************************************************************/
bool XINDEX::GetAllSizes(PGLOBAL g,/* int &ndif,*/ int &numk)
{
- char *ftype;
+ PCSZ ftype;
char fn[_MAX_PATH];
int nv[NZ], id = -1; // n
//bool estim = false;
@@ -2320,9 +2320,9 @@ XFILE::XFILE(void) : XLOAD()
/***********************************************************************/
bool XFILE::Open(PGLOBAL g, char *filename, int id, MODE mode)
{
- char *pmod;
- bool rc;
- IOFF noff[MAX_INDX];
+ PCSZ pmod;
+ bool rc;
+ IOFF noff[MAX_INDX];
/*********************************************************************/
/* Open the index file according to mode. */
@@ -3032,7 +3032,7 @@ bool KXYCOL::Init(PGLOBAL g, PCOL colp, int n, bool sm, int kln)
return true;
Klen = Valp->GetClen();
- Keys.Size = n * Klen;
+ Keys.Size = (size_t)n * (size_t)Klen;
if (!PlgDBalloc(g, NULL, Keys)) {
sprintf(g->Message, MSG(KEY_ALLOC_ERROR), Klen, n);
diff --git a/storage/connect/xobject.cpp b/storage/connect/xobject.cpp
index 746de097918..8f0b76d2ddc 100644
--- a/storage/connect/xobject.cpp
+++ b/storage/connect/xobject.cpp
@@ -1,7 +1,7 @@
/************ Xobject C++ Functions Source Code File (.CPP) ************/
-/* Name: XOBJECT.CPP Version 2.4 */
+/* Name: XOBJECT.CPP Version 2.5 */
/* */
-/* (C) Copyright to the author Olivier BERTRAND 1998-2014 */
+/* (C) Copyright to the author Olivier BERTRAND 1998-2017 */
/* */
/* This file contains base XOBJECT class functions. */
/* Also here is the implementation of the CONSTANT class. */
@@ -84,7 +84,7 @@ double XOBJECT::GetFloatValue(void)
CONSTANT::CONSTANT(PGLOBAL g, void *value, short type)
{
if (!(Value = AllocateValue(g, value, (int)type)))
- longjmp(g->jumper[g->jump_level], TYPE_CONST);
+ throw TYPE_CONST;
Constant = true;
} // end of CONSTANT constructor
@@ -95,7 +95,7 @@ CONSTANT::CONSTANT(PGLOBAL g, void *value, short type)
CONSTANT::CONSTANT(PGLOBAL g, int n)
{
if (!(Value = AllocateValue(g, &n, TYPE_INT)))
- longjmp(g->jumper[g->jump_level], TYPE_CONST);
+ throw TYPE_CONST;
Constant = true;
} // end of CONSTANT constructor
@@ -117,7 +117,7 @@ void CONSTANT::Convert(PGLOBAL g, int newtype)
{
if (Value->GetType() != newtype)
if (!(Value = AllocateValue(g, Value, newtype)))
- longjmp(g->jumper[g->jump_level], TYPE_CONST);
+ throw TYPE_CONST;
} // end of Convert
@@ -192,7 +192,7 @@ void CONSTANT::Print(PGLOBAL g, char *ps, uint z)
/* STRING public constructor for new char values. Alloc Size must be */
/* calculated because PlugSubAlloc rounds up size to multiple of 8. */
/***********************************************************************/
-STRING::STRING(PGLOBAL g, uint n, char *str)
+STRING::STRING(PGLOBAL g, uint n, PCSZ str)
{
G = g;
Length = (str) ? strlen(str) : 0;
@@ -205,10 +205,12 @@ STRING::STRING(PGLOBAL g, uint n, char *str)
Next = GetNext();
Size = Next - Strp;
+ Trc = false;
} else {
// This should normally never happen
Next = NULL;
Size = 0;
+ Trc = true;
} // endif Strp
} // end of STRING constructor
@@ -229,6 +231,7 @@ char *STRING::Realloc(uint len)
if (!p) {
// No more room in Sarea; this is very unlikely
strcpy(G->Message, "No more room in work area");
+ Trc = true;
return NULL;
} // endif p
@@ -243,7 +246,7 @@ char *STRING::Realloc(uint len)
/***********************************************************************/
/* Set a STRING new PSZ value. */
/***********************************************************************/
-bool STRING::Set(PSZ s)
+bool STRING::Set(PCSZ s)
{
if (!s)
return false;
@@ -333,9 +336,9 @@ bool STRING::Append(const char *s, uint ln, bool nq)
} // end of Append
/***********************************************************************/
-/* Append a PSZ to a STRING. */
+/* Append a PCSZ to a STRING. */
/***********************************************************************/
-bool STRING::Append(PSZ s)
+bool STRING::Append(PCSZ s)
{
if (!s)
return false;
@@ -392,11 +395,11 @@ bool STRING::Append(char c)
/***********************************************************************/
/* Append a quoted PSZ to a STRING. */
/***********************************************************************/
-bool STRING::Append_quoted(PSZ s)
+bool STRING::Append_quoted(PCSZ s)
{
bool b = Append('\'');
- if (s) for (char *p = s; !b && *p; p++)
+ if (s) for (const char *p = s; !b && *p; p++)
switch (*p) {
case '\'':
case '\\':
diff --git a/storage/connect/xobject.h b/storage/connect/xobject.h
index 8f6c23c4aeb..204144182c8 100644
--- a/storage/connect/xobject.h
+++ b/storage/connect/xobject.h
@@ -123,24 +123,25 @@ class DllExport CONSTANT : public XOBJECT {
class DllExport STRING : public BLOCK {
public:
// Constructor
- STRING(PGLOBAL g, uint n, PSZ str = NULL);
+ STRING(PGLOBAL g, uint n, PCSZ str = NULL);
// Implementation
inline int GetLength(void) {return (int)Length;}
inline void SetLength(uint n) {Length = n;}
inline PSZ GetStr(void) {return Strp;}
inline uint32 GetSize(void) {return Size;}
+ inline bool IsTruncated(void) {return Trc;}
// Methods
inline void Reset(void) {*Strp = 0;}
- bool Set(PSZ s);
+ bool Set(PCSZ s);
bool Set(char *s, uint n);
bool Append(const char *s, uint ln, bool nq = false);
- bool Append(PSZ s);
+ bool Append(PCSZ s);
bool Append(STRING &str);
bool Append(char c);
bool Resize(uint n);
- bool Append_quoted(PSZ s);
+ bool Append_quoted(PCSZ 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;}
@@ -156,6 +157,7 @@ class DllExport STRING : public BLOCK {
PSZ Strp; // The char string
uint Length; // String length
uint Size; // Allocated size
+ bool Trc; // When truncated
char *Next; // Next alloc position
}; // end of class STRING
diff --git a/storage/connect/xtable.h b/storage/connect/xtable.h
index 4aeea05946a..3da0c17bdfe 100644
--- a/storage/connect/xtable.h
+++ b/storage/connect/xtable.h
@@ -33,29 +33,6 @@ class CMD : public BLOCK {
char *Cmd;
}; // end of class CMD
-#if 0
-// Condition filter structure
-class CONDFIL : public BLOCK {
- public:
- // Constructor
- CONDFIL(const Item *cond, uint idx, AMT type)
- {
- Cond = cond; Idx = idx; Type = type; Op = OP_XX;
- Cmds = NULL; All = true; Body = NULL, Having = NULL;
- }
-
- // Members
- const Item *Cond;
- AMT Type;
- uint Idx;
- OPVAL Op;
- PCMD Cmds;
- bool All;
- char *Body;
- char *Having;
-}; // end of class CONDFIL
-#endif // 0
-
typedef class EXTCOL *PEXTCOL;
typedef class CONDFIL *PCFIL;
typedef class TDBCAT *PTDBCAT;
@@ -84,7 +61,6 @@ class DllExport TDB: public BLOCK { // Table Descriptor Block.
inline PFIL GetFilter(void) {return To_Filter;}
inline PCOL GetSetCols(void) {return To_SetCols;}
inline void SetSetCols(PCOL colp) {To_SetCols = colp;}
- inline void SetFilter(PFIL fp) {To_Filter = fp;}
inline void SetOrig(PTDB txp) {To_Orig = txp;}
inline void SetUse(TUSE n) {Use = n;}
inline void SetCondFil(PCFIL cfp) {To_CondFil = cfp;}
@@ -94,11 +70,14 @@ class DllExport TDB: public BLOCK { // Table Descriptor Block.
inline void SetColumns(PCOL colp) {Columns = colp;}
inline void SetDegree(int degree) {Degree = degree;}
inline void SetMode(MODE mode) {Mode = mode;}
+ inline const Item *GetCond(void) {return Cond;}
+ inline void SetCond(const Item *cond) {Cond = cond;}
// Properties
virtual AMT GetAmType(void) {return TYPE_AM_ERROR;}
virtual bool IsRemote(void) {return false;}
virtual bool IsIndexed(void) {return false;}
+ virtual void SetFilter(PFIL fp) {To_Filter = fp;}
virtual int GetTdb_No(void) {return Tdb_No;}
virtual PTDB GetNext(void) {return Next;}
virtual PCATLG GetCat(void) {return NULL;}
@@ -110,7 +89,7 @@ class DllExport TDB: public BLOCK { // Table Descriptor Block.
virtual bool IsSpecial(PSZ name);
virtual bool IsReadOnly(void) {return Read_Only;}
virtual bool IsView(void) {return FALSE;}
- virtual PSZ GetPath(void);
+ virtual PCSZ GetPath(void);
virtual RECFM GetFtype(void) {return RECFM_NAF;}
virtual bool GetBlockValues(PGLOBAL) { return false; }
virtual int Cardinality(PGLOBAL) {return 0;}
@@ -119,11 +98,12 @@ class DllExport TDB: public BLOCK { // Table Descriptor Block.
virtual int GetMaxSize(PGLOBAL) = 0;
virtual int GetProgMax(PGLOBAL) = 0;
virtual int GetProgCur(void) {return GetRecpos();}
- virtual PSZ GetFile(PGLOBAL) {return "Not a file";}
- virtual void SetFile(PGLOBAL, PSZ) {}
+ virtual PCSZ GetFile(PGLOBAL) {return "Not a file";}
+ virtual void SetFile(PGLOBAL, PCSZ) {}
virtual void ResetDB(void) {}
virtual void ResetSize(void) {MaxSize = -1;}
virtual int RowNumber(PGLOBAL g, bool b = false);
+ virtual bool CanBeFiltered(void) {return true;}
virtual PTDB Duplicate(PGLOBAL) {return NULL;}
virtual PTDB Clone(PTABS) {return this;}
virtual PTDB Copy(PTABS t);
@@ -131,7 +111,7 @@ class DllExport TDB: public BLOCK { // Table Descriptor Block.
{fprintf(f, "%s AM(%d)\n", m, GetAmType());}
virtual void Print(PGLOBAL g, FILE *f, uint n);
virtual void Print(PGLOBAL g, char *ps, uint z);
- virtual PSZ GetServer(void) = 0;
+ virtual PCSZ GetServer(void) = 0;
virtual int GetBadLines(void) {return 0;}
virtual CHARSET_INFO *data_charset(void);
@@ -157,6 +137,7 @@ class DllExport TDB: public BLOCK { // Table Descriptor Block.
TUSE Use;
PFIL To_Filter;
PCFIL To_CondFil; // To condition filter structure
+ const Item *Cond; // The condition used to make filters
static int Tnum; // Used to generate Tdb_no's
const int Tdb_No; // GetTdb_No() is always 0 for OPJOIN
PTDB Next; // Next in linearized queries
@@ -187,9 +168,6 @@ class DllExport TDBASE : public TDB {
// Implementation
inline int GetKnum(void) {return Knum;}
-//inline PTABDEF GetDef(void) {return To_Def;}
-//inline PCOL GetSetCols(void) {return To_SetCols;}
-//inline void SetSetCols(PCOL colp) {To_SetCols = colp;}
inline void SetKey_Col(PCOL *cpp) {To_Key_Col = cpp;}
inline void SetXdp(PIXDEF xdp) {To_Xdp = xdp;}
inline void SetKindex(PKXBASE kxp) {To_Kindex = kxp;}
@@ -201,36 +179,14 @@ class DllExport TDBASE : public TDB {
// Methods
virtual bool IsUsingTemp(PGLOBAL) {return false;}
-//virtual bool IsIndexed(void) {return false;}
-//virtual bool IsSpecial(PSZ name);
virtual PCATLG GetCat(void);
-//virtual PSZ GetPath(void);
virtual void PrintAM(FILE *f, char *m);
-//virtual RECFM GetFtype(void) {return RECFM_NAF;}
-//virtual int GetAffectedRows(void) {return -1;}
-//virtual int GetRecpos(void) = 0;
-//virtual bool SetRecpos(PGLOBAL g, int recpos);
-//virtual bool IsReadOnly(void) {return Read_Only;}
-//virtual bool IsView(void) {return FALSE;}
-//virtual CHARSET_INFO *data_charset(void);
virtual int GetProgMax(PGLOBAL g) {return GetMaxSize(g);}
-//virtual int GetProgCur(void) {return GetRecpos();}
-//virtual PSZ GetFile(PGLOBAL) {return "Not a file";}
-//virtual int GetRemote(void) {return 0;}
-//virtual void SetFile(PGLOBAL, PSZ) {}
-//virtual void ResetDB(void) {}
-//virtual void ResetSize(void) {MaxSize = -1;}
virtual void RestoreNrec(void) {}
virtual int ResetTableOpt(PGLOBAL g, bool dop, bool dox);
- virtual PSZ GetServer(void) {return "Current";}
+ virtual PCSZ GetServer(void) {return "Current";}
// Database routines
-//virtual PCOL ColDB(PGLOBAL g, PSZ name, int num);
-//virtual PCOL MakeCol(PGLOBAL, PCOLDEF, PCOL, int)
-// {assert(false); return NULL;}
-//virtual PCOL InsertSpecialColumn(PCOL colp);
-//virtual PCOL InsertSpcBlk(PGLOBAL g, PCOLDEF cdp);
-//virtual void MarkDB(PGLOBAL g, PTDB tdb2);
virtual int MakeIndex(PGLOBAL g, PIXDEF, bool)
{strcpy(g->Message, "Remote index"); return RC_INFO;}
virtual bool ReadKey(PGLOBAL, OPVAL, const key_range *)
@@ -241,18 +197,12 @@ class DllExport TDBASE : public TDB {
"This function should not be called for this table"); return true;}
// Members
-//PTABDEF To_Def; // Points to catalog description block
PXOB *To_Link; // Points to column of previous relations
PCOL *To_Key_Col; // Points to key columns in current file
PKXBASE To_Kindex; // Points to table key index
PIXDEF To_Xdp; // To the index definition block
-//PCOL To_SetCols; // Points to updated columns
RECFM Ftype; // File type: 0-var 1-fixed 2-binary (VCT)
-//int MaxSize; // Max size in number of lines
int Knum; // Size of key arrays
-//bool Read_Only; // True for read only tables
-//const CHARSET_INFO *m_data_charset;
-//const char *csname; // Table charset name
}; // end of class TDBASE
/***********************************************************************/
diff --git a/storage/innobase/btr/btr0sea.cc b/storage/innobase/btr/btr0sea.cc
index 712e15a8171..70f2cbc10e2 100644
--- a/storage/innobase/btr/btr0sea.cc
+++ b/storage/innobase/btr/btr0sea.cc
@@ -175,7 +175,7 @@ btr_search_sys_create(
btr_search_sys = (btr_search_sys_t*)
mem_alloc(sizeof(btr_search_sys_t));
- btr_search_sys->hash_index = ha_create(hash_size, 0,
+ btr_search_sys->hash_index = ib_create(hash_size, 0,
MEM_HEAP_FOR_BTR_SEARCH, 0);
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
btr_search_sys->hash_index->adaptive = TRUE;
diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc
index 9a4a6f18551..6c54cee06b2 100644
--- a/storage/innobase/buf/buf0buf.cc
+++ b/storage/innobase/buf/buf0buf.cc
@@ -1451,7 +1451,7 @@ buf_pool_init_instance(
ut_a(srv_n_page_hash_locks != 0);
ut_a(srv_n_page_hash_locks <= MAX_PAGE_HASH_LOCKS);
- buf_pool->page_hash = ha_create(2 * buf_pool->curr_size,
+ buf_pool->page_hash = ib_create(2 * buf_pool->curr_size,
srv_n_page_hash_locks,
MEM_HEAP_FOR_PAGE_HASH,
SYNC_BUF_PAGE_HASH);
diff --git a/storage/innobase/buf/buf0dblwr.cc b/storage/innobase/buf/buf0dblwr.cc
index be41b69b487..e2c7ae9bae1 100644
--- a/storage/innobase/buf/buf0dblwr.cc
+++ b/storage/innobase/buf/buf0dblwr.cc
@@ -1,7 +1,7 @@
/*****************************************************************************
-Copyright (c) 1995, 2014, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2013, 2017, MariaDB Corporation. All Rights Reserved.
+Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2013, 2017, MariaDB Corporation.
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
@@ -351,7 +351,7 @@ recovery, this function loads the pages from double write buffer into memory. */
void
buf_dblwr_init_or_load_pages(
/*=========================*/
- os_file_t file,
+ pfs_os_file_t file,
char* path,
bool load_corrupt_pages)
{
diff --git a/storage/innobase/buf/buf0dump.cc b/storage/innobase/buf/buf0dump.cc
index c7e7d442bb4..0994d87bc2d 100644
--- a/storage/innobase/buf/buf0dump.cc
+++ b/storage/innobase/buf/buf0dump.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2011, 2016, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2011, 2017, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, MariaDB Corporation. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
@@ -685,6 +685,7 @@ extern "C" UNIV_INTERN
os_thread_ret_t
DECLARE_THREAD(buf_dump_thread)(void*)
{
+ my_thread_init();
ut_ad(!srv_read_only_mode);
buf_dump_status(STATUS_INFO, "Dumping buffer pool(s) not yet started");
@@ -721,6 +722,7 @@ DECLARE_THREAD(buf_dump_thread)(void*)
srv_buf_dump_thread_active = false;
+ my_thread_end();
/* 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. */
os_thread_exit(NULL);
diff --git a/storage/innobase/buf/buf0flu.cc b/storage/innobase/buf/buf0flu.cc
index b41ea4c8f02..b5ce171c92e 100644
--- a/storage/innobase/buf/buf0flu.cc
+++ b/storage/innobase/buf/buf0flu.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2013, 2017, MariaDB Corporation.
Copyright (c) 2013, 2014, Fusion-io
@@ -2302,6 +2302,7 @@ DECLARE_THREAD(buf_flush_page_cleaner_thread)(
/*!< in: a dummy parameter required by
os_thread_create */
{
+ my_thread_init();
ulint next_loop_time = ut_time_ms() + 1000;
ulint n_flushed = 0;
ulint last_activity = srv_get_activity_count();
@@ -2414,6 +2415,7 @@ DECLARE_THREAD(buf_flush_page_cleaner_thread)(
thread_exit:
buf_page_cleaner_is_active = FALSE;
+ my_thread_end();
/* 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. */
os_thread_exit(NULL);
diff --git a/storage/innobase/dict/dict0stats.cc b/storage/innobase/dict/dict0stats.cc
index 1960471afb6..364add4791d 100644
--- a/storage/innobase/dict/dict0stats.cc
+++ b/storage/innobase/dict/dict0stats.cc
@@ -1168,8 +1168,9 @@ dict_stats_analyze_index_level(
leaf-level delete marks because delete marks on
non-leaf level do not make sense. */
- if (level == 0 && srv_stats_include_delete_marked? 0:
- rec_get_deleted_flag(
+ if (level == 0
+ && !srv_stats_include_delete_marked
+ && rec_get_deleted_flag(
rec,
page_is_comp(btr_pcur_get_page(&pcur)))) {
diff --git a/storage/innobase/dict/dict0stats_bg.cc b/storage/innobase/dict/dict0stats_bg.cc
index 4d197f9ab88..721e4706e2a 100644
--- a/storage/innobase/dict/dict0stats_bg.cc
+++ b/storage/innobase/dict/dict0stats_bg.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2012, 2016, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2012, 2017, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, MariaDB Corporation. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
@@ -529,6 +529,7 @@ extern "C" UNIV_INTERN
os_thread_ret_t
DECLARE_THREAD(dict_stats_thread)(void*)
{
+ my_thread_init();
ut_a(!srv_read_only_mode);
while (!SHUTTING_DOWN()) {
@@ -555,6 +556,7 @@ DECLARE_THREAD(dict_stats_thread)(void*)
srv_dict_stats_thread_active = false;
+ my_thread_end();
/* We count the number of threads in os_thread_exit(). A created
thread should always use that to exit instead of return(). */
os_thread_exit(NULL);
diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc
index 14b23702ca9..9a0b6010d0c 100644
--- a/storage/innobase/fil/fil0fil.cc
+++ b/storage/innobase/fil/fil0fil.cc
@@ -1,7 +1,7 @@
/*****************************************************************************
-Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2014, 2017, MariaDB Corporation.
+Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2014, 2017, MariaDB Corporation. 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
@@ -163,7 +163,8 @@ UNIV_INTERN extern uint srv_fil_crypt_rotate_key_age;
UNIV_INTERN extern ib_mutex_t fil_crypt_threads_mutex;
/** Determine if (i) is a user tablespace id or not. */
-# define fil_is_user_tablespace_id(i) ((i) > srv_undo_tablespaces_open)
+# define fil_is_user_tablespace_id(i) (i != 0 \
+ && !srv_is_undo_tablespace(i))
/** Determine if user has explicitly disabled fsync(). */
#ifndef __WIN__
@@ -613,7 +614,8 @@ fil_node_open_file(
size_bytes = os_file_get_size(node->handle);
ut_a(size_bytes != (os_offset_t) -1);
- node->file_block_size = os_file_get_block_size(node->handle, node->name);
+ node->file_block_size = os_file_get_block_size(
+ node->handle, node->name);
space->file_block_size = node->file_block_size;
#ifdef UNIV_HOTBACKUP
@@ -723,7 +725,8 @@ add_size:
}
if (node->file_block_size == 0) {
- node->file_block_size = os_file_get_block_size(node->handle, node->name);
+ node->file_block_size = os_file_get_block_size(
+ node->handle, node->name);
space->file_block_size = node->file_block_size;
}
@@ -2362,7 +2365,7 @@ UNIV_INTERN
const char*
fil_read_first_page(
/*================*/
- os_file_t data_file, /*!< in: open data file */
+ pfs_os_file_t data_file, /*!< in: open data file */
ibool one_read_already, /*!< in: TRUE if min and max
parameters below already
contain sensible data */
@@ -3682,7 +3685,7 @@ fil_open_linked_file(
/*===============*/
const char* tablename, /*!< in: database/tablename */
char** remote_filepath,/*!< out: remote filepath */
- os_file_t* remote_file, /*!< out: remote file handle */
+ pfs_os_file_t* remote_file, /*!< out: remote file handle */
ulint atomic_writes) /*!< in: atomic writes table option
value */
{
@@ -3745,7 +3748,8 @@ fil_create_new_single_table_tablespace(
fil_encryption_t mode, /*!< in: encryption mode */
ulint key_id) /*!< in: encryption key_id */
{
- os_file_t file;
+ pfs_os_file_t file;
+
ibool ret;
dberr_t err;
byte* buf2;
@@ -6536,7 +6540,7 @@ fil_buf_block_init(
}
struct fil_iterator_t {
- os_file_t file; /*!< File handle */
+ pfs_os_file_t file; /*!< File handle */
const char* filepath; /*!< File path name */
os_offset_t start; /*!< From where to start */
os_offset_t end; /*!< Where to stop */
@@ -6809,7 +6813,7 @@ fil_tablespace_iterate(
PageCallback& callback)
{
dberr_t err;
- os_file_t file;
+ pfs_os_file_t file;
char* filepath;
ut_a(n_io_buffers > 0);
diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index a7c112aa64e..012d81380f1 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2000, 2016, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2000, 2017, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2013, 2017, MariaDB Corporation.
Copyright (c) 2008, 2009 Google Inc.
Copyright (c) 2009, Percona Inc.
@@ -12509,7 +12509,8 @@ ha_innobase::delete_table(
extension, in contrast to ::create */
normalize_table_name(norm_name, name);
- if (srv_read_only_mode) {
+ if (srv_read_only_mode
+ || srv_force_recovery >= SRV_FORCE_NO_UNDO_LOG_SCAN) {
DBUG_RETURN(HA_ERR_TABLE_READONLY);
} else if (row_is_magic_monitor_table(norm_name)
&& check_global_access(thd, PROCESS_ACL)) {
diff --git a/storage/innobase/include/buf0dblwr.h b/storage/innobase/include/buf0dblwr.h
index 5582778825c..8e1b00db83c 100644
--- a/storage/innobase/include/buf0dblwr.h
+++ b/storage/innobase/include/buf0dblwr.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1995, 2014, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, MariaDB Corporation. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
@@ -56,7 +56,7 @@ recovery, this function loads the pages from double write buffer into memory. */
void
buf_dblwr_init_or_load_pages(
/*=========================*/
- os_file_t file,
+ pfs_os_file_t file,
char* path,
bool load_corrupt_pages);
diff --git a/storage/innobase/include/fil0fil.h b/storage/innobase/include/fil0fil.h
index 28b63312087..d546bab6862 100644
--- a/storage/innobase/include/fil0fil.h
+++ b/storage/innobase/include/fil0fil.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2013, 2017, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
@@ -213,7 +213,7 @@ struct fsp_open_info {
ibool success; /*!< Has the tablespace been opened? */
const char* check_msg; /*!< fil_check_first_page() message */
ibool valid; /*!< Is the tablespace valid? */
- os_file_t file; /*!< File handle */
+ pfs_os_file_t file; /*!< File handle */
char* filepath; /*!< File path to open */
lsn_t lsn; /*!< Flushed LSN from header page */
ulint id; /*!< Space ID */
@@ -234,7 +234,7 @@ struct fil_node_t {
belongs */
char* name; /*!< path to the file */
ibool open; /*!< TRUE if file open */
- os_file_t handle; /*!< OS handle to the file, if file open */
+ pfs_os_file_t handle; /*!< OS handle to the file, if file open */
os_event_t sync_event;/*!< Condition event to group and
serialize calls to fsync;
os_event_set() and os_event_reset()
@@ -802,7 +802,7 @@ UNIV_INTERN
const char*
fil_read_first_page(
/*================*/
- os_file_t data_file, /*!< in: open data file */
+ pfs_os_file_t data_file, /*!< in: open data file */
ibool one_read_already, /*!< in: TRUE if min and max
parameters below already
contain sensible data */
@@ -1323,12 +1323,12 @@ struct PageCallback {
Called for every page in the tablespace. If the page was not
updated then its state must be set to BUF_PAGE_NOT_USED. For
compressed tables the page descriptor memory will be at offset:
- block->frame + UNIV_PAGE_SIZE;
+ block->frame + UNIV_PAGE_SIZE;
@param offset - physical offset within the file
@param block - block read from file, note it is not from the buffer pool
@retval DB_SUCCESS or error code. */
virtual dberr_t operator()(
- os_offset_t offset,
+ os_offset_t offset,
buf_block_t* block) UNIV_NOTHROW = 0;
/**
@@ -1336,7 +1336,7 @@ struct PageCallback {
to open it for the file that is being iterated over.
@param filename - then physical name of the tablespace file.
@param file - OS file handle */
- void set_file(const char* filename, os_file_t file) UNIV_NOTHROW
+ void set_file(const char* filename, pfs_os_file_t file) UNIV_NOTHROW
{
m_file = file;
m_filepath = filename;
@@ -1372,7 +1372,7 @@ struct PageCallback {
ulint m_page_size;
/** File handle to the tablespace */
- os_file_t m_file;
+ pfs_os_file_t m_file;
/** Physical file path. */
const char* m_filepath;
diff --git a/storage/innobase/include/ha0ha.h b/storage/innobase/include/ha0ha.h
index 07ab20ab995..a4ea5f6371a 100644
--- a/storage/innobase/include/ha0ha.h
+++ b/storage/innobase/include/ha0ha.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1994, 2011, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1994, 2016, 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
@@ -107,7 +107,7 @@ chosen to be a slightly bigger prime number.
@param level in: level of the mutexes in the latching order
@param n_m in: number of mutexes to protect the hash table;
must be a power of 2, or 0 */
-# define ha_create(n_c,n_m,type,level) ha_create_func(n_c,level,n_m,type)
+# define ib_create(n_c,n_m,type,level) ha_create_func(n_c,level,n_m,type)
#else /* UNIV_SYNC_DEBUG */
/** Creates a hash table.
@return own: created table
@@ -116,7 +116,7 @@ chosen to be a slightly bigger prime number.
@param level in: level of the mutexes in the latching order
@param n_m in: number of mutexes to protect the hash table;
must be a power of 2, or 0 */
-# define ha_create(n_c,n_m,type,level) ha_create_func(n_c,n_m,type)
+# define ib_create(n_c,n_m,type,level) ha_create_func(n_c,n_m,type)
#endif /* UNIV_SYNC_DEBUG */
/*************************************************************//**
diff --git a/storage/innobase/include/os0file.h b/storage/innobase/include/os0file.h
index 27803c34a0e..e2e88eee560 100644
--- a/storage/innobase/include/os0file.h
+++ b/storage/innobase/include/os0file.h
@@ -1,6 +1,6 @@
/***********************************************************************
-Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2009, Percona Inc.
Copyright (c) 2013, 2017, MariaDB Corporation.
@@ -80,6 +80,25 @@ typedef int os_file_t;
# define OS_FILE_FROM_FD(fd) fd
#endif
+/** File descriptor with optional PERFORMANCE_SCHEMA instrumentation */
+struct pfs_os_file_t
+{
+ /** The wrapped file handle */
+ os_file_t m_file;
+#ifdef UNIV_PFS_IO
+ /** PERFORMANCE_SCHEMA descriptor */
+ struct PSI_file *m_psi;
+ /** Default constructor */
+ pfs_os_file_t() : m_file(), m_psi(NULL) {}
+#endif
+ /** Implicit type conversion.
+ @return the wrapped file handle */
+ operator os_file_t() const { return m_file; }
+ /** Assignment operator.
+ @param[in] file file handle to be assigned */
+ void operator=(os_file_t file) { m_file = file; }
+};
+
/** Umask for creating files */
extern ulint os_innodb_umask;
@@ -207,6 +226,8 @@ extern mysql_pfs_key_t innodb_file_temp_key;
various file I/O operations with performance schema.
1) register_pfs_file_open_begin() and register_pfs_file_open_end() are
used to register file creation, opening, closing and renaming.
+2) register_pfs_file_rename_begin() and register_pfs_file_rename_end()
+are used to register file renaming
2) register_pfs_file_io_begin() and register_pfs_file_io_end() are
used to register actual file read, write and flush
3) register_pfs_file_close_begin() and register_pfs_file_close_end()
@@ -216,17 +237,30 @@ are used to register file deletion operations*/
do { \
locker = PSI_FILE_CALL(get_thread_file_name_locker)( \
state, key, op, name, &locker); \
- if (UNIV_LIKELY(locker != NULL)) { \
+ if (locker != NULL) { \
PSI_FILE_CALL(start_file_open_wait)( \
locker, src_file, src_line); \
} \
} while (0)
-# define register_pfs_file_open_end(locker, file) \
+# define register_pfs_file_open_end(locker, file, result) \
do { \
- if (UNIV_LIKELY(locker != NULL)) { \
- PSI_FILE_CALL(end_file_open_wait_and_bind_to_descriptor)(\
- locker, file); \
+ if (locker != NULL) { \
+ file.m_psi = PSI_FILE_CALL( \
+ end_file_open_wait)( \
+ locker, result); \
+ } \
+} while (0)
+
+# define register_pfs_file_rename_begin(state, locker, key, op, name, \
+ src_file, src_line) \
+ register_pfs_file_open_begin(state, locker, key, op, name, \
+ src_file, src_line) \
+
+# define register_pfs_file_rename_end(locker, result) \
+do { \
+ if (locker != NULL) { \
+ PSI_FILE_CALL(end_file_open_wait)(locker, result); \
} \
} while (0)
@@ -252,9 +286,9 @@ do { \
# define register_pfs_file_io_begin(state, locker, file, count, op, \
src_file, src_line) \
do { \
- locker = PSI_FILE_CALL(get_thread_file_descriptor_locker)( \
- state, file, op); \
- if (UNIV_LIKELY(locker != NULL)) { \
+ locker = PSI_FILE_CALL(get_thread_file_stream_locker)( \
+ state, file.m_psi, op); \
+ if (locker != NULL) { \
PSI_FILE_CALL(start_file_wait)( \
locker, count, src_file, src_line); \
} \
@@ -262,7 +296,7 @@ do { \
# define register_pfs_file_io_end(locker, count) \
do { \
- if (UNIV_LIKELY(locker != NULL)) { \
+ if (locker != NULL) { \
PSI_FILE_CALL(end_file_wait)(locker, count); \
} \
} while (0)
@@ -280,7 +314,9 @@ os_file_rename
os_aio
os_file_read
os_file_read_no_error_handling
+os_file_read_no_error_handling_int_fd
os_file_write
+os_file_write_int_fd
The wrapper functions have the prefix of "innodb_". */
@@ -315,11 +351,20 @@ The wrapper functions have the prefix of "innodb_". */
pfs_os_file_read_no_error_handling_func(file, buf, offset, n, \
__FILE__, __LINE__)
-# define os_file_write(name, file, buf, offset, n) \
- pfs_os_file_write_func(name, file, buf, offset, \
+# define os_file_read_no_error_handling_int_fd( \
+ file, buf, offset, n) \
+ pfs_os_file_read_no_error_handling_int_fd_func( \
+ file, buf, offset, n, __FILE__, __LINE__)
+
+# define os_file_write(name, file, buf, offset, n) \
+ pfs_os_file_write_func(name, file, buf, offset, \
n, __FILE__, __LINE__)
-# define os_file_flush(file) \
+# define os_file_write_int_fd(name, file, buf, offset, n) \
+ pfs_os_file_write_int_fd_func(name, file, buf, offset, \
+ n, __FILE__, __LINE__)
+
+# define os_file_flush(file) \
pfs_os_file_flush_func(file, __FILE__, __LINE__)
# define os_file_rename(key, oldpath, newpath) \
@@ -345,22 +390,29 @@ to original un-instrumented file I/O APIs */
os_file_create_simple_no_error_handling_func( \
name, create_mode, access, success, atomic_writes)
-# define os_file_close(file) os_file_close_func(file)
+# define os_file_close(file) \
+ os_file_close_func(file)
# define os_aio(type, is_log, mode, name, file, buf, offset, n, page_size, message1, \
message2, write_size) \
os_aio_func(type, is_log, mode, name, file, buf, offset, n, \
page_size, message1, message2, write_size)
-# define os_file_read(file, buf, offset, n) \
+# define os_file_read(file, buf, offset, n) \
os_file_read_func(file, buf, offset, n)
# define os_file_read_no_error_handling(file, buf, offset, n) \
os_file_read_no_error_handling_func(file, buf, offset, n)
+# define os_file_read_no_error_handling_int_fd( \
+ file, buf, offset, n) \
+ os_file_read_no_error_handling_func(file, buf, offset, n)
+# define os_file_write_int_fd(name, file, buf, offset, n) \
+ os_file_write_func(name, file, buf, offset, n)
# define os_file_write(name, file, buf, offset, n) \
os_file_write_func(name, file, buf, offset, n)
+
# define os_file_flush(file) os_file_flush_func(file)
# define os_file_rename(key, oldpath, newpath) \
@@ -512,7 +564,7 @@ A simple function to open or create a file.
@return own: handle to the file, not defined if error, error number
can be retrieved with os_file_get_last_error */
UNIV_INTERN
-os_file_t
+pfs_os_file_t
os_file_create_simple_no_error_handling_func(
/*=========================================*/
const char* name, /*!< in: name of the file or path as a
@@ -544,7 +596,7 @@ Opens an existing file or creates a new.
@return own: handle to the file, not defined if error, error number
can be retrieved with os_file_get_last_error */
UNIV_INTERN
-os_file_t
+pfs_os_file_t
os_file_create_func(
/*================*/
const char* name, /*!< in: name of the file or path as a
@@ -615,7 +667,7 @@ os_file_create_simple() which opens or creates a file.
@return own: handle to the file, not defined if error, error number
can be retrieved with os_file_get_last_error */
UNIV_INLINE
-os_file_t
+pfs_os_file_t
pfs_os_file_create_simple_func(
/*===========================*/
mysql_pfs_key_t key, /*!< in: Performance Schema Key */
@@ -638,7 +690,7 @@ monitor file creation/open.
@return own: handle to the file, not defined if error, error number
can be retrieved with os_file_get_last_error */
UNIV_INLINE
-os_file_t
+pfs_os_file_t
pfs_os_file_create_simple_no_error_handling_func(
/*=============================================*/
mysql_pfs_key_t key, /*!< in: Performance Schema Key */
@@ -664,7 +716,7 @@ Add instrumentation to monitor file creation/open.
@return own: handle to the file, not defined if error, error number
can be retrieved with os_file_get_last_error */
UNIV_INLINE
-os_file_t
+pfs_os_file_t
pfs_os_file_create_func(
/*====================*/
mysql_pfs_key_t key, /*!< in: Performance Schema Key */
@@ -695,7 +747,7 @@ UNIV_INLINE
ibool
pfs_os_file_close_func(
/*===================*/
- os_file_t file, /*!< in, own: handle to a file */
+ pfs_os_file_t file, /*!< in, own: handle to a file */
const char* src_file,/*!< in: file name where func invoked */
ulint src_line);/*!< in: line where the func invoked */
/*******************************************************************//**
@@ -708,7 +760,7 @@ UNIV_INLINE
ibool
pfs_os_file_read_func(
/*==================*/
- os_file_t file, /*!< in: handle to a file */
+ pfs_os_file_t file, /*!< in: handle to a file */
void* buf, /*!< in: buffer where to read */
os_offset_t offset, /*!< in: file offset where to read */
ulint n, /*!< in: number of bytes to read */
@@ -726,7 +778,7 @@ UNIV_INLINE
ibool
pfs_os_file_read_no_error_handling_func(
/*====================================*/
- os_file_t file, /*!< in: handle to a file */
+ pfs_os_file_t file, /*!< in: handle to a file */
void* buf, /*!< in: buffer where to read */
os_offset_t offset, /*!< in: file offset where to read */
ulint n, /*!< in: number of bytes to read */
@@ -748,7 +800,7 @@ pfs_os_aio_func(
ulint mode, /*!< in: OS_AIO_NORMAL etc. I/O mode */
const char* name, /*!< in: name of the file or path as a
null-terminated string */
- os_file_t file, /*!< in: handle to a file */
+ pfs_os_file_t file, /*!< in: handle to a file */
void* buf, /*!< in: buffer where to read or from which
to write */
os_offset_t offset, /*!< in: file offset where to read or write */
@@ -781,7 +833,7 @@ pfs_os_file_write_func(
/*===================*/
const char* name, /*!< in: name of the file or path as a
null-terminated string */
- os_file_t file, /*!< in: handle to a file */
+ pfs_os_file_t file, /*!< in: handle to a file */
const void* buf, /*!< in: buffer from which to write */
os_offset_t offset, /*!< in: file offset where to write */
ulint n, /*!< in: number of bytes to write */
@@ -798,7 +850,7 @@ UNIV_INLINE
ibool
pfs_os_file_flush_func(
/*===================*/
- os_file_t file, /*!< in, own: handle to a file */
+ pfs_os_file_t file, /*!< in, own: handle to a file */
const char* src_file,/*!< in: file name where func invoked */
ulint src_line);/*!< in: line where the func invoked */
@@ -869,7 +921,7 @@ UNIV_INTERN
os_offset_t
os_file_get_size(
/*=============*/
- os_file_t file) /*!< in: handle to a file */
+ pfs_os_file_t file) /*!< in: handle to a file */
MY_ATTRIBUTE((warn_unused_result));
/** Set the size of a newly created file.
@param[in] name file name
@@ -881,7 +933,7 @@ UNIV_INTERN
bool
os_file_set_size(
const char* name,
- os_file_t file,
+ pfs_os_file_t file,
os_offset_t size,
bool is_sparse = false)
MY_ATTRIBUTE((nonnull, warn_unused_result));
@@ -1122,7 +1174,7 @@ os_aio_func(
caution! */
const char* name, /*!< in: name of the file or path as a
null-terminated string */
- os_file_t file, /*!< in: handle to a file */
+ pfs_os_file_t file, /*!< in: handle to a file */
void* buf, /*!< in: buffer where to read or from which
to write */
os_offset_t offset, /*!< in: file offset where to read or write */
diff --git a/storage/innobase/include/os0file.ic b/storage/innobase/include/os0file.ic
index 6ca8b371093..2e7c12ecd79 100644
--- a/storage/innobase/include/os0file.ic
+++ b/storage/innobase/include/os0file.ic
@@ -1,7 +1,7 @@
/*****************************************************************************
-Copyright (c) 2010, 2011, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2013, SkySQL Ab. All Rights Reserved.
+Copyright (c) 2010, 2017, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2013, 2017, MariaDB Corporation.
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
@@ -35,7 +35,7 @@ os_file_create_simple() which opens or creates a file.
@return own: handle to the file, not defined if error, error number
can be retrieved with os_file_get_last_error */
UNIV_INLINE
-os_file_t
+pfs_os_file_t
pfs_os_file_create_simple_func(
/*===========================*/
mysql_pfs_key_t key, /*!< in: Performance Schema Key */
@@ -48,7 +48,7 @@ pfs_os_file_create_simple_func(
const char* src_file,/*!< in: file name where func invoked */
ulint src_line)/*!< in: line where the func invoked */
{
- os_file_t file;
+ pfs_os_file_t file;
struct PSI_file_locker* locker = NULL;
PSI_file_locker_state state;
@@ -62,8 +62,9 @@ pfs_os_file_create_simple_func(
file = os_file_create_simple_func(name, create_mode,
access_type, success);
- /* Regsiter the returning "file" value with the system */
- register_pfs_file_open_end(locker, file);
+ /* Register psi value for the file */
+ register_pfs_file_open_end(locker, file,
+ (*success == TRUE ? success : 0));
return(file);
}
@@ -77,7 +78,7 @@ monitor file creation/open.
@return own: handle to the file, not defined if error, error number
can be retrieved with os_file_get_last_error */
UNIV_INLINE
-os_file_t
+pfs_os_file_t
pfs_os_file_create_simple_no_error_handling_func(
/*=============================================*/
mysql_pfs_key_t key, /*!< in: Performance Schema Key */
@@ -94,7 +95,7 @@ pfs_os_file_create_simple_no_error_handling_func(
const char* src_file,/*!< in: file name where func invoked */
ulint src_line)/*!< in: line where the func invoked */
{
- os_file_t file;
+ pfs_os_file_t file;
struct PSI_file_locker* locker = NULL;
PSI_file_locker_state state;
@@ -108,7 +109,8 @@ pfs_os_file_create_simple_no_error_handling_func(
file = os_file_create_simple_no_error_handling_func(
name, create_mode, access_type, success, atomic_writes);
- register_pfs_file_open_end(locker, file);
+ register_pfs_file_open_end(locker, file,
+ (*success == TRUE ? success : 0));
return(file);
}
@@ -121,7 +123,7 @@ Add instrumentation to monitor file creation/open.
@return own: handle to the file, not defined if error, error number
can be retrieved with os_file_get_last_error */
UNIV_INLINE
-os_file_t
+pfs_os_file_t
pfs_os_file_create_func(
/*====================*/
mysql_pfs_key_t key, /*!< in: Performance Schema Key */
@@ -142,7 +144,7 @@ pfs_os_file_create_func(
const char* src_file,/*!< in: file name where func invoked */
ulint src_line)/*!< in: line where the func invoked */
{
- os_file_t file;
+ pfs_os_file_t file;
struct PSI_file_locker* locker = NULL;
PSI_file_locker_state state;
@@ -155,7 +157,8 @@ pfs_os_file_create_func(
file = os_file_create_func(name, create_mode, purpose, type, success, atomic_writes);
- register_pfs_file_open_end(locker, file);
+ register_pfs_file_open_end(locker, file,
+ (*success == TRUE ? success : 0));
return(file);
}
@@ -169,7 +172,7 @@ UNIV_INLINE
ibool
pfs_os_file_close_func(
/*===================*/
- os_file_t file, /*!< in, own: handle to a file */
+ pfs_os_file_t file, /*!< in, own: handle to a file */
const char* src_file,/*!< in: file name where func invoked */
ulint src_line)/*!< in: line where the func invoked */
{
@@ -203,7 +206,7 @@ pfs_os_aio_func(
ulint mode, /*!< in: OS_AIO_NORMAL etc. I/O mode */
const char* name, /*!< in: name of the file or path as a
null-terminated string */
- os_file_t file, /*!< in: handle to a file */
+ pfs_os_file_t file, /*!< in: handle to a file */
void* buf, /*!< in: buffer where to read or from which
to write */
os_offset_t offset, /*!< in: file offset where to read or write */
@@ -254,7 +257,7 @@ UNIV_INLINE
ibool
pfs_os_file_read_func(
/*==================*/
- os_file_t file, /*!< in: handle to a file */
+ pfs_os_file_t file, /*!< in: handle to a file */
void* buf, /*!< in: buffer where to read */
os_offset_t offset, /*!< in: file offset where to read */
ulint n, /*!< in: number of bytes to read */
@@ -287,7 +290,7 @@ UNIV_INLINE
ibool
pfs_os_file_read_no_error_handling_func(
/*====================================*/
- os_file_t file, /*!< in: handle to a file */
+ pfs_os_file_t file, /*!< in: handle to a file */
void* buf, /*!< in: buffer where to read */
os_offset_t offset, /*!< in: file offset where to read */
ulint n, /*!< in: number of bytes to read */
@@ -308,6 +311,42 @@ pfs_os_file_read_no_error_handling_func(
return(result);
}
+/** NOTE! Please use the corresponding macro
+os_file_read_no_error_handling_int_fd(), not directly this function!
+This is the performance schema instrumented wrapper function for
+os_file_read_no_error_handling_int_fd_func() which requests a
+synchronous read operation.
+@return TRUE if request was successful, FALSE if fail */
+UNIV_INLINE
+ibool
+pfs_os_file_read_no_error_handling_int_fd_func(
+ int file, /*!< in: handle to a file */
+ void* buf, /*!< in: buffer where to read */
+ os_offset_t offset, /*!< in: file offset where to read */
+ ulint n, /*!< in: number of bytes to read */
+ const char* src_file,/*!< in: file name where func invoked */
+ ulint src_line)/*!< in: line where the func invoked */
+{
+ PSI_file_locker_state state;
+ struct PSI_file_locker* locker;
+
+ locker = PSI_FILE_CALL(get_thread_file_descriptor_locker)(
+ &state, file, PSI_FILE_READ);
+ if (locker != NULL) {
+ PSI_FILE_CALL(start_file_wait)(
+ locker, n,
+ __FILE__, __LINE__);
+ }
+ ibool result = os_file_read_no_error_handling_func(
+ OS_FILE_FROM_FD(file), buf, offset, n);
+
+ if (locker != NULL) {
+ PSI_FILE_CALL(end_file_wait)(locker, n);
+ }
+
+ return(result);
+}
+
/*******************************************************************//**
NOTE! Please use the corresponding macro os_file_write(), not directly
this function!
@@ -320,7 +359,7 @@ pfs_os_file_write_func(
/*===================*/
const char* name, /*!< in: name of the file or path as a
null-terminated string */
- os_file_t file, /*!< in: handle to a file */
+ pfs_os_file_t file, /*!< in: handle to a file */
const void* buf, /*!< in: buffer from which to write */
os_offset_t offset, /*!< in: file offset where to write */
ulint n, /*!< in: number of bytes to write */
@@ -341,6 +380,43 @@ pfs_os_file_write_func(
return(result);
}
+/** NOTE! Please use the corresponding macro os_file_write(), not
+directly this function!
+This is the performance schema instrumented wrapper function for
+os_file_write() which requests a synchronous write operation.
+@return TRUE if request was successful, FALSE if fail */
+UNIV_INLINE
+ibool
+pfs_os_file_write_int_fd_func(
+ const char* name, /*!< in: name of the file or path as a
+ null-terminated string */
+ int file, /*!< in: handle to a file */
+ const void* buf, /*!< in: buffer from which to write */
+ os_offset_t offset, /*!< in: file offset where to write */
+ ulint n, /*!< in: number of bytes to write */
+ const char* src_file,/*!< in: file name where func invoked */
+ ulint src_line)/*!< in: line where the func invoked */
+{
+ PSI_file_locker_state state;
+ struct PSI_file_locker* locker = NULL;
+
+ locker = PSI_FILE_CALL(get_thread_file_descriptor_locker)(
+ &state, file, PSI_FILE_WRITE);
+ if (locker != NULL) {
+ PSI_FILE_CALL(start_file_wait)(
+ locker, n,
+ __FILE__, __LINE__);
+ }
+ ibool result = os_file_write_func(
+ name, OS_FILE_FROM_FD(file), buf, offset, n);
+
+ if (locker != NULL) {
+ PSI_FILE_CALL(end_file_wait)(locker, n);
+ }
+
+ return(result);
+}
+
/***********************************************************************//**
NOTE! Please use the corresponding macro os_file_flush(), not directly
this function!
@@ -351,7 +427,7 @@ UNIV_INLINE
ibool
pfs_os_file_flush_func(
/*===================*/
- os_file_t file, /*!< in, own: handle to a file */
+ pfs_os_file_t file, /*!< in, own: handle to a file */
const char* src_file,/*!< in: file name where func invoked */
ulint src_line)/*!< in: line where the func invoked */
{
@@ -389,12 +465,12 @@ pfs_os_file_rename_func(
struct PSI_file_locker* locker = NULL;
PSI_file_locker_state state;
- register_pfs_file_open_begin(&state, locker, key, PSI_FILE_RENAME, newpath,
+ register_pfs_file_rename_begin(&state, locker, key, PSI_FILE_RENAME, newpath,
src_file, src_line);
result = os_file_rename_func(oldpath, newpath);
- register_pfs_file_open_end(locker, 0);
+ register_pfs_file_rename_end(locker, 0);
return(result);
}
diff --git a/storage/innobase/include/srv0srv.h b/storage/innobase/include/srv0srv.h
index 522eff23a0d..79cf9cdd2ab 100644
--- a/storage/innobase/include/srv0srv.h
+++ b/storage/innobase/include/srv0srv.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1995, 2016, Oracle and/or its affiliates. All rights reserved.
+Copyright (c) 1995, 2017, Oracle and/or its affiliates. All rights reserved.
Copyright (c) 2008, 2009, Google Inc.
Copyright (c) 2009, Percona Inc.
Copyright (c) 2013, 2017, MariaDB Corporation.
@@ -904,6 +904,13 @@ UNIV_INTERN
void
srv_purge_wakeup();
+/** Check whether given space id is undo tablespace id
+@param[in] space_id space id to check
+@return true if it is undo tablespace else false. */
+bool
+srv_is_undo_tablespace(
+ ulint space_id);
+
/** Status variables to be passed to MySQL */
struct export_var_t{
ulint innodb_data_pending_reads; /*!< Pending reads */
diff --git a/storage/innobase/include/srv0start.h b/storage/innobase/include/srv0start.h
index d2e70f969b7..bb4ab85e836 100644
--- a/storage/innobase/include/srv0start.h
+++ b/storage/innobase/include/srv0start.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1995, 2017, 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
@@ -140,6 +140,8 @@ extern ibool srv_startup_is_before_trx_rollback_phase;
/** TRUE if a raw partition is in use */
extern ibool srv_start_raw_disk_in_use;
+/** Undo tablespaces starts with space_id. */
+extern ulint srv_undo_space_id_start;
/** Shutdown state */
enum srv_shutdown_state {
diff --git a/storage/innobase/include/trx0xa.h b/storage/innobase/include/trx0xa.h
index 7caddfb7ba4..4d5adc68dcd 100644
--- a/storage/innobase/include/trx0xa.h
+++ b/storage/innobase/include/trx0xa.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1995, 2009, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1995, 2016, 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
@@ -24,6 +24,8 @@ this program; if not, write to the Free Software Foundation, Inc.,
#ifndef XA_H
#define XA_H
+#include "handler.h"
+
/*
* Transaction branch identification: XID and NULLXID:
*/
@@ -35,17 +37,6 @@ this program; if not, write to the Free Software Foundation, Inc.,
#define MAXGTRIDSIZE 64 /*!< maximum size in bytes of gtrid */
#define MAXBQUALSIZE 64 /*!< maximum size in bytes of bqual */
-/** X/Open XA distributed transaction identifier */
-struct xid_t {
- long formatID; /*!< format identifier; -1
- means that the XID is null */
- long gtrid_length; /*!< value from 1 through 64 */
- long bqual_length; /*!< value from 1 through 64 */
- char data[XIDDATASIZE]; /*!< distributed transaction
- identifier */
-};
-/** X/Open XA distributed transaction identifier */
-typedef struct xid_t XID;
#endif
/** X/Open XA distributed transaction status codes */
/* @{ */
diff --git a/storage/innobase/include/univ.i b/storage/innobase/include/univ.i
index 288fea6670f..1cc89ae503c 100644
--- a/storage/innobase/include/univ.i
+++ b/storage/innobase/include/univ.i
@@ -45,7 +45,7 @@ Created 1/20/1994 Heikki Tuuri
#define INNODB_VERSION_MAJOR 5
#define INNODB_VERSION_MINOR 6
-#define INNODB_VERSION_BUGFIX 35
+#define INNODB_VERSION_BUGFIX 36
/* The following is the InnoDB version as shown in
SELECT plugin_version FROM information_schema.plugins;
@@ -134,14 +134,8 @@ HAVE_PSI_INTERFACE is defined. */
#if defined HAVE_PSI_INTERFACE && !defined UNIV_HOTBACKUP
# define UNIV_PFS_MUTEX
# define UNIV_PFS_RWLOCK
-/* For I/O instrumentation, performance schema rely
-on a native descriptor to identify the file, this
-descriptor could conflict with our OS level descriptor.
-Disable IO instrumentation on Windows until this is
-resolved */
-# ifndef __WIN__
-# define UNIV_PFS_IO
-# endif
+
+# define UNIV_PFS_IO
# define UNIV_PFS_THREAD
/* There are mutexes/rwlocks that we want to exclude from
diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc
index ac7b858ed08..2dc2d419e3f 100644
--- a/storage/innobase/log/log0recv.cc
+++ b/storage/innobase/log/log0recv.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1997, 2016, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1997, 2017, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2012, Facebook Inc.
Copyright (c) 2013, 2017, MariaDB Corporation.
@@ -333,6 +333,7 @@ DECLARE_THREAD(recv_writer_thread)(
/*!< in: a dummy parameter required by
os_thread_create */
{
+ my_thread_init();
ut_ad(!srv_read_only_mode);
#ifdef UNIV_PFS_THREAD
@@ -366,6 +367,7 @@ DECLARE_THREAD(recv_writer_thread)(
recv_writer_thread_active = false;
+ my_thread_end();
/* 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. */
diff --git a/storage/innobase/os/os0file.cc b/storage/innobase/os/os0file.cc
index d1ef91d72bb..5a945aae7bc 100644
--- a/storage/innobase/os/os0file.cc
+++ b/storage/innobase/os/os0file.cc
@@ -1,6 +1,6 @@
/***********************************************************************
-Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2009, Percona Inc.
Copyright (c) 2013, 2017, MariaDB Corporation.
@@ -209,7 +209,7 @@ struct os_aio_slot_t{
ulint page_size; /*!< UNIV_PAGE_SIZE or zip_size */
os_offset_t offset; /*!< file offset in bytes */
- os_file_t file; /*!< file where to read or write */
+ pfs_os_file_t file; /*!< file where to read or write */
const char* name; /*!< file name or path */
ibool io_already_done;/*!< used only in simulated aio:
TRUE if the physical i/o already
@@ -1462,7 +1462,7 @@ A simple function to open or create a file.
@return own: handle to the file, not defined if error, error number
can be retrieved with os_file_get_last_error */
UNIV_INTERN
-os_file_t
+pfs_os_file_t
os_file_create_simple_no_error_handling_func(
/*=========================================*/
const char* name, /*!< in: name of the file or path as a
@@ -1476,7 +1476,7 @@ os_file_create_simple_no_error_handling_func(
ulint atomic_writes) /*! in: atomic writes table option
value */
{
- os_file_t file;
+ pfs_os_file_t file;
atomic_writes_t awrites = (atomic_writes_t) atomic_writes;
*success = FALSE;
@@ -1485,7 +1485,6 @@ os_file_create_simple_no_error_handling_func(
DWORD create_flag;
DWORD attributes = 0;
DWORD share_mode = FILE_SHARE_READ;
-
ut_a(name);
ut_a(!(create_mode & OS_FILE_ON_ERROR_SILENT));
@@ -1502,8 +1501,8 @@ os_file_create_simple_no_error_handling_func(
ib_logf(IB_LOG_LEVEL_ERROR,
"Unknown file create mode (%lu) for file '%s'",
create_mode, name);
-
- return((os_file_t) -1);
+ file = INVALID_HANDLE_VALUE;
+ return(file);
}
if (access_type == OS_FILE_READ_ONLY) {
@@ -1526,8 +1525,8 @@ os_file_create_simple_no_error_handling_func(
ib_logf(IB_LOG_LEVEL_ERROR,
"Unknown file access type (%lu) for file '%s'",
access_type, name);
-
- return((os_file_t) -1);
+ file = INVALID_HANDLE_VALUE;
+ return(file);
}
file = CreateFile((LPCTSTR) name,
@@ -1555,11 +1554,10 @@ os_file_create_simple_no_error_handling_func(
}
}
- *success = (file != INVALID_HANDLE_VALUE);
+ *success = file != INVALID_HANDLE_VALUE;
#else /* __WIN__ */
int create_flag;
const char* mode_str = NULL;
-
ut_a(name);
if (create_mode != OS_FILE_OPEN && create_mode != OS_FILE_OPEN_RAW)
WAIT_ALLOW_WRITES();
@@ -1603,13 +1601,13 @@ os_file_create_simple_no_error_handling_func(
ib_logf(IB_LOG_LEVEL_ERROR,
"Unknown file create mode (%lu) for file '%s'",
create_mode, name);
-
- return((os_file_t) -1);
+ file = -1;
+ return(file);
}
- file = ::open(name, create_flag, os_innodb_umask);
+ file = open(name, create_flag, os_innodb_umask);
- *success = file == -1 ? FALSE : TRUE;
+ *success = file != -1;
/* This function is always called for data files, we should disable
OS caching (O_DIRECT) here as we do in os_file_create_func(), so
@@ -1619,13 +1617,13 @@ os_file_create_simple_no_error_handling_func(
&& (srv_unix_file_flush_method == SRV_UNIX_O_DIRECT
|| srv_unix_file_flush_method == SRV_UNIX_O_DIRECT_NO_FSYNC)) {
- os_file_set_nocache(file, name, mode_str);
+ os_file_set_nocache(file, name, mode_str);
}
#ifdef USE_FILE_LOCK
if (!srv_read_only_mode
&& *success
- && (access_type == OS_FILE_READ_WRITE)
+ && access_type == OS_FILE_READ_WRITE
&& os_file_lock(file, name)) {
*success = FALSE;
@@ -1723,7 +1721,7 @@ Opens an existing file or creates a new.
@return own: handle to the file, not defined if error, error number
can be retrieved with os_file_get_last_error */
UNIV_INTERN
-os_file_t
+pfs_os_file_t
os_file_create_func(
/*================*/
const char* name, /*!< in: name of the file or path as a
@@ -1741,7 +1739,7 @@ os_file_create_func(
ulint atomic_writes) /*! in: atomic writes table option
value */
{
- os_file_t file;
+ pfs_os_file_t file;
ibool retry;
ibool on_error_no_exit;
ibool on_error_silent;
@@ -1752,14 +1750,16 @@ os_file_create_func(
"ib_create_table_fail_disk_full",
*success = FALSE;
SetLastError(ERROR_DISK_FULL);
- return((os_file_t) -1);
+ file = INVALID_HANDLE_VALUE;
+ return(file);
);
#else /* __WIN__ */
DBUG_EXECUTE_IF(
"ib_create_table_fail_disk_full",
*success = FALSE;
errno = ENOSPC;
- return((os_file_t) -1);
+ file = -1;
+ return(file);
);
#endif /* __WIN__ */
@@ -1810,7 +1810,8 @@ os_file_create_func(
"Unknown file create mode (%lu) for file '%s'",
create_mode, name);
- return((os_file_t) -1);
+ file = INVALID_HANDLE_VALUE;
+ return(file);
}
DWORD attributes = 0;
@@ -1835,8 +1836,8 @@ os_file_create_func(
ib_logf(IB_LOG_LEVEL_ERROR,
"Unknown purpose flag (%lu) while opening file '%s'",
purpose, name);
-
- return((os_file_t)(-1));
+ file = INVALID_HANDLE_VALUE;
+ return(file);
}
#ifdef UNIV_NON_BUFFERED_IO
@@ -1948,7 +1949,8 @@ os_file_create_func(
"Unknown file create mode (%lu) for file '%s'",
create_mode, name);
- return((os_file_t) -1);
+ file = -1;
+ return(file);
}
ut_a(type == OS_LOG_FILE || type == OS_DATA_FILE);
@@ -1968,7 +1970,7 @@ os_file_create_func(
#endif /* O_SYNC */
do {
- file = ::open(name, create_flag, os_innodb_umask);
+ file = open(name, create_flag, os_innodb_umask);
if (file == -1) {
const char* operation;
@@ -1993,13 +1995,13 @@ os_file_create_func(
} while (retry);
/* We disable OS caching (O_DIRECT) only on data files */
- if (!srv_read_only_mode
- && *success
- && type != OS_LOG_FILE
- && (srv_unix_file_flush_method == SRV_UNIX_O_DIRECT
- || srv_unix_file_flush_method == SRV_UNIX_O_DIRECT_NO_FSYNC)) {
+ if (!srv_read_only_mode
+ && *success
+ && type != OS_LOG_FILE
+ && (srv_unix_file_flush_method == SRV_UNIX_O_DIRECT
+ || srv_unix_file_flush_method == SRV_UNIX_O_DIRECT_NO_FSYNC)) {
- os_file_set_nocache(file, name, mode_str);
+ os_file_set_nocache(file, name, mode_str);
}
#ifdef USE_FILE_LOCK
@@ -2317,7 +2319,7 @@ UNIV_INTERN
os_offset_t
os_file_get_size(
/*=============*/
- os_file_t file) /*!< in: handle to a file */
+ pfs_os_file_t file) /*!< in: handle to a file */
{
#ifdef __WIN__
os_offset_t offset;
@@ -2335,6 +2337,7 @@ os_file_get_size(
return(offset);
#else
return((os_offset_t) lseek(file, 0, SEEK_END));
+
#endif /* __WIN__ */
}
@@ -2348,7 +2351,7 @@ UNIV_INTERN
bool
os_file_set_size(
const char* name,
- os_file_t file,
+ pfs_os_file_t file,
os_offset_t size,
bool is_sparse)
{
@@ -4368,7 +4371,7 @@ os_aio_array_reserve_slot(
the aio operation */
void* message2,/*!< in: message to be passed along with
the aio operation */
- os_file_t file, /*!< in: file handle */
+ pfs_os_file_t file, /*!< in: file handle */
const char* name, /*!< in: name of the file or path as a
null-terminated string */
void* buf, /*!< in: buffer where to read or from which
@@ -4744,7 +4747,7 @@ os_aio_func(
caution! */
const char* name, /*!< in: name of the file or path as a
null-terminated string */
- os_file_t file, /*!< in: handle to a file */
+ pfs_os_file_t file, /*!< in: handle to a file */
void* buf, /*!< in: buffer where to read or from which
to write */
os_offset_t offset, /*!< in: file offset where to read or write */
@@ -4776,7 +4779,6 @@ os_aio_func(
ulint dummy_type;
#endif /* WIN_ASYNC_IO */
ulint wake_later;
-
ut_ad(buf);
ut_ad(n > 0);
ut_ad(n % OS_FILE_LOG_BLOCK_SIZE == 0);
@@ -4886,7 +4888,6 @@ try_again:
#ifdef WIN_ASYNC_IO
ret = ReadFile(file, buf, (DWORD) n, &len,
&(slot->control));
-
#elif defined(LINUX_NATIVE_AIO)
if (!os_aio_linux_dispatch(array, slot)) {
goto err_exit;
@@ -4909,7 +4910,6 @@ try_again:
buffer = buf;
ret = WriteFile(file, buffer, (DWORD) n, &len,
&(slot->control));
-
#elif defined(LINUX_NATIVE_AIO)
if (!os_aio_linux_dispatch(array, slot)) {
goto err_exit;
@@ -5063,8 +5063,7 @@ os_aio_windows_handle(
srv_set_io_thread_op_info(
orig_seg, "get windows aio return value");
}
-
- ret = GetOverlappedResult(slot->file, &(slot->control), &len, TRUE);
+ ret = GetOverlappedResult(slot->file, &slot->control, &len, TRUE);
*message1 = slot->message1;
*message2 = slot->message2;
@@ -5101,7 +5100,8 @@ os_aio_windows_handle(
and os_file_write APIs, need to register with
performance schema explicitly here. */
struct PSI_file_locker* locker = NULL;
- register_pfs_file_io_begin(locker, slot->file, slot->len,
+ PSI_file_locker_state state;
+ register_pfs_file_io_begin(&state, locker, slot->file, slot->len,
(slot->type == OS_FILE_WRITE)
? PSI_FILE_WRITE
: PSI_FILE_READ,
@@ -5110,8 +5110,8 @@ os_aio_windows_handle(
ut_a((slot->len & 0xFFFFFFFFUL) == slot->len);
- switch (slot->type) {
- case OS_FILE_WRITE:
+ switch (slot->type) {
+ case OS_FILE_WRITE:
ret = WriteFile(slot->file, slot->buf,
(DWORD) slot->len, &len,
&(slot->control));
@@ -5120,7 +5120,6 @@ os_aio_windows_handle(
ret = ReadFile(slot->file, slot->buf,
(DWORD) slot->len, &len,
&(slot->control));
-
break;
default:
ut_error;
@@ -5136,7 +5135,6 @@ os_aio_windows_handle(
file where we also use async i/o: in Windows
we must use the same wait mechanism as for
async i/o */
-
ret = GetOverlappedResult(slot->file,
&(slot->control),
&len, TRUE);
@@ -5607,7 +5605,6 @@ consecutive_loop:
os_aio_slot_t* slot;
slot = os_aio_array_get_nth_slot(array, i + segment * n);
-
if (slot->reserved
&& slot != aio_slot
&& slot->offset == aio_slot->offset + aio_slot->len
@@ -6161,7 +6158,9 @@ os_file_trim(
#ifdef __linux__
#if defined(HAVE_FALLOC_PUNCH_HOLE_AND_KEEP_SIZE)
- int ret = fallocate(slot->file, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, off, trim_len);
+ int ret = fallocate(slot->file,
+ FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
+ off, trim_len);
if (ret) {
/* After first failure do not try to trim again */
diff --git a/storage/innobase/row/row0log.cc b/storage/innobase/row/row0log.cc
index 65690d7038c..88398c20342 100644
--- a/storage/innobase/row/row0log.cc
+++ b/storage/innobase/row/row0log.cc
@@ -368,9 +368,9 @@ row_log_online_op(
goto err_exit;
}
- ret = os_file_write(
+ ret = os_file_write_int_fd(
"(modification log)",
- OS_FILE_FROM_FD(log->fd),
+ log->fd,
log->tail.block, byte_offset, srv_sort_buf_size);
log->tail.blocks++;
if (!ret) {
@@ -484,9 +484,9 @@ row_log_table_close_func(
goto err_exit;
}
- ret = os_file_write(
+ ret = os_file_write_int_fd(
"(modification log)",
- OS_FILE_FROM_FD(log->fd),
+ log->fd,
log->tail.block, byte_offset, srv_sort_buf_size);
log->tail.blocks++;
if (!ret) {
@@ -2622,11 +2622,10 @@ all_done:
goto func_exit;
}
- success = os_file_read_no_error_handling(
- OS_FILE_FROM_FD(index->online_log->fd),
+ success = os_file_read_no_error_handling_int_fd(
+ index->online_log->fd,
index->online_log->head.block, ofs,
srv_sort_buf_size);
-
if (!success) {
fprintf(stderr, "InnoDB: unable to read temporary file"
" for table %s\n", index->table_name);
@@ -3452,8 +3451,8 @@ all_done:
goto func_exit;
}
- success = os_file_read_no_error_handling(
- OS_FILE_FROM_FD(index->online_log->fd),
+ success = os_file_read_no_error_handling_int_fd(
+ index->online_log->fd,
index->online_log->head.block, ofs,
srv_sort_buf_size);
diff --git a/storage/innobase/row/row0merge.cc b/storage/innobase/row/row0merge.cc
index 433c2eb7154..9cd79bdd523 100644
--- a/storage/innobase/row/row0merge.cc
+++ b/storage/innobase/row/row0merge.cc
@@ -960,8 +960,8 @@ row_merge_read(
}
#endif /* UNIV_DEBUG */
- success = os_file_read_no_error_handling(OS_FILE_FROM_FD(fd), buf,
- ofs, srv_sort_buf_size);
+ success = os_file_read_no_error_handling_int_fd(fd, buf,
+ ofs, srv_sort_buf_size);
/* For encrypted tables, decrypt data after reading and copy data */
if (crypt_data && crypt_buf) {
@@ -1016,7 +1016,7 @@ row_merge_write(
mach_write_to_4((byte *)out_buf, 0);
}
- ret = os_file_write("(merge)", OS_FILE_FROM_FD(fd), out_buf, ofs, buf_len);
+ ret = os_file_write_int_fd("(merge)", fd, buf, ofs, buf_len);
#ifdef UNIV_DEBUG
if (row_merge_print_block_write) {
@@ -3425,14 +3425,21 @@ row_merge_file_create_low(
performance schema */
struct PSI_file_locker* locker = NULL;
PSI_file_locker_state state;
- register_pfs_file_open_begin(&state, locker, innodb_file_temp_key,
- PSI_FILE_OPEN,
- "Innodb Merge Temp File",
- __FILE__, __LINE__);
+ locker = PSI_FILE_CALL(get_thread_file_name_locker)(
+ &state, innodb_file_temp_key, PSI_FILE_OPEN,
+ "Innodb Merge Temp File", &locker);
+ if (locker != NULL) {
+ PSI_FILE_CALL(start_file_open_wait)(locker,
+ __FILE__,
+ __LINE__);
+ }
#endif
fd = innobase_mysql_tmpfile(path);
#ifdef UNIV_PFS_IO
- register_pfs_file_open_end(locker, fd);
+ if (locker != NULL) {
+ PSI_FILE_CALL(end_file_open_wait_and_bind_to_descriptor)(
+ locker, fd);
+ }
#endif
if (fd < 0) {
@@ -3479,15 +3486,20 @@ row_merge_file_destroy_low(
#ifdef UNIV_PFS_IO
struct PSI_file_locker* locker = NULL;
PSI_file_locker_state state;
- register_pfs_file_io_begin(&state, locker,
- fd, 0, PSI_FILE_CLOSE,
- __FILE__, __LINE__);
+ locker = PSI_FILE_CALL(get_thread_file_descriptor_locker)(
+ &state, fd, PSI_FILE_CLOSE);
+ if (locker != NULL) {
+ PSI_FILE_CALL(start_file_wait)(
+ locker, 0, __FILE__, __LINE__);
+ }
#endif
if (fd >= 0) {
close(fd);
}
#ifdef UNIV_PFS_IO
- register_pfs_file_io_end(locker, 0);
+ if (locker != NULL) {
+ PSI_FILE_CALL(end_file_wait)(locker, 0);
+ }
#endif
}
/*********************************************************************//**
diff --git a/storage/innobase/row/row0sel.cc b/storage/innobase/row/row0sel.cc
index 10b071c048b..1b57e0d56fd 100644
--- a/storage/innobase/row/row0sel.cc
+++ b/storage/innobase/row/row0sel.cc
@@ -2748,27 +2748,32 @@ row_sel_field_store_in_mysql_format_func(
# define row_sel_store_mysql_field(m,p,r,i,o,f,t) \
row_sel_store_mysql_field_func(m,p,r,o,f,t)
#endif /* UNIV_DEBUG */
-/**************************************************************//**
-Convert a field in the Innobase format to a field in the MySQL format. */
+/** Convert a field in the Innobase format to a field in the MySQL format.
+@param[out] mysql_rec record in the MySQL format
+@param[in,out] prebuilt prebuilt struct
+@param[in] rec InnoDB record; must be protected
+ by a page latch
+@param[in] index index of rec
+@param[in] offsets array returned by rec_get_offsets()
+@param[in] field_no templ->rec_field_no or
+ templ->clust_rec_field_no
+ or templ->icp_rec_field_no
+ or sec field no if clust_templ_for_sec
+ is TRUE
+@param[in] templ row template
+*/
static MY_ATTRIBUTE((warn_unused_result))
ibool
row_sel_store_mysql_field_func(
-/*===========================*/
- byte* mysql_rec, /*!< out: record in the
- MySQL format */
- row_prebuilt_t* prebuilt, /*!< in/out: prebuilt struct */
- const rec_t* rec, /*!< in: InnoDB record;
- must be protected by
- a page latch */
+ byte* mysql_rec,
+ row_prebuilt_t* prebuilt,
+ const rec_t* rec,
#ifdef UNIV_DEBUG
- const dict_index_t* index, /*!< in: index of rec */
+ const dict_index_t* index,
#endif
- const ulint* offsets, /*!< in: array returned by
- rec_get_offsets() */
- ulint field_no, /*!< in: templ->rec_field_no or
- templ->clust_rec_field_no or
- templ->icp_rec_field_no */
- const mysql_row_templ_t*templ) /*!< in: row template */
+ const ulint* offsets,
+ ulint field_no,
+ const mysql_row_templ_t*templ)
{
const byte* data;
ulint len;
@@ -2894,30 +2899,35 @@ row_sel_store_mysql_field_func(
return(TRUE);
}
-/**************************************************************//**
-Convert a row in the Innobase format to a row in the MySQL format.
+/** Convert a row in the Innobase format to a row in the MySQL format.
Note that the template in prebuilt may advise us to copy only a few
columns to mysql_rec, other columns are left blank. All columns may not
be needed in the query.
+@param[out] mysql_rec row in the MySQL format
+@param[in] prebuilt prebuilt structure
+@param[in] rec Innobase record in the index
+ which was described in prebuilt's
+ template, or in the clustered index;
+ must be protected by a page latch
+@param[in] rec_clust TRUE if the rec in the clustered index
+@param[in] index index of rec
+@param[in] offsets array returned by rec_get_offsets(rec)
+@param[in] clust_templ_for_sec TRUE if rec belongs to secondary index
+ but the prebuilt->template is in
+ clustered index format and it is
+ used only for end range comparison
@return TRUE on success, FALSE if not all columns could be retrieved */
static MY_ATTRIBUTE((warn_unused_result))
ibool
row_sel_store_mysql_rec(
-/*====================*/
- byte* mysql_rec, /*!< out: row in the MySQL format */
- row_prebuilt_t* prebuilt, /*!< in: prebuilt struct */
- const rec_t* rec, /*!< in: Innobase record in the index
- which was described in prebuilt's
- template, or in the clustered index;
- must be protected by a page latch */
- ibool rec_clust, /*!< in: TRUE if rec is in the
- clustered index instead of
- prebuilt->index */
- const dict_index_t* index, /*!< in: index of rec */
- const ulint* offsets) /*!< in: array returned by
- rec_get_offsets(rec) */
+ byte* mysql_rec,
+ row_prebuilt_t* prebuilt,
+ const rec_t* rec,
+ ibool rec_clust,
+ const dict_index_t* index,
+ const ulint* offsets)
{
- ulint i;
+ ulint i;
ut_ad(rec_clust || index == prebuilt->index);
ut_ad(!rec_clust || dict_index_is_clust(index));
@@ -3668,7 +3678,7 @@ row_search_for_mysql(
trx_t* trx = prebuilt->trx;
dict_index_t* clust_index;
que_thr_t* thr;
- const rec_t* rec;
+ const rec_t* rec = NULL;
const rec_t* result_rec = NULL;
const rec_t* clust_rec;
dberr_t err = DB_SUCCESS;
@@ -3970,7 +3980,8 @@ row_search_for_mysql(
if (!row_sel_store_mysql_rec(
buf, prebuilt,
- rec, FALSE, index, offsets)) {
+ rec, FALSE, index,
+ offsets)) {
/* Only fresh inserts may contain
incomplete externally stored
columns. Pretend that such
diff --git a/storage/innobase/srv/srv0srv.cc b/storage/innobase/srv/srv0srv.cc
index 99ffc470aa0..94d4761775a 100644
--- a/storage/innobase/srv/srv0srv.cc
+++ b/storage/innobase/srv/srv0srv.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2008, 2009 Google Inc.
Copyright (c) 2009, Percona Inc.
Copyright (c) 2013, 2017, MariaDB Corporation.
@@ -2481,6 +2481,8 @@ DECLARE_THREAD(srv_master_thread)(
/*!< in: a dummy parameter required by
os_thread_create */
{
+ my_thread_init();
+
srv_slot_t* slot;
ulint old_activity_count = srv_get_activity_count();
ib_time_t last_print_time;
@@ -2542,6 +2544,7 @@ suspend_thread:
srv_resume_thread(slot);
if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) {
+ my_thread_end();
os_thread_exit(NULL);
}
@@ -2624,6 +2627,8 @@ DECLARE_THREAD(srv_worker_thread)(
void* arg MY_ATTRIBUTE((unused))) /*!< in: a dummy parameter
required by os_thread_create */
{
+ my_thread_init();
+
srv_slot_t* slot;
ut_ad(!srv_read_only_mode);
@@ -2681,6 +2686,7 @@ DECLARE_THREAD(srv_worker_thread)(
os_thread_pf(os_thread_get_curr_id()));
#endif /* UNIV_DEBUG_THREAD_CREATION */
+ my_thread_end();
/* 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. */
os_thread_exit(NULL);
@@ -2847,6 +2853,8 @@ DECLARE_THREAD(srv_purge_coordinator_thread)(
void* arg MY_ATTRIBUTE((unused))) /*!< in: a dummy parameter
required by os_thread_create */
{
+ my_thread_init();
+
srv_slot_t* slot;
ulint n_total_purged = ULINT_UNDEFINED;
@@ -2953,6 +2961,7 @@ DECLARE_THREAD(srv_purge_coordinator_thread)(
srv_release_threads(SRV_WORKER, srv_n_purge_threads - 1);
}
+ my_thread_end();
/* 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. */
os_thread_exit(NULL);
@@ -3018,3 +3027,19 @@ srv_purge_wakeup()
}
}
}
+
+/** Check whether given space id is undo tablespace id
+@param[in] space_id space id to check
+@return true if it is undo tablespace else false. */
+bool
+srv_is_undo_tablespace(
+ ulint space_id)
+{
+ if (srv_undo_space_id_start == 0) {
+ return (false);
+ }
+
+ return(space_id >= srv_undo_space_id_start
+ && space_id < (srv_undo_space_id_start
+ + srv_undo_tablespaces_open));
+}
diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc
index 1993bb76e57..f3304c5dad8 100644
--- a/storage/innobase/srv/srv0start.cc
+++ b/storage/innobase/srv/srv0start.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
+Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved.
Copyright (c) 2008, Google Inc.
Copyright (c) 2009, Percona Inc.
Copyright (c) 2013, 2017, MariaDB Corporation.
@@ -118,6 +118,9 @@ UNIV_INTERN ibool srv_have_fullfsync = FALSE;
/** TRUE if a raw partition is in use */
UNIV_INTERN ibool srv_start_raw_disk_in_use = FALSE;
+/** UNDO tablespaces starts with space id. */
+ulint srv_undo_space_id_start;
+
/** TRUE if the server is being started, before rolling back any
incomplete transactions */
UNIV_INTERN ibool srv_startup_is_before_trx_rollback_phase = FALSE;
@@ -137,7 +140,7 @@ SRV_SHUTDOWN_CLEANUP and then to SRV_SHUTDOWN_LAST_PHASE, and so on */
UNIV_INTERN enum srv_shutdown_state srv_shutdown_state = SRV_SHUTDOWN_NONE;
/** Files comprising the system tablespace */
-static os_file_t files[1000];
+static pfs_os_file_t files[1000];
/** io_handler_thread parameters for thread identification */
static ulint n[SRV_MAX_N_IO_THREADS + 6];
@@ -554,7 +557,7 @@ static MY_ATTRIBUTE((nonnull, warn_unused_result))
dberr_t
create_log_file(
/*============*/
- os_file_t* file, /*!< out: file handle */
+ pfs_os_file_t* file, /*!< out: file handle */
const char* name) /*!< in: log file name */
{
ibool ret;
@@ -762,7 +765,7 @@ static MY_ATTRIBUTE((nonnull, warn_unused_result))
dberr_t
open_log_file(
/*==========*/
- os_file_t* file, /*!< out: file handle */
+ pfs_os_file_t* file, /*!< out: file handle */
const char* name, /*!< in: log file name */
os_offset_t* size) /*!< out: file size */
{
@@ -879,7 +882,7 @@ open_or_create_data_files(
&& os_file_get_last_error(false)
!= OS_FILE_ALREADY_EXISTS
#ifdef UNIV_AIX
- /* AIX 5.1 after security patch ML7 may have
+ /* AIX 5.1 after security patch ML7 may have
errno set to 0 here, which causes our
function to return 100; work around that
AIX problem */
@@ -1185,7 +1188,7 @@ srv_undo_tablespace_create(
const char* name, /*!< in: tablespace name */
ulint size) /*!< in: tablespace size in pages */
{
- os_file_t fh;
+ pfs_os_file_t fh;
ibool ret;
dberr_t err = DB_SUCCESS;
@@ -1263,7 +1266,7 @@ srv_undo_tablespace_open(
const char* name, /*!< in: tablespace name */
ulint space) /*!< in: tablespace id */
{
- os_file_t fh;
+ pfs_os_file_t fh;
dberr_t err = DB_ERROR;
ibool ret;
ulint flags;
@@ -1365,13 +1368,23 @@ srv_undo_tablespaces_init(
for (i = 0; create_new_db && i < n_conf_tablespaces; ++i) {
char name[OS_FILE_MAX_PATH];
+ ulint space_id = i + 1;
+
+ DBUG_EXECUTE_IF("innodb_undo_upgrade",
+ space_id = i + 3;);
ut_snprintf(
name, sizeof(name),
"%s%cundo%03lu",
- srv_undo_dir, SRV_PATH_SEPARATOR, i + 1);
+ srv_undo_dir, SRV_PATH_SEPARATOR, space_id);
+
+ if (i == 0) {
+ srv_undo_space_id_start = space_id;
+ prev_space_id = srv_undo_space_id_start - 1;
+ }
+
+ undo_tablespace_ids[i] = space_id;
- /* Undo space ids start from 1. */
err = srv_undo_tablespace_create(
name, SRV_UNDO_TABLESPACE_SIZE_IN_PAGES);
@@ -1393,14 +1406,16 @@ srv_undo_tablespaces_init(
if (!create_new_db) {
n_undo_tablespaces = trx_rseg_get_n_undo_tablespaces(
undo_tablespace_ids);
- } else {
- n_undo_tablespaces = n_conf_tablespaces;
- for (i = 1; i <= n_undo_tablespaces; ++i) {
- undo_tablespace_ids[i - 1] = i;
+ if (n_undo_tablespaces != 0) {
+ srv_undo_space_id_start = undo_tablespace_ids[0];
+ prev_space_id = srv_undo_space_id_start - 1;
}
- undo_tablespace_ids[i] = ULINT_UNDEFINED;
+ } else {
+ n_undo_tablespaces = n_conf_tablespaces;
+
+ undo_tablespace_ids[n_conf_tablespaces] = ULINT_UNDEFINED;
}
/* Open all the undo tablespaces that are currently in use. If we
@@ -1424,8 +1439,6 @@ srv_undo_tablespaces_init(
ut_a(undo_tablespace_ids[i] != 0);
ut_a(undo_tablespace_ids[i] != ULINT_UNDEFINED);
- /* Undo space ids start from 1. */
-
err = srv_undo_tablespace_open(name, undo_tablespace_ids[i]);
if (err != DB_SUCCESS) {
@@ -1460,11 +1473,23 @@ srv_undo_tablespaces_init(
break;
}
+ /** Note the first undo tablespace id in case of
+ no active undo tablespace. */
+ if (n_undo_tablespaces == 0) {
+ srv_undo_space_id_start = i;
+ }
+
++n_undo_tablespaces;
++*n_opened;
}
+ /** Explictly specify the srv_undo_space_id_start
+ as zero when there are no undo tablespaces. */
+ if (n_undo_tablespaces == 0) {
+ srv_undo_space_id_start = 0;
+ }
+
/* If the user says that there are fewer than what we find we
tolerate that discrepancy but not the inverse. Because there could
be unused undo tablespaces for future use. */
@@ -1509,10 +1534,11 @@ srv_undo_tablespaces_init(
mtr_start(&mtr);
/* The undo log tablespace */
- for (i = 1; i <= n_undo_tablespaces; ++i) {
+ for (i = 0; i < n_undo_tablespaces; ++i) {
fsp_header_init(
- i, SRV_UNDO_TABLESPACE_SIZE_IN_PAGES, &mtr);
+ undo_tablespace_ids[i],
+ SRV_UNDO_TABLESPACE_SIZE_IN_PAGES, &mtr);
}
mtr_commit(&mtr);
@@ -1602,6 +1628,10 @@ innobase_start_or_create_for_mysql(void)
/* This should be initialized early */
ut_init_timer();
+ if (srv_force_recovery == SRV_FORCE_NO_LOG_REDO) {
+ srv_read_only_mode = 1;
+ }
+
high_level_read_only = srv_read_only_mode
|| srv_force_recovery > SRV_FORCE_NO_TRX_UNDO;
diff --git a/storage/innobase/trx/trx0purge.cc b/storage/innobase/trx/trx0purge.cc
index 66693592366..8d042ae014c 100644
--- a/storage/innobase/trx/trx0purge.cc
+++ b/storage/innobase/trx/trx0purge.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1996, 2017, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, MariaDB Corporation. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
@@ -685,7 +685,8 @@ trx_purge_get_rseg_with_min_trx_id(
/* We assume in purge of externally stored fields that space id is
in the range of UNDO tablespace space ids */
- ut_a(purge_sys->rseg->space <= srv_undo_tablespaces_open);
+ ut_a(purge_sys->rseg->space == 0
+ || srv_is_undo_tablespace(purge_sys->rseg->space));
zip_size = purge_sys->rseg->zip_size;
diff --git a/storage/innobase/trx/trx0roll.cc b/storage/innobase/trx/trx0roll.cc
index 0ef0d90b9cd..e22700c8fce 100644
--- a/storage/innobase/trx/trx0roll.cc
+++ b/storage/innobase/trx/trx0roll.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1996, 2017, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2016, 2017, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
@@ -806,6 +806,7 @@ DECLARE_THREAD(trx_rollback_or_clean_all_recovered)(
/*!< in: a dummy parameter required by
os_thread_create */
{
+ my_thread_init();
ut_ad(!srv_read_only_mode);
#ifdef UNIV_PFS_THREAD
@@ -816,6 +817,7 @@ DECLARE_THREAD(trx_rollback_or_clean_all_recovered)(
trx_rollback_or_clean_is_active = false;
+ my_thread_end();
/* 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. */
diff --git a/storage/innobase/trx/trx0sys.cc b/storage/innobase/trx/trx0sys.cc
index 24c5ce38339..f54466c8f82 100644
--- a/storage/innobase/trx/trx0sys.cc
+++ b/storage/innobase/trx/trx0sys.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2015, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1996, 2017, 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
@@ -1041,18 +1041,12 @@ trx_sys_create_rsegs(
ulint new_rsegs = n_rsegs - n_used;
for (i = 0; i < new_rsegs; ++i) {
- ulint space;
+ ulint space_id;
+ space_id = (n_spaces == 0) ? 0
+ : (srv_undo_space_id_start + i % n_spaces);
- /* Tablespace 0 is the system tablespace. All UNDO
- log tablespaces start from 1. */
-
- if (n_spaces > 0) {
- space = (i % n_spaces) + 1;
- } else {
- space = 0; /* System tablespace */
- }
-
- if (trx_rseg_create(space) != NULL) {
+ /* Tablespace 0 is the system tablespace. */
+ if (trx_rseg_create(space_id) != NULL) {
++n_used;
} else {
break;
diff --git a/storage/perfschema/ha_perfschema.cc b/storage/perfschema/ha_perfschema.cc
index 50d91842344..971f0c46be8 100644
--- a/storage/perfschema/ha_perfschema.cc
+++ b/storage/perfschema/ha_perfschema.cc
@@ -225,7 +225,7 @@ maria_declare_plugin(perfschema)
0x0001,
pfs_status_vars,
NULL,
- "5.6.33",
+ "5.6.36",
MariaDB_PLUGIN_MATURITY_STABLE
}
maria_declare_plugin_end;
diff --git a/storage/perfschema/pfs.cc b/storage/perfschema/pfs.cc
index ad3faeea618..c30ff4b6640 100644
--- a/storage/perfschema/pfs.cc
+++ b/storage/perfschema/pfs.cc
@@ -3951,9 +3951,11 @@ static PSI_file* end_file_open_wait_v1(PSI_file_locker *locker,
switch (state->m_operation)
{
case PSI_FILE_STAT:
+ case PSI_FILE_RENAME:
break;
case PSI_FILE_STREAM_OPEN:
case PSI_FILE_CREATE:
+ case PSI_FILE_OPEN:
if (result != NULL)
{
PFS_file_class *klass= reinterpret_cast<PFS_file_class*> (state->m_class);
@@ -3964,7 +3966,6 @@ static PSI_file* end_file_open_wait_v1(PSI_file_locker *locker,
state->m_file= reinterpret_cast<PSI_file*> (pfs_file);
}
break;
- case PSI_FILE_OPEN:
default:
DBUG_ASSERT(false);
break;
diff --git a/storage/perfschema/pfs_digest.cc b/storage/perfschema/pfs_digest.cc
index 3330c29795f..86b05f37fd2 100644
--- a/storage/perfschema/pfs_digest.cc
+++ b/storage/perfschema/pfs_digest.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2008, 2017, 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
@@ -257,10 +257,11 @@ search:
if (safe_index == 0)
{
/* Record [0] is reserved. */
- safe_index= 1;
+ continue;
}
/* Add a new record in digest stat array. */
+ DBUG_ASSERT(safe_index < digest_max);
pfs= &statements_digest_stat_array[safe_index];
if (pfs->m_lock.is_free())
diff --git a/storage/perfschema/unittest/pfs-t.cc b/storage/perfschema/unittest/pfs-t.cc
index f76b1aa2e75..b8814f2ad2d 100644
--- a/storage/perfschema/unittest/pfs-t.cc
+++ b/storage/perfschema/unittest/pfs-t.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2008, 2017, 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
@@ -27,6 +27,8 @@
#include "stub_print_error.h"
#include "stub_pfs_defaults.h"
+void unload_performance_schema();
+
/* test helpers, to simulate the setup */
void setup_thread(PSI_thread *t, bool enabled)
@@ -126,7 +128,7 @@ void test_bootstrap()
psi_2= boot->get_interface(PSI_VERSION_2);
ok(psi_2 == NULL, "version 2");
- shutdown_performance_schema();
+ unload_performance_schema();
}
/*
@@ -183,6 +185,27 @@ PSI * load_perfschema()
return (PSI*) psi;
}
+void unload_performance_schema()
+{
+ cleanup_table_share();
+ cleanup_instruments();
+ cleanup_sync_class();
+ cleanup_thread_class();
+ cleanup_table_share();
+ cleanup_file_class();
+ cleanup_stage_class();
+ cleanup_statement_class();
+ cleanup_socket_class();
+ cleanup_events_waits_history_long();
+ cleanup_events_stages_history_long();
+ cleanup_events_statements_history_long();
+ cleanup_table_share_hash();
+ cleanup_file_hash();
+ cleanup_digest();
+
+ shutdown_performance_schema();
+}
+
void test_bad_registration()
{
PSI *psi;
@@ -581,8 +604,7 @@ void test_bad_registration()
psi->register_socket("X", bad_socket_3, 1);
ok(dummy_socket_key == 2, "assigned key");
-
- shutdown_performance_schema();
+ unload_performance_schema();
}
void test_init_disabled()
@@ -1016,7 +1038,7 @@ void test_init_disabled()
socket_A1= psi->init_socket(99, NULL, NULL, 0);
ok(socket_A1 == NULL, "broken socket key not instrumented");
- shutdown_performance_schema();
+ unload_performance_schema();
}
void test_locker_disabled()
@@ -1316,14 +1338,14 @@ void test_locker_disabled()
/* Pretend the socket does not have a thread owner */
/* ---------------------------------------------- */
- psi->delete_current_thread();
socket_class_A->m_enabled= true;
socket_A1= psi->init_socket(socket_key_A, NULL, NULL, 0);
ok(socket_A1 != NULL, "instrumented");
/* Socket thread owner has not been set */
socket_locker= psi->start_socket_wait(&socket_state, socket_A1, PSI_SOCKET_SEND, 12, "foo.cc", 12);
- ok(socket_locker == NULL, "no locker (no thread owner)");
-
+ ok(socket_locker != NULL, "locker (owner not used)");
+ psi->end_socket_wait(socket_locker, 10);
+
/* Pretend the running thread is not instrumented */
/* ---------------------------------------------- */
@@ -1351,7 +1373,7 @@ void test_locker_disabled()
socket_locker= psi->start_socket_wait(&socket_state, socket_A1, PSI_SOCKET_SEND, 12, "foo.cc", 12);
ok(socket_locker == NULL, "no locker");
- shutdown_performance_schema();
+ unload_performance_schema();
}
void test_file_instrumentation_leak()
@@ -1438,7 +1460,7 @@ void test_file_instrumentation_leak()
file_locker= psi->get_thread_file_descriptor_locker(&file_state, (File) 12, PSI_FILE_WRITE);
ok(file_locker == NULL, "no locker, no leak");
- shutdown_performance_schema();
+ unload_performance_schema();
}
void test_enabled()
@@ -1474,7 +1496,7 @@ void test_enabled()
{ & cond_key_B, "C-B", 0}
};
- shutdown_performance_schema();
+ unload_performance_schema();
#endif
}
@@ -1644,5 +1666,5 @@ int main(int argc, char **argv)
MY_INIT(argv[0]);
do_all_tests();
my_end(0);
- return exit_status();
+ return (exit_status());
}
diff --git a/storage/perfschema/unittest/pfs_account-oom-t.cc b/storage/perfschema/unittest/pfs_account-oom-t.cc
index f1cd5069b54..a87588487cb 100644
--- a/storage/perfschema/unittest/pfs_account-oom-t.cc
+++ b/storage/perfschema/unittest/pfs_account-oom-t.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2011, 2017, 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
@@ -108,6 +108,6 @@ int main(int, char **)
MY_INIT("pfs_account-oom-t");
do_all_tests();
my_end(0);
- return exit_status();
+ return (exit_status());
}
diff --git a/storage/perfschema/unittest/pfs_connect_attr-t.cc b/storage/perfschema/unittest/pfs_connect_attr-t.cc
index 7bee1d063a1..ecf790eeede 100644
--- a/storage/perfschema/unittest/pfs_connect_attr-t.cc
+++ b/storage/perfschema/unittest/pfs_connect_attr-t.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2008, 2017, 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
@@ -341,5 +341,5 @@ int main(int, char **)
diag("skipping the cp1251 tests : missing character set");
plan(59 + (cs_cp1251 ? 10 : 0));
do_all_tests();
- return 0;
+ return (exit_status());
}
diff --git a/storage/perfschema/unittest/pfs_host-oom-t.cc b/storage/perfschema/unittest/pfs_host-oom-t.cc
index c72162038ca..c089083e4ae 100644
--- a/storage/perfschema/unittest/pfs_host-oom-t.cc
+++ b/storage/perfschema/unittest/pfs_host-oom-t.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2011, 2017, 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
@@ -108,6 +108,6 @@ int main(int, char **)
MY_INIT("pfs_host-oom-t");
do_all_tests();
my_end(0);
- return exit_status();
+ return (exit_status());
}
diff --git a/storage/perfschema/unittest/pfs_instr-oom-t.cc b/storage/perfschema/unittest/pfs_instr-oom-t.cc
index 93cddb0de6c..888acfab744 100644
--- a/storage/perfschema/unittest/pfs_instr-oom-t.cc
+++ b/storage/perfschema/unittest/pfs_instr-oom-t.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2008, 2017, 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
@@ -355,6 +355,11 @@ void test_oom()
rc= init_instruments(& param);
ok(rc == 1, "oom (per thread wait)");
+ cleanup_sync_class();
+ cleanup_thread_class();
+ cleanup_file_class();
+ cleanup_instruments();
+
param.m_enabled= true;
param.m_mutex_class_sizing= 0;
param.m_rwlock_class_sizing= 0;
@@ -432,6 +437,8 @@ void test_oom()
init_event_name_sizing(& param);
rc= init_instruments(& param);
ok(rc == 1, "oom (thread stages history sizing)");
+
+ cleanup_thread_class();
cleanup_instruments();
param.m_enabled= true;
@@ -467,6 +474,9 @@ void test_oom()
init_event_name_sizing(& param);
rc= init_instruments(& param);
ok(rc == 1, "oom (per thread stages)");
+
+ cleanup_stage_class();
+ cleanup_thread_class();
cleanup_instruments();
param.m_enabled= true;
@@ -502,6 +512,8 @@ void test_oom()
init_event_name_sizing(& param);
rc= init_instruments(& param);
ok(rc == 1, "oom (thread statements history sizing)");
+
+ cleanup_thread_class();
cleanup_instruments();
param.m_enabled= true;
@@ -537,6 +549,9 @@ void test_oom()
init_event_name_sizing(& param);
rc= init_instruments(& param);
ok(rc == 1, "oom (per thread statements)");
+
+ cleanup_statement_class();
+ cleanup_thread_class();
cleanup_instruments();
param.m_enabled= true;
@@ -572,6 +587,8 @@ void test_oom()
init_event_name_sizing(& param);
rc= init_instruments(& param);
ok(rc == 1, "oom (global waits)");
+
+ cleanup_sync_class();
cleanup_instruments();
param.m_enabled= true;
@@ -609,8 +626,10 @@ void test_oom()
ok(rc == 0, "init stage class");
rc= init_instruments(& param);
ok(rc == 1, "oom (global stages)");
- cleanup_instruments();
+
+ cleanup_sync_class();
cleanup_stage_class();
+ cleanup_instruments();
param.m_enabled= true;
param.m_mutex_class_sizing= 10;
@@ -647,8 +666,10 @@ void test_oom()
ok(rc == 0, "init statement class");
rc= init_instruments(& param);
ok(rc == 1, "oom (global statements)");
- cleanup_instruments();
+
+ cleanup_sync_class();
cleanup_statement_class();
+ cleanup_instruments();
}
void do_all_tests()
@@ -662,6 +683,6 @@ int main(int argc, char **argv)
MY_INIT(argv[0]);
do_all_tests();
my_end(0);
- return exit_status();
+ return (exit_status());
}
diff --git a/storage/perfschema/unittest/pfs_instr-t.cc b/storage/perfschema/unittest/pfs_instr-t.cc
index c191b3dc41a..659f410e283 100644
--- a/storage/perfschema/unittest/pfs_instr-t.cc
+++ b/storage/perfschema/unittest/pfs_instr-t.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2008, 2017, 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
@@ -23,10 +23,11 @@
#include <memory.h>
+PFS_global_param param;
+
void test_no_instruments()
{
int rc;
- PFS_global_param param;
memset(& param, 0xFF, sizeof(param));
param.m_enabled= true;
@@ -86,7 +87,6 @@ void test_no_instances()
PFS_file *file;
PFS_socket *socket;
PFS_table *table;
- PFS_global_param param;
memset(& param, 0xFF, sizeof(param));
param.m_enabled= true;
@@ -227,7 +227,6 @@ void test_with_instances()
PFS_socket *socket_2;
PFS_table *table_1;
PFS_table *table_2;
- PFS_global_param param;
memset(& param, 0xFF, sizeof(param));
param.m_enabled= true;
@@ -414,6 +413,6 @@ int main(int argc, char **argv)
MY_INIT(argv[0]);
do_all_tests();
my_end(0);
- return exit_status();
+ return (exit_status());
}
diff --git a/storage/perfschema/unittest/pfs_instr_class-oom-t.cc b/storage/perfschema/unittest/pfs_instr_class-oom-t.cc
index 708e08be6d4..c9b87b9cf1e 100644
--- a/storage/perfschema/unittest/pfs_instr_class-oom-t.cc
+++ b/storage/perfschema/unittest/pfs_instr_class-oom-t.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2008, 2017, 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
@@ -64,6 +64,6 @@ int main(int argc, char **argv)
MY_INIT(argv[0]);
do_all_tests();
my_end(0);
- return exit_status();
+ return (exit_status());
}
diff --git a/storage/perfschema/unittest/pfs_instr_class-t.cc b/storage/perfschema/unittest/pfs_instr_class-t.cc
index 19a8989b34e..dcbc3927eae 100644
--- a/storage/perfschema/unittest/pfs_instr_class-t.cc
+++ b/storage/perfschema/unittest/pfs_instr_class-t.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2008, 2017, 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
@@ -670,5 +670,5 @@ int main(int argc, char **argv)
MY_INIT(argv[0]);
do_all_tests();
my_end(0);
- return exit_status();
+ return (exit_status());
}
diff --git a/storage/perfschema/unittest/pfs_misc-t.cc b/storage/perfschema/unittest/pfs_misc-t.cc
index a4b11b9a727..eed9039dfb2 100644
--- a/storage/perfschema/unittest/pfs_misc-t.cc
+++ b/storage/perfschema/unittest/pfs_misc-t.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2015, 2017, 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
@@ -67,6 +67,6 @@ int main(int, char **)
MY_INIT("pfs_misc-t");
do_all_tests();
my_end(0);
- return exit_status();
+ return (exit_status());
}
diff --git a/storage/perfschema/unittest/pfs_timer-t.cc b/storage/perfschema/unittest/pfs_timer-t.cc
index 8fb3a206ebf..55113860532 100644
--- a/storage/perfschema/unittest/pfs_timer-t.cc
+++ b/storage/perfschema/unittest/pfs_timer-t.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2008, 2017, 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
@@ -115,6 +115,6 @@ int main(int, char **)
MY_INIT("pfs_timer-t");
do_all_tests();
my_end(0);
- return exit_status();
+ return (exit_status());
}
diff --git a/storage/perfschema/unittest/pfs_user-oom-t.cc b/storage/perfschema/unittest/pfs_user-oom-t.cc
index 9fb64d130ae..e153b39cbd2 100644
--- a/storage/perfschema/unittest/pfs_user-oom-t.cc
+++ b/storage/perfschema/unittest/pfs_user-oom-t.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2011, 2017, 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
@@ -107,6 +107,6 @@ int main(int, char **)
MY_INIT("pfs_user-oom-t");
do_all_tests();
my_end(0);
- return exit_status();
+ return (exit_status());
}
diff --git a/storage/tokudb/CMakeLists.txt b/storage/tokudb/CMakeLists.txt
index 041adc51abc..0e2cdb79bff 100644
--- a/storage/tokudb/CMakeLists.txt
+++ b/storage/tokudb/CMakeLists.txt
@@ -1,4 +1,4 @@
-SET(TOKUDB_VERSION 5.6.35-80.0)
+SET(TOKUDB_VERSION 5.6.36-82.0)
# PerconaFT only supports x86-64 and cmake-2.8.9+
IF(CMAKE_VERSION VERSION_LESS "2.8.9")
MESSAGE(STATUS "CMake 2.8.9 or higher is required by TokuDB")
@@ -21,7 +21,8 @@ SET(TOKUDB_SOURCES
tokudb_background.cc
tokudb_information_schema.cc
tokudb_sysvars.cc
- tokudb_thread.cc)
+ tokudb_thread.cc
+ tokudb_dir_cmd.cc)
MYSQL_ADD_PLUGIN(tokudb ${TOKUDB_SOURCES} STORAGE_ENGINE MODULE_ONLY)
IF(NOT TARGET tokudb)
diff --git a/storage/tokudb/PerconaFT/buildheader/make_tdb.cc b/storage/tokudb/PerconaFT/buildheader/make_tdb.cc
index 0145d631839..6f0b7c5f419 100644
--- a/storage/tokudb/PerconaFT/buildheader/make_tdb.cc
+++ b/storage/tokudb/PerconaFT/buildheader/make_tdb.cc
@@ -426,6 +426,9 @@ static void print_db_env_struct (void) {
"bool (*set_dir_per_db)(DB_ENV *, bool new_val)",
"bool (*get_dir_per_db)(DB_ENV *)",
"const char *(*get_data_dir)(DB_ENV *env)",
+ "int (*dirtool_attach)(DB_ENV *, DB_TXN *, const char *, const char *)",
+ "int (*dirtool_detach)(DB_ENV *, DB_TXN *, const char *)",
+ "int (*dirtool_move)(DB_ENV *, DB_TXN *, const char *, const char *)",
"void (*kill_waiter)(DB_ENV *, void *extra)",
NULL};
diff --git a/storage/tokudb/PerconaFT/ft/ft-ops.cc b/storage/tokudb/PerconaFT/ft/ft-ops.cc
index ad9ecb1d074..63c6335dafd 100644
--- a/storage/tokudb/PerconaFT/ft/ft-ops.cc
+++ b/storage/tokudb/PerconaFT/ft/ft-ops.cc
@@ -3900,25 +3900,34 @@ struct keyrange_compare_s {
};
// TODO: Remove me, I'm boring
-static int keyrange_compare(DBT const &kdbt, const struct keyrange_compare_s &s) {
+static int keyrange_compare(DBT const &kdbt,
+ const struct keyrange_compare_s &s) {
return s.ft->cmp(&kdbt, s.key);
}
-static void
-keysrange_in_leaf_partition (FT_HANDLE ft_handle, FTNODE node,
- DBT* key_left, DBT* key_right,
- int left_child_number, int right_child_number, uint64_t estimated_num_rows,
- uint64_t *less, uint64_t* equal_left, uint64_t* middle,
- uint64_t* equal_right, uint64_t* greater, bool* single_basement_node)
+static void keysrange_in_leaf_partition(FT_HANDLE ft_handle,
+ FTNODE node,
+ DBT *key_left,
+ DBT *key_right,
+ int left_child_number,
+ int right_child_number,
+ uint64_t estimated_num_rows,
+ uint64_t *less,
+ uint64_t *equal_left,
+ uint64_t *middle,
+ uint64_t *equal_right,
+ uint64_t *greater,
+ bool *single_basement_node)
// If the partition is in main memory then estimate the number
// Treat key_left == NULL as negative infinity
// Treat key_right == NULL as positive infinity
{
- paranoid_invariant(node->height == 0); // we are in a leaf
+ paranoid_invariant(node->height == 0); // we are in a leaf
paranoid_invariant(!(key_left == NULL && key_right != NULL));
paranoid_invariant(left_child_number <= right_child_number);
bool single_basement = left_child_number == right_child_number;
- paranoid_invariant(!single_basement || (BP_STATE(node, left_child_number) == PT_AVAIL));
+ paranoid_invariant(!single_basement ||
+ (BP_STATE(node, left_child_number) == PT_AVAIL));
if (BP_STATE(node, left_child_number) == PT_AVAIL) {
int r;
// The partition is in main memory then get an exact count.
@@ -3926,29 +3935,35 @@ keysrange_in_leaf_partition (FT_HANDLE ft_handle, FTNODE node,
BASEMENTNODE bn = BLB(node, left_child_number);
uint32_t idx_left = 0;
// if key_left is NULL then set r==-1 and idx==0.
- r = key_left ? bn->data_buffer.find_zero<decltype(s_left), keyrange_compare>(s_left, nullptr, nullptr, nullptr, &idx_left) : -1;
+ r = key_left
+ ? bn->data_buffer.find_zero<decltype(s_left), keyrange_compare>(
+ s_left, nullptr, nullptr, nullptr, &idx_left)
+ : -1;
*less = idx_left;
- *equal_left = (r==0) ? 1 : 0;
+ *equal_left = (r == 0) ? 1 : 0;
uint32_t size = bn->data_buffer.num_klpairs();
uint32_t idx_right = size;
r = -1;
if (single_basement && key_right) {
struct keyrange_compare_s s_right = {ft_handle->ft, key_right};
- r = bn->data_buffer.find_zero<decltype(s_right), keyrange_compare>(s_right, nullptr, nullptr, nullptr, &idx_right);
+ r = bn->data_buffer.find_zero<decltype(s_right), keyrange_compare>(
+ s_right, nullptr, nullptr, nullptr, &idx_right);
}
*middle = idx_right - idx_left - *equal_left;
- *equal_right = (r==0) ? 1 : 0;
+ *equal_right = (r == 0) ? 1 : 0;
*greater = size - idx_right - *equal_right;
} else {
paranoid_invariant(!single_basement);
uint32_t idx_left = estimated_num_rows / 2;
if (!key_left) {
- //Both nullptr, assume key_left belongs before leftmost entry, key_right belongs after rightmost entry
+ // Both nullptr, assume key_left belongs before leftmost entry,
+ // key_right belongs after rightmost entry
idx_left = 0;
paranoid_invariant(!key_right);
}
- // Assume idx_left and idx_right point to where key_left and key_right belong, (but are not there).
+ // Assume idx_left and idx_right point to where key_left and key_right
+ // belong, (but are not there).
*less = idx_left;
*equal_left = 0;
*middle = estimated_num_rows - idx_left;
@@ -3958,44 +3973,76 @@ keysrange_in_leaf_partition (FT_HANDLE ft_handle, FTNODE node,
*single_basement_node = single_basement;
}
-static int
-toku_ft_keysrange_internal (FT_HANDLE ft_handle, FTNODE node,
- DBT* key_left, DBT* key_right, bool may_find_right,
- uint64_t* less, uint64_t* equal_left, uint64_t* middle,
- uint64_t* equal_right, uint64_t* greater, bool* single_basement_node,
- uint64_t estimated_num_rows,
- ftnode_fetch_extra *min_bfe, // set up to read a minimal read.
- ftnode_fetch_extra *match_bfe, // set up to read a basement node iff both keys in it
- struct unlockers *unlockers, ANCESTORS ancestors, const pivot_bounds &bounds)
-// Implementation note: Assign values to less, equal, and greater, and then on the way out (returning up the stack) we add more values in.
+static int toku_ft_keysrange_internal(
+ FT_HANDLE ft_handle,
+ FTNODE node,
+ DBT *key_left,
+ DBT *key_right,
+ bool may_find_right,
+ uint64_t *less,
+ uint64_t *equal_left,
+ uint64_t *middle,
+ uint64_t *equal_right,
+ uint64_t *greater,
+ bool *single_basement_node,
+ uint64_t estimated_num_rows,
+ ftnode_fetch_extra *min_bfe, // set up to read a minimal read.
+ ftnode_fetch_extra
+ *match_bfe, // set up to read a basement node iff both keys in it
+ struct unlockers *unlockers,
+ ANCESTORS ancestors,
+ const pivot_bounds &bounds)
+// Implementation note: Assign values to less, equal, and greater, and then on
+// the way out (returning up the stack) we add more values in.
{
int r = 0;
// if KEY is NULL then use the leftmost key.
- int left_child_number = key_left ? toku_ftnode_which_child (node, key_left, ft_handle->ft->cmp) : 0;
- int right_child_number = node->n_children; // Sentinel that does not equal left_child_number.
+ int left_child_number =
+ key_left ? toku_ftnode_which_child(node, key_left, ft_handle->ft->cmp)
+ : 0;
+ int right_child_number =
+ node->n_children; // Sentinel that does not equal left_child_number.
if (may_find_right) {
- right_child_number = key_right ? toku_ftnode_which_child (node, key_right, ft_handle->ft->cmp) : node->n_children - 1;
+ right_child_number =
+ key_right
+ ? toku_ftnode_which_child(node, key_right, ft_handle->ft->cmp)
+ : node->n_children - 1;
}
uint64_t rows_per_child = estimated_num_rows / node->n_children;
if (node->height == 0) {
- keysrange_in_leaf_partition(ft_handle, node, key_left, key_right, left_child_number, right_child_number,
- rows_per_child, less, equal_left, middle, equal_right, greater, single_basement_node);
-
- *less += rows_per_child * left_child_number;
+ keysrange_in_leaf_partition(ft_handle,
+ node,
+ key_left,
+ key_right,
+ left_child_number,
+ right_child_number,
+ rows_per_child,
+ less,
+ equal_left,
+ middle,
+ equal_right,
+ greater,
+ single_basement_node);
+
+ *less += rows_per_child * left_child_number;
if (*single_basement_node) {
- *greater += rows_per_child * (node->n_children - left_child_number - 1);
+ *greater +=
+ rows_per_child * (node->n_children - left_child_number - 1);
} else {
- *middle += rows_per_child * (node->n_children - left_child_number - 1);
+ *middle +=
+ rows_per_child * (node->n_children - left_child_number - 1);
}
} else {
// do the child.
struct ancestors next_ancestors = {node, left_child_number, ancestors};
BLOCKNUM childblocknum = BP_BLOCKNUM(node, left_child_number);
- uint32_t fullhash = compute_child_fullhash(ft_handle->ft->cf, node, left_child_number);
+ uint32_t fullhash =
+ compute_child_fullhash(ft_handle->ft->cf, node, left_child_number);
FTNODE childnode;
bool msgs_applied = false;
- bool child_may_find_right = may_find_right && left_child_number == right_child_number;
+ bool child_may_find_right =
+ may_find_right && left_child_number == right_child_number;
r = toku_pin_ftnode_for_query(
ft_handle,
childblocknum,
@@ -4006,27 +4053,45 @@ toku_ft_keysrange_internal (FT_HANDLE ft_handle, FTNODE node,
child_may_find_right ? match_bfe : min_bfe,
false,
&childnode,
- &msgs_applied
- );
+ &msgs_applied);
paranoid_invariant(!msgs_applied);
if (r != TOKUDB_TRY_AGAIN) {
assert_zero(r);
- struct unlock_ftnode_extra unlock_extra = {ft_handle,childnode,false};
- struct unlockers next_unlockers = {true, unlock_ftnode_fun, (void*)&unlock_extra, unlockers};
- const pivot_bounds next_bounds = bounds.next_bounds(node, left_child_number);
-
- r = toku_ft_keysrange_internal(ft_handle, childnode, key_left, key_right, child_may_find_right,
- less, equal_left, middle, equal_right, greater, single_basement_node,
- rows_per_child, min_bfe, match_bfe, &next_unlockers, &next_ancestors, next_bounds);
+ struct unlock_ftnode_extra unlock_extra = {
+ ft_handle, childnode, false};
+ struct unlockers next_unlockers = {
+ true, unlock_ftnode_fun, (void *)&unlock_extra, unlockers};
+ const pivot_bounds next_bounds =
+ bounds.next_bounds(node, left_child_number);
+
+ r = toku_ft_keysrange_internal(ft_handle,
+ childnode,
+ key_left,
+ key_right,
+ child_may_find_right,
+ less,
+ equal_left,
+ middle,
+ equal_right,
+ greater,
+ single_basement_node,
+ rows_per_child,
+ min_bfe,
+ match_bfe,
+ &next_unlockers,
+ &next_ancestors,
+ next_bounds);
if (r != TOKUDB_TRY_AGAIN) {
assert_zero(r);
- *less += rows_per_child * left_child_number;
+ *less += rows_per_child * left_child_number;
if (*single_basement_node) {
- *greater += rows_per_child * (node->n_children - left_child_number - 1);
+ *greater += rows_per_child *
+ (node->n_children - left_child_number - 1);
} else {
- *middle += rows_per_child * (node->n_children - left_child_number - 1);
+ *middle += rows_per_child *
+ (node->n_children - left_child_number - 1);
}
assert(unlockers->locked);
@@ -4037,10 +4102,21 @@ toku_ft_keysrange_internal (FT_HANDLE ft_handle, FTNODE node,
return r;
}
-void toku_ft_keysrange(FT_HANDLE ft_handle, DBT* key_left, DBT* key_right, uint64_t *less_p, uint64_t* equal_left_p, uint64_t* middle_p, uint64_t* equal_right_p, uint64_t* greater_p, bool* middle_3_exact_p)
-// Effect: Return an estimate of the number of keys to the left, the number equal (to left key), number between keys, number equal to right key, and the number to the right of both keys.
+void toku_ft_keysrange(FT_HANDLE ft_handle,
+ DBT *key_left,
+ DBT *key_right,
+ uint64_t *less_p,
+ uint64_t *equal_left_p,
+ uint64_t *middle_p,
+ uint64_t *equal_right_p,
+ uint64_t *greater_p,
+ bool *middle_3_exact_p)
+// Effect: Return an estimate of the number of keys to the left, the number
+// equal (to left key), number between keys, number equal to right key, and the
+// number to the right of both keys.
// The values are an estimate.
-// If you perform a keyrange on two keys that are in the same basement, equal_less, middle, and equal_right will be exact.
+// If you perform a keyrange on two keys that are in the same basement,
+// equal_less, middle, and equal_right will be exact.
// 4184: What to do with a NULL key?
// key_left==NULL is treated as -infinity
// key_right==NULL is treated as +infinity
@@ -4048,10 +4124,21 @@ void toku_ft_keysrange(FT_HANDLE ft_handle, DBT* key_left, DBT* key_right, uint6
// key_right can be non-null only if key_left is non-null;
{
if (!key_left && key_right) {
- // Simplify internals by only supporting key_right != null when key_left != null
- // If key_right != null and key_left == null, then swap them and fix up numbers.
- uint64_t less = 0, equal_left = 0, middle = 0, equal_right = 0, greater = 0;
- toku_ft_keysrange(ft_handle, key_right, nullptr, &less, &equal_left, &middle, &equal_right, &greater, middle_3_exact_p);
+ // Simplify internals by only supporting key_right != null when key_left
+ // != null
+ // If key_right != null and key_left == null, then swap them and fix up
+ // numbers.
+ uint64_t less = 0, equal_left = 0, middle = 0, equal_right = 0,
+ greater = 0;
+ toku_ft_keysrange(ft_handle,
+ key_right,
+ nullptr,
+ &less,
+ &equal_left,
+ &middle,
+ &equal_right,
+ &greater,
+ middle_3_exact_p);
*less_p = 0;
*equal_left_p = 0;
*middle_p = less;
@@ -4064,98 +4151,132 @@ void toku_ft_keysrange(FT_HANDLE ft_handle, DBT* key_left, DBT* key_right, uint6
paranoid_invariant(!(!key_left && key_right));
ftnode_fetch_extra min_bfe;
ftnode_fetch_extra match_bfe;
- min_bfe.create_for_min_read(ft_handle->ft); // read pivot keys but not message buffers
- match_bfe.create_for_keymatch(ft_handle->ft, key_left, key_right, false, false); // read basement node only if both keys in it.
-try_again:
+ min_bfe.create_for_min_read(
+ ft_handle->ft); // read pivot keys but not message buffers
+ match_bfe.create_for_keymatch(
+ ft_handle->ft,
+ key_left,
+ key_right,
+ false,
+ false); // read basement node only if both keys in it.
+try_again : {
+ uint64_t less = 0, equal_left = 0, middle = 0, equal_right = 0, greater = 0;
+ bool single_basement_node = false;
+ FTNODE node = NULL;
{
- uint64_t less = 0, equal_left = 0, middle = 0, equal_right = 0, greater = 0;
- bool single_basement_node = false;
- FTNODE node = NULL;
- {
- uint32_t fullhash;
- CACHEKEY root_key;
- toku_calculate_root_offset_pointer(ft_handle->ft, &root_key, &fullhash);
- toku_pin_ftnode(
- ft_handle->ft,
- root_key,
- fullhash,
- &match_bfe,
- PL_READ, // may_modify_node, cannot change root during keyrange
- &node,
- true
- );
- }
+ uint32_t fullhash;
+ CACHEKEY root_key;
+ toku_calculate_root_offset_pointer(ft_handle->ft, &root_key, &fullhash);
+ toku_pin_ftnode(
+ ft_handle->ft,
+ root_key,
+ fullhash,
+ &match_bfe,
+ PL_READ, // may_modify_node, cannot change root during keyrange
+ &node,
+ true);
+ }
- struct unlock_ftnode_extra unlock_extra = {ft_handle,node,false};
- struct unlockers unlockers = {true, unlock_ftnode_fun, (void*)&unlock_extra, (UNLOCKERS)NULL};
+ struct unlock_ftnode_extra unlock_extra = {ft_handle, node, false};
+ struct unlockers unlockers = {
+ true, unlock_ftnode_fun, (void *)&unlock_extra, (UNLOCKERS)NULL};
- {
- int r;
- int64_t numrows = ft_handle->ft->in_memory_stats.numrows;
- if (numrows < 0)
- numrows = 0; // prevent appearance of a negative number
- r = toku_ft_keysrange_internal (ft_handle, node, key_left, key_right, true,
- &less, &equal_left, &middle, &equal_right, &greater,
- &single_basement_node, numrows,
- &min_bfe, &match_bfe, &unlockers, (ANCESTORS)NULL, pivot_bounds::infinite_bounds());
+ {
+ int r;
+ int64_t numrows = ft_handle->ft->in_memory_logical_rows;
+ if (numrows < 0)
+ numrows = 0; // prevent appearance of a negative number
+ r = toku_ft_keysrange_internal(ft_handle,
+ node,
+ key_left,
+ key_right,
+ true,
+ &less,
+ &equal_left,
+ &middle,
+ &equal_right,
+ &greater,
+ &single_basement_node,
+ numrows,
+ &min_bfe,
+ &match_bfe,
+ &unlockers,
+ (ANCESTORS)NULL,
+ pivot_bounds::infinite_bounds());
+ assert(r == 0 || r == TOKUDB_TRY_AGAIN);
+ if (r == TOKUDB_TRY_AGAIN) {
+ assert(!unlockers.locked);
+ goto try_again;
+ }
+ // May need to do a second query.
+ if (!single_basement_node && key_right != nullptr) {
+ // "greater" is stored in "middle"
+ invariant_zero(equal_right);
+ invariant_zero(greater);
+ uint64_t less2 = 0, equal_left2 = 0, middle2 = 0, equal_right2 = 0,
+ greater2 = 0;
+ bool ignore;
+ r = toku_ft_keysrange_internal(ft_handle,
+ node,
+ key_right,
+ nullptr,
+ false,
+ &less2,
+ &equal_left2,
+ &middle2,
+ &equal_right2,
+ &greater2,
+ &ignore,
+ numrows,
+ &min_bfe,
+ &match_bfe,
+ &unlockers,
+ (ANCESTORS) nullptr,
+ pivot_bounds::infinite_bounds());
assert(r == 0 || r == TOKUDB_TRY_AGAIN);
if (r == TOKUDB_TRY_AGAIN) {
assert(!unlockers.locked);
goto try_again;
}
- // May need to do a second query.
- if (!single_basement_node && key_right != nullptr) {
- // "greater" is stored in "middle"
- invariant_zero(equal_right);
- invariant_zero(greater);
- uint64_t less2 = 0, equal_left2 = 0, middle2 = 0, equal_right2 = 0, greater2 = 0;
- bool ignore;
- r = toku_ft_keysrange_internal (ft_handle, node, key_right, nullptr, false,
- &less2, &equal_left2, &middle2, &equal_right2, &greater2,
- &ignore, numrows,
- &min_bfe, &match_bfe, &unlockers, (ANCESTORS)nullptr, pivot_bounds::infinite_bounds());
- assert(r == 0 || r == TOKUDB_TRY_AGAIN);
- if (r == TOKUDB_TRY_AGAIN) {
- assert(!unlockers.locked);
- goto try_again;
- }
- invariant_zero(equal_right2);
- invariant_zero(greater2);
- // Update numbers.
- // less is already correct.
- // equal_left is already correct.
-
- // "middle" currently holds everything greater than left_key in first query
- // 'middle2' currently holds everything greater than right_key in second query
- // 'equal_left2' is how many match right_key
-
- // Prevent underflow.
- if (middle >= equal_left2 + middle2) {
- middle -= equal_left2 + middle2;
- } else {
- middle = 0;
- }
- equal_right = equal_left2;
- greater = middle2;
+ invariant_zero(equal_right2);
+ invariant_zero(greater2);
+ // Update numbers.
+ // less is already correct.
+ // equal_left is already correct.
+
+ // "middle" currently holds everything greater than left_key in
+ // first query
+ // 'middle2' currently holds everything greater than right_key in
+ // second query
+ // 'equal_left2' is how many match right_key
+
+ // Prevent underflow.
+ if (middle >= equal_left2 + middle2) {
+ middle -= equal_left2 + middle2;
+ } else {
+ middle = 0;
}
+ equal_right = equal_left2;
+ greater = middle2;
}
- assert(unlockers.locked);
- toku_unpin_ftnode_read_only(ft_handle->ft, node);
- if (!key_right) {
- paranoid_invariant_zero(equal_right);
- paranoid_invariant_zero(greater);
- }
- if (!key_left) {
- paranoid_invariant_zero(less);
- paranoid_invariant_zero(equal_left);
- }
- *less_p = less;
- *equal_left_p = equal_left;
- *middle_p = middle;
- *equal_right_p = equal_right;
- *greater_p = greater;
- *middle_3_exact_p = single_basement_node;
}
+ assert(unlockers.locked);
+ toku_unpin_ftnode_read_only(ft_handle->ft, node);
+ if (!key_right) {
+ paranoid_invariant_zero(equal_right);
+ paranoid_invariant_zero(greater);
+ }
+ if (!key_left) {
+ paranoid_invariant_zero(less);
+ paranoid_invariant_zero(equal_left);
+ }
+ *less_p = less;
+ *equal_left_p = equal_left;
+ *middle_p = middle;
+ *equal_right_p = equal_right;
+ *greater_p = greater;
+ *middle_3_exact_p = single_basement_node;
+}
}
struct get_key_after_bytes_iterate_extra {
diff --git a/storage/tokudb/PerconaFT/src/ydb.cc b/storage/tokudb/PerconaFT/src/ydb.cc
index f99b8dfa5da..90129aa74c4 100644
--- a/storage/tokudb/PerconaFT/src/ydb.cc
+++ b/storage/tokudb/PerconaFT/src/ydb.cc
@@ -70,6 +70,8 @@ const char *toku_copyright_string = "Copyright (c) 2006, 2015, Percona and/or it
#include "util/status.h"
#include "util/context.h"
+#include <functional>
+
// Include ydb_lib.cc here so that its constructor/destructor gets put into
// ydb.o, to make sure they don't get erased at link time (when linking to
// a static libtokufractaltree.a that was compiled with gcc). See #5094.
@@ -1314,6 +1316,159 @@ static const char *env_get_data_dir(DB_ENV *env) {
return env->i->real_data_dir;
}
+static int env_dirtool_attach(DB_ENV *env,
+ DB_TXN *txn,
+ const char *dname,
+ const char *iname) {
+ int r;
+ DBT dname_dbt;
+ DBT iname_dbt;
+
+ HANDLE_PANICKED_ENV(env);
+ if (!env_opened(env)) {
+ return EINVAL;
+ }
+ HANDLE_READ_ONLY_TXN(txn);
+ toku_fill_dbt(&dname_dbt, dname, strlen(dname) + 1);
+ toku_fill_dbt(&iname_dbt, iname, strlen(iname) + 1);
+
+ r = toku_db_put(env->i->directory,
+ txn,
+ &dname_dbt,
+ &iname_dbt,
+ 0,
+ true);
+ return r;
+}
+
+static int env_dirtool_detach(DB_ENV *env,
+ DB_TXN *txn,
+ const char *dname) {
+ int r;
+ DBT dname_dbt;
+ DBT old_iname_dbt;
+
+ HANDLE_PANICKED_ENV(env);
+ if (!env_opened(env)) {
+ return EINVAL;
+ }
+ HANDLE_READ_ONLY_TXN(txn);
+
+ toku_fill_dbt(&dname_dbt, dname, strlen(dname) + 1);
+ toku_init_dbt_flags(&old_iname_dbt, DB_DBT_REALLOC);
+
+ r = toku_db_get(env->i->directory,
+ txn,
+ &dname_dbt,
+ &old_iname_dbt,
+ DB_SERIALIZABLE); // allocates memory for iname
+ if (r == DB_NOTFOUND)
+ return EEXIST;
+ toku_free(old_iname_dbt.data);
+
+ r = toku_db_del(env->i->directory, txn, &dname_dbt, DB_DELETE_ANY, true);
+
+ return r;
+}
+
+static int env_dirtool_move(DB_ENV *env,
+ DB_TXN *txn,
+ const char *old_dname,
+ const char *new_dname) {
+ int r;
+ DBT old_dname_dbt;
+ DBT new_dname_dbt;
+ DBT iname_dbt;
+
+ HANDLE_PANICKED_ENV(env);
+ if (!env_opened(env)) {
+ return EINVAL;
+ }
+ HANDLE_READ_ONLY_TXN(txn);
+
+ toku_fill_dbt(&old_dname_dbt, old_dname, strlen(old_dname) + 1);
+ toku_fill_dbt(&new_dname_dbt, new_dname, strlen(new_dname) + 1);
+ toku_init_dbt_flags(&iname_dbt, DB_DBT_REALLOC);
+
+ r = toku_db_get(env->i->directory,
+ txn,
+ &old_dname_dbt,
+ &iname_dbt,
+ DB_SERIALIZABLE); // allocates memory for iname
+ if (r == DB_NOTFOUND)
+ return EEXIST;
+
+ r = toku_db_del(
+ env->i->directory, txn, &old_dname_dbt, DB_DELETE_ANY, true);
+ if (r != 0)
+ goto exit;
+
+ r = toku_db_put(
+ env->i->directory, txn, &new_dname_dbt, &iname_dbt, 0, true);
+
+exit:
+ toku_free(iname_dbt.data);
+ return r;
+}
+
+static int locked_env_op(DB_ENV *env,
+ DB_TXN *txn,
+ std::function<int(DB_TXN *)> f) {
+ int ret, r;
+ HANDLE_READ_ONLY_TXN(txn);
+ HANDLE_ILLEGAL_WORKING_PARENT_TXN(env, txn);
+
+ DB_TXN *child_txn = NULL;
+ int using_txns = env->i->open_flags & DB_INIT_TXN;
+ if (using_txns) {
+ ret = toku_txn_begin(env, txn, &child_txn, 0);
+ lazy_assert_zero(ret);
+ }
+
+ // cannot begin a checkpoint
+ toku_multi_operation_client_lock();
+ r = f(child_txn);
+ toku_multi_operation_client_unlock();
+
+ if (using_txns) {
+ if (r == 0) {
+ ret = locked_txn_commit(child_txn, 0);
+ lazy_assert_zero(ret);
+ } else {
+ ret = locked_txn_abort(child_txn);
+ lazy_assert_zero(ret);
+ }
+ }
+ return r;
+
+}
+
+static int locked_env_dirtool_attach(DB_ENV *env,
+ DB_TXN *txn,
+ const char *dname,
+ const char *iname) {
+ auto f = std::bind(
+ env_dirtool_attach, env, std::placeholders::_1, dname, iname);
+ return locked_env_op(env, txn, f);
+}
+
+static int locked_env_dirtool_detach(DB_ENV *env,
+ DB_TXN *txn,
+ const char *dname) {
+ auto f = std::bind(
+ env_dirtool_detach, env, std::placeholders::_1, dname);
+ return locked_env_op(env, txn, f);
+}
+
+static int locked_env_dirtool_move(DB_ENV *env,
+ DB_TXN *txn,
+ const char *old_dname,
+ const char *new_dname) {
+ auto f = std::bind(
+ env_dirtool_move, env, std::placeholders::_1, old_dname, new_dname);
+ return locked_env_op(env, txn, f);
+}
+
static int env_dbremove(DB_ENV * env, DB_TXN *txn, const char *fname, const char *dbname, uint32_t flags);
static int
@@ -2656,6 +2811,9 @@ toku_env_create(DB_ENV ** envp, uint32_t flags) {
#define SENV(name) result->name = locked_env_ ## name
SENV(dbremove);
SENV(dbrename);
+ SENV(dirtool_attach);
+ SENV(dirtool_detach);
+ SENV(dirtool_move);
//SENV(set_noticecall);
#undef SENV
#define USENV(name) result->name = env_ ## name
@@ -2987,8 +3145,10 @@ env_dbremove(DB_ENV * env, DB_TXN *txn, const char *fname, const char *dbname, u
if (txn && r) {
if (r == EMFILE || r == ENFILE)
r = toku_ydb_do_error(env, r, "toku dbremove failed because open file limit reached\n");
- else
+ else if (r != ENOENT)
r = toku_ydb_do_error(env, r, "toku dbremove failed\n");
+ else
+ r = 0;
goto exit;
}
if (txn) {
diff --git a/storage/tokudb/ha_tokudb.cc b/storage/tokudb/ha_tokudb.cc
index 53dc2d20bb1..962b9928c5e 100644
--- a/storage/tokudb/ha_tokudb.cc
+++ b/storage/tokudb/ha_tokudb.cc
@@ -5254,17 +5254,17 @@ int ha_tokudb::fill_range_query_buf(
DEBUG_SYNC(ha_thd(), "tokudb_icp_asc_scan_out_of_range");
goto cleanup;
} else if (result == ICP_NO_MATCH) {
- // if we are performing a DESC ICP scan and have no end_range
- // to compare to stop using ICP filtering as there isn't much more
- // that we can do without going through contortions with remembering
- // and comparing key parts.
+ // Optimizer change for MyRocks also benefits us here in TokuDB as
+ // opt_range.cc QUICK_SELECT::get_next now sets end_range during
+ // descending scan. We should not ever hit this condition, but
+ // leaving this code in to prevent any possibility of a descending
+ // scan to the beginning of an index and catch any possibility
+ // in debug builds with an assertion
+ assert_debug(!(!end_range && direction < 0));
if (!end_range &&
direction < 0) {
-
cancel_pushed_idx_cond();
- DEBUG_SYNC(ha_thd(), "tokudb_icp_desc_scan_invalidate");
}
-
error = TOKUDB_CURSOR_CONTINUE;
goto cleanup;
}
@@ -6122,7 +6122,6 @@ int ha_tokudb::info(uint flag) {
stats.records = share->row_count() + share->rows_from_locked_table;
stats.deleted = 0;
if (!(flag & HA_STATUS_NO_LOCK)) {
- uint64_t num_rows = 0;
error = txn_begin(db_env, NULL, &txn, DB_READ_UNCOMMITTED, ha_thd());
if (error) {
@@ -6132,20 +6131,13 @@ int ha_tokudb::info(uint flag) {
// we should always have a primary key
assert_always(share->file != NULL);
- error = estimate_num_rows(share->file, &num_rows, txn);
- if (error == 0) {
- share->set_row_count(num_rows, false);
- stats.records = num_rows;
- } else {
- goto cleanup;
- }
-
DB_BTREE_STAT64 dict_stats;
error = share->file->stat64(share->file, txn, &dict_stats);
if (error) {
goto cleanup;
}
-
+ share->set_row_count(dict_stats.bt_ndata, false);
+ stats.records = dict_stats.bt_ndata;
stats.create_time = dict_stats.bt_create_time_sec;
stats.update_time = dict_stats.bt_modify_time_sec;
stats.check_time = dict_stats.bt_verify_time_sec;
@@ -7848,7 +7840,7 @@ ha_rows ha_tokudb::records_in_range(uint keynr, key_range* start_key, key_range*
// As a result, equal may be 0 and greater may actually be equal+greater
// So, we call key_range64 on the key, and the key that is after it.
if (!start_key && !end_key) {
- error = estimate_num_rows(kfile, &rows, transaction);
+ error = estimate_num_rows(share->file, &rows, transaction);
if (error) {
ret_val = HA_TOKUDB_RANGE_COUNT;
goto cleanup;
diff --git a/storage/tokudb/mysql-test/tokudb/r/bug-1657908.result b/storage/tokudb/mysql-test/tokudb/r/bug-1657908.result
new file mode 100644
index 00000000000..1d86478d833
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb/r/bug-1657908.result
@@ -0,0 +1,70 @@
+SET GLOBAL tokudb_dir_per_db=ON;
+CREATE PROCEDURE create_table()
+BEGIN
+CREATE TABLE test.t1 (
+a INT
+) ENGINE = TokuDB
+PARTITION BY RANGE (a)
+(PARTITION p100 VALUES LESS THAN (100) ENGINE = TokuDB,
+PARTITION p_to_del VALUES LESS THAN (200) ENGINE = TokuDB,
+PARTITION p300 VALUES LESS THAN (300) ENGINE = TokuDB,
+PARTITION p400 VALUES LESS THAN (400) ENGINE = TokuDB
+);
+END|
+### Create partitioned table
+CALL create_table();
+## Looking for *.tokudb files in data_dir
+## Looking for *.tokudb files in data_dir/test
+t1_P_p100_main_id.tokudb
+t1_P_p100_status_id.tokudb
+t1_P_p300_main_id.tokudb
+t1_P_p300_status_id.tokudb
+t1_P_p400_main_id.tokudb
+t1_P_p400_status_id.tokudb
+t1_P_p_to_del_main_id.tokudb
+t1_P_p_to_del_status_id.tokudb
+### Stop server
+### Remove 'main' file of one of the partitions
+### Start server
+### Make sure 'main' partition file is deleted
+## Looking for *.tokudb files in data_dir
+## Looking for *.tokudb files in data_dir/test
+t1_P_p100_main_id.tokudb
+t1_P_p100_status_id.tokudb
+t1_P_p300_main_id.tokudb
+t1_P_p300_status_id.tokudb
+t1_P_p400_main_id.tokudb
+t1_P_p400_status_id.tokudb
+t1_P_p_to_del_status_id.tokudb
+### Make sure the table still exists
+SHOW TABLES;
+Tables_in_test
+t1
+### Drop table
+DROP TABLE t1;
+### Make sure the table is dropped
+SHOW TABLES;
+Tables_in_test
+### Check what files still exist after DROP TABLE
+## Looking for *.tokudb files in data_dir
+## Looking for *.tokudb files in data_dir/test
+### Remove the rest of the files
+### Make sure there are no tokudb files
+## Looking for *.tokudb files in data_dir
+## Looking for *.tokudb files in data_dir/test
+### Create the same table once more
+CALL create_table();
+## Looking for *.tokudb files in data_dir
+## Looking for *.tokudb files in data_dir/test
+t1_P_p100_main_id.tokudb
+t1_P_p100_status_id.tokudb
+t1_P_p300_main_id.tokudb
+t1_P_p300_status_id.tokudb
+t1_P_p400_main_id.tokudb
+t1_P_p400_status_id.tokudb
+t1_P_p_to_del_main_id.tokudb
+t1_P_p_to_del_status_id.tokudb
+### Restore state
+DROP TABLE t1;
+DROP PROCEDURE create_table;
+SET GLOBAL tokudb_dir_per_db=default;
diff --git a/storage/tokudb/mysql-test/tokudb/r/dir_cmd.result b/storage/tokudb/mysql-test/tokudb/r/dir_cmd.result
new file mode 100644
index 00000000000..dd3b693db49
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb/r/dir_cmd.result
@@ -0,0 +1,58 @@
+SET GLOBAL tokudb_dir_per_db = ON;
+SET tokudb_dir_cmd = "attach test_dname_1 test_iname_1";
+SET tokudb_dir_cmd = "attach test_dname_2 test_iname_2";
+SELECT dictionary_name, internal_file_name
+FROM information_schema.TokuDB_file_map;
+dictionary_name internal_file_name
+test_dname_1 test_iname_1
+test_dname_2 test_iname_2
+SET tokudb_dir_cmd = "detach test_dname_1";
+SELECT dictionary_name, internal_file_name
+FROM information_schema.TokuDB_file_map;
+dictionary_name internal_file_name
+test_dname_2 test_iname_2
+SET tokudb_dir_cmd = "move test_dname_2 test_dname_3";
+SELECT dictionary_name, internal_file_name
+FROM information_schema.TokuDB_file_map;
+dictionary_name internal_file_name
+test_dname_3 test_iname_2
+SET tokudb_dir_cmd = "detach test_dname_3";
+SELECT dictionary_name, internal_file_name
+FROM information_schema.TokuDB_file_map;
+dictionary_name internal_file_name
+CREATE TABLE t1(a int) ENGINE=tokudb;
+INSERT INTO t1 (a) VALUES (10);
+SELECT dictionary_name, internal_file_name
+FROM information_schema.TokuDB_file_map;
+dictionary_name internal_file_name
+./test/t1-main ./test/t1_main_id.tokudb
+./test/t1-status ./test/t1_status_id.tokudb
+SET tokudb_dir_cmd = "attach ./test/t1-main test/t1-main-renamed.tokudb";
+SELECT dictionary_name, internal_file_name
+FROM information_schema.TokuDB_file_map;
+dictionary_name internal_file_name
+./test/t1-main test/t1-main-renamed.tokudb
+./test/t1-status ./test/t1_status_id.tokudb
+### rename t1_main_id.tokudb to t1-main-renamed.tokudb
+SELECT * FROM t1;
+a
+10
+### Test for errors notification
+SET tokudb_dir_cmd = "detach foo";
+ERROR 42000: Variable 'tokudb_dir_cmd' can't be set to the value of 'detach foo'
+SELECT @@tokudb_dir_cmd_last_error;
+@@tokudb_dir_cmd_last_error
+17
+SELECT @@tokudb_dir_cmd_last_error_string;
+@@tokudb_dir_cmd_last_error_string
+detach command error
+SET @@tokudb_dir_cmd_last_error_string = "blablabla";
+SELECT @@tokudb_dir_cmd_last_error_string;
+@@tokudb_dir_cmd_last_error_string
+blablabla
+SET STATEMENT tokudb_dir_cmd_last_error_string = "statement_blablabla" FOR
+SELECT @@tokudb_dir_cmd_last_error_string;
+@@tokudb_dir_cmd_last_error_string
+statement_blablabla
+DROP TABLE t1;
+SET GLOBAL tokudb_dir_per_db = default;
diff --git a/storage/tokudb/mysql-test/tokudb/t/background_job_manager.opt b/storage/tokudb/mysql-test/tokudb/t/background_job_manager.opt
deleted file mode 100644
index 3cc9ea3009e..00000000000
--- a/storage/tokudb/mysql-test/tokudb/t/background_job_manager.opt
+++ /dev/null
@@ -1 +0,0 @@
---tokudb-background-job-status
diff --git a/storage/tokudb/mysql-test/tokudb/t/background_job_manager.test b/storage/tokudb/mysql-test/tokudb/t/background_job_manager.test
index 933814442e0..709fc463696 100644
--- a/storage/tokudb/mysql-test/tokudb/t/background_job_manager.test
+++ b/storage/tokudb/mysql-test/tokudb/t/background_job_manager.test
@@ -1,3 +1,4 @@
+skip Background Job Manager not supported in MariaDB;
# This is a comprehensive test for the background job manager and
# the information_schema.tokudb_background_job_status table
#
diff --git a/storage/tokudb/mysql-test/tokudb/t/bug-1657908.test b/storage/tokudb/mysql-test/tokudb/t/bug-1657908.test
new file mode 100644
index 00000000000..adcf4ef55f6
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb/t/bug-1657908.test
@@ -0,0 +1,73 @@
+--source include/have_partition.inc
+# See https://bugs.launchpad.net/percona-server/+bug/1657908
+
+source include/have_tokudb.inc;
+
+SET GLOBAL tokudb_dir_per_db=ON;
+
+--let $DB= test
+--let $DATADIR= `SELECT @@datadir`
+
+--delimiter |
+CREATE PROCEDURE create_table()
+BEGIN
+CREATE TABLE test.t1 (
+ a INT
+) ENGINE = TokuDB
+PARTITION BY RANGE (a)
+(PARTITION p100 VALUES LESS THAN (100) ENGINE = TokuDB,
+ PARTITION p_to_del VALUES LESS THAN (200) ENGINE = TokuDB,
+ PARTITION p300 VALUES LESS THAN (300) ENGINE = TokuDB,
+ PARTITION p400 VALUES LESS THAN (400) ENGINE = TokuDB
+);
+END|
+--delimiter ;
+
+--echo ### Create partitioned table
+CALL create_table();
+--source dir_per_db_show_table_files.inc
+
+--echo ### Stop server
+--exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+--shutdown_server
+--source include/wait_until_disconnected.inc
+
+--echo ### Remove 'main' file of one of the partitions
+--remove_files_wildcard $DATADIR/$DB t1_P_p_to_del_main_*.tokudb
+
+--echo ### Start server
+--enable_reconnect
+--exec echo "restart: --loose-tokudb-dir-per-db=ON" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+--source include/wait_until_connected_again.inc
+
+--echo ### Make sure 'main' partition file is deleted
+--source dir_per_db_show_table_files.inc
+
+--echo ### Make sure the table still exists
+SHOW TABLES;
+
+--echo ### Drop table
+# error 1051 was here before the fix
+DROP TABLE t1;
+
+--echo ### Make sure the table is dropped
+SHOW TABLES;
+
+--echo ### Check what files still exist after DROP TABLE
+--source dir_per_db_show_table_files.inc
+
+--echo ### Remove the rest of the files
+--remove_files_wildcard $DATADIR/$DB *.tokudb
+
+--echo ### Make sure there are no tokudb files
+--source dir_per_db_show_table_files.inc
+
+--echo ### Create the same table once more
+# engine error 17 (EEXIST) was here before the fix
+CALL create_table();
+--source dir_per_db_show_table_files.inc
+
+--echo ### Restore state
+DROP TABLE t1;
+DROP PROCEDURE create_table;
+SET GLOBAL tokudb_dir_per_db=default;
diff --git a/storage/tokudb/mysql-test/tokudb/t/card_auto_analyze_lots.test b/storage/tokudb/mysql-test/tokudb/t/card_auto_analyze_lots.test
index ec74a4a28bc..9675449372b 100644
--- a/storage/tokudb/mysql-test/tokudb/t/card_auto_analyze_lots.test
+++ b/storage/tokudb/mysql-test/tokudb/t/card_auto_analyze_lots.test
@@ -1,3 +1,4 @@
+skip Background Job Manager not supported in MariaDB;
# Test the auto analyze on lots of tables
-- source include/have_tokudb.inc
diff --git a/storage/tokudb/mysql-test/tokudb/t/dir_cmd.test b/storage/tokudb/mysql-test/tokudb/t/dir_cmd.test
new file mode 100644
index 00000000000..b9d8c80de65
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb/t/dir_cmd.test
@@ -0,0 +1,52 @@
+skip TokuDB dir CMD disabled in MariaDB;
+source include/have_tokudb.inc;
+
+--let $MYSQL_DATADIR=`select @@datadir`
+
+SET GLOBAL tokudb_dir_per_db = ON;
+
+SET tokudb_dir_cmd = "attach test_dname_1 test_iname_1";
+SET tokudb_dir_cmd = "attach test_dname_2 test_iname_2";
+SELECT dictionary_name, internal_file_name
+ FROM information_schema.TokuDB_file_map;
+
+SET tokudb_dir_cmd = "detach test_dname_1";
+SELECT dictionary_name, internal_file_name
+ FROM information_schema.TokuDB_file_map;
+
+SET tokudb_dir_cmd = "move test_dname_2 test_dname_3";
+SELECT dictionary_name, internal_file_name
+ FROM information_schema.TokuDB_file_map;
+
+SET tokudb_dir_cmd = "detach test_dname_3";
+SELECT dictionary_name, internal_file_name
+ FROM information_schema.TokuDB_file_map;
+
+CREATE TABLE t1(a int) ENGINE=tokudb;
+INSERT INTO t1 (a) VALUES (10);
+--source include/table_files_replace_pattern.inc
+SELECT dictionary_name, internal_file_name
+ FROM information_schema.TokuDB_file_map;
+
+SET tokudb_dir_cmd = "attach ./test/t1-main test/t1-main-renamed.tokudb";
+--source include/table_files_replace_pattern.inc
+SELECT dictionary_name, internal_file_name
+ FROM information_schema.TokuDB_file_map;
+
+--echo ### rename t1_main_id.tokudb to t1-main-renamed.tokudb
+--exec mv $MYSQL_DATADIR/test/t1_main_*.tokudb $MYSQL_DATADIR/test/t1-main-renamed.tokudb
+
+SELECT * FROM t1;
+
+--echo ### Test for errors notification
+--error 1231
+SET tokudb_dir_cmd = "detach foo";
+SELECT @@tokudb_dir_cmd_last_error;
+SELECT @@tokudb_dir_cmd_last_error_string;
+SET @@tokudb_dir_cmd_last_error_string = "blablabla";
+SELECT @@tokudb_dir_cmd_last_error_string;
+SET STATEMENT tokudb_dir_cmd_last_error_string = "statement_blablabla" FOR
+ SELECT @@tokudb_dir_cmd_last_error_string;
+
+DROP TABLE t1;
+SET GLOBAL tokudb_dir_per_db = default;
diff --git a/storage/tokudb/mysql-test/tokudb/t/i_s_tokudb_lock_waits_timeout.test b/storage/tokudb/mysql-test/tokudb/t/i_s_tokudb_lock_waits_timeout.test
index 42fb548814f..8fe5e66a9b3 100644
--- a/storage/tokudb/mysql-test/tokudb/t/i_s_tokudb_lock_waits_timeout.test
+++ b/storage/tokudb/mysql-test/tokudb/t/i_s_tokudb_lock_waits_timeout.test
@@ -1,3 +1,4 @@
+skip Tokudb Lock Waits not in I_S in MariaDB;
# verify that tokudb_locks and tokudb_lock_waits contents for 2 conflicting transactions with a lock timeout
source include/have_tokudb.inc;
diff --git a/storage/tokudb/mysql-test/tokudb/t/i_s_tokudb_locks.test b/storage/tokudb/mysql-test/tokudb/t/i_s_tokudb_locks.test
index 8f205ad7f45..59d04ead386 100644
--- a/storage/tokudb/mysql-test/tokudb/t/i_s_tokudb_locks.test
+++ b/storage/tokudb/mysql-test/tokudb/t/i_s_tokudb_locks.test
@@ -1,3 +1,4 @@
+skip Tokudb Lock Waits not in I_S in MariaDB;
# verify that information_schema.tokudb_locks gets populated with locks for 2 clients
source include/have_tokudb.inc;
diff --git a/storage/tokudb/mysql-test/tokudb/t/i_s_tokudb_trx.test b/storage/tokudb/mysql-test/tokudb/t/i_s_tokudb_trx.test
index 517280391c4..b4ab64be962 100644
--- a/storage/tokudb/mysql-test/tokudb/t/i_s_tokudb_trx.test
+++ b/storage/tokudb/mysql-test/tokudb/t/i_s_tokudb_trx.test
@@ -1,3 +1,4 @@
+skip Tokudb trx not in I_S in MariaDB;
# verify that information_schema.tokudb_trx gets populated with transactions
source include/have_tokudb.inc;
diff --git a/storage/tokudb/mysql-test/tokudb_backup/r/backup_master_info.result b/storage/tokudb/mysql-test/tokudb_backup/r/backup_master_info.result
new file mode 100644
index 00000000000..992a828e287
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb_backup/r/backup_master_info.result
@@ -0,0 +1,26 @@
+###
+# Test for binlog position
+#####
+include/master-slave.inc
+Warnings:
+Note #### Sending passwords in plain text without SSL/TLS is extremely insecure.
+Note #### Storing MySQL user name or password information in the master info repository is not secure and is therefore not recommended. Please consider using the USER and PASSWORD connection options for START SLAVE; see the 'START SLAVE Syntax' in the MySQL Manual for more information.
+[connection master]
+CREATE TABLE t1(a INT) ENGINE=TokuDB;
+DROP TABLE t1;
+Backup
+include/filter_file.inc
+### tokubackup_slave_info content:
+host: #.#.#.#, user: ####, port: ####, master log file: ####, relay log file: ####, exec master log pos: ####, executed gtid set: , channel name:
+###
+# Test for gtid set
+#####
+include/rpl_set_gtid_mode.inc
+CREATE TABLE t1(a INT) ENGINE=TokuDB;
+DROP TABLE t1;
+Backup
+include/filter_file.inc
+### tokubackup_slave_info content:
+host: #.#.#.#, user: ####, port: ####, master log file: ####, relay log file: ####, exec master log pos: ####, executed gtid set: ####, channel name:
+include/rpl_set_gtid_mode.inc
+include/rpl_end.inc
diff --git a/storage/tokudb/mysql-test/tokudb_backup/r/backup_master_state.result b/storage/tokudb/mysql-test/tokudb_backup/r/backup_master_state.result
new file mode 100644
index 00000000000..072dfff448b
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb_backup/r/backup_master_state.result
@@ -0,0 +1,36 @@
+### Create backup dir
+include/master-slave.inc
+Warnings:
+Note #### Sending passwords in plain text without SSL/TLS is extremely insecure.
+Note #### Storing MySQL user name or password information in the master info repository is not secure and is therefore not recommended. Please consider using the USER and PASSWORD connection options for START SLAVE; see the 'START SLAVE Syntax' in the MySQL Manual for more information.
+[connection master]
+### Check for settings
+SELECT @@gtid_mode;
+@@gtid_mode
+OFF
+### Generate some binlog events
+CREATE TABLE t1(a INT) ENGINE=TokuDB;
+DROP TABLE t1;
+### Master backup
+include/filter_file.inc
+### tokubackup_binlog_info content:
+filename: ####, position: ####, gtid_mode: OFF, GTID of last change:
+### Delete backup dir
+### Create backup dir
+### GTID-mode on
+include/rpl_set_gtid_mode.inc
+### Check for settings
+SELECT @@gtid_mode;
+@@gtid_mode
+ON
+### Generate some binlog events
+CREATE TABLE t1(a INT) ENGINE=TokuDB;
+DROP TABLE t1;
+### Master backup
+include/filter_file.inc
+### tokubackup_binlog_info content:
+filename: ####, position: ####, gtid_mode: ON, GTID of last change: #####
+### Delete backup dir
+### GTID-mode off
+include/rpl_set_gtid_mode.inc
+include/rpl_end.inc
diff --git a/storage/tokudb/mysql-test/tokudb_backup/r/empty_slave_info_file.result b/storage/tokudb/mysql-test/tokudb_backup/r/empty_slave_info_file.result
new file mode 100644
index 00000000000..a0af40d80cc
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb_backup/r/empty_slave_info_file.result
@@ -0,0 +1 @@
+Backup
diff --git a/storage/tokudb/mysql-test/tokudb_backup/r/innodb_use_native_aio_enabled.result b/storage/tokudb/mysql-test/tokudb_backup/r/innodb_use_native_aio_enabled.result
new file mode 100644
index 00000000000..94e113fc87d
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb_backup/r/innodb_use_native_aio_enabled.result
@@ -0,0 +1,5 @@
+SELECT @@innodb_use_native_aio;
+@@innodb_use_native_aio
+1
+SET SESSION tokudb_backup_dir='MYSQL_TMP_DIR/tokudb_backup';
+ERROR 42000: Variable 'tokudb_backup_dir' can't be set to the value of 'MYSQL_TMP_DIR/tokudb_backup'
diff --git a/storage/tokudb/mysql-test/tokudb_backup/r/rpl_safe_slave.result b/storage/tokudb/mysql-test/tokudb_backup/r/rpl_safe_slave.result
new file mode 100644
index 00000000000..13b5915354f
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb_backup/r/rpl_safe_slave.result
@@ -0,0 +1,77 @@
+###
+# Master-slave test
+####
+include/rpl_init.inc [topology=1->2]
+Warnings:
+Note #### Sending passwords in plain text without SSL/TLS is extremely insecure.
+Note #### Storing MySQL user name or password information in the master info repository is not secure and is therefore not recommended. Please consider using the USER and PASSWORD connection options for START SLAVE; see the 'START SLAVE Syntax' in the MySQL Manual for more information.
+### Create temp table on master
+CREATE TEMPORARY TABLE t1 (a INT);
+include/sync_slave_sql_with_master.inc
+### Setup debug_sync points and prepare for slave backup
+SET SESSION debug="+d,debug_sync_abort_on_timeout";
+SHOW STATUS LIKE 'Slave_open_temp_tables';
+Variable_name Value
+Slave_open_temp_tables 1
+SET DEBUG_SYNC= 'tokudb_backup_wait_for_safe_slave_entered SIGNAL sse WAIT_FOR sse_continue';
+SET DEBUG_SYNC= 'tokudb_backup_wait_for_temp_tables_loop_begin SIGNAL ttlb WAIT_FOR ttlb_continue';
+SET DEBUG_SYNC= 'tokudb_backup_wait_for_temp_tables_loop_slave_started SIGNAL ttlss WAIT_FOR ttlss_continue EXECUTE 2';
+SET DEBUG_SYNC= 'tokudb_backup_wait_for_temp_tables_loop_end SIGNAL ttle WAIT_FOR ttle_continue';
+### Turn-on safe-slave option
+SET GLOBAL tokudb_backup_safe_slave=ON;
+SET GLOBAL tokudb_backup_safe_slave_timeout=30;
+### Start slave backup
+SET SESSION debug="+d,debug_sync_abort_on_timeout";
+### Wait for safe slave function to start
+SET DEBUG_SYNC = "now WAIT_FOR sse";
+SHOW STATUS LIKE 'Slave_open_temp_tables';
+Variable_name Value
+Slave_open_temp_tables 1
+### Wait for safe slave loop start
+SET DEBUG_SYNC = "now SIGNAL sse_continue WAIT_FOR ttlb";
+SHOW STATUS LIKE 'Slave_open_temp_tables';
+Variable_name Value
+Slave_open_temp_tables 1
+### Wait for safe thread loop point just after slave sql thread start 1
+SET DEBUG_SYNC = "now SIGNAL ttlb_continue WAIT_FOR ttlss";
+SHOW STATUS LIKE 'Slave_open_temp_tables';
+Variable_name Value
+Slave_open_temp_tables 1
+### Wait for safe thread loop end
+SET DEBUG_SYNC = "now SIGNAL ttlss_continue WAIT_FOR ttle";
+SHOW STATUS LIKE 'Slave_open_temp_tables';
+Variable_name Value
+Slave_open_temp_tables 1
+### Wait for safe thread loop point just after slave sql thread start 2
+SET DEBUG_SYNC = "now SIGNAL ttle_continue WAIT_FOR ttlss";
+### Drop temp table on master
+DROP TABLE t1;
+### and syncronize slave
+include/sync_slave_sql_with_master.inc
+SHOW STATUS LIKE 'Slave_open_temp_tables';
+Variable_name Value
+Slave_open_temp_tables 0
+### Continue backup
+SET DEBUG_SYNC = "now SIGNAL ttlss_continue";
+## Reset debug_sync points
+SET DEBUG_SYNC = "RESET";
+### Wait for backup finish
+include/filter_file.inc
+### Slave tokubackup_slave_info content:
+host: #.#.#.#, user: ####, port: ####, master log file: ####, relay log file: ####, exec master log pos: ####, executed gtid set: , channel name:
+### Delete slave backup dir
+### Turn-off safe-slave option for slave
+SET GLOBAL tokudb_backup_safe_slave=default;
+SET GLOBAL tokudb_backup_safe_slave_timeout=default;
+### Turn-on safe-slave option for master
+SET GLOBAL tokudb_backup_safe_slave=ON;
+SET GLOBAL tokudb_backup_safe_slave_timeout=30;
+### Backup master
+### Turn-off safe-slave option for master
+SET GLOBAL tokudb_backup_safe_slave=default;
+SET GLOBAL tokudb_backup_safe_slave_timeout=default;
+include/filter_file.inc
+### Master tokubackup_binlog_info content:
+filename: ####, position: ####, gtid_mode: OFF, GTID of last change:
+### Delete master backup dir
+include/rpl_end.inc
diff --git a/storage/tokudb/mysql-test/tokudb_backup/r/rpl_tokudb_commit_sync.result b/storage/tokudb/mysql-test/tokudb_backup/r/rpl_tokudb_commit_sync.result
new file mode 100644
index 00000000000..50508f073ab
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb_backup/r/rpl_tokudb_commit_sync.result
@@ -0,0 +1,59 @@
+include/master-slave.inc
+Warnings:
+Note #### Sending passwords in plain text without SSL/TLS is extremely insecure.
+Note #### Storing MySQL user name or password information in the master info repository is not secure and is therefore not recommended. Please consider using the USER and PASSWORD connection options for START SLAVE; see the 'START SLAVE Syntax' in the MySQL Manual for more information.
+[connection master]
+### Create some data on master
+CREATE TABLE t1(a INT, b INT, PRIMARY KEY (a)) ENGINE=TokuDB;
+INSERT INTO t1 SET a=100, b=100;
+INSERT INTO t1 SET a=200, b=100;
+INSERT INTO t1 SET a=300, b=100;
+INSERT INTO t1 SET a=400, b=100;
+INSERT INTO t1 SET a=500, b=100;
+UPDATE t1 SET b = 200 WHERE a = 200;
+DELETE FROM t1 WHERE a = 100;
+SELECT * FROM t1;
+a b
+200 200
+300 100
+400 100
+500 100
+### Check for slave options
+SELECT @@tokudb_commit_sync;
+@@tokudb_commit_sync
+0
+SELECT @@tokudb_fsync_log_period;
+@@tokudb_fsync_log_period
+1000000
+### Check data on slave after sync
+SELECT * FROM t1;
+a b
+200 200
+300 100
+400 100
+500 100
+### Do backup on slave
+### Check for errors
+SELECT @@session.tokudb_backup_last_error;
+@@session.tokudb_backup_last_error
+0
+SELECT @@session.tokudb_backup_last_error_string;
+@@session.tokudb_backup_last_error_string
+NULL
+### Stop slave server
+include/rpl_stop_server.inc [server_number=2]
+### Restore backup
+### Start slave server and slave threads
+include/rpl_start_server.inc [server_number=2]
+include/start_slave.inc
+### Sync slave with master
+### Check data on slave
+SELECT * FROM t1;
+a b
+200 200
+300 100
+400 100
+500 100
+### Cleanup
+DROP TABLE t1;
+include/rpl_end.inc
diff --git a/storage/tokudb/mysql-test/tokudb_backup/t/backup_master_info.test b/storage/tokudb/mysql-test/tokudb_backup/t/backup_master_info.test
new file mode 100644
index 00000000000..8e9f6df4b1d
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb_backup/t/backup_master_info.test
@@ -0,0 +1,94 @@
+--source include/have_tokudb_backup.inc
+--source include/not_gtid_enabled.inc
+
+
+--let $SLAVE_INFO_FILE=tokubackup_slave_info
+--let $BACKUP_DIR_SLAVE=$MYSQL_TMP_DIR/tokudb_backup_slave
+--let $SLAVE_INFO_FILE_PATH=$BACKUP_DIR_SLAVE/$SLAVE_INFO_FILE
+--let DDIR=$BACKUP_DIR_SLAVE
+
+# Settings for include/filter_file.inc
+
+--delimiter |
+let $script=
+ s{host: [^,]+,}{host: #.#.#.#,};
+ s{user: [^,]+,}{user: ####,};
+ s{port: [^,]+,}{port: ####,};
+ s{master log file: [^,]+,}{master log file: ####,};
+ s{relay log file: [^,]+,}{relay log file: ####,};
+ s{exec master log pos: [^,]+,}{exec master log pos: ####,};
+ s{executed gtid set: [^,]+, }{executed gtid set: ####, };
+ s{executed gtid set: [^,]+,[^,]+, }{executed gtid set: ####,####, };
+|
+--delimiter ;
+--let $input_file = $SLAVE_INFO_FILE_PATH
+--let $skip_column_names= 1
+
+--echo ###
+--echo # Test for binlog position
+--echo #####
+
+--mkdir $BACKUP_DIR_SLAVE
+
+--source include/master-slave.inc
+
+--connection master
+CREATE TABLE t1(a INT) ENGINE=TokuDB;
+DROP TABLE t1;
+
+--sync_slave_with_master
+
+--connection slave
+--echo Backup
+--disable_query_log
+--eval SET SESSION tokudb_backup_dir='$BACKUP_DIR_SLAVE'
+--enable_query_log
+
+--source include/filter_file.inc
+--echo ### $SLAVE_INFO_FILE content:
+--cat_file $SLAVE_INFO_FILE_PATH
+
+--perl
+use File::Path 'rmtree';
+$DDIR=$ENV{"DDIR"};
+rmtree([ "$DDIR" ]);
+EOF
+
+--echo ###
+--echo # Test for gtid set
+--echo #####
+
+--mkdir $BACKUP_DIR_SLAVE
+
+--let $rpl_server_numbers= 1,2
+--let $rpl_set_enforce_gtid_consistency= 1
+--source include/rpl_set_gtid_mode.inc
+
+--connection master
+CREATE TABLE t1(a INT) ENGINE=TokuDB;
+DROP TABLE t1;
+
+--sync_slave_with_master
+
+--connection slave
+--echo Backup
+--disable_query_log
+--eval SET SESSION tokudb_backup_dir='$BACKUP_DIR_SLAVE'
+--enable_query_log
+
+--source include/filter_file.inc
+--echo ### $SLAVE_INFO_FILE content:
+--cat_file $SLAVE_INFO_FILE_PATH
+
+--perl
+use File::Path 'rmtree';
+$DDIR=$ENV{"DDIR"};
+rmtree([ "$DDIR" ]);
+EOF
+
+--let $rpl_gtid_mode= OFF
+--let $rpl_set_enforce_gtid_consistency= 0
+--let $rpl_server_numbers= 1,2
+--let $rpl_skip_sync= 1
+--source include/rpl_set_gtid_mode.inc
+--source include/rpl_end.inc
diff --git a/storage/tokudb/mysql-test/tokudb_backup/t/backup_master_state.test b/storage/tokudb/mysql-test/tokudb_backup/t/backup_master_state.test
new file mode 100644
index 00000000000..c301d55f8fa
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb_backup/t/backup_master_state.test
@@ -0,0 +1,87 @@
+--source include/have_tokudb_backup.inc
+--source include/not_gtid_enabled.inc
+
+--let $MASTER_STATE_FILE=tokubackup_binlog_info
+--let $BACKUP_DIR_MASTER=$MYSQL_TMP_DIR/tokudb_backup_master
+--let $MASTER_STATE_FILE_PATH=$BACKUP_DIR_MASTER/$MASTER_STATE_FILE
+--let DDIR=$BACKUP_DIR_MASTER
+
+# Settings for include/filter_file.inc
+--delimiter |
+let $script=
+ s{filename: [^,]+,}{filename: ####,};
+ s{position: [^,]+,}{position: ####,};
+ s{GTID of last change: [^ ]+}{GTID of last change: #####};
+|
+--delimiter ;
+--let $input_file = $MASTER_STATE_FILE_PATH
+--let $skip_column_names= 1
+
+--echo ### Create backup dir
+--mkdir $BACKUP_DIR_MASTER
+
+--source include/master-slave.inc
+
+--connection master
+
+--echo ### Check for settings
+SELECT @@gtid_mode;
+
+--echo ### Generate some binlog events
+CREATE TABLE t1(a INT) ENGINE=TokuDB;
+DROP TABLE t1;
+
+--echo ### Master backup
+--disable_query_log
+--eval SET SESSION tokudb_backup_dir='$BACKUP_DIR_MASTER'
+--enable_query_log
+
+--source include/filter_file.inc
+--echo ### $MASTER_STATE_FILE content:
+--cat_file $MASTER_STATE_FILE_PATH
+
+--echo ### Delete backup dir
+--perl
+use File::Path 'rmtree';
+$DDIR=$ENV{"DDIR"};
+rmtree([ "$DDIR" ]);
+EOF
+
+--echo ### Create backup dir
+--mkdir $BACKUP_DIR_MASTER
+
+--echo ### GTID-mode on
+--let $rpl_server_numbers= 1,2
+--let $rpl_set_enforce_gtid_consistency= 1
+--source include/rpl_set_gtid_mode.inc
+
+--echo ### Check for settings
+SELECT @@gtid_mode;
+
+--echo ### Generate some binlog events
+CREATE TABLE t1(a INT) ENGINE=TokuDB;
+DROP TABLE t1;
+
+--echo ### Master backup
+--disable_query_log
+--eval SET SESSION tokudb_backup_dir='$BACKUP_DIR_MASTER'
+--enable_query_log
+
+--source include/filter_file.inc
+--echo ### $MASTER_STATE_FILE content:
+--cat_file $MASTER_STATE_FILE_PATH
+
+--echo ### Delete backup dir
+--perl
+use File::Path 'rmtree';
+$DDIR=$ENV{"DDIR"};
+rmtree([ "$DDIR" ]);
+EOF
+
+--echo ### GTID-mode off
+--let $rpl_gtid_mode= OFF
+--let $rpl_set_enforce_gtid_consistency= 0
+--let $rpl_server_numbers= 1,2
+--source include/rpl_set_gtid_mode.inc
+
+--source include/rpl_end.inc
diff --git a/storage/tokudb/mysql-test/tokudb_backup/t/empty_slave_info_file.test b/storage/tokudb/mysql-test/tokudb_backup/t/empty_slave_info_file.test
new file mode 100644
index 00000000000..53592903a27
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb_backup/t/empty_slave_info_file.test
@@ -0,0 +1,23 @@
+--source include/have_tokudb_backup.inc
+--source include/not_gtid_enabled.inc
+
+
+--let $SLAVE_INFO_FILE=tokubackup_slave_info
+--let $BACKUP_DIR_SLAVE=$MYSQL_TMP_DIR/tokudb_backup_slave
+--let DDIR=$BACKUP_DIR_SLAVE
+
+--mkdir $BACKUP_DIR_SLAVE
+
+--echo Backup
+--disable_query_log
+--eval SET SESSION tokudb_backup_dir='$BACKUP_DIR_SLAVE'
+--enable_query_log
+
+--list_files $BACKUP_DIR_SLAVE $SLAVE_INFO_FILE
+
+--perl
+use File::Path 'rmtree';
+$DDIR=$ENV{"DDIR"};
+rmtree([ "$DDIR" ]);
+EOF
+
diff --git a/storage/tokudb/mysql-test/tokudb_backup/t/innodb_use_native_aio_enabled-master.opt b/storage/tokudb/mysql-test/tokudb_backup/t/innodb_use_native_aio_enabled-master.opt
new file mode 100644
index 00000000000..5f5dbb9c7c6
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb_backup/t/innodb_use_native_aio_enabled-master.opt
@@ -0,0 +1 @@
+--innodb_use_native_aio=on
diff --git a/storage/tokudb/mysql-test/tokudb_backup/t/innodb_use_native_aio_enabled.test b/storage/tokudb/mysql-test/tokudb_backup/t/innodb_use_native_aio_enabled.test
new file mode 100644
index 00000000000..3e09b465c02
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb_backup/t/innodb_use_native_aio_enabled.test
@@ -0,0 +1,19 @@
+# Check if tokudb hot backup is prevented if innodb_use_native_aio enabled
+--source include/have_tokudb_backup.inc
+--source include/have_innodb.inc
+
+SELECT @@innodb_use_native_aio;
+
+--let BACKUP_DIR= $MYSQL_TMP_DIR/tokudb_backup
+
+--mkdir $BACKUP_DIR
+
+--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR
+--error ER_WRONG_VALUE_FOR_VAR
+--eval SET SESSION tokudb_backup_dir='$BACKUP_DIR'
+
+--perl
+use File::Path 'rmtree';
+$DDIR=$ENV{"BACKUP_DIR"};
+rmtree([ "$DDIR" ]);
+EOF
diff --git a/storage/tokudb/mysql-test/tokudb_backup/t/rpl_safe_slave-master.opt b/storage/tokudb/mysql-test/tokudb_backup/t/rpl_safe_slave-master.opt
new file mode 100644
index 00000000000..af3a211967b
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb_backup/t/rpl_safe_slave-master.opt
@@ -0,0 +1 @@
+--binlog-format=statement
diff --git a/storage/tokudb/mysql-test/tokudb_backup/t/rpl_safe_slave-slave.opt b/storage/tokudb/mysql-test/tokudb_backup/t/rpl_safe_slave-slave.opt
new file mode 100644
index 00000000000..49405b1aec3
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb_backup/t/rpl_safe_slave-slave.opt
@@ -0,0 +1 @@
+--master-info-repository=TABLE --relay-log-info-repository=TABLE
diff --git a/storage/tokudb/mysql-test/tokudb_backup/t/rpl_safe_slave.cnf b/storage/tokudb/mysql-test/tokudb_backup/t/rpl_safe_slave.cnf
new file mode 100644
index 00000000000..321be4ab2fc
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb_backup/t/rpl_safe_slave.cnf
@@ -0,0 +1,14 @@
+!include ../../rpl/my.cnf
+
+[mysqld.1]
+
+[mysqld.2]
+
+[mysqld.3]
+master-info-repository=TABLE
+relay-log-info-repository=TABLE
+
+[ENV]
+SERVER_MYPORT_3= @mysqld.3.port
+SERVER_MYSOCK_3= @mysqld.3.socket
+
diff --git a/storage/tokudb/mysql-test/tokudb_backup/t/rpl_safe_slave.inc b/storage/tokudb/mysql-test/tokudb_backup/t/rpl_safe_slave.inc
new file mode 100644
index 00000000000..e0732ee63fc
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb_backup/t/rpl_safe_slave.inc
@@ -0,0 +1,112 @@
+--connection server_1
+--echo ### Create temp table on master
+CREATE TEMPORARY TABLE t1 (a INT);
+
+--let $sync_slave_connection= server_2
+--source include/sync_slave_sql_with_master.inc
+
+--echo ### Setup debug_sync points and prepare for slave backup
+--connection slave_2
+SET SESSION debug="+d,debug_sync_abort_on_timeout";
+
+SHOW STATUS LIKE 'Slave_open_temp_tables';
+
+SET DEBUG_SYNC= 'tokudb_backup_wait_for_safe_slave_entered SIGNAL sse WAIT_FOR sse_continue';
+SET DEBUG_SYNC= 'tokudb_backup_wait_for_temp_tables_loop_begin SIGNAL ttlb WAIT_FOR ttlb_continue';
+SET DEBUG_SYNC= 'tokudb_backup_wait_for_temp_tables_loop_slave_started SIGNAL ttlss WAIT_FOR ttlss_continue EXECUTE 2';
+SET DEBUG_SYNC= 'tokudb_backup_wait_for_temp_tables_loop_end SIGNAL ttle WAIT_FOR ttle_continue';
+
+--mkdir $BACKUP_DIR_SLAVE
+
+--echo ### Turn-on safe-slave option
+SET GLOBAL tokudb_backup_safe_slave=ON;
+SET GLOBAL tokudb_backup_safe_slave_timeout=30;
+
+--echo ### Start slave backup
+--disable_query_log
+--send_eval SET SESSION tokudb_backup_dir='$BACKUP_DIR_SLAVE'
+--enable_query_log
+
+--connection server_2
+SET SESSION debug="+d,debug_sync_abort_on_timeout";
+
+--echo ### Wait for safe slave function to start
+SET DEBUG_SYNC = "now WAIT_FOR sse";
+SHOW STATUS LIKE 'Slave_open_temp_tables';
+--echo ### Wait for safe slave loop start
+SET DEBUG_SYNC = "now SIGNAL sse_continue WAIT_FOR ttlb";
+SHOW STATUS LIKE 'Slave_open_temp_tables';
+--echo ### Wait for safe thread loop point just after slave sql thread start 1
+SET DEBUG_SYNC = "now SIGNAL ttlb_continue WAIT_FOR ttlss";
+SHOW STATUS LIKE 'Slave_open_temp_tables';
+--echo ### Wait for safe thread loop end
+SET DEBUG_SYNC = "now SIGNAL ttlss_continue WAIT_FOR ttle";
+SHOW STATUS LIKE 'Slave_open_temp_tables';
+
+--echo ### Wait for safe thread loop point just after slave sql thread start 2
+SET DEBUG_SYNC = "now SIGNAL ttle_continue WAIT_FOR ttlss";
+
+--connection server_1
+--echo ### Drop temp table on master
+DROP TABLE t1;
+
+--echo ### and syncronize slave
+--let $sync_slave_connection= server_2
+--source include/sync_slave_sql_with_master.inc
+
+SHOW STATUS LIKE 'Slave_open_temp_tables';
+
+--echo ### Continue backup
+SET DEBUG_SYNC = "now SIGNAL ttlss_continue";
+
+--echo ## Reset debug_sync points
+SET DEBUG_SYNC = "RESET";
+
+--connection slave_2
+--echo ### Wait for backup finish
+--reap
+
+--let $input_file = $S_SLAVE_INFO_FILE_PATH
+--source include/filter_file.inc
+--echo ### Slave $SLAVE_INFO_FILE content:
+--cat_file $S_SLAVE_INFO_FILE_PATH
+
+--echo ### Delete slave backup dir
+--perl
+use File::Path 'rmtree';
+$DDIR=$ENV{"BACKUP_DIR_SLAVE"};
+rmtree([ "$DDIR" ]);
+EOF
+
+--echo ### Turn-off safe-slave option for slave
+SET GLOBAL tokudb_backup_safe_slave=default;
+SET GLOBAL tokudb_backup_safe_slave_timeout=default;
+
+--connection server_1
+
+--echo ### Turn-on safe-slave option for master
+SET GLOBAL tokudb_backup_safe_slave=ON;
+SET GLOBAL tokudb_backup_safe_slave_timeout=30;
+
+--echo ### Backup master
+--mkdir $BACKUP_DIR_MASTER
+--disable_query_log
+--eval SET SESSION tokudb_backup_dir='$BACKUP_DIR_MASTER'
+--enable_query_log
+
+--echo ### Turn-off safe-slave option for master
+SET GLOBAL tokudb_backup_safe_slave=default;
+SET GLOBAL tokudb_backup_safe_slave_timeout=default;
+
+--let $input_file = $M_MASTER_INFO_FILE_PATH
+--source include/filter_file.inc
+--echo ### Master $MASTER_INFO_FILE content:
+--cat_file $M_MASTER_INFO_FILE_PATH
+
+--echo ### Delete master backup dir
+--perl
+use File::Path 'rmtree';
+$DDIR=$ENV{"BACKUP_DIR_MASTER"};
+rmtree([ "$DDIR" ]);
+EOF
+
diff --git a/storage/tokudb/mysql-test/tokudb_backup/t/rpl_safe_slave.test b/storage/tokudb/mysql-test/tokudb_backup/t/rpl_safe_slave.test
new file mode 100644
index 00000000000..15ba1d8bb66
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb_backup/t/rpl_safe_slave.test
@@ -0,0 +1,49 @@
+--source include/have_tokudb_backup.inc
+--source include/have_binlog_format_statement.inc
+--source include/have_debug_sync.inc
+
+--let $SLAVE_INFO_FILE=tokubackup_slave_info
+--let $MASTER_INFO_FILE=tokubackup_binlog_info
+
+--let BACKUP_DIR_SLAVE=$MYSQL_TMP_DIR/tokudb_backup_slave
+--let $S_SLAVE_INFO_FILE_PATH=$BACKUP_DIR_SLAVE/$SLAVE_INFO_FILE
+
+--let BACKUP_DIR_MASTER=$MYSQL_TMP_DIR/tokudb_backup_master
+--let $M_MASTER_INFO_FILE_PATH=$BACKUP_DIR_MASTER/$MASTER_INFO_FILE
+
+# Settings for include/filter_file.inc
+--delimiter |
+let $script=
+ s{filename: [^,]+,}{filename: ####,};
+ s{position: [^,]+,}{position: ####,};
+ s{GTID of last change: [^ ]+}{GTID of last change: #####};
+ s{host: [^,]+,}{host: #.#.#.#,};
+ s{user: [^,]+,}{user: ####,};
+ s{port: [^,]+,}{port: ####,};
+ s{master log file: [^,]+,}{master log file: ####,};
+ s{relay log file: [^,]+,}{relay log file: ####,};
+ s{exec master log pos: [^,]+,}{exec master log pos: ####,};
+ s{executed gtid set: [^,]+, }{executed gtid set: ####, };
+ s{executed gtid set: [^,]+,[^,]+, }{executed gtid set: ####,####, };
+|
+--delimiter ;
+--let $skip_column_names= 1
+
+--disable_query_log
+CALL mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT");
+CALL mtr.add_suppression("Sending passwords in plain text without SSL/TLS is extremely insecure");
+--enable_query_log
+
+--echo ###
+--echo # Master-slave test
+--echo ####
+
+--let $rpl_server_count=3
+--let $rpl_topology=1->2
+--source include/rpl_init.inc
+
+--connect (slave_2,localhost,root,,test,$SLAVE_MYPORT,$SLAVE_MYSOCK)
+
+--source rpl_safe_slave.inc
+
+--source include/rpl_end.inc
diff --git a/storage/tokudb/mysql-test/tokudb_backup/t/rpl_tokudb_commit_sync-slave.opt b/storage/tokudb/mysql-test/tokudb_backup/t/rpl_tokudb_commit_sync-slave.opt
new file mode 100644
index 00000000000..263e1aef0ab
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb_backup/t/rpl_tokudb_commit_sync-slave.opt
@@ -0,0 +1 @@
+--loose-tokudb-commit-sync=OFF --loose-tokudb-fsync-log-period=1000000
diff --git a/storage/tokudb/mysql-test/tokudb_backup/t/rpl_tokudb_commit_sync.test b/storage/tokudb/mysql-test/tokudb_backup/t/rpl_tokudb_commit_sync.test
new file mode 100644
index 00000000000..5bd53cacdab
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb_backup/t/rpl_tokudb_commit_sync.test
@@ -0,0 +1,72 @@
+# if --tokudb-commit-sync is off on slave tokudb log must be flushed on backup
+# to provide the ability to restore replication after backup restoring
+
+--source include/have_tokudb_backup.inc
+
+--let $BACKUP_DIR_SLAVE= $MYSQL_TMP_DIR/tokudb_backup_slave
+--let $BACKUP_MYSQL_DATA_DIR= $BACKUP_DIR_SLAVE/mysql_data_dir
+
+--mkdir $BACKUP_DIR_SLAVE
+
+--source include/master-slave.inc
+
+--echo ### Create some data on master
+--connection master
+CREATE TABLE t1(a INT, b INT, PRIMARY KEY (a)) ENGINE=TokuDB;
+INSERT INTO t1 SET a=100, b=100;
+INSERT INTO t1 SET a=200, b=100;
+INSERT INTO t1 SET a=300, b=100;
+INSERT INTO t1 SET a=400, b=100;
+INSERT INTO t1 SET a=500, b=100;
+UPDATE t1 SET b = 200 WHERE a = 200;
+DELETE FROM t1 WHERE a = 100;
+
+SELECT * FROM t1;
+
+--sync_slave_with_master
+--let $SLAVE_DATA_DIR=`SELECT @@DATADIR`
+
+--echo ### Check for slave options
+SELECT @@tokudb_commit_sync;
+SELECT @@tokudb_fsync_log_period;
+
+--echo ### Check data on slave after sync
+SELECT * FROM t1;
+
+
+--echo ### Do backup on slave
+--disable_query_log
+--eval SET SESSION tokudb_backup_dir='$BACKUP_DIR_SLAVE'
+--enable_query_log
+
+--echo ### Check for errors
+SELECT @@session.tokudb_backup_last_error;
+SELECT @@session.tokudb_backup_last_error_string;
+
+--echo ### Stop slave server
+--connection slave
+--let $rpl_server_number= 2
+--let $rpl_force_stop= 1
+--source include/rpl_stop_server.inc
+
+--echo ### Restore backup
+--exec rm -rf $SLAVE_DATA_DIR;
+--exec mv $BACKUP_MYSQL_DATA_DIR $SLAVE_DATA_DIR;
+
+--echo ### Start slave server and slave threads
+--connection slave
+--source include/rpl_start_server.inc
+--source include/start_slave.inc
+
+--echo ### Sync slave with master
+--connection master
+--sync_slave_with_master
+
+--echo ### Check data on slave
+SELECT * FROM t1;
+
+--echo ### Cleanup
+--connection master
+DROP TABLE t1;
+
+--source include/rpl_end.inc
diff --git a/storage/tokudb/mysql-test/tokudb_backup/t/suite.opt b/storage/tokudb/mysql-test/tokudb_backup/t/suite.opt
index 5d4cb245e27..a624d6895cc 100644
--- a/storage/tokudb/mysql-test/tokudb_backup/t/suite.opt
+++ b/storage/tokudb/mysql-test/tokudb_backup/t/suite.opt
@@ -1 +1 @@
-$TOKUDB_OPT $TOKUDB_LOAD_ADD_PATH $TOKUDB_BACKUP_OPT $TOKUDB_BACKUP_LOAD_ADD_PATH --loose-tokudb-check-jemalloc=0 --loose-tokudb-cache-size=512M --loose-tokudb-block-size=1M
+$TOKUDB_OPT $TOKUDB_LOAD_ADD_PATH $TOKUDB_BACKUP_OPT $TOKUDB_BACKUP_LOAD_ADD_PATH --loose-innodb_use_native_aio=off --loose-tokudb-check-jemalloc=0 --loose-tokudb-cache-size=512M --loose-tokudb-block-size=1M
diff --git a/storage/tokudb/mysql-test/tokudb_bugs/r/db233.result b/storage/tokudb/mysql-test/tokudb_bugs/r/db233.result
index e5808f52e69..a7cdbcae1e2 100644
--- a/storage/tokudb/mysql-test/tokudb_bugs/r/db233.result
+++ b/storage/tokudb/mysql-test/tokudb_bugs/r/db233.result
@@ -14,16 +14,6 @@ INSERT INTO t1 VALUES(1, 1, '1', '1'), (2, 2, '2', '2'), (3, 3, '3', '3'), (4, 4
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
test.t1 analyze status OK
-set DEBUG_SYNC = 'tokudb_icp_desc_scan_invalidate SIGNAL hit1 WAIT_FOR done1';
-SELECT c FROM t1 WHERE id BETWEEN 5 AND 8 ORDER BY id DESC;
-set DEBUG_SYNC = 'now WAIT_FOR hit1';
-set DEBUG_SYNC = 'now SIGNAL done1';
-c
-8
-7
-6
-6
-5
set DEBUG_SYNC = 'tokudb_icp_asc_scan_out_of_range SIGNAL hit2 WAIT_FOR done2';
SELECT c FROM t1 WHERE id BETWEEN 5 AND 8 ORDER BY id ASC;
set DEBUG_SYNC = 'now WAIT_FOR hit2';
diff --git a/storage/tokudb/mysql-test/tokudb_bugs/t/db233.test b/storage/tokudb/mysql-test/tokudb_bugs/t/db233.test
index 8e4c3b73c09..fec11bf0553 100644
--- a/storage/tokudb/mysql-test/tokudb_bugs/t/db233.test
+++ b/storage/tokudb/mysql-test/tokudb_bugs/t/db233.test
@@ -29,24 +29,6 @@ ANALYZE TABLE t1;
# lets flip to another connection
connect(conn1, localhost, root);
-# set up the DEBUG_SYNC point
-set DEBUG_SYNC = 'tokudb_icp_desc_scan_invalidate SIGNAL hit1 WAIT_FOR done1';
-
-# send the query
-send SELECT c FROM t1 WHERE id BETWEEN 5 AND 8 ORDER BY id DESC;
-
-# back to default connection
-connection default;
-
-# wait for the ICP reverse scan to invalidate
-set DEBUG_SYNC = 'now WAIT_FOR hit1';
-
-# lets release and clean up
-set DEBUG_SYNC = 'now SIGNAL done1';
-
-connection conn1;
-reap;
-
# set up the DEBUG_SYNC point again, but for the out of range
set DEBUG_SYNC = 'tokudb_icp_asc_scan_out_of_range SIGNAL hit2 WAIT_FOR done2';
diff --git a/storage/tokudb/mysql-test/tokudb_bugs/t/db397_delete_trigger.test b/storage/tokudb/mysql-test/tokudb_bugs/t/db397_delete_trigger.test
index 79043664607..7343768a7d7 100644
--- a/storage/tokudb/mysql-test/tokudb_bugs/t/db397_delete_trigger.test
+++ b/storage/tokudb/mysql-test/tokudb_bugs/t/db397_delete_trigger.test
@@ -1,3 +1,4 @@
+skip Tokudb Lock Waits not in I_S in MariaDB;
# check for any locking weirdness on DELETE triggers
source include/have_tokudb.inc;
set default_storage_engine='tokudb';
diff --git a/storage/tokudb/mysql-test/tokudb_bugs/t/db397_insert_trigger.test b/storage/tokudb/mysql-test/tokudb_bugs/t/db397_insert_trigger.test
index ffe2face9f2..313b1f96b52 100644
--- a/storage/tokudb/mysql-test/tokudb_bugs/t/db397_insert_trigger.test
+++ b/storage/tokudb/mysql-test/tokudb_bugs/t/db397_insert_trigger.test
@@ -1,3 +1,4 @@
+skip Tokudb Lock Waits not in I_S in MariaDB;
# check for any locking weirdness on INSERT triggers
source include/have_tokudb.inc;
set default_storage_engine='tokudb';
diff --git a/storage/tokudb/mysql-test/tokudb_bugs/t/db397_update_trigger.test b/storage/tokudb/mysql-test/tokudb_bugs/t/db397_update_trigger.test
index 063a88cb4ab..ce1eb6bddd1 100644
--- a/storage/tokudb/mysql-test/tokudb_bugs/t/db397_update_trigger.test
+++ b/storage/tokudb/mysql-test/tokudb_bugs/t/db397_update_trigger.test
@@ -1,3 +1,4 @@
+skip Tokudb Lock Waits not in I_S in MariaDB;
# check for any locking weirdness on UPDATE triggers
source include/have_tokudb.inc;
set default_storage_engine='tokudb';
diff --git a/storage/tokudb/mysql-test/tokudb_bugs/t/db938.test b/storage/tokudb/mysql-test/tokudb_bugs/t/db938.test
index 50434a79a00..d65bf3d95de 100644
--- a/storage/tokudb/mysql-test/tokudb_bugs/t/db938.test
+++ b/storage/tokudb/mysql-test/tokudb_bugs/t/db938.test
@@ -1,3 +1,4 @@
+skip Background Job Manager not supported in MariaDB;
# This test for DB-938 tests a race condition where a scheduled background job
# (analyze) ends up operating on a set of DB* key_file[] in TOKUDB_SHARE that
# were set to NULL during a TRUNCATE TABLE operation.
diff --git a/storage/tokudb/mysql-test/tokudb_bugs/t/db945.test b/storage/tokudb/mysql-test/tokudb_bugs/t/db945.test
index 27b0d284484..7996f9f5792 100644
--- a/storage/tokudb/mysql-test/tokudb_bugs/t/db945.test
+++ b/storage/tokudb/mysql-test/tokudb_bugs/t/db945.test
@@ -1,3 +1,4 @@
+skip Background Job Manager not supported in MariaDB;
source include/have_tokudb.inc;
set default_storage_engine='tokudb';
disable_warnings;
diff --git a/storage/tokudb/mysql-test/tokudb_bugs/t/leak172.test b/storage/tokudb/mysql-test/tokudb_bugs/t/leak172.test
index 9d82604e4b1..28cfff14770 100644
--- a/storage/tokudb/mysql-test/tokudb_bugs/t/leak172.test
+++ b/storage/tokudb/mysql-test/tokudb_bugs/t/leak172.test
@@ -132,6 +132,7 @@ CREATE TABLE `t2` (
);
LOAD DATA INFILE 'leak172_t1.data' INTO TABLE `t1` fields terminated by ',';
+remove_file $MYSQLD_DATADIR/test/leak172_t1.data;
connect(conn1,localhost,root,,);
set session debug_dbug="+d,tokudb_end_bulk_insert_sleep";
@@ -145,6 +146,7 @@ UPDATE t1, t2 SET t1.`c5` = 4 WHERE t1.`c6` <= 'o';
connection conn1;
reap;
+remove_file $MYSQLD_DATADIR/test/leak172_t2.data;
connection default;
disconnect conn1;
diff --git a/storage/tokudb/mysql-test/tokudb_bugs/t/tokudb718.test b/storage/tokudb/mysql-test/tokudb_bugs/t/tokudb718.test
index 735a88afed8..e7ef3211401 100644
--- a/storage/tokudb/mysql-test/tokudb_bugs/t/tokudb718.test
+++ b/storage/tokudb/mysql-test/tokudb_bugs/t/tokudb718.test
@@ -1,3 +1,4 @@
+skip Tokudb Fractal Tree info not in I_S in MariaDB;
# test DB-718, a crash caused by broken error handling in tokudb's fractal_tree_info information schema
source include/have_tokudb.inc;
set default_storage_engine='tokudb';
diff --git a/storage/tokudb/tokudb_dir_cmd.cc b/storage/tokudb/tokudb_dir_cmd.cc
new file mode 100644
index 00000000000..f9995302d49
--- /dev/null
+++ b/storage/tokudb/tokudb_dir_cmd.cc
@@ -0,0 +1,331 @@
+/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4:
+/* -*- mode: C; c-basic-offset: 4 -*- */
+#ident "$Id$"
+/*======
+This file is part of TokuDB
+
+
+Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved.
+
+ TokuDBis is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License, version 2,
+ as published by the Free Software Foundation.
+
+ TokuDB is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with TokuDB. If not, see <http://www.gnu.org/licenses/>.
+
+======= */
+
+#ident "Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved."
+
+#include "hatoku_hton.h"
+#include "tokudb_dir_cmd.h"
+#include "my_dbug.h"
+#include "sql_base.h"
+
+#include <vector>
+#include <string>
+
+namespace tokudb {
+
+const char tokens_delimiter = ' ';
+const char tokens_escape_delimiter_char = '\\';
+
+static int MDL_and_TDC(THD *thd,
+ const char *db,
+ const char *table,
+ const dir_cmd_callbacks &cb) {
+ int error;
+ LEX_STRING db_arg;
+ LEX_STRING table_arg;
+
+ db_arg.str = const_cast<char *>(db);
+ db_arg.length = strlen(db);;
+ table_arg.str = const_cast<char *>(table);
+ table_arg.length = strlen(table);
+ Table_ident table_ident(thd, db_arg, table_arg, true);;
+ thd->lex->select_lex.add_table_to_list(
+ thd, &table_ident, NULL, 1, TL_UNLOCK, MDL_EXCLUSIVE, 0, 0, 0);
+ /* The lock will be released at the end of mysq_execute_command() */
+ error = lock_table_names(thd,
+ thd->lex->select_lex.table_list.first,
+ NULL,
+ thd->variables.lock_wait_timeout,
+ 0);
+ if (error) {
+ if (cb.set_error)
+ cb.set_error(thd,
+ error,
+ "Can't lock table '%s.%s'",
+ db,
+ table);
+ return error;
+ }
+ tdc_remove_table(thd, TDC_RT_REMOVE_ALL, db, table, false);
+ return error;
+}
+
+static bool parse_db_and_table(const char *dname,
+ std::string /*out*/ &db_name,
+ std::string /*out*/ &table_name) {
+ const char *begin;
+ const char *end;
+ const char *db_name_begin;
+ const char *db_name_end;
+
+ begin = strchr(dname, '/');
+ if (!begin)
+ return false;
+ ++begin;
+ end = strchr(begin, '/');
+ if (!end)
+ return false;
+
+ db_name_begin = begin;
+ db_name_end = end;
+
+ begin = end + 1;
+
+ end = strchr(begin, '-');
+ if (!end)
+ return false;
+
+ if (strncmp(end, "-main", strlen("-main")) &&
+ strncmp(end, "-status", strlen("-status")) &&
+ strncmp(end, "-key", strlen("-key")))
+ return false;
+
+ db_name.assign(db_name_begin, db_name_end);
+ table_name.assign(begin, end);
+
+ return true;
+}
+
+static int attach(THD *thd,
+ const std::string &dname,
+ const std::string &iname,
+ const dir_cmd_callbacks &cb) {
+ int error;
+ DB_TXN* txn = NULL;
+ DB_TXN *parent_txn = NULL;
+ tokudb_trx_data *trx = NULL;
+
+ std::string db_name;
+ std::string table_name;
+
+ if (parse_db_and_table(dname.c_str(), db_name, table_name)) {
+ error = MDL_and_TDC(thd, db_name.c_str(), table_name.c_str(), cb);
+ if (error)
+ goto cleanup;
+ }
+
+ trx = (tokudb_trx_data *) thd_get_ha_data(thd, tokudb_hton);
+ if (trx && trx->sub_sp_level)
+ parent_txn = trx->sub_sp_level;
+ error = txn_begin(db_env, parent_txn, &txn, 0, thd);
+ if (error)
+ goto cleanup;
+
+ error = db_env->dirtool_attach(db_env,
+ txn,
+ dname.c_str(),
+ iname.c_str());
+cleanup:
+ if (txn) {
+ if (error) {
+ abort_txn(txn);
+ }
+ else {
+ commit_txn(txn, 0);
+ }
+ }
+ return error;
+}
+
+static int detach(THD *thd,
+ const std::string &dname,
+ const dir_cmd_callbacks &cb) {
+ int error;
+ DB_TXN* txn = NULL;
+ DB_TXN *parent_txn = NULL;
+ tokudb_trx_data *trx = NULL;
+
+ std::string db_name;
+ std::string table_name;
+
+ if (parse_db_and_table(dname.c_str(), db_name, table_name)) {
+ error = MDL_and_TDC(thd, db_name.c_str(), table_name.c_str(), cb);
+ if (error)
+ goto cleanup;
+ }
+
+ trx = (tokudb_trx_data *) thd_get_ha_data(thd, tokudb_hton);
+ if (trx && trx->sub_sp_level)
+ parent_txn = trx->sub_sp_level;
+ error = txn_begin(db_env, parent_txn, &txn, 0, thd);
+ if (error)
+ goto cleanup;
+
+ error = db_env->dirtool_detach(db_env,
+ txn,
+ dname.c_str());
+cleanup:
+ if (txn) {
+ if (error) {
+ abort_txn(txn);
+ }
+ else {
+ commit_txn(txn, 0);
+ }
+ }
+ return error;
+}
+
+static int move(THD *thd,
+ const std::string &old_dname,
+ const std::string &new_dname,
+ const dir_cmd_callbacks &cb) {
+ int error;
+ DB_TXN* txn = NULL;
+ DB_TXN *parent_txn = NULL;
+ tokudb_trx_data *trx = NULL;
+
+ std::string db_name;
+ std::string table_name;
+
+ if (parse_db_and_table(old_dname.c_str(), db_name, table_name)) {
+ error = MDL_and_TDC(thd, db_name.c_str(), table_name.c_str(), cb);
+ if (error)
+ goto cleanup;
+ }
+
+ trx = (tokudb_trx_data *) thd_get_ha_data(thd, tokudb_hton);
+ if (trx && trx->sub_sp_level)
+ parent_txn = trx->sub_sp_level;
+ error = txn_begin(db_env, parent_txn, &txn, 0, thd);
+ if (error)
+ goto cleanup;
+
+ error = db_env->dirtool_move(db_env,
+ txn,
+ old_dname.c_str(),
+ new_dname.c_str());
+cleanup:
+ if (txn) {
+ if (error) {
+ abort_txn(txn);
+ }
+ else {
+ commit_txn(txn, 0);
+ }
+ }
+ return error;
+}
+
+static void tokenize(const char *cmd_str,
+ std::vector<std::string> /*out*/ &tokens) {
+ DBUG_ASSERT(cmd_str);
+
+ bool was_escape = false;
+ const char *token_begin = cmd_str;
+ const char *token_end = token_begin;
+
+ while (*token_end) {
+ if (*token_end == tokens_escape_delimiter_char) {
+ was_escape = true;
+ }
+ else if (*token_end == tokens_delimiter) {
+ if (was_escape)
+ was_escape = false;
+ else {
+ if (token_begin == token_end)
+ ++token_begin;
+ else {
+ tokens.push_back(std::string(token_begin, token_end));
+ token_begin = token_end + 1;
+ }
+ }
+ }
+ else {
+ was_escape = false;
+ }
+ ++token_end;
+ }
+
+ if (token_begin != token_end)
+ tokens.push_back(std::string(token_begin, token_end));
+}
+
+void process_dir_cmd(THD *thd,
+ const char *cmd_str,
+ const dir_cmd_callbacks &cb) {
+
+ DBUG_ASSERT(thd);
+ DBUG_ASSERT(cmd_str);
+
+ std::vector<std::string> tokens;
+ tokenize(cmd_str, tokens);
+
+ if (tokens.empty())
+ return;
+
+ const std::string &cmd = tokens[0];
+
+ if (!cmd.compare("attach")) {
+ if (tokens.size() != 3) {
+ if (cb.set_error)
+ cb.set_error(thd,
+ EINVAL,
+ "attach command requires two arguments");
+ }
+ else {
+ int r = attach(thd, tokens[1], tokens[2], cb);
+ if (r && cb.set_error)
+ cb.set_error(thd, r, "Attach command error");
+ }
+ }
+ else if (!cmd.compare("detach")) {
+ if (tokens.size() != 2) {
+ if (cb.set_error)
+ cb.set_error(thd,
+ EINVAL,
+ "detach command requires one argument");
+ }
+ else {
+ int r = detach(thd, tokens[1], cb);
+ if (r && cb.set_error)
+ cb.set_error(thd, r, "detach command error");
+ }
+ }
+ else if (!cmd.compare("move")) {
+ if (tokens.size() != 3) {
+ if (cb.set_error)
+ cb.set_error(thd,
+ EINVAL,
+ "move command requires two arguments");
+ }
+ else {
+ int r = move(thd, tokens[1], tokens[2], cb);
+ if (r && cb.set_error)
+ cb.set_error(thd, r, "move command error");
+ }
+ }
+ else {
+ if (cb.set_error)
+ cb.set_error(thd,
+ ENOENT,
+ "Unknown command '%s'",
+ cmd.c_str());
+ }
+
+ return;
+};
+
+
+} // namespace tokudb
diff --git a/storage/tokudb/tokudb_dir_cmd.h b/storage/tokudb/tokudb_dir_cmd.h
new file mode 100644
index 00000000000..b39caadc7c3
--- /dev/null
+++ b/storage/tokudb/tokudb_dir_cmd.h
@@ -0,0 +1,46 @@
+/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4:
+#ident "$Id$"
+/*======
+This file is part of TokuDB
+
+
+Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved.
+
+ TokuDBis is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License, version 2,
+ as published by the Free Software Foundation.
+
+ TokuDB is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with TokuDB. If not, see <http://www.gnu.org/licenses/>.
+
+======= */
+
+#ident "Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved."
+
+#ifndef _TOKUDB_DIR_CMD_H
+#define _TOKUDB_DIR_CMD_H
+
+#include <sql_class.h>
+
+namespace tokudb {
+
+struct dir_cmd_callbacks {
+ void (*set_error)(THD *thd,
+ int error,
+ const char *error_fmt,
+ ...);
+};
+
+void process_dir_cmd(THD *thd,
+ const char *cmd_str,
+ const dir_cmd_callbacks &cb);
+
+};
+
+#endif // _TOKUDB_DIR_CMD_H
diff --git a/storage/tokudb/tokudb_sysvars.cc b/storage/tokudb/tokudb_sysvars.cc
index b758929c10e..bbc39dc550a 100644
--- a/storage/tokudb/tokudb_sysvars.cc
+++ b/storage/tokudb/tokudb_sysvars.cc
@@ -25,6 +25,9 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved.
#ident "Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved."
#include "hatoku_hton.h"
+#include "sql_acl.h"
+#include "tokudb_dir_cmd.h"
+#include "sql_parse.h"
namespace tokudb {
namespace sysvars {
@@ -40,6 +43,7 @@ namespace sysvars {
#define TOKUDB_VERSION_STR NULL
#endif
+
ulonglong cache_size = 0;
uint cachetable_pool_threads = 0;
int cardinality_scale_percent = 0;
@@ -918,8 +922,6 @@ static MYSQL_THDVAR_BOOL(
true);
#endif
-
-
//******************************************************************************
// all system variables
//******************************************************************************
@@ -949,7 +951,6 @@ st_mysql_sys_var* system_variables[] = {
MYSQL_SYSVAR(version),
MYSQL_SYSVAR(write_status_frequency),
MYSQL_SYSVAR(dir_per_db),
-
#if TOKU_INCLUDE_HANDLERTON_HANDLE_FATAL_SIGNAL
MYSQL_SYSVAR(gdb_path),
MYSQL_SYSVAR(gdb_on_fatal),
diff --git a/storage/xtradb/btr/btr0sea.cc b/storage/xtradb/btr/btr0sea.cc
index 78cb9dfd6e0..2ed383b0dcb 100644
--- a/storage/xtradb/btr/btr0sea.cc
+++ b/storage/xtradb/btr/btr0sea.cc
@@ -199,7 +199,7 @@ btr_search_sys_create(
&btr_search_latch_arr[i], SYNC_SEARCH_SYS);
btr_search_sys->hash_tables[i]
- = ha_create(hash_size, 0, MEM_HEAP_FOR_BTR_SEARCH, 0);
+ = ib_create(hash_size, 0, MEM_HEAP_FOR_BTR_SEARCH, 0);
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
btr_search_sys->hash_tables[i]->adaptive = TRUE;
diff --git a/storage/xtradb/buf/buf0buf.cc b/storage/xtradb/buf/buf0buf.cc
index 3fde6994b91..0226b6738d4 100644
--- a/storage/xtradb/buf/buf0buf.cc
+++ b/storage/xtradb/buf/buf0buf.cc
@@ -1530,7 +1530,7 @@ buf_pool_init_instance(
ut_a(srv_n_page_hash_locks != 0);
ut_a(srv_n_page_hash_locks <= MAX_PAGE_HASH_LOCKS);
- buf_pool->page_hash = ha_create(2 * buf_pool->curr_size,
+ buf_pool->page_hash = ib_create(2 * buf_pool->curr_size,
srv_n_page_hash_locks,
MEM_HEAP_FOR_PAGE_HASH,
SYNC_BUF_PAGE_HASH);
diff --git a/storage/xtradb/buf/buf0dblwr.cc b/storage/xtradb/buf/buf0dblwr.cc
index 1c9646c0bd6..c0c52deb57f 100644
--- a/storage/xtradb/buf/buf0dblwr.cc
+++ b/storage/xtradb/buf/buf0dblwr.cc
@@ -1,7 +1,7 @@
/*****************************************************************************
-Copyright (c) 1995, 2014, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2013, 2017, MariaDB Corporation. All Rights Reserved.
+Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2013, 2017, MariaDB Corporation.
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
@@ -351,7 +351,7 @@ recovery, this function loads the pages from double write buffer into memory. */
void
buf_dblwr_init_or_load_pages(
/*=========================*/
- os_file_t file,
+ pfs_os_file_t file,
char* path,
bool load_corrupt_pages)
{
diff --git a/storage/xtradb/buf/buf0dump.cc b/storage/xtradb/buf/buf0dump.cc
index e728636042b..c66dcc3824a 100644
--- a/storage/xtradb/buf/buf0dump.cc
+++ b/storage/xtradb/buf/buf0dump.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2011, 2016, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2011, 2017, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, MariaDB Corporation. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
@@ -685,6 +685,7 @@ extern "C" UNIV_INTERN
os_thread_ret_t
DECLARE_THREAD(buf_dump_thread)(void*)
{
+ my_thread_init();
ut_ad(!srv_read_only_mode);
buf_dump_status(STATUS_INFO, "Dumping buffer pool(s) not yet started");
@@ -721,6 +722,7 @@ DECLARE_THREAD(buf_dump_thread)(void*)
srv_buf_dump_thread_active = false;
+ my_thread_end();
/* 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. */
os_thread_exit(NULL);
diff --git a/storage/xtradb/buf/buf0flu.cc b/storage/xtradb/buf/buf0flu.cc
index 6f8bbd75d99..92b783fe81c 100644
--- a/storage/xtradb/buf/buf0flu.cc
+++ b/storage/xtradb/buf/buf0flu.cc
@@ -1,7 +1,7 @@
/*****************************************************************************
-Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2013, 2017, MariaDB Corporation. All Rights Reserved.
+Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2013, 2017, MariaDB Corporation.
Copyright (c) 2013, 2014, Fusion-io
This program is free software; you can redistribute it and/or modify it under
@@ -352,6 +352,7 @@ buf_flush_insert_into_flush_list(
buf_block_t* block, /*!< in/out: block which is modified */
lsn_t lsn) /*!< in: oldest modification */
{
+ ut_ad(srv_shutdown_state != SRV_SHUTDOWN_FLUSH_PHASE);
ut_ad(log_flush_order_mutex_own());
ut_ad(mutex_own(&block->mutex));
@@ -410,6 +411,7 @@ buf_flush_insert_sorted_into_flush_list(
buf_page_t* prev_b;
buf_page_t* b;
+ ut_ad(srv_shutdown_state != SRV_SHUTDOWN_FLUSH_PHASE);
ut_ad(log_flush_order_mutex_own());
ut_ad(mutex_own(&block->mutex));
ut_ad(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
@@ -715,6 +717,7 @@ buf_flush_write_complete(
buf_page_set_io_fix(bpage, BUF_IO_NONE);
buf_pool->n_flush[flush_type]--;
+ ut_ad(buf_pool->n_flush[flush_type] != ULINT_MAX);
#ifdef UNIV_MTFLUSH_DEBUG
fprintf(stderr, "n pending flush %lu\n",
@@ -1099,6 +1102,7 @@ buf_flush_page(
}
++buf_pool->n_flush[flush_type];
+ ut_ad(buf_pool->n_flush[flush_type] != 0);
mutex_exit(&buf_pool->flush_state_mutex);
@@ -2264,13 +2268,14 @@ Clears up tail of the LRU lists:
* Flush dirty pages at the tail of LRU to the disk
The depth to which we scan each buffer pool is controlled by dynamic
config parameter innodb_LRU_scan_depth.
-@return number of pages flushed */
+@return number of flushed and evicted pages */
UNIV_INTERN
ulint
buf_flush_LRU_tail(void)
/*====================*/
{
ulint total_flushed = 0;
+ ulint total_evicted = 0;
ulint start_time = ut_time_ms();
ulint scan_depth[MAX_BUFFER_POOLS];
ulint requested_pages[MAX_BUFFER_POOLS];
@@ -2341,6 +2346,7 @@ buf_flush_LRU_tail(void)
limited_scan[i]
= (previous_evicted[i] > n.evicted);
previous_evicted[i] = n.evicted;
+ total_evicted += n.evicted;
requested_pages[i] += lru_chunk_size;
@@ -2381,7 +2387,7 @@ buf_flush_LRU_tail(void)
}
}
- return(total_flushed);
+ return(total_flushed + total_evicted);
}
/*********************************************************************//**
@@ -2682,6 +2688,23 @@ buf_get_total_free_list_length(void)
return result;
}
+/** Returns the aggregate LRU list length over all buffer pool instances.
+@return total LRU list length. */
+MY_ATTRIBUTE((warn_unused_result))
+static
+ulint
+buf_get_total_LRU_list_length(void)
+{
+ ulint result = 0;
+
+ for (ulint i = 0; i < srv_buf_pool_instances; i++) {
+
+ result += UT_LIST_GET_LEN(buf_pool_from_array(i)->LRU);
+ }
+
+ return result;
+}
+
/*********************************************************************//**
Adjust the desired page cleaner thread sleep time for LRU flushes. */
MY_ATTRIBUTE((nonnull))
@@ -2694,8 +2717,9 @@ page_cleaner_adapt_lru_sleep_time(
ulint lru_n_flushed) /*!< in: number of flushed in previous batch */
{
- ulint free_len = buf_get_total_free_list_length();
- ulint max_free_len = srv_LRU_scan_depth * srv_buf_pool_instances;
+ ulint free_len = buf_get_total_free_list_length();
+ ulint max_free_len = ut_min(buf_get_total_LRU_list_length(),
+ srv_LRU_scan_depth * srv_buf_pool_instances);
if (free_len < max_free_len / 100 && lru_n_flushed) {
@@ -2707,7 +2731,7 @@ page_cleaner_adapt_lru_sleep_time(
/* Free lists filled more than 20%
or no pages flushed in previous batch, sleep a bit more */
- *lru_sleep_time += 50;
+ *lru_sleep_time += 1;
if (*lru_sleep_time > srv_cleaner_max_lru_time)
*lru_sleep_time = srv_cleaner_max_lru_time;
} else if (free_len < max_free_len / 20 && *lru_sleep_time >= 50) {
@@ -2754,6 +2778,7 @@ DECLARE_THREAD(buf_flush_page_cleaner_thread)(
/*!< in: a dummy parameter required by
os_thread_create */
{
+ my_thread_init();
ulint next_loop_time = ut_time_ms() + 1000;
ulint n_flushed = 0;
ulint last_activity = srv_get_activity_count();
@@ -2886,6 +2911,7 @@ DECLARE_THREAD(buf_flush_page_cleaner_thread)(
thread_exit:
buf_page_cleaner_is_active = FALSE;
+ my_thread_end();
/* 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. */
os_thread_exit(NULL);
diff --git a/storage/xtradb/dict/dict0dict.cc b/storage/xtradb/dict/dict0dict.cc
index bc46bcab63b..a1cfeb3860f 100644
--- a/storage/xtradb/dict/dict0dict.cc
+++ b/storage/xtradb/dict/dict0dict.cc
@@ -888,6 +888,12 @@ dict_index_get_nth_col_or_prefix_pos(
ut_ad(index);
ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
+ ut_ad((inc_prefix && !prefix_col_pos) || (!inc_prefix));
+
+ if (!prefix_col_pos) {
+ prefix_col_pos = &prefixed_pos_dummy;
+ }
+ *prefix_col_pos = ULINT_UNDEFINED;
if (!prefix_col_pos) {
prefix_col_pos = &prefixed_pos_dummy;
diff --git a/storage/xtradb/dict/dict0stats.cc b/storage/xtradb/dict/dict0stats.cc
index d2e9a2618c0..c1463e98ce0 100644
--- a/storage/xtradb/dict/dict0stats.cc
+++ b/storage/xtradb/dict/dict0stats.cc
@@ -1168,8 +1168,9 @@ dict_stats_analyze_index_level(
leaf-level delete marks because delete marks on
non-leaf level do not make sense. */
- if (level == 0 && srv_stats_include_delete_marked? 0:
- rec_get_deleted_flag(
+ if (level == 0
+ && !srv_stats_include_delete_marked
+ && rec_get_deleted_flag(
rec,
page_is_comp(btr_pcur_get_page(&pcur)))) {
diff --git a/storage/xtradb/dict/dict0stats_bg.cc b/storage/xtradb/dict/dict0stats_bg.cc
index 55d34ff6ae1..ec5efe0dd7c 100644
--- a/storage/xtradb/dict/dict0stats_bg.cc
+++ b/storage/xtradb/dict/dict0stats_bg.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2012, 2016, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2012, 2017, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, MariaDB Corporation. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
@@ -530,6 +530,7 @@ extern "C" UNIV_INTERN
os_thread_ret_t
DECLARE_THREAD(dict_stats_thread)(void*)
{
+ my_thread_init();
ut_a(!srv_read_only_mode);
while (!SHUTTING_DOWN()) {
@@ -556,6 +557,7 @@ DECLARE_THREAD(dict_stats_thread)(void*)
srv_dict_stats_thread_active = false;
+ my_thread_end();
/* We count the number of threads in os_thread_exit(). A created
thread should always use that to exit instead of return(). */
os_thread_exit(NULL);
diff --git a/storage/xtradb/fil/fil0fil.cc b/storage/xtradb/fil/fil0fil.cc
index f94b8acc715..fc46d2b71e9 100644
--- a/storage/xtradb/fil/fil0fil.cc
+++ b/storage/xtradb/fil/fil0fil.cc
@@ -1,7 +1,7 @@
/*****************************************************************************
-Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2014, 2017, MariaDB Corporation.
+Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2014, 2017, MariaDB Corporation. 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
@@ -166,7 +166,8 @@ UNIV_INTERN extern uint srv_fil_crypt_rotate_key_age;
UNIV_INTERN extern ib_mutex_t fil_crypt_threads_mutex;
/** Determine if (i) is a user tablespace id or not. */
-# define fil_is_user_tablespace_id(i) ((i) > srv_undo_tablespaces_open)
+# define fil_is_user_tablespace_id(i) (i != 0 \
+ && !srv_is_undo_tablespace(i))
/** Determine if user has explicitly disabled fsync(). */
#ifndef __WIN__
@@ -621,7 +622,8 @@ fil_node_open_file(
size_bytes = os_file_get_size(node->handle);
ut_a(size_bytes != (os_offset_t) -1);
- node->file_block_size = os_file_get_block_size(node->handle, node->name);
+ node->file_block_size = os_file_get_block_size(
+ node->handle, node->name);
space->file_block_size = node->file_block_size;
#ifdef UNIV_HOTBACKUP
@@ -731,7 +733,8 @@ add_size:
}
if (node->file_block_size == 0) {
- node->file_block_size = os_file_get_block_size(node->handle, node->name);
+ node->file_block_size = os_file_get_block_size(
+ node->handle, node->name);
space->file_block_size = node->file_block_size;
}
@@ -2416,7 +2419,7 @@ UNIV_INTERN
const char*
fil_read_first_page(
/*================*/
- os_file_t data_file, /*!< in: open data file */
+ pfs_os_file_t data_file, /*!< in: open data file */
ibool one_read_already, /*!< in: TRUE if min and max
parameters below already
contain sensible data */
@@ -3740,7 +3743,7 @@ fil_open_linked_file(
/*===============*/
const char* tablename, /*!< in: database/tablename */
char** remote_filepath,/*!< out: remote filepath */
- os_file_t* remote_file, /*!< out: remote file handle */
+ pfs_os_file_t* remote_file, /*!< out: remote file handle */
ulint atomic_writes) /*!< in: atomic writes table option
value */
{
@@ -3803,7 +3806,8 @@ fil_create_new_single_table_tablespace(
fil_encryption_t mode, /*!< in: encryption mode */
ulint key_id) /*!< in: encryption key_id */
{
- os_file_t file;
+ pfs_os_file_t file;
+
ibool ret;
dberr_t err;
byte* buf2;
@@ -6882,7 +6886,7 @@ fil_buf_block_init(
}
struct fil_iterator_t {
- os_file_t file; /*!< File handle */
+ pfs_os_file_t file; /*!< File handle */
const char* filepath; /*!< File path name */
os_offset_t start; /*!< From where to start */
os_offset_t end; /*!< Where to stop */
@@ -7155,7 +7159,7 @@ fil_tablespace_iterate(
PageCallback& callback)
{
dberr_t err;
- os_file_t file;
+ pfs_os_file_t file;
char* filepath;
ut_a(n_io_buffers > 0);
diff --git a/storage/xtradb/fts/fts0que.cc b/storage/xtradb/fts/fts0que.cc
index 2e335c1c255..f24973e26fb 100644
--- a/storage/xtradb/fts/fts0que.cc
+++ b/storage/xtradb/fts/fts0que.cc
@@ -953,6 +953,18 @@ fts_query_free_doc_ids(
query->total_size -= SIZEOF_RBT_CREATE;
}
+/**
+Free the query intersection
+@param[in] query query instance */
+static
+void
+fts_query_free_intersection(
+ fts_query_t* query)
+{
+ fts_query_free_doc_ids(query, query->intersection);
+ query->intersection = NULL;
+}
+
/*******************************************************************//**
Add the word to the documents "list" of matching words from
the query. We make a copy of the word from the query heap. */
@@ -1311,6 +1323,7 @@ fts_query_intersect(
/* error is passed by 'query->error' */
if (query->error != DB_SUCCESS) {
ut_ad(query->error == DB_FTS_EXCEED_RESULT_CACHE_LIMIT);
+ fts_query_free_intersection(query);
return(query->error);
}
@@ -1339,6 +1352,8 @@ fts_query_intersect(
ut_a(!query->multi_exist || (query->multi_exist
&& rbt_size(query->doc_ids) <= n_doc_ids));
+ } else if (query->intersection != NULL) {
+ fts_query_free_intersection(query);
}
}
@@ -1557,6 +1572,11 @@ fts_merge_doc_ids(
query, ranking->doc_id, ranking->rank);
if (query->error != DB_SUCCESS) {
+ if (query->intersection != NULL)
+ {
+ ut_a(query->oper == FTS_EXIST);
+ fts_query_free_intersection(query);
+ }
DBUG_RETURN(query->error);
}
diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc
index f461a42e1ec..cdd3497b895 100644
--- a/storage/xtradb/handler/ha_innodb.cc
+++ b/storage/xtradb/handler/ha_innodb.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2000, 2016, Oracle and/or its affiliates.
+Copyright (c) 2000, 2017, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2013, 2017, MariaDB Corporation.
Copyright (c) 2008, 2009 Google Inc.
Copyright (c) 2009, Percona Inc.
@@ -871,6 +871,31 @@ innobase_purge_changed_page_bitmaps(
/*================================*/
ulonglong lsn) __attribute__((unused)); /*!< in: LSN to purge files up to */
+/** Empty free list algorithm.
+Checks if buffer pool is big enough to enable backoff algorithm.
+InnoDB empty free list algorithm backoff requires free pages
+from LRU for the best performance.
+buf_LRU_buf_pool_running_out cancels query if 1/4 of
+buffer pool belongs to LRU or freelist.
+At the same time buf_flush_LRU_list_batch
+keeps up to BUF_LRU_MIN_LEN in LRU.
+In order to avoid deadlock baclkoff requires buffer pool
+to be at least 4*BUF_LRU_MIN_LEN,
+but flush peformance is bad because of trashing
+and additional BUF_LRU_MIN_LEN pages are requested.
+@param[in] algorithm desired algorithm from srv_empty_free_list_t
+@return true if it's possible to enable backoff. */
+static inline
+bool
+innodb_empty_free_list_algorithm_allowed(
+ srv_empty_free_list_t algorithm)
+{
+ long long buf_pool_pages = srv_buf_pool_size / srv_page_size
+ / srv_buf_pool_instances;
+
+ return(buf_pool_pages >= BUF_LRU_MIN_LEN * (4 + 1)
+ || algorithm != SRV_EMPTY_FREE_LIST_BACKOFF);
+}
/** Get the list of foreign keys referencing a specified table
table.
@@ -1687,28 +1712,6 @@ normalize_table_name_low(
ibool set_lower_case); /* in: TRUE if we want to set
name to lower case */
-/*************************************************************//**
-Checks if buffer pool is big enough to enable backoff algorithm.
-InnoDB empty free list algorithm backoff requires free pages
-from LRU for the best performance.
-buf_LRU_buf_pool_running_out cancels query if 1/4 of
-buffer pool belongs to LRU or freelist.
-At the same time buf_flush_LRU_list_batch
-keeps up to BUF_LRU_MIN_LEN in LRU.
-In order to avoid deadlock baclkoff requires buffer pool
-to be at least 4*BUF_LRU_MIN_LEN,
-but flush peformance is bad because of trashing
-and additional BUF_LRU_MIN_LEN pages are requested.
-@return true if it's possible to enable backoff. */
-static
-bool
-innodb_empty_free_list_algorithm_backoff_allowed(
- srv_empty_free_list_t
- algorithm, /*!< in: desired algorithm
- from srv_empty_free_list_t */
- long long buf_pool_pages); /*!< in: total number
- of pages inside buffer pool */
-
#ifdef NOT_USED
/*************************************************************//**
Removes old archived transaction log files.
@@ -4353,10 +4356,9 @@ innobase_change_buffering_inited_ok:
srv_use_posix_fallocate = (ibool) innobase_use_fallocate;
#endif
/* Do not enable backoff algorithm for small buffer pool. */
- if (!innodb_empty_free_list_algorithm_backoff_allowed(
+ if (!innodb_empty_free_list_algorithm_allowed(
static_cast<srv_empty_free_list_t>(
- srv_empty_free_list_algorithm),
- innobase_buffer_pool_size / srv_page_size)) {
+ srv_empty_free_list_algorithm))) {
sql_print_information(
"InnoDB: innodb_empty_free_list_algorithm "
"has been changed to legacy "
@@ -8135,17 +8137,31 @@ build_template_field(
templ->rec_field_is_prefix = FALSE;
if (dict_index_is_clust(index)) {
+ templ->rec_field_is_prefix = false;
templ->rec_field_no = templ->clust_rec_field_no;
templ->rec_prefix_field_no = ULINT_UNDEFINED;
} else {
- /* If we're in a secondary index, keep track
- * of the original index position even if this
- * is just a prefix index; we will use this
- * later to avoid a cluster index lookup in
- * some cases.*/
+ /* If we're in a secondary index, keep track of the original
+ index position even if this is just a prefix index; we will use
+ this later to avoid a cluster index lookup in some cases.*/
templ->rec_field_no = dict_index_get_nth_col_pos(index, i,
&templ->rec_prefix_field_no);
+ templ->rec_field_is_prefix
+ = (templ->rec_field_no == ULINT_UNDEFINED)
+ && (templ->rec_prefix_field_no != ULINT_UNDEFINED);
+#ifdef UNIV_DEBUG
+ if (templ->rec_prefix_field_no != ULINT_UNDEFINED)
+ {
+ const dict_field_t* field = dict_index_get_nth_field(
+ index,
+ templ->rec_prefix_field_no);
+ ut_ad(templ->rec_field_is_prefix
+ == (field->prefix_len != 0));
+ } else {
+ ut_ad(!templ->rec_field_is_prefix);
+ }
+#endif
}
if (field->real_maybe_null()) {
@@ -13075,7 +13091,8 @@ ha_innobase::delete_table(
extension, in contrast to ::create */
normalize_table_name(norm_name, name);
- if (srv_read_only_mode) {
+ if (srv_read_only_mode
+ || srv_force_recovery >= SRV_FORCE_NO_UNDO_LOG_SCAN) {
DBUG_RETURN(HA_ERR_TABLE_READONLY);
} else if (row_is_magic_monitor_table(norm_name)
&& check_global_access(thd, PROCESS_ACL)) {
@@ -18600,15 +18617,17 @@ innodb_buffer_pool_evict_uncompressed(void)
ut_ad(block->page.in_LRU_list);
mutex_enter(&block->mutex);
- if (!buf_LRU_free_page(&block->page, false)) {
- mutex_exit(&block->mutex);
- all_evicted = false;
- } else {
- mutex_exit(&block->mutex);
+ all_evicted = buf_LRU_free_page(&block->page, false);
+ mutex_exit(&block->mutex);
+
+ if (all_evicted) {
+
mutex_enter(&buf_pool->LRU_list_mutex);
- }
+ block = UT_LIST_GET_LAST(buf_pool->unzip_LRU);
+ } else {
- block = prev_block;
+ block = prev_block;
+ }
}
mutex_exit(&buf_pool->LRU_list_mutex);
@@ -19822,32 +19841,6 @@ wsrep_fake_trx_id(
/*************************************************************//**
-Empty free list algorithm.
-Checks if buffer pool is big enough to enable backoff algorithm.
-InnoDB empty free list algorithm backoff requires free pages
-from LRU for the best performance.
-buf_LRU_buf_pool_running_out cancels query if 1/4 of
-buffer pool belongs to LRU or freelist.
-At the same time buf_flush_LRU_list_batch
-keeps up to BUF_LRU_MIN_LEN in LRU.
-In order to avoid deadlock baclkoff requires buffer pool
-to be at least 4*BUF_LRU_MIN_LEN,
-but flush peformance is bad because of trashing
-and additional BUF_LRU_MIN_LEN pages are requested.
-@return true if it's possible to enable backoff. */
-static
-bool
-innodb_empty_free_list_algorithm_backoff_allowed(
- srv_empty_free_list_t algorithm, /*!< in: desired algorithm
- from srv_empty_free_list_t */
- long long buf_pool_pages) /*!< in: total number
- of pages inside buffer pool */
-{
- return(buf_pool_pages >= BUF_LRU_MIN_LEN * (4 + 1)
- || algorithm != SRV_EMPTY_FREE_LIST_BACKOFF);
-}
-
-/*************************************************************//**
Empty free list algorithm. This function is registered as
a callback with MySQL.
@return 0 for valid algorithm */
@@ -19888,13 +19881,11 @@ innodb_srv_empty_free_list_algorithm_validate(
return(1);
algorithm = static_cast<srv_empty_free_list_t>(algo);
- if (!innodb_empty_free_list_algorithm_backoff_allowed(
- algorithm,
- innobase_buffer_pool_size / srv_page_size)) {
+ if (!innodb_empty_free_list_algorithm_allowed(algorithm)) {
sql_print_warning(
"InnoDB: innodb_empty_free_list_algorithm "
"= 'backoff' requires at least"
- " 20MB buffer pool.\n");
+ " 20MB buffer pool instances.\n");
return(1);
}
diff --git a/storage/xtradb/include/buf0dblwr.h b/storage/xtradb/include/buf0dblwr.h
index 5582778825c..8e1b00db83c 100644
--- a/storage/xtradb/include/buf0dblwr.h
+++ b/storage/xtradb/include/buf0dblwr.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1995, 2014, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, MariaDB Corporation. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
@@ -56,7 +56,7 @@ recovery, this function loads the pages from double write buffer into memory. */
void
buf_dblwr_init_or_load_pages(
/*=========================*/
- os_file_t file,
+ pfs_os_file_t file,
char* path,
bool load_corrupt_pages);
diff --git a/storage/xtradb/include/dict0dict.h b/storage/xtradb/include/dict0dict.h
index 6da8eb892d9..0290b884ece 100644
--- a/storage/xtradb/include/dict0dict.h
+++ b/storage/xtradb/include/dict0dict.h
@@ -1192,7 +1192,7 @@ dict_index_get_nth_col_pos(
const dict_index_t* index, /*!< in: index */
ulint n, /*!< in: column number */
ulint* prefix_col_pos) /*!< out: col num if prefix */
- __attribute__((nonnull(1), warn_unused_result));
+ MY_ATTRIBUTE((nonnull(1), warn_unused_result));
/********************************************************************//**
Looks for column n in an index.
@return position in internal representation of the index;
@@ -1207,7 +1207,7 @@ dict_index_get_nth_col_or_prefix_pos(
column prefixes too */
ulint* prefix_col_pos) /*!< out: col num if prefix */
- __attribute__((nonnull(1), warn_unused_result));
+ MY_ATTRIBUTE((nonnull(1), warn_unused_result));
/********************************************************************//**
Returns TRUE if the index contains a column or a prefix of that column.
@return TRUE if contains the column or its prefix */
diff --git a/storage/xtradb/include/fil0fil.h b/storage/xtradb/include/fil0fil.h
index 6b8f164f291..a4e147b9797 100644
--- a/storage/xtradb/include/fil0fil.h
+++ b/storage/xtradb/include/fil0fil.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2013, 2017, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
@@ -210,7 +210,7 @@ struct fsp_open_info {
ibool success; /*!< Has the tablespace been opened? */
const char* check_msg; /*!< fil_check_first_page() message */
ibool valid; /*!< Is the tablespace valid? */
- os_file_t file; /*!< File handle */
+ pfs_os_file_t file; /*!< File handle */
char* filepath; /*!< File path to open */
lsn_t lsn; /*!< Flushed LSN from header page */
ulint id; /*!< Space ID */
@@ -228,7 +228,7 @@ struct fil_node_t {
belongs */
char* name; /*!< path to the file */
ibool open; /*!< TRUE if file open */
- os_file_t handle; /*!< OS handle to the file, if file open */
+ pfs_os_file_t handle; /*!< OS handle to the file, if file open */
os_event_t sync_event;/*!< Condition event to group and
serialize calls to fsync;
os_event_set() and os_event_reset()
@@ -808,7 +808,7 @@ UNIV_INTERN
const char*
fil_read_first_page(
/*================*/
- os_file_t data_file, /*!< in: open data file */
+ pfs_os_file_t data_file, /*!< in: open data file */
ibool one_read_already, /*!< in: TRUE if min and max
parameters below already
contain sensible data */
@@ -1340,12 +1340,12 @@ struct PageCallback {
Called for every page in the tablespace. If the page was not
updated then its state must be set to BUF_PAGE_NOT_USED. For
compressed tables the page descriptor memory will be at offset:
- block->frame + UNIV_PAGE_SIZE;
+ block->frame + UNIV_PAGE_SIZE;
@param offset - physical offset within the file
@param block - block read from file, note it is not from the buffer pool
@retval DB_SUCCESS or error code. */
virtual dberr_t operator()(
- os_offset_t offset,
+ os_offset_t offset,
buf_block_t* block) UNIV_NOTHROW = 0;
/**
@@ -1353,7 +1353,7 @@ struct PageCallback {
to open it for the file that is being iterated over.
@param filename - then physical name of the tablespace file.
@param file - OS file handle */
- void set_file(const char* filename, os_file_t file) UNIV_NOTHROW
+ void set_file(const char* filename, pfs_os_file_t file) UNIV_NOTHROW
{
m_file = file;
m_filepath = filename;
@@ -1389,7 +1389,7 @@ struct PageCallback {
ulint m_page_size;
/** File handle to the tablespace */
- os_file_t m_file;
+ pfs_os_file_t m_file;
/** Physical file path. */
const char* m_filepath;
diff --git a/storage/xtradb/include/ha0ha.h b/storage/xtradb/include/ha0ha.h
index 7351b407e8c..58eb581e76a 100644
--- a/storage/xtradb/include/ha0ha.h
+++ b/storage/xtradb/include/ha0ha.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1994, 2011, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1994, 2016, 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
@@ -107,7 +107,7 @@ chosen to be a slightly bigger prime number.
@param level in: level of the mutexes in the latching order
@param n_m in: number of mutexes to protect the hash table;
must be a power of 2, or 0 */
-# define ha_create(n_c,n_m,type,level) ha_create_func(n_c,level,n_m,type)
+# define ib_create(n_c,n_m,type,level) ha_create_func(n_c,level,n_m,type)
#else /* UNIV_SYNC_DEBUG */
/** Creates a hash table.
@return own: created table
@@ -116,7 +116,7 @@ chosen to be a slightly bigger prime number.
@param level in: level of the mutexes in the latching order
@param n_m in: number of mutexes to protect the hash table;
must be a power of 2, or 0 */
-# define ha_create(n_c,n_m,type,level) ha_create_func(n_c,n_m,type)
+# define ib_create(n_c,n_m,type,level) ha_create_func(n_c,n_m,type)
#endif /* UNIV_SYNC_DEBUG */
/*************************************************************//**
diff --git a/storage/xtradb/include/log0online.h b/storage/xtradb/include/log0online.h
index 722336dd6b4..5c3e7d07fd9 100644
--- a/storage/xtradb/include/log0online.h
+++ b/storage/xtradb/include/log0online.h
@@ -130,7 +130,7 @@ log_online_bitmap_iterator_next(
/** Struct for single bitmap file information */
struct log_online_bitmap_file_struct {
char name[FN_REFLEN]; /*!< Name with full path */
- os_file_t file; /*!< Handle to opened file */
+ pfs_os_file_t file; /*!< Handle to opened file */
ib_uint64_t size; /*!< Size of the file */
os_offset_t offset; /*!< Offset of the next read,
or count of already-read bytes
diff --git a/storage/xtradb/include/os0file.h b/storage/xtradb/include/os0file.h
index 06bb6a6fbac..b17e09cf0fa 100644
--- a/storage/xtradb/include/os0file.h
+++ b/storage/xtradb/include/os0file.h
@@ -1,6 +1,6 @@
/***********************************************************************
-Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2009, Percona Inc.
Copyright (c) 2013, 2017, MariaDB Corporation.
@@ -65,26 +65,54 @@ extern ibool os_aio_print_debug;
/** File offset in bytes */
typedef ib_uint64_t os_offset_t;
-#ifdef __WIN__
-#define SRV_PATH_SEPARATOR '\\'
+#ifdef _WIN32
+# define SRV_PATH_SEPARATOR '\\'
/** File handle */
-# define os_file_t HANDLE
-# define os_file_invalid INVALID_HANDLE_VALUE
+typedef HANDLE os_file_t;
/** Convert a C file descriptor to a native file handle
@param fd file descriptor
@return native file handle */
-# define OS_FILE_FROM_FD(fd) (HANDLE) _get_osfhandle(fd)
+# define OS_FILE_FROM_FD(fd) reinterpret_cast<HANDLE>(_get_osfhandle(fd))
#else
-#define SRV_PATH_SEPARATOR '/'
+# define SRV_PATH_SEPARATOR '/'
/** File handle */
typedef int os_file_t;
-# define os_file_invalid (-1)
/** Convert a C file descriptor to a native file handle
@param fd file descriptor
@return native file handle */
# define OS_FILE_FROM_FD(fd) fd
#endif
+/** File descriptor with optional PERFORMANCE_SCHEMA instrumentation */
+struct pfs_os_file_t
+{
+ /** Default constructor */
+ pfs_os_file_t() : m_file(
+#ifdef _WIN32
+ INVALID_HANDLE_VALUE
+#else
+ -1
+#endif
+ )
+#ifdef UNIV_PFS_IO
+ , m_psi(NULL)
+#endif
+ {}
+
+ /** The wrapped file handle */
+ os_file_t m_file;
+#ifdef UNIV_PFS_IO
+ /** PERFORMANCE_SCHEMA descriptor */
+ struct PSI_file *m_psi;
+#endif
+ /** Implicit type conversion.
+ @return the wrapped file handle */
+ operator os_file_t() const { return m_file; }
+ /** Assignment operator.
+ @param[in] file file handle to be assigned */
+ void operator=(os_file_t file) { m_file = file; }
+};
+
/** Umask for creating files */
extern ulint os_innodb_umask;
@@ -120,6 +148,21 @@ enum os_file_create_t {
ON_ERROR_NO_EXIT is set */
};
+/** Options for os_file_advise_func @{ */
+enum os_file_advise_t {
+ OS_FILE_ADVISE_NORMAL = 1, /*!< no advice on access pattern
+ (default) */
+ OS_FILE_ADVISE_RANDOM = 2, /*!< access in random order */
+ OS_FILE_ADVISE_SEQUENTIAL = 4, /*!< access the specified data
+ sequentially (with lower offsets read
+ before higher ones) */
+ OS_FILE_ADVISE_WILLNEED = 8, /*!< specified data will be accessed
+ in the near future */
+ OS_FILE_ADVISE_DONTNEED = 16, /*!< specified data will not be
+ accessed in the near future */
+ OS_FILE_ADVISE_NOREUSE = 32 /*!< access only once */
+};
+
#define OS_FILE_READ_ONLY 333
#define OS_FILE_READ_WRITE 444
#define OS_FILE_READ_ALLOW_DELETE 555 /* for mysqlbackup */
@@ -221,6 +264,8 @@ extern mysql_pfs_key_t innodb_file_bmp_key;
various file I/O operations with performance schema.
1) register_pfs_file_open_begin() and register_pfs_file_open_end() are
used to register file creation, opening, closing and renaming.
+2) register_pfs_file_rename_begin() and register_pfs_file_rename_end()
+are used to register file renaming
2) register_pfs_file_io_begin() and register_pfs_file_io_end() are
used to register actual file read, write and flush
3) register_pfs_file_close_begin() and register_pfs_file_close_end()
@@ -230,17 +275,30 @@ are used to register file deletion operations*/
do { \
locker = PSI_FILE_CALL(get_thread_file_name_locker)( \
state, key, op, name, &locker); \
- if (UNIV_LIKELY(locker != NULL)) { \
+ if (locker != NULL) { \
PSI_FILE_CALL(start_file_open_wait)( \
locker, src_file, src_line); \
} \
} while (0)
-# define register_pfs_file_open_end(locker, file) \
+# define register_pfs_file_open_end(locker, file, result) \
do { \
- if (UNIV_LIKELY(locker != NULL)) { \
- PSI_FILE_CALL(end_file_open_wait_and_bind_to_descriptor)(\
- locker, file); \
+ if (locker != NULL) { \
+ file.m_psi = PSI_FILE_CALL( \
+ end_file_open_wait)( \
+ locker, result); \
+ } \
+} while (0)
+
+# define register_pfs_file_rename_begin(state, locker, key, op, name, \
+ src_file, src_line) \
+ register_pfs_file_open_begin(state, locker, key, op, name, \
+ src_file, src_line) \
+
+# define register_pfs_file_rename_end(locker, result) \
+do { \
+ if (locker != NULL) { \
+ PSI_FILE_CALL(end_file_open_wait)(locker, result); \
} \
} while (0)
@@ -266,9 +324,9 @@ do { \
# define register_pfs_file_io_begin(state, locker, file, count, op, \
src_file, src_line) \
do { \
- locker = PSI_FILE_CALL(get_thread_file_descriptor_locker)( \
- state, file, op); \
- if (UNIV_LIKELY(locker != NULL)) { \
+ locker = PSI_FILE_CALL(get_thread_file_stream_locker)( \
+ state, file.m_psi, op); \
+ if (locker != NULL) { \
PSI_FILE_CALL(start_file_wait)( \
locker, count, src_file, src_line); \
} \
@@ -276,7 +334,7 @@ do { \
# define register_pfs_file_io_end(locker, count) \
do { \
- if (UNIV_LIKELY(locker != NULL)) { \
+ if (locker != NULL) { \
PSI_FILE_CALL(end_file_wait)(locker, count); \
} \
} while (0)
@@ -290,11 +348,16 @@ os_file_create
os_file_create_simple
os_file_create_simple_no_error_handling
os_file_close
+os_file_close_no_error_handling
os_file_rename
os_aio
os_file_read
os_file_read_no_error_handling
+os_file_read_no_error_handling_int_fd
os_file_write
+os_file_write_int_fd
+os_file_set_eof_at
+os_file_allocate
The wrapper functions have the prefix of "innodb_". */
@@ -315,6 +378,9 @@ The wrapper functions have the prefix of "innodb_". */
# define os_file_close(file) \
pfs_os_file_close_func(file, __FILE__, __LINE__)
+# define os_file_close_no_error_handling(file) \
+ pfs_os_file_close_no_error_handling_func(file, __FILE__, __LINE__)
+
# define os_aio(type, is_log, mode, name, file, buf, offset, \
n, page_size, message1, message2, space_id, \
trx, write_size) \
@@ -334,9 +400,18 @@ The wrapper functions have the prefix of "innodb_". */
pfs_os_file_read_no_error_handling_func(file, buf, offset, n, \
__FILE__, __LINE__)
-# define os_file_write(name, file, buf, offset, n) \
- pfs_os_file_write_func(name, file, buf, offset, n, \
- __FILE__, __LINE__)
+# define os_file_read_no_error_handling_int_fd( \
+ file, buf, offset, n) \
+ pfs_os_file_read_no_error_handling_int_fd_func( \
+ file, buf, offset, n, __FILE__, __LINE__)
+
+# define os_file_write(name, file, buf, offset, n) \
+ pfs_os_file_write_func(name, file, buf, offset, \
+ n, __FILE__, __LINE__)
+
+# define os_file_write_int_fd(name, file, buf, offset, n) \
+ pfs_os_file_write_int_fd_func(name, file, buf, offset, \
+ n, __FILE__, __LINE__)
# define os_file_flush(file) \
pfs_os_file_flush_func(file, __FILE__, __LINE__)
@@ -349,6 +424,15 @@ The wrapper functions have the prefix of "innodb_". */
# define os_file_delete_if_exists(key, name) \
pfs_os_file_delete_if_exists_func(key, name, __FILE__, __LINE__)
+
+# define os_file_set_eof_at(file, new_len) \
+ pfs_os_file_set_eof_at_func(file, new_len, __FILE__, __LINE__)
+
+# ifdef HAVE_POSIX_FALLOCATE
+# define os_file_allocate(file, offset, len) \
+ pfs_os_file_allocate_func(file, offset, len, __FILE__, __LINE__)
+# endif
+
#else /* UNIV_PFS_IO */
/* If UNIV_PFS_IO is not defined, these I/O APIs point
@@ -364,7 +448,11 @@ to original un-instrumented file I/O APIs */
os_file_create_simple_no_error_handling_func( \
name, create_mode, access, success, atomic_writes)
-# define os_file_close(file) os_file_close_func(file)
+# define os_file_close(file) \
+ os_file_close_func(file)
+
+# define os_file_close_no_error_handling(file) \
+ os_file_close_no_error_handling_func(file)
# define os_aio(type, is_log, mode, name, file, buf, offset, n, page_size, message1, \
message2, space_id, trx, write_size) \
@@ -379,11 +467,17 @@ to original un-instrumented file I/O APIs */
# define os_file_read_no_error_handling(file, buf, offset, n) \
os_file_read_no_error_handling_func(file, buf, offset, n)
+# define os_file_read_no_error_handling_int_fd( \
+ file, buf, offset, n) \
+ os_file_read_no_error_handling_func(file, buf, offset, n)
+# define os_file_write_int_fd(name, file, buf, offset, n) \
+ os_file_write_func(name, file, buf, offset, n)
# define os_file_write(name, file, buf, offset, n) \
os_file_write_func(name, file, buf, offset, n)
-# define os_file_flush(file) os_file_flush_func(file)
+
+# define os_file_flush(file) os_file_flush_func(file)
# define os_file_rename(key, oldpath, newpath) \
os_file_rename_func(oldpath, newpath)
@@ -393,6 +487,9 @@ to original un-instrumented file I/O APIs */
# define os_file_delete_if_exists(key, name) \
os_file_delete_if_exists_func(name)
+# define os_file_set_eof_at(file, new_len) \
+ os_file_set_eof_at_func(file, new_len)
+
#endif /* UNIV_PFS_IO */
/* File types for directory entry data type */
@@ -530,7 +627,7 @@ A simple function to open or create a file.
@return own: handle to the file, not defined if error, error number
can be retrieved with os_file_get_last_error */
UNIV_INTERN
-os_file_t
+pfs_os_file_t
os_file_create_simple_no_error_handling_func(
/*=========================================*/
const char* name, /*!< in: name of the file or path as a
@@ -565,7 +662,7 @@ Opens an existing file or creates a new.
@return own: handle to the file, not defined if error, error number
can be retrieved with os_file_get_last_error */
UNIV_INTERN
-os_file_t
+pfs_os_file_t
os_file_create_func(
/*================*/
const char* name, /*!< in: name of the file or path as a
@@ -626,6 +723,42 @@ ibool
os_file_close_func(
/*===============*/
os_file_t file); /*!< in, own: handle to a file */
+/***********************************************************************//**
+NOTE! Use the corresponding macro os_file_close(), not directly this
+function!
+Closes a file handle. In case of error, error number can be retrieved with
+os_file_get_last_error.
+@return TRUE if success */
+UNIV_INTERN
+bool
+os_file_close_no_error_handling_func(
+/*===============*/
+ os_file_t file); /*!< in, own: handle to a file */
+
+/***********************************************************************//**
+NOTE! Please use the corresponding macro os_file_set_eof_at(), not
+directly this function!
+Truncates a file at the specified position.
+@return TRUE if success */
+UNIV_INTERN
+bool
+os_file_set_eof_at_func(
+ os_file_t file, /*!< in: handle to a file */
+ ib_uint64_t new_len);/*!< in: new file length */
+
+#ifdef HAVE_POSIX_FALLOCATE
+/***********************************************************************//**
+NOTE! Please use the corresponding macro os_file_allocate(), not
+directly this function!
+Ensures that disk space is allocated for the file.
+@return TRUE if success */
+UNIV_INTERN
+bool
+os_file_allocate_func(
+ os_file_t file, /*!< in, own: handle to a file */
+ os_offset_t offset, /*!< in: file region offset */
+ os_offset_t len); /*!< in: file region length */
+#endif
#ifdef UNIV_PFS_IO
/****************************************************************//**
@@ -636,7 +769,7 @@ os_file_create_simple() which opens or creates a file.
@return own: handle to the file, not defined if error, error number
can be retrieved with os_file_get_last_error */
UNIV_INLINE
-os_file_t
+pfs_os_file_t
pfs_os_file_create_simple_func(
/*===========================*/
mysql_pfs_key_t key, /*!< in: Performance Schema Key */
@@ -661,7 +794,7 @@ monitor file creation/open.
@return own: handle to the file, not defined if error, error number
can be retrieved with os_file_get_last_error */
UNIV_INLINE
-os_file_t
+pfs_os_file_t
pfs_os_file_create_simple_no_error_handling_func(
/*=============================================*/
mysql_pfs_key_t key, /*!< in: Performance Schema Key */
@@ -687,7 +820,7 @@ Add instrumentation to monitor file creation/open.
@return own: handle to the file, not defined if error, error number
can be retrieved with os_file_get_last_error */
UNIV_INLINE
-os_file_t
+pfs_os_file_t
pfs_os_file_create_func(
/*====================*/
mysql_pfs_key_t key, /*!< in: Performance Schema Key */
@@ -718,7 +851,20 @@ UNIV_INLINE
ibool
pfs_os_file_close_func(
/*===================*/
- os_file_t file, /*!< in, own: handle to a file */
+ pfs_os_file_t file, /*!< in, own: handle to a file */
+ const char* src_file,/*!< in: file name where func invoked */
+ ulint src_line);/*!< in: line where the func invoked */
+/***********************************************************************//**
+NOTE! Please use the corresponding macro os_file_close_no_error_handling(),
+not directly this function!
+A performance schema instrumented wrapper function for
+os_file_close_no_error_handling().
+@return TRUE if success */
+UNIV_INLINE
+bool
+pfs_os_file_close_no_error_handling_func(
+/*===================*/
+ pfs_os_file_t file, /*!< in, own: handle to a file */
const char* src_file,/*!< in: file name where func invoked */
ulint src_line);/*!< in: line where the func invoked */
/*******************************************************************//**
@@ -731,7 +877,7 @@ UNIV_INLINE
ibool
pfs_os_file_read_func(
/*==================*/
- os_file_t file, /*!< in: handle to a file */
+ pfs_os_file_t file, /*!< in: handle to a file */
void* buf, /*!< in: buffer where to read */
os_offset_t offset, /*!< in: file offset where to read */
ulint n, /*!< in: number of bytes to read */
@@ -750,7 +896,7 @@ UNIV_INLINE
ibool
pfs_os_file_read_no_error_handling_func(
/*====================================*/
- os_file_t file, /*!< in: handle to a file */
+ pfs_os_file_t file, /*!< in: handle to a file */
void* buf, /*!< in: buffer where to read */
os_offset_t offset, /*!< in: file offset where to read */
ulint n, /*!< in: number of bytes to read */
@@ -772,7 +918,7 @@ pfs_os_aio_func(
ulint mode, /*!< in: OS_AIO_NORMAL etc. I/O mode */
const char* name, /*!< in: name of the file or path as a
null-terminated string */
- os_file_t file, /*!< in: handle to a file */
+ pfs_os_file_t file, /*!< in: handle to a file */
void* buf, /*!< in: buffer where to read or from which
to write */
os_offset_t offset, /*!< in: file offset where to read or write */
@@ -807,7 +953,7 @@ pfs_os_file_write_func(
/*===================*/
const char* name, /*!< in: name of the file or path as a
null-terminated string */
- os_file_t file, /*!< in: handle to a file */
+ pfs_os_file_t file, /*!< in: handle to a file */
const void* buf, /*!< in: buffer from which to write */
os_offset_t offset, /*!< in: file offset where to write */
ulint n, /*!< in: number of bytes to write */
@@ -824,7 +970,7 @@ UNIV_INLINE
ibool
pfs_os_file_flush_func(
/*===================*/
- os_file_t file, /*!< in, own: handle to a file */
+ pfs_os_file_t file, /*!< in, own: handle to a file */
const char* src_file,/*!< in: file name where func invoked */
ulint src_line);/*!< in: line where the func invoked */
@@ -876,16 +1022,66 @@ pfs_os_file_delete_if_exists_func(
string */
const char* src_file,/*!< in: file name where func invoked */
ulint src_line);/*!< in: line where the func invoked */
+
+/***********************************************************************//**
+NOTE! Please use the corresponding macro os_file_set_eof_at(), not
+directly this function!
+This is the performance schema instrumented wrapper function for
+os_file_set_eof_at()
+@return TRUE if success */
+UNIV_INLINE
+bool
+pfs_os_file_set_eof_at_func(
+ pfs_os_file_t file, /*!< in: handle to a file */
+ ib_uint64_t new_len,/*!< in: new file length */
+ const char* src_file,/*!< in: file name where func invoked */
+ ulint src_line);/*!< in: line where the func invoked */
+
+#ifdef HAVE_POSIX_FALLOCATE
+/***********************************************************************//**
+NOTE! Please use the corresponding macro os_file_allocate(), not
+directly this function!
+Ensures that disk space is allocated for the file.
+@return TRUE if success */
+UNIV_INLINE
+bool
+pfs_os_file_allocate_func(
+ pfs_os_file_t file, /*!< in, own: handle to a file */
+ os_offset_t offset, /*!< in: file region offset */
+ os_offset_t len, /*!< in: file region length */
+ const char* src_file,/*!< in: file name where func invoked */
+ ulint src_line);/*!< in: line where the func invoked */
+#endif
+
#endif /* UNIV_PFS_IO */
/***********************************************************************//**
-Closes a file handle.
-@return TRUE if success */
+Checks if the file is marked as invalid.
+@return TRUE if invalid */
UNIV_INTERN
-ibool
-os_file_close_no_error_handling(
-/*============================*/
- os_file_t file); /*!< in, own: handle to a file */
+bool
+os_file_is_invalid(
+ pfs_os_file_t file); /*!< in, own: handle to a file */
+
+/***********************************************************************//**
+Marks the file as invalid. */
+UNIV_INTERN
+void
+os_file_mark_invalid(
+ pfs_os_file_t* file); /*!< out: pointer to a handle to a file */
+
+/***********************************************************************//**
+Announces an intention to access file data in a specific pattern in the
+future.
+@return TRUE if success */
+UNIV_INTERN
+bool
+os_file_advise(
+ pfs_os_file_t file, /*!< in, own: handle to a file */
+ os_offset_t offset, /*!< in: file region offset */
+ os_offset_t len, /*!< in: file region length */
+ ulint advice);/*!< in: advice for access pattern */
+
/***********************************************************************//**
Gets a file size.
@return file size, or (os_offset_t) -1 on failure */
@@ -893,7 +1089,7 @@ UNIV_INTERN
os_offset_t
os_file_get_size(
/*=============*/
- os_file_t file) /*!< in: handle to a file */
+ pfs_os_file_t file) /*!< in: handle to a file */
MY_ATTRIBUTE((warn_unused_result));
/** Set the size of a newly created file.
@param[in] name file name
@@ -905,7 +1101,7 @@ UNIV_INTERN
bool
os_file_set_size(
const char* name,
- os_file_t file,
+ pfs_os_file_t file,
os_offset_t size,
bool is_sparse = false)
MY_ATTRIBUTE((nonnull, warn_unused_result));
@@ -918,14 +1114,6 @@ os_file_set_eof(
/*============*/
FILE* file); /*!< in: file to be truncated */
/***********************************************************************//**
-Truncates a file at the specified position.
-@return TRUE if success */
-UNIV_INTERN
-ibool
-os_file_set_eof_at(
- os_file_t file, /*!< in: handle to a file */
- ib_uint64_t new_len);/*!< in: new file length */
-/***********************************************************************//**
NOTE! Use the corresponding macro os_file_flush(), not directly this function!
Flushes the write buffers of a given file to the disk.
@return TRUE if success */
@@ -1155,7 +1343,7 @@ os_aio_func(
caution! */
const char* name, /*!< in: name of the file or path as a
null-terminated string */
- os_file_t file, /*!< in: handle to a file */
+ pfs_os_file_t file, /*!< in: handle to a file */
void* buf, /*!< in: buffer where to read or from which
to write */
os_offset_t offset, /*!< in: file offset where to read or write */
diff --git a/storage/xtradb/include/os0file.ic b/storage/xtradb/include/os0file.ic
index b284d7ea9ac..72ac9d9dd6a 100644
--- a/storage/xtradb/include/os0file.ic
+++ b/storage/xtradb/include/os0file.ic
@@ -1,7 +1,7 @@
/*****************************************************************************
-Copyright (c) 2010, 2011, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2013, SkySQL Ab. All Rights Reserved.
+Copyright (c) 2010, 2017, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2013, 2017, MariaDB Corporation.
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
@@ -35,7 +35,7 @@ os_file_create_simple() which opens or creates a file.
@return own: handle to the file, not defined if error, error number
can be retrieved with os_file_get_last_error */
UNIV_INLINE
-os_file_t
+pfs_os_file_t
pfs_os_file_create_simple_func(
/*===========================*/
mysql_pfs_key_t key, /*!< in: Performance Schema Key */
@@ -50,7 +50,7 @@ pfs_os_file_create_simple_func(
const char* src_file,/*!< in: file name where func invoked */
ulint src_line)/*!< in: line where the func invoked */
{
- os_file_t file;
+ pfs_os_file_t file;
struct PSI_file_locker* locker = NULL;
PSI_file_locker_state state;
@@ -64,8 +64,9 @@ pfs_os_file_create_simple_func(
file = os_file_create_simple_func(name, create_mode,
access_type, success, atomic_writes);
- /* Regsiter the returning "file" value with the system */
- register_pfs_file_open_end(locker, file);
+ /* Register psi value for the file */
+ register_pfs_file_open_end(locker, file,
+ (*success == TRUE ? success : 0));
return(file);
}
@@ -79,7 +80,7 @@ monitor file creation/open.
@return own: handle to the file, not defined if error, error number
can be retrieved with os_file_get_last_error */
UNIV_INLINE
-os_file_t
+pfs_os_file_t
pfs_os_file_create_simple_no_error_handling_func(
/*=============================================*/
mysql_pfs_key_t key, /*!< in: Performance Schema Key */
@@ -96,7 +97,7 @@ pfs_os_file_create_simple_no_error_handling_func(
const char* src_file,/*!< in: file name where func invoked */
ulint src_line)/*!< in: line where the func invoked */
{
- os_file_t file;
+ pfs_os_file_t file;
struct PSI_file_locker* locker = NULL;
PSI_file_locker_state state;
@@ -108,9 +109,10 @@ pfs_os_file_create_simple_no_error_handling_func(
name, src_file, src_line);
file = os_file_create_simple_no_error_handling_func(
- name, create_mode, access_type, success, atomic_writes);
+ name, create_mode, access_type, success, atomic_writes);
- register_pfs_file_open_end(locker, file);
+ register_pfs_file_open_end(locker, file,
+ (*success == TRUE ? success : 0));
return(file);
}
@@ -123,7 +125,7 @@ Add instrumentation to monitor file creation/open.
@return own: handle to the file, not defined if error, error number
can be retrieved with os_file_get_last_error */
UNIV_INLINE
-os_file_t
+pfs_os_file_t
pfs_os_file_create_func(
/*====================*/
mysql_pfs_key_t key, /*!< in: Performance Schema Key */
@@ -144,7 +146,7 @@ pfs_os_file_create_func(
const char* src_file,/*!< in: file name where func invoked */
ulint src_line)/*!< in: line where the func invoked */
{
- os_file_t file;
+ pfs_os_file_t file;
struct PSI_file_locker* locker = NULL;
PSI_file_locker_state state;
@@ -158,7 +160,8 @@ pfs_os_file_create_func(
file = os_file_create_func(name, create_mode, purpose, type,
success, atomic_writes);
- register_pfs_file_open_end(locker, file);
+ register_pfs_file_open_end(locker, file,
+ (*success == TRUE ? success : 0));
return(file);
}
@@ -172,7 +175,7 @@ UNIV_INLINE
ibool
pfs_os_file_close_func(
/*===================*/
- os_file_t file, /*!< in, own: handle to a file */
+ pfs_os_file_t file, /*!< in, own: handle to a file */
const char* src_file,/*!< in: file name where func invoked */
ulint src_line)/*!< in: line where the func invoked */
{
@@ -190,6 +193,34 @@ pfs_os_file_close_func(
return(result);
}
+/***********************************************************************//**
+NOTE! Please use the corresponding macro os_file_close_no_error_handling(),
+not directly this function!
+A performance schema instrumented wrapper function for
+os_file_close_no_error_handling().
+@return TRUE if success */
+UNIV_INLINE
+bool
+pfs_os_file_close_no_error_handling_func(
+/*===================*/
+ pfs_os_file_t file, /*!< in, own: handle to a file */
+ const char* src_file,/*!< in: file name where func invoked */
+ ulint src_line)/*!< in: line where the func invoked */
+{
+ bool result;
+ struct PSI_file_locker* locker = NULL;
+ PSI_file_locker_state state;
+
+ /* register the file close */
+ register_pfs_file_io_begin(&state, locker, file, 0, PSI_FILE_CLOSE,
+ src_file, src_line);
+
+ result = os_file_close_no_error_handling_func(file);
+
+ register_pfs_file_io_end(locker, 0);
+
+ return(result);
+}
/*******************************************************************//**
NOTE! Please use the corresponding macro os_aio(), not directly this
@@ -206,7 +237,7 @@ pfs_os_aio_func(
ulint mode, /*!< in: OS_AIO_NORMAL etc. I/O mode */
const char* name, /*!< in: name of the file or path as a
null-terminated string */
- os_file_t file, /*!< in: handle to a file */
+ pfs_os_file_t file, /*!< in: handle to a file */
void* buf, /*!< in: buffer where to read or from which
to write */
os_offset_t offset, /*!< in: file offset where to read or write */
@@ -260,7 +291,7 @@ UNIV_INLINE
ibool
pfs_os_file_read_func(
/*==================*/
- os_file_t file, /*!< in: handle to a file */
+ pfs_os_file_t file, /*!< in: handle to a file */
void* buf, /*!< in: buffer where to read */
os_offset_t offset, /*!< in: file offset where to read */
ulint n, /*!< in: number of bytes to read */
@@ -294,7 +325,7 @@ UNIV_INLINE
ibool
pfs_os_file_read_no_error_handling_func(
/*====================================*/
- os_file_t file, /*!< in: handle to a file */
+ pfs_os_file_t file, /*!< in: handle to a file */
void* buf, /*!< in: buffer where to read */
os_offset_t offset, /*!< in: file offset where to read */
ulint n, /*!< in: number of bytes to read */
@@ -315,6 +346,42 @@ pfs_os_file_read_no_error_handling_func(
return(result);
}
+/** NOTE! Please use the corresponding macro
+os_file_read_no_error_handling_int_fd(), not directly this function!
+This is the performance schema instrumented wrapper function for
+os_file_read_no_error_handling_int_fd_func() which requests a
+synchronous read operation.
+@return TRUE if request was successful, FALSE if fail */
+UNIV_INLINE
+ibool
+pfs_os_file_read_no_error_handling_int_fd_func(
+ int file, /*!< in: handle to a file */
+ void* buf, /*!< in: buffer where to read */
+ os_offset_t offset, /*!< in: file offset where to read */
+ ulint n, /*!< in: number of bytes to read */
+ const char* src_file,/*!< in: file name where func invoked */
+ ulint src_line)/*!< in: line where the func invoked */
+{
+ PSI_file_locker_state state;
+ struct PSI_file_locker* locker;
+
+ locker = PSI_FILE_CALL(get_thread_file_descriptor_locker)(
+ &state, file, PSI_FILE_READ);
+ if (locker != NULL) {
+ PSI_FILE_CALL(start_file_wait)(
+ locker, n,
+ __FILE__, __LINE__);
+ }
+ ibool result = os_file_read_no_error_handling_func(
+ OS_FILE_FROM_FD(file), buf, offset, n);
+
+ if (locker != NULL) {
+ PSI_FILE_CALL(end_file_wait)(locker, n);
+ }
+
+ return(result);
+}
+
/*******************************************************************//**
NOTE! Please use the corresponding macro os_file_write(), not directly
this function!
@@ -327,7 +394,7 @@ pfs_os_file_write_func(
/*===================*/
const char* name, /*!< in: name of the file or path as a
null-terminated string */
- os_file_t file, /*!< in: handle to a file */
+ pfs_os_file_t file, /*!< in: handle to a file */
const void* buf, /*!< in: buffer from which to write */
os_offset_t offset, /*!< in: file offset where to write */
ulint n, /*!< in: number of bytes to write */
@@ -348,6 +415,43 @@ pfs_os_file_write_func(
return(result);
}
+/** NOTE! Please use the corresponding macro os_file_write(), not
+directly this function!
+This is the performance schema instrumented wrapper function for
+os_file_write() which requests a synchronous write operation.
+@return TRUE if request was successful, FALSE if fail */
+UNIV_INLINE
+ibool
+pfs_os_file_write_int_fd_func(
+ const char* name, /*!< in: name of the file or path as a
+ null-terminated string */
+ int file, /*!< in: handle to a file */
+ const void* buf, /*!< in: buffer from which to write */
+ os_offset_t offset, /*!< in: file offset where to write */
+ ulint n, /*!< in: number of bytes to write */
+ const char* src_file,/*!< in: file name where func invoked */
+ ulint src_line)/*!< in: line where the func invoked */
+{
+ PSI_file_locker_state state;
+ struct PSI_file_locker* locker = NULL;
+
+ locker = PSI_FILE_CALL(get_thread_file_descriptor_locker)(
+ &state, file, PSI_FILE_WRITE);
+ if (locker != NULL) {
+ PSI_FILE_CALL(start_file_wait)(
+ locker, n,
+ __FILE__, __LINE__);
+ }
+ ibool result = os_file_write_func(
+ name, OS_FILE_FROM_FD(file), buf, offset, n);
+
+ if (locker != NULL) {
+ PSI_FILE_CALL(end_file_wait)(locker, n);
+ }
+
+ return(result);
+}
+
/***********************************************************************//**
NOTE! Please use the corresponding macro os_file_flush(), not directly
this function!
@@ -358,7 +462,7 @@ UNIV_INLINE
ibool
pfs_os_file_flush_func(
/*===================*/
- os_file_t file, /*!< in, own: handle to a file */
+ pfs_os_file_t file, /*!< in, own: handle to a file */
const char* src_file,/*!< in: file name where func invoked */
ulint src_line)/*!< in: line where the func invoked */
{
@@ -396,12 +500,12 @@ pfs_os_file_rename_func(
struct PSI_file_locker* locker = NULL;
PSI_file_locker_state state;
- register_pfs_file_open_begin(&state, locker, key, PSI_FILE_RENAME, newpath,
+ register_pfs_file_rename_begin(&state, locker, key, PSI_FILE_RENAME, newpath,
src_file, src_line);
result = os_file_rename_func(oldpath, newpath);
- register_pfs_file_open_end(locker, 0);
+ register_pfs_file_rename_end(locker, 0);
return(result);
}
@@ -465,4 +569,61 @@ pfs_os_file_delete_if_exists_func(
return(result);
}
+
+/***********************************************************************//**
+NOTE! Please use the corresponding macro os_file_set_eof_at(), not
+directly this function!
+This is the performance schema instrumented wrapper function for
+os_file_set_eof_at()
+@return TRUE if success */
+UNIV_INLINE
+bool
+pfs_os_file_set_eof_at_func(
+ pfs_os_file_t file, /*!< in: handle to a file */
+ ib_uint64_t new_len,/*!< in: new file length */
+ const char* src_file,/*!< in: file name where func invoked */
+ ulint src_line)/*!< in: line where the func invoked */
+{
+ bool result;
+ struct PSI_file_locker* locker = NULL;
+ PSI_file_locker_state state;
+
+ register_pfs_file_io_begin(&state, locker, file, 0, PSI_FILE_CHSIZE,
+ src_file, src_line);
+ result = os_file_set_eof_at_func(file, new_len);
+
+ register_pfs_file_io_end(locker, 0);
+
+ return(result);
+}
+
+#ifdef HAVE_POSIX_FALLOCATE
+/***********************************************************************//**
+NOTE! Please use the corresponding macro os_file_allocate(), not
+directly this function!
+Ensures that disk space is allocated for the file.
+@return TRUE if success */
+UNIV_INLINE
+bool
+pfs_os_file_allocate_func(
+ pfs_os_file_t file, /*!< in, own: handle to a file */
+ os_offset_t offset, /*!< in: file region offset */
+ os_offset_t len, /*!< in: file region length */
+ const char* src_file,/*!< in: file name where func invoked */
+ ulint src_line)/*!< in: line where the func invoked */
+{
+ bool result;
+ struct PSI_file_locker* locker = NULL;
+ PSI_file_locker_state state;
+
+ register_pfs_file_io_begin(&state, locker, file, 0, PSI_FILE_CHSIZE,
+ src_file, src_line);
+ result = os_file_allocate_func(file, offset, len);
+
+ register_pfs_file_io_end(locker, 0);
+
+ return(result);
+}
+#endif
+
#endif /* UNIV_PFS_IO */
diff --git a/storage/xtradb/include/row0mysql.h b/storage/xtradb/include/row0mysql.h
index 2bd17980896..a8503a5cfda 100644
--- a/storage/xtradb/include/row0mysql.h
+++ b/storage/xtradb/include/row0mysql.h
@@ -614,7 +614,7 @@ struct mysql_row_templ_t {
Innobase record in the current index;
not defined if template_type is
ROW_MYSQL_WHOLE_ROW */
- ibool rec_field_is_prefix; /* is this field in a prefix index? */
+ bool rec_field_is_prefix; /* is this field in a prefix index? */
ulint rec_prefix_field_no; /* record field, even if just a
prefix; same as rec_field_no when not a
prefix, otherwise rec_field_no is
diff --git a/storage/xtradb/include/srv0srv.h b/storage/xtradb/include/srv0srv.h
index c07a8db1bb3..30c125ea269 100644
--- a/storage/xtradb/include/srv0srv.h
+++ b/storage/xtradb/include/srv0srv.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1995, 2016, Oracle and/or its affiliates. All rights reserved.
+Copyright (c) 1995, 2017, Oracle and/or its affiliates. All rights reserved.
Copyright (c) 2008, 2009, Google Inc.
Copyright (c) 2009, Percona Inc.
Copyright (c) 2013, 2017, MariaDB Corporation.
@@ -1099,6 +1099,13 @@ UNIV_INTERN
void
srv_purge_wakeup();
+/** Check whether given space id is undo tablespace id
+@param[in] space_id space id to check
+@return true if it is undo tablespace else false. */
+bool
+srv_is_undo_tablespace(
+ ulint space_id);
+
/** Status variables to be passed to MySQL */
struct export_var_t{
ulint innodb_adaptive_hash_hash_searches;
diff --git a/storage/xtradb/include/srv0start.h b/storage/xtradb/include/srv0start.h
index 963b767f0fb..a60776a4665 100644
--- a/storage/xtradb/include/srv0start.h
+++ b/storage/xtradb/include/srv0start.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1995, 2017, 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
@@ -139,6 +139,8 @@ extern ibool srv_startup_is_before_trx_rollback_phase;
/** TRUE if a raw partition is in use */
extern ibool srv_start_raw_disk_in_use;
+/** Undo tablespaces starts with space_id. */
+extern ulint srv_undo_space_id_start;
/** Shutdown state */
enum srv_shutdown_state {
diff --git a/storage/xtradb/include/trx0xa.h b/storage/xtradb/include/trx0xa.h
index 7caddfb7ba4..4d5adc68dcd 100644
--- a/storage/xtradb/include/trx0xa.h
+++ b/storage/xtradb/include/trx0xa.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1995, 2009, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1995, 2016, 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
@@ -24,6 +24,8 @@ this program; if not, write to the Free Software Foundation, Inc.,
#ifndef XA_H
#define XA_H
+#include "handler.h"
+
/*
* Transaction branch identification: XID and NULLXID:
*/
@@ -35,17 +37,6 @@ this program; if not, write to the Free Software Foundation, Inc.,
#define MAXGTRIDSIZE 64 /*!< maximum size in bytes of gtrid */
#define MAXBQUALSIZE 64 /*!< maximum size in bytes of bqual */
-/** X/Open XA distributed transaction identifier */
-struct xid_t {
- long formatID; /*!< format identifier; -1
- means that the XID is null */
- long gtrid_length; /*!< value from 1 through 64 */
- long bqual_length; /*!< value from 1 through 64 */
- char data[XIDDATASIZE]; /*!< distributed transaction
- identifier */
-};
-/** X/Open XA distributed transaction identifier */
-typedef struct xid_t XID;
#endif
/** X/Open XA distributed transaction status codes */
/* @{ */
diff --git a/storage/xtradb/include/univ.i b/storage/xtradb/include/univ.i
index 310053b9145..23c8c0a659d 100644
--- a/storage/xtradb/include/univ.i
+++ b/storage/xtradb/include/univ.i
@@ -45,10 +45,10 @@ Created 1/20/1994 Heikki Tuuri
#define INNODB_VERSION_MAJOR 5
#define INNODB_VERSION_MINOR 6
-#define INNODB_VERSION_BUGFIX 35
+#define INNODB_VERSION_BUGFIX 36
#ifndef PERCONA_INNODB_VERSION
-#define PERCONA_INNODB_VERSION 80.0
+#define PERCONA_INNODB_VERSION 82.0
#endif
/* Enable UNIV_LOG_ARCHIVE in XtraDB */
@@ -146,14 +146,8 @@ HAVE_PSI_INTERFACE is defined. */
#if defined HAVE_PSI_INTERFACE && !defined UNIV_HOTBACKUP
# define UNIV_PFS_MUTEX
# define UNIV_PFS_RWLOCK
-/* For I/O instrumentation, performance schema rely
-on a native descriptor to identify the file, this
-descriptor could conflict with our OS level descriptor.
-Disable IO instrumentation on Windows until this is
-resolved */
-# ifndef __WIN__
-# define UNIV_PFS_IO
-# endif
+
+# define UNIV_PFS_IO
# define UNIV_PFS_THREAD
/* There are mutexes/rwlocks that we want to exclude from
diff --git a/storage/xtradb/log/log0log.cc b/storage/xtradb/log/log0log.cc
index 309de7daaf8..7abab278416 100644
--- a/storage/xtradb/log/log0log.cc
+++ b/storage/xtradb/log/log0log.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2009, Google Inc.
Copyright (c) 2014, 2017, MariaDB Corporation.
@@ -2804,7 +2804,7 @@ log_group_archive(
/*==============*/
log_group_t* group) /*!< in: log group */
{
- os_file_t file_handle;
+ pfs_os_file_t file_handle;
lsn_t start_lsn;
lsn_t end_lsn;
char name[OS_FILE_MAX_PATH];
@@ -3820,7 +3820,8 @@ wait_suspend_loop:
ut_a(freed);
ut_a(lsn == log_sys->lsn);
- ut_ad(lsn == log_sys->last_checkpoint_lsn);
+ ut_ad(srv_force_recovery >= SRV_FORCE_NO_LOG_REDO
+ || lsn == log_sys->last_checkpoint_lsn);
if (lsn < srv_start_lsn) {
ib_logf(IB_LOG_LEVEL_ERROR,
diff --git a/storage/xtradb/log/log0online.cc b/storage/xtradb/log/log0online.cc
index 74f2e2360a8..b00003147dd 100644
--- a/storage/xtradb/log/log0online.cc
+++ b/storage/xtradb/log/log0online.cc
@@ -329,7 +329,7 @@ log_online_read_last_tracked_lsn(void)
lsn_t result;
os_offset_t read_offset = log_bmp_sys->out.offset;
- while (!checksum_ok && read_offset > 0 && !is_last_page)
+ while ((!checksum_ok || !is_last_page) && read_offset > 0)
{
read_offset -= MODIFIED_PAGE_BLOCK_SIZE;
log_bmp_sys->out.offset = read_offset;
@@ -554,9 +554,9 @@ log_online_rotate_bitmap_file(
lsn_t next_file_start_lsn) /*!<in: the start LSN name
part */
{
- if (log_bmp_sys->out.file != os_file_invalid) {
+ if (!os_file_is_invalid(log_bmp_sys->out.file)) {
os_file_close(log_bmp_sys->out.file);
- log_bmp_sys->out.file = os_file_invalid;
+ os_file_mark_invalid(&log_bmp_sys->out.file);
}
log_bmp_sys->out_seq_num++;
log_online_make_bitmap_name(next_file_start_lsn);
@@ -723,7 +723,11 @@ log_online_read_init(void)
}
last_tracked_lsn = log_online_read_last_tracked_lsn();
+ /* Do not rotate if we truncated the file to zero length - we
+ can just start writing there */
+ const bool need_rotate = (last_tracked_lsn != 0);
if (!last_tracked_lsn) {
+
last_tracked_lsn = last_file_start_lsn;
}
@@ -735,7 +739,8 @@ log_online_read_init(void)
} else {
file_start_lsn = tracking_start_lsn;
}
- ut_a(log_online_rotate_bitmap_file(file_start_lsn));
+ ut_a(!need_rotate
+ || log_online_rotate_bitmap_file(file_start_lsn));
if (last_tracked_lsn < tracking_start_lsn) {
@@ -773,9 +778,9 @@ log_online_read_shutdown(void)
ib_rbt_node_t *free_list_node = log_bmp_sys->page_free_list;
- if (log_bmp_sys->out.file != os_file_invalid) {
+ if (!os_file_is_invalid(log_bmp_sys->out.file)) {
os_file_close(log_bmp_sys->out.file);
- log_bmp_sys->out.file = os_file_invalid;
+ os_file_mark_invalid(&log_bmp_sys->out.file);
}
rbt_free(log_bmp_sys->modified_pages);
@@ -1114,6 +1119,18 @@ log_online_write_bitmap_page(
}
});
+ /* A crash injection site that ensures last checkpoint LSN > last
+ tracked LSN, so that LSN tracking for this interval is tested. */
+ DBUG_EXECUTE_IF("crash_before_bitmap_write",
+ {
+ ulint space_id
+ = mach_read_from_4(block
+ + MODIFIED_PAGE_SPACE_ID);
+ if (space_id > 0)
+ DBUG_SUICIDE();
+ });
+
+
ibool success = os_file_write(log_bmp_sys->out.name,
log_bmp_sys->out.file, block,
log_bmp_sys->out.offset,
@@ -1137,10 +1154,8 @@ log_online_write_bitmap_page(
return FALSE;
}
-#ifdef UNIV_LINUX
- posix_fadvise(log_bmp_sys->out.file, log_bmp_sys->out.offset,
- MODIFIED_PAGE_BLOCK_SIZE, POSIX_FADV_DONTNEED);
-#endif
+ os_file_advise(log_bmp_sys->out.file, log_bmp_sys->out.offset,
+ MODIFIED_PAGE_BLOCK_SIZE, OS_FILE_ADVISE_DONTNEED);
log_bmp_sys->out.offset += MODIFIED_PAGE_BLOCK_SIZE;
return TRUE;
@@ -1262,10 +1277,6 @@ log_online_follow_redo_log(void)
group = UT_LIST_GET_NEXT(log_groups, group);
}
- /* A crash injection site that ensures last checkpoint LSN > last
- tracked LSN, so that LSN tracking for this interval is tested. */
- DBUG_EXECUTE_IF("crash_before_bitmap_write", DBUG_SUICIDE(););
-
result = log_online_write_bitmap();
log_bmp_sys->start_lsn = log_bmp_sys->end_lsn;
log_set_tracked_lsn(log_bmp_sys->start_lsn);
@@ -1535,10 +1546,8 @@ log_online_open_bitmap_file_read_only(
bitmap_file->size = os_file_get_size(bitmap_file->file);
bitmap_file->offset = 0;
-#ifdef UNIV_LINUX
- posix_fadvise(bitmap_file->file, 0, 0, POSIX_FADV_SEQUENTIAL);
- posix_fadvise(bitmap_file->file, 0, 0, POSIX_FADV_NOREUSE);
-#endif
+ os_file_advise(bitmap_file->file, 0, 0, OS_FILE_ADVISE_SEQUENTIAL);
+ os_file_advise(bitmap_file->file, 0, 0, OS_FILE_ADVISE_NOREUSE);
return TRUE;
}
@@ -1624,7 +1633,7 @@ log_online_bitmap_iterator_init(
/* Empty range */
i->in_files.count = 0;
i->in_files.files = NULL;
- i->in.file = os_file_invalid;
+ os_file_mark_invalid(&i->in.file);
i->page = NULL;
i->failed = FALSE;
return TRUE;
@@ -1642,7 +1651,7 @@ log_online_bitmap_iterator_init(
if (i->in_files.count == 0) {
/* Empty range */
- i->in.file = os_file_invalid;
+ os_file_mark_invalid(&i->in.file);
i->page = NULL;
i->failed = FALSE;
return TRUE;
@@ -1681,10 +1690,10 @@ log_online_bitmap_iterator_release(
{
ut_a(i);
- if (i->in.file != os_file_invalid) {
+ if (!os_file_is_invalid(i->in.file)) {
os_file_close(i->in.file);
- i->in.file = os_file_invalid;
+ os_file_mark_invalid(&i->in.file);
}
if (i->in_files.files) {
@@ -1738,8 +1747,9 @@ log_online_bitmap_iterator_next(
/* Advance file */
i->in_i++;
- success = os_file_close_no_error_handling(i->in.file);
- i->in.file = os_file_invalid;
+ success = os_file_close_no_error_handling(
+ i->in.file);
+ os_file_mark_invalid(&i->in.file);
if (UNIV_UNLIKELY(!success)) {
os_file_get_last_error(TRUE);
@@ -1848,7 +1858,7 @@ log_online_purge_changed_page_bitmaps(
/* If we have to delete the current output file, close it
first. */
os_file_close(log_bmp_sys->out.file);
- log_bmp_sys->out.file = os_file_invalid;
+ os_file_mark_invalid(&log_bmp_sys->out.file);
}
for (i = 0; i < bitmap_files.count; i++) {
diff --git a/storage/xtradb/log/log0recv.cc b/storage/xtradb/log/log0recv.cc
index 978e6051711..0b797fd6c23 100644
--- a/storage/xtradb/log/log0recv.cc
+++ b/storage/xtradb/log/log0recv.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1997, 2016, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1997, 2017, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2012, Facebook Inc.
Copyright (c) 2013, 2017, MariaDB Corporation.
@@ -332,6 +332,7 @@ DECLARE_THREAD(recv_writer_thread)(
/*!< in: a dummy parameter required by
os_thread_create */
{
+ my_thread_init();
ut_ad(!srv_read_only_mode);
#ifdef UNIV_PFS_THREAD
@@ -362,6 +363,7 @@ DECLARE_THREAD(recv_writer_thread)(
recv_writer_thread_active = false;
+ my_thread_end();
/* 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. */
diff --git a/storage/xtradb/os/os0file.cc b/storage/xtradb/os/os0file.cc
index 4f219b18428..34336a4bb7d 100644
--- a/storage/xtradb/os/os0file.cc
+++ b/storage/xtradb/os/os0file.cc
@@ -1,6 +1,6 @@
/***********************************************************************
-Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2009, Percona Inc.
Copyright (c) 2013, 2017, MariaDB Corporation.
@@ -114,10 +114,12 @@ my_umask */
#ifndef __WIN__
/** Umask for creating files */
UNIV_INTERN ulint os_innodb_umask = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP;
+# define os_file_invalid (-1)
#else
/** Umask for creating files */
UNIV_INTERN ulint os_innodb_umask = 0;
-#define ECANCELED 125
+# define ECANCELED 125
+# define os_file_invalid INVALID_HANDLE_VALUE
#endif /* __WIN__ */
#ifndef UNIV_HOTBACKUP
@@ -221,7 +223,7 @@ struct os_aio_slot_t{
ulint page_size; /*!< UNIV_PAGE_SIZE or zip_size */
os_offset_t offset; /*!< file offset in bytes */
- os_file_t file; /*!< file where to read or write */
+ pfs_os_file_t file; /*!< file where to read or write */
const char* name; /*!< file name or path */
ibool io_already_done;/*!< used only in simulated aio:
TRUE if the physical i/o already
@@ -1568,7 +1570,7 @@ A simple function to open or create a file.
@return own: handle to the file, not defined if error, error number
can be retrieved with os_file_get_last_error */
UNIV_INTERN
-os_file_t
+pfs_os_file_t
os_file_create_simple_no_error_handling_func(
/*=========================================*/
const char* name, /*!< in: name of the file or path as a
@@ -1584,7 +1586,7 @@ os_file_create_simple_no_error_handling_func(
ulint atomic_writes) /*! in: atomic writes table option
value */
{
- os_file_t file;
+ pfs_os_file_t file;
atomic_writes_t awrites = (atomic_writes_t) atomic_writes;
*success = FALSE;
@@ -1593,7 +1595,6 @@ os_file_create_simple_no_error_handling_func(
DWORD create_flag;
DWORD attributes = 0;
DWORD share_mode = FILE_SHARE_READ;
-
ut_a(name);
ut_a(!(create_mode & OS_FILE_ON_ERROR_SILENT));
@@ -1610,8 +1611,8 @@ os_file_create_simple_no_error_handling_func(
ib_logf(IB_LOG_LEVEL_ERROR,
"Unknown file create mode (%lu) for file '%s'",
create_mode, name);
-
- return((os_file_t) -1);
+ file = INVALID_HANDLE_VALUE;
+ return(file);
}
if (access_type == OS_FILE_READ_ONLY) {
@@ -1635,8 +1636,8 @@ os_file_create_simple_no_error_handling_func(
ib_logf(IB_LOG_LEVEL_ERROR,
"Unknown file access type (%lu) for file '%s'",
access_type, name);
-
- return((os_file_t) -1);
+ file = INVALID_HANDLE_VALUE;
+ return(file);
}
if (IS_XTRABACKUP()) {
@@ -1668,11 +1669,10 @@ os_file_create_simple_no_error_handling_func(
}
}
- *success = (file != INVALID_HANDLE_VALUE);
+ *success = file != INVALID_HANDLE_VALUE;
#else /* __WIN__ */
int create_flag;
const char* mode_str = NULL;
-
ut_a(name);
if (create_mode != OS_FILE_OPEN && create_mode != OS_FILE_OPEN_RAW)
WAIT_ALLOW_WRITES();
@@ -1717,13 +1717,13 @@ os_file_create_simple_no_error_handling_func(
ib_logf(IB_LOG_LEVEL_ERROR,
"Unknown file create mode (%lu) for file '%s'",
create_mode, name);
-
- return((os_file_t) -1);
+ file = -1;
+ return(file);
}
- file = ::open(name, create_flag, os_innodb_umask);
+ file = open(name, create_flag, os_innodb_umask);
- *success = file == -1 ? FALSE : TRUE;
+ *success = file != -1;
/* This function is always called for data files, we should disable
OS caching (O_DIRECT) here as we do in os_file_create_func(), so
@@ -1872,7 +1872,7 @@ Opens an existing file or creates a new.
@return own: handle to the file, not defined if error, error number
can be retrieved with os_file_get_last_error */
UNIV_INTERN
-os_file_t
+pfs_os_file_t
os_file_create_func(
/*================*/
const char* name, /*!< in: name of the file or path as a
@@ -1890,7 +1890,7 @@ os_file_create_func(
ulint atomic_writes) /*! in: atomic writes table option
value */
{
- os_file_t file;
+ pfs_os_file_t file;
ibool retry;
ibool on_error_no_exit;
ibool on_error_silent;
@@ -1901,14 +1901,16 @@ os_file_create_func(
"ib_create_table_fail_disk_full",
*success = FALSE;
SetLastError(ERROR_DISK_FULL);
- return((os_file_t) -1);
+ file = INVALID_HANDLE_VALUE;
+ return(file);
);
#else /* __WIN__ */
DBUG_EXECUTE_IF(
"ib_create_table_fail_disk_full",
*success = FALSE;
errno = ENOSPC;
- return((os_file_t) -1);
+ file = -1;
+ return(file);
);
#endif /* __WIN__ */
@@ -1962,7 +1964,8 @@ os_file_create_func(
"Unknown file create mode (%lu) for file '%s'",
create_mode, name);
- return((os_file_t) -1);
+ file = INVALID_HANDLE_VALUE;
+ return(file);
}
DWORD attributes = 0;
@@ -1986,8 +1989,8 @@ os_file_create_func(
ib_logf(IB_LOG_LEVEL_ERROR,
"Unknown purpose flag (%lu) while opening file '%s'",
purpose, name);
-
- return((os_file_t)(-1));
+ file = INVALID_HANDLE_VALUE;
+ return(file);
}
#ifdef UNIV_NON_BUFFERED_IO
@@ -2113,7 +2116,8 @@ os_file_create_func(
"Unknown file create mode (%lu) for file '%s'",
create_mode, name);
- return((os_file_t) -1);
+ file = -1;
+ return(file);
}
ut_a(type == OS_LOG_FILE || type == OS_DATA_FILE);
@@ -2133,7 +2137,7 @@ os_file_create_func(
#endif /* O_SYNC */
do {
- file = ::open(name, create_flag, os_innodb_umask);
+ file = open(name, create_flag, os_innodb_umask);
if (file == -1) {
const char* operation;
@@ -2442,8 +2446,8 @@ os_file_close_func(
Closes a file handle.
@return TRUE if success */
UNIV_INTERN
-ibool
-os_file_close_no_error_handling(
+bool
+os_file_close_no_error_handling_func(
/*============================*/
os_file_t file) /*!< in, own: handle to a file */
{
@@ -2453,10 +2457,10 @@ os_file_close_no_error_handling(
ret = CloseHandle(file);
if (ret) {
- return(TRUE);
+ return(true);
}
- return(FALSE);
+ return(false);
#else
int ret;
@@ -2464,10 +2468,83 @@ os_file_close_no_error_handling(
if (ret == -1) {
- return(FALSE);
+ return(false);
}
- return(TRUE);
+ return(true);
+#endif /* __WIN__ */
+}
+
+#ifdef HAVE_POSIX_FALLOCATE
+/***********************************************************************//**
+Ensures that disk space is allocated for the file.
+@return TRUE if success */
+UNIV_INTERN
+bool
+os_file_allocate_func(
+ os_file_t file, /*!< in, own: handle to a file */
+ os_offset_t offset, /*!< in: file region offset */
+ os_offset_t len) /*!< in: file region length */
+{
+ return(posix_fallocate(file, offset, len) == 0);
+}
+#endif
+
+/***********************************************************************//**
+Checks if the file is marked as invalid.
+@return TRUE if invalid */
+UNIV_INTERN
+bool
+os_file_is_invalid(
+ pfs_os_file_t file) /*!< in, own: handle to a file */
+{
+ return(file == os_file_invalid);
+}
+
+/***********************************************************************//**
+Marks the file as invalid. */
+UNIV_INTERN
+void
+os_file_mark_invalid(
+ pfs_os_file_t* file) /*!< out: pointer to a handle to a file */
+{
+ file->m_file = os_file_invalid;
+}
+
+/***********************************************************************//**
+Announces an intention to access file data in a specific pattern in the
+future.
+@return TRUE if success */
+UNIV_INTERN
+bool
+os_file_advise(
+ pfs_os_file_t file, /*!< in, own: handle to a file */
+ os_offset_t offset, /*!< in: file region offset */
+ os_offset_t len, /*!< in: file region length */
+ ulint advice)/*!< in: advice for access pattern */
+{
+#ifdef __WIN__
+ return(true);
+#else
+#ifdef UNIV_LINUX
+ int native_advice = 0;
+ if ((advice & OS_FILE_ADVISE_NORMAL) != 0)
+ native_advice |= POSIX_FADV_NORMAL;
+ if ((advice & OS_FILE_ADVISE_RANDOM) != 0)
+ native_advice |= POSIX_FADV_RANDOM;
+ if ((advice & OS_FILE_ADVISE_SEQUENTIAL) != 0)
+ native_advice |= POSIX_FADV_SEQUENTIAL;
+ if ((advice & OS_FILE_ADVISE_WILLNEED) != 0)
+ native_advice |= POSIX_FADV_WILLNEED;
+ if ((advice & OS_FILE_ADVISE_DONTNEED) != 0)
+ native_advice |= POSIX_FADV_DONTNEED;
+ if ((advice & OS_FILE_ADVISE_NOREUSE) != 0)
+ native_advice |= POSIX_FADV_NOREUSE;
+
+ return(posix_fadvise(file, offset, len, native_advice) == 0);
+#else
+ return(true);
+#endif
#endif /* __WIN__ */
}
@@ -2478,7 +2555,7 @@ UNIV_INTERN
os_offset_t
os_file_get_size(
/*=============*/
- os_file_t file) /*!< in: handle to a file */
+ pfs_os_file_t file) /*!< in: handle to a file */
{
#ifdef __WIN__
os_offset_t offset;
@@ -2496,6 +2573,7 @@ os_file_get_size(
return(offset);
#else
return((os_offset_t) lseek(file, 0, SEEK_END));
+
#endif /* __WIN__ */
}
@@ -2509,7 +2587,7 @@ UNIV_INTERN
bool
os_file_set_size(
const char* name,
- os_file_t file,
+ pfs_os_file_t file,
os_offset_t size,
bool is_sparse)
{
@@ -2618,8 +2696,8 @@ os_file_set_eof(
Truncates a file at the specified position.
@return TRUE if success */
UNIV_INTERN
-ibool
-os_file_set_eof_at(
+bool
+os_file_set_eof_at_func(
os_file_t file, /*!< in: handle to a file */
ib_uint64_t new_len)/*!< in: new file length */
{
@@ -4553,7 +4631,7 @@ os_aio_array_reserve_slot(
the aio operation */
void* message2,/*!< in: message to be passed along with
the aio operation */
- os_file_t file, /*!< in: file handle */
+ pfs_os_file_t file, /*!< in: file handle */
const char* name, /*!< in: name of the file or path as a
null-terminated string */
void* buf, /*!< in: buffer where to read or from which
@@ -4928,7 +5006,7 @@ os_aio_func(
caution! */
const char* name, /*!< in: name of the file or path as a
null-terminated string */
- os_file_t file, /*!< in: handle to a file */
+ pfs_os_file_t file, /*!< in: handle to a file */
void* buf, /*!< in: buffer where to read or from which
to write */
os_offset_t offset, /*!< in: file offset where to read or write */
@@ -4958,7 +5036,6 @@ os_aio_func(
BOOL ret;
#endif
ulint wake_later;
-
ut_ad(buf);
ut_ad(n > 0);
ut_ad(n % OS_MIN_LOG_BLOCK_SIZE == 0);
@@ -5205,7 +5282,6 @@ os_aio_windows_handle(
break;
}
}
-
*message1 = slot->message1;
*message2 = slot->message2;
@@ -5229,12 +5305,14 @@ os_aio_windows_handle(
switch (slot->type) {
case OS_FILE_WRITE:
- ret_val = os_file_write(slot->name, slot->file, slot->buf,
- slot->offset, slot->len);
+ ret_val = os_file_write(
+ slot->name, slot->file, slot->buf,
+ slot->offset, slot->len);
break;
case OS_FILE_READ:
- ret_val = os_file_read(slot->file, slot->buf,
- slot->offset, slot->len);
+ ret_val = os_file_read(
+ slot->file, slot->buf,
+ slot->offset, slot->len);
break;
default:
ut_error;
@@ -5503,12 +5581,14 @@ found:
iocb = &(slot->control);
if (slot->type == OS_FILE_READ) {
- io_prep_pread(&slot->control, slot->file, slot->buf,
- slot->len, (off_t) slot->offset);
+ io_prep_pread(&slot->control, slot->file,
+ slot->buf, slot->len,
+ (off_t) slot->offset);
} else {
ut_a(slot->type == OS_FILE_WRITE);
- io_prep_pwrite(&slot->control, slot->file, slot->buf,
- slot->len, (off_t) slot->offset);
+ io_prep_pwrite(&slot->control, slot->file,
+ slot->buf, slot->len,
+ (off_t) slot->offset);
}
/* Resubmit an I/O request */
submit_ret = io_submit(array->aio_ctx[segment], 1, &iocb);
@@ -5742,7 +5822,6 @@ consecutive_loop:
os_aio_slot_t* slot;
slot = os_aio_array_get_nth_slot(array, i + segment * n);
-
if (slot->reserved
&& slot != aio_slot
&& slot->offset == aio_slot->offset + aio_slot->len
@@ -6296,7 +6375,9 @@ os_file_trim(
#ifdef __linux__
#if defined(HAVE_FALLOC_PUNCH_HOLE_AND_KEEP_SIZE)
- int ret = fallocate(slot->file, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, off, trim_len);
+ int ret = fallocate(slot->file,
+ FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
+ off, trim_len);
if (ret) {
/* After first failure do not try to trim again */
diff --git a/storage/xtradb/row/row0log.cc b/storage/xtradb/row/row0log.cc
index 3cb909632dc..2cd663fd600 100644
--- a/storage/xtradb/row/row0log.cc
+++ b/storage/xtradb/row/row0log.cc
@@ -368,9 +368,9 @@ row_log_online_op(
goto err_exit;
}
- ret = os_file_write(
+ ret = os_file_write_int_fd(
"(modification log)",
- OS_FILE_FROM_FD(log->fd),
+ log->fd,
log->tail.block, byte_offset, srv_sort_buf_size);
log->tail.blocks++;
if (!ret) {
@@ -484,9 +484,9 @@ row_log_table_close_func(
goto err_exit;
}
- ret = os_file_write(
+ ret = os_file_write_int_fd(
"(modification log)",
- OS_FILE_FROM_FD(log->fd),
+ log->fd,
log->tail.block, byte_offset, srv_sort_buf_size);
log->tail.blocks++;
if (!ret) {
@@ -2619,11 +2619,10 @@ all_done:
goto func_exit;
}
- success = os_file_read_no_error_handling(
- OS_FILE_FROM_FD(index->online_log->fd),
+ success = os_file_read_no_error_handling_int_fd(
+ index->online_log->fd,
index->online_log->head.block, ofs,
srv_sort_buf_size);
-
if (!success) {
fprintf(stderr, "InnoDB: unable to read temporary file"
" for table %s\n", index->table_name);
@@ -3446,8 +3445,8 @@ all_done:
goto func_exit;
}
- success = os_file_read_no_error_handling(
- OS_FILE_FROM_FD(index->online_log->fd),
+ success = os_file_read_no_error_handling_int_fd(
+ index->online_log->fd,
index->online_log->head.block, ofs,
srv_sort_buf_size);
diff --git a/storage/xtradb/row/row0merge.cc b/storage/xtradb/row/row0merge.cc
index f0c804eb4bc..42033983cfa 100644
--- a/storage/xtradb/row/row0merge.cc
+++ b/storage/xtradb/row/row0merge.cc
@@ -967,8 +967,8 @@ row_merge_read(
}
#endif /* UNIV_DEBUG */
- success = os_file_read_no_error_handling(OS_FILE_FROM_FD(fd), buf,
- ofs, srv_sort_buf_size);
+ success = os_file_read_no_error_handling_int_fd(fd, buf,
+ ofs, srv_sort_buf_size);
/* For encrypted tables, decrypt data after reading and copy data */
if (crypt_data && crypt_buf) {
@@ -1023,7 +1023,7 @@ row_merge_write(
mach_write_to_4((byte *)out_buf, 0);
}
- ret = os_file_write("(merge)", OS_FILE_FROM_FD(fd), out_buf, ofs, buf_len);
+ ret = os_file_write_int_fd("(merge)", fd, buf, ofs, buf_len);
#ifdef UNIV_DEBUG
if (row_merge_print_block_write) {
@@ -3427,14 +3427,21 @@ row_merge_file_create_low(
performance schema */
struct PSI_file_locker* locker = NULL;
PSI_file_locker_state state;
- register_pfs_file_open_begin(&state, locker, innodb_file_temp_key,
- PSI_FILE_OPEN,
- "Innodb Merge Temp File",
- __FILE__, __LINE__);
+ locker = PSI_FILE_CALL(get_thread_file_name_locker)(
+ &state, innodb_file_temp_key, PSI_FILE_OPEN,
+ "Innodb Merge Temp File", &locker);
+ if (locker != NULL) {
+ PSI_FILE_CALL(start_file_open_wait)(locker,
+ __FILE__,
+ __LINE__);
+ }
#endif
fd = innobase_mysql_tmpfile(path);
#ifdef UNIV_PFS_IO
- register_pfs_file_open_end(locker, fd);
+ if (locker != NULL) {
+ PSI_FILE_CALL(end_file_open_wait_and_bind_to_descriptor)(
+ locker, fd);
+ }
#endif
if (fd < 0) {
@@ -3481,15 +3488,20 @@ row_merge_file_destroy_low(
#ifdef UNIV_PFS_IO
struct PSI_file_locker* locker = NULL;
PSI_file_locker_state state;
- register_pfs_file_io_begin(&state, locker,
- fd, 0, PSI_FILE_CLOSE,
- __FILE__, __LINE__);
+ locker = PSI_FILE_CALL(get_thread_file_descriptor_locker)(
+ &state, fd, PSI_FILE_CLOSE);
+ if (locker != NULL) {
+ PSI_FILE_CALL(start_file_wait)(
+ locker, 0, __FILE__, __LINE__);
+ }
#endif
if (fd >= 0) {
close(fd);
}
#ifdef UNIV_PFS_IO
- register_pfs_file_io_end(locker, 0);
+ if (locker != NULL) {
+ PSI_FILE_CALL(end_file_wait)(locker, 0);
+ }
#endif
}
/*********************************************************************//**
diff --git a/storage/xtradb/row/row0sel.cc b/storage/xtradb/row/row0sel.cc
index 7d4435eba5b..8e3ed3d1a4e 100644
--- a/storage/xtradb/row/row0sel.cc
+++ b/storage/xtradb/row/row0sel.cc
@@ -66,6 +66,8 @@ Created 12/19/1997 Heikki Tuuri
#include "my_compare.h" /* enum icp_result */
+#include <vector>
+
/* Maximum number of rows to prefetch; MySQL interface has another parameter */
#define SEL_MAX_N_PREFETCH 16
@@ -2715,7 +2717,8 @@ row_sel_field_store_in_mysql_format_func(
|| !(templ->mysql_col_len % templ->mbmaxlen));
ut_ad(len * templ->mbmaxlen >= templ->mysql_col_len
|| (field_no == templ->icp_rec_field_no
- && field->prefix_len > 0));
+ && field->prefix_len > 0)
+ || templ->rec_field_is_prefix);
ut_ad(!(field->prefix_len % templ->mbmaxlen));
if (templ->mbminlen == 1 && templ->mbmaxlen != 1) {
@@ -2757,27 +2760,32 @@ row_sel_field_store_in_mysql_format_func(
# define row_sel_store_mysql_field(m,p,r,i,o,f,t) \
row_sel_store_mysql_field_func(m,p,r,o,f,t)
#endif /* UNIV_DEBUG */
-/**************************************************************//**
-Convert a field in the Innobase format to a field in the MySQL format. */
+/** Convert a field in the Innobase format to a field in the MySQL format.
+@param[out] mysql_rec record in the MySQL format
+@param[in,out] prebuilt prebuilt struct
+@param[in] rec InnoDB record; must be protected
+ by a page latch
+@param[in] index index of rec
+@param[in] offsets array returned by rec_get_offsets()
+@param[in] field_no templ->rec_field_no or
+ templ->clust_rec_field_no
+ or templ->icp_rec_field_no
+ or sec field no if clust_templ_for_sec
+ is TRUE
+@param[in] templ row template
+*/
static MY_ATTRIBUTE((warn_unused_result))
ibool
row_sel_store_mysql_field_func(
-/*===========================*/
- byte* mysql_rec, /*!< out: record in the
- MySQL format */
- row_prebuilt_t* prebuilt, /*!< in/out: prebuilt struct */
- const rec_t* rec, /*!< in: InnoDB record;
- must be protected by
- a page latch */
+ byte* mysql_rec,
+ row_prebuilt_t* prebuilt,
+ const rec_t* rec,
#ifdef UNIV_DEBUG
- const dict_index_t* index, /*!< in: index of rec */
+ const dict_index_t* index,
#endif
- const ulint* offsets, /*!< in: array returned by
- rec_get_offsets() */
- ulint field_no, /*!< in: templ->rec_field_no or
- templ->clust_rec_field_no or
- templ->icp_rec_field_no */
- const mysql_row_templ_t*templ) /*!< in: row template */
+ const ulint* offsets,
+ ulint field_no,
+ const mysql_row_templ_t*templ)
{
const byte* data;
ulint len;
@@ -2906,31 +2914,31 @@ row_sel_store_mysql_field_func(
return(TRUE);
}
-/**************************************************************//**
-Convert a row in the Innobase format to a row in the MySQL format.
+/** Convert a row in the Innobase format to a row in the MySQL format.
Note that the template in prebuilt may advise us to copy only a few
columns to mysql_rec, other columns are left blank. All columns may not
be needed in the query.
+@param[out] mysql_rec row in the MySQL format
+@param[in] prebuilt prebuilt structure
+@param[in] rec Innobase record in the index
+ which was described in prebuilt's
+ template, or in the clustered index;
+ must be protected by a page latch
+@param[in] rec_clust TRUE if the rec in the clustered index
+@param[in] index index of rec
+@param[in] offsets array returned by rec_get_offsets(rec)
@return TRUE on success, FALSE if not all columns could be retrieved */
static MY_ATTRIBUTE((warn_unused_result))
ibool
row_sel_store_mysql_rec(
-/*====================*/
- byte* mysql_rec, /*!< out: row in the MySQL format */
- row_prebuilt_t* prebuilt, /*!< in: prebuilt struct */
- const rec_t* rec, /*!< in: Innobase record in the index
- which was described in prebuilt's
- template, or in the clustered index;
- must be protected by a page latch */
- ibool rec_clust, /*!< in: TRUE if rec is in the
- clustered index instead of
- prebuilt->index */
- const dict_index_t* index, /*!< in: index of rec */
- const ulint* offsets) /*!< in: array returned by
- rec_get_offsets(rec) */
+ byte* mysql_rec,
+ row_prebuilt_t* prebuilt,
+ const rec_t* rec,
+ ibool rec_clust,
+ const dict_index_t* index,
+ const ulint* offsets)
{
ulint i;
-
ut_ad(rec_clust || index == prebuilt->index);
ut_ad(!rec_clust || dict_index_is_clust(index));
@@ -2946,12 +2954,14 @@ row_sel_store_mysql_rec(
? templ->clust_rec_field_no
: templ->rec_field_no;
/* We should never deliver column prefixes to MySQL,
- except for evaluating innobase_index_cond(). */
+ except for evaluating innobase_index_cond() and if the prefix
+ index is longer than the actual row data. */
/* ...actually, we do want to do this in order to
support the prefix query optimization.
ut_ad(dict_index_get_nth_field(index, field_no)->prefix_len
- == 0);
+ == 0 || templ->rec_field_is_prefix);
+
...so we disable this assert. */
@@ -3681,7 +3691,7 @@ row_search_for_mysql(
trx_t* trx = prebuilt->trx;
dict_index_t* clust_index;
que_thr_t* thr;
- const rec_t* rec;
+ const rec_t* rec = NULL;
const rec_t* result_rec = NULL;
const rec_t* clust_rec;
dberr_t err = DB_SUCCESS;
@@ -3706,7 +3716,7 @@ row_search_for_mysql(
ulint* offsets = offsets_;
ibool table_lock_waited = FALSE;
byte* next_buf = 0;
- ibool use_clustered_index = FALSE;
+ bool use_clustered_index = false;
rec_offs_init(offsets_);
@@ -3966,7 +3976,8 @@ row_search_for_mysql(
if (!row_sel_store_mysql_rec(
buf, prebuilt,
- rec, FALSE, index, offsets)) {
+ rec, FALSE, index,
+ offsets)) {
/* Only fresh inserts may contain
incomplete externally stored
columns. Pretend that such
@@ -4248,7 +4259,6 @@ rec_loop:
}
if (page_rec_is_supremum(rec)) {
-
if (set_also_gap_locks
&& !(srv_locks_unsafe_for_binlog
|| trx->isolation_level <= TRX_ISO_READ_COMMITTED)
@@ -4777,17 +4787,17 @@ locks_ok:
indexes are shorter than the prefix size
This optimization can avoid many IOs for certain schemas.
*/
- ibool row_contains_all_values = TRUE;
- int i;
+ bool row_contains_all_values = true;
+ unsigned int i;
for (i = 0; i < prebuilt->n_template; i++) {
/* Condition (1) from above: is the field in the
index (prefix or not)? */
- mysql_row_templ_t* templ =
+ const mysql_row_templ_t* templ =
prebuilt->mysql_template + i;
ulint secondary_index_field_no =
templ->rec_prefix_field_no;
if (secondary_index_field_no == ULINT_UNDEFINED) {
- row_contains_all_values = FALSE;
+ row_contains_all_values = false;
break;
}
/* Condition (2) from above: if this is a
@@ -4802,8 +4812,9 @@ locks_ok:
index,
secondary_index_field_no);
ut_a(field->prefix_len > 0);
- if (record_size >= field->prefix_len) {
- row_contains_all_values = FALSE;
+ if (record_size >= field->prefix_len
+ / templ->mbmaxlen) {
+ row_contains_all_values = false;
break;
}
}
@@ -4819,7 +4830,7 @@ locks_ok:
templ->rec_prefix_field_no;
ut_a(templ->rec_field_no != ULINT_UNDEFINED);
}
- use_clustered_index = FALSE;
+ use_clustered_index = false;
srv_stats.n_sec_rec_cluster_reads_avoided.inc();
}
}
diff --git a/storage/xtradb/srv/srv0srv.cc b/storage/xtradb/srv/srv0srv.cc
index 4a05bb7a532..d04149dd243 100644
--- a/storage/xtradb/srv/srv0srv.cc
+++ b/storage/xtradb/srv/srv0srv.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2008, 2009 Google Inc.
Copyright (c) 2009, Percona Inc.
Copyright (c) 2013, 2017, MariaDB Corporation.
@@ -171,7 +171,8 @@ UNIV_INTERN unsigned long long srv_online_max_size;
OS (provided we compiled Innobase with it in), otherwise we will
use simulated aio we build below with threads.
Currently we support native aio on windows and linux */
-UNIV_INTERN my_bool srv_use_native_aio = TRUE;
+/* make srv_use_native_aio to be visible for other plugins */
+my_bool srv_use_native_aio = TRUE;
UNIV_INTERN my_bool srv_numa_interleave = FALSE;
/* Default compression level if page compression is used and no compression
@@ -3153,6 +3154,8 @@ DECLARE_THREAD(srv_master_thread)(
/*!< in: a dummy parameter required by
os_thread_create */
{
+ my_thread_init();
+
srv_slot_t* slot;
ulint old_activity_count = srv_get_activity_count();
ulint old_ibuf_merge_activity_count
@@ -3226,6 +3229,7 @@ suspend_thread:
srv_resume_thread(slot);
if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) {
+ my_thread_end();
os_thread_exit(NULL);
}
@@ -3312,6 +3316,8 @@ DECLARE_THREAD(srv_worker_thread)(
void* arg MY_ATTRIBUTE((unused))) /*!< in: a dummy parameter
required by os_thread_create */
{
+ my_thread_init();
+
srv_slot_t* slot;
ulint tid_i = os_atomic_increment_ulint(&purge_tid_i, 1);
@@ -3377,6 +3383,7 @@ DECLARE_THREAD(srv_worker_thread)(
os_thread_pf(os_thread_get_curr_id()));
#endif /* UNIV_DEBUG_THREAD_CREATION */
+ my_thread_end();
/* 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. */
os_thread_exit(NULL);
@@ -3545,6 +3552,8 @@ DECLARE_THREAD(srv_purge_coordinator_thread)(
void* arg MY_ATTRIBUTE((unused))) /*!< in: a dummy parameter
required by os_thread_create */
{
+ my_thread_init();
+
srv_slot_t* slot;
ulint n_total_purged = ULINT_UNDEFINED;
@@ -3658,6 +3667,7 @@ DECLARE_THREAD(srv_purge_coordinator_thread)(
srv_release_threads(SRV_WORKER, srv_n_purge_threads - 1);
}
+ my_thread_end();
/* 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. */
os_thread_exit(NULL);
@@ -3723,3 +3733,19 @@ srv_purge_wakeup()
}
}
}
+
+/** Check whether given space id is undo tablespace id
+@param[in] space_id space id to check
+@return true if it is undo tablespace else false. */
+bool
+srv_is_undo_tablespace(
+ ulint space_id)
+{
+ if (srv_undo_space_id_start == 0) {
+ return (false);
+ }
+
+ return(space_id >= srv_undo_space_id_start
+ && space_id < (srv_undo_space_id_start
+ + srv_undo_tablespaces_open));
+}
diff --git a/storage/xtradb/srv/srv0start.cc b/storage/xtradb/srv/srv0start.cc
index c383121de55..46fb0017a9a 100644
--- a/storage/xtradb/srv/srv0start.cc
+++ b/storage/xtradb/srv/srv0start.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
+Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved.
Copyright (c) 2008, Google Inc.
Copyright (c) 2009, Percona Inc.
Copyright (c) 2013, 2017, MariaDB Corporation
@@ -121,6 +121,9 @@ UNIV_INTERN ibool srv_have_fullfsync = FALSE;
/** TRUE if a raw partition is in use */
UNIV_INTERN ibool srv_start_raw_disk_in_use = FALSE;
+/** UNDO tablespaces starts with space id. */
+ulint srv_undo_space_id_start;
+
/** TRUE if the server is being started, before rolling back any
incomplete transactions */
UNIV_INTERN ibool srv_startup_is_before_trx_rollback_phase = FALSE;
@@ -139,8 +142,8 @@ UNIV_INTERN uint srv_sys_space_size_debug;
SRV_SHUTDOWN_CLEANUP and then to SRV_SHUTDOWN_LAST_PHASE, and so on */
UNIV_INTERN enum srv_shutdown_state srv_shutdown_state = SRV_SHUTDOWN_NONE;
-/** Files comprising the system tablespace */
-os_file_t files[1000];
+/** Files comprising the system tablespace. Also used by Mariabackup. */
+UNIV_INTERN pfs_os_file_t files[1000];
/** io_handler_thread parameters for thread identification */
static ulint n[SRV_MAX_N_IO_THREADS];
@@ -584,7 +587,7 @@ static MY_ATTRIBUTE((nonnull, warn_unused_result))
dberr_t
create_log_file(
/*============*/
- os_file_t* file, /*!< out: file handle */
+ pfs_os_file_t* file, /*!< out: file handle */
const char* name) /*!< in: log file name */
{
ibool ret;
@@ -802,7 +805,7 @@ static MY_ATTRIBUTE((nonnull, warn_unused_result))
dberr_t
open_log_file(
/*==========*/
- os_file_t* file, /*!< out: file handle */
+ pfs_os_file_t* file, /*!< out: file handle */
const char* name, /*!< in: log file name */
os_offset_t* size) /*!< out: file size */
{
@@ -919,7 +922,7 @@ open_or_create_data_files(
&& os_file_get_last_error(false)
!= OS_FILE_ALREADY_EXISTS
#ifdef UNIV_AIX
- /* AIX 5.1 after security patch ML7 may have
+ /* AIX 5.1 after security patch ML7 may have
errno set to 0 here, which causes our
function to return 100; work around that
AIX problem */
@@ -1221,7 +1224,7 @@ srv_undo_tablespace_create(
const char* name, /*!< in: tablespace name */
ulint size) /*!< in: tablespace size in pages */
{
- os_file_t fh;
+ pfs_os_file_t fh;
ibool ret;
dberr_t err = DB_SUCCESS;
@@ -1299,7 +1302,7 @@ srv_undo_tablespace_open(
const char* name, /*!< in: tablespace name */
ulint space) /*!< in: tablespace id */
{
- os_file_t fh;
+ pfs_os_file_t fh;
dberr_t err = DB_ERROR;
ibool ret;
ulint flags;
@@ -1404,13 +1407,23 @@ srv_undo_tablespaces_init(
for (i = 0; create_new_db && i < n_conf_tablespaces; ++i) {
char name[OS_FILE_MAX_PATH];
+ ulint space_id = i + 1;
+
+ DBUG_EXECUTE_IF("innodb_undo_upgrade",
+ space_id = i + 3;);
ut_snprintf(
name, sizeof(name),
"%s%cundo%03lu",
- srv_undo_dir, SRV_PATH_SEPARATOR, i + 1);
+ srv_undo_dir, SRV_PATH_SEPARATOR, space_id);
+
+ if (i == 0) {
+ srv_undo_space_id_start = space_id;
+ prev_space_id = srv_undo_space_id_start - 1;
+ }
+
+ undo_tablespace_ids[i] = space_id;
- /* Undo space ids start from 1. */
err = srv_undo_tablespace_create(
name, SRV_UNDO_TABLESPACE_SIZE_IN_PAGES);
@@ -1432,14 +1445,16 @@ srv_undo_tablespaces_init(
if (!create_new_db && !backup_mode) {
n_undo_tablespaces = trx_rseg_get_n_undo_tablespaces(
undo_tablespace_ids);
- } else {
- n_undo_tablespaces = n_conf_tablespaces;
- for (i = 1; i <= n_undo_tablespaces; ++i) {
- undo_tablespace_ids[i - 1] = i;
+ if (n_undo_tablespaces != 0) {
+ srv_undo_space_id_start = undo_tablespace_ids[0];
+ prev_space_id = srv_undo_space_id_start - 1;
}
- undo_tablespace_ids[i] = ULINT_UNDEFINED;
+ } else {
+ n_undo_tablespaces = n_conf_tablespaces;
+
+ undo_tablespace_ids[n_conf_tablespaces] = ULINT_UNDEFINED;
}
/* Open all the undo tablespaces that are currently in use. If we
@@ -1463,8 +1478,6 @@ srv_undo_tablespaces_init(
ut_a(undo_tablespace_ids[i] != 0);
ut_a(undo_tablespace_ids[i] != ULINT_UNDEFINED);
- /* Undo space ids start from 1. */
-
err = srv_undo_tablespace_open(name, undo_tablespace_ids[i]);
if (err != DB_SUCCESS) {
@@ -1499,11 +1512,23 @@ srv_undo_tablespaces_init(
break;
}
+ /** Note the first undo tablespace id in case of
+ no active undo tablespace. */
+ if (n_undo_tablespaces == 0) {
+ srv_undo_space_id_start = i;
+ }
+
++n_undo_tablespaces;
++*n_opened;
}
+ /** Explictly specify the srv_undo_space_id_start
+ as zero when there are no undo tablespaces. */
+ if (n_undo_tablespaces == 0) {
+ srv_undo_space_id_start = 0;
+ }
+
/* If the user says that there are fewer than what we find we
tolerate that discrepancy but not the inverse. Because there could
be unused undo tablespaces for future use. */
@@ -1548,10 +1573,11 @@ srv_undo_tablespaces_init(
mtr_start(&mtr);
/* The undo log tablespace */
- for (i = 1; i <= n_undo_tablespaces; ++i) {
+ for (i = 0; i < n_undo_tablespaces; ++i) {
fsp_header_init(
- i, SRV_UNDO_TABLESPACE_SIZE_IN_PAGES, &mtr);
+ undo_tablespace_ids[i],
+ SRV_UNDO_TABLESPACE_SIZE_IN_PAGES, &mtr);
}
mtr_commit(&mtr);
@@ -1665,6 +1691,10 @@ innobase_start_or_create_for_mysql(void)
/* This should be initialized early */
ut_init_timer();
+ if (srv_force_recovery == SRV_FORCE_NO_LOG_REDO) {
+ srv_read_only_mode = 1;
+ }
+
high_level_read_only = srv_read_only_mode
|| srv_force_recovery > SRV_FORCE_NO_TRX_UNDO;
diff --git a/storage/xtradb/trx/trx0purge.cc b/storage/xtradb/trx/trx0purge.cc
index 7d35bb12093..90f22e7ef82 100644
--- a/storage/xtradb/trx/trx0purge.cc
+++ b/storage/xtradb/trx/trx0purge.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1996, 2017, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, MariaDB Corporation. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
@@ -685,7 +685,8 @@ trx_purge_get_rseg_with_min_trx_id(
/* We assume in purge of externally stored fields that space id is
in the range of UNDO tablespace space ids */
- ut_a(purge_sys->rseg->space <= srv_undo_tablespaces_open);
+ ut_a(purge_sys->rseg->space == 0
+ || srv_is_undo_tablespace(purge_sys->rseg->space));
zip_size = purge_sys->rseg->zip_size;
diff --git a/storage/xtradb/trx/trx0roll.cc b/storage/xtradb/trx/trx0roll.cc
index d228743d300..335ef8859c4 100644
--- a/storage/xtradb/trx/trx0roll.cc
+++ b/storage/xtradb/trx/trx0roll.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1996, 2017, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2016, 2017, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
@@ -818,6 +818,7 @@ DECLARE_THREAD(trx_rollback_or_clean_all_recovered)(
/*!< in: a dummy parameter required by
os_thread_create */
{
+ my_thread_init();
ut_ad(!srv_read_only_mode);
#ifdef UNIV_PFS_THREAD
@@ -828,6 +829,7 @@ DECLARE_THREAD(trx_rollback_or_clean_all_recovered)(
trx_rollback_or_clean_is_active = false;
+ my_thread_end();
/* 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. */
diff --git a/storage/xtradb/trx/trx0sys.cc b/storage/xtradb/trx/trx0sys.cc
index ba45e67322c..4e1cc53fec9 100644
--- a/storage/xtradb/trx/trx0sys.cc
+++ b/storage/xtradb/trx/trx0sys.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2015, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1996, 2017, 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
@@ -1055,18 +1055,12 @@ trx_sys_create_rsegs(
ulint new_rsegs = n_rsegs - n_used;
for (i = 0; i < new_rsegs; ++i) {
- ulint space;
+ ulint space_id;
+ space_id = (n_spaces == 0) ? 0
+ : (srv_undo_space_id_start + i % n_spaces);
- /* Tablespace 0 is the system tablespace. All UNDO
- log tablespaces start from 1. */
-
- if (n_spaces > 0) {
- space = (i % n_spaces) + 1;
- } else {
- space = 0; /* System tablespace */
- }
-
- if (trx_rseg_create(space) != NULL) {
+ /* Tablespace 0 is the system tablespace. */
+ if (trx_rseg_create(space_id) != NULL) {
++n_used;
} else {
break;