Merge branch '10.2' into 10.3

This commit is contained in:
Oleksandr Byelkin 2019-12-04 17:46:28 +01:00
commit 008ee867a4
57 changed files with 1016 additions and 521 deletions

View File

@ -3211,7 +3211,7 @@ static int
com_go(String *buffer,char *line __attribute__((unused)))
{
char buff[200]; /* about 110 chars used so far */
char time_buff[53+3+1]; /* time max + space&parens + NUL */
char time_buff[53+3+1]; /* time max + space & parens + NUL */
MYSQL_RES *result;
ulonglong timer;
ulong warnings= 0;
@ -3231,7 +3231,7 @@ com_go(String *buffer,char *line __attribute__((unused)))
if (buffer->is_empty())
{
if (status.batch) // Ignore empty quries
if (status.batch) // Ignore empty queries.
return 0;
return put_info("No query specified\n",INFO_ERROR);
@ -3296,7 +3296,7 @@ com_go(String *buffer,char *line __attribute__((unused)))
else
time_buff[0]= '\0';
/* Every branch must truncate buff . */
/* Every branch must truncate buff. */
if (result)
{
if (!mysql_num_rows(result) && ! quick && !column_types_flag)

View File

@ -324,8 +324,36 @@ static void DbugVfprintf(FILE *stream, const char* format, va_list args);
*/
#include <my_pthread.h>
/*
** Protects writing to all file descriptors, init_settings.keywords
** pointer and it's pointee - a linked list with keywords.
*/
static pthread_mutex_t THR_LOCK_dbug;
static void LockMutex(CODE_STATE *cs)
{
if (!cs->locked)
pthread_mutex_lock(&THR_LOCK_dbug);
cs->locked++;
}
static void UnlockMutex(CODE_STATE *cs)
{
--cs->locked;
assert(cs->locked >= 0);
if (cs->locked == 0)
pthread_mutex_unlock(&THR_LOCK_dbug);
}
static void LockIfInitSettings(CODE_STATE *cs)
{
if (cs->stack == &init_settings)
LockMutex(cs);
}
static void UnlockIfInitSettings(CODE_STATE *cs)
{
if (cs->stack == &init_settings)
UnlockMutex(cs);
}
static CODE_STATE *code_state(void)
{
CODE_STATE *cs, **cs_ptr;
@ -453,16 +481,9 @@ static int DbugParse(CODE_STATE *cs, const char *control)
const char *end;
int rel, f_used=0;
struct settings *stack;
int org_cs_locked;
stack= cs->stack;
if (!(org_cs_locked= cs->locked))
{
pthread_mutex_lock(&THR_LOCK_dbug);
cs->locked= 1;
}
if (control[0] == '-' && control[1] == '#')
control+=2;
@ -476,7 +497,9 @@ static int DbugParse(CODE_STATE *cs, const char *control)
stack->sub_level= 0;
stack->out_file= sstderr;
stack->functions= NULL;
LockIfInitSettings(cs);
stack->keywords= NULL;
UnlockIfInitSettings(cs);
stack->processes= NULL;
}
else if (!stack->out_file)
@ -492,7 +515,9 @@ static int DbugParse(CODE_STATE *cs, const char *control)
{
/* never share with the global parent - it can change under your feet */
stack->functions= ListCopy(init_settings.functions);
LockIfInitSettings(cs);
stack->keywords= ListCopy(init_settings.keywords);
UnlockIfInitSettings(cs);
stack->processes= ListCopy(init_settings.processes);
}
else
@ -516,21 +541,31 @@ static int DbugParse(CODE_STATE *cs, const char *control)
case 'd':
if (sign < 0 && control == end)
{
LockIfInitSettings(cs);
if (!is_shared(stack, keywords))
FreeList(stack->keywords);
stack->keywords=NULL;
UnlockIfInitSettings(cs);
stack->flags &= ~DEBUG_ON;
break;
}
LockIfInitSettings(cs);
if (rel && is_shared(stack, keywords))
stack->keywords= ListCopy(stack->keywords);
UnlockIfInitSettings(cs);
if (sign < 0)
{
if (DEBUGGING)
{
LockIfInitSettings(cs);
stack->keywords= ListDel(stack->keywords, control, end);
UnlockIfInitSettings(cs);
}
break;
}
LockIfInitSettings(cs);
stack->keywords= ListAdd(stack->keywords, control, end);
UnlockIfInitSettings(cs);
stack->flags |= DEBUG_ON;
break;
case 'D':
@ -665,11 +700,6 @@ static int DbugParse(CODE_STATE *cs, const char *control)
control=end+1;
end= DbugStrTok(control);
}
if (!org_cs_locked)
{
cs->locked= 0;
pthread_mutex_unlock(&THR_LOCK_dbug);
}
return !rel || f_used;
}
@ -1002,7 +1032,9 @@ int _db_explain_ (CODE_STATE *cs, char *buf, size_t len)
get_code_state_if_not_set_or_return *buf=0;
LockIfInitSettings(cs);
op_list_to_buf('d', cs->stack->keywords, DEBUGGING);
UnlockIfInitSettings(cs);
op_int_to_buf ('D', cs->stack->delay, 0);
op_list_to_buf('f', cs->stack->functions, cs->stack->functions);
op_bool_to_buf('F', cs->stack->flags & FILE_ON);
@ -1097,7 +1129,6 @@ int _db_explain_init_(char *buf, size_t len)
void _db_enter_(const char *_func_, const char *_file_,
uint _line_, struct _db_stack_frame_ *_stack_frame_)
{
int save_errno, org_cs_locked;
CODE_STATE *cs;
if (!((cs=code_state())))
{
@ -1105,7 +1136,6 @@ void _db_enter_(const char *_func_, const char *_file_,
_stack_frame_->prev= 0;
return;
}
save_errno= errno;
_stack_frame_->line= -1;
_stack_frame_->func= cs->func;
@ -1126,20 +1156,14 @@ void _db_enter_(const char *_func_, const char *_file_,
cs->stack->flags &= ~SANITY_CHECK_ON;
if (TRACING)
{
if (!(org_cs_locked= cs->locked))
{
pthread_mutex_lock(&THR_LOCK_dbug);
cs->locked= 1;
}
int save_errno= errno;
LockMutex(cs);
DoPrefix(cs, _line_);
Indent(cs, cs->level);
(void) fprintf(cs->stack->out_file->file, ">%s\n", cs->func);
DbugFlush(cs); /* This does a unlock */
if (!org_cs_locked)
{
cs->locked= 0;
pthread_mutex_unlock(&THR_LOCK_dbug);
}
UnlockMutex(cs);
DbugFlush(cs);
errno=save_errno;
}
break;
case DISABLE_TRACE:
@ -1148,7 +1172,6 @@ void _db_enter_(const char *_func_, const char *_file_,
case DONT_TRACE:
break;
}
errno=save_errno;
}
/*
@ -1173,7 +1196,6 @@ void _db_enter_(const char *_func_, const char *_file_,
void _db_return_(struct _db_stack_frame_ *_stack_frame_)
{
int save_errno=errno;
uint _slevel_= _stack_frame_->level & ~TRACE_ON;
CODE_STATE *cs;
get_code_state_or_return;
@ -1190,25 +1212,18 @@ void _db_return_(struct _db_stack_frame_ *_stack_frame_)
if (DoTrace(cs) & DO_TRACE)
{
int org_cs_locked;
if ((cs->stack->flags & SANITY_CHECK_ON) && (*dbug_sanity)())
cs->stack->flags &= ~SANITY_CHECK_ON;
if (TRACING)
{
if (!(org_cs_locked= cs->locked))
{
pthread_mutex_lock(&THR_LOCK_dbug);
cs->locked= 1;
}
int save_errno=errno;
LockMutex(cs);
DoPrefix(cs, _stack_frame_->line);
Indent(cs, cs->level);
(void) fprintf(cs->stack->out_file->file, "<%s\n", cs->func);
UnlockMutex(cs);
DbugFlush(cs);
if (!org_cs_locked)
{
cs->locked= 0;
pthread_mutex_unlock(&THR_LOCK_dbug);
}
errno=save_errno;
}
}
/*
@ -1220,7 +1235,6 @@ void _db_return_(struct _db_stack_frame_ *_stack_frame_)
cs->file= _stack_frame_->file;
if (cs->framep != NULL)
cs->framep= cs->framep->prev;
errno=save_errno;
}
@ -1285,18 +1299,14 @@ void _db_doprnt_(const char *format,...)
{
va_list args;
CODE_STATE *cs;
int save_errno, org_cs_locked;
int save_errno;
get_code_state_or_return;
va_start(args,format);
if (!(org_cs_locked= cs->locked))
{
pthread_mutex_lock(&THR_LOCK_dbug);
cs->locked= 1;
}
save_errno=errno;
LockMutex(cs);
DoPrefix(cs, cs->u_line);
if (TRACING)
Indent(cs, cs->level + 1);
@ -1304,12 +1314,8 @@ void _db_doprnt_(const char *format,...)
(void) fprintf(cs->stack->out_file->file, "%s: ", cs->func);
(void) fprintf(cs->stack->out_file->file, "%s: ", cs->u_keyword);
DbugVfprintf(cs->stack->out_file->file, format, args);
UnlockMutex(cs);
DbugFlush(cs);
if (!org_cs_locked)
{
cs->locked= 0;
pthread_mutex_unlock(&THR_LOCK_dbug);
}
errno=save_errno;
va_end(args);
@ -1349,17 +1355,13 @@ static void DbugVfprintf(FILE *stream, const char* format, va_list args)
void _db_dump_(uint _line_, const char *keyword,
const unsigned char *memory, size_t length)
{
int pos, org_cs_locked;
int pos;
CODE_STATE *cs;
get_code_state_or_return;
if (!(org_cs_locked= cs->locked))
{
pthread_mutex_lock(&THR_LOCK_dbug);
cs->locked= 1;
}
if (_db_keyword_(cs, keyword, 0))
{
LockMutex(cs);
DoPrefix(cs, _line_);
if (TRACING)
{
@ -1387,13 +1389,9 @@ void _db_dump_(uint _line_, const char *keyword,
fputc(' ',cs->stack->out_file->file);
}
(void) fputc('\n',cs->stack->out_file->file);
UnlockMutex(cs);
DbugFlush(cs);
}
if (!org_cs_locked)
{
cs->locked= 0;
pthread_mutex_unlock(&THR_LOCK_dbug);
}
}
@ -1621,8 +1619,10 @@ static void PushState(CODE_STATE *cs)
static void FreeState(CODE_STATE *cs, int free_state)
{
struct settings *state= cs->stack;
LockIfInitSettings(cs);
if (!is_shared(state, keywords))
FreeList(state->keywords);
UnlockIfInitSettings(cs);
if (!is_shared(state, functions))
FreeList(state->functions);
if (!is_shared(state, processes))
@ -1701,8 +1701,6 @@ void _db_end_()
static int DoTrace(CODE_STATE *cs)
{
int res= DONT_TRACE;
if (!cs->locked)
pthread_mutex_lock(&THR_LOCK_dbug);
if ((cs->stack->maxdepth == 0 || cs->level <= cs->stack->maxdepth) &&
InList(cs->stack->processes, cs->process, 0) & (MATCHED|INCLUDE))
{
@ -1727,8 +1725,6 @@ static int DoTrace(CODE_STATE *cs)
break;
}
}
if (!cs->locked)
pthread_mutex_unlock(&THR_LOCK_dbug);
return res;
}
@ -1768,11 +1764,9 @@ BOOLEAN _db_keyword_(CODE_STATE *cs, const char *keyword, int strict)
if (!(DEBUGGING && (DoTrace(cs) & DO_TRACE)))
return 0;
if (!cs->locked)
pthread_mutex_lock(&THR_LOCK_dbug);
LockIfInitSettings(cs);
res= (InList(cs->stack->keywords, keyword, strict) & match);
if (!cs->locked)
pthread_mutex_unlock(&THR_LOCK_dbug);
UnlockIfInitSettings(cs);
return res != 0;
}
@ -1999,16 +1993,16 @@ static void DBUGCloseFile(CODE_STATE *cs, sFILE *new_value)
sFILE *fp;
if (!cs || !cs->stack || !cs->stack->out_file)
return;
if (!cs->locked)
pthread_mutex_lock(&THR_LOCK_dbug);
fp= cs->stack->out_file;
if (--fp->used == 0)
{
if (fclose(fp->file) == EOF)
{
LockMutex(cs);
(void) fprintf(stderr, ERR_CLOSE, cs->process);
perror("");
UnlockMutex(cs);
}
else
{
@ -2016,8 +2010,6 @@ static void DBUGCloseFile(CODE_STATE *cs, sFILE *new_value)
}
}
cs->stack->out_file= new_value;
if (!cs->locked)
pthread_mutex_unlock(&THR_LOCK_dbug);
}
@ -2200,9 +2192,7 @@ void _db_flush_()
get_code_state_or_return;
if (DEBUGGING)
{
pthread_mutex_lock(&THR_LOCK_dbug);
(void) fflush(cs->stack->out_file->file);
pthread_mutex_unlock(&THR_LOCK_dbug);
}
}
@ -2230,16 +2220,14 @@ void _db_lock_file_()
{
CODE_STATE *cs;
get_code_state_or_return;
pthread_mutex_lock(&THR_LOCK_dbug);
cs->locked=1;
LockMutex(cs);
}
void _db_unlock_file_()
{
CODE_STATE *cs;
get_code_state_or_return;
cs->locked=0;
pthread_mutex_unlock(&THR_LOCK_dbug);
UnlockMutex(cs);
}
const char* _db_get_func_(void)

@ -1 +1 @@
Subproject commit f035fc5f7fda5ac01d557073ef219c7e8d65fe10
Subproject commit c8833751cf48d0085d9d7a4285aafdc967a63a4d

View File

@ -1937,8 +1937,10 @@ Run stress test, providing options to mysql\-stress\-test\&.pl\&. Options are se
.\" suite option: mysql-test-run.pl
\fB\-\-suite[s]=\fR\fB\fIsuite_name...\fR\fR
.sp
Comma separated list of suite names to run. The default is: "main-,archive-,binlog-,csv-,federated-,funcs_1-,funcs_2-,handler-,heap-,innodb-,innodb_fts-,
innodb_zip-,maria-,multi_source-,optimizer_unfixed_bugs-,parts-,perfschema-,
Comma separated list of suite names to run. The default is:
"main-,archive-,binlog-,csv-,federated-,funcs_1-,funcs_2-,
handler-,heap-,innodb-,innodb_fts-,innodb_zip-,maria-,
multi_source-,optimizer_unfixed_bugs-,parts-,perfschema-,
plugins-,roles-,rpl-,sys_vars-,unit-,vcol-"\&.
.RE
.sp

View File

@ -1717,5 +1717,5 @@ userstat FALSE
verbose TRUE
wait-timeout 28800
To see what values a running MySQL server is using, type
To see what variables a running MySQL server is using, type
'mysqladmin variables' instead of 'mysqld --verbose --help'.

View File

@ -3206,6 +3206,36 @@ pk
3
DROP TABLE t1;
#
# MDEV-21044: Wrong result when using a smaller size for sort buffer
#
create table t1(a varchar(765),b int);
insert into t1 values ("a",1),("b",2),("c",3),("e",4);
insert into t1 values ("d",5),("f",6),("g",7),("h",8);
insert into t1 values ("k",11),("l",12),("i",9),("j",10);
insert into t1 values ("m",13),("n",14),("o",15),("p",16);
set @save_sort_buffer_size= @@sort_buffer_size;
set sort_buffer_size=1024;
select * from t1 order by b;
a b
a 1
b 2
c 3
e 4
d 5
f 6
g 7
h 8
i 9
j 10
k 11
l 12
m 13
n 14
o 15
p 16
set @@sort_buffer_size= @save_sort_buffer_size;
drop table t1;
#
# MDEV-13994: Bad join results with orderby_uses_equalities=on
#
CREATE TABLE books (

View File

@ -2145,6 +2145,22 @@ SELECT DISTINCT pk FROM t1 GROUP BY 'foo';
SELECT DISTINCT pk FROM t1;
DROP TABLE t1;
--echo #
--echo # MDEV-21044: Wrong result when using a smaller size for sort buffer
--echo #
create table t1(a varchar(765),b int);
insert into t1 values ("a",1),("b",2),("c",3),("e",4);
insert into t1 values ("d",5),("f",6),("g",7),("h",8);
insert into t1 values ("k",11),("l",12),("i",9),("j",10);
insert into t1 values ("m",13),("n",14),("o",15),("p",16);
set @save_sort_buffer_size= @@sort_buffer_size;
set sort_buffer_size=1024;
select * from t1 order by b;
set @@sort_buffer_size= @save_sort_buffer_size;
drop table t1;
--echo #
--echo # MDEV-13994: Bad join results with orderby_uses_equalities=on
--echo #

View File

@ -324,7 +324,8 @@ my $opt_valgrind_mysqld= 0;
my $opt_valgrind_mysqltest= 0;
my @valgrind_args;
my $opt_strace= 0;
my $opt_strace_client;
my $opt_stracer;
my $opt_client_strace = 0;
my @strace_args;
my $opt_valgrind_path;
my $valgrind_reports= 0;
@ -1329,9 +1330,10 @@ sub command_line_setup {
'debugger=s' => \$opt_debugger,
'boot-dbx' => \$opt_boot_dbx,
'client-debugger=s' => \$opt_client_debugger,
'strace' => \$opt_strace,
'strace-client' => \$opt_strace_client,
'strace-option=s' => \@strace_args,
'strace' => \$opt_strace,
'strace-option=s' => \@strace_args,
'client-strace' => \$opt_client_strace,
'stracer=s' => \$opt_stracer,
'max-save-core=i' => \$opt_max_save_core,
'max-save-datadir=i' => \$opt_max_save_datadir,
'max-test-fail=i' => \$opt_max_test_fail,
@ -1927,7 +1929,7 @@ sub command_line_setup {
join(" ", @valgrind_args), "\"");
}
if (@strace_args)
if (@strace_args || $opt_stracer)
{
$opt_strace=1;
}
@ -5861,14 +5863,6 @@ sub start_mysqltest ($) {
mtr_add_arg($args, "--non-blocking-api");
}
if ( $opt_strace_client )
{
$exe= $opt_strace_client || "strace";
mtr_add_arg($args, "-o");
mtr_add_arg($args, "%s/log/mysqltest.strace", $opt_vardir);
mtr_add_arg($args, "$exe_mysqltest");
}
mtr_add_arg($args, "--timer-file=%s/log/timer", $opt_vardir);
if ( $opt_compress )
@ -5934,6 +5928,17 @@ sub start_mysqltest ($) {
mtr_add_arg($args, "%s", $_) for @args_saved;
}
# ----------------------------------------------------------------------
# Prefix the strace options to the argument list.
# ----------------------------------------------------------------------
if ( $opt_client_strace )
{
my @args_saved = @$args;
mtr_init_args(\$args);
strace_arguments($args, \$exe, "mysqltest");
mtr_add_arg($args, "%s", $_) for @args_saved;
}
if ($opt_force > 1)
{
mtr_add_arg($args, "--continue-on-error");
@ -6258,16 +6263,17 @@ sub strace_arguments {
my $args= shift;
my $exe= shift;
my $mysqld_name= shift;
my $output= sprintf("%s/log/%s.strace", $path_vardir_trace, $mysqld_name);
mtr_add_arg($args, "-f");
mtr_add_arg($args, "-o%s/var/log/%s.strace", $glob_mysql_test_dir, $mysqld_name);
mtr_add_arg($args, "-o%s", $output);
# Add strace options, can be overridden by user
# Add strace options
mtr_add_arg($args, '%s', $_) for (@strace_args);
mtr_add_arg($args, $$exe);
$$exe= "strace";
$$exe= $opt_stracer || "strace";
if ($exe_libtool)
{
@ -6543,11 +6549,11 @@ Options for valgrind
Options for strace
strace Run the "mysqld" executables using strace. Default
options are -f -o var/log/'mysqld-name'.strace
strace-option=ARGS Option to give strace, replaces default option(s),
strace-client=[path] Create strace output for mysqltest client, optionally
specifying name and path to the trace program to use.
Example: $0 --strace-client=ktrace
options are -f -o 'vardir'/log/'mysqld-name'.strace.
client-strace Trace the "mysqltest".
strace-option=ARGS Option to give strace, appends to existing options.
stracer=<EXE> Specify name and path to the trace program to use.
Default is "strace". Example: $0 --stracer=ktrace.
Misc options
user=USER User for connecting to mysqld(default: $opt_user)

View File

@ -0,0 +1,28 @@
connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2;
connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3;
connection node_2;
START SLAVE;
connection node_1;
SHOW VARIABLES LIKE 'binlog_format';
Variable_name Value
binlog_format ROW
connection node_1;
CREATE TABLE source (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
CREATE TABLE target AS SELECT * FROM source;
connection node_2;
connection node_3;
connection node_1;
DROP TABLE target;
INSERT INTO source VALUES(1);
CREATE TABLE target AS SELECT * FROM source;
connection node_2;
connection node_3;
connection node_1;
DROP TABLE source;
DROP TABLE target;
connection node_3;
connection node_2;
STOP SLAVE;
RESET SLAVE ALL;
connection node_1;
RESET MASTER;

View File

@ -0,0 +1,29 @@
connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2;
connection node_2;
ALTER TABLE mysql.gtid_slave_pos engine = InnoDB;
START SLAVE;
connection node_1;
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=MyISAM;
INSERT INTO t1 VALUES(1);
SELECT LENGTH(@@global.gtid_binlog_state) > 1;
LENGTH(@@global.gtid_binlog_state) > 1
1
connection node_2;
gtid_binlog_state_equal
0
connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3;
SELECT COUNT(*) = 0 FROM t1;
COUNT(*) = 0
1
gtid_binlog_state_equal
0
#cleanup
connection node_1;
DROP TABLE t1;
reset master;
connection node_2;
STOP SLAVE;
RESET SLAVE ALL;
reset master;
connection node_3;
reset master;

View File

@ -1,10 +1,11 @@
connection node_1;
SELECT COUNT(DISTINCT uuid) = 2 FROM mtr_wsrep_notify.membership;
COUNT(DISTINCT uuid) = 2
SET SESSION wsrep_sync_wait=15;
SELECT COUNT(DISTINCT uuid) FROM mtr_wsrep_notify.membership;
COUNT(DISTINCT uuid)
2
SELECT MAX(size) FROM mtr_wsrep_notify.status;
MAX(size)
2
SELECT COUNT(DISTINCT idx) FROM mtr_wsrep_notify.status;
COUNT(DISTINCT idx)
1
SELECT MAX(size) = 2 FROM mtr_wsrep_notify.status;
MAX(size) = 2
1
SELECT COUNT(DISTINCT idx) = 2 FROM mtr_wsrep_notify.status;
COUNT(DISTINCT idx) = 2
0

View File

@ -0,0 +1,5 @@
!include ../galera_2nodes_as_slave.cnf
# make sure master server uses ROW format for replication
[mysqld]
binlog-format=row

View File

@ -0,0 +1,75 @@
#
# Test Galera as a slave to a MySQL master
#
# The galera/galera_2node_slave.cnf describes the setup of the nodes
# also, for this test, master server must have binlog_format=ROW
#
--source include/have_innodb.inc
# As node #1 is not a Galera node, we connect to node #2 in order to run include/galera_cluster.inc
--connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2
--source include/galera_cluster.inc
--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3
--connection node_2
--disable_query_log
--eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_USER='root', MASTER_PORT=$NODE_MYPORT_1;
--enable_query_log
START SLAVE;
# make sure master server has binlog_format=ROW
--connection node_1
SHOW VARIABLES LIKE 'binlog_format';
#
# test phase one, issue CTAS with empty source table
#
--connection node_1
CREATE TABLE source (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
CREATE TABLE target AS SELECT * FROM source;
--connection node_2
--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'target';
--source include/wait_condition.inc
--connection node_3
--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'target';
--source include/wait_condition.inc
#
# test phase two, issue CTAS with populated source table
#
--connection node_1
DROP TABLE target;
INSERT INTO source VALUES(1);
CREATE TABLE target AS SELECT * FROM source;
--connection node_2
--let $wait_condition = SELECT COUNT(*) = 1 FROM target;
--source include/wait_condition.inc
--connection node_3
--let $wait_condition = SELECT COUNT(*) = 1 FROM target;
--source include/wait_condition.inc
--connection node_1
DROP TABLE source;
DROP TABLE target;
--connection node_3
--let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'target';
--source include/wait_condition.inc
--connection node_2
STOP SLAVE;
RESET SLAVE ALL;
--connection node_1
RESET MASTER;

View File

@ -0,0 +1,6 @@
!include ../galera_2nodes_as_slave.cnf
[mysqld]
log-bin=mysqld-bin
log-slave-updates
binlog-format=ROW

View File

@ -0,0 +1,65 @@
#
# Test Galera as a slave to a MariaDB master using GTIDs
#
# suite/galera/galera_2nodes_as_slave.cnf describes the setup of the nodes
# suite/galera/t/galera_as_slave_gtid.cnf has the GTID options
#
# This test will replicate writes to MyISAM table and check that slave node is able
# to apply them.
# mysql.gtid_slave_pos table should be defined as innodb engine, original problem
# by writes to mysql.gtid_slave_pos, whereas the replicated transaction contained
# no innodb writes
#
--source include/have_innodb.inc
# As node #1 is not a Galera node, we connect to node #2 in order to run include/galera_cluster.inc
--connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2
--source include/galera_cluster.inc
--connection node_2
# make sure gtid_slave_pos is of innodb engine, mtr does not currently provide that
ALTER TABLE mysql.gtid_slave_pos engine = InnoDB;
--disable_query_log
--eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_USER='root', MASTER_PORT=$NODE_MYPORT_1;
--enable_query_log
START SLAVE;
--connection node_1
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=MyISAM;
INSERT INTO t1 VALUES(1);
SELECT LENGTH(@@global.gtid_binlog_state) > 1;
--let $gtid_binlog_state_node1 = `SELECT @@global.gtid_binlog_state;`
--connection node_2
--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1';
--source include/wait_condition.inc
--let $wait_condition = SELECT COUNT(*) = 1 FROM t1;
--source include/wait_condition.inc
--disable_query_log
--eval SELECT '$gtid_binlog_state_node1' = @@global.gtid_binlog_state AS gtid_binlog_state_equal;
--enable_query_log
--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3
SELECT COUNT(*) = 0 FROM t1;
--disable_query_log
--eval SELECT '$gtid_binlog_state_node1' = @@global.gtid_binlog_state AS gtid_binlog_state_equal;
--enable_query_log
--echo #cleanup
--connection node_1
DROP TABLE t1;
reset master;
--connection node_2
STOP SLAVE;
RESET SLAVE ALL;
reset master;
--connection node_3
reset master;

View File

@ -3,10 +3,10 @@
# notifications into a table.
#
--source include/have_innodb.inc
--source include/galera_cluster.inc
--connection node_1
SELECT COUNT(DISTINCT uuid) = 2 FROM mtr_wsrep_notify.membership;
SELECT MAX(size) = 2 FROM mtr_wsrep_notify.status;
SELECT COUNT(DISTINCT idx) = 2 FROM mtr_wsrep_notify.status;
SET SESSION wsrep_sync_wait=15;
SELECT COUNT(DISTINCT uuid) FROM mtr_wsrep_notify.membership;
SELECT MAX(size) FROM mtr_wsrep_notify.status;
SELECT COUNT(DISTINCT idx) FROM mtr_wsrep_notify.status;

View File

@ -243,7 +243,7 @@ cannot_find_file()
echo "If you compiled from source, you need to either run 'make install' to"
echo "copy the software into the correct location ready for operation."
echo "If you don't want to do a full install, you can use the --srcdir"
echo "option to only install the mysql database and privilege tables"
echo "option to only install the mysql database and privilege tables."
echo
echo "If you are using a binary release, you must either be at the top"
echo "level of the extracted archive, or pass the --basedir option"

View File

@ -315,6 +315,7 @@ SORT_INFO *filesort(THD *thd, TABLE *table, Filesort *filesort,
param.max_keys_per_buffer=((param.max_keys_per_buffer *
(param.rec_length + sizeof(char*))) /
param.rec_length - 1);
set_if_bigger(param.max_keys_per_buffer, 1);
maxbuffer--; // Offset from 0
if (merge_many_buff(&param,
(uchar*) sort->get_sort_keys(),

View File

@ -5211,6 +5211,9 @@ bool event_that_should_be_ignored(const char *buf);
bool event_checksum_test(uchar *buf, ulong event_len, enum_binlog_checksum_alg alg);
enum enum_binlog_checksum_alg get_checksum_alg(const char* buf, ulong len);
extern TYPELIB binlog_checksum_typelib;
#ifdef WITH_WSREP
enum Log_event_type wsrep_peak_event(rpl_group_info *rgi, ulonglong* event_size);
#endif /* WITH_WSREP */
/**
@} (end of group Replication)

View File

@ -8907,8 +8907,8 @@ static void usage(void)
"\nbecause execution stopped before plugins were initialized.");
}
puts("\nTo see what values a running MySQL server is using, type"
"\n'mysqladmin variables' instead of 'mysqld --verbose --help'.");
puts("\nTo see what variables a running MySQL server is using, type"
"\n'mysqladmin variables' instead of 'mysqld --verbose --help'.");
}
DBUG_VOID_RETURN;
}

View File

@ -481,6 +481,9 @@ handle_slave_background(void *arg __attribute__((unused)))
thd->store_globals();
thd->security_ctx->skip_grants();
thd->set_command(COM_DAEMON);
#ifdef WITH_WSREP
thd->variables.wsrep_on= 0;
#endif
thd_proc_info(thd, "Loading slave GTID position from table");
if (rpl_load_gtid_slave_state(thd))
@ -4656,6 +4659,9 @@ pthread_handler_t handle_slave_io(void *arg)
}
#ifdef WITH_WSREP
thd->variables.wsrep_on= 0;
#endif
if (DBUG_EVALUATE_IF("failed_slave_start", 1, 0)
|| repl_semisync_slave.slave_start(mi))
{
@ -7844,7 +7850,39 @@ err:
sql_print_error("Error reading relay log event: %s", errmsg);
DBUG_RETURN(0);
}
#ifdef WITH_WSREP
enum Log_event_type wsrep_peak_event(rpl_group_info *rgi, ulonglong* event_size)
{
enum Log_event_type ev_type;
mysql_mutex_lock(&rgi->rli->data_lock);
unsigned long long event_pos= rgi->event_relay_log_pos;
unsigned long long orig_future_pos= rgi->future_event_relay_log_pos;
unsigned long long future_pos= rgi->future_event_relay_log_pos;
/* scan the log to read next event and we skip
annotate events. */
do {
my_b_seek(rgi->rli->cur_log, future_pos);
rgi->rli->event_relay_log_pos= future_pos;
rgi->event_relay_log_pos= future_pos;
Log_event* ev= next_event(rgi, event_size);
ev_type= (ev) ? ev->get_type_code() : UNKNOWN_EVENT;
delete ev;
future_pos+= *event_size;
} while (ev_type == ANNOTATE_ROWS_EVENT);
/* scan the log back and re-set the positions to original values */
rgi->rli->event_relay_log_pos= event_pos;
rgi->event_relay_log_pos= event_pos;
my_b_seek(rgi->rli->cur_log, orig_future_pos);
mysql_mutex_unlock(&rgi->rli->data_lock);
return ev_type;
}
#endif /* WITH_WSREP */
/*
Rotate a relay log (this is used only by FLUSH LOGS; the automatic rotation
because of size is simpler because when we do it we already have all relevant

View File

@ -20586,7 +20586,7 @@ join_read_last(JOIN_TAB *tab)
{
TABLE *table=tab->table;
int error= 0;
DBUG_ENTER("join_read_first");
DBUG_ENTER("join_read_last");
DBUG_ASSERT(table->no_keyread ||
!table->covering_keys.is_set(tab->index) ||

View File

@ -488,11 +488,27 @@ wsrep_run_wsrep_commit(THD *thd, bool all)
if (WSREP_UNDEFINED_TRX_ID == thd->wsrep_ws_handle.trx_id)
{
WSREP_WARN("SQL statement was ineffective thd: %lld buf: %zu\n"
/*
Async replication slave may have applied some non-innodb workload,
and then has written replication "meta data" into gtid_slave_pos
innodb table. Writes to gtid_slave_pos must not be replicated,
but this activity has caused that innodb hton is registered for this
transaction, but no wsrep keys have been appended.
We enter in this code path, because IO cache has events for non-innodb
tables.
=> we should not treat it an error if trx is not introduced for provider
*/
if (thd->system_thread == SYSTEM_THREAD_SLAVE_SQL)
{
WSREP_DEBUG("skipping wsrep replication for async slave, error not raised");
DBUG_RETURN(WSREP_TRX_OK);
}
WSREP_WARN("SQL statement was ineffective thd: %llu buf: %zu\n"
"schema: %s \n"
"QUERY: %s\n"
" => Skipping replication",
(longlong) thd->thread_id, data_len,
(ulonglong) thd->thread_id, data_len,
thd->get_db(), thd->query());
rcode = WSREP_TRX_FAIL;
}

View File

@ -37,7 +37,6 @@
#include <cstdio>
#include <cstdlib>
#include "log_event.h"
#include <slave.h>
wsrep_t *wsrep = NULL;
/*
@ -1546,6 +1545,39 @@ static bool wsrep_can_run_in_toi(THD *thd, const char *db, const char *table,
{
return false;
}
/*
If mariadb master has replicated a CTAS, we should not replicate the create table
part separately as TOI, but to replicate both create table and following inserts
as one write set.
Howver, if CTAS creates empty table, we should replicate the create table alone
as TOI. We have to do relay log event lookup to see if row events follow the
create table event.
*/
if (thd->slave_thread && !(thd->rgi_slave->gtid_ev_flags2 & Gtid_log_event::FL_STANDALONE))
{
/* this is CTAS, either empty or populated table */
ulonglong event_size = 0;
enum Log_event_type ev_type= wsrep_peak_event(thd->rgi_slave, &event_size);
switch (ev_type)
{
case QUERY_EVENT:
/* CTAS with empty table, we replicate create table as TOI */
break;
case TABLE_MAP_EVENT:
WSREP_DEBUG("replicating CTAS of empty table as TOI");
// fall through
case WRITE_ROWS_EVENT:
/* CTAS with populated table, we replicate later at commit time */
WSREP_DEBUG("skipping create table of CTAS replication");
return false;
default:
WSREP_WARN("unexpected async replication event: %d", ev_type);
}
return true;
}
/* no next async replication event */
return true;
case SQLCOM_CREATE_VIEW:

View File

@ -318,6 +318,9 @@ ENDIF(CONNECT_WITH_MONGO)
OPTION(CONNECT_WITH_REST "Compile CONNECT storage engine with REST support" ON)
IF(CONNECT_WITH_REST)
MESSAGE(STATUS "=====> REST support is ON")
SET(CONNECT_SOURCES ${CONNECT_SOURCES} tabrest.cpp tabrest.h)
add_definitions(-DREST_SUPPORT)
FIND_PACKAGE(cpprestsdk QUIET)
IF (cpprestsdk_FOUND)
IF(UNIX)
@ -331,10 +334,10 @@ IF(CONNECT_WITH_REST)
# Comment it out if not needed depending on your cpprestsdk installation.
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MDd")
ENDIF(UNIX)
IF(REST_LIBRARY)
SET(CONNECT_SOURCES ${CONNECT_SOURCES} tabrest.cpp restget.cpp tabrest.h)
add_definitions(-DREST_SUPPORT)
ENDIF()
# IF(REST_LIBRARY) why this? how about Windows
SET(CONNECT_SOURCES ${CONNECT_SOURCES} restget.cpp)
add_definitions(-DREST_SOURCE)
# ENDIF()
ELSE(NOT cpprestsdk_FOUND)
# MESSAGE(STATUS "=====> cpprestsdk package not found")
ENDIF (cpprestsdk_FOUND)

View File

@ -566,7 +566,7 @@ int CntCloseTable(PGLOBAL g, PTDB tdbp, bool nox, bool abort)
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);
rc = ((PTDBDOS)tdbp)->GetTxfp()->UpdateSortedRows(g);
switch (rc) {
case RC_FX:
@ -593,7 +593,7 @@ int CntCloseTable(PGLOBAL g, PTDB tdbp, bool nox, bool abort)
if (!tdbp->IsRemote()) {
// Make all the eventual indexes
PTDBDOX tbxp = (PTDBDOX)tdbp;
PTDBDOS tbxp = (PTDBDOS)tdbp;
tbxp->ResetKindex(g, NULL);
tbxp->SetKey_Col(NULL);
rc = tbxp->ResetTableOpt(g, true, tbxp->GetDef()->Indexable() == 1);
@ -622,8 +622,8 @@ int CntCloseTable(PGLOBAL g, PTDB tdbp, bool nox, bool abort)
int CntIndexInit(PGLOBAL g, PTDB ptdb, int id, bool sorted)
{
PIXDEF xdp;
PTDBDOX tdbp;
DOXDEF *dfp;
PTDBDOS tdbp;
DOSDEF *dfp;
if (!ptdb)
return -1;
@ -633,9 +633,9 @@ int CntIndexInit(PGLOBAL g, PTDB ptdb, int id, bool sorted)
} else if (ptdb->GetDef()->Indexable() == 3) {
return 1;
} else
tdbp= (PTDBDOX)ptdb;
tdbp= (PTDBDOS)ptdb;
dfp= (DOXDEF*)tdbp->To_Def;
dfp= (DOSDEF*)tdbp->GetDef();
//if (!(k= colp->GetKey()))
// if (colp->GetOpt() >= 2) {
@ -645,16 +645,16 @@ int CntIndexInit(PGLOBAL g, PTDB ptdb, int id, bool sorted)
// This is a pseudo indexed sorted block optimized column
// return 0;
if (tdbp->To_Kindex)
if (((XXBASE*)tdbp->To_Kindex)->GetID() == id) {
tdbp->To_Kindex->Reset(); // Same index
return (tdbp->To_Kindex->IsMul()) ? 2 : 1;
if (tdbp->GetKindex())
if (((XXBASE*)tdbp->GetKindex())->GetID() == id) {
tdbp->GetKindex()->Reset(); // Same index
return (tdbp->GetKindex()->IsMul()) ? 2 : 1;
} else {
tdbp->To_Kindex->Close();
tdbp->To_Kindex= NULL;
tdbp->GetKindex()->Close();
tdbp->SetKindex(NULL);
} // endif colp
for (xdp= dfp->To_Indx; xdp; xdp= xdp->GetNext())
for (xdp= dfp->GetIndx(); xdp; xdp= xdp->GetNext())
if (xdp->GetID() == id)
break;
@ -676,7 +676,7 @@ int CntIndexInit(PGLOBAL g, PTDB ptdb, int id, bool sorted)
if (tdbp->InitialyzeIndex(g, xdp, sorted))
return 0;
return (tdbp->To_Kindex->IsMul()) ? 2 : 1;
return (tdbp->GetKindex()->IsMul()) ? 2 : 1;
} // end of CntIndexInit
#if defined(WORDS_BIGENDIAN)
@ -710,7 +710,7 @@ RCODE CntIndexRead(PGLOBAL g, PTDB ptdb, OPVAL op,
int n, x;
RCODE rc;
XXBASE *xbp;
PTDBDOX tdbp;
PTDBDOS tdbp;
if (!ptdb)
return RC_FX;
@ -736,12 +736,12 @@ RCODE CntIndexRead(PGLOBAL g, PTDB ptdb, OPVAL op,
goto rnd;
} else
tdbp= (PTDBDOX)ptdb;
tdbp= (PTDBDOS)ptdb;
// Set reference values and index operator
if (!tdbp->To_Link || !tdbp->To_Kindex) {
if (!tdbp->GetLink() || !tdbp->GetKindex()) {
// if (!tdbp->To_Xdp) {
sprintf(g->Message, "Index not initialized for table %s", tdbp->Name);
sprintf(g->Message, "Index not initialized for table %s", tdbp->GetName());
return RC_FX;
#if 0
} // endif !To_Xdp
@ -754,7 +754,7 @@ RCODE CntIndexRead(PGLOBAL g, PTDB ptdb, OPVAL op,
#endif // 0
} // endif !To_Kindex
xbp= (XXBASE*)tdbp->To_Kindex;
xbp= (XXBASE*)tdbp->GetKindex();
if (kr) {
char *kp= (char*)kr->key;
@ -764,13 +764,13 @@ RCODE CntIndexRead(PGLOBAL g, PTDB ptdb, OPVAL op,
PVAL valp;
PCOL colp;
for (n= 0; n < tdbp->Knum; n++) {
colp= (PCOL)tdbp->To_Key_Col[n];
for (n= 0; n < tdbp->GetKnum(); n++) {
colp= (PCOL)tdbp->Key(n);
if (colp->GetColUse(U_NULLS))
kp++; // Skip null byte
valp= tdbp->To_Link[n]->GetValue();
valp= tdbp->Link(n)->GetValue();
if (!valp->IsTypeNum()) {
if (colp->GetColUse(U_VAR)) {
@ -840,7 +840,7 @@ int CntIndexRange(PGLOBAL g, PTDB ptdb, const uchar* *key, uint *len,
bool b, rcb;
PVAL valp;
PCOL colp;
PTDBDOX tdbp;
PTDBDOS tdbp;
XXBASE *xbp;
if (!ptdb)
@ -865,35 +865,35 @@ int CntIndexRange(PGLOBAL g, PTDB ptdb, const uchar* *key, uint *len,
return k[1] - k[0] + 1;
} else
tdbp= (PTDBDOX)ptdb;
tdbp= (PTDBDOS)ptdb;
if (!tdbp->To_Kindex || !tdbp->To_Link) {
if (!tdbp->To_Xdp) {
sprintf(g->Message, "Index not initialized for table %s", tdbp->Name);
if (!tdbp->GetKindex() || !tdbp->GetLink()) {
if (!tdbp->GetXdp()) {
sprintf(g->Message, "Index not initialized for table %s", tdbp->GetName());
DBUG_PRINT("Range", ("%s", g->Message));
return -1;
} else // Dynamic index
return tdbp->To_Xdp->GetMaxSame(); // TODO a better estimate
return tdbp->GetXdp()->GetMaxSame(); // TODO a better estimate
} else
xbp= (XXBASE*)tdbp->To_Kindex;
xbp= (XXBASE*)tdbp->GetKindex();
for (b= false, i= 0; i < 2; i++) {
p= kp= key[i];
if (kp) {
for (n= 0; n < tdbp->Knum; n++) {
for (n= 0; n < tdbp->GetKnum(); n++) {
if (kmap[i] & (key_part_map)(1 << n)) {
if (b == true)
// Cannot do indexing with missing intermediate key
return -1;
colp= (PCOL)tdbp->To_Key_Col[n];
colp= (PCOL)tdbp->Key(n);
if (colp->GetColUse(U_NULLS))
p++; // Skip null byte ???
valp= tdbp->To_Link[n]->GetValue();
valp= tdbp->Link(n)->GetValue();
if (!valp->IsTypeNum()) {
if (colp->GetColUse(U_VAR)) {

View File

@ -46,6 +46,7 @@ int CntIndexRange(PGLOBAL g, PTDB ptdb, const uchar* *key, uint *len,
bool *incl, key_part_map *kmap);
PGLOBAL CntExit(PGLOBAL g);
#if 0
/***********************************************************************/
/* Definition of classes XKPDEF, DOXDEF, TDBDOX */
/* These classes purpose is chiefly to access protected items! */
@ -76,3 +77,4 @@ class XKPDEF: public KPARTDEF {
public:
XKPDEF(const char *name, int n) : KPARTDEF((PSZ)name, n) {}
}; // end of class XKPDEF
#endif // 0

View File

@ -48,7 +48,6 @@ class DllExport FILTER : public XOBJECT { /* Filter description block */
PVAL &Val(int i) {return Test[i].Value;}
bool &Conv(int i) {return Test[i].Conv;}
void SetNext(PFIL filp) {Next = filp;}
bool MakeSelector(PGLOBAL g, PSTRG s);
// Methods
virtual void Reset(void);

View File

@ -170,9 +170,9 @@
#define JSONMAX 10 // JSON Default max grp size
extern "C" {
char version[]= "Version 1.06.0010 June 01, 2019";
char version[]= "Version 1.07.0001 November 12, 2019";
#if defined(__WIN__)
char compver[]= "Version 1.06.0010 " __DATE__ " " __TIME__;
char compver[]= "Version 1.07.0001 " __DATE__ " " __TIME__;
char slash= '\\';
#else // !__WIN__
char slash= '/';
@ -1043,6 +1043,8 @@ TABTYPE ha_connect::GetRealType(PTOS pos)
case TAB_REST:
type = TAB_NIY;
break;
default:
break;
} // endswitch type
#endif // REST_SUPPORT
@ -2963,9 +2965,9 @@ PCFIL ha_connect::CheckCond(PGLOBAL g, PCFIL filp, const Item *cond)
case Item_func::GE_FUNC: vop= OP_GE; break;
case Item_func::GT_FUNC: vop= OP_GT; break;
case Item_func::LIKE_FUNC:
vop= OP_LIKE;
neg= ((Item_func_opt_neg *)condf)->negated;
break;
vop = OP_LIKE;
neg= ((Item_func_like*)condf)->negated;
break;
case Item_func::ISNOTNULL_FUNC:
neg= true;
// fall through
@ -3783,9 +3785,9 @@ int ha_connect::index_init(uint idx, bool sorted)
active_index= MAX_KEY;
rc= HA_ERR_INTERNAL_ERROR;
} else if (tdbp->GetKindex()) {
if (((PTDBDOX)tdbp)->To_Kindex->GetNum_K()) {
if (((PTDBDOS)tdbp)->GetKindex()->GetNum_K()) {
if (tdbp->GetFtype() != RECFM_NAF)
((PTDBDOX)tdbp)->GetTxfp()->ResetBuffer(g);
((PTDBDOS)tdbp)->GetTxfp()->ResetBuffer(g);
active_index= idx;
// } else { // Void table
@ -5630,6 +5632,8 @@ static int connect_assisted_discovery(handlerton *, THD* thd,
case TAB_CSV:
ttp = TAB_REST;
break;
default:
break;
} // endswitch type
#endif // REST_SUPPORT
} // endif ttp
@ -6039,7 +6043,7 @@ static int connect_assisted_discovery(handlerton *, THD* thd,
} // endif !nblin
for (i= 0; !rc && i < qrp->Nblin; i++) {
typ= len= prec= dec= 0;
typ= len= prec= dec= flg= 0;
tm= NOT_NULL_FLAG;
cnm= (char*)"noname";
dft= xtra= key= fmt= tn= NULL;
@ -6079,6 +6083,9 @@ static int connect_assisted_discovery(handlerton *, THD* thd,
if (crp->Kdata->GetIntValue(i))
tm= 0; // Nullable
break;
case FLD_FLAG:
flg = crp->Kdata->GetIntValue(i);
break;
case FLD_FORMAT:
fmt= (crp->Kdata) ? crp->Kdata->GetCharValue(i) : NULL;
@ -6210,7 +6217,7 @@ static int connect_assisted_discovery(handlerton *, THD* thd,
// Now add the field
if (add_field(&sql, cnm, typ, prec, dec, key, tm, rem, dft, xtra,
fmt, 0, dbf, v))
fmt, flg, dbf, v))
rc= HA_ERR_OUT_OF_MEM;
} // endfor i
@ -7358,14 +7365,14 @@ maria_declare_plugin(connect)
&connect_storage_engine,
"CONNECT",
"Olivier Bertrand",
"Management of External Data (SQL/NOSQL/MED), including many file formats",
"Management of External Data (SQL/NOSQL/MED), including Rest query results",
PLUGIN_LICENSE_GPL,
connect_init_func, /* Plugin Init */
connect_done_func, /* Plugin Deinit */
0x0106, /* version number (1.06) */
0x0107, /* version number (1.07) */
NULL, /* status variables */
connect_system_variables, /* system variables */
"1.06.0010", /* string version */
"1.07.0001", /* string version */
MariaDB_PLUGIN_MATURITY_STABLE /* maturity */
}
maria_declare_plugin_end;

View File

@ -194,7 +194,7 @@ static void PROFILE_Save( FILE *file, PROFILESECTION *section )
}
for (key = section->key; key; key = key->next)
if (key->name && key->name[0]) {
if (key->name[0]) {
fprintf(file, "%s", SVP(key->name));
if (key->value)

View File

@ -95,7 +95,7 @@
#endif // ZIP_SUPPORT
#if defined(REST_SUPPORT)
#include "tabrest.h"
#endif // Rest_SUPPORT
#endif // REST_SUPPORT
#include "mycat.h"
/***********************************************************************/
@ -104,8 +104,9 @@
#if defined(__WIN__)
extern "C" HINSTANCE s_hModule; // Saved module handle
#endif // !__WIN__
PQRYRES OEMColumns(PGLOBAL g, PTOS topt, char *tab, char *db, bool info);
#if defined(JAVA_SUPPORT) || defined(CMGO_SUPPORT)
bool MongoEnabled(void);
#endif // JAVA_SUPPORT || CMGO_SUPPORT
/***********************************************************************/
/* Get the plugin directory. */
@ -347,100 +348,6 @@ uint GetFuncID(const char *func)
return fnc;
} // end of GetFuncID
/***********************************************************************/
/* OEMColumn: Get table column info for an OEM table. */
/***********************************************************************/
PQRYRES OEMColumns(PGLOBAL g, PTOS topt, char *tab, char *db, bool info)
{
typedef PQRYRES (__stdcall *XCOLDEF) (PGLOBAL, void*, char*, char*, bool);
const char *module, *subtype;
char c, soname[_MAX_PATH], getname[40] = "Col";
#if defined(__WIN__)
HANDLE hdll; /* Handle to the external DLL */
#else // !__WIN__
void *hdll; /* Handle for the loaded shared library */
#endif // !__WIN__
XCOLDEF coldef = NULL;
PQRYRES qrp = NULL;
module = topt->module;
subtype = topt->subtype;
if (!module || !subtype)
return NULL;
/*********************************************************************/
/* Ensure that the .dll doesn't have a path. */
/* This is done to ensure that only approved dll from the system */
/* directories are used (to make this even remotely secure). */
/*********************************************************************/
if (check_valid_path(module, strlen(module))) {
strcpy(g->Message, "Module cannot contain a path");
return NULL;
} else
PlugSetPath(soname, module, GetPluginDir());
// The exported name is always in uppercase
for (int i = 0; ; i++) {
c = subtype[i];
getname[i + 3] = toupper(c);
if (!c) break;
} // endfor i
#if defined(__WIN__)
// Load the Dll implementing the table
if (!(hdll = LoadLibrary(soname))) {
char buf[256];
DWORD rc = GetLastError();
sprintf(g->Message, MSG(DLL_LOAD_ERROR), rc, soname);
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS, NULL, rc, 0,
(LPTSTR)buf, sizeof(buf), NULL);
strcat(strcat(g->Message, ": "), buf);
return NULL;
} // endif hDll
// Get the function returning an instance of the external DEF class
if (!(coldef = (XCOLDEF)GetProcAddress((HINSTANCE)hdll, getname))) {
sprintf(g->Message, MSG(PROCADD_ERROR), GetLastError(), getname);
FreeLibrary((HMODULE)hdll);
return NULL;
} // endif coldef
#else // !__WIN__
const char *error = NULL;
// Load the desired shared library
if (!(hdll = dlopen(soname, RTLD_LAZY))) {
error = dlerror();
sprintf(g->Message, MSG(SHARED_LIB_ERR), soname, SVP(error));
return NULL;
} // endif Hdll
// Get the function returning an instance of the external DEF class
if (!(coldef = (XCOLDEF)dlsym(hdll, getname))) {
error = dlerror();
sprintf(g->Message, MSG(GET_FUNC_ERR), getname, SVP(error));
dlclose(hdll);
return NULL;
} // endif coldef
#endif // !__WIN__
// Just in case the external Get function does not set error messages
sprintf(g->Message, "Error getting column info from %s", subtype);
// Get the table column definition
qrp = coldef(g, topt, tab, db, info);
#if defined(__WIN__)
FreeLibrary((HMODULE)hdll);
#else // !__WIN__
dlclose(hdll);
#endif // !__WIN__
return qrp;
} // end of OEMColumns
/* ------------------------- Class CATALOG --------------------------- */
/***********************************************************************/
@ -481,10 +388,10 @@ void MYCAT::Reset(void)
/* GetTableDesc: retrieve a table descriptor. */
/* Look for a table descriptor matching the name and type. */
/***********************************************************************/
PRELDEF MYCAT::GetTableDesc(PGLOBAL g, PTABLE tablep,
PTABDEF MYCAT::GetTableDesc(PGLOBAL g, PTABLE tablep,
LPCSTR type, PRELDEF *)
{
PRELDEF tdp= NULL;
PTABDEF tdp= NULL;
if (trace(1))
htrc("GetTableDesc: name=%s am=%s\n", tablep->GetName(), SVP(type));
@ -505,12 +412,12 @@ PRELDEF MYCAT::GetTableDesc(PGLOBAL g, PTABLE tablep,
/* MakeTableDesc: make a table/view description. */
/* Note: caller must check if name already exists before calling it. */
/***********************************************************************/
PRELDEF MYCAT::MakeTableDesc(PGLOBAL g, PTABLE tablep, LPCSTR am)
PTABDEF MYCAT::MakeTableDesc(PGLOBAL g, PTABLE tablep, LPCSTR am)
{
TABTYPE tc;
LPCSTR name= (PSZ)PlugDup(g, tablep->GetName());
LPCSTR schema= (PSZ)PlugDup(g, tablep->GetSchema());
PRELDEF tdp= NULL;
PTABDEF tdp= NULL;
if (trace(1))
htrc("MakeTableDesc: name=%s schema=%s am=%s\n",
@ -578,8 +485,8 @@ PRELDEF MYCAT::MakeTableDesc(PGLOBAL g, PTABLE tablep, LPCSTR am)
} // endswitch
// Do make the table/view definition
if (tdp && tdp->Define(g, this, name, schema, am))
tdp= NULL;
if (tdp && tdp->Define(g, this, name, schema, am))
tdp = NULL;
if (trace(1))
htrc("Table %s made\n", am);
@ -592,7 +499,7 @@ PRELDEF MYCAT::MakeTableDesc(PGLOBAL g, PTABLE tablep, LPCSTR am)
/***********************************************************************/
PTDB MYCAT::GetTable(PGLOBAL g, PTABLE tablep, MODE mode, LPCSTR type)
{
PRELDEF tdp;
PTABDEF tdp;
PTDB tdbp= NULL;
// LPCSTR name= tablep->GetName();

View File

@ -102,14 +102,14 @@ class MYCAT : public CATALOG {
// Methods
void Reset(void);
bool StoreIndex(PGLOBAL, PTABDEF) {return false;} // Temporary
PRELDEF GetTableDesc(PGLOBAL g, PTABLE tablep,
PTABDEF GetTableDesc(PGLOBAL g, PTABLE tablep,
LPCSTR type, PRELDEF *prp = NULL);
PTDB GetTable(PGLOBAL g, PTABLE tablep,
MODE mode = MODE_READ, LPCSTR type = NULL);
void ClearDB(PGLOBAL g);
protected:
PRELDEF MakeTableDesc(PGLOBAL g, PTABLE tablep, LPCSTR am);
PTABDEF MakeTableDesc(PGLOBAL g, PTABLE tablep, LPCSTR am);
// Members
ha_connect *Hc; // The Connect handler

View File

@ -472,7 +472,7 @@ int MYSQLC::Open(PGLOBAL g, const char *host, const char *db,
int pt, const char *csname)
{
const char *pipe = NULL;
uint cto = 10, nrt = 20;
//uint cto = 10, nrt = 20;
my_bool my_true= 1;
m_DB = mysql_init(NULL);
@ -485,11 +485,11 @@ int MYSQLC::Open(PGLOBAL g, const char *host, const char *db,
if (trace(1))
htrc("MYSQLC Open: m_DB=%.4X size=%d\n", m_DB, (int)sizeof(*m_DB));
// Removed to do like FEDERATED do
// Removed to do like FEDERATED does
//mysql_options(m_DB, MYSQL_READ_DEFAULT_GROUP, "client-mariadb");
mysql_options(m_DB, MYSQL_OPT_USE_REMOTE_CONNECTION, NULL);
mysql_options(m_DB, MYSQL_OPT_CONNECT_TIMEOUT, &cto);
mysql_options(m_DB, MYSQL_OPT_READ_TIMEOUT, &nrt);
//mysql_options(m_DB, MYSQL_OPT_USE_REMOTE_CONNECTION, NULL);
//mysql_options(m_DB, MYSQL_OPT_CONNECT_TIMEOUT, &cto);
//mysql_options(m_DB, MYSQL_OPT_READ_TIMEOUT, &nrt);
//mysql_options(m_DB, MYSQL_OPT_WRITE_TIMEOUT, ...);
#if defined(__WIN__)

View File

@ -149,16 +149,22 @@ enum AMT {TYPE_AM_ERROR = 0, /* Type not defined */
TYPE_AM_MGO = 194, /* 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 */
RECFM_VAR = 0, /* Varying length DOS files */
RECFM_FIX = 1, /* Fixed length DOS files */
RECFM_BIN = 2, /* Binary DOS files (also fixed) */
RECFM_VCT = 3, /* VCT formatted files */
RECFM_ODBC = 4, /* Table accessed via ODBC */
RECFM_JDBC = 5, /* Table accessed via JDBC */
RECFM_PLG = 6, /* Table accessed via PLGconn */
RECFM_DBF = 7}; /* DBase formatted file */
enum RECFM {RECFM_DFLT = 0, /* Default table type */
RECFM_NAF = 1, /* Not a file table */
RECFM_OEM = 2, /* OEM table */
RECFM_VAR = 3, /* Varying length DOS files */
RECFM_FIX = 4, /* Fixed length DOS files */
RECFM_BIN = 5, /* Binary DOS files (also fixed) */
RECFM_DBF = 6, /* DBase formatted file */
RECFM_CSV = 7, /* CSV file */
RECFM_FMT = 8, /* FMT formatted file */
RECFM_VCT = 9, /* VCT formatted files */
RECFM_XML = 10, /* XML formatted files */
RECFM_JASON = 11, /* JASON formatted files */
RECFM_DIR = 12, /* DIR table */
RECFM_ODBC = 13, /* Table accessed via ODBC */
RECFM_JDBC = 14, /* Table accessed via JDBC */
RECFM_PLG = 15}; /* Table accessed via PLGconn */
enum MISC {DB_TABNO = 1, /* DB routines in Utility Table */
MAX_MULT_KEY = 10, /* Max multiple key number */
@ -537,7 +543,8 @@ enum XFLD {FLD_NO = 0, /* Not a field definition item */
FLD_FORMAT = 16, /* Field format */
FLD_CAT = 17, /* Table catalog */
FLD_SCHEM = 18, /* Table schema */
FLD_TABNAME = 19}; /* Column Table name */
FLD_TABNAME = 19, /* Column Table name */
FLD_FLAG = 20}; /* Field flag (CONNECT specific) */
/***********************************************************************/
/* Result of last SQL noconv query. */

View File

@ -1,11 +1,11 @@
/************* RelDef CPP Program Source Code File (.CPP) **************/
/* PROGRAM NAME: RELDEF */
/* ------------- */
/* Version 1.6 */
/* Version 1.7 */
/* */
/* COPYRIGHT: */
/* ---------- */
/* (C) Copyright to the author Olivier BERTRAND 2004-2016 */
/* (C) Copyright to the author Olivier BERTRAND 2004-2019 */
/* */
/* WHAT THIS PROGRAM DOES: */
/* ----------------------- */
@ -61,6 +61,102 @@ extern handlerton *connect_hton;
/***********************************************************************/
USETEMP UseTemp(void);
char *GetPluginDir(void);
PQRYRES OEMColumns(PGLOBAL g, PTOS topt, char* tab, char* db, bool info);
/***********************************************************************/
/* OEMColumns: Get table column info for an OEM table. */
/***********************************************************************/
PQRYRES OEMColumns(PGLOBAL g, PTOS topt, char* tab, char* db, bool info)
{
typedef PQRYRES(__stdcall* XCOLDEF) (PGLOBAL, void*, char*, char*, bool);
const char* module, * subtype;
char c, soname[_MAX_PATH], getname[40] = "Col";
#if defined(__WIN__)
HANDLE hdll; /* Handle to the external DLL */
#else // !__WIN__
void* hdll; /* Handle for the loaded shared library */
#endif // !__WIN__
XCOLDEF coldef = NULL;
PQRYRES qrp = NULL;
module = topt->module;
subtype = topt->subtype;
if (!module || !subtype)
return NULL;
/*********************************************************************/
/* Ensure that the .dll doesn't have a path. */
/* This is done to ensure that only approved dll from the system */
/* directories are used (to make this even remotely secure). */
/*********************************************************************/
if (check_valid_path(module, strlen(module))) {
strcpy(g->Message, "Module cannot contain a path");
return NULL;
}
else
PlugSetPath(soname, module, GetPluginDir());
// The exported name is always in uppercase
for (int i = 0; ; i++) {
c = subtype[i];
getname[i + 3] = toupper(c);
if (!c) break;
} // endfor i
#if defined(__WIN__)
// Load the Dll implementing the table
if (!(hdll = LoadLibrary(soname))) {
char buf[256];
DWORD rc = GetLastError();
sprintf(g->Message, MSG(DLL_LOAD_ERROR), rc, soname);
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS, NULL, rc, 0,
(LPTSTR)buf, sizeof(buf), NULL);
strcat(strcat(g->Message, ": "), buf);
return NULL;
} // endif hDll
// Get the function returning an instance of the external DEF class
if (!(coldef = (XCOLDEF)GetProcAddress((HINSTANCE)hdll, getname))) {
sprintf(g->Message, MSG(PROCADD_ERROR), GetLastError(), getname);
FreeLibrary((HMODULE)hdll);
return NULL;
} // endif coldef
#else // !__WIN__
const char* error = NULL;
// Load the desired shared library
if (!(hdll = dlopen(soname, RTLD_LAZY))) {
error = dlerror();
sprintf(g->Message, MSG(SHARED_LIB_ERR), soname, SVP(error));
return NULL;
} // endif Hdll
// Get the function returning an instance of the external DEF class
if (!(coldef = (XCOLDEF)dlsym(hdll, getname))) {
error = dlerror();
sprintf(g->Message, MSG(GET_FUNC_ERR), getname, SVP(error));
dlclose(hdll);
return NULL;
} // endif coldef
#endif // !__WIN__
// Just in case the external Get function does not set error messages
sprintf(g->Message, "Error getting column info from %s", subtype);
// Get the table column definition
qrp = coldef(g, topt, tab, db, info);
#if defined(__WIN__)
FreeLibrary((HMODULE)hdll);
#else // !__WIN__
dlclose(hdll);
#endif // !__WIN__
return qrp;
} // end of OEMColumns
/* --------------------------- Class RELDEF -------------------------- */
@ -208,6 +304,7 @@ TABDEF::TABDEF(void)
{
Schema = NULL;
Desc = NULL;
Recfm = RECFM_DFLT;
Catfunc = FNC_NO;
Card = 0;
Elemt = 0;
@ -220,12 +317,41 @@ TABDEF::TABDEF(void)
csname = NULL;
} // end of TABDEF constructor
/***********************************************************************/
/* Return the table format. */
/***********************************************************************/
RECFM TABDEF::GetTableFormat(const char* type)
{
RECFM recfm = Recfm;
if (recfm == RECFM_DFLT) {
// Default format depends on the table type
TABTYPE tc = (Catfunc == FNC_NO) ? GetTypeID(type) : TAB_PRX;
switch (tc) {
case TAB_DOS: recfm = RECFM_VAR; break;
case TAB_CSV: recfm = RECFM_CSV; break;
case TAB_FMT: recfm = RECFM_FMT; break;
case TAB_FIX: recfm = RECFM_FIX; break;
case TAB_BIN: recfm = RECFM_BIN; break;
case TAB_VEC: recfm = RECFM_VCT; break;
case TAB_DBF: recfm = RECFM_DBF; break;
case TAB_XML: recfm = RECFM_XML; break;
case TAB_DIR: recfm = RECFM_DIR; break;
default: recfm = RECFM_NAF; break;
} // endswitch type
} // endif recfm
return recfm;
} // end of GetTableFormat
/***********************************************************************/
/* Define: initialize the table definition block from XDB file. */
/***********************************************************************/
bool TABDEF::Define(PGLOBAL g, PCATLG cat,
LPCSTR name, LPCSTR schema, LPCSTR am)
{
{
int poff = 0;
Hc = ((MYCAT*)cat)->GetHandler();
@ -243,13 +369,17 @@ bool TABDEF::Define(PGLOBAL g, PCATLG cat,
NULL;
csname = GetStringCatInfo(g, "Table_charset", NULL);
// Get The column definitions
if ((poff = GetColCatInfo(g)) < 0)
return true;
// Do the definition of AM specific fields
if (DefineAM(g, am, 0))
return true;
// Do the definition of AM specific fields
return DefineAM(g, am, poff);
} // end of Define
// Get The column definitions
if (stricmp(am, "OEM") && GetColCatInfo(g) < 0)
return true;
Hc->tshp = NULL; // TO BE CHECKED
return false;
} // end of Define
/***********************************************************************/
/* This function returns the database data path. */
@ -264,71 +394,71 @@ PCSZ TABDEF::GetPath(void)
/***********************************************************************/
int TABDEF::GetColCatInfo(PGLOBAL g)
{
char *type= GetStringCatInfo(g, "Type", "*");
char *type = GetStringCatInfo(g, "Type", "*");
char c, fty, eds;
int i, n, loff, poff, nof, nlg;
void *field= NULL;
TABTYPE tc;
PCOLDEF cdp, lcdp= NULL, tocols= NULL;
void *field = NULL;
RECFM trf;
PCOLDEF cdp, lcdp = NULL, tocols= NULL;
PCOLINFO pcf= (PCOLINFO)PlugSubAlloc(g, NULL, sizeof(COLINFO));
memset(pcf, 0, sizeof(COLINFO));
// Get a unique char identifier for type
tc= (Catfunc == FNC_NO) ? GetTypeID(type) : TAB_PRX;
// Get the table format
trf = GetTableFormat(type);
// 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= (trf == RECFM_DBF) ? 1 : (trf == RECFM_XML || trf == RECFM_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;
loff = (trf == RECFM_DBF || trf == RECFM_DIR) ? 1 : (trf == RECFM_XML) ? -1 : 0;
#endif // !__WIN__
while (true) {
// Default Offset depends on table type
switch (tc) {
case TAB_DOS:
case TAB_FIX:
case TAB_BIN:
case TAB_VEC:
case TAB_DBF:
// Default Offset depends on table format
switch (trf ) {
case RECFM_VAR:
case RECFM_FIX:
case RECFM_BIN:
case RECFM_VCT:
case RECFM_DBF:
poff= loff + nof; // Default next offset
nlg= MY_MAX(nlg, poff); // Default lrecl
break;
case TAB_CSV:
case TAB_FMT:
case RECFM_CSV:
case RECFM_FMT:
nlg+= nof;
case TAB_DIR:
case TAB_XML:
case RECFM_DIR:
case RECFM_XML:
poff= loff + (pcf->Flags & U_VIRTUAL ? 0 : 1);
break;
case TAB_INI:
case TAB_MAC:
case TAB_TBL:
case TAB_XCL:
case TAB_OCCUR:
case TAB_PRX:
case TAB_OEM:
//case RECFM_INI:
//case RECFM_MAC:
//case RECFM_TBL:
//case RECFM_XCL:
//case RECFM_OCCUR:
//case RECFM_PRX:
case RECFM_OEM:
poff = 0; // Offset represents an independant flag
break;
default: // VCT PLG ODBC JDBC MYSQL WMI...
default: // PLG ODBC JDBC MYSQL WMI...
poff = 0; // NA
break;
} // endswitch tc
} // endswitch trf
// do {
field= Hc->GetColumnOption(g, field, pcf);
// } while (field && (*pcf->Name =='*' /*|| pcf->Flags & U_VIRTUAL*/));
if (tc == TAB_DBF && pcf->Type == TYPE_DATE && !pcf->Datefmt) {
if (trf == RECFM_DBF && pcf->Type == TYPE_DATE && !pcf->Datefmt) {
// DBF date format defaults to 'YYYMMDD'
pcf->Datefmt= "YYYYMMDD";
pcf->Length= 8;
} // endif tc
} // endif trf
if (!field)
break;
@ -341,10 +471,10 @@ int TABDEF::GetColCatInfo(PGLOBAL g)
else
loff= cdp->GetOffset();
switch (tc) {
case TAB_VEC:
switch (trf ) {
case RECFM_VCT:
cdp->SetOffset(0); // Not to have shift
case TAB_BIN:
case RECFM_BIN:
// BIN/VEC are packed by default
if (nof) {
// Field width is the internal representation width
@ -395,7 +525,7 @@ int TABDEF::GetColCatInfo(PGLOBAL g)
default:
break;
} // endswitch tc
} // endswitch trf
if (lcdp)
lcdp->SetNext(cdp);
@ -413,21 +543,15 @@ int TABDEF::GetColCatInfo(PGLOBAL g)
if (GetDefType() == TYPE_AM_DOS) {
int ending, recln= 0;
// Was commented because sometimes ending is 0 even when
// not specified (for instance if quoted is specified)
// if ((ending= Hc->GetIntegerOption("Ending")) < 0) {
if ((ending= Hc->GetIntegerOption("Ending")) <= 0) {
ending= (tc == TAB_BIN || tc == TAB_VEC) ? 0 : CRLF;
Hc->SetIntegerOption("Ending", ending);
} // endif ending
ending = Hc->GetIntegerOption("Ending");
// Calculate the default record size
switch (tc) {
case TAB_FIX:
case TAB_BIN:
switch (trf ) {
case RECFM_FIX:
case RECFM_BIN:
recln= nlg + ending; // + length of line ending
break;
case TAB_VEC:
case RECFM_VCT:
recln= nlg;
// if ((k= (pak < 0) ? 8 : pak) > 1)
@ -436,18 +560,18 @@ int TABDEF::GetColCatInfo(PGLOBAL g)
// recln= ((recln + k - 1) / k) * k;
break;
case TAB_DOS:
case TAB_DBF:
case RECFM_VAR:
case RECFM_DBF:
recln= nlg;
break;
case TAB_CSV:
case TAB_FMT:
case RECFM_CSV:
case RECFM_FMT:
// The number of separators (assuming an extra one can exist)
// recln= poff * ((qotd) ? 3 : 1); to be investigated
recln= nlg + poff * 3; // To be safe
default:
break;
} // endswitch tc
} // endswitch trf
// lrecl must be at least recln to avoid buffer overflow
if (trace(1))
@ -461,7 +585,7 @@ int TABDEF::GetColCatInfo(PGLOBAL g)
if (trace(1))
htrc("Lrecl set to %d\n", recln);
} // endif Lrecl
} // endif TYPE
// Attach the column definition to the tabdef
SetCols(tocols);
@ -500,7 +624,8 @@ PTABDEF OEMDEF::GetXdef(PGLOBAL g)
return NULL;
} else
// PlugSetPath(soname, Module, GetPluginDir()); // Crashes on Fedora
strncat(strcpy(soname, GetPluginDir()), Module, _MAX_PATH);
strncat(strcpy(soname, GetPluginDir()), Module,
sizeof(soname) - strlen(soname) - 1);
#if defined(__WIN__)
// Is the DLL already loaded?
@ -596,10 +721,6 @@ PTABDEF OEMDEF::GetXdef(PGLOBAL g)
cat->Cbuf = (char*)PlugSubAlloc(g, NULL, cat->Cblen);
} // endif Cbuf
// Here "OEM" should be replace by a more useful value
if (xdefp->Define(g, cat, Name, Schema, "OEM"))
return NULL;
// Ok, return external block
return xdefp;
} // end of GetXdef
@ -622,7 +743,7 @@ bool OEMDEF::DeleteTableFile(PGLOBAL g)
/***********************************************************************/
bool OEMDEF::DefineAM(PGLOBAL g, LPCSTR, int)
{
Module = GetStringCatInfo(g, "Module", "");
Module = GetStringCatInfo(g, "Module", "");
Subtype = GetStringCatInfo(g, "Subtype", Module);
if (!*Module)
@ -632,7 +753,13 @@ bool OEMDEF::DefineAM(PGLOBAL g, LPCSTR, int)
+ strlen(Subtype) + 3);
sprintf(desc, "%s(%s)", Module, Subtype);
Desc = desc;
return false;
// If define block not here yet, get it now
if (!Pxdef && !(Pxdef = GetXdef(g)))
return true; // Error
// Here "OEM" should be replace by a more useful value
return Pxdef->Define(g, Cat, Name, Schema, Subtype);
} // end of DefineAM
/***********************************************************************/
@ -640,7 +767,6 @@ bool OEMDEF::DefineAM(PGLOBAL g, LPCSTR, int)
/***********************************************************************/
PTDB OEMDEF::GetTable(PGLOBAL g, MODE mode)
{
RECFM rfm;
PTDB tdbp = NULL;
// If define block not here yet, get it now
@ -653,18 +779,10 @@ PTDB OEMDEF::GetTable(PGLOBAL g, MODE mode)
/*********************************************************************/
if (!(tdbp = Pxdef->GetTable(g, mode)))
return NULL;
else
rfm = tdbp->GetFtype();
if (rfm == RECFM_NAF)
return tdbp;
else if (rfm == RECFM_OEM) {
if (Multiple)
tdbp = new(g) TDBMUL(tdbp); // No block optimization yet
return tdbp;
} // endif OEM
else if (Multiple && tdbp->GetFtype() == RECFM_OEM)
tdbp = new(g) TDBMUL(tdbp); // No block optimization yet
#if 0
/*********************************************************************/
/* The OEM table is based on a file type (currently DOS+ only) */
/*********************************************************************/
@ -723,7 +841,7 @@ PTDB OEMDEF::GetTable(PGLOBAL g, MODE mode)
if (Multiple)
tdbp = new(g) TDBMUL(tdbp);
#endif // 0
return tdbp;
} // end of GetTable

View File

@ -84,10 +84,12 @@ public:
void SetNext(PTABDEF tdfp) {Next = tdfp;}
int GetMultiple(void) {return Multiple;}
int GetPseudo(void) {return Pseudo;}
PCSZ GetPath(void);
RECFM GetRecfm(void) {return Recfm;}
PCSZ GetPath(void);
//PSZ GetPath(void)
// {return (Database) ? (PSZ)Database : Cat->GetDataPath();}
bool SepIndex(void) {return GetBoolCatInfo("SepIndex", false);}
RECFM GetTableFormat(const char* type);
bool SepIndex(void) {return GetBoolCatInfo("SepIndex", false);}
bool IsReadOnly(void) {return Read_Only;}
virtual AMT GetDefType(void) {return TYPE_AM_TAB;}
virtual PIXDEF GetIndx(void) {return NULL;}
@ -108,7 +110,8 @@ public:
// Members
PCSZ Schema; /* Table schema (for ODBC) */
PCSZ Desc; /* Table description */
uint Catfunc; /* Catalog function ID */
RECFM Recfm; /* File or table format */
uint Catfunc; /* Catalog function ID */
int Card; /* (max) number of rows in table */
int Elemt; /* Number of rows in blocks or rowset */
int Sort; /* Table already sorted ??? */

View File

@ -4,12 +4,6 @@
/***********************************************************************/
#include <cpprest/filestream.h>
#include <cpprest/http_client.h>
#if defined(MARIADB)
#include <my_global.h>
#else
#include "mini-global.h"
#define _OS_H_INCLUDED // Prevent os.h to be called
#endif
using namespace utility::conversions; // String conversions utilities
using namespace web; // Common features like URIs.
@ -17,24 +11,24 @@ using namespace web::http; // Common HTTP functionality
using namespace web::http::client; // HTTP client features
using namespace concurrency::streams; // Asynchronous streams
#include "global.h"
typedef const char* PCSZ;
/***********************************************************************/
/* Make a local copy of the requested file. */
/***********************************************************************/
int restGetFile(PGLOBAL g, PCSZ http, PCSZ uri, PCSZ fn)
int restGetFile(char *m, bool xt, PCSZ http, PCSZ uri, PCSZ fn)
{
int rc = 0;
bool xt = trace(515);
auto fileStream = std::make_shared<ostream>();
if (!http || !fn) {
strcpy(g->Message, "Missing http or filename");
return 2;
//strcpy(g->Message, "Missing http or filename");
strcpy(m, "Missing http or filename");
return 2;
} // endif
if (xt)
htrc("restGetFile: fn=%s\n", fn);
fprintf(stderr, "restGetFile: fn=%s\n", fn);
// Open stream to output file.
pplx::task<void> requestTask = fstream::open_ostream(to_string_t(fn))
@ -42,7 +36,7 @@ int restGetFile(PGLOBAL g, PCSZ http, PCSZ uri, PCSZ fn)
*fileStream= outFile;
if (xt)
htrc("Outfile isopen=%d\n", outFile.is_open());
fprintf(stderr, "Outfile isopen=%d\n", outFile.is_open());
// Create http_client to send the request.
http_client client(to_string_t(http));
@ -58,8 +52,8 @@ int restGetFile(PGLOBAL g, PCSZ http, PCSZ uri, PCSZ fn)
// Handle response headers arriving.
.then([=](http_response response) {
if (xt)
htrc("Received response status code:%u\n",
response.status_code());
fprintf(stderr, "Received response status code:%u\n",
response.status_code());
// Write response body into the file.
return response.body().read_to_end(fileStream->streambuf());
@ -68,27 +62,27 @@ int restGetFile(PGLOBAL g, PCSZ http, PCSZ uri, PCSZ fn)
// Close the file stream.
.then([=](size_t n) {
if (xt)
htrc("Return size=%u\n", n);
fprintf(stderr, "Return size=%zu\n", n);
return fileStream->close();
});
// Wait for all the outstanding I/O to complete and handle any exceptions
try {
requestTask.wait();
if (xt)
htrc("In Wait\n");
fprintf(stderr, "Waiting\n");
requestTask.wait();
} catch (const std::exception &e) {
if (xt)
htrc("Error exception: %s\n", e.what());
sprintf(g->Message, "Error exception: %s", e.what());
rc= 1;
fprintf(stderr, "Error exception: %s\n", e.what());
sprintf(m, "Error exception: %s", e.what());
rc= 1;
} // end try/catch
if (xt)
htrc("restget done: rc=%d\n", rc);
fprintf(stderr, "restget done: rc=%d\n", rc);
return rc;
} // end of restGetFile

View File

@ -53,25 +53,30 @@ bool CMGDISC::FindInDoc(PGLOBAL g, bson_iter_t *iter, const bson_t *doc,
{
if (!doc || bson_iter_init(iter, doc)) {
const char *key;
char colname[65];
char fmt[129];
bool newcol;
char colname[65];
char fmt[129];
bool newcol;
size_t n;
while (bson_iter_next(iter)) {
key = bson_iter_key(iter);
newcol = true;
if (pcn) {
strncpy(colname, pcn, 64);
colname[64] = 0;
strncat(strncat(colname, "_", 65), key, 65);
n = sizeof(colname) - 1;
strncpy(colname, pcn, n);
colname[n] = 0;
n -= strlen(colname);
strncat(strncat(colname, "_", n), key, n - 1);
} else
strcpy(colname, key);
if (pfmt) {
strncpy(fmt, pfmt, 128);
fmt[128] = 0;
strncat(strncat(fmt, ".", 129), key, 129);
n = sizeof(fmt) - 1;
strncpy(fmt, pfmt, n);
fmt[n] = 0;
n -= strlen(fmt);
strncat(strncat(fmt, ".", n), key, n - 1);
} else
strcpy(fmt, key);

View File

@ -45,7 +45,7 @@
#include "global.h"
#include "osutil.h"
#include "plgdbsem.h"
#include "catalog.h"
//#include "catalog.h"
#include "mycat.h"
#include "xindex.h"
#include "filamap.h"
@ -161,7 +161,12 @@ bool DOSDEF::DefineAM(PGLOBAL g, LPCSTR am, int)
//Last = GetIntCatInfo("Last", 0);
Ending = GetIntCatInfo("Ending", CRLF);
if (Recfm == RECFM_FIX || Recfm == RECFM_BIN) {
if (Ending <= 0) {
Ending = (Recfm == RECFM_BIN || Recfm == RECFM_VCT) ? 0 : CRLF;
SetIntCatInfo("Ending", Ending);
} // endif ending
if (Recfm == RECFM_FIX || Recfm == RECFM_BIN) {
Huge = GetBoolCatInfo("Huge", Cat->GetDefHuge());
Padded = GetBoolCatInfo("Padded", false);
Blksize = GetIntCatInfo("Blksize", 0);
@ -191,7 +196,8 @@ bool DOSDEF::GetOptFileName(PGLOBAL g, char *filename)
case RECFM_FIX: ftype = ".fop"; break;
case RECFM_BIN: ftype = ".bop"; break;
case RECFM_VCT: ftype = ".vop"; break;
case RECFM_DBF: ftype = ".dbp"; break;
case RECFM_CSV: ftype = ".cop"; break;
case RECFM_DBF: ftype = ".dbp"; break;
default:
sprintf(g->Message, MSG(INVALID_FTYPE), Recfm);
return true;
@ -261,7 +267,8 @@ bool DOSDEF::DeleteIndexFile(PGLOBAL g, PIXDEF pxdf)
case RECFM_FIX: ftype = ".fnx"; break;
case RECFM_BIN: ftype = ".bnx"; break;
case RECFM_VCT: ftype = ".vnx"; break;
case RECFM_DBF: ftype = ".dbx"; break;
case RECFM_CSV: ftype = ".cnx"; break;
case RECFM_DBF: ftype = ".dbx"; break;
default:
sprintf(g->Message, MSG(BAD_RECFM_VAL), Recfm);
return true;
@ -2257,7 +2264,7 @@ int TDBDOS::ReadDB(PGLOBAL g)
/***********************************************************************/
bool TDBDOS::PrepareWriting(PGLOBAL)
{
if (!Ftype && (Mode == MODE_INSERT || Txfp->GetUseTemp())) {
if (Ftype == RECFM_VAR && (Mode == MODE_INSERT || Txfp->GetUseTemp())) {
char *p;
/*******************************************************************/
@ -2542,7 +2549,8 @@ void DOSCOL::ReadColumn(PGLOBAL g)
/*********************************************************************/
/* For a variable length file, check if the field exists. */
/*********************************************************************/
if (tdbp->Ftype == RECFM_VAR && strlen(tdbp->To_Line) < (unsigned)Deplac)
if ((tdbp->Ftype == RECFM_VAR || tdbp->Ftype == RECFM_CSV)
&& strlen(tdbp->To_Line) < (unsigned)Deplac)
field = 0;
else if (Dsp)
for(i = 0; i < field; i++)
@ -2552,7 +2560,8 @@ void DOSCOL::ReadColumn(PGLOBAL g)
switch (tdbp->Ftype) {
case RECFM_VAR:
case RECFM_FIX: // Fixed length text file
case RECFM_DBF: // Fixed length DBase file
case RECFM_CSV: // Variable length CSV or FMT file
case RECFM_DBF: // Fixed length DBase file
if (Nod) switch (Buf_Type) {
case TYPE_INT:
case TYPE_SHORT:

View File

@ -80,7 +80,6 @@ class DllExport DOSDEF : public TABDEF { /* Logical table description */
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 */
bool Zipped; /* true for zipped table file */
bool Mulentries; /* true for multiple entries */

View File

@ -84,7 +84,7 @@ PTDB TDBFIX::Clone(PTABS t)
tp = new(g) TDBFIX(g, this);
if (Ftype < 2) {
if (Ftype == RECFM_VAR || Ftype == RECFM_FIX) {
// File is text
PDOSCOL cp1, cp2;

View File

@ -1,11 +1,11 @@
/************* TabFmt C++ Program Source Code File (.CPP) **************/
/* PROGRAM NAME: TABFMT */
/* ------------- */
/* Version 3.9.2 */
/* Version 3.9.3 */
/* */
/* COPYRIGHT: */
/* ---------- */
/* (C) Copyright to the author Olivier BERTRAND 2001 - 2017 */
/* (C) Copyright to the author Olivier BERTRAND 2001 - 2019 */
/* */
/* WHAT THIS PROGRAM DOES: */
/* ----------------------- */
@ -477,6 +477,7 @@ bool CSVDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
if (DOSDEF::DefineAM(g, "CSV", poff))
return true;
Recfm = RECFM_CSV;
GetCharCatInfo("Separator", ",", buf, sizeof(buf));
Sep = (strlen(buf) == 2 && buf[0] == '\\' && buf[1] == 't') ? '\t' : *buf;
Quoted = GetIntCatInfo("Quoted", -1);

View File

@ -394,10 +394,11 @@ err:
bool JSONDISC::Find(PGLOBAL g, PJVAL jvp, PCSZ key, int j)
{
char *p, *pc = colname + strlen(colname);
int ars;
PJOB job;
PJAR jar;
char *p, *pc = colname + strlen(colname);
int ars;
size_t n;
PJOB job;
PJAR jar;
if ((valp = jvp ? jvp->GetValue() : NULL)) {
jcol.Type = valp->GetType();
@ -423,8 +424,10 @@ bool JSONDISC::Find(PGLOBAL g, PJVAL jvp, PCSZ key, int j)
PCSZ k = jrp->GetKey();
if (*k != '$') {
strncat(strncat(fmt, sep, 128), k, 128);
strncat(strncat(colname, "_", 64), k, 64);
n = sizeof(fmt) - strlen(fmt) -1;
strncat(strncat(fmt, sep, n), k, n - strlen(sep));
n = sizeof(colname) - strlen(colname) - 1;
strncat(strncat(colname, "_", n), k, n - 1);
} // endif Key
if (Find(g, jrp->GetVal(), k, j + 1))
@ -443,19 +446,26 @@ bool JSONDISC::Find(PGLOBAL g, PJVAL jvp, PCSZ key, int j)
ars = MY_MIN(jar->GetSize(false), 1);
for (int k = 0; k < ars; k++) {
if (!tdp->Xcol || stricmp(tdp->Xcol, key)) {
n = sizeof(fmt) - (strlen(fmt) + 1);
if (!tdp->Xcol || stricmp(tdp->Xcol, key)) {
sprintf(buf, "%d", k);
if (tdp->Uri)
strncat(strncat(fmt, sep, 128), buf, 128);
else
strncat(strncat(strncat(fmt, "[", 128), buf, 128), "]", 128);
if (tdp->Uri) {
strncat(strncat(fmt, sep, n), buf, n - strlen(sep));
} else {
strncat(strncat(fmt, "[", n), buf, n - 1);
strncat(fmt, "]", n - (strlen(buf) + 1));
} // endif uri
if (all)
strncat(strncat(colname, "_", 64), buf, 64);
if (all) {
n = sizeof(colname) - (strlen(colname) + 1);
strncat(strncat(colname, "_", n), buf, n - 1);
} // endif all
} else
strncat(fmt, (tdp->Uri ? sep : "[*]"), 128);
} else {
strncat(fmt, (tdp->Uri ? sep : "[*]"), n);
}
if (Find(g, jar->GetValue(k), "", j))
return true;

View File

@ -342,11 +342,13 @@ bool MYSQLDEF::DefineAM(PGLOBAL g, LPCSTR am, int)
Delayed = !!GetIntCatInfo("Delayed", 0);
} else {
// MYSQL access from a PROXY table
Tabschema = GetStringCatInfo(g, "Database", Tabschema ? Tabschema : PlugDup(g, "*"));
TABLE_SHARE* s;
Tabschema = GetStringCatInfo(g, "Database", Tabschema ? Tabschema : PlugDup(g, "*"));
Isview = GetBoolCatInfo("View", false);
// We must get other connection parms from the calling table
Remove_tshp(Cat);
s = Remove_tshp(Cat);
url = GetStringCatInfo(g, "Connect", NULL);
if (!url || !*url) {
@ -365,6 +367,9 @@ bool MYSQLDEF::DefineAM(PGLOBAL g, LPCSTR am, int)
} // endif url
Tabname = Name;
// Needed for column description
Restore_tshp(Cat, s);
} // endif am
if ((Srcdef = GetStringCatInfo(g, "Srcdef", NULL))) {

View File

@ -1,5 +1,5 @@
/*************** Rest C++ Program Source Code File (.CPP) **************/
/* PROGRAM NAME: Rest Version 1.5 */
/* PROGRAM NAME: Rest Version 1.6 */
/* (C) Copyright to the author Olivier BERTRAND 2018 - 2019 */
/* This program is the REST Web API support for MariaDB. */
/* When compiled without MARIADB defined, it is the EOM module code. */
@ -36,17 +36,7 @@
#include "tabfmt.h"
#include "tabrest.h"
/***********************************************************************/
/* Get the file from the Web. */
/***********************************************************************/
int restGetFile(PGLOBAL g, PCSZ http, PCSZ uri, PCSZ fn);
#if defined(__WIN__)
static PCSZ slash = "\\";
#else // !__WIN__
static PCSZ slash = "/";
#define stricmp strcasecmp
#endif // !__WIN__
static XGETREST getRestFnc = NULL;
#if !defined(MARIADB)
/***********************************************************************/
@ -75,6 +65,74 @@ PTABDEF __stdcall GetREST(PGLOBAL g, void *memp)
} // end of GetREST
#endif // !MARIADB
/***********************************************************************/
/* GetREST: get the external TABDEF from OEM module. */
/***********************************************************************/
XGETREST GetRestFunction(PGLOBAL g)
{
if (getRestFnc)
return getRestFnc;
#if !defined(REST_SOURCE)
if (trace(515))
htrc("Looking for GetRest library\n");
#if defined(__WIN__)
HANDLE Hdll;
const char* soname = "GetRest.dll"; // Module name
if (!(Hdll = LoadLibrary(soname))) {
char buf[256];
DWORD rc = GetLastError();
sprintf(g->Message, MSG(DLL_LOAD_ERROR), rc, soname);
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS, NULL, rc, 0,
(LPTSTR)buf, sizeof(buf), NULL);
strcat(strcat(g->Message, ": "), buf);
return NULL;
} // endif Hdll
// Get the function returning an instance of the external DEF class
if (!(getRestFnc = (XGETREST)GetProcAddress((HINSTANCE)Hdll, "restGetFile"))) {
char buf[256];
DWORD rc = GetLastError();
sprintf(g->Message, MSG(PROCADD_ERROR), rc, "restGetFile");
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS, NULL, rc, 0,
(LPTSTR)buf, sizeof(buf), NULL);
strcat(strcat(g->Message, ": "), buf);
FreeLibrary((HMODULE)Hdll);
return NULL;
} // endif getRestFnc
#else // !__WIN__
void* Hso;
const char* error = NULL;
const char* soname = "GetRest.so"; // Module name
// Load the desired shared library
if (!(Hso = dlopen(soname, RTLD_LAZY))) {
error = dlerror();
sprintf(g->Message, MSG(SHARED_LIB_ERR), soname, SVP(error));
return NULL;
} // endif Hdll
// Get the function returning an instance of the external DEF class
if (!(getRestFnc = (XGETREST)dlsym(Hso, "restGetFile"))) {
error = dlerror();
sprintf(g->Message, MSG(GET_FUNC_ERR), "restGetFile", SVP(error));
dlclose(Hso);
return NULL;
} // endif getdef
#endif // !__WIN__
#else
getRestFnc = restGetFile;
#endif
return getRestFnc;
} // end of GetRestFunction
/***********************************************************************/
/* Return the columns definition to MariaDB. */
/***********************************************************************/
@ -87,6 +145,10 @@ PQRYRES __stdcall ColREST(PGLOBAL g, PTOS tp, char *tab, char *db, bool info)
PQRYRES qrp= NULL;
char filename[_MAX_PATH + 1]; // MAX PATH ???
PCSZ http, uri, fn, ftype;
XGETREST grf = GetRestFunction(g);
if (!grf)
return NULL;
http = GetStringTableOption(g, tp, "Http", NULL);
uri = GetStringTableOption(g, tp, "Uri", NULL);
@ -100,11 +162,11 @@ PQRYRES __stdcall ColREST(PGLOBAL g, PTOS tp, char *tab, char *db, bool info)
// We used the file name relative to recorded datapath
strcat(strcat(strcat(strcpy(filename, "."), slash), db), slash);
strncat(filename, fn, _MAX_PATH);
strncat(filename, fn, _MAX_PATH - strlen(filename));
// Retrieve the file from the web and copy it locally
if (http && restGetFile(g, http, uri, filename)) {
// sprintf(g->Message, "Failed to get file at %s", http);
if (http && grf(g->Message, trace(515), http, uri, filename)) {
// sprintf(g->Message, "Failed to get file at %s", http);
} else if (!stricmp(ftype, "XML"))
qrp = XMLColumns(g, db, tab, tp, info);
else if (!stricmp(ftype, "JSON"))
@ -124,9 +186,14 @@ PQRYRES __stdcall ColREST(PGLOBAL g, PTOS tp, char *tab, char *db, bool info)
/***********************************************************************/
bool RESTDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
{
char filename[_MAX_PATH + 1];
char filename[_MAX_PATH + 1];
int rc = 0, n;
LPCSTR ftype;
bool xt = trace(515);
LPCSTR ftype;
XGETREST grf = GetRestFunction(g);
if (!grf)
return true;
#if defined(MARIADB)
ftype = GetStringCatInfo(g, "Type", "JSON");
@ -135,7 +202,7 @@ bool RESTDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
ftype = GetStringCatInfo(g, "Ftype", "JSON");
#endif // !MARIADB
if (trace(515))
if (xt)
htrc("ftype = %s am = %s\n", ftype, SVP(am));
n = (!stricmp(ftype, "JSON")) ? 1
@ -154,12 +221,13 @@ bool RESTDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
// We used the file name relative to recorded datapath
//PlugSetPath(filename, Fn, GetPath());
strncat(strcpy(filename, GetPath()), Fn, _MAX_PATH);
strcpy(filename, GetPath());
strncat(filename, Fn, _MAX_PATH - strlen(filename));
// Retrieve the file from the web and copy it locally
rc = restGetFile(g, Http, Uri, filename);
rc = grf(g->Message, xt, Http, Uri, filename);
if (trace(515))
if (xt)
htrc("Return from restGetFile: rc=%d\n", rc);
if (rc)
@ -175,7 +243,7 @@ bool RESTDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
if (Tdp && Tdp->Define(g, Cat, Name, Schema, "REST"))
Tdp = NULL; // Error occured
if (trace(515))
if (xt)
htrc("Tdp defined\n", rc);
// Return true in case of error

View File

@ -5,6 +5,25 @@
/***********************************************************************/
#pragma once
#if defined(__WIN__)
static PCSZ slash = "\\";
#else // !__WIN__
static PCSZ slash = "/";
#define stricmp strcasecmp
#endif // !__WIN__
typedef int(__stdcall* XGETREST) (char*, bool, PCSZ, PCSZ, PCSZ);
/***********************************************************************/
/* Functions used by REST. */
/***********************************************************************/
XGETREST GetRestFunction(PGLOBAL g);
int restGetFile(char* m, bool x, PCSZ http, PCSZ uri, PCSZ fn);
#if defined(MARIADB)
PQRYRES RESTColumns(PGLOBAL g, PTOS tp, char* tab, char* db, bool info);
#endif // !MARIADB
/***********************************************************************/
/* Restest table. */
/***********************************************************************/

View File

@ -59,11 +59,23 @@ int GetConvSize(void);
/* Used by MYSQL tables to get MySQL parameters from the calling proxy */
/* table (PROXY, TBL, XCL, or OCCUR) when used by one of these. */
/************************************************************************/
void Remove_tshp(PCATLG cat)
TABLE_SHARE *Remove_tshp(PCATLG cat)
{
((MYCAT*)cat)->GetHandler()->tshp = NULL;
TABLE_SHARE *s = ((MYCAT*)cat)->GetHandler()->tshp;
((MYCAT*)cat)->GetHandler()->tshp = NULL;
return s;
} // end of Remove_thsp
/************************************************************************/
/* Used by MYSQL tables to get MySQL parameters from the calling proxy */
/* table (PROXY, TBL, XCL, or OCCUR) when used by one of these. */
/************************************************************************/
void Restore_tshp(PCATLG cat, TABLE_SHARE *s)
{
((MYCAT*)cat)->GetHandler()->tshp = s;
} // end of Restore_thsp
/************************************************************************/
/* GetTableShare: allocates and open a table share. */
/************************************************************************/

View File

@ -18,7 +18,8 @@ TABLE_SHARE *GetTableShare(PGLOBAL g, THD *thd, const char *db,
PQRYRES TabColumns(PGLOBAL g, THD *thd, const char *db,
const char *name, bool& info);
void Remove_tshp(PCATLG cat);
TABLE_SHARE *Remove_tshp(PCATLG cat);
void Restore_tshp(PCATLG cat, TABLE_SHARE *s);
/* -------------------------- PROXY classes -------------------------- */

View File

@ -115,11 +115,14 @@ bool VCTDEF::DefineAM(PGLOBAL g, LPCSTR, int poff)
Recfm = RECFM_VCT;
// poff is no more in use; This will have to be revisited
#if 0
// For packed files the logical record length is calculated in poff
if (poff != Lrecl) {
Lrecl = poff;
SetIntCatInfo("Lrecl", poff);
} // endif poff
#endif // 0
Padded = false;
Blksize = 0;

View File

@ -240,7 +240,9 @@ PQRYRES XMLColumns(PGLOBAL g, char *db, char *tab, PTOS topt, bool info)
more:
if (vp->atp) {
strncpy(colname, vp->atp->GetName(g), sizeof(colname));
size_t z = sizeof(colname) - 1;
strncpy(colname, vp->atp->GetName(g), z);
colname[z] = 0;
strncat(xcol->Name, colname, XLEN(xcol->Name));
switch (vp->atp->GetText(g, buf, sizeof(buf))) {

View File

@ -659,7 +659,7 @@ bool XINDEX::Make(PGLOBAL g, PIXDEF sxp)
/* Not true for DBF tables because of eventual soft deleted lines. */
/* Note: for Num_K = 1 any non null value is Ok. */
/*********************************************************************/
if (Srtd && !filp && Tdbp->Ftype != RECFM_VAR
if (Srtd && !filp && Tdbp->Ftype != RECFM_VAR && Tdbp->Ftype != RECFM_CSV
&& Tdbp->Txfp->GetAmType() != TYPE_AM_DBF) {
Incr = (Num_K > 1) ? To_Rec[1] : Num_K;
PlgDBfree(Record);
@ -837,7 +837,8 @@ bool XINDEX::SaveIndex(PGLOBAL g, PIXDEF sxp)
case RECFM_FIX: ftype = ".fnx"; break;
case RECFM_BIN: ftype = ".bnx"; break;
case RECFM_VCT: ftype = ".vnx"; break;
case RECFM_DBF: ftype = ".dbx"; break;
case RECFM_CSV: ftype = ".cnx"; break;
case RECFM_DBF: ftype = ".dbx"; break;
default:
sprintf(g->Message, MSG(INVALID_FTYPE), Tdbp->Ftype);
return true;
@ -990,7 +991,8 @@ bool XINDEX::Init(PGLOBAL g)
case RECFM_FIX: ftype = ".fnx"; break;
case RECFM_BIN: ftype = ".bnx"; break;
case RECFM_VCT: ftype = ".vnx"; break;
case RECFM_DBF: ftype = ".dbx"; break;
case RECFM_CSV: ftype = ".cnx"; break;
case RECFM_DBF: ftype = ".dbx"; break;
default:
sprintf(g->Message, MSG(INVALID_FTYPE), Tdbp->Ftype);
return true;
@ -1243,7 +1245,8 @@ bool XINDEX::MapInit(PGLOBAL g)
case RECFM_FIX: ftype = ".fnx"; break;
case RECFM_BIN: ftype = ".bnx"; break;
case RECFM_VCT: ftype = ".vnx"; break;
case RECFM_DBF: ftype = ".dbx"; break;
case RECFM_CSV: ftype = ".cnx"; break;
case RECFM_DBF: ftype = ".dbx"; break;
default:
sprintf(g->Message, MSG(INVALID_FTYPE), Tdbp->Ftype);
return true;
@ -1457,7 +1460,8 @@ bool XINDEX::GetAllSizes(PGLOBAL g,/* int &ndif,*/ int &numk)
case RECFM_FIX: ftype = ".fnx"; break;
case RECFM_BIN: ftype = ".bnx"; break;
case RECFM_VCT: ftype = ".vnx"; break;
case RECFM_DBF: ftype = ".dbx"; break;
case RECFM_CSV: ftype = ".cnx"; break;
case RECFM_DBF: ftype = ".dbx"; break;
default:
sprintf(g->Message, MSG(INVALID_FTYPE), Tdbp->Ftype);
return true;

View File

@ -173,9 +173,12 @@ class DllExport TDBASE : public TDB {
inline void SetKindex(PKXBASE kxp) {To_Kindex = kxp;}
// Properties
virtual PKXBASE GetKindex(void) {return To_Kindex;}
PKXBASE GetKindex(void) {return To_Kindex;}
PXOB *GetLink(void) {return To_Link;}
PIXDEF GetXdp(void) {return To_Xdp;}
void ResetKindex(PGLOBAL g, PKXBASE kxp);
PCOL Key(int i) {return (To_Key_Col) ? To_Key_Col[i] : NULL;}
PXOB Link(int i) { return (To_Link) ? To_Link[i] : NULL; }
// Methods
virtual bool IsUsingTemp(PGLOBAL) {return false;}

View File

@ -791,35 +791,3 @@ rtree_area_overlapping(
return(area);
}
/** Get the wkb of default POINT value, which represents POINT(0 0)
if it's of dimension 2, etc.
@param[in] n_dims dimensions
@param[out] wkb wkb buffer for default POINT
@param[in] len length of wkb buffer
@return non-0 indicate the length of wkb of the default POINT,
0 if the buffer is too small */
uint
get_wkb_of_default_point(
uint n_dims,
uchar* wkb,
uint len)
{
// JAN: TODO: MYSQL 5.7 GIS
#define GEOM_HEADER_SIZE 16
if (len < GEOM_HEADER_SIZE + sizeof(double) * n_dims) {
return(0);
}
/** POINT wkb comprises SRID, wkb header(byte order and type)
and coordinates of the POINT */
len = GEOM_HEADER_SIZE + sizeof(double) * n_dims;
/** We always use 0 as default coordinate */
memset(wkb, 0, len);
/** We don't need to write SRID, write 0x01 for Byte Order */
mach_write_to_n_little_endian(wkb + SRID_SIZE, 1, 0x01);
/** Write wkbType::wkbPoint for the POINT type */
mach_write_to_n_little_endian(wkb + SRID_SIZE + 1, 4, wkbPoint);
return(len);
}

View File

@ -54,19 +54,6 @@ enum wkbByteOrder
wkbNDR = 1 /* Little Endian */
};
/** Get the wkb of default POINT value, which represents POINT(0 0)
if it's of dimension 2, etc.
@param[in] n_dims dimensions
@param[out] wkb wkb buffer for default POINT
@param[in] len length of wkb buffer
@return non-0 indicate the length of wkb of the default POINT,
0 if the buffer is too small */
uint
get_wkb_of_default_point(
uint n_dims,
uchar* wkb,
uint len);
/*************************************************************//**
Calculate minimal bounding rectangle (mbr) of the spatial object
stored in "well-known binary representation" (wkb) format.

View File

@ -1788,6 +1788,9 @@ LinuxAIOHandler::resubmit(Slot* slot)
iocb->data = slot;
ut_a(reinterpret_cast<size_t>(iocb->u.c.buf) % OS_FILE_LOG_BLOCK_SIZE
== 0);
/* Resubmit an I/O request */
int ret = io_submit(m_array->io_ctx(m_segment), 1, &iocb);
ut_a(ret != -EINVAL);
@ -2156,6 +2159,9 @@ AIO::linux_dispatch(Slot* slot)
io_ctx_index = (slot->pos * m_n_segments) / m_slots.size();
ut_a(reinterpret_cast<size_t>(iocb->u.c.buf) % OS_FILE_LOG_BLOCK_SIZE
== 0);
int ret = io_submit(io_ctx(io_ctx_index), 1, &iocb);
ut_a(ret != -EINVAL);
@ -2348,6 +2354,8 @@ AIO::is_linux_native_aio_supported()
io_prep_pread(p_iocb, fd, ptr, 512, 0);
}
ut_a(reinterpret_cast<size_t>(p_iocb->u.c.buf) % OS_FILE_LOG_BLOCK_SIZE
== 0);
int err = io_submit(io_ctx, 1, &p_iocb);
ut_a(err != -EINVAL);
@ -6215,6 +6223,10 @@ AIO::reserve_slot(
os_offset_t offset,
ulint len)
{
ut_ad(reinterpret_cast<size_t>(buf) % OS_FILE_LOG_BLOCK_SIZE == 0);
ut_ad(offset % OS_FILE_LOG_BLOCK_SIZE == 0);
ut_ad(len % OS_FILE_LOG_BLOCK_SIZE == 0);
#ifdef WIN_ASYNC_IO
ut_a((len & 0xFFFFFFFFUL) == len);
#endif /* WIN_ASYNC_IO */

View File

@ -125,11 +125,17 @@ os_thread_create_func(
pthread_attr_t attr;
pthread_attr_init(&attr);
int ret = pthread_attr_init(&attr);
if (UNIV_UNLIKELY(ret)) {
fprintf(stderr,
"InnoDB: Error: pthread_attr_init() returned %d\n",
ret);
abort();
}
my_atomic_addlint(&os_thread_count, 1);
int ret = pthread_create(&new_thread_id, &attr, func, arg);
ret = pthread_create(&new_thread_id, &attr, func, arg);
ut_a(ret == 0);

View File

@ -41,7 +41,7 @@ a b c
connection child2_1;
SELECT argument FROM mysql.general_log WHERE argument LIKE '%select%';
argument
select `a`,`b`,`c` from `auto_test_remote`.`ta_r` where (`b` not like 'a%')
select t0.`a` `a`,t0.`b` `b`,t0.`c` `c` from `auto_test_remote`.`ta_r` t0 where (t0.`b` not like 'a%')
SELECT argument FROM mysql.general_log WHERE argument LIKE '%select%'
deinit