Merge branch '10.1' into 10.2
This commit is contained in:
commit
7f1900705b
@ -2952,10 +2952,11 @@ int main(int argc, char** argv)
|
||||
|
||||
if (!argc || opt_version)
|
||||
{
|
||||
if (!argc)
|
||||
usage();
|
||||
if (!opt_version)
|
||||
{
|
||||
usage();
|
||||
retval= ERROR_STOP;
|
||||
}
|
||||
goto err;
|
||||
}
|
||||
|
||||
|
@ -26,7 +26,7 @@ ENDIF()
|
||||
OPTION(WITH_WSREP "WSREP replication API (to use, e.g. Galera Replication library)" ${with_wsrep_default})
|
||||
|
||||
# Set the patch version
|
||||
SET(WSREP_PATCH_VERSION "20")
|
||||
SET(WSREP_PATCH_VERSION "21")
|
||||
|
||||
# Obtain wsrep API version
|
||||
FILE(STRINGS "${MySQL_SOURCE_DIR}/wsrep/wsrep_api.h" WSREP_API_VERSION
|
||||
|
@ -27,6 +27,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
#include "write_filt.h"
|
||||
#include "fil_cur.h"
|
||||
#include "xtrabackup.h"
|
||||
#include <os0proc.h>
|
||||
|
||||
/************************************************************************
|
||||
Write-through page write filter. */
|
||||
@ -67,19 +68,22 @@ wf_incremental_init(xb_write_filt_ctxt_t *ctxt, char *dst_name,
|
||||
xb_fil_cur_t *cursor)
|
||||
{
|
||||
char meta_name[FN_REFLEN];
|
||||
ulint buf_size;
|
||||
xb_wf_incremental_ctxt_t *cp =
|
||||
&(ctxt->u.wf_incremental_ctxt);
|
||||
|
||||
ctxt->cursor = cursor;
|
||||
|
||||
/* allocate buffer for incremental backup (4096 pages) */
|
||||
buf_size = (cursor->page_size.physical() / 4 + 1)
|
||||
* cursor->page_size.physical();
|
||||
cp->delta_buf_base = static_cast<byte *>(malloc(buf_size));
|
||||
memset(cp->delta_buf_base, 0, buf_size);
|
||||
cp->delta_buf = static_cast<byte *>
|
||||
(ut_align(cp->delta_buf_base, cursor->page_size.physical()));
|
||||
cp->delta_buf_size = (cursor->page_size.physical() / 4)
|
||||
* cursor->page_size.physical();
|
||||
cp->delta_buf = (unsigned char *)os_mem_alloc_large(&cp->delta_buf_size);
|
||||
|
||||
if (!cp->delta_buf) {
|
||||
msg("[%02u] mariabackup: Error: "
|
||||
"cannot allocate %zu bytes\n",
|
||||
cursor->thread_n, (size_t) cp->delta_buf_size);
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
/* write delta meta info */
|
||||
snprintf(meta_name, sizeof(meta_name), "%s%s", dst_name,
|
||||
@ -183,8 +187,7 @@ static void
|
||||
wf_incremental_deinit(xb_write_filt_ctxt_t *ctxt)
|
||||
{
|
||||
xb_wf_incremental_ctxt_t *cp = &(ctxt->u.wf_incremental_ctxt);
|
||||
|
||||
free(cp->delta_buf_base);
|
||||
os_mem_free_large(cp->delta_buf, cp->delta_buf_size);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
|
@ -30,7 +30,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
|
||||
/* Incremental page filter context */
|
||||
typedef struct {
|
||||
byte *delta_buf_base;
|
||||
ulint delta_buf_size;
|
||||
byte *delta_buf;
|
||||
ulint npages;
|
||||
} xb_wf_incremental_ctxt_t;
|
||||
|
@ -2,8 +2,3 @@
|
||||
# suite.pm will make sure that all tests including this file
|
||||
# will be skipped unless this is a debug build.
|
||||
#
|
||||
# The test below is redundant
|
||||
|
||||
if (`select version() not like '%debug%'`) {
|
||||
--skip Needs a debug build
|
||||
}
|
||||
|
@ -1,14 +1,4 @@
|
||||
#
|
||||
# Check if server has support for loading plugins
|
||||
# suite.pm will make sure that all tests including this file
|
||||
# will be skipped unless dynamic ha_example plugin is available
|
||||
#
|
||||
if (`SELECT @@have_dynamic_loading != 'YES'`) {
|
||||
--skip Example plugin requires dynamic loading
|
||||
}
|
||||
|
||||
#
|
||||
# Check if the variable EXAMPLE_PLUGIN is set
|
||||
#
|
||||
if (!$HA_EXAMPLE_SO) {
|
||||
--skip Need example plugin
|
||||
}
|
||||
|
||||
|
@ -2,9 +2,3 @@
|
||||
# suite.pm will make sure that all tests including this file
|
||||
# will be skipped unless innodb or xtradb is enabled
|
||||
#
|
||||
# The test below is redundant
|
||||
|
||||
if (`SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.ENGINES WHERE engine = 'innodb' AND support IN ('YES', 'DEFAULT', 'ENABLED')`)
|
||||
{
|
||||
--skip Test requires InnoDB.
|
||||
}
|
||||
|
@ -2,10 +2,3 @@
|
||||
# suite.pm will make sure that all tests including this file
|
||||
# will be skipped unless xtradb is enabled
|
||||
#
|
||||
# The test below is redundant
|
||||
|
||||
if (!`SELECT count(*) FROM information_schema.plugins WHERE
|
||||
plugin_name = 'innodb' AND plugin_status = 'active' AND
|
||||
plugin_description LIKE '%xtradb%'`){
|
||||
skip Needs XtraDB engine;
|
||||
}
|
||||
|
@ -2,9 +2,3 @@
|
||||
# suite.pm will make sure that all tests including this file
|
||||
# will be skipped unless this is an embedded test run
|
||||
#
|
||||
# The test below is redundant
|
||||
|
||||
if (`select version() like '%embedded%'`) {
|
||||
This should never happen;
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
--require r/not_windows.require
|
||||
disable_query_log;
|
||||
select convert(@@version_compile_os using latin1) NOT IN ("Win32","Win64","Windows") as "TRUE";
|
||||
enable_query_log;
|
||||
#
|
||||
# suite.pm will make sure that all tests including this file
|
||||
# will be skipped unless this is on Windows
|
||||
#
|
||||
|
15
mysql-test/include/show_gtid_list.inc
Normal file
15
mysql-test/include/show_gtid_list.inc
Normal file
@ -0,0 +1,15 @@
|
||||
# ==== Purpose ====
|
||||
#
|
||||
# Extract Gtid_list info from SHOW BINLOG EVENTS output masking
|
||||
# non-deterministic fields.
|
||||
#
|
||||
# ==== Usage ====
|
||||
#
|
||||
# [--let $binlog_file=filename
|
||||
#
|
||||
if ($binlog_file)
|
||||
{
|
||||
--let $_in_binlog_file=in '$binlog_file'
|
||||
}
|
||||
--replace_column 2 # 5 #
|
||||
--eval show binlog events $_in_binlog_file limit 1,1
|
@ -1258,3 +1258,4 @@ DELIMITER ;
|
||||
ROLLBACK /* added by mysqlbinlog */;
|
||||
/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
|
||||
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;
|
||||
mysqlbinlog Ver VER for OS at ARCH
|
||||
|
@ -1,2 +0,0 @@
|
||||
TRUE
|
||||
1
|
@ -8115,6 +8115,18 @@ CALL p();
|
||||
drop procedure p;
|
||||
drop view v;
|
||||
drop table t, tmp_t;
|
||||
#
|
||||
# MDEV-13936: Server crashes in Time_and_counter_tracker::incr_loops
|
||||
#
|
||||
CREATE TABLE t1 (i INT);
|
||||
CREATE VIEW v1 AS SELECT * FROM t1 WHERE RAND() > 0.5;
|
||||
CREATE FUNCTION f1() RETURNS INT RETURN ( SELECT MAX(i) FROM v1 );
|
||||
REPLACE INTO v1 VALUES (f1());
|
||||
ERROR HY000: The target table v1 of the INSERT is not insertable-into
|
||||
SET @aux = f1();
|
||||
DROP FUNCTION f1;
|
||||
DROP VIEW v1;
|
||||
DROP TABLE t1;
|
||||
#End of 10.1 tests
|
||||
#
|
||||
# MDEV-11081: CURSOR for query with GROUP BY
|
||||
|
@ -2329,6 +2329,23 @@ DROP TRIGGER t1_bi;
|
||||
DROP TABLE t1;
|
||||
SET TIMESTAMP=DEFAULT;
|
||||
set time_zone= @@global.time_zone;
|
||||
#
|
||||
# MDEV-13936: Server crashes in Time_and_counter_tracker::incr_loops
|
||||
#
|
||||
CREATE TABLE t1 (i INT);
|
||||
CREATE VIEW v1 AS SELECT * FROM t1 WHERE RAND() > 0.5;
|
||||
CREATE TABLE t2 (a int);
|
||||
CREATE TABLE t3 (a int);
|
||||
create trigger trg after insert on t2 for each row
|
||||
INSERT INTO t3 SELECT MAX(i) FROM v1 UNION SELECT MAX(i) FROM v1;
|
||||
drop table t1;
|
||||
insert into t2 value (2);
|
||||
ERROR 42S02: Table 'test.t1' doesn't exist
|
||||
CREATE TABLE t1 (i INT);
|
||||
insert into t2 value (2);
|
||||
DROP VIEW v1;
|
||||
DROP TABLE t1,t2,t3;
|
||||
End of 10.1 tests.
|
||||
create table t1 (i int);
|
||||
create trigger tr1 after insert on t1 for each row set @a=@a+1;
|
||||
create trigger tr2 after insert on t1 for each row set @a=@a+1;
|
||||
|
@ -0,0 +1,78 @@
|
||||
RESET MASTER;
|
||||
FLUSH BINARY LOGS DELETE_DOMAIN_ID = ();
|
||||
and the command execution is effective thence rotates binlog as usual
|
||||
show binary logs;
|
||||
Log_name File_size
|
||||
master-bin.000001 #
|
||||
master-bin.000002 #
|
||||
Non-existed domain is warned, the command completes without rotation
|
||||
but with a warning
|
||||
FLUSH BINARY LOGS DELETE_DOMAIN_ID = (99);
|
||||
Warnings:
|
||||
Warning 1076 The gtid domain being deleted ('99') is not in the current binlog state
|
||||
show binary logs;
|
||||
Log_name File_size
|
||||
master-bin.000001 #
|
||||
master-bin.000002 #
|
||||
SET @@SESSION.gtid_domain_id=1;
|
||||
SET @@SESSION.server_id=1;
|
||||
CREATE TABLE t (a int);
|
||||
FLUSH BINARY LOGS DELETE_DOMAIN_ID = (1);
|
||||
ERROR HY000: Could not delete gtid domain. Reason: binlog files may contain gtids from the domain ('1') being deleted. Make sure to first purge those files.
|
||||
FLUSH BINARY LOGS;
|
||||
FLUSH BINARY LOGS DELETE_DOMAIN_ID = (1);
|
||||
ERROR HY000: Could not delete gtid domain. Reason: binlog files may contain gtids from the domain ('1') being deleted. Make sure to first purge those files.
|
||||
PURGE BINARY LOGS TO 'master-bin.000003';;
|
||||
FLUSH BINARY LOGS DELETE_DOMAIN_ID = (1);
|
||||
Gtid_list of the current binlog does not contain '1':
|
||||
show binlog events in 'master-bin.000004' limit 1,1;
|
||||
Log_name Pos Event_type Server_id End_log_pos Info
|
||||
master-bin.000004 # Gtid_list 1 # []
|
||||
But the previous log's Gtid_list may have it which explains a warning from the following command
|
||||
show binlog events in 'master-bin.000003' limit 1,1;
|
||||
Log_name Pos Event_type Server_id End_log_pos Info
|
||||
master-bin.000003 # Gtid_list 1 # [1-1-1]
|
||||
Already deleted domain in Gtid_list of the earliest log is benign
|
||||
but may cause a warning
|
||||
FLUSH BINARY LOGS DELETE_DOMAIN_ID = (1);
|
||||
Warnings:
|
||||
Warning 1076 The current gtid binlog state is incompatible with a former one missing gtids from the '1-1' domain-server pair which is referred to in the gtid list describing an earlier state. Ignore if the domain ('1') was already explicitly deleted.
|
||||
Warning 1076 The gtid domain being deleted ('1') is not in the current binlog state
|
||||
FLUSH BINARY LOGS DELETE_DOMAIN_ID = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 0);
|
||||
ERROR HY000: Could not delete gtid domain. Reason: binlog files may contain gtids from the domain ('1') being deleted. Make sure to first purge those files.
|
||||
FLUSH BINARY LOGS;
|
||||
PURGE BINARY LOGS TO 'master-bin.000005';
|
||||
FLUSH BINARY LOGS DELETE_DOMAIN_ID = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 0);
|
||||
Warnings:
|
||||
Warning 1076 The gtid domain being deleted ('0') is not in the current binlog state
|
||||
Gtid_list of the current binlog does not contain 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 0:
|
||||
show binlog events in 'master-bin.000006' limit 1,1;
|
||||
Log_name Pos Event_type Server_id End_log_pos Info
|
||||
master-bin.000006 # Gtid_list 1 # []
|
||||
SET @@SESSION.gtid_domain_id=1;;
|
||||
SET @@SESSION.server_id=1;
|
||||
SET @@SESSION.gtid_seq_no=1;
|
||||
INSERT INTO t SET a=1;
|
||||
SET @@SESSION.server_id=2;
|
||||
SET @@SESSION.gtid_seq_no=2;
|
||||
INSERT INTO t SET a=2;
|
||||
SET @@SESSION.gtid_domain_id=11;
|
||||
SET @@SESSION.server_id=11;
|
||||
SET @@SESSION.gtid_seq_no=11;
|
||||
INSERT INTO t SET a=11;
|
||||
SET @gtid_binlog_state_saved=@@GLOBAL.gtid_binlog_state;
|
||||
FLUSH BINARY LOGS;
|
||||
SET @@SESSION.gtid_domain_id=11;
|
||||
SET @@SESSION.server_id=11;
|
||||
SET @@SESSION.gtid_seq_no=1;
|
||||
INSERT INTO t SET a=1;
|
||||
SELECT @gtid_binlog_state_saved "as original state", @@GLOBAL.gtid_binlog_state as "out of order for 11 domain state";
|
||||
as original state out of order for 11 domain state
|
||||
1-1-1,1-2-2,11-11-11 1-1-1,1-2-2,11-11-1
|
||||
PURGE BINARY LOGS TO 'master-bin.000007';
|
||||
the following command succeeds with warnings
|
||||
FLUSH BINARY LOGS DELETE_DOMAIN_ID = (1);
|
||||
Warnings:
|
||||
Warning 1076 The current gtid binlog state is incompatible with a former one having a gtid '11-11-1' which is less than the '11-11-11' of the gtid list describing an earlier state. The state may have been affected by manually injecting a lower sequence number gtid or via replication.
|
||||
DROP TABLE t;
|
||||
RESET MASTER;
|
@ -0,0 +1,6 @@
|
||||
SET @@SESSION.debug_dbug='+d,inject_binlog_delete_domain_init_error';
|
||||
FLUSH BINARY LOGS DELETE_DOMAIN_ID = (99);
|
||||
ERROR HY000: Could not delete gtid domain. Reason: injected error.
|
||||
SHOW WARNINGS;
|
||||
Level Code Message
|
||||
Error 1076 Could not delete gtid domain. Reason: injected error.
|
@ -0,0 +1,137 @@
|
||||
# Prove basic properties of
|
||||
#
|
||||
# FLUSH BINARY LOGS DELETE_DOMAIN_ID = (...)
|
||||
#
|
||||
# The command removes the supplied list of domains from the current
|
||||
# @@global.gtid_binlog_state provided the binlog files do not contain
|
||||
# events from such domains.
|
||||
|
||||
# The test is not format specific. One format is chosen to run it.
|
||||
--source include/have_binlog_format_mixed.inc
|
||||
|
||||
# Reset binlog state
|
||||
RESET MASTER;
|
||||
|
||||
# Empty list is accepted
|
||||
FLUSH BINARY LOGS DELETE_DOMAIN_ID = ();
|
||||
--echo and the command execution is effective thence rotates binlog as usual
|
||||
--source include/show_binary_logs.inc
|
||||
|
||||
--echo Non-existed domain is warned, the command completes without rotation
|
||||
--echo but with a warning
|
||||
--let $binlog_pre_flush=query_get_value(SHOW MASTER STATUS, Position, 1)
|
||||
FLUSH BINARY LOGS DELETE_DOMAIN_ID = (99);
|
||||
--let $binlog_start=$binlog_pre_flush
|
||||
--source include/show_binary_logs.inc
|
||||
|
||||
# Log one event in a specified domain and try to delete the domain
|
||||
SET @@SESSION.gtid_domain_id=1;
|
||||
SET @@SESSION.server_id=1;
|
||||
CREATE TABLE t (a int);
|
||||
|
||||
--error ER_BINLOG_CANT_DELETE_GTID_DOMAIN
|
||||
FLUSH BINARY LOGS DELETE_DOMAIN_ID = (1);
|
||||
|
||||
# the same error after log rotation
|
||||
FLUSH BINARY LOGS;
|
||||
--error ER_BINLOG_CANT_DELETE_GTID_DOMAIN
|
||||
FLUSH BINARY LOGS DELETE_DOMAIN_ID = (1);
|
||||
|
||||
# the latest binlog does not really contain any events incl ones from 1-domain
|
||||
--let $purge_to_binlog= query_get_value(SHOW MASTER STATUS, File, 1)
|
||||
--eval PURGE BINARY LOGS TO '$purge_to_binlog';
|
||||
# So now it's safe to delete
|
||||
--error 0
|
||||
FLUSH BINARY LOGS DELETE_DOMAIN_ID = (1);
|
||||
--echo Gtid_list of the current binlog does not contain '1':
|
||||
--let $binlog_file=query_get_value(SHOW MASTER STATUS, File, 1)
|
||||
--source include/show_gtid_list.inc
|
||||
--echo But the previous log's Gtid_list may have it which explains a warning from the following command
|
||||
--let $binlog_file=$purge_to_binlog
|
||||
--source include/show_gtid_list.inc
|
||||
|
||||
--echo Already deleted domain in Gtid_list of the earliest log is benign
|
||||
--echo but may cause a warning
|
||||
--error 0
|
||||
FLUSH BINARY LOGS DELETE_DOMAIN_ID = (1);
|
||||
|
||||
# Few domains delete. The chosen number verifies among others how
|
||||
# expected overrun of the static buffers of underlying dynamic arrays is doing.
|
||||
--let $domain_cnt=17
|
||||
--let $server_in_domain_cnt=3
|
||||
--let $domain_list=
|
||||
--disable_query_log
|
||||
while ($domain_cnt)
|
||||
{
|
||||
--let servers=$server_in_domain_cnt
|
||||
--eval SET @@SESSION.gtid_domain_id=$domain_cnt
|
||||
while ($servers)
|
||||
{
|
||||
--eval SET @@SESSION.server_id=10*$domain_cnt + $servers
|
||||
--eval INSERT INTO t SET a=@@SESSION.server_id
|
||||
|
||||
--dec $servers
|
||||
}
|
||||
--let $domain_list= $domain_cnt, $domain_list
|
||||
|
||||
--dec $domain_cnt
|
||||
}
|
||||
--enable_query_log
|
||||
--let $zero=0
|
||||
--let $domain_list= $domain_list$zero
|
||||
|
||||
--error ER_BINLOG_CANT_DELETE_GTID_DOMAIN
|
||||
--eval FLUSH BINARY LOGS DELETE_DOMAIN_ID = ($domain_list)
|
||||
|
||||
# Now satisfy the safety condtion to purge log files containing $domain list
|
||||
FLUSH BINARY LOGS;
|
||||
--let $purge_to_binlog= query_get_value(SHOW MASTER STATUS, File, 1)
|
||||
--eval PURGE BINARY LOGS TO '$purge_to_binlog'
|
||||
--error 0
|
||||
--eval FLUSH BINARY LOGS DELETE_DOMAIN_ID = ($domain_list)
|
||||
--echo Gtid_list of the current binlog does not contain $domain_list:
|
||||
--let $binlog_file=query_get_value(SHOW MASTER STATUS, File, 1)
|
||||
--source include/show_gtid_list.inc
|
||||
|
||||
# Show reaction on @@global.gtid_binlog_state not succeeding
|
||||
# earlier state as described by the 1st binlog' Gtid_list.
|
||||
# Now let it be out-order gtid logged to a domain unrelated to deletion.
|
||||
|
||||
--let $del_d_id=1
|
||||
--eval SET @@SESSION.gtid_domain_id=$del_d_id;
|
||||
SET @@SESSION.server_id=1;
|
||||
SET @@SESSION.gtid_seq_no=1;
|
||||
INSERT INTO t SET a=1;
|
||||
SET @@SESSION.server_id=2;
|
||||
SET @@SESSION.gtid_seq_no=2;
|
||||
INSERT INTO t SET a=2;
|
||||
|
||||
SET @@SESSION.gtid_domain_id=11;
|
||||
SET @@SESSION.server_id=11;
|
||||
SET @@SESSION.gtid_seq_no=11;
|
||||
INSERT INTO t SET a=11;
|
||||
|
||||
SET @gtid_binlog_state_saved=@@GLOBAL.gtid_binlog_state;
|
||||
FLUSH BINARY LOGS;
|
||||
|
||||
# Inject out of order for domain '11' before
|
||||
SET @@SESSION.gtid_domain_id=11;
|
||||
SET @@SESSION.server_id=11;
|
||||
SET @@SESSION.gtid_seq_no=1;
|
||||
INSERT INTO t SET a=1;
|
||||
|
||||
SELECT @gtid_binlog_state_saved "as original state", @@GLOBAL.gtid_binlog_state as "out of order for 11 domain state";
|
||||
|
||||
# to delete '1', first to purge logs containing its events
|
||||
--let $purge_to_binlog= query_get_value(SHOW MASTER STATUS, File, 1)
|
||||
--eval PURGE BINARY LOGS TO '$purge_to_binlog'
|
||||
|
||||
--echo the following command succeeds with warnings
|
||||
--eval FLUSH BINARY LOGS DELETE_DOMAIN_ID = ($del_d_id)
|
||||
|
||||
#
|
||||
# Cleanup
|
||||
#
|
||||
|
||||
DROP TABLE t;
|
||||
RESET MASTER;
|
@ -0,0 +1,11 @@
|
||||
# Check "internal" error branches of
|
||||
# FLUSH BINARY LOGS DELETE_DOMAIN_ID = (...)
|
||||
# handler.
|
||||
--source include/have_debug.inc
|
||||
--source include/have_binlog_format_mixed.inc
|
||||
|
||||
SET @@SESSION.debug_dbug='+d,inject_binlog_delete_domain_init_error';
|
||||
--error ER_BINLOG_CANT_DELETE_GTID_DOMAIN
|
||||
FLUSH BINARY LOGS DELETE_DOMAIN_ID = (99);
|
||||
|
||||
SHOW WARNINGS;
|
46
mysql-test/suite/galera/r/MW-388.result
Normal file
46
mysql-test/suite/galera/r/MW-388.result
Normal file
@ -0,0 +1,46 @@
|
||||
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 CHAR(255)) Engine=InnoDB;
|
||||
CREATE PROCEDURE insert_proc ()
|
||||
BEGIN
|
||||
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
|
||||
BEGIN
|
||||
GET DIAGNOSTICS CONDITION 1 @errno = MYSQL_ERRNO;
|
||||
END;
|
||||
INSERT INTO t1 VALUES (1, 'node 1'),(2, 'node 1');
|
||||
INSERT INTO t1 VALUES (3, 'node 1');
|
||||
END|
|
||||
SET GLOBAL wsrep_slave_threads = 2;
|
||||
SET GLOBAL DEBUG = "d,sync.wsrep_apply_cb";
|
||||
Warnings:
|
||||
Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead
|
||||
INSERT INTO t1 VALUES (1, 'node 2');;
|
||||
SET SESSION DEBUG_SYNC = "now WAIT_FOR sync.wsrep_apply_cb_reached";
|
||||
SET SESSION wsrep_sync_wait = 0;
|
||||
SET SESSION DEBUG_SYNC = 'wsrep_after_replication SIGNAL wsrep_after_replication_reached WAIT_FOR wsrep_after_replication_continue';
|
||||
CALL insert_proc ();;
|
||||
SET SESSION DEBUG_SYNC = "now WAIT_FOR wsrep_after_replication_reached";
|
||||
SET GLOBAL DEBUG = "";
|
||||
Warnings:
|
||||
Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead
|
||||
SET DEBUG_SYNC = "now SIGNAL wsrep_after_replication_continue";
|
||||
SET DEBUG_SYNC = "now SIGNAL signal.wsrep_apply_cb";
|
||||
SELECT @errno = 1213;
|
||||
@errno = 1213
|
||||
1
|
||||
SELECT * FROM t1;
|
||||
f1 f2
|
||||
1 node 2
|
||||
3 node 1
|
||||
SELECT * FROM t1;
|
||||
f1 f2
|
||||
1 node 2
|
||||
3 node 1
|
||||
SET GLOBAL wsrep_slave_threads = DEFAULT;
|
||||
DROP TABLE t1;
|
||||
DROP PROCEDURE insert_proc;
|
||||
SET GLOBAL debug = NULL;
|
||||
Warnings:
|
||||
Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead
|
||||
SET debug_sync='RESET';
|
||||
SELECT @@debug_sync;
|
||||
@@debug_sync
|
||||
ON - current signal: ''
|
@ -7,6 +7,7 @@ INSERT INTO t1 VALUES (1);
|
||||
# Disable binary logging for current session
|
||||
SET SQL_LOG_BIN=OFF;
|
||||
INSERT INTO t1 VALUES (2);
|
||||
FLUSH BINARY LOGS;
|
||||
CREATE TABLE t2(c1 INT PRIMARY KEY) ENGINE=INNODB;
|
||||
INSERT INTO t2 VALUES (1);
|
||||
CREATE TABLE test.t3 AS SELECT * from t1;
|
||||
|
76
mysql-test/suite/galera/t/MW-388.test
Normal file
76
mysql-test/suite/galera/t/MW-388.test
Normal file
@ -0,0 +1,76 @@
|
||||
--source include/galera_cluster.inc
|
||||
--source include/have_innodb.inc
|
||||
--source include/have_debug.inc
|
||||
--source include/have_debug_sync.inc
|
||||
|
||||
--connection node_1
|
||||
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 CHAR(255)) Engine=InnoDB;
|
||||
|
||||
DELIMITER |;
|
||||
CREATE PROCEDURE insert_proc ()
|
||||
BEGIN
|
||||
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
|
||||
BEGIN
|
||||
GET DIAGNOSTICS CONDITION 1 @errno = MYSQL_ERRNO;
|
||||
END;
|
||||
INSERT INTO t1 VALUES (1, 'node 1'),(2, 'node 1');
|
||||
INSERT INTO t1 VALUES (3, 'node 1');
|
||||
END|
|
||||
DELIMITER ;|
|
||||
|
||||
# We need two slave threads here to guarantee progress.
|
||||
# If we use only one thread the following could happen
|
||||
# in node_1:
|
||||
# We block the only slave thread in wsrep_apply_cb and we
|
||||
# issue an INSERT (by calling the stored procedure) that will
|
||||
# try to acquire galera's local monitor in pre_commit().
|
||||
# This usually works fine, except for when a commit cut event
|
||||
# sneaks in the slave queue and gets a local seqno smaller than
|
||||
# that of the INSERT. Because there is only one slave thread,
|
||||
# commit cut is not processed and therefore does not advance
|
||||
# local monitor, and our INSERT remains stuck there.
|
||||
SET GLOBAL wsrep_slave_threads = 2;
|
||||
SET GLOBAL DEBUG = "d,sync.wsrep_apply_cb";
|
||||
|
||||
--connection node_2
|
||||
--send INSERT INTO t1 VALUES (1, 'node 2');
|
||||
|
||||
--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1
|
||||
--connection node_1a
|
||||
SET SESSION DEBUG_SYNC = "now WAIT_FOR sync.wsrep_apply_cb_reached";
|
||||
|
||||
--connection node_1
|
||||
SET SESSION wsrep_sync_wait = 0;
|
||||
SET SESSION DEBUG_SYNC = 'wsrep_after_replication SIGNAL wsrep_after_replication_reached WAIT_FOR wsrep_after_replication_continue';
|
||||
--send CALL insert_proc ();
|
||||
|
||||
--connection node_1a
|
||||
SET SESSION DEBUG_SYNC = "now WAIT_FOR wsrep_after_replication_reached";
|
||||
|
||||
|
||||
SET GLOBAL DEBUG = "";
|
||||
SET DEBUG_SYNC = "now SIGNAL wsrep_after_replication_continue";
|
||||
SET DEBUG_SYNC = "now SIGNAL signal.wsrep_apply_cb";
|
||||
|
||||
--connection node_2
|
||||
--reap
|
||||
|
||||
--connection node_1
|
||||
# We expect no errors here, because the handler in insert_proc() caught the deadlock error
|
||||
--reap
|
||||
SELECT @errno = 1213;
|
||||
SELECT * FROM t1;
|
||||
|
||||
--connection node_2
|
||||
SELECT * FROM t1;
|
||||
|
||||
--connection node_1
|
||||
SET GLOBAL wsrep_slave_threads = DEFAULT;
|
||||
DROP TABLE t1;
|
||||
DROP PROCEDURE insert_proc;
|
||||
|
||||
SET GLOBAL debug = NULL;
|
||||
SET debug_sync='RESET';
|
||||
|
||||
# Make sure no pending signals are leftover to surprise subsequent tests.
|
||||
SELECT @@debug_sync;
|
@ -29,12 +29,11 @@ SELECT * FROM t1;
|
||||
|
||||
UNLOCK TABLES;
|
||||
|
||||
SHOW TABLES;
|
||||
SELECT COUNT(*) = 1 FROM t1;
|
||||
|
||||
--disable_query_log
|
||||
--eval SET GLOBAL wsrep_provider_options = "$wsrep_provider_options_orig";
|
||||
--enable_query_log
|
||||
|
||||
DROP TABLE t1;
|
||||
SHOW TABLES;
|
||||
SELECT COUNT(*) = 1 FROM t1;
|
||||
|
||||
DROP TABLE t1;
|
||||
|
@ -25,7 +25,7 @@ CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
|
||||
my $pid_filename = $ENV{'NODE_2_PIDFILE'};
|
||||
my $mysqld_pid = `cat $pid_filename`;
|
||||
chomp($mysqld_pid);
|
||||
system("kill -19 $mysqld_pid");
|
||||
system("kill -SIGSTOP $mysqld_pid");
|
||||
exit(0);
|
||||
EOF
|
||||
|
||||
@ -37,7 +37,7 @@ INSERT INTO t1 VALUES (1);
|
||||
my $pid_filename = $ENV{'NODE_2_PIDFILE'};
|
||||
my $mysqld_pid = `cat $pid_filename`;
|
||||
chomp($mysqld_pid);
|
||||
system("kill -18 $mysqld_pid");
|
||||
system("kill -SIGCONT $mysqld_pid");
|
||||
exit(0);
|
||||
EOF
|
||||
|
||||
|
@ -1,5 +1,13 @@
|
||||
# Test to check the behavior of galera cluster with sql_log_bin=ON|OFF & binary
|
||||
# logging is disabled. sql_bin_log should not affect galera replication.
|
||||
#
|
||||
# The following bugfixes are tested:
|
||||
#
|
||||
# MDEV-9510: Segmentation fault in binlog thread.
|
||||
# A scenario otherwise causing a similar segfault is replayed.
|
||||
# The test must pass having no crashes.
|
||||
# The sequence of sql statements is provided by original
|
||||
# sql_log_bin.test augmented with a FLUSH BINLOG LOGS, below.
|
||||
|
||||
--source include/galera_cluster.inc
|
||||
--source include/have_innodb.inc
|
||||
@ -15,6 +23,10 @@ INSERT INTO t1 VALUES (1);
|
||||
--echo # Disable binary logging for current session
|
||||
SET SQL_LOG_BIN=OFF;
|
||||
INSERT INTO t1 VALUES (2);
|
||||
|
||||
# MDEV-9510: the following binlog rotation due to FLUSH segfaults wo/ the fixes
|
||||
FLUSH BINARY LOGS;
|
||||
|
||||
CREATE TABLE t2(c1 INT PRIMARY KEY) ENGINE=INNODB;
|
||||
INSERT INTO t2 VALUES (1);
|
||||
CREATE TABLE test.t3 AS SELECT * from t1;
|
||||
|
13
mysql-test/suite/innodb/r/innodb-replace-debug.result
Normal file
13
mysql-test/suite/innodb/r/innodb-replace-debug.result
Normal file
@ -0,0 +1,13 @@
|
||||
#
|
||||
# Bug#17604730 ASSERTION: *CURSOR->INDEX->NAME == TEMP_INDEX_PREFIX
|
||||
#
|
||||
create table t1 (f1 int primary key, f2 int, f3 int, unique key k1(f2),
|
||||
key k2(f3)) engine=innodb;
|
||||
insert into t1 values (14, 24, 34);
|
||||
set @@debug_dbug = '+d,row_ins_sec_index_entry_timeout';
|
||||
replace into t1 values (14, 25, 34);
|
||||
select * from t1;
|
||||
f1 f2 f3
|
||||
14 25 34
|
||||
drop table t1;
|
||||
set @@debug_dbug = '-d,row_ins_sec_index_entry_timeout';
|
15
mysql-test/suite/innodb/t/innodb-replace-debug.test
Normal file
15
mysql-test/suite/innodb/t/innodb-replace-debug.test
Normal file
@ -0,0 +1,15 @@
|
||||
--source include/have_innodb.inc
|
||||
--source include/have_debug.inc
|
||||
|
||||
--echo #
|
||||
--echo # Bug#17604730 ASSERTION: *CURSOR->INDEX->NAME == TEMP_INDEX_PREFIX
|
||||
--echo #
|
||||
|
||||
create table t1 (f1 int primary key, f2 int, f3 int, unique key k1(f2),
|
||||
key k2(f3)) engine=innodb;
|
||||
insert into t1 values (14, 24, 34);
|
||||
set @@debug_dbug = '+d,row_ins_sec_index_entry_timeout';
|
||||
replace into t1 values (14, 25, 34);
|
||||
select * from t1;
|
||||
drop table t1;
|
||||
set @@debug_dbug = '-d,row_ins_sec_index_entry_timeout';
|
43
mysql-test/suite/rpl/r/rpl_gtid_delete_domain.result
Normal file
43
mysql-test/suite/rpl/r/rpl_gtid_delete_domain.result
Normal file
@ -0,0 +1,43 @@
|
||||
include/master-slave.inc
|
||||
[connection master]
|
||||
connection master;
|
||||
SET @@SESSION.gtid_domain_id=0;
|
||||
CREATE TABLE t (a INT);
|
||||
connection slave;
|
||||
connection slave;
|
||||
call mtr.add_suppression("connecting slave requested to start from.*which is not in the master's binlog");
|
||||
include/stop_slave.inc
|
||||
CHANGE MASTER TO master_use_gtid=slave_pos;
|
||||
connection master;
|
||||
SET @@SESSION.gtid_domain_id=11;
|
||||
SET @@SESSION.server_id=111;
|
||||
SET @@SESSION.gtid_seq_no=1;
|
||||
INSERT INTO t SET a=1;
|
||||
connection slave;
|
||||
SET @save.gtid_slave_pos=@@global.gtid_slave_pos;
|
||||
SET @@global.gtid_slave_pos=concat(@@global.gtid_slave_pos, ",", 11, "-", 111, "-", 1 + 1);
|
||||
Warnings:
|
||||
Warning 1947 Specified GTID 0-1-1 conflicts with the binary log which contains a more recent GTID 0-2-2. If MASTER_GTID_POS=CURRENT_POS is used, the binlog position will override the new value of @@gtid_slave_pos
|
||||
START SLAVE IO_THREAD;
|
||||
include/wait_for_slave_io_error.inc [errno=1236]
|
||||
connection master;
|
||||
FLUSH BINARY LOGS;
|
||||
PURGE BINARY LOGS TO 'master-bin.000002';;
|
||||
FLUSH BINARY LOGS DELETE_DOMAIN_ID=(11);
|
||||
connection slave;
|
||||
include/start_slave.inc
|
||||
connection master;
|
||||
INSERT INTO t SET a=1;
|
||||
connection slave;
|
||||
include/wait_for_slave_io_error.inc [errno=1236]
|
||||
connection master;
|
||||
FLUSH BINARY LOGS;
|
||||
PURGE BINARY LOGS TO 'master-bin.000004';;
|
||||
FLUSH BINARY LOGS DELETE_DOMAIN_ID=(11);
|
||||
connection slave;
|
||||
include/start_slave.inc
|
||||
connection master;
|
||||
SET @@SESSION.gtid_domain_id=0;
|
||||
DROP TABLE t;
|
||||
connection slave;
|
||||
include/rpl_end.inc
|
95
mysql-test/suite/rpl/t/rpl_gtid_delete_domain.test
Normal file
95
mysql-test/suite/rpl/t/rpl_gtid_delete_domain.test
Normal file
@ -0,0 +1,95 @@
|
||||
# In case master's gtid binlog state is divergent from the slave's gtid_slave_pos
|
||||
# slave may not be able to connect.
|
||||
# For instance when slave is more updated in some of domains, see
|
||||
# MDEV-12012 as example, the master's state may require adjustment.
|
||||
# In a specific case of an "old" divergent domain, that is there
|
||||
# won't be no more event groups from it generated, the states can be
|
||||
# made compatible with wiping the problematic domain away. After that slave
|
||||
# becomes connectable.
|
||||
#
|
||||
# Notice that the slave applied gtid state is not really required to
|
||||
# be similarly cleaned in order for replication to flow.
|
||||
# However this could lead to an expected error when the master
|
||||
# resumes binlogging of such domain which the test demonstrate.
|
||||
|
||||
--source include/master-slave.inc
|
||||
|
||||
--connection master
|
||||
# enforce the default domain_id binlogging explicitly
|
||||
SET @@SESSION.gtid_domain_id=0;
|
||||
CREATE TABLE t (a INT);
|
||||
--sync_slave_with_master
|
||||
|
||||
--connection slave
|
||||
call mtr.add_suppression("connecting slave requested to start from.*which is not in the master's binlog");
|
||||
|
||||
--source include/stop_slave.inc
|
||||
CHANGE MASTER TO master_use_gtid=slave_pos;
|
||||
|
||||
--connection master
|
||||
# create extra gtid domains for binlog state
|
||||
--let $extra_domain_id=11
|
||||
--let $extra_domain_server_id=111
|
||||
--let $extra_gtid_seq_no=1
|
||||
--eval SET @@SESSION.gtid_domain_id=$extra_domain_id
|
||||
--eval SET @@SESSION.server_id=$extra_domain_server_id
|
||||
--eval SET @@SESSION.gtid_seq_no=$extra_gtid_seq_no
|
||||
INSERT INTO t SET a=1;
|
||||
|
||||
#
|
||||
# Set up the slave replication state as if slave knows more events from the extra
|
||||
# domain.
|
||||
#
|
||||
--connection slave
|
||||
SET @save.gtid_slave_pos=@@global.gtid_slave_pos;
|
||||
--eval SET @@global.gtid_slave_pos=concat(@@global.gtid_slave_pos, ",", $extra_domain_id, "-", $extra_domain_server_id, "-", $extra_gtid_seq_no + 1)
|
||||
|
||||
# unsuccessful attempt to start slave
|
||||
START SLAVE IO_THREAD;
|
||||
--let $slave_io_errno=1236
|
||||
--source include/wait_for_slave_io_error.inc
|
||||
|
||||
--connection master
|
||||
# adjust the master binlog state
|
||||
FLUSH BINARY LOGS;
|
||||
--let $purge_to_binlog= query_get_value(SHOW MASTER STATUS, File, 1)
|
||||
--eval PURGE BINARY LOGS TO '$purge_to_binlog';
|
||||
# with final removal of the extra domain
|
||||
--eval FLUSH BINARY LOGS DELETE_DOMAIN_ID=($extra_domain_id)
|
||||
|
||||
--connection slave
|
||||
# start the slave sucessfully
|
||||
--source include/start_slave.inc
|
||||
|
||||
--connection master
|
||||
# but the following gtid from the *extra* domain will break replication
|
||||
INSERT INTO t SET a=1;
|
||||
|
||||
# take note of the slave io thread error due to being dismissed
|
||||
# extra domain at connection to master which tried becoming active;
|
||||
# slave is to stop.
|
||||
--connection slave
|
||||
--let $errno=1236
|
||||
--source include/wait_for_slave_io_error.inc
|
||||
|
||||
# let's apply the very same medicine
|
||||
--connection master
|
||||
FLUSH BINARY LOGS;
|
||||
--let $purge_to_binlog= query_get_value(SHOW MASTER STATUS, File, 1)
|
||||
--eval PURGE BINARY LOGS TO '$purge_to_binlog';
|
||||
# with final removal of the extra domain
|
||||
--eval FLUSH BINARY LOGS DELETE_DOMAIN_ID=($extra_domain_id)
|
||||
|
||||
--connection slave
|
||||
--source include/start_slave.inc
|
||||
|
||||
#
|
||||
# cleanup
|
||||
#
|
||||
--connection master
|
||||
SET @@SESSION.gtid_domain_id=0;
|
||||
DROP TABLE t;
|
||||
|
||||
sync_slave_with_master;
|
||||
|
||||
--source include/rpl_end.inc
|
@ -589,3 +589,9 @@ eval SET GLOBAL SERVER_ID = $old_server_id;
|
||||
--exec $MYSQL_BINLOG --hexdump std_data/mdev-4645-binlog_group_id.binlog
|
||||
--exec $MYSQL_BINLOG --hexdump std_data/mdev-4645-binlog_group_id_checksum.binlog
|
||||
--exec $MYSQL_BINLOG --hexdump std_data/mdev-4645-binlog_none.binlog
|
||||
|
||||
#
|
||||
# MDEV-12372 mysqlbinlog --version output is the same on 10.x as on 5.5.x, and contains not only version
|
||||
#
|
||||
replace_regex /.*mysqlbinlog(\.exe)? Ver .* for .* at [-_a-zA-Z0-9]+/mysqlbinlog Ver VER for OS at ARCH/;
|
||||
exec $MYSQL_BINLOG --version;
|
||||
|
@ -9581,6 +9581,23 @@ drop procedure p;
|
||||
drop view v;
|
||||
drop table t, tmp_t;
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-13936: Server crashes in Time_and_counter_tracker::incr_loops
|
||||
--echo #
|
||||
CREATE TABLE t1 (i INT);
|
||||
CREATE VIEW v1 AS SELECT * FROM t1 WHERE RAND() > 0.5;
|
||||
CREATE FUNCTION f1() RETURNS INT RETURN ( SELECT MAX(i) FROM v1 );
|
||||
|
||||
--error ER_NON_INSERTABLE_TABLE
|
||||
REPLACE INTO v1 VALUES (f1());
|
||||
SET @aux = f1();
|
||||
|
||||
# Cleanup
|
||||
DROP FUNCTION f1;
|
||||
DROP VIEW v1;
|
||||
DROP TABLE t1;
|
||||
|
||||
--echo #End of 10.1 tests
|
||||
|
||||
--echo #
|
||||
|
@ -2643,8 +2643,33 @@ DROP TABLE t1;
|
||||
SET TIMESTAMP=DEFAULT;
|
||||
set time_zone= @@global.time_zone;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-13936: Server crashes in Time_and_counter_tracker::incr_loops
|
||||
--echo #
|
||||
|
||||
CREATE TABLE t1 (i INT);
|
||||
CREATE VIEW v1 AS SELECT * FROM t1 WHERE RAND() > 0.5;
|
||||
CREATE TABLE t2 (a int);
|
||||
CREATE TABLE t3 (a int);
|
||||
|
||||
create trigger trg after insert on t2 for each row
|
||||
INSERT INTO t3 SELECT MAX(i) FROM v1 UNION SELECT MAX(i) FROM v1;
|
||||
|
||||
drop table t1;
|
||||
|
||||
--error ER_NO_SUCH_TABLE
|
||||
insert into t2 value (2);
|
||||
CREATE TABLE t1 (i INT);
|
||||
insert into t2 value (2);
|
||||
|
||||
DROP VIEW v1;
|
||||
DROP TABLE t1,t2,t3;
|
||||
|
||||
|
||||
--echo End of 10.1 tests.
|
||||
|
||||
#
|
||||
# MDEV-10915 Count number of exceuted triggers
|
||||
# MDEV-10915 Count number of executed triggers
|
||||
#
|
||||
|
||||
create table t1 (i int);
|
||||
|
@ -266,18 +266,18 @@ parse_cnf()
|
||||
# finally get the variable value (if variables has been specified multiple time use the last value only)
|
||||
|
||||
# look in group+suffix
|
||||
if [[ -n $WSREP_SST_OPT_CONF_SUFFIX ]]; then
|
||||
if [ -n $WSREP_SST_OPT_CONF_SUFFIX ]; then
|
||||
reval=$($MY_PRINT_DEFAULTS "${group}${WSREP_SST_OPT_CONF_SUFFIX}" | awk -F= '{if ($1 ~ /_/) { gsub(/_/,"-",$1); print $1"="$2 } else { print $0 }}' | grep -- "--$var=" | cut -d= -f2- | tail -1)
|
||||
fi
|
||||
|
||||
# look in group
|
||||
if [[ -z $reval ]]; then
|
||||
if [ -z $reval ]; then
|
||||
reval=$($MY_PRINT_DEFAULTS $group | awk -F= '{if ($1 ~ /_/) { gsub(/_/,"-",$1); print $1"="$2 } else { print $0 }}' | grep -- "--$var=" | cut -d= -f2- | tail -1)
|
||||
fi
|
||||
|
||||
# use default if we haven't found a value
|
||||
if [[ -z $reval ]]; then
|
||||
[[ -n $3 ]] && reval=$3
|
||||
if [ -z $reval ]; then
|
||||
[ -n $3 ] && reval=$3
|
||||
fi
|
||||
echo $reval
|
||||
}
|
||||
|
@ -5503,7 +5503,7 @@ void Regexp_processor_pcre::pcre_exec_warn(int rc) const
|
||||
switch (rc)
|
||||
{
|
||||
case PCRE_ERROR_NULL:
|
||||
errmsg= "pcre_exec: null arguement passed";
|
||||
errmsg= "pcre_exec: null argument passed";
|
||||
break;
|
||||
case PCRE_ERROR_BADOPTION:
|
||||
errmsg= "pcre_exec: bad option";
|
||||
|
@ -179,6 +179,7 @@ static SYMBOL symbols[] = {
|
||||
{ "DELAYED", SYM(DELAYED_SYM)},
|
||||
{ "DELAY_KEY_WRITE", SYM(DELAY_KEY_WRITE_SYM)},
|
||||
{ "DELETE", SYM(DELETE_SYM)},
|
||||
{ "DELETE_DOMAIN_ID", SYM(DELETE_DOMAIN_ID_SYM)},
|
||||
{ "DESC", SYM(DESC)},
|
||||
{ "DESCRIBE", SYM(DESCRIBE)},
|
||||
{ "DES_KEY_FILE", SYM(DES_KEY_FILE)},
|
||||
|
217
sql/log.cc
217
sql/log.cc
@ -6618,6 +6618,120 @@ void MYSQL_BIN_LOG::checkpoint_and_purge(ulong binlog_id)
|
||||
purge();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Searches for the first (oldest) binlog file name in in the binlog index.
|
||||
|
||||
@param[in,out] buf_arg pointer to a buffer to hold found
|
||||
the first binary log file name
|
||||
@return NULL on success, otherwise error message
|
||||
*/
|
||||
static const char* get_first_binlog(char* buf_arg)
|
||||
{
|
||||
IO_CACHE *index_file;
|
||||
size_t length;
|
||||
char fname[FN_REFLEN];
|
||||
const char* errmsg= NULL;
|
||||
|
||||
DBUG_ENTER("get_first_binlog");
|
||||
|
||||
DBUG_ASSERT(mysql_bin_log.is_open());
|
||||
|
||||
mysql_bin_log.lock_index();
|
||||
|
||||
index_file=mysql_bin_log.get_index_file();
|
||||
if (reinit_io_cache(index_file, READ_CACHE, (my_off_t) 0, 0, 0))
|
||||
{
|
||||
errmsg= "failed to create a cache on binlog index";
|
||||
goto end;
|
||||
}
|
||||
/* The file ends with EOF or empty line */
|
||||
if ((length=my_b_gets(index_file, fname, sizeof(fname))) <= 1)
|
||||
{
|
||||
errmsg= "empty binlog index";
|
||||
goto end;
|
||||
}
|
||||
else
|
||||
{
|
||||
fname[length-1]= 0; // Remove end \n
|
||||
}
|
||||
if (normalize_binlog_name(buf_arg, fname, false))
|
||||
{
|
||||
errmsg= "cound not normalize the first file name in the binlog index";
|
||||
goto end;
|
||||
}
|
||||
end:
|
||||
mysql_bin_log.unlock_index();
|
||||
|
||||
DBUG_RETURN(errmsg);
|
||||
}
|
||||
|
||||
/**
|
||||
Check weather the gtid binlog state can safely remove gtid
|
||||
domains passed as the argument. A safety condition is satisfied when
|
||||
there are no events from the being deleted domains in the currently existing
|
||||
binlog files. Upon successful check the supplied domains are removed
|
||||
from @@gtid_binlog_state. The caller is supposed to rotate binlog so that
|
||||
the active latest file won't have the deleted domains in its Gtid_list header.
|
||||
|
||||
@param domain_drop_lex gtid domain id sequence from lex.
|
||||
Passed as a pointer to dynamic array must be not empty
|
||||
unless pointer value NULL.
|
||||
@retval zero on success
|
||||
@retval > 0 ineffective call none from the *non* empty
|
||||
gtid domain sequence is deleted
|
||||
@retval < 0 on error
|
||||
*/
|
||||
static int do_delete_gtid_domain(DYNAMIC_ARRAY *domain_drop_lex)
|
||||
{
|
||||
int rc= 0;
|
||||
Gtid_list_log_event *glev= NULL;
|
||||
char buf[FN_REFLEN];
|
||||
File file;
|
||||
IO_CACHE cache;
|
||||
const char* errmsg= NULL;
|
||||
char errbuf[MYSQL_ERRMSG_SIZE]= {0};
|
||||
|
||||
if (!domain_drop_lex)
|
||||
return 0; // still "effective" having empty domain sequence to delete
|
||||
|
||||
DBUG_ASSERT(domain_drop_lex->elements > 0);
|
||||
mysql_mutex_assert_owner(mysql_bin_log.get_log_lock());
|
||||
|
||||
if ((errmsg= get_first_binlog(buf)) != NULL)
|
||||
goto end;
|
||||
bzero((char*) &cache, sizeof(cache));
|
||||
if ((file= open_binlog(&cache, buf, &errmsg)) == (File) -1)
|
||||
goto end;
|
||||
errmsg= get_gtid_list_event(&cache, &glev);
|
||||
end_io_cache(&cache);
|
||||
mysql_file_close(file, MYF(MY_WME));
|
||||
|
||||
DBUG_EXECUTE_IF("inject_binlog_delete_domain_init_error",
|
||||
errmsg= "injected error";);
|
||||
if (errmsg)
|
||||
goto end;
|
||||
errmsg= rpl_global_gtid_binlog_state.drop_domain(domain_drop_lex,
|
||||
glev, errbuf);
|
||||
|
||||
end:
|
||||
if (errmsg)
|
||||
{
|
||||
if (strlen(errmsg) > 0)
|
||||
{
|
||||
my_error(ER_BINLOG_CANT_DELETE_GTID_DOMAIN, MYF(0), errmsg);
|
||||
rc= -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
rc= 1;
|
||||
}
|
||||
}
|
||||
delete glev;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
The method is a shortcut of @c rotate() and @c purge().
|
||||
LOCK_log is acquired prior to rotate and is released after it.
|
||||
@ -6627,16 +6741,24 @@ void MYSQL_BIN_LOG::checkpoint_and_purge(ulong binlog_id)
|
||||
@retval
|
||||
nonzero - error in rotating routine.
|
||||
*/
|
||||
int MYSQL_BIN_LOG::rotate_and_purge(bool force_rotate)
|
||||
int MYSQL_BIN_LOG::rotate_and_purge(bool force_rotate,
|
||||
DYNAMIC_ARRAY *domain_drop_lex)
|
||||
{
|
||||
int error= 0;
|
||||
int err_gtid=0, error= 0;
|
||||
ulong prev_binlog_id;
|
||||
DBUG_ENTER("MYSQL_BIN_LOG::rotate_and_purge");
|
||||
bool check_purge= false;
|
||||
|
||||
mysql_mutex_lock(&LOCK_log);
|
||||
prev_binlog_id= current_binlog_id;
|
||||
if ((error= rotate(force_rotate, &check_purge)))
|
||||
|
||||
if ((err_gtid= do_delete_gtid_domain(domain_drop_lex)))
|
||||
{
|
||||
// inffective attempt to delete merely skips rotate and purge
|
||||
if (err_gtid < 0)
|
||||
error= 1; // otherwise error is propagated the user
|
||||
}
|
||||
else if ((error= rotate(force_rotate, &check_purge)))
|
||||
check_purge= false;
|
||||
/*
|
||||
NOTE: Run purge_logs wo/ holding LOCK_log because it does not need
|
||||
@ -7038,8 +7160,15 @@ MYSQL_BIN_LOG::write_transaction_to_binlog(THD *thd,
|
||||
mode. Also, do not write the cached updates to binlog if binary logging is
|
||||
disabled (log-bin/sql_log_bin).
|
||||
*/
|
||||
if (wsrep_emulate_bin_log || !(thd->variables.option_bits & OPTION_BIN_LOG))
|
||||
if (wsrep_emulate_bin_log)
|
||||
{
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
else if (!(thd->variables.option_bits & OPTION_BIN_LOG))
|
||||
{
|
||||
cache_mngr->need_unlog= false;
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
entry.thd= thd;
|
||||
entry.cache_mngr= cache_mngr;
|
||||
@ -9362,11 +9491,19 @@ TC_LOG_BINLOG::log_and_order(THD *thd, my_xid xid, bool all,
|
||||
|
||||
if (err)
|
||||
DBUG_RETURN(0);
|
||||
|
||||
bool need_unlog= cache_mngr->need_unlog;
|
||||
/*
|
||||
The transaction won't need the flag anymore.
|
||||
Todo/fixme: consider to move the statement into cache_mngr->reset()
|
||||
relocated to the current or later point.
|
||||
*/
|
||||
cache_mngr->need_unlog= false;
|
||||
/*
|
||||
If using explicit user XA, we will not have XID. We must still return a
|
||||
non-zero cookie (as zero cookie signals error).
|
||||
*/
|
||||
if (!xid || !cache_mngr->need_unlog)
|
||||
if (!xid || !need_unlog)
|
||||
DBUG_RETURN(BINLOG_COOKIE_DUMMY(cache_mngr->delayed_error));
|
||||
else
|
||||
DBUG_RETURN(BINLOG_COOKIE_MAKE(cache_mngr->binlog_id,
|
||||
@ -9439,6 +9576,9 @@ TC_LOG_BINLOG::mark_xid_done(ulong binlog_id, bool write_checkpoint)
|
||||
if (b->binlog_id == binlog_id)
|
||||
{
|
||||
--b->xid_count;
|
||||
|
||||
DBUG_ASSERT(b->xid_count >= 0); // catch unmatched (++) decrement
|
||||
|
||||
break;
|
||||
}
|
||||
first= false;
|
||||
@ -10212,6 +10352,73 @@ TC_LOG_BINLOG::set_status_variables(THD *thd)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Find the Gtid_list_log_event at the start of a binlog.
|
||||
|
||||
NULL for ok, non-NULL error message for error.
|
||||
|
||||
If ok, then the event is returned in *out_gtid_list. This can be NULL if we
|
||||
get back to binlogs written by old server version without GTID support. If
|
||||
so, it means we have reached the point to start from, as no GTID events can
|
||||
exist in earlier binlogs.
|
||||
*/
|
||||
const char *
|
||||
get_gtid_list_event(IO_CACHE *cache, Gtid_list_log_event **out_gtid_list)
|
||||
{
|
||||
Format_description_log_event init_fdle(BINLOG_VERSION);
|
||||
Format_description_log_event *fdle;
|
||||
Log_event *ev;
|
||||
const char *errormsg = NULL;
|
||||
|
||||
*out_gtid_list= NULL;
|
||||
|
||||
if (!(ev= Log_event::read_log_event(cache, 0, &init_fdle,
|
||||
opt_master_verify_checksum)) ||
|
||||
ev->get_type_code() != FORMAT_DESCRIPTION_EVENT)
|
||||
{
|
||||
if (ev)
|
||||
delete ev;
|
||||
return "Could not read format description log event while looking for "
|
||||
"GTID position in binlog";
|
||||
}
|
||||
|
||||
fdle= static_cast<Format_description_log_event *>(ev);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
Log_event_type typ;
|
||||
|
||||
ev= Log_event::read_log_event(cache, 0, fdle, opt_master_verify_checksum);
|
||||
if (!ev)
|
||||
{
|
||||
errormsg= "Could not read GTID list event while looking for GTID "
|
||||
"position in binlog";
|
||||
break;
|
||||
}
|
||||
typ= ev->get_type_code();
|
||||
if (typ == GTID_LIST_EVENT)
|
||||
break; /* Done, found it */
|
||||
if (typ == START_ENCRYPTION_EVENT)
|
||||
{
|
||||
if (fdle->start_decryption((Start_encryption_log_event*) ev))
|
||||
errormsg= "Could not set up decryption for binlog.";
|
||||
}
|
||||
delete ev;
|
||||
if (typ == ROTATE_EVENT || typ == STOP_EVENT ||
|
||||
typ == FORMAT_DESCRIPTION_EVENT || typ == START_ENCRYPTION_EVENT)
|
||||
continue; /* Continue looking */
|
||||
|
||||
/* We did not find any Gtid_list_log_event, must be old binlog. */
|
||||
ev= NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
delete fdle;
|
||||
*out_gtid_list= static_cast<Gtid_list_log_event *>(ev);
|
||||
return errormsg;
|
||||
}
|
||||
|
||||
struct st_mysql_storage_engine binlog_storage_engine=
|
||||
{ MYSQL_HANDLERTON_INTERFACE_VERSION };
|
||||
|
||||
|
@ -758,7 +758,7 @@ public:
|
||||
int update_log_index(LOG_INFO* linfo, bool need_update_threads);
|
||||
int rotate(bool force_rotate, bool* check_purge);
|
||||
void checkpoint_and_purge(ulong binlog_id);
|
||||
int rotate_and_purge(bool force_rotate);
|
||||
int rotate_and_purge(bool force_rotate, DYNAMIC_ARRAY* drop_gtid_domain= NULL);
|
||||
/**
|
||||
Flush binlog cache and synchronize to disk.
|
||||
|
||||
@ -1167,4 +1167,9 @@ static inline TC_LOG *get_tc_log_implementation()
|
||||
return &tc_log_mmap;
|
||||
}
|
||||
|
||||
|
||||
class Gtid_list_log_event;
|
||||
const char *
|
||||
get_gtid_list_event(IO_CACHE *cache, Gtid_list_log_event **out_gtid_list);
|
||||
|
||||
#endif /* LOG_H */
|
||||
|
@ -5875,9 +5875,6 @@ int mysqld_main(int argc, char **argv)
|
||||
#ifdef __WIN__
|
||||
if (!opt_console)
|
||||
{
|
||||
if (reopen_fstreams(log_error_file, stdout, stderr))
|
||||
unireg_abort(1);
|
||||
setbuf(stderr, NULL);
|
||||
FreeConsole(); // Remove window
|
||||
}
|
||||
|
||||
|
151
sql/rpl_gtid.cc
151
sql/rpl_gtid.cc
@ -26,7 +26,7 @@
|
||||
#include "key.h"
|
||||
#include "rpl_gtid.h"
|
||||
#include "rpl_rli.h"
|
||||
|
||||
#include "log_event.h"
|
||||
|
||||
const LEX_STRING rpl_gtid_slave_state_table_name=
|
||||
{ C_STRING_WITH_LEN("gtid_slave_pos") };
|
||||
@ -1727,6 +1727,155 @@ end:
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
Remove domains supplied by the first argument from binlog state.
|
||||
Removal is done for any domain whose last gtids (from all its servers) match
|
||||
ones in Gtid list event of the 2nd argument.
|
||||
|
||||
@param ids gtid domain id sequence, may contain dups
|
||||
@param glev pointer to Gtid list event describing
|
||||
the match condition
|
||||
@param errbuf [out] pointer to possible error message array
|
||||
|
||||
@retval NULL as success when at least one domain is removed
|
||||
@retval "" empty string to indicate ineffective call
|
||||
when no domains removed
|
||||
@retval NOT EMPTY string otherwise an error message
|
||||
*/
|
||||
const char*
|
||||
rpl_binlog_state::drop_domain(DYNAMIC_ARRAY *ids,
|
||||
Gtid_list_log_event *glev,
|
||||
char* errbuf)
|
||||
{
|
||||
DYNAMIC_ARRAY domain_unique; // sequece (unsorted) of unique element*:s
|
||||
rpl_binlog_state::element* domain_unique_buffer[16];
|
||||
ulong k, l;
|
||||
const char* errmsg= NULL;
|
||||
|
||||
DBUG_ENTER("rpl_binlog_state::drop_domain");
|
||||
|
||||
my_init_dynamic_array2(&domain_unique,
|
||||
sizeof(element*), domain_unique_buffer,
|
||||
sizeof(domain_unique_buffer) / sizeof(element*), 4, 0);
|
||||
|
||||
mysql_mutex_lock(&LOCK_binlog_state);
|
||||
|
||||
/*
|
||||
Gtid list is supposed to come from a binlog's Gtid_list event and
|
||||
therefore should be a subset of the current binlog state. That is
|
||||
for every domain in the list the binlog state contains a gtid with
|
||||
sequence number not less than that of the list.
|
||||
Exceptions of this inclusion rule are:
|
||||
A. the list may still refer to gtids from already deleted domains.
|
||||
Files containing them must have been purged whereas the file
|
||||
with the list is not yet.
|
||||
B. out of order groups were injected
|
||||
C. manually build list of binlog files violating the inclusion
|
||||
constraint.
|
||||
While A is a normal case (not necessarily distinguishable from C though),
|
||||
B and C may require the user's attention so any (incl the A's suspected)
|
||||
inconsistency is diagnosed and *warned*.
|
||||
*/
|
||||
for (l= 0, errbuf[0]= 0; l < glev->count; l++, errbuf[0]= 0)
|
||||
{
|
||||
rpl_gtid* rb_state_gtid= find_nolock(glev->list[l].domain_id,
|
||||
glev->list[l].server_id);
|
||||
if (!rb_state_gtid)
|
||||
sprintf(errbuf,
|
||||
"missing gtids from the '%u-%u' domain-server pair which is "
|
||||
"referred to in the gtid list describing an earlier state. Ignore "
|
||||
"if the domain ('%u') was already explicitly deleted",
|
||||
glev->list[l].domain_id, glev->list[l].server_id,
|
||||
glev->list[l].domain_id);
|
||||
else if (rb_state_gtid->seq_no < glev->list[l].seq_no)
|
||||
sprintf(errbuf,
|
||||
"having a gtid '%u-%u-%llu' which is less than "
|
||||
"the '%u-%u-%llu' of the gtid list describing an earlier state. "
|
||||
"The state may have been affected by manually injecting "
|
||||
"a lower sequence number gtid or via replication",
|
||||
rb_state_gtid->domain_id, rb_state_gtid->server_id,
|
||||
rb_state_gtid->seq_no, glev->list[l].domain_id,
|
||||
glev->list[l].server_id, glev->list[l].seq_no);
|
||||
if (strlen(errbuf)) // use strlen() as cheap flag
|
||||
push_warning_printf(current_thd, Sql_condition::WARN_LEVEL_WARN,
|
||||
ER_BINLOG_CANT_DELETE_GTID_DOMAIN,
|
||||
"The current gtid binlog state is incompatible with "
|
||||
"a former one %s.", errbuf);
|
||||
}
|
||||
|
||||
/*
|
||||
For each domain_id from ids
|
||||
when no such domain in binlog state
|
||||
warn && continue
|
||||
For each domain.server's last gtid
|
||||
when not locate the last gtid in glev.list
|
||||
error out binlog state can't change
|
||||
otherwise continue
|
||||
*/
|
||||
for (ulong i= 0; i < ids->elements; i++)
|
||||
{
|
||||
rpl_binlog_state::element *elem= NULL;
|
||||
ulong *ptr_domain_id;
|
||||
bool not_match;
|
||||
|
||||
ptr_domain_id= (ulong*) dynamic_array_ptr(ids, i);
|
||||
elem= (rpl_binlog_state::element *)
|
||||
my_hash_search(&hash, (const uchar *) ptr_domain_id, 0);
|
||||
if (!elem)
|
||||
{
|
||||
push_warning_printf(current_thd, Sql_condition::WARN_LEVEL_WARN,
|
||||
ER_BINLOG_CANT_DELETE_GTID_DOMAIN,
|
||||
"The gtid domain being deleted ('%lu') is not in "
|
||||
"the current binlog state", *ptr_domain_id);
|
||||
continue;
|
||||
}
|
||||
|
||||
for (not_match= true, k= 0; k < elem->hash.records; k++)
|
||||
{
|
||||
rpl_gtid *d_gtid= (rpl_gtid *)my_hash_element(&elem->hash, k);
|
||||
for (ulong l= 0; l < glev->count && not_match; l++)
|
||||
not_match= !(*d_gtid == glev->list[l]);
|
||||
}
|
||||
|
||||
if (not_match)
|
||||
{
|
||||
sprintf(errbuf, "binlog files may contain gtids from the domain ('%lu') "
|
||||
"being deleted. Make sure to first purge those files",
|
||||
*ptr_domain_id);
|
||||
errmsg= errbuf;
|
||||
goto end;
|
||||
}
|
||||
// compose a sequence of unique pointers to domain object
|
||||
for (k= 0; k < domain_unique.elements; k++)
|
||||
{
|
||||
if ((rpl_binlog_state::element*) dynamic_array_ptr(&domain_unique, k)
|
||||
== elem)
|
||||
break; // domain_id's elem has been already in
|
||||
}
|
||||
if (k == domain_unique.elements) // proven not to have duplicates
|
||||
insert_dynamic(&domain_unique, (uchar*) &elem);
|
||||
}
|
||||
|
||||
// Domain removal from binlog state
|
||||
for (k= 0; k < domain_unique.elements; k++)
|
||||
{
|
||||
rpl_binlog_state::element *elem= *(rpl_binlog_state::element**)
|
||||
dynamic_array_ptr(&domain_unique, k);
|
||||
my_hash_free(&elem->hash);
|
||||
my_hash_delete(&hash, (uchar*) elem);
|
||||
}
|
||||
|
||||
DBUG_ASSERT(strlen(errbuf) == 0);
|
||||
|
||||
if (domain_unique.elements == 0)
|
||||
errmsg= "";
|
||||
|
||||
end:
|
||||
mysql_mutex_unlock(&LOCK_binlog_state);
|
||||
delete_dynamic(&domain_unique);
|
||||
|
||||
DBUG_RETURN(errmsg);
|
||||
}
|
||||
|
||||
slave_connection_state::slave_connection_state()
|
||||
{
|
||||
|
@ -34,6 +34,13 @@ struct rpl_gtid
|
||||
uint64 seq_no;
|
||||
};
|
||||
|
||||
inline bool operator==(const rpl_gtid& lhs, const rpl_gtid& rhs)
|
||||
{
|
||||
return
|
||||
lhs.domain_id == rhs.domain_id &&
|
||||
lhs.server_id == rhs.server_id &&
|
||||
lhs.seq_no == rhs.seq_no;
|
||||
};
|
||||
|
||||
enum enum_gtid_skip_type {
|
||||
GTID_SKIP_NOT, GTID_SKIP_STANDALONE, GTID_SKIP_TRANSACTION
|
||||
@ -93,6 +100,7 @@ struct gtid_waiting {
|
||||
|
||||
class Relay_log_info;
|
||||
struct rpl_group_info;
|
||||
class Gtid_list_log_event;
|
||||
|
||||
/*
|
||||
Replication slave state.
|
||||
@ -257,6 +265,7 @@ struct rpl_binlog_state
|
||||
rpl_gtid *find_nolock(uint32 domain_id, uint32 server_id);
|
||||
rpl_gtid *find(uint32 domain_id, uint32 server_id);
|
||||
rpl_gtid *find_most_recent(uint32 domain_id);
|
||||
const char* drop_domain(DYNAMIC_ARRAY *ids, Gtid_list_log_event *glev, char*);
|
||||
};
|
||||
|
||||
|
||||
|
@ -1801,8 +1801,8 @@ ER_WRONG_AUTO_KEY 42000 S1009
|
||||
spa "Puede ser solamente un campo automatico y este debe ser definido como una clave"
|
||||
swe "Det får finnas endast ett AUTO_INCREMENT-fält och detta måste vara en nyckel"
|
||||
ukr "Невірне визначення таблиці; Може бути лише один автоматичний стовбець, що повинен бути визначений як ключ"
|
||||
ER_UNUSED_9
|
||||
eng "You should never see it"
|
||||
ER_BINLOG_CANT_DELETE_GTID_DOMAIN
|
||||
eng "Could not delete gtid domain. Reason: %s."
|
||||
ER_NORMAL_SHUTDOWN
|
||||
cze "%s (%s): normální ukončení\n"
|
||||
dan "%s (%s): Normal nedlukning\n"
|
||||
@ -7330,7 +7330,7 @@ ER_SUBQUERIES_NOT_SUPPORTED 42000
|
||||
eng "%s does not support subqueries or stored functions"
|
||||
ER_SET_STATEMENT_NOT_SUPPORTED 42000
|
||||
eng "The system variable %.200s cannot be set in SET STATEMENT."
|
||||
ER_UNUSED_17
|
||||
ER_UNUSED_9
|
||||
eng "You should never see it"
|
||||
ER_USER_CREATE_EXISTS
|
||||
eng "Can't create user '%-.64s'@'%-.64s'; it already exists"
|
||||
|
@ -1144,6 +1144,19 @@ sp_head::execute(THD *thd, bool merge_da_on_success)
|
||||
if (check_stack_overrun(thd, 7 * STACK_MIN_SIZE, (uchar*)&old_packet))
|
||||
DBUG_RETURN(TRUE);
|
||||
|
||||
/*
|
||||
Normally the counter is not reset between parsing and first execution,
|
||||
but it is possible in case of error to have parsing on one CALL and
|
||||
first execution (where VIEW will be parsed and added). So we store the
|
||||
counter after parsing and restore it before execution just to avoid
|
||||
repeating SELECT numbers.
|
||||
|
||||
Other problem is that it can be more SELECTs parsed in case of fixing
|
||||
error causes previous interruption of the SP. So it is save not just
|
||||
assign old value but add it.
|
||||
*/
|
||||
thd->select_number+= m_select_number;
|
||||
|
||||
/* init per-instruction memroot */
|
||||
init_sql_alloc(&execute_mem_root, MEM_ROOT_BLOCK_SIZE, 0, MYF(0));
|
||||
|
||||
@ -1477,6 +1490,16 @@ sp_head::execute(THD *thd, bool merge_da_on_success)
|
||||
m_recursion_level + 1));
|
||||
m_first_instance->m_first_free_instance= this;
|
||||
|
||||
/*
|
||||
This execution of the SP was aborted with an error (e.g. "Table not
|
||||
found"). However it might still have consumed some numbers from the
|
||||
thd->select_number counter. The next sp->exec() call must not use the
|
||||
consumed numbers, so we remember the first free number (We know that
|
||||
nobody will use it as this execution has stopped with an error).
|
||||
*/
|
||||
if (err_status)
|
||||
set_select_number(thd->select_number);
|
||||
|
||||
DBUG_RETURN(err_status);
|
||||
}
|
||||
|
||||
@ -2109,26 +2132,7 @@ sp_head::execute_procedure(THD *thd, List<Item> *args)
|
||||
|
||||
if (!err_status)
|
||||
{
|
||||
/*
|
||||
Normally the counter is not reset between parsing and first execution,
|
||||
but it is possible in case of error to have parsing on one CALL and
|
||||
first execution (where VIEW will be parsed and added). So we store the
|
||||
counter after parsing and restore it before execution just to avoid
|
||||
repeating SELECT numbers.
|
||||
*/
|
||||
thd->select_number= m_select_number;
|
||||
|
||||
err_status= execute(thd, TRUE);
|
||||
DBUG_PRINT("info", ("execute returned %d", (int) err_status));
|
||||
/*
|
||||
This execution of the SP was aborted with an error (e.g. "Table not
|
||||
found"). However it might still have consumed some numbers from the
|
||||
thd->select_number counter. The next sp->exec() call must not use the
|
||||
consumed numbers, so we remember the first free number (We know that
|
||||
nobody will use it as this execution has stopped with an error).
|
||||
*/
|
||||
if (err_status)
|
||||
set_select_number(thd->select_number);
|
||||
}
|
||||
|
||||
if (save_log_general)
|
||||
|
@ -4852,17 +4852,14 @@ extern "C" int thd_non_transactional_update(const MYSQL_THD thd)
|
||||
|
||||
extern "C" int thd_binlog_format(const MYSQL_THD thd)
|
||||
{
|
||||
#ifdef WITH_WSREP
|
||||
if (WSREP(thd))
|
||||
{
|
||||
/* for wsrep binlog format is meaningful also when binlogging is off */
|
||||
return (int) WSREP_BINLOG_FORMAT(thd->variables.binlog_format);
|
||||
return (int) thd->wsrep_binlog_format();
|
||||
}
|
||||
#endif /* WITH_WSREP */
|
||||
if (mysql_bin_log.is_open() && (thd->variables.option_bits & OPTION_BIN_LOG))
|
||||
return (int) thd->variables.binlog_format;
|
||||
else
|
||||
return BINLOG_FORMAT_UNSPEC;
|
||||
return BINLOG_FORMAT_UNSPEC;
|
||||
}
|
||||
|
||||
extern "C" void thd_mark_transaction_to_rollback(MYSQL_THD thd, bool all)
|
||||
|
@ -808,6 +808,7 @@ void lex_end_stage2(LEX *lex)
|
||||
|
||||
/* Reset LEX_MASTER_INFO */
|
||||
lex->mi.reset(lex->sql_command == SQLCOM_CHANGE_MASTER);
|
||||
delete_dynamic(&lex->delete_gtid_domain);
|
||||
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
@ -2933,6 +2934,10 @@ LEX::LEX()
|
||||
INITIAL_LEX_PLUGIN_LIST_SIZE, 0);
|
||||
reset_query_tables_list(TRUE);
|
||||
mi.init();
|
||||
init_dynamic_array2(&delete_gtid_domain, sizeof(ulong*),
|
||||
gtid_domain_static_buffer,
|
||||
initial_gtid_domain_buffer_size,
|
||||
initial_gtid_domain_buffer_size, 0);
|
||||
}
|
||||
|
||||
|
||||
|
@ -2834,6 +2834,13 @@ public:
|
||||
*/
|
||||
Item *limit_rows_examined;
|
||||
ulonglong limit_rows_examined_cnt;
|
||||
/**
|
||||
Holds a set of domain_ids for deletion at FLUSH..DELETE_DOMAIN_ID
|
||||
*/
|
||||
DYNAMIC_ARRAY delete_gtid_domain;
|
||||
static const ulong initial_gtid_domain_buffer_size= 16;
|
||||
ulong gtid_domain_static_buffer[initial_gtid_domain_buffer_size];
|
||||
|
||||
inline void set_limit_rows_examined()
|
||||
{
|
||||
if (limit_rows_examined)
|
||||
|
@ -6236,6 +6236,24 @@ finish:
|
||||
}
|
||||
if (thd->is_error() || (thd->variables.option_bits & OPTION_MASTER_SQL_ERROR))
|
||||
trans_rollback_stmt(thd);
|
||||
#ifdef WITH_WSREP
|
||||
else if (thd->spcont &&
|
||||
(thd->wsrep_conflict_state == MUST_ABORT ||
|
||||
thd->wsrep_conflict_state == CERT_FAILURE))
|
||||
{
|
||||
/*
|
||||
The error was cleared, but THD was aborted by wsrep and
|
||||
wsrep_conflict_state is still set accordingly. This
|
||||
situation is expected if we are running a stored procedure
|
||||
that declares a handler that catches ER_LOCK_DEADLOCK error.
|
||||
In which case the error may have been cleared in method
|
||||
sp_rcontext::handle_sql_condition().
|
||||
*/
|
||||
trans_rollback_stmt(thd);
|
||||
thd->wsrep_conflict_state= NO_CONFLICT;
|
||||
thd->killed= NOT_KILLED;
|
||||
}
|
||||
#endif /* WITH_WSREP */
|
||||
else
|
||||
{
|
||||
/* If commit fails, we should be able to reset the OK status. */
|
||||
|
@ -153,7 +153,10 @@ bool reload_acl_and_cache(THD *thd, unsigned long long options,
|
||||
tmp_write_to_binlog= 0;
|
||||
if (mysql_bin_log.is_open())
|
||||
{
|
||||
if (mysql_bin_log.rotate_and_purge(true))
|
||||
DYNAMIC_ARRAY *drop_gtid_domain=
|
||||
(thd && (thd->lex->delete_gtid_domain.elements > 0)) ?
|
||||
&thd->lex->delete_gtid_domain : NULL;
|
||||
if (mysql_bin_log.rotate_and_purge(true, drop_gtid_domain))
|
||||
*write_to_binlog= -1;
|
||||
|
||||
if (WSREP_ON)
|
||||
|
@ -30,7 +30,7 @@
|
||||
#include <my_dir.h>
|
||||
#include "rpl_handler.h"
|
||||
#include "debug_sync.h"
|
||||
|
||||
#include "log.h" // get_gtid_list_event
|
||||
|
||||
enum enum_gtid_until_state {
|
||||
GTID_UNTIL_NOT_DONE,
|
||||
@ -876,72 +876,6 @@ get_binlog_list(MEM_ROOT *memroot)
|
||||
DBUG_RETURN(current_list);
|
||||
}
|
||||
|
||||
/*
|
||||
Find the Gtid_list_log_event at the start of a binlog.
|
||||
|
||||
NULL for ok, non-NULL error message for error.
|
||||
|
||||
If ok, then the event is returned in *out_gtid_list. This can be NULL if we
|
||||
get back to binlogs written by old server version without GTID support. If
|
||||
so, it means we have reached the point to start from, as no GTID events can
|
||||
exist in earlier binlogs.
|
||||
*/
|
||||
static const char *
|
||||
get_gtid_list_event(IO_CACHE *cache, Gtid_list_log_event **out_gtid_list)
|
||||
{
|
||||
Format_description_log_event init_fdle(BINLOG_VERSION);
|
||||
Format_description_log_event *fdle;
|
||||
Log_event *ev;
|
||||
const char *errormsg = NULL;
|
||||
|
||||
*out_gtid_list= NULL;
|
||||
|
||||
if (!(ev= Log_event::read_log_event(cache, 0, &init_fdle,
|
||||
opt_master_verify_checksum)) ||
|
||||
ev->get_type_code() != FORMAT_DESCRIPTION_EVENT)
|
||||
{
|
||||
if (ev)
|
||||
delete ev;
|
||||
return "Could not read format description log event while looking for "
|
||||
"GTID position in binlog";
|
||||
}
|
||||
|
||||
fdle= static_cast<Format_description_log_event *>(ev);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
Log_event_type typ;
|
||||
|
||||
ev= Log_event::read_log_event(cache, 0, fdle, opt_master_verify_checksum);
|
||||
if (!ev)
|
||||
{
|
||||
errormsg= "Could not read GTID list event while looking for GTID "
|
||||
"position in binlog";
|
||||
break;
|
||||
}
|
||||
typ= ev->get_type_code();
|
||||
if (typ == GTID_LIST_EVENT)
|
||||
break; /* Done, found it */
|
||||
if (typ == START_ENCRYPTION_EVENT)
|
||||
{
|
||||
if (fdle->start_decryption((Start_encryption_log_event*) ev))
|
||||
errormsg= "Could not set up decryption for binlog.";
|
||||
}
|
||||
delete ev;
|
||||
if (typ == ROTATE_EVENT || typ == STOP_EVENT ||
|
||||
typ == FORMAT_DESCRIPTION_EVENT || typ == START_ENCRYPTION_EVENT)
|
||||
continue; /* Continue looking */
|
||||
|
||||
/* We did not find any Gtid_list_log_event, must be old binlog. */
|
||||
ev= NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
delete fdle;
|
||||
*out_gtid_list= static_cast<Gtid_list_log_event *>(ev);
|
||||
return errormsg;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Check if every GTID requested by the slave is contained in this (or a later)
|
||||
|
@ -81,7 +81,6 @@ int rpl_append_gtid_state(String *dest, bool use_binlog);
|
||||
int rpl_load_gtid_state(slave_connection_state *state, bool use_binlog);
|
||||
bool rpl_gtid_pos_check(THD *thd, char *str, size_t len);
|
||||
bool rpl_gtid_pos_update(THD *thd, char *str, size_t len);
|
||||
|
||||
#else
|
||||
|
||||
struct LOAD_FILE_IO_CACHE : public IO_CACHE { };
|
||||
|
@ -1178,6 +1178,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
|
||||
%token DEFINER_SYM
|
||||
%token DELAYED_SYM
|
||||
%token DELAY_KEY_WRITE_SYM
|
||||
%token DELETE_DOMAIN_ID_SYM
|
||||
%token DELETE_SYM /* SQL-2003-R */
|
||||
%token DENSE_RANK_SYM
|
||||
%token DESC /* SQL-2003-N */
|
||||
@ -1995,6 +1996,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
|
||||
vcol_opt_attribute_list vcol_attribute
|
||||
opt_serial_attribute opt_serial_attribute_list serial_attribute
|
||||
explainable_command
|
||||
opt_delete_gtid_domain
|
||||
END_OF_INPUT
|
||||
|
||||
%type <NONE> call sp_proc_stmts sp_proc_stmts1 sp_proc_stmt
|
||||
@ -13319,7 +13321,7 @@ flush_option:
|
||||
{ Lex->type|= REFRESH_GENERAL_LOG; }
|
||||
| SLOW LOGS_SYM
|
||||
{ Lex->type|= REFRESH_SLOW_LOG; }
|
||||
| BINARY LOGS_SYM
|
||||
| BINARY LOGS_SYM opt_delete_gtid_domain
|
||||
{ Lex->type|= REFRESH_BINARY_LOG; }
|
||||
| RELAY LOGS_SYM optional_connection_name
|
||||
{
|
||||
@ -13376,6 +13378,24 @@ opt_table_list:
|
||||
| table_list {}
|
||||
;
|
||||
|
||||
opt_delete_gtid_domain:
|
||||
/* empty */ {}
|
||||
| DELETE_DOMAIN_ID_SYM '=' '(' delete_domain_id_list ')'
|
||||
{}
|
||||
;
|
||||
delete_domain_id_list:
|
||||
/* Empty */
|
||||
| delete_domain_id
|
||||
| delete_domain_id_list ',' delete_domain_id
|
||||
;
|
||||
|
||||
delete_domain_id:
|
||||
ulong_num
|
||||
{
|
||||
insert_dynamic(&Lex->delete_gtid_domain, (uchar*) &($1));
|
||||
}
|
||||
;
|
||||
|
||||
optional_flush_tables_arguments:
|
||||
/* empty */ {$$= 0;}
|
||||
| AND_SYM DISABLE_SYM CHECKPOINT_SYM {$$= REFRESH_CHECKPOINT; }
|
||||
|
@ -507,6 +507,9 @@ wsrep_run_wsrep_commit(THD *thd, bool all)
|
||||
}
|
||||
|
||||
mysql_mutex_lock(&thd->LOCK_wsrep_thd);
|
||||
|
||||
DEBUG_SYNC(thd, "wsrep_after_replication");
|
||||
|
||||
switch(rcode) {
|
||||
case 0:
|
||||
/*
|
||||
|
@ -2021,7 +2021,7 @@ static bool abort_replicated(THD *thd)
|
||||
bool ret_code= false;
|
||||
if (thd->wsrep_query_state== QUERY_COMMITTING)
|
||||
{
|
||||
WSREP_DEBUG("aborting replicated trx: %lu", thd->real_id);
|
||||
WSREP_DEBUG("aborting replicated trx: %llu", (ulonglong)(thd->real_id));
|
||||
|
||||
(void)wsrep_abort_thd(thd, thd, TRUE);
|
||||
ret_code= true;
|
||||
|
@ -327,8 +327,9 @@ bool wsrep_provider_update (sys_var *self, THD* thd, enum_var_type type)
|
||||
if (wsrep_inited == 1)
|
||||
wsrep_deinit(false);
|
||||
|
||||
char* tmp= strdup(wsrep_provider); // wsrep_init() rewrites provider
|
||||
char* tmp= strdup(wsrep_provider); // wsrep_init() rewrites provider
|
||||
//when fails
|
||||
|
||||
if (wsrep_init())
|
||||
{
|
||||
my_error(ER_CANT_OPEN_LIBRARY, MYF(0), tmp);
|
||||
|
@ -547,14 +547,12 @@ PTABDEF OEMDEF::GetXdef(PGLOBAL g)
|
||||
} // endif dladdr
|
||||
#endif // 0
|
||||
|
||||
// Is the library already loaded?
|
||||
if (!Hdll && !(Hdll = dlopen(soname, RTLD_NOLOAD)))
|
||||
// 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
|
||||
// Load the desired shared library
|
||||
if (!Hdll && !(Hdll = dlopen(soname, RTLD_LAZY))) {
|
||||
error = dlerror();
|
||||
sprintf(g->Message, MSG(SHARED_LIB_ERR), soname, SVP(error));
|
||||
return NULL;
|
||||
} // endif Hdll
|
||||
|
||||
// The exported name is always in uppercase
|
||||
for (int i = 0; ; i++) {
|
||||
|
@ -1438,11 +1438,11 @@ row_ins_foreign_check_on_constraint(
|
||||
|
||||
#ifdef WITH_WSREP
|
||||
err = wsrep_append_foreign_key(
|
||||
thr_get_trx(thr),
|
||||
foreign,
|
||||
clust_rec,
|
||||
clust_index,
|
||||
FALSE, FALSE);
|
||||
thr_get_trx(thr),
|
||||
foreign,
|
||||
clust_rec,
|
||||
clust_index,
|
||||
FALSE, FALSE);
|
||||
if (err != DB_SUCCESS) {
|
||||
fprintf(stderr,
|
||||
"WSREP: foreign key append failed: %d\n", err);
|
||||
|
@ -15,7 +15,7 @@
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with this library; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
cmake_minimum_required(VERSION 2.6)
|
||||
project(mroonga)
|
||||
@ -51,6 +51,14 @@ if(MSVC)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(MRN_BUNDLED)
|
||||
if(WITHOUT_MROONGA OR
|
||||
WITHOUT_MROONGA_STORAGE_ENGINE OR
|
||||
"${PLUGIN_MROONGA}" STREQUAL "NO")
|
||||
return()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(MRN_BUNDLED_GROONGA_RELATIVE_DIR "vendor/groonga")
|
||||
set(MRN_BUNDLED_GROONGA_DIR
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/${MRN_BUNDLED_GROONGA_RELATIVE_DIR}")
|
||||
@ -79,6 +87,58 @@ file(READ ${MRN_SOURCE_DIR}/version_micro MRN_VERSION_MICRO)
|
||||
file(READ ${MRN_SOURCE_DIR}/version_in_hex MRN_VERSION_IN_HEX)
|
||||
file(READ ${MRN_SOURCE_DIR}/plugin_version MRN_PLUGIN_VERSION)
|
||||
|
||||
if(MRN_GROONGA_BUNDLED)
|
||||
option(MRN_GROONGA_EMBED
|
||||
"Embed libgroonga"
|
||||
ON)
|
||||
if(MRN_GROONGA_EMBED)
|
||||
set(GRN_EMBED ON)
|
||||
endif()
|
||||
|
||||
set(MRN_BUNDLED_GROONGA_NORMALIZER_MYSQL_DIR
|
||||
"${MRN_BUNDLED_GROONGA_DIR}/vendor/plugins/groonga-normalizer-mysql")
|
||||
option(MRN_GROONGA_NORMALIZER_MYSQL_EMBED
|
||||
"Embed groonga-normalizer-mysql Groonga plugin"
|
||||
ON)
|
||||
if(EXISTS ${MRN_BUNDLED_GROONGA_NORMALIZER_MYSQL_DIR})
|
||||
set(GROONGA_NORMALIZER_MYSQL_FOUND ON)
|
||||
else()
|
||||
set(GROONGA_NORMALIZER_MYSQL_FOUND OFF)
|
||||
set(MRN_GROONGA_NORMALIZER_MYSQL_EMBED OFF)
|
||||
endif()
|
||||
if(MRN_GROONGA_NORMALIZER_MYSQL_EMBED)
|
||||
set(GROONGA_NORMALIZER_MYSQL_EMBED ON)
|
||||
endif()
|
||||
|
||||
file(READ "${MRN_BUNDLED_GROONGA_DIR}/bundled_lz4_version"
|
||||
MRN_BUNDLED_LZ4_VERSION)
|
||||
string(STRIP
|
||||
"${MRN_BUNDLED_LZ4_VERSION}"
|
||||
MRN_BUNDLED_LZ4_VERSION)
|
||||
set(MRN_BUNDLED_LZ4_DIR
|
||||
"${MRN_BUNDLED_GROONGA_DIR}/vendor/lz4-${MRN_BUNDLED_LZ4_VERSION}")
|
||||
if(EXISTS ${MRN_BUNDLED_LZ4_DIR})
|
||||
set(GRN_WITH_BUNDLED_LZ4 ON)
|
||||
set(GRN_WITH_LZ4 "yes")
|
||||
else()
|
||||
set(GRN_WITH_LZ4 "no")
|
||||
endif()
|
||||
|
||||
add_subdirectory("${MRN_BUNDLED_GROONGA_RELATIVE_DIR}")
|
||||
else()
|
||||
set(MRN_GROONGA_EMBED OFF)
|
||||
|
||||
file(READ ${MRN_SOURCE_DIR}/required_groonga_version REQUIRED_GROONGA_VERSION)
|
||||
string(STRIP "${REQUIRED_GROONGA_VERSION}" REQUIRED_GROONGA_VERSION)
|
||||
|
||||
file(READ
|
||||
${MRN_SOURCE_DIR}/required_groonga_normalizer_mysql_version
|
||||
REQUIRED_GROONGA_NORMALIZER_MYSQL_VERSION)
|
||||
string(STRIP
|
||||
"${REQUIRED_GROONGA_NORMALIZER_MYSQL_VERSION}"
|
||||
REQUIRED_GROONGA_NORMALIZER_MYSQL_VERSION)
|
||||
endif()
|
||||
|
||||
set(MRN_PACKAGE_STRING "${PROJECT_NAME} ${MRN_VERSION}")
|
||||
|
||||
include(CheckCCompilerFlag)
|
||||
@ -107,18 +167,7 @@ read_file_list(${CMAKE_CURRENT_SOURCE_DIR}/udf/sources.am MRN_UDF_SOURCES)
|
||||
string(REGEX REPLACE "([^;]+)" "${MRN_RELATIVE_DIR_PREFIX}udf/\\1"
|
||||
MRN_UDF_SOURCES "${MRN_UDF_SOURCES}")
|
||||
|
||||
set(MRN_ALL_SOURCES
|
||||
${MRN_SOURCES}
|
||||
${MRN_UDF_SOURCES}
|
||||
${LIBMRN_NO_MYSQL_SOURCES}
|
||||
${LIBMRN_NEED_MYSQL_SOURCES})
|
||||
|
||||
if(MRN_BUNDLED)
|
||||
mysql_add_plugin(mroonga ${MRN_ALL_SOURCES} STORAGE_ENGINE MODULE_ONLY)
|
||||
if(NOT TARGET mroonga)
|
||||
return()
|
||||
endif()
|
||||
|
||||
set(MYSQL_SOURCE_DIR ${CMAKE_SOURCE_DIR})
|
||||
set(MYSQL_BUILD_DIR ${MYSQL_SOURCE_DIR})
|
||||
set(MYSQL_CONFIG ${CMAKE_SOURCE_DIR}/scripts/mysql_config)
|
||||
@ -134,44 +183,6 @@ else()
|
||||
endif()
|
||||
find_path(MYSQL_CONFIG "${MYSQL_CONFIG}")
|
||||
|
||||
if(MRN_GROONGA_BUNDLED)
|
||||
option(MRN_GROONGA_EMBED
|
||||
"Embed libgroonga"
|
||||
ON)
|
||||
if(MRN_GROONGA_EMBED)
|
||||
set(GRN_EMBED ON)
|
||||
endif()
|
||||
|
||||
set(MRN_BUNDLED_GROONGA_NORMALIZER_MYSQL_DIR
|
||||
"${MRN_BUNDLED_GROONGA_DIR}/vendor/plugins/groonga-normalizer-mysql")
|
||||
option(MRN_GROONGA_NORMALIZER_MYSQL_EMBED
|
||||
"Embed groonga-normalizer-mysql Groonga plugin"
|
||||
ON)
|
||||
if(EXISTS ${MRN_BUNDLED_GROONGA_NORMALIZER_MYSQL_DIR})
|
||||
set(GROONGA_NORMALIZER_MYSQL_FOUND ON)
|
||||
else()
|
||||
set(GROONGA_NORMALIZER_MYSQL_FOUND OFF)
|
||||
set(MRN_GROONGA_NORMALIZER_MYSQL_EMBED OFF)
|
||||
endif()
|
||||
if(MRN_GROONGA_NORMALIZER_MYSQL_EMBED)
|
||||
set(GROONGA_NORMALIZER_MYSQL_EMBED ON)
|
||||
endif()
|
||||
|
||||
add_subdirectory("${MRN_BUNDLED_GROONGA_RELATIVE_DIR}")
|
||||
else()
|
||||
set(MRN_GROONGA_EMBED OFF)
|
||||
|
||||
file(READ ${MRN_SOURCE_DIR}/required_groonga_version REQUIRED_GROONGA_VERSION)
|
||||
string(STRIP "${REQUIRED_GROONGA_VERSION}" REQUIRED_GROONGA_VERSION)
|
||||
|
||||
file(READ
|
||||
${MRN_SOURCE_DIR}/required_groonga_normalizer_mysql_version
|
||||
REQUIRED_GROONGA_NORMALIZER_MYSQL_VERSION)
|
||||
string(STRIP
|
||||
"${REQUIRED_GROONGA_NORMALIZER_MYSQL_VERSION}"
|
||||
REQUIRED_GROONGA_NORMALIZER_MYSQL_VERSION)
|
||||
endif()
|
||||
|
||||
if(EXISTS "${MYSQL_SOURCE_DIR}/storage/maria")
|
||||
set(MYSQL_VARIANT "MariaDB")
|
||||
else()
|
||||
@ -194,6 +205,7 @@ if(EXISTS "${MYSQL_SOURCE_DIR}/libbinlogevents")
|
||||
set(MYSQL_LIBBINLOGEVENTS_EXPORT_DIR
|
||||
"${MYSQL_SOURCE_DIR}/libbinlogevents/export")
|
||||
set(MYSQL_LIBBINLOGEVENTS_INCLUDE_DIR
|
||||
"${MYSQL_BUILD_DIR}/libbinlogevents/include"
|
||||
"${MYSQL_SOURCE_DIR}/libbinlogevents/include")
|
||||
else()
|
||||
set(MYSQL_LIBBINLOGEVENTS_EXPORT_DIR)
|
||||
@ -270,6 +282,7 @@ else()
|
||||
set(MRN_LIBRARY_DIRS
|
||||
${MRN_LIBRARY_DIRS}
|
||||
${GROONGA_LIBRARY_DIRS})
|
||||
set(MRN_LIBRARIES ${GROONGA_LIBRARIES})
|
||||
endif()
|
||||
|
||||
include_directories(
|
||||
@ -291,11 +304,17 @@ link_directories(
|
||||
${MRN_LIBRARY_DIRS}
|
||||
${MYSQL_LIBRARY_DIRS})
|
||||
|
||||
set(MRN_ALL_SOURCES
|
||||
${MRN_SOURCES}
|
||||
${MRN_UDF_SOURCES}
|
||||
${LIBMRN_NO_MYSQL_SOURCES}
|
||||
${LIBMRN_NEED_MYSQL_SOURCES})
|
||||
|
||||
if(MRN_BUNDLED)
|
||||
target_link_libraries(mroonga ${MRN_LIBRARIES})
|
||||
if(NOT TARGET mroonga)
|
||||
return()
|
||||
endif()
|
||||
mysql_add_plugin(mroonga
|
||||
${MRN_ALL_SOURCES}
|
||||
STORAGE_ENGINE MODULE_ONLY
|
||||
LINK_LIBRARIES ${MRN_LIBRARIES})
|
||||
else()
|
||||
add_library(mroonga MODULE ${MRN_ALL_SOURCES})
|
||||
|
||||
@ -340,8 +359,12 @@ else()
|
||||
MY_CHECK_AND_SET_COMPILER_FLAG("-Wno-strict-aliasing")
|
||||
MY_CHECK_AND_SET_COMPILER_FLAG("-Wno-deprecated")
|
||||
MY_CHECK_AND_SET_COMPILER_FLAG("-fno-implicit-templates")
|
||||
MY_CHECK_AND_SET_COMPILER_FLAG("-fno-exceptions")
|
||||
MY_CHECK_AND_SET_COMPILER_FLAG("-fno-rtti")
|
||||
if(("${MYSQL_VARIANT}" STREQUAL "MariaDB") OR
|
||||
("${MYSQL_VARIANT}" STREQUAL "MySQL" AND
|
||||
${MYSQL_VERSION} VERSION_LESS "5.7.0"))
|
||||
MY_CHECK_AND_SET_COMPILER_FLAG("-fno-exceptions")
|
||||
MY_CHECK_AND_SET_COMPILER_FLAG("-fno-rtti")
|
||||
endif()
|
||||
MY_CHECK_AND_SET_COMPILER_FLAG("-felide-constructors")
|
||||
MY_CHECK_AND_SET_COMPILER_FLAG("-Wno-implicit-fallthrough")
|
||||
endif()
|
||||
@ -362,10 +385,20 @@ else()
|
||||
install(TARGETS mroonga DESTINATION "${MYSQL_PLUGIN_DIR}")
|
||||
endif()
|
||||
|
||||
option(MRN_BUILD_FOR_EMBEDDED_SERVER
|
||||
"Whether to build Mroonga for embedded server or not. You can't use Mroonga built for embedded server with non embedded server."
|
||||
OFF)
|
||||
if(MRN_BUILD_FOR_EMBEDDED_SERVER)
|
||||
set_property(TARGET mroonga APPEND PROPERTY
|
||||
COMPILE_DEFINITIONS "EMBEDDED_LIBRARY")
|
||||
endif()
|
||||
|
||||
if(GROONGA_NORMALIZER_MYSQL_FOUND)
|
||||
add_definitions("-DWITH_GROONGA_NORMALIZER_MYSQL=1")
|
||||
set_property(TARGET mroonga APPEND PROPERTY
|
||||
COMPILE_DEFINITIONS "WITH_GROONGA_NORMALIZER_MYSQL=1")
|
||||
if(MRN_GROONGA_NORMALIZER_MYSQL_EMBED)
|
||||
add_definitions("-DMRN_GROONGA_NORMALIZER_MYSQL_EMBEDDED")
|
||||
set_property(TARGET mroonga APPEND PROPERTY
|
||||
COMPILE_DEFINITIONS "MRN_GROONGA_NORMALIZER_MYSQL_EMBEDDED")
|
||||
else()
|
||||
set_property(TARGET mroonga APPEND PROPERTY
|
||||
COMPILE_DEFINITIONS "GROONGA_NORMALIZER_MYSQL_PLUGIN_NAME=\"normalizers/mysql\"")
|
||||
@ -373,7 +406,8 @@ if(GROONGA_NORMALIZER_MYSQL_FOUND)
|
||||
endif()
|
||||
|
||||
if(MRN_GROONGA_EMBED)
|
||||
add_definitions("-DMRN_GROONGA_EMBEDDED")
|
||||
set_property(TARGET mroonga APPEND PROPERTY
|
||||
COMPILE_DEFINITIONS "MRN_GROONGA_EMBEDDED")
|
||||
endif()
|
||||
|
||||
set(MRN_DEFAULT_PARSER "" CACHE STRING
|
||||
@ -419,6 +453,8 @@ else()
|
||||
set(MRN_DATA_DIR "share/${PROJECT_NAME}")
|
||||
endif()
|
||||
install(FILES
|
||||
"${PROJECT_SOURCE_DIR}/AUTHORS"
|
||||
"${PROJECT_SOURCE_DIR}/COPYING"
|
||||
"${PROJECT_BINARY_DIR}/data/install.sql"
|
||||
"${PROJECT_SOURCE_DIR}/data/uninstall.sql"
|
||||
DESTINATION "${MRN_DATA_DIR}/")
|
||||
|
@ -1,9 +1,9 @@
|
||||
ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_ARGS}
|
||||
AUTOMAKE_OPTIONS = 1.9.7
|
||||
|
||||
LOCALES = ja
|
||||
|
||||
AM_CPPFLAGS = $(MYSQL_INCLUDES) $(GROONGA_CFLAGS) -I$(top_srcdir)/lib
|
||||
ACLOCAL_AMFLAGS = $$ACLOCAL_ARGS
|
||||
|
||||
include sources.am
|
||||
|
||||
@ -49,7 +49,13 @@ tag:
|
||||
cd $(top_srcdir) && \
|
||||
git tag v$(VERSION) -a -m 'Mroonga $(VERSION)!!!'
|
||||
|
||||
update-latest-release: misc
|
||||
ensure-cutter-source-path:
|
||||
@if test -z "$(CUTTER_SOURCE_PATH)"; then \
|
||||
echo "\$$(CUTTER_SOURCE_PATH) is missing"; \
|
||||
exit 1; \
|
||||
fi
|
||||
|
||||
update-latest-release: ensure-cutter-source-path
|
||||
@if test -z "$(OLD_RELEASE)"; then \
|
||||
echo "\$$(OLD_RELEASE) is missing"; \
|
||||
exit 1; \
|
||||
@ -63,17 +69,40 @@ update-latest-release: misc
|
||||
exit 1; \
|
||||
fi
|
||||
cd $(top_srcdir) && \
|
||||
misc/update-latest-release.rb \
|
||||
"$(CUTTER_SOURCE_PATH)/misc/update-latest-release.rb" \
|
||||
$(PACKAGE) $(OLD_RELEASE) $(OLD_RELEASE_DATE) \
|
||||
$(VERSION) $(NEW_RELEASE_DATE) \
|
||||
packages/rpm/centos/mariadb-mroonga.spec.in \
|
||||
packages/rpm/centos/mariadb-10.1-mroonga.spec.in \
|
||||
packages/rpm/centos/mariadb-10.2-mroonga.spec.in \
|
||||
packages/rpm/centos/mysql55-mroonga.spec.in \
|
||||
packages/rpm/centos/mysql56-community-mroonga.spec.in \
|
||||
packages/debian/changelog \
|
||||
packages/rpm/centos/mysql57-community-mroonga.spec.in \
|
||||
packages/rpm/centos/percona-server-56-mroonga.spec.in \
|
||||
packages/rpm/centos/percona-server-57-mroonga.spec.in \
|
||||
doc/source/install/*.rst \
|
||||
doc/locale/*/LC_MESSAGES/install.po \
|
||||
$(MROONGA_GITHUB_COM_PATH)/index.html \
|
||||
$(MROONGA_GITHUB_COM_PATH)/ja/index.html
|
||||
$(MROONGA_GITHUB_COM_PATH)/_config.yml
|
||||
cd $(top_srcdir) && \
|
||||
"$(CUTTER_SOURCE_PATH)/misc/update-latest-release.rb" \
|
||||
$(PACKAGE)-5.5 $(OLD_RELEASE) $(OLD_RELEASE_DATE) \
|
||||
$(VERSION) $(NEW_RELEASE_DATE) \
|
||||
packages/debian-5.5/changelog
|
||||
cd $(top_srcdir) && \
|
||||
"$(CUTTER_SOURCE_PATH)/misc/update-latest-release.rb" \
|
||||
$(PACKAGE)-5.6 $(OLD_RELEASE) $(OLD_RELEASE_DATE) \
|
||||
$(VERSION) $(NEW_RELEASE_DATE) \
|
||||
packages/debian-5.6/changelog
|
||||
cd $(top_srcdir) && \
|
||||
"$(CUTTER_SOURCE_PATH)/misc/update-latest-release.rb" \
|
||||
$(PACKAGE)-5.7 $(OLD_RELEASE) $(OLD_RELEASE_DATE) \
|
||||
$(VERSION) $(NEW_RELEASE_DATE) \
|
||||
packages/debian-5.7/changelog
|
||||
cd $(top_srcdir) && \
|
||||
"$(CUTTER_SOURCE_PATH)/misc/update-latest-release.rb" \
|
||||
$(PACKAGE)-mariadb-10.0 $(OLD_RELEASE) $(OLD_RELEASE_DATE) \
|
||||
$(VERSION) $(NEW_RELEASE_DATE) \
|
||||
packages/debian-mariadb-10.0/changelog
|
||||
|
||||
update-po:
|
||||
@for lang in $(LOCALES); do \
|
||||
@ -144,10 +173,3 @@ upload-to-github:
|
||||
|
||||
echo-cutter:
|
||||
echo $(CUTTER)
|
||||
|
||||
misc:
|
||||
@if test -z "$(CUTTER_SOURCE_PATH)"; then \
|
||||
echo "\$$(CUTTER_SOURCE_PATH) is missing"; \
|
||||
exit 1; \
|
||||
fi
|
||||
ln -s "$(CUTTER_SOURCE_PATH)/misc" misc
|
||||
|
@ -1,54 +1,63 @@
|
||||
version: "{build}"
|
||||
clone_depth: 10
|
||||
environment:
|
||||
global:
|
||||
MARIADB_VERSION: 10.1.26
|
||||
matrix:
|
||||
- CMAKE_GENERATOR_NAME: "Visual Studio 14 2015"
|
||||
- CMAKE_GENERATOR_NAME: "Visual Studio 14 2015 Win64"
|
||||
|
||||
install:
|
||||
- cd ..
|
||||
- choco install -y curl 7zip.commandline
|
||||
- curl -O http://mirror.jmu.edu/pub/mariadb/mariadb-10.0.20/source/mariadb-10.0.20.tar.gz
|
||||
- 7z x mariadb-10.0.20.tar.gz
|
||||
- 7z x mariadb-10.0.20.tar > nul
|
||||
- cd mariadb-10.0.20
|
||||
- curl -O http://mirror.jmu.edu/pub/mariadb/mariadb-%MARIADB_VERSION%/source/mariadb-%MARIADB_VERSION%.tar.gz
|
||||
- 7z x mariadb-%MARIADB_VERSION%.tar.gz
|
||||
- 7z x mariadb-%MARIADB_VERSION%.tar > nul
|
||||
- cd mariadb-%MARIADB_VERSION%
|
||||
- rmdir /S /Q storage\mroonga\
|
||||
- move ..\mroonga storage\mroonga
|
||||
- git clone --quiet --depth 1 https://github.com/groonga/groonga.git ..\groonga
|
||||
- cd ..\groonga
|
||||
- git submodule update --init
|
||||
- cd ..\mariadb-10.0.20
|
||||
- git clone --quiet --depth 1 --recursive https://github.com/groonga/groonga.git ..\groonga
|
||||
- rmdir /S /Q ..\groonga\test\
|
||||
- cd ..\groonga\vendor
|
||||
- c:\Ruby22-x64\bin\ruby -v download_lz4.rb
|
||||
- c:\Ruby22-x64\bin\ruby -v download_mecab.rb
|
||||
- cd ..\..\mariadb-%MARIADB_VERSION%
|
||||
- mkdir storage\mroonga\vendor
|
||||
- move ..\groonga storage\mroonga\vendor\groonga
|
||||
- git clone --quiet --depth 1 https://github.com/groonga/groonga-normalizer-mysql.git storage\mroonga\vendor\groonga\vendor\plugins\groonga-normalizer-mysql
|
||||
build_script:
|
||||
- "echo # > win\\packaging\\CMakeLists.txt"
|
||||
- cmake . -G "Visual Studio 12 Win64"
|
||||
- cmake . -G "%CMAKE_GENERATOR_NAME%"
|
||||
-DCMAKE_BUILD_TYPE=Debug
|
||||
-DWITHOUT_ARCHIVE=ON
|
||||
-DWITHOUT_BLACKHOLE=ON
|
||||
-DWITHOUT_CASSANDRA=ON
|
||||
-DWITHOUT_CONNECT=ON
|
||||
-DWITHOUT_CSV=ON
|
||||
-DWITHOUT_EXAMPLE=ON
|
||||
-DWITHOUT_FEDERATED=ON
|
||||
-DWITHOUT_FEDERATEDX=ON
|
||||
-DWITHOUT_HEAP=ON
|
||||
-DWITHOUT_INNOBASE=ON
|
||||
-DWITHOUT_MYISAM=ON
|
||||
-DWITHOUT_MYISAMMRG=ON
|
||||
-DWITHOUT_OQGRAPH=ON
|
||||
-DWITHOUT_PERFSCHEMA=OFF
|
||||
-DWITHOUT_SEQUENCE=ON
|
||||
-DWITHOUT_SPHINX=ON
|
||||
-DWITHOUT_SPIDER=ON
|
||||
-DWITHOUT_TEST_SQL_DISCOVERY=ON
|
||||
-DWITHOUT_TOKUDB=ON
|
||||
-DWITHOUT_XTRADB=ON
|
||||
-DPLUGIN_ARCHIVE=NO
|
||||
-DPLUGIN_BLACKHOLE=NO
|
||||
-DPLUGIN_CASSANDRA=NO
|
||||
-DPLUGIN_CONNECT=NO
|
||||
-DPLUGIN_CSV=NO
|
||||
-DPLUGIN_EXAMPLE=NO
|
||||
-DPLUGIN_FEDERATED=NO
|
||||
-DPLUGIN_FEDERATEDX=NO
|
||||
-DPLUGIN_HEAP=NO
|
||||
-DPLUGIN_INNOBASE=NO
|
||||
-DPLUGIN_MYISAM=NO
|
||||
-DPLUGIN_MYISAMMRG=NO
|
||||
-DPLUGIN_OQGRAPH=NO
|
||||
-DPLUGIN_PERFSCHEMA=NO
|
||||
-DPLUGIN_SEQUENCE=NO
|
||||
-DPLUGIN_SPHINX=NO
|
||||
-DPLUGIN_SPIDER=NO
|
||||
-DPLUGIN_TEST_SQL_DISCOVERY=NO
|
||||
-DPLUGIN_TOKUDB=NO
|
||||
-DPLUGIN_XTRADB=NO
|
||||
-DWITH_UNIT_TESTS=OFF
|
||||
-DWITH_MARIABACKUP=OFF
|
||||
-DGRN_WITH_BUNDLED_MECAB=ON
|
||||
- cmake --build . --config Debug
|
||||
|
||||
notifications:
|
||||
- provider: Email
|
||||
to:
|
||||
- groonga-mysql-commit@lists.sourceforge.jp
|
||||
- kou@clear-code.com
|
||||
on_build_status_changed: true
|
||||
|
||||
test: off
|
||||
|
@ -1,116 +1,11 @@
|
||||
#!/bin/sh
|
||||
|
||||
warn() {
|
||||
echo " WARNING: $@" 1>&2
|
||||
}
|
||||
|
||||
# init
|
||||
|
||||
LIBTOOLIZE=libtoolize
|
||||
ACLOCAL=aclocal
|
||||
AUTOCONF=autoconf
|
||||
AUTOHEADER=autoheader
|
||||
AUTOMAKE=automake
|
||||
|
||||
case `uname -s` in
|
||||
Darwin)
|
||||
LIBTOOLIZE=glibtoolize
|
||||
;;
|
||||
case $(uname -s) in
|
||||
FreeBSD)
|
||||
ACLOCAL_ARGS="$ACLOCAL_ARGS -I /usr/local/share/aclocal/"
|
||||
;;
|
||||
ACLOCAL_ARGS="$ACLOCAL_ARGS -I /usr/local/share/aclocal/"
|
||||
;;
|
||||
esac
|
||||
|
||||
mkdir -p m4
|
||||
|
||||
# libtoolize
|
||||
echo "Searching libtoolize..."
|
||||
if [ `which $LIBTOOLIZE` ] ; then
|
||||
echo " FOUND: libtoolize -> $LIBTOOLIZE"
|
||||
else
|
||||
warn "Cannot Found libtoolize... input libtool command"
|
||||
read LIBTOOLIZE
|
||||
LIBTOOLIZE=`which $LIBTOOLIZE`
|
||||
if [ `which $LIBTOOLIZE` ] ; then
|
||||
echo " SET: libtoolize -> $LIBTOOLIZE"
|
||||
else
|
||||
warn "$LIBTOOLIZE: Command not found."
|
||||
exit 1;
|
||||
fi
|
||||
fi
|
||||
|
||||
# aclocal
|
||||
echo "Searching aclocal..."
|
||||
if [ `which $ACLOCAL` ] ; then
|
||||
echo " FOUND: aclocal -> $ACLOCAL"
|
||||
else
|
||||
warn "Cannot Found aclocal... input aclocal command"
|
||||
read ACLOCAL
|
||||
ACLOCAL=`which $ACLOCAL`
|
||||
if [ `which $ACLOCAL` ] ; then
|
||||
echo " SET: aclocal -> $ACLOCAL"
|
||||
else
|
||||
warn "$ACLOCAL: Command not found."
|
||||
exit 1;
|
||||
fi
|
||||
fi
|
||||
|
||||
# automake
|
||||
echo "Searching automake..."
|
||||
if [ `which $AUTOMAKE` ] ; then
|
||||
echo " FOUND: automake -> $AUTOMAKE"
|
||||
else
|
||||
warn "Cannot Found automake... input automake command"
|
||||
read AUTOMAKE
|
||||
ACLOCAL=`which $AUTOMAKE`
|
||||
if [ `which $AUTOMAKE` ] ; then
|
||||
echo " SET: automake -> $AUTOMAKE"
|
||||
else
|
||||
warn "$AUTOMAKE: Command not found."
|
||||
exit 1;
|
||||
fi
|
||||
fi
|
||||
|
||||
# autoheader
|
||||
echo "Searching autoheader..."
|
||||
if [ `which $AUTOHEADER` ] ; then
|
||||
echo " FOUND: autoheader -> $AUTOHEADER"
|
||||
else
|
||||
warn "Cannot Found autoheader... input autoheader command"
|
||||
read AUTOHEADER
|
||||
ACLOCAL=`which $AUTOHEADER`
|
||||
if [ `which $AUTOHEADER` ] ; then
|
||||
echo " SET: autoheader -> $AUTOHEADER"
|
||||
else
|
||||
warn "$AUTOHEADER: Command not found."
|
||||
exit 1;
|
||||
fi
|
||||
fi
|
||||
|
||||
# autoconf
|
||||
echo "Searching autoconf..."
|
||||
if [ `which $AUTOCONF` ] ; then
|
||||
echo " FOUND: autoconf -> $AUTOCONF"
|
||||
else
|
||||
warn "Cannot Found autoconf... input autoconf command"
|
||||
read AUTOCONF
|
||||
ACLOCAL=`which $AUTOCONF`
|
||||
if [ `which $AUTOCONF` ] ; then
|
||||
echo " SET: autoconf -> $AUTOCONF"
|
||||
else
|
||||
warn "$AUTOCONF: Command not found."
|
||||
exit 1;
|
||||
fi
|
||||
fi
|
||||
|
||||
set -e
|
||||
|
||||
echo "Running libtoolize ..."
|
||||
$LIBTOOLIZE --force --copy
|
||||
echo "Running aclocal ..."
|
||||
$ACLOCAL ${ACLOCAL_ARGS}
|
||||
echo "Running autoheader..."
|
||||
$AUTOHEADER
|
||||
echo "Running automake ..."
|
||||
$AUTOMAKE --add-missing --copy
|
||||
echo "Running autoconf ..."
|
||||
$AUTOCONF
|
||||
${AUTORECONF:-autoreconf} --force --install "$@"
|
||||
|
@ -10,10 +10,8 @@ PAPEROPT_a4 = -D latex_paper_size=a4
|
||||
PAPEROPT_letter = -D latex_paper_size=letter
|
||||
ALLSPHINXOPTS = $(PAPEROPT_$(PAPER)) -E $(SPHINXOPTS) $(SOURCE_DIR)
|
||||
|
||||
SPHINX_DIR = $(abs_top_builddir)/doc/sphinx
|
||||
SPHINX_BUILD_COMMAND = \
|
||||
DOCUMENT_VERSION="$(DOCUMENT_VERSION)" \
|
||||
DOCUMENT_VERSION_FULL="$(DOCUMENT_VERSION_FULL)" \
|
||||
LOCALE="$(LOCALE)" \
|
||||
PYTHONPATH="$(SPHINX_DIR):$$PYTHONPATH" \
|
||||
$(SPHINX_BUILD)
|
||||
|
@ -12,7 +12,7 @@
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with this library; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
MYSQL_SOURCE_DIR="@MYSQL_SOURCE_DIR@"
|
||||
MYSQL_BUILD_DIR="@MYSQL_BUILD_DIR@"
|
||||
|
@ -8,6 +8,7 @@ m4_define([mrn_version_in_hex], m4_include(version_in_hex))
|
||||
m4_define([mrn_plugin_version], m4_include(plugin_version))
|
||||
|
||||
AC_INIT([mroonga], [mrn_version], [groonga-talk@lists.sourceforge.net])
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
AC_CONFIG_HEADERS([config.h])
|
||||
|
||||
AM_INIT_AUTOMAKE([tar-pax foreign subdir-objects])
|
||||
@ -173,18 +174,27 @@ AC_DEFUN([CONFIG_OPTION_MYSQL],[
|
||||
MYSQL_INCLUDES=""
|
||||
MYSQL_INCLUDES="$MYSQL_INCLUDES -I$ac_mysql_build_dir/include"
|
||||
MYSQL_INCLUDES="$MYSQL_INCLUDES -I$ac_mysql_source_dir/sql"
|
||||
if test -d "$ac_mysql_source_dir/sql/auth"; then
|
||||
MYSQL_INCLUDES="$MYSQL_INCLUDES -I$ac_mysql_source_dir/sql/auth"
|
||||
fi
|
||||
MYSQL_INCLUDES="$MYSQL_INCLUDES -I$ac_mysql_source_dir/include"
|
||||
if test -d "$ac_mysql_source_dir/extra/rapidjson"; then
|
||||
mysql_rapidjson_include_dir="$ac_mysql_source_dir/extra/rapidjson/include"
|
||||
MYSQL_INCLUDES="$MYSQL_INCLUDES -I$mysql_rapidjson_include_dir"
|
||||
fi
|
||||
if test -d "$ac_mysql_source_dir/pcre"; then
|
||||
mysql_regex_include_dir="$ac_mysql_source_dir/pcre"
|
||||
if test -d "$ac_mysql_source_dir/extra/regex"; then
|
||||
mysql_regex_include_dir="$ac_mysql_source_dir/extra/regex"
|
||||
MYSQL_INCLUDES="$MYSQL_INCLUDES -I$mysql_regex_include_dir"
|
||||
else
|
||||
mysql_regex_include_dir="$ac_mysql_source_dir/regex"
|
||||
if test -d "$ac_mysql_source_dir/pcre"; then
|
||||
mysql_regex_include_dir="$ac_mysql_source_dir/pcre"
|
||||
else
|
||||
mysql_regex_include_dir="$ac_mysql_source_dir/regex"
|
||||
fi
|
||||
MYSQL_INCLUDES="$MYSQL_INCLUDES -I$mysql_regex_include_dir"
|
||||
fi
|
||||
MYSQL_INCLUDES="$MYSQL_INCLUDES -I$mysql_regex_include_dir"
|
||||
if test -d "$ac_mysql_source_dir/libbinlogevents"; then
|
||||
MYSQL_INCLUDES="$MYSQL_INCLUDES -I$ac_mysql_build_dir/libbinlogevents/include"
|
||||
MYSQL_INCLUDES="$MYSQL_INCLUDES -I$ac_mysql_source_dir/libbinlogevents/export"
|
||||
MYSQL_INCLUDES="$MYSQL_INCLUDES -I$ac_mysql_source_dir/libbinlogevents/include"
|
||||
fi
|
||||
@ -199,7 +209,7 @@ AC_DEFUN([CONFIG_OPTION_MYSQL],[
|
||||
|
||||
MYSQL_CXXFLAGS="-fno-implicit-templates -felide-constructors"
|
||||
case "$MYSQL_MAJOR_MINOR_VERSION" in
|
||||
5.7)
|
||||
5.7|8.*)
|
||||
:
|
||||
;;
|
||||
*)
|
||||
@ -381,6 +391,13 @@ AC_ARG_WITH(rsync-path,
|
||||
[RSYNC_PATH="packages@packages.groonga.org:public"])
|
||||
AC_SUBST(RSYNC_PATH)
|
||||
|
||||
AC_ARG_WITH(launchpad-ppa,
|
||||
[AS_HELP_STRING([--with-launchpad-ppa=PPA],
|
||||
[specify Launchpad Personal Package Archive. [default=groonga-ppa]])],
|
||||
[LAUNCHPAD_PPA="$withval"],
|
||||
[LAUNCHPAD_PPA="groonga-ppa"])
|
||||
AC_SUBST(LAUNCHPAD_PPA)
|
||||
|
||||
AC_ARG_WITH(launchpad-uploader-pgp-key,
|
||||
[AS_HELP_STRING([--with-launchpad-uploader-pgp-key=KEY],
|
||||
[specify PGP key UID to upload Groonga packages to Launchpad.])],
|
||||
@ -429,7 +446,7 @@ if test x"$enable_document" != x"no"; then
|
||||
AC_PATH_PROG(SPHINX_BUILD, sphinx-build, [])
|
||||
if test -n "$SPHINX_BUILD"; then
|
||||
sphinx_build_version=`"$SPHINX_BUILD" --version`
|
||||
if ! echo "$sphinx_build_version" | grep -q ' 1\.[[23]]'; then
|
||||
if ! echo "$sphinx_build_version" | grep -q ' 1\.[[2-6]]'; then
|
||||
AC_MSG_ERROR([
|
||||
sphinx-build is old: $sphinx_build_version
|
||||
Sphinx 1.2 or later is required.])
|
||||
@ -509,12 +526,19 @@ AC_OUTPUT([
|
||||
mrn_version.h
|
||||
mysql-test/mroonga/storage/information_schema/r/plugins.result
|
||||
mysql-test/mroonga/storage/variable/r/version.result
|
||||
packages/debian/control
|
||||
packages/debian-5.5/control
|
||||
packages/debian-5.6/control
|
||||
packages/debian-5.7/control
|
||||
packages/debian-mariadb-10.0/control
|
||||
packages/apt/env.sh
|
||||
packages/rpm/centos/mysql55-mroonga.spec
|
||||
packages/rpm/centos/mysql56-community-mroonga.spec
|
||||
packages/rpm/centos/mysql57-community-mroonga.spec
|
||||
packages/rpm/centos/mariadb-mroonga.spec
|
||||
packages/rpm/centos/mariadb-10.1-mroonga.spec
|
||||
packages/rpm/centos/mariadb-10.2-mroonga.spec
|
||||
packages/rpm/centos/percona-server-56-mroonga.spec
|
||||
packages/rpm/centos/percona-server-57-mroonga.spec
|
||||
packages/yum/env.sh
|
||||
data/install.sql
|
||||
])
|
||||
|
@ -17,3 +17,19 @@ CREATE FUNCTION mroonga_command RETURNS STRING
|
||||
DROP FUNCTION IF EXISTS mroonga_escape;
|
||||
CREATE FUNCTION mroonga_escape RETURNS STRING
|
||||
SONAME 'ha_mroonga@MRN_PLUGIN_SUFFIX@';
|
||||
|
||||
DROP FUNCTION IF EXISTS mroonga_snippet_html;
|
||||
CREATE FUNCTION mroonga_snippet_html RETURNS STRING
|
||||
SONAME 'ha_mroonga@MRN_PLUGIN_SUFFIX@';
|
||||
|
||||
DROP FUNCTION IF EXISTS mroonga_normalize;
|
||||
CREATE FUNCTION mroonga_normalize RETURNS STRING
|
||||
SONAME 'ha_mroonga@MRN_PLUGIN_SUFFIX@';
|
||||
|
||||
DROP FUNCTION IF EXISTS mroonga_highlight_html;
|
||||
CREATE FUNCTION mroonga_highlight_html RETURNS STRING
|
||||
SONAME 'ha_mroonga@MRN_PLUGIN_SUFFIX@';
|
||||
|
||||
DROP FUNCTION IF EXISTS mroonga_query_expand;
|
||||
CREATE FUNCTION mroonga_query_expand RETURNS STRING
|
||||
SONAME 'ha_mroonga@MRN_PLUGIN_SUFFIX@';
|
||||
|
@ -2,6 +2,10 @@ DROP FUNCTION IF EXISTS last_insert_grn_id;
|
||||
DROP FUNCTION IF EXISTS mroonga_snippet;
|
||||
DROP FUNCTION IF EXISTS mroonga_command;
|
||||
DROP FUNCTION IF EXISTS mroonga_escape;
|
||||
DROP FUNCTION IF EXISTS mroonga_snippet_html;
|
||||
DROP FUNCTION IF EXISTS mroonga_normalize;
|
||||
DROP FUNCTION IF EXISTS mroonga_highlight_html;
|
||||
DROP FUNCTION IF EXISTS mroonga_query_expand;
|
||||
|
||||
UNINSTALL PLUGIN Mroonga;
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -13,3 +13,6 @@ EXPORTS
|
||||
mroonga_escape
|
||||
mroonga_escape_init
|
||||
mroonga_escape_deinit
|
||||
mroonga_normalize
|
||||
mroonga_normalize_init
|
||||
mroonga_normalize_deinit
|
||||
|
@ -32,6 +32,14 @@ extern "C" {
|
||||
|
||||
#include <groonga.h>
|
||||
#include "mrn_mysql_compat.h"
|
||||
#include <mrn_operations.hpp>
|
||||
#include <mrn_database.hpp>
|
||||
|
||||
#if __cplusplus >= 201402
|
||||
# define mrn_override override
|
||||
#else
|
||||
# define mrn_override
|
||||
#endif
|
||||
|
||||
#if (MYSQL_VERSION_ID >= 50514 && MYSQL_VERSION_ID < 50600)
|
||||
# define MRN_HANDLER_HAVE_FINAL_ADD_INDEX 1
|
||||
@ -102,6 +110,13 @@ extern "C" {
|
||||
# define MRN_HAVE_HA_EXTRA_PREPARE_FOR_FORCED_CLOSE
|
||||
#endif
|
||||
|
||||
#if (!defined(MRN_MARIADB_P) && MYSQL_VERSION_ID >= 80002)
|
||||
#define MRN_HAVE_HA_EXTRA_SKIP_SERIALIZABLE_DD_VIEW
|
||||
#define MRN_HAVE_HA_EXTRA_BEGIN_ALTER_COPY
|
||||
#define MRN_HAVE_HA_EXTRA_END_ALTER_COPY
|
||||
#define MRN_HAVE_HA_EXTRA_NO_AUTOINC_LOCKING
|
||||
#endif
|
||||
|
||||
#if MYSQL_VERSION_ID >= 50607 && \
|
||||
(!defined(MRN_MARIADB_P) || MYSQL_VERSION_ID < 100008)
|
||||
# define MRN_HAVE_HA_EXTRA_EXPORT
|
||||
@ -196,6 +211,10 @@ extern "C" {
|
||||
# define MRN_FOREIGN_KEY_USE_CONST_STRING
|
||||
#endif
|
||||
|
||||
#if MYSQL_VERSION_ID >= 100203 && defined(MRN_MARIADB_P)
|
||||
# define MRN_FOREIGN_KEY_USE_METHOD_ENUM
|
||||
#endif
|
||||
|
||||
#if MYSQL_VERSION_ID < 50706 || defined(MRN_MARIADB_P)
|
||||
# define MRN_HANDLER_IS_FATAL_ERROR_HAVE_FLAGS
|
||||
#endif
|
||||
@ -204,6 +223,45 @@ extern "C" {
|
||||
# define MRN_HANDLER_HAVE_RESET_AUTO_INCREMENT
|
||||
#endif
|
||||
|
||||
#if (!defined(MRN_MARIADB_P) && MYSQL_VERSION_ID >= 50709) || \
|
||||
(defined(MRN_MARIADB_P) && MYSQL_VERSION_ID >= 100203)
|
||||
# define MRN_ALTER_INPLACE_INFO_ALTER_STORED_COLUMN_TYPE \
|
||||
Alter_inplace_info::ALTER_STORED_COLUMN_TYPE
|
||||
# define MRN_ALTER_INPLACE_INFO_ALTER_STORED_COLUMN_ORDER \
|
||||
Alter_inplace_info::ALTER_STORED_COLUMN_ORDER
|
||||
#else
|
||||
# define MRN_ALTER_INPLACE_INFO_ALTER_STORED_COLUMN_TYPE \
|
||||
Alter_inplace_info::ALTER_COLUMN_TYPE
|
||||
# define MRN_ALTER_INPLACE_INFO_ALTER_STORED_COLUMN_ORDER \
|
||||
Alter_inplace_info::ALTER_COLUMN_ORDER
|
||||
#endif
|
||||
|
||||
#if MYSQL_VERSION_ID >= 50700 && !defined(MRN_MARIADB_P)
|
||||
# define MRN_HANDLER_RECORDS_RETURN_ERROR
|
||||
#endif
|
||||
|
||||
#if MYSQL_VERSION_ID < 80002 || defined(MRN_MARIADB_P)
|
||||
# define MRN_HANDLER_HAVE_KEYS_TO_USE_FOR_SCANNING
|
||||
#endif
|
||||
|
||||
#if (!defined(MRN_MARIADB_P) && MYSQL_VERSION_ID >= 80002)
|
||||
# define MRN_ST_MYSQL_PLUGIN_HAVE_CHECK_UNINSTALL
|
||||
#endif
|
||||
|
||||
#if (!defined(MRN_MARIADB_P) && MYSQL_VERSION_ID >= 80002)
|
||||
# define MRN_HANDLER_OPEN_HAVE_TABLE_DEFINITION
|
||||
# define MRN_HANDLER_CREATE_HAVE_TABLE_DEFINITION
|
||||
#endif
|
||||
|
||||
#if (!defined(MRN_MARIADB_P) && MYSQL_VERSION_ID >= 80002)
|
||||
# define MRN_HANDLERTON_CREATE_HAVE_PARTITIONED
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_PSI_INTERFACE) && \
|
||||
(MYSQL_VERSION_ID < 80002 || defined(MRN_MARIADB_P))
|
||||
# define MRN_HAVE_PSI_SERVER
|
||||
#endif
|
||||
|
||||
class ha_mroonga;
|
||||
|
||||
/* structs */
|
||||
@ -347,6 +405,8 @@ private:
|
||||
// for ft in where clause test
|
||||
Item_func_match *current_ft_item;
|
||||
|
||||
mrn::Operations *operations_;
|
||||
|
||||
public:
|
||||
ha_mroonga(handlerton *hton, TABLE_SHARE *share_arg);
|
||||
~ha_mroonga();
|
||||
@ -357,8 +417,20 @@ public:
|
||||
ulonglong table_flags() const; // required
|
||||
ulong index_flags(uint idx, uint part, bool all_parts) const; // required
|
||||
|
||||
int create(const char *name, TABLE *form, HA_CREATE_INFO *info); // required
|
||||
int open(const char *name, int mode, uint test_if_locked); // required
|
||||
// required
|
||||
int create(const char *name, TABLE *form, HA_CREATE_INFO *info
|
||||
#ifdef MRN_HANDLER_CREATE_HAVE_TABLE_DEFINITION
|
||||
,
|
||||
dd::Table *table_def
|
||||
#endif
|
||||
) mrn_override;
|
||||
// required
|
||||
int open(const char *name, int mode, uint open_options
|
||||
#ifdef MRN_HANDLER_OPEN_HAVE_TABLE_DEFINITION
|
||||
,
|
||||
const dd::Table *table_def
|
||||
#endif
|
||||
) mrn_override;
|
||||
#ifndef MRN_HANDLER_HAVE_HA_CLOSE
|
||||
int close(); // required
|
||||
#endif
|
||||
@ -419,11 +491,6 @@ public:
|
||||
#endif
|
||||
int index_next_same(uchar *buf, const uchar *key, uint keylen);
|
||||
|
||||
int read_range_first(const key_range *start_key,
|
||||
const key_range *end_key,
|
||||
bool eq_range, bool sorted);
|
||||
int read_range_next();
|
||||
|
||||
int ft_init();
|
||||
FT_INFO *ft_init_ext(uint flags, uint inx, String *key);
|
||||
int ft_read(uchar *buf);
|
||||
@ -469,7 +536,9 @@ public:
|
||||
int truncate();
|
||||
double scan_time();
|
||||
double read_time(uint index, uint ranges, ha_rows rows);
|
||||
#ifdef MRN_HANDLER_HAVE_KEYS_TO_USE_FOR_SCANNING
|
||||
const key_map *keys_to_use_for_scanning();
|
||||
#endif
|
||||
ha_rows estimate_rows_upper_bound();
|
||||
void update_create_info(HA_CREATE_INFO* create_info);
|
||||
int rename_table(const char *from, const char *to);
|
||||
@ -518,6 +587,11 @@ public:
|
||||
int start_stmt(THD *thd, thr_lock_type lock_type);
|
||||
|
||||
protected:
|
||||
#ifdef MRN_HANDLER_RECORDS_RETURN_ERROR
|
||||
int records(ha_rows *num_rows);
|
||||
#else
|
||||
ha_rows records();
|
||||
#endif
|
||||
#ifdef MRN_HANDLER_HAVE_HA_RND_NEXT
|
||||
int rnd_next(uchar *buf);
|
||||
#endif
|
||||
@ -580,6 +654,9 @@ private:
|
||||
|
||||
bool have_unique_index();
|
||||
|
||||
bool is_foreign_key_field(const char *table_name,
|
||||
const char *field_name);
|
||||
|
||||
void push_warning_unsupported_spatial_index_search(enum ha_rkey_function flag);
|
||||
void clear_cursor();
|
||||
void clear_cursor_geo();
|
||||
@ -592,7 +669,8 @@ private:
|
||||
void remove_grn_obj_force(const char *name);
|
||||
int drop_index(MRN_SHARE *target_share, uint key_index);
|
||||
int drop_indexes_normal(const char *table_name, grn_obj *table);
|
||||
int drop_indexes_multiple(const char *table_name, grn_obj *table);
|
||||
int drop_indexes_multiple(const char *table_name, grn_obj *table,
|
||||
const char *index_table_name_separator);
|
||||
int drop_indexes(const char *table_name);
|
||||
bool find_column_flags(Field *field, MRN_SHARE *mrn_share, int i,
|
||||
grn_obj_flags *column_flags);
|
||||
@ -600,9 +678,10 @@ private:
|
||||
int error_code);
|
||||
grn_obj *find_tokenizer(KEY *key, MRN_SHARE *mrn_share, int i);
|
||||
grn_obj *find_tokenizer(const char *name, int name_length);
|
||||
bool have_custom_normalizer(KEY *key) const;
|
||||
grn_obj *find_normalizer(KEY *key);
|
||||
grn_obj *find_normalizer(KEY *key, const char *name);
|
||||
bool find_index_column_flags(KEY *key, grn_obj_flags *index_column_flags);
|
||||
bool find_index_column_flags(KEY *key, grn_column_flags *index_column_flags);
|
||||
bool find_token_filters(KEY *key, grn_obj *token_filters);
|
||||
bool find_token_filters_put(grn_obj *token_filters,
|
||||
const char *token_filter_name,
|
||||
@ -622,9 +701,7 @@ private:
|
||||
bool is_dry_write();
|
||||
bool is_enable_optimization();
|
||||
bool should_normalize(Field *field) const;
|
||||
bool is_temporary_table_name(const char *name) const;
|
||||
void check_count_skip(key_part_map start_key_part_map,
|
||||
key_part_map end_key_part_map, bool fulltext);
|
||||
void check_count_skip(key_part_map target_key_part_map);
|
||||
bool is_grn_zero_column_value(grn_obj *column, grn_obj *value);
|
||||
bool is_primary_key_field(Field *field) const;
|
||||
void check_fast_order_limit(grn_table_sort_key **sort_keys, int *n_sort_keys,
|
||||
@ -652,6 +729,9 @@ private:
|
||||
int generic_store_bulk_new_decimal(Field *field, grn_obj *buf);
|
||||
int generic_store_bulk_blob(Field *field, grn_obj *buf);
|
||||
int generic_store_bulk_geometry(Field *field, grn_obj *buf);
|
||||
#ifdef MRN_HAVE_MYSQL_TYPE_JSON
|
||||
int generic_store_bulk_json(Field *field, grn_obj *buf);
|
||||
#endif
|
||||
int generic_store_bulk(Field *field, grn_obj *buf);
|
||||
|
||||
void storage_store_field_string(Field *field,
|
||||
@ -687,6 +767,10 @@ private:
|
||||
const char *value, uint value_length);
|
||||
void storage_store_field_geometry(Field *field,
|
||||
const char *value, uint value_length);
|
||||
#ifdef MRN_HAVE_MYSQL_TYPE_JSON
|
||||
void storage_store_field_json(Field *field,
|
||||
const char *value, uint value_length);
|
||||
#endif
|
||||
void storage_store_field(Field *field, const char *value, uint value_length);
|
||||
void storage_store_field_column(Field *field, bool is_primary_key,
|
||||
int nth_column, grn_id record_id);
|
||||
@ -731,6 +815,15 @@ private:
|
||||
int storage_encode_multiple_column_key(KEY *key_info,
|
||||
const uchar *key, uint key_length,
|
||||
uchar *buffer, uint *encoded_length);
|
||||
int storage_encode_multiple_column_key_range(KEY *key_info,
|
||||
const uchar *start,
|
||||
uint start_size,
|
||||
const uchar *end,
|
||||
uint end_size,
|
||||
uchar *min_buffer,
|
||||
uint *min_encoded_size,
|
||||
uchar *max_buffer,
|
||||
uint *max_encoded_size);
|
||||
int storage_encode_multiple_column_key_range(KEY *key_info,
|
||||
const key_range *start,
|
||||
const key_range *end,
|
||||
@ -758,9 +851,7 @@ private:
|
||||
grn_obj **index_tables,
|
||||
grn_obj **index_columns,
|
||||
MRN_SHARE *tmp_share);
|
||||
int wrapper_create_index(const char *name, TABLE *table,
|
||||
HA_CREATE_INFO *info, MRN_SHARE *tmp_share,
|
||||
const char *grn_table_name);
|
||||
int wrapper_create_index(const char *name, TABLE *table, MRN_SHARE *tmp_share);
|
||||
int storage_create_validate_pseudo_column(TABLE *table);
|
||||
#ifdef MRN_SUPPORT_FOREIGN_KEYS
|
||||
bool storage_create_foreign_key(TABLE *table, const char *grn_table_name,
|
||||
@ -778,16 +869,18 @@ private:
|
||||
int storage_create_indexes(TABLE *table, const char *grn_table_name,
|
||||
grn_obj *grn_table, MRN_SHARE *tmp_share);
|
||||
int close_databases();
|
||||
int ensure_database_open(const char *name);
|
||||
int ensure_database_open(const char *name, mrn::Database **db=NULL);
|
||||
int ensure_database_remove(const char *name);
|
||||
int wrapper_delete_table(const char *name, handlerton *wrap_handlerton,
|
||||
const char *table_name);
|
||||
int generic_delete_table(const char *name, const char *table_name);
|
||||
int wrapper_open(const char *name, int mode, uint test_if_locked);
|
||||
int wrapper_open(const char *name, int mode, uint open_options);
|
||||
int wrapper_open_indexes(const char *name);
|
||||
int storage_open(const char *name, int mode, uint test_if_locked);
|
||||
int storage_reindex();
|
||||
int storage_open(const char *name, int mode, uint open_options);
|
||||
int open_table(const char *name);
|
||||
int storage_open_columns(void);
|
||||
void storage_close_columns(void);
|
||||
int storage_open_indexes(const char *name);
|
||||
void wrapper_overwrite_index_bits();
|
||||
int wrapper_close();
|
||||
@ -872,6 +965,13 @@ private:
|
||||
void storage_info_variable();
|
||||
void storage_info_variable_records();
|
||||
void storage_info_variable_data_file_length();
|
||||
#ifdef MRN_HANDLER_RECORDS_RETURN_ERROR
|
||||
int wrapper_records(ha_rows *num_rows);
|
||||
int storage_records(ha_rows *num_rows);
|
||||
#else
|
||||
ha_rows wrapper_records();
|
||||
ha_rows storage_records();
|
||||
#endif
|
||||
int wrapper_rnd_init(bool scan);
|
||||
int storage_rnd_init(bool scan);
|
||||
int wrapper_rnd_end();
|
||||
@ -914,14 +1014,6 @@ private:
|
||||
int storage_index_last(uchar *buf);
|
||||
int wrapper_index_next_same(uchar *buf, const uchar *key, uint keylen);
|
||||
int storage_index_next_same(uchar *buf, const uchar *key, uint keylen);
|
||||
int wrapper_read_range_first(const key_range *start_key,
|
||||
const key_range *end_key,
|
||||
bool eq_range, bool sorted);
|
||||
int storage_read_range_first(const key_range *start_key,
|
||||
const key_range *end_key,
|
||||
bool eq_range, bool sorted);
|
||||
int wrapper_read_range_next();
|
||||
int storage_read_range_next();
|
||||
int generic_ft_init();
|
||||
int wrapper_ft_init();
|
||||
int storage_ft_init();
|
||||
@ -929,41 +1021,18 @@ private:
|
||||
FT_INFO *storage_ft_init_ext(uint flags, uint key_nr, String *key);
|
||||
void generic_ft_init_ext_add_conditions_fast_order_limit(
|
||||
struct st_mrn_ft_info *info, grn_obj *expression);
|
||||
bool generic_ft_init_ext_parse_pragma_d(struct st_mrn_ft_info *info,
|
||||
const char *keyword,
|
||||
uint keyword_length,
|
||||
grn_operator *default_operator,
|
||||
uint *consumed_keyword_length);
|
||||
void generic_ft_init_ext_parse_pragma_w_append_section(
|
||||
struct st_mrn_ft_info *info,
|
||||
grn_obj *index_column,
|
||||
grn_obj *match_columns,
|
||||
uint section,
|
||||
grn_obj *section_value_buffer,
|
||||
int weight,
|
||||
uint n_weights);
|
||||
bool generic_ft_init_ext_parse_pragma_w(struct st_mrn_ft_info *info,
|
||||
const char *keyword,
|
||||
uint keyword_length,
|
||||
grn_obj *index_column,
|
||||
grn_obj *match_columns,
|
||||
uint *consumed_keyword_length,
|
||||
grn_obj *tmp_objects);
|
||||
grn_expr_flags expr_flags_in_boolean_mode();
|
||||
grn_rc generic_ft_init_ext_prepare_expression_in_boolean_mode(
|
||||
struct st_mrn_ft_info *info,
|
||||
String *key,
|
||||
grn_obj *index_column,
|
||||
grn_obj *match_columns,
|
||||
grn_obj *expression,
|
||||
grn_obj *tmp_objects);
|
||||
grn_obj *expression);
|
||||
grn_rc generic_ft_init_ext_prepare_expression_in_normal_mode(
|
||||
struct st_mrn_ft_info *info,
|
||||
String *key,
|
||||
grn_obj *index_column,
|
||||
grn_obj *match_columns,
|
||||
grn_obj *expression,
|
||||
grn_obj *tmp_objects);
|
||||
grn_obj *expression);
|
||||
struct st_mrn_ft_info *generic_ft_init_ext_select(uint flags,
|
||||
uint key_nr,
|
||||
String *key);
|
||||
@ -1041,8 +1110,10 @@ private:
|
||||
double storage_scan_time();
|
||||
double wrapper_read_time(uint index, uint ranges, ha_rows rows);
|
||||
double storage_read_time(uint index, uint ranges, ha_rows rows);
|
||||
#ifdef MRN_HANDLER_HAVE_KEYS_TO_USE_FOR_SCANNING
|
||||
const key_map *wrapper_keys_to_use_for_scanning();
|
||||
const key_map *storage_keys_to_use_for_scanning();
|
||||
#endif
|
||||
ha_rows wrapper_estimate_rows_upper_bound();
|
||||
ha_rows storage_estimate_rows_upper_bound();
|
||||
void wrapper_update_create_info(HA_CREATE_INFO* create_info);
|
||||
@ -1069,8 +1140,10 @@ private:
|
||||
bool wrapper_auto_repair(int error) const;
|
||||
bool storage_auto_repair(int error) const;
|
||||
int generic_disable_index(int i, KEY *key_info);
|
||||
int wrapper_disable_indexes_mroonga(uint mode);
|
||||
int wrapper_disable_indexes(uint mode);
|
||||
int storage_disable_indexes(uint mode);
|
||||
int wrapper_enable_indexes_mroonga(uint mode);
|
||||
int wrapper_enable_indexes(uint mode);
|
||||
int storage_enable_indexes(uint mode);
|
||||
int wrapper_check(THD* thd, HA_CHECK_OPT* check_opt);
|
||||
@ -1111,8 +1184,10 @@ private:
|
||||
Alter_inplace_info *ha_alter_info);
|
||||
bool wrapper_inplace_alter_table(TABLE *altered_table,
|
||||
Alter_inplace_info *ha_alter_info);
|
||||
bool storage_inplace_alter_table_index(TABLE *altered_table,
|
||||
Alter_inplace_info *ha_alter_info);
|
||||
bool storage_inplace_alter_table_add_index(TABLE *altered_table,
|
||||
Alter_inplace_info *ha_alter_info);
|
||||
bool storage_inplace_alter_table_drop_index(TABLE *altered_table,
|
||||
Alter_inplace_info *ha_alter_info);
|
||||
bool storage_inplace_alter_table_add_column(TABLE *altered_table,
|
||||
Alter_inplace_info *ha_alter_info);
|
||||
bool storage_inplace_alter_table_drop_column(TABLE *altered_table,
|
||||
@ -1208,7 +1283,9 @@ private:
|
||||
void storage_free_foreign_key_create_info(char* str);
|
||||
void wrapper_set_keys_in_use();
|
||||
void storage_set_keys_in_use();
|
||||
#ifdef MRN_RBR_UPDATE_NEED_ALL_COLUMNS
|
||||
bool check_written_by_row_based_binlog();
|
||||
#endif
|
||||
#ifdef MRN_HAVE_HA_REBIND_PSI
|
||||
void wrapper_unbind_psi();
|
||||
void storage_unbind_psi();
|
||||
|
@ -28,4 +28,23 @@ libmrn_need_mysql_la_SOURCES = \
|
||||
mrn_value_decoder.cpp \
|
||||
mrn_value_decoder.hpp \
|
||||
mrn_database_repairer.cpp \
|
||||
mrn_database_repairer.hpp
|
||||
mrn_database_repairer.hpp \
|
||||
mrn_context_pool.cpp \
|
||||
mrn_context_pool.hpp \
|
||||
mrn_operations.cpp \
|
||||
mrn_operations.hpp \
|
||||
mrn_operation.cpp \
|
||||
mrn_operation.hpp \
|
||||
mrn_database.cpp \
|
||||
mrn_database.hpp \
|
||||
mrn_column_name.cpp \
|
||||
mrn_column_name.hpp \
|
||||
mrn_count_skip_checker.cpp \
|
||||
mrn_count_skip_checker.hpp \
|
||||
mrn_query_parser.cpp \
|
||||
mrn_query_parser.hpp \
|
||||
mrn_current_thread.hpp \
|
||||
mrn_smart_bitmap.cpp \
|
||||
mrn_smart_bitmap.hpp \
|
||||
mrn_table_fields_offset_mover.cpp \
|
||||
mrn_table_fields_offset_mover.hpp
|
||||
|
63
storage/mroonga/lib/mrn_column_name.cpp
Normal file
63
storage/mroonga/lib/mrn_column_name.cpp
Normal file
@ -0,0 +1,63 @@
|
||||
/* -*- c-basic-offset: 2 -*- */
|
||||
/*
|
||||
Copyright(C) 2016 Kouhei Sutou <kou@clear-code.com>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <mrn_mysql.h>
|
||||
#include <mrn_mysql_compat.h>
|
||||
|
||||
#include "mrn_column_name.hpp"
|
||||
|
||||
#include <strfunc.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
// for debug
|
||||
#define MRN_CLASS_NAME "mrn::ColumnName"
|
||||
|
||||
namespace mrn {
|
||||
ColumnName::ColumnName(const char *mysql_name)
|
||||
: mysql_name_(mysql_name) {
|
||||
encode();
|
||||
}
|
||||
|
||||
const char *ColumnName::mysql_name() {
|
||||
return mysql_name_;
|
||||
}
|
||||
|
||||
const char *ColumnName::c_str() {
|
||||
return name_;
|
||||
}
|
||||
|
||||
size_t ColumnName::length() {
|
||||
return length_;
|
||||
}
|
||||
|
||||
void ColumnName::encode() {
|
||||
MRN_DBUG_ENTER_METHOD();
|
||||
uint errors;
|
||||
length_ = mrn_strconvert(system_charset_info,
|
||||
mysql_name_,
|
||||
strlen(mysql_name_),
|
||||
&my_charset_filename,
|
||||
name_,
|
||||
MRN_MAX_PATH_SIZE,
|
||||
&errors);
|
||||
name_[length_] = '\0';
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
}
|
38
storage/mroonga/lib/mrn_column_name.hpp
Normal file
38
storage/mroonga/lib/mrn_column_name.hpp
Normal file
@ -0,0 +1,38 @@
|
||||
/* -*- c-basic-offset: 2 -*- */
|
||||
/*
|
||||
Copyright(C) 2016 Kouhei Sutou <kou@clear-code.com>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <mrn_constants.hpp>
|
||||
|
||||
namespace mrn {
|
||||
class ColumnName {
|
||||
public:
|
||||
ColumnName(const char *mysql_name);
|
||||
const char *mysql_name();
|
||||
const char *c_str();
|
||||
size_t length();
|
||||
private:
|
||||
const char *mysql_name_;
|
||||
char name_[MRN_MAX_PATH_SIZE];
|
||||
size_t length_;
|
||||
|
||||
void encode();
|
||||
};
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
/* -*- c-basic-offset: 2 -*- */
|
||||
/*
|
||||
Copyright(C) 2013-2014 Kouhei Sutou <kou@clear-code.com>
|
||||
Copyright(C) 2013-2017 Kouhei Sutou <kou@clear-code.com>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
@ -175,7 +175,7 @@ namespace mrn {
|
||||
|
||||
bool convertable = false;
|
||||
|
||||
enum_field_types field_type = field_item->field_type();
|
||||
enum_field_types field_type = field_item->field->real_type();
|
||||
NormalizedType normalized_type = normalize_field_type(field_type);
|
||||
switch (normalized_type) {
|
||||
case STRING_TYPE:
|
||||
@ -185,7 +185,12 @@ namespace mrn {
|
||||
}
|
||||
break;
|
||||
case INT_TYPE:
|
||||
convertable = value_item->type() == Item::INT_ITEM;
|
||||
if (field_type == MYSQL_TYPE_ENUM) {
|
||||
convertable = (value_item->type() == Item::STRING_ITEM ||
|
||||
value_item->type() == Item::INT_ITEM);
|
||||
} else {
|
||||
convertable = value_item->type() == Item::INT_ITEM;
|
||||
}
|
||||
break;
|
||||
case TIME_TYPE:
|
||||
if (is_valid_time_value(field_item, value_item)) {
|
||||
@ -206,7 +211,7 @@ namespace mrn {
|
||||
|
||||
bool convertable = false;
|
||||
|
||||
enum_field_types field_type = field_item->field_type();
|
||||
enum_field_types field_type = field_item->field->type();
|
||||
NormalizedType normalized_type = normalize_field_type(field_type);
|
||||
switch (normalized_type) {
|
||||
case STRING_TYPE:
|
||||
@ -251,7 +256,7 @@ namespace mrn {
|
||||
|
||||
bool error;
|
||||
Item *real_value_item = value_item->real_item();
|
||||
switch (field_item->field_type()) {
|
||||
switch (field_item->field->type()) {
|
||||
case MYSQL_TYPE_TIME:
|
||||
error = real_value_item->get_time(mysql_time);
|
||||
break;
|
||||
@ -352,6 +357,11 @@ namespace mrn {
|
||||
case MYSQL_TYPE_GEOMETRY:
|
||||
type = UNSUPPORTED_TYPE;
|
||||
break;
|
||||
#ifdef MRN_HAVE_MYSQL_TYPE_JSON
|
||||
case MYSQL_TYPE_JSON:
|
||||
type = STRING_TYPE;
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
DBUG_RETURN(type);
|
||||
@ -404,11 +414,11 @@ namespace mrn {
|
||||
DBUG_RETURN(have);
|
||||
}
|
||||
|
||||
const Item_func *ConditionConverter::find_match_against(const Item *item) {
|
||||
unsigned int ConditionConverter::count_match_against(const Item *item) {
|
||||
MRN_DBUG_ENTER_METHOD();
|
||||
|
||||
if (!item) {
|
||||
DBUG_RETURN(NULL);
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
switch (item->type()) {
|
||||
@ -416,14 +426,13 @@ namespace mrn {
|
||||
if (is_storage_mode_) {
|
||||
Item_cond *cond_item = (Item_cond *)item;
|
||||
if (cond_item->functype() == Item_func::COND_AND_FUNC) {
|
||||
unsigned int n_match_againsts = 0;
|
||||
List_iterator<Item> iterator(*((cond_item)->argument_list()));
|
||||
const Item *sub_item;
|
||||
while ((sub_item = iterator++)) {
|
||||
const Item_func *match_against = find_match_against(sub_item);
|
||||
if (match_against) {
|
||||
DBUG_RETURN(match_against);
|
||||
}
|
||||
n_match_againsts += count_match_against(sub_item);
|
||||
}
|
||||
DBUG_RETURN(n_match_againsts);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -432,7 +441,7 @@ namespace mrn {
|
||||
const Item_func *func_item = (const Item_func *)item;
|
||||
switch (func_item->functype()) {
|
||||
case Item_func::FT_FUNC:
|
||||
DBUG_RETURN(func_item);
|
||||
DBUG_RETURN(1);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -443,7 +452,7 @@ namespace mrn {
|
||||
break;
|
||||
}
|
||||
|
||||
DBUG_RETURN(NULL);
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
void ConditionConverter::convert(const Item *where, grn_obj *expression) {
|
||||
@ -560,7 +569,7 @@ namespace mrn {
|
||||
grn_obj *expression) {
|
||||
MRN_DBUG_ENTER_METHOD();
|
||||
|
||||
enum_field_types field_type = field_item->field_type();
|
||||
enum_field_types field_type = field_item->field->real_type();
|
||||
NormalizedType normalized_type = normalize_field_type(field_type);
|
||||
|
||||
switch (normalized_type) {
|
||||
@ -574,7 +583,21 @@ namespace mrn {
|
||||
break;
|
||||
case INT_TYPE:
|
||||
grn_obj_reinit(ctx_, &value_, GRN_DB_INT64, 0);
|
||||
GRN_INT64_SET(ctx_, &value_, const_item->val_int());
|
||||
if (field_type == MYSQL_TYPE_ENUM) {
|
||||
if (const_item->type() == Item::STRING_ITEM) {
|
||||
String *string;
|
||||
string = const_item->val_str(NULL);
|
||||
Field_enum *enum_field = static_cast<Field_enum *>(field_item->field);
|
||||
int enum_value = find_type(string->c_ptr(),
|
||||
enum_field->typelib,
|
||||
FIND_TYPE_BASIC);
|
||||
GRN_INT64_SET(ctx_, &value_, enum_value);
|
||||
} else {
|
||||
GRN_INT64_SET(ctx_, &value_, const_item->val_int());
|
||||
}
|
||||
} else {
|
||||
GRN_INT64_SET(ctx_, &value_, const_item->val_int());
|
||||
}
|
||||
break;
|
||||
case TIME_TYPE:
|
||||
grn_obj_reinit(ctx_, &value_, GRN_DB_TIME, 0);
|
||||
|
@ -33,7 +33,7 @@ namespace mrn {
|
||||
~ConditionConverter();
|
||||
|
||||
bool is_convertable(const Item *item);
|
||||
const Item_func *find_match_against(const Item *item);
|
||||
unsigned int count_match_against(const Item *item);
|
||||
// caller must check "where" can be convertable by
|
||||
// is_convertable(). This method doesn't validate "where".
|
||||
void convert(const Item *where, grn_obj *expression);
|
||||
|
120
storage/mroonga/lib/mrn_context_pool.cpp
Normal file
120
storage/mroonga/lib/mrn_context_pool.cpp
Normal file
@ -0,0 +1,120 @@
|
||||
/* -*- c-basic-offset: 2 -*- */
|
||||
/*
|
||||
Copyright(C) 2015 Kouhei Sutou <kou@clear-code.com>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "mrn_context_pool.hpp"
|
||||
#include "mrn_lock.hpp"
|
||||
|
||||
#include <time.h>
|
||||
|
||||
namespace mrn {
|
||||
// for debug
|
||||
#define MRN_CLASS_NAME "mrn::ContextPool::Impl"
|
||||
|
||||
class ContextPool::Impl {
|
||||
public:
|
||||
Impl(mysql_mutex_t *mutex)
|
||||
: mutex_(mutex),
|
||||
pool_(NULL),
|
||||
last_pull_time_(0) {
|
||||
}
|
||||
|
||||
~Impl(void) {
|
||||
clear();
|
||||
}
|
||||
|
||||
grn_ctx *pull(void) {
|
||||
MRN_DBUG_ENTER_METHOD();
|
||||
grn_ctx *ctx = NULL;
|
||||
|
||||
{
|
||||
time_t now;
|
||||
time(&now);
|
||||
|
||||
mrn::Lock lock(mutex_);
|
||||
if (pool_) {
|
||||
ctx = static_cast<grn_ctx *>(pool_->data);
|
||||
list_pop(pool_);
|
||||
if ((now - last_pull_time_) >= CLEAR_THREATHOLD_IN_SECONDS) {
|
||||
clear();
|
||||
}
|
||||
}
|
||||
last_pull_time_ = now;
|
||||
}
|
||||
|
||||
if (!ctx) {
|
||||
ctx = grn_ctx_open(0);
|
||||
}
|
||||
|
||||
DBUG_RETURN(ctx);
|
||||
}
|
||||
|
||||
void release(grn_ctx *ctx) {
|
||||
MRN_DBUG_ENTER_METHOD();
|
||||
|
||||
{
|
||||
mrn::Lock lock(mutex_);
|
||||
list_push(pool_, ctx);
|
||||
grn_ctx_use(ctx, NULL);
|
||||
}
|
||||
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
private:
|
||||
static const unsigned int CLEAR_THREATHOLD_IN_SECONDS = 60 * 5;
|
||||
|
||||
mysql_mutex_t *mutex_;
|
||||
LIST *pool_;
|
||||
time_t last_pull_time_;
|
||||
|
||||
void clear(void) {
|
||||
MRN_DBUG_ENTER_METHOD();
|
||||
while (pool_) {
|
||||
grn_ctx *ctx = static_cast<grn_ctx *>(pool_->data);
|
||||
grn_ctx_close(ctx);
|
||||
list_pop(pool_);
|
||||
}
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
};
|
||||
|
||||
// For debug
|
||||
#undef MRN_CLASS_NAME
|
||||
#define MRN_CLASS_NAME "mrn::ContextPool"
|
||||
|
||||
ContextPool::ContextPool(mysql_mutex_t *mutex)
|
||||
: impl_(new Impl(mutex)) {
|
||||
}
|
||||
|
||||
ContextPool::~ContextPool(void) {
|
||||
delete impl_;
|
||||
}
|
||||
|
||||
grn_ctx *ContextPool::pull(void) {
|
||||
MRN_DBUG_ENTER_METHOD();
|
||||
grn_ctx *ctx = impl_->pull();
|
||||
DBUG_RETURN(ctx);
|
||||
}
|
||||
|
||||
void ContextPool::release(grn_ctx *ctx) {
|
||||
MRN_DBUG_ENTER_METHOD();
|
||||
impl_->release(ctx);
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
}
|
41
storage/mroonga/lib/mrn_context_pool.hpp
Normal file
41
storage/mroonga/lib/mrn_context_pool.hpp
Normal file
@ -0,0 +1,41 @@
|
||||
/* -*- c-basic-offset: 2 -*- */
|
||||
/*
|
||||
Copyright(C) 2015 Kouhei Sutou <kou@clear-code.com>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef MRN_CONTEXT_POOL_HPP_
|
||||
#define MRN_CONTEXT_POOL_HPP_
|
||||
|
||||
#include <mrn_mysql.h>
|
||||
|
||||
#include <groonga.h>
|
||||
|
||||
namespace mrn {
|
||||
class ContextPool {
|
||||
public:
|
||||
ContextPool(mysql_mutex_t *mutex);
|
||||
~ContextPool(void);
|
||||
grn_ctx *pull(void);
|
||||
void release(grn_ctx *context);
|
||||
|
||||
private:
|
||||
class Impl;
|
||||
Impl *impl_;
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* MRN_CONTEXT_POOL_HPP_ */
|
303
storage/mroonga/lib/mrn_count_skip_checker.cpp
Normal file
303
storage/mroonga/lib/mrn_count_skip_checker.cpp
Normal file
@ -0,0 +1,303 @@
|
||||
/* -*- c-basic-offset: 2 -*- */
|
||||
/*
|
||||
Copyright(C) 2010-2013 Kentoku SHIBA
|
||||
Copyright(C) 2011-2017 Kouhei Sutou <kou@clear-code.com>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "mrn_count_skip_checker.hpp"
|
||||
|
||||
#include <item_sum.h>
|
||||
|
||||
// for debug
|
||||
#define MRN_CLASS_NAME "mrn::CountSkipChecker"
|
||||
|
||||
namespace mrn {
|
||||
CountSkipChecker::CountSkipChecker(grn_ctx *ctx,
|
||||
TABLE *table,
|
||||
SELECT_LEX *select_lex,
|
||||
KEY *key_info,
|
||||
key_part_map target_key_part_map,
|
||||
bool is_storage_mode)
|
||||
: ctx_(ctx),
|
||||
table_(table),
|
||||
select_lex_(select_lex),
|
||||
key_info_(key_info),
|
||||
target_key_part_map_(target_key_part_map),
|
||||
is_storage_mode_(is_storage_mode) {
|
||||
}
|
||||
|
||||
CountSkipChecker::~CountSkipChecker() {
|
||||
}
|
||||
|
||||
bool CountSkipChecker::check() {
|
||||
MRN_DBUG_ENTER_METHOD();
|
||||
|
||||
if (select_lex_->item_list.elements != 1) {
|
||||
GRN_LOG(ctx_, GRN_LOG_DEBUG,
|
||||
"[mroonga][count-skip][false] not only one item: %u",
|
||||
select_lex_->item_list.elements);
|
||||
DBUG_RETURN(false);
|
||||
}
|
||||
if (select_lex_->group_list.elements > 0) {
|
||||
GRN_LOG(ctx_, GRN_LOG_DEBUG,
|
||||
"[mroonga][count-skip][false] have groups: %u",
|
||||
select_lex_->group_list.elements);
|
||||
DBUG_RETURN(false);
|
||||
}
|
||||
if (MRN_SELECT_LEX_GET_HAVING_COND(select_lex_)) {
|
||||
GRN_LOG(ctx_, GRN_LOG_DEBUG,
|
||||
"[mroonga][count-skip][false] have HAVING");
|
||||
DBUG_RETURN(false);
|
||||
}
|
||||
if (select_lex_->table_list.elements != 1) {
|
||||
GRN_LOG(ctx_, GRN_LOG_DEBUG,
|
||||
"[mroonga][count-skip][false] not only one table: %u",
|
||||
select_lex_->table_list.elements);
|
||||
DBUG_RETURN(false);
|
||||
}
|
||||
|
||||
Item *info = static_cast<Item *>(select_lex_->item_list.first_node()->info);
|
||||
if (info->type() != Item::SUM_FUNC_ITEM) {
|
||||
GRN_LOG(ctx_, GRN_LOG_DEBUG,
|
||||
"[mroonga][count-skip][false] item isn't sum function: %u",
|
||||
info->type());
|
||||
DBUG_RETURN(false);
|
||||
}
|
||||
Item_sum *sum_item = static_cast<Item_sum *>(info);
|
||||
if (sum_item->sum_func() != Item_sum::COUNT_FUNC) {
|
||||
GRN_LOG(ctx_, GRN_LOG_DEBUG,
|
||||
"[mroonga][count-skip][false] not COUNT: %u",
|
||||
sum_item->sum_func());
|
||||
DBUG_RETURN(false);
|
||||
}
|
||||
if (ITEM_SUM_GET_NEST_LEVEL(sum_item) != 0 ||
|
||||
ITEM_SUM_GET_AGGR_LEVEL(sum_item) != 0 ||
|
||||
ITEM_SUM_GET_MAX_AGGR_LEVEL(sum_item) != -1 ||
|
||||
sum_item->max_sum_func_level != -1) {
|
||||
GRN_LOG(ctx_, GRN_LOG_DEBUG,
|
||||
"[mroonga][count-skip][false] not simple COUNT(*): %d:%d:%d:%d",
|
||||
ITEM_SUM_GET_NEST_LEVEL(sum_item),
|
||||
ITEM_SUM_GET_AGGR_LEVEL(sum_item),
|
||||
ITEM_SUM_GET_MAX_AGGR_LEVEL(sum_item),
|
||||
sum_item->max_sum_func_level);
|
||||
DBUG_RETURN(false);
|
||||
}
|
||||
|
||||
Item *where = MRN_SELECT_LEX_GET_WHERE_COND(select_lex_);
|
||||
if (!where) {
|
||||
if (is_storage_mode_) {
|
||||
GRN_LOG(ctx_, GRN_LOG_DEBUG,
|
||||
"[mroonga][count-skip][true] no condition");
|
||||
DBUG_RETURN(true);
|
||||
} else {
|
||||
GRN_LOG(ctx_, GRN_LOG_DEBUG,
|
||||
"[mroonga][count-skip][false] no condition with wrapper mode");
|
||||
DBUG_RETURN(false);
|
||||
}
|
||||
}
|
||||
|
||||
bool skippable = is_skippable(where);
|
||||
DBUG_RETURN(skippable);
|
||||
}
|
||||
|
||||
bool CountSkipChecker::is_skippable(Item *where) {
|
||||
MRN_DBUG_ENTER_METHOD();
|
||||
|
||||
bool skippable = false;
|
||||
switch (where->type()) {
|
||||
case Item::COND_ITEM:
|
||||
{
|
||||
Item_cond *cond_item = static_cast<Item_cond *>(where);
|
||||
skippable = is_skippable(cond_item);
|
||||
if (skippable) {
|
||||
GRN_LOG(ctx_, GRN_LOG_DEBUG,
|
||||
"[mroonga][count-skip][true] skippable multiple conditions");
|
||||
}
|
||||
}
|
||||
break;
|
||||
case Item::FUNC_ITEM:
|
||||
{
|
||||
Item_func *func_item = static_cast<Item_func *>(where);
|
||||
if (func_item->functype() == Item_func::FT_FUNC) {
|
||||
if (select_lex_->select_n_where_fields == 1) {
|
||||
GRN_LOG(ctx_, GRN_LOG_DEBUG,
|
||||
"[mroonga][count-skip][true] "
|
||||
"only one full text search condition");
|
||||
DBUG_RETURN(true);
|
||||
} else {
|
||||
GRN_LOG(ctx_, GRN_LOG_DEBUG,
|
||||
"[mroonga][count-skip][false] "
|
||||
"full text search condition and more conditions: %u",
|
||||
select_lex_->select_n_where_fields);
|
||||
DBUG_RETURN(false);
|
||||
}
|
||||
} else {
|
||||
skippable = is_skippable(func_item);
|
||||
if (skippable) {
|
||||
GRN_LOG(ctx_, GRN_LOG_DEBUG,
|
||||
"[mroonga][count-skip][true] skippable condition");
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
GRN_LOG(ctx_, GRN_LOG_DEBUG,
|
||||
"[mroonga][count-skip][false] unsupported top level item: %u",
|
||||
where->type());
|
||||
break;
|
||||
}
|
||||
|
||||
DBUG_RETURN(skippable);
|
||||
}
|
||||
|
||||
bool CountSkipChecker::is_skippable(Item_cond *cond_item) {
|
||||
MRN_DBUG_ENTER_METHOD();
|
||||
|
||||
List_iterator<Item> iterator(*(cond_item->argument_list()));
|
||||
Item *sub_item;
|
||||
while ((sub_item = iterator++)) {
|
||||
if (sub_item->type() != Item::FUNC_ITEM) {
|
||||
GRN_LOG(ctx_, GRN_LOG_DEBUG,
|
||||
"[mroonga][count-skip][false] "
|
||||
"sub condition isn't function item: %u",
|
||||
sub_item->type());
|
||||
DBUG_RETURN(false);
|
||||
}
|
||||
if (!is_skippable(static_cast<Item_func *>(sub_item))) {
|
||||
DBUG_RETURN(false);
|
||||
}
|
||||
}
|
||||
DBUG_RETURN(true);
|
||||
}
|
||||
|
||||
bool CountSkipChecker::is_skippable(Item_func *func_item) {
|
||||
MRN_DBUG_ENTER_METHOD();
|
||||
|
||||
switch (func_item->functype()) {
|
||||
case Item_func::EQ_FUNC:
|
||||
case Item_func::EQUAL_FUNC:
|
||||
case Item_func::NE_FUNC:
|
||||
case Item_func::LT_FUNC:
|
||||
case Item_func::LE_FUNC:
|
||||
case Item_func::GE_FUNC:
|
||||
case Item_func::GT_FUNC:
|
||||
{
|
||||
Item **arguments = func_item->arguments();
|
||||
Item *left_item = arguments[0];
|
||||
if (left_item->type() != Item::FIELD_ITEM) {
|
||||
GRN_LOG(ctx_, GRN_LOG_DEBUG,
|
||||
"[mroonga][count-skip][false] not field: %u:%u",
|
||||
func_item->functype(),
|
||||
left_item->type());
|
||||
DBUG_RETURN(false);
|
||||
}
|
||||
|
||||
bool skippable = is_skippable(static_cast<Item_field *>(left_item));
|
||||
DBUG_RETURN(skippable);
|
||||
}
|
||||
break;
|
||||
case Item_func::BETWEEN:
|
||||
{
|
||||
Item **arguments = func_item->arguments();
|
||||
Item *target_item = arguments[0];
|
||||
if (target_item->type() != Item::FIELD_ITEM) {
|
||||
GRN_LOG(ctx_, GRN_LOG_DEBUG,
|
||||
"[mroonga][count-skip][false] BETWEEN target isn't field: %u",
|
||||
target_item->type());
|
||||
DBUG_RETURN(false);
|
||||
}
|
||||
|
||||
bool skippable = is_skippable(static_cast<Item_field *>(target_item));
|
||||
DBUG_RETURN(skippable);
|
||||
}
|
||||
break;
|
||||
case Item_func::MULT_EQUAL_FUNC:
|
||||
#ifdef MRN_HAVE_ITEM_EQUAL_FIELDS_ITERATOR
|
||||
{
|
||||
Item_equal *equal_item = static_cast<Item_equal *>(func_item);
|
||||
Item_equal_fields_iterator iterator(*equal_item);
|
||||
Item *field_item;
|
||||
while ((field_item = iterator++)) {
|
||||
bool skippable = is_skippable(static_cast<Item_field *>(field_item));
|
||||
if (!skippable) {
|
||||
DBUG_RETURN(skippable);
|
||||
}
|
||||
}
|
||||
DBUG_RETURN(true);
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
GRN_LOG(ctx_, GRN_LOG_DEBUG,
|
||||
"[mroonga][count-skip][false] unsupported function item: %u",
|
||||
func_item->functype());
|
||||
DBUG_RETURN(false);
|
||||
}
|
||||
|
||||
bool CountSkipChecker::is_skippable(Item_field *field_item) {
|
||||
MRN_DBUG_ENTER_METHOD();
|
||||
|
||||
Field *field = field_item->field;
|
||||
if (!field) {
|
||||
GRN_LOG(ctx_, GRN_LOG_DEBUG,
|
||||
"[mroonga][count-skip][false] field is missing");
|
||||
DBUG_RETURN(false);
|
||||
}
|
||||
|
||||
if (field->table != table_) {
|
||||
GRN_LOG(ctx_, GRN_LOG_DEBUG,
|
||||
"[mroonga][count-skip][false] external table's field");
|
||||
DBUG_RETURN(false);
|
||||
}
|
||||
|
||||
if (!key_info_) {
|
||||
GRN_LOG(ctx_, GRN_LOG_DEBUG,
|
||||
"[mroonga][count-skip][false] no active index: <%s>:<%s>",
|
||||
*(field->table_name),
|
||||
field->field_name);
|
||||
DBUG_RETURN(false);
|
||||
}
|
||||
|
||||
uint i;
|
||||
KEY_PART_INFO *key_part = key_info_->key_part;
|
||||
for (i = 0; i < KEY_N_KEY_PARTS(key_info_); i++) {
|
||||
if (key_part[i].field == field) {
|
||||
if ((target_key_part_map_ >> i) & 1) {
|
||||
DBUG_RETURN(true);
|
||||
} else {
|
||||
GRN_LOG(ctx_, GRN_LOG_DEBUG,
|
||||
"[mroonga][count-skip][false] "
|
||||
"field's index are out of key part map: %u:%lu: <%s>:<%s>",
|
||||
i,
|
||||
target_key_part_map_,
|
||||
*(field->table_name),
|
||||
field->field_name);
|
||||
DBUG_RETURN(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GRN_LOG(ctx_, GRN_LOG_DEBUG,
|
||||
"[mroonga][count-skip][false] field isn't indexed: <%s>:<%s>",
|
||||
*(field->table_name),
|
||||
field->field_name);
|
||||
DBUG_RETURN(false);
|
||||
}
|
||||
}
|
57
storage/mroonga/lib/mrn_count_skip_checker.hpp
Normal file
57
storage/mroonga/lib/mrn_count_skip_checker.hpp
Normal file
@ -0,0 +1,57 @@
|
||||
/* -*- c-basic-offset: 2 -*- */
|
||||
/*
|
||||
Copyright(C) 2016 Kouhei Sutou <kou@clear-code.com>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef MRN_COUNT_SKIP_CHECKER_HPP_
|
||||
#define MRN_COUNT_SKIP_CHECKER_HPP_
|
||||
|
||||
#include <mrn_mysql_compat.h>
|
||||
|
||||
#include <item_cmpfunc.h>
|
||||
|
||||
#include <groonga.h>
|
||||
|
||||
namespace mrn {
|
||||
class CountSkipChecker {
|
||||
public:
|
||||
CountSkipChecker(grn_ctx *ctx,
|
||||
TABLE *table,
|
||||
SELECT_LEX *select_lex,
|
||||
KEY *key_info,
|
||||
key_part_map target_key_part_map,
|
||||
bool is_storage_mode);
|
||||
~CountSkipChecker();
|
||||
|
||||
bool check();
|
||||
|
||||
private:
|
||||
grn_ctx *ctx_;
|
||||
TABLE *table_;
|
||||
SELECT_LEX *select_lex_;
|
||||
KEY *key_info_;
|
||||
key_part_map target_key_part_map_;
|
||||
bool is_storage_mode_;
|
||||
|
||||
bool is_skippable(Item *where);
|
||||
bool is_skippable(Item_cond *cond_item);
|
||||
bool is_skippable(Item_func *func_item);
|
||||
bool is_skippable(Item_field *field_item);
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* MRN_COUNT_SKIP_CHECKER_HPP_ */
|
27
storage/mroonga/lib/mrn_current_thread.hpp
Normal file
27
storage/mroonga/lib/mrn_current_thread.hpp
Normal file
@ -0,0 +1,27 @@
|
||||
/* -*- c-basic-offset: 2 -*- */
|
||||
/*
|
||||
Copyright(C) 2017 Kouhei Sutou <kou@clear-code.com>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <mrn_mysql.h>
|
||||
#include <mrn_mysql_compat.h>
|
||||
|
||||
#if (!defined(MRN_MARIADB_P) && MYSQL_VERSION_ID >= 80002)
|
||||
# include <current_thd.h>
|
||||
#endif
|
89
storage/mroonga/lib/mrn_database.cpp
Normal file
89
storage/mroonga/lib/mrn_database.cpp
Normal file
@ -0,0 +1,89 @@
|
||||
/* -*- c-basic-offset: 2 -*- */
|
||||
/*
|
||||
Copyright(C) 2015 Kouhei Sutou <kou@clear-code.com>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <mrn_mysql.h>
|
||||
|
||||
#include "mrn_database.hpp"
|
||||
#include "mrn_operations.hpp"
|
||||
|
||||
// for debug
|
||||
#define MRN_CLASS_NAME "mrn::Database"
|
||||
|
||||
namespace mrn {
|
||||
Database::Database(grn_ctx *ctx, grn_obj *db)
|
||||
: ctx_(ctx),
|
||||
db_(db),
|
||||
broken_table_names_(NULL),
|
||||
is_broken_(false) {
|
||||
Operations operations(ctx_);
|
||||
broken_table_names_ = operations.collect_processing_table_names();
|
||||
is_broken_ = operations.is_locked();
|
||||
}
|
||||
|
||||
Database::~Database(void) {
|
||||
close();
|
||||
}
|
||||
|
||||
void Database::close() {
|
||||
MRN_DBUG_ENTER_METHOD();
|
||||
if (db_) {
|
||||
grn_hash_close(ctx_, broken_table_names_);
|
||||
broken_table_names_ = NULL;
|
||||
grn_obj_close(ctx_, db_);
|
||||
db_ = NULL;
|
||||
}
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
grn_rc Database::remove() {
|
||||
MRN_DBUG_ENTER_METHOD();
|
||||
grn_rc rc = GRN_SUCCESS;
|
||||
if (db_) {
|
||||
grn_hash_close(ctx_, broken_table_names_);
|
||||
broken_table_names_ = NULL;
|
||||
rc = grn_obj_remove(ctx_, db_);
|
||||
if (rc == GRN_SUCCESS) {
|
||||
db_ = NULL;
|
||||
}
|
||||
}
|
||||
DBUG_RETURN(rc);
|
||||
}
|
||||
|
||||
grn_obj *Database::get() {
|
||||
MRN_DBUG_ENTER_METHOD();
|
||||
DBUG_RETURN(db_);
|
||||
}
|
||||
|
||||
bool Database::is_broken() {
|
||||
MRN_DBUG_ENTER_METHOD();
|
||||
DBUG_RETURN(is_broken_);
|
||||
}
|
||||
|
||||
bool Database::is_broken_table(const char *name, size_t name_size) {
|
||||
MRN_DBUG_ENTER_METHOD();
|
||||
grn_id id = grn_hash_get(ctx_, broken_table_names_, name, name_size, NULL);
|
||||
DBUG_RETURN(id != GRN_ID_NIL);
|
||||
}
|
||||
|
||||
void Database::mark_table_repaired(const char *name, size_t name_size) {
|
||||
MRN_DBUG_ENTER_METHOD();
|
||||
grn_hash_delete(ctx_, broken_table_names_, name, name_size, NULL);
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
}
|
47
storage/mroonga/lib/mrn_database.hpp
Normal file
47
storage/mroonga/lib/mrn_database.hpp
Normal file
@ -0,0 +1,47 @@
|
||||
/* -*- c-basic-offset: 2 -*- */
|
||||
/*
|
||||
Copyright(C) 2015 Kouhei Sutou <kou@clear-code.com>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef MRN_DATABASE_HPP_
|
||||
#define MRN_DATABASE_HPP_
|
||||
|
||||
#include <groonga.h>
|
||||
|
||||
namespace mrn {
|
||||
class Database {
|
||||
public:
|
||||
Database(grn_ctx *ctx, grn_obj *db);
|
||||
~Database(void);
|
||||
|
||||
void close();
|
||||
grn_rc remove();
|
||||
grn_obj *get();
|
||||
|
||||
bool is_broken();
|
||||
bool is_broken_table(const char *name, size_t name_size);
|
||||
void mark_table_repaired(const char *name, size_t name_size);
|
||||
|
||||
private:
|
||||
grn_ctx *ctx_;
|
||||
grn_obj *db_;
|
||||
grn_hash *broken_table_names_;
|
||||
bool is_broken_;
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* MRN_DATABASE_HPP_ */
|
@ -56,9 +56,9 @@ namespace mrn {
|
||||
if (cache_) {
|
||||
void *db_address;
|
||||
GRN_HASH_EACH(ctx_, cache_, id, NULL, 0, &db_address, {
|
||||
grn_obj *db;
|
||||
Database *db;
|
||||
memcpy(&db, db_address, sizeof(grn_obj *));
|
||||
grn_obj_unlink(ctx_, db);
|
||||
delete db;
|
||||
});
|
||||
grn_hash_close(ctx_, cache_);
|
||||
}
|
||||
@ -80,7 +80,7 @@ namespace mrn {
|
||||
DBUG_RETURN(true);
|
||||
}
|
||||
|
||||
int DatabaseManager::open(const char *path, grn_obj **db) {
|
||||
int DatabaseManager::open(const char *path, Database **db) {
|
||||
MRN_DBUG_ENTER_METHOD();
|
||||
|
||||
int error = 0;
|
||||
@ -100,36 +100,54 @@ namespace mrn {
|
||||
mapper.db_name(), strlen(mapper.db_name()),
|
||||
&db_address);
|
||||
if (id == GRN_ID_NIL) {
|
||||
grn_obj *grn_db;
|
||||
struct stat db_stat;
|
||||
if (stat(mapper.db_path(), &db_stat)) {
|
||||
GRN_LOG(ctx_, GRN_LOG_INFO,
|
||||
"database not found. creating...: <%s>", mapper.db_path());
|
||||
if (path[0] == FN_CURLIB &&
|
||||
(path[1] == FN_LIBCHAR || path[1] == FN_LIBCHAR2)) {
|
||||
mrn_is_directory_separator(path[1])) {
|
||||
ensure_database_directory();
|
||||
}
|
||||
*db = grn_db_create(ctx_, mapper.db_path(), NULL);
|
||||
grn_db = grn_db_create(ctx_, mapper.db_path(), NULL);
|
||||
if (ctx_->rc) {
|
||||
error = ER_CANT_CREATE_TABLE;
|
||||
my_message(error, ctx_->errbuf, MYF(0));
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
} else {
|
||||
*db = grn_db_open(ctx_, mapper.db_path());
|
||||
grn_db = grn_db_open(ctx_, mapper.db_path());
|
||||
if (ctx_->rc) {
|
||||
error = ER_CANT_OPEN_FILE;
|
||||
my_message(error, ctx_->errbuf, MYF(0));
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
}
|
||||
*db = new Database(ctx_, grn_db);
|
||||
grn_hash_add(ctx_, cache_,
|
||||
mapper.db_name(), strlen(mapper.db_name()),
|
||||
&db_address, NULL);
|
||||
memcpy(db_address, db, sizeof(grn_obj *));
|
||||
error = ensure_normalizers_registered(*db);
|
||||
memcpy(db_address, db, sizeof(Database *));
|
||||
error = ensure_normalizers_registered((*db)->get());
|
||||
if (!error) {
|
||||
if ((*db)->is_broken()) {
|
||||
error = ER_CANT_OPEN_FILE;
|
||||
char error_message[MRN_MESSAGE_BUFFER_SIZE];
|
||||
snprintf(error_message, MRN_MESSAGE_BUFFER_SIZE,
|
||||
"mroonga: database: open: "
|
||||
"The database maybe broken. "
|
||||
"We recommend you to recreate the database. "
|
||||
"If the database isn't broken, "
|
||||
"you can remove this error by running "
|
||||
"'groonga %s table_remove mroonga_operations' "
|
||||
"on server. But the latter isn't recommended.",
|
||||
mapper.db_path());
|
||||
my_message(error, error_message, MYF(0));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
memcpy(db, db_address, sizeof(grn_obj *));
|
||||
grn_ctx_use(ctx_, *db);
|
||||
memcpy(db, db_address, sizeof(Database *));
|
||||
grn_ctx_use(ctx_, (*db)->get());
|
||||
}
|
||||
|
||||
DBUG_RETURN(error);
|
||||
@ -150,10 +168,11 @@ namespace mrn {
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
grn_obj *db = NULL;
|
||||
memcpy(&db, db_address, sizeof(grn_obj *));
|
||||
Database *db = NULL;
|
||||
memcpy(&db, db_address, sizeof(Database *));
|
||||
grn_ctx_use(ctx_, db->get());
|
||||
if (db) {
|
||||
grn_obj_close(ctx_, db);
|
||||
delete db;
|
||||
}
|
||||
|
||||
grn_hash_delete_by_id(ctx_, cache_, id, NULL);
|
||||
@ -173,29 +192,35 @@ namespace mrn {
|
||||
mapper.db_name(), strlen(mapper.db_name()),
|
||||
&db_address);
|
||||
|
||||
grn_obj *db = NULL;
|
||||
Database *db = NULL;
|
||||
if (id == GRN_ID_NIL) {
|
||||
struct stat dummy;
|
||||
if (stat(mapper.db_path(), &dummy) == 0) {
|
||||
db = grn_db_open(ctx_, mapper.db_path());
|
||||
grn_obj *grn_db = grn_db_open(ctx_, mapper.db_path());
|
||||
db = new Database(ctx_, grn_db);
|
||||
}
|
||||
} else {
|
||||
memcpy(&db, db_address, sizeof(grn_obj *));
|
||||
memcpy(&db, db_address, sizeof(Database *));
|
||||
grn_ctx_use(ctx_, db->get());
|
||||
}
|
||||
|
||||
if (!db) {
|
||||
DBUG_RETURN(false);
|
||||
}
|
||||
|
||||
if (grn_obj_remove(ctx_, db) == GRN_SUCCESS) {
|
||||
if (db->remove() == GRN_SUCCESS) {
|
||||
if (id != GRN_ID_NIL) {
|
||||
grn_hash_delete_by_id(ctx_, cache_, id, NULL);
|
||||
}
|
||||
delete db;
|
||||
DBUG_RETURN(true);
|
||||
} else {
|
||||
GRN_LOG(ctx_, GRN_LOG_ERROR,
|
||||
"failed to drop database: <%s>: <%s>",
|
||||
mapper.db_path(), ctx_->errbuf);
|
||||
if (id == GRN_ID_NIL) {
|
||||
delete db;
|
||||
}
|
||||
DBUG_RETURN(false);
|
||||
}
|
||||
}
|
||||
@ -223,22 +248,28 @@ namespace mrn {
|
||||
break;
|
||||
}
|
||||
void *db_address;
|
||||
grn_obj *db;
|
||||
Database *db;
|
||||
grn_hash_cursor_get_value(ctx_, cursor, &db_address);
|
||||
memcpy(&db, db_address, sizeof(grn_obj *));
|
||||
memcpy(&db, db_address, sizeof(Database *));
|
||||
grn_ctx_use(ctx_, db->get());
|
||||
grn_rc rc = grn_hash_cursor_delete(ctx_, cursor, NULL);
|
||||
if (rc) {
|
||||
error = ER_ERROR_ON_READ;
|
||||
my_message(error, ctx_->errbuf, MYF(0));
|
||||
break;
|
||||
}
|
||||
grn_obj_close(ctx_, db);
|
||||
delete db;
|
||||
}
|
||||
grn_hash_cursor_close(ctx_, cursor);
|
||||
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
|
||||
const char *DatabaseManager::error_message() {
|
||||
MRN_DBUG_ENTER_METHOD();
|
||||
DBUG_RETURN(ctx_->errbuf);
|
||||
}
|
||||
|
||||
void DatabaseManager::mkdir_p(const char *directory) {
|
||||
MRN_DBUG_ENTER_METHOD();
|
||||
|
||||
@ -246,8 +277,7 @@ namespace mrn {
|
||||
char sub_directory[MRN_MAX_PATH_SIZE];
|
||||
sub_directory[0] = '\0';
|
||||
while (true) {
|
||||
if (directory[i] == FN_LIBCHAR ||
|
||||
directory[i] == FN_LIBCHAR2 ||
|
||||
if (mrn_is_directory_separator(directory[i]) ||
|
||||
directory[i] == '\0') {
|
||||
sub_directory[i] = '\0';
|
||||
struct stat directory_status;
|
||||
@ -290,8 +320,10 @@ namespace mrn {
|
||||
|
||||
const char *last_path_separator;
|
||||
last_path_separator = strrchr(path_prefix, FN_LIBCHAR);
|
||||
#ifdef FN_LIBCHAR2
|
||||
if (!last_path_separator)
|
||||
last_path_separator = strrchr(path_prefix, FN_LIBCHAR2);
|
||||
#endif
|
||||
if (!last_path_separator)
|
||||
DBUG_VOID_RETURN;
|
||||
if (path_prefix == last_path_separator)
|
||||
|
@ -22,6 +22,8 @@
|
||||
#ifndef MRN_DATABASE_MANAGER_HPP_
|
||||
#define MRN_DATABASE_MANAGER_HPP_
|
||||
|
||||
#include "mrn_database.hpp"
|
||||
|
||||
#include <groonga.h>
|
||||
|
||||
namespace mrn {
|
||||
@ -30,10 +32,11 @@ namespace mrn {
|
||||
DatabaseManager(grn_ctx *ctx, mysql_mutex_t *mutex);
|
||||
~DatabaseManager(void);
|
||||
bool init(void);
|
||||
int open(const char *path, grn_obj **db);
|
||||
int open(const char *path, Database **db);
|
||||
void close(const char *path);
|
||||
bool drop(const char *path);
|
||||
int clear(void);
|
||||
const char *error_message();
|
||||
|
||||
private:
|
||||
grn_ctx *ctx_;
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* -*- c-basic-offset: 2 -*- */
|
||||
/*
|
||||
Copyright(C) 2015 Kouhei Sutou <kou@clear-code.com>
|
||||
Copyright(C) 2015-2017 Kouhei Sutou <kou@clear-code.com>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
@ -36,6 +36,16 @@
|
||||
#endif
|
||||
|
||||
namespace mrn {
|
||||
struct CheckResult {
|
||||
CheckResult() :
|
||||
is_crashed(false),
|
||||
is_corrupt(false) {
|
||||
}
|
||||
|
||||
bool is_crashed;
|
||||
bool is_corrupt;
|
||||
};
|
||||
|
||||
DatabaseRepairer::DatabaseRepairer(grn_ctx *ctx, THD *thd)
|
||||
: ctx_(ctx),
|
||||
thd_(thd),
|
||||
@ -53,10 +63,19 @@ namespace mrn {
|
||||
bool DatabaseRepairer::is_crashed(void) {
|
||||
MRN_DBUG_ENTER_METHOD();
|
||||
|
||||
bool is_crashed = false;
|
||||
each_database(&DatabaseRepairer::is_crashed_body, &is_crashed);
|
||||
CheckResult result;
|
||||
each_database(&DatabaseRepairer::check_body, &result);
|
||||
|
||||
DBUG_RETURN(is_crashed);
|
||||
DBUG_RETURN(result.is_crashed);
|
||||
}
|
||||
|
||||
bool DatabaseRepairer::is_corrupt(void) {
|
||||
MRN_DBUG_ENTER_METHOD();
|
||||
|
||||
CheckResult result;
|
||||
each_database(&DatabaseRepairer::check_body, &result);
|
||||
|
||||
DBUG_RETURN(result.is_corrupt);
|
||||
}
|
||||
|
||||
bool DatabaseRepairer::repair(void) {
|
||||
@ -81,9 +100,19 @@ namespace mrn {
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
do {
|
||||
each_database_body(data.cFileName, each_body_func, user_data);
|
||||
} while (FindNextFile(finder, &data) != 0);
|
||||
grn_ctx ctx;
|
||||
grn_rc rc = grn_ctx_init(&ctx, 0);
|
||||
if (rc == GRN_SUCCESS) {
|
||||
do {
|
||||
each_database_body(data.cFileName, &ctx, each_body_func, user_data);
|
||||
} while (FindNextFile(finder, &data) != 0);
|
||||
grn_ctx_fin(&ctx);
|
||||
} else {
|
||||
GRN_LOG(ctx_, GRN_LOG_WARNING,
|
||||
"[mroonga][database][repairer][each] "
|
||||
"failed to initialize grn_ctx: %d: %s",
|
||||
rc, grn_rc_to_string(rc));
|
||||
}
|
||||
FindClose(finder);
|
||||
#else
|
||||
DIR *dir = opendir(base_directory_);
|
||||
@ -91,8 +120,18 @@ namespace mrn {
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
while (struct dirent *entry = readdir(dir)) {
|
||||
each_database_body(entry->d_name, each_body_func, user_data);
|
||||
grn_ctx ctx;
|
||||
grn_rc rc = grn_ctx_init(&ctx, 0);
|
||||
if (rc == GRN_SUCCESS) {
|
||||
while (struct dirent *entry = readdir(dir)) {
|
||||
each_database_body(entry->d_name, &ctx, each_body_func, user_data);
|
||||
}
|
||||
grn_ctx_fin(&ctx);
|
||||
} else {
|
||||
GRN_LOG(ctx_, GRN_LOG_WARNING,
|
||||
"[mroonga][database][repairer][each] "
|
||||
"failed to initialize grn_ctx: %d: %s",
|
||||
rc, grn_rc_to_string(rc));
|
||||
}
|
||||
closedir(dir);
|
||||
#endif
|
||||
@ -101,6 +140,7 @@ namespace mrn {
|
||||
}
|
||||
|
||||
void DatabaseRepairer::each_database_body(const char *base_path,
|
||||
grn_ctx *ctx,
|
||||
EachBodyFunc each_body_func,
|
||||
void *user_data) {
|
||||
MRN_DBUG_ENTER_METHOD();
|
||||
@ -123,14 +163,14 @@ namespace mrn {
|
||||
char db_path[MRN_MAX_PATH_SIZE];
|
||||
snprintf(db_path, MRN_MAX_PATH_SIZE,
|
||||
"%s%c%s", base_directory_, FN_LIBCHAR, base_path);
|
||||
grn_obj *db = grn_db_open(ctx_, db_path);
|
||||
grn_obj *db = grn_db_open(ctx, db_path);
|
||||
if (!db) {
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
(this->*each_body_func)(db, db_path, user_data);
|
||||
(this->*each_body_func)(ctx, db, db_path, user_data);
|
||||
|
||||
grn_obj_close(ctx_, db);
|
||||
grn_obj_close(ctx, db);
|
||||
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
@ -150,8 +190,7 @@ namespace mrn {
|
||||
size_t raw_path_prefix_length = strlen(raw_path_prefix);
|
||||
size_t separator_position = raw_path_prefix_length;
|
||||
for (; separator_position > 0; separator_position--) {
|
||||
if (base_directory_buffer_[separator_position] == FN_LIBCHAR ||
|
||||
base_directory_buffer_[separator_position] == FN_LIBCHAR2) {
|
||||
if (mrn_is_directory_separator(base_directory_buffer_[separator_position])) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -169,34 +208,46 @@ namespace mrn {
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
void DatabaseRepairer::is_crashed_body(grn_obj *db,
|
||||
const char *db_path,
|
||||
void *user_data) {
|
||||
void DatabaseRepairer::check_body(grn_ctx *ctx,
|
||||
grn_obj *db,
|
||||
const char *db_path,
|
||||
void *user_data) {
|
||||
MRN_DBUG_ENTER_METHOD();
|
||||
|
||||
bool *is_crashed = static_cast<bool *>(user_data);
|
||||
CheckResult *result = static_cast<CheckResult *>(user_data);
|
||||
|
||||
if (grn_obj_is_locked(ctx_, db)) {
|
||||
*is_crashed = true;
|
||||
if (grn_obj_is_locked(ctx, db)) {
|
||||
result->is_crashed = true;
|
||||
result->is_corrupt = true;
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
grn_table_cursor *cursor;
|
||||
cursor = grn_table_cursor_open(ctx_, db,
|
||||
cursor = grn_table_cursor_open(ctx, db,
|
||||
NULL, 0,
|
||||
NULL, 0,
|
||||
0, -1, GRN_CURSOR_BY_ID);
|
||||
if (!cursor) {
|
||||
*is_crashed = true;
|
||||
result->is_crashed = true;
|
||||
result->is_corrupt = true;
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
grn_id id;
|
||||
while ((id = grn_table_cursor_next(ctx_, cursor)) != GRN_ID_NIL) {
|
||||
grn_obj *object = grn_ctx_at(ctx_, id);
|
||||
while ((id = grn_table_cursor_next(ctx, cursor)) != GRN_ID_NIL) {
|
||||
if (grn_id_is_builtin(ctx, id)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
grn_obj *object = grn_ctx_at(ctx, id);
|
||||
|
||||
if (!object) {
|
||||
continue;
|
||||
if (ctx->rc == GRN_SUCCESS) {
|
||||
continue;
|
||||
} else {
|
||||
result->is_corrupt = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch (object->header.type) {
|
||||
@ -207,37 +258,40 @@ namespace mrn {
|
||||
case GRN_COLUMN_FIX_SIZE:
|
||||
case GRN_COLUMN_VAR_SIZE:
|
||||
case GRN_COLUMN_INDEX:
|
||||
grn_obj_is_locked(ctx_, object);
|
||||
*is_crashed = true;
|
||||
if (grn_obj_is_locked(ctx_, object)) {
|
||||
result->is_crashed = true;
|
||||
result->is_corrupt = true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
grn_obj_unlink(ctx_, object);
|
||||
grn_obj_unlink(ctx, object);
|
||||
|
||||
if (*is_crashed) {
|
||||
if (result->is_crashed || result->is_corrupt) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
grn_table_cursor_close(ctx_, cursor);
|
||||
grn_table_cursor_close(ctx, cursor);
|
||||
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
void DatabaseRepairer::repair_body(grn_obj *db,
|
||||
void DatabaseRepairer::repair_body(grn_ctx *ctx,
|
||||
grn_obj *db,
|
||||
const char *db_path,
|
||||
void *user_data) {
|
||||
MRN_DBUG_ENTER_METHOD();
|
||||
|
||||
bool *succeeded = static_cast<bool *>(user_data);
|
||||
if (grn_db_recover(ctx_, db) != GRN_SUCCESS) {
|
||||
if (grn_db_recover(ctx, db) != GRN_SUCCESS) {
|
||||
push_warning_printf(thd_,
|
||||
MRN_SEVERITY_WARNING,
|
||||
ER_NOT_KEYFILE,
|
||||
"mroonga: repair: "
|
||||
"Failed to recover database: <%s>: <%s>",
|
||||
db_path, ctx_->errbuf);
|
||||
db_path, ctx->errbuf);
|
||||
*succeeded = false;
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* -*- c-basic-offset: 2 -*- */
|
||||
/*
|
||||
Copyright(C) 2015 Kouhei Sutou <kou@clear-code.com>
|
||||
Copyright(C) 2015-2017 Kouhei Sutou <kou@clear-code.com>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
@ -28,6 +28,7 @@ namespace mrn {
|
||||
DatabaseRepairer(grn_ctx *ctx, THD *thd);
|
||||
~DatabaseRepairer(void);
|
||||
bool is_crashed(void);
|
||||
bool is_corrupt(void);
|
||||
bool repair(void);
|
||||
|
||||
private:
|
||||
@ -40,18 +41,26 @@ namespace mrn {
|
||||
size_t path_prefix_length_;
|
||||
size_t mrn_db_file_suffix_length_;
|
||||
|
||||
typedef void (DatabaseRepairer::*EachBodyFunc)(grn_obj *db,
|
||||
typedef void (DatabaseRepairer::*EachBodyFunc)(grn_ctx *ctx,
|
||||
grn_obj *db,
|
||||
const char *db_path,
|
||||
void *user_data);
|
||||
|
||||
void each_database(EachBodyFunc each_body_func, void *user_data);
|
||||
void each_database_body(const char *base_path,
|
||||
grn_ctx *ctx,
|
||||
EachBodyFunc each_body_func,
|
||||
void *user_data);
|
||||
void detect_paths(void);
|
||||
|
||||
void is_crashed_body(grn_obj *db, const char *db_path, void *user_data);
|
||||
void repair_body(grn_obj *db, const char *db_path, void *user_data);
|
||||
void check_body(grn_ctx *ctx,
|
||||
grn_obj *db,
|
||||
const char *db_path,
|
||||
void *user_data);
|
||||
void repair_body(grn_ctx *ctx,
|
||||
grn_obj *db,
|
||||
const char *db_path,
|
||||
void *user_data);
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
/* -*- c-basic-offset: 2 -*- */
|
||||
/*
|
||||
Copyright(C) 2011 Kentoku SHIBA
|
||||
Copyright(C) 2011-2012 Kouhei Sutou <kou@clear-code.com>
|
||||
Copyright(C) 2011-2015 Kouhei Sutou <kou@clear-code.com>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
@ -26,7 +26,8 @@
|
||||
#define MRN_CLASS_NAME "mrn::IndexTableName"
|
||||
|
||||
namespace mrn {
|
||||
const char *IndexTableName::SEPARATOR = "-";
|
||||
const char *IndexTableName::SEPARATOR = "#";
|
||||
const char *IndexTableName::OLD_SEPARATOR = "-";
|
||||
|
||||
bool IndexTableName::is_custom_name(const char *table_name,
|
||||
size_t table_name_length,
|
||||
@ -43,9 +44,12 @@ namespace mrn {
|
||||
DBUG_RETURN(true);
|
||||
}
|
||||
|
||||
if (strncmp(SEPARATOR,
|
||||
index_table_name + table_name_length,
|
||||
strlen(SEPARATOR)) != 0) {
|
||||
if ((strncmp(OLD_SEPARATOR,
|
||||
index_table_name + table_name_length,
|
||||
strlen(OLD_SEPARATOR)) != 0) &&
|
||||
(strncmp(SEPARATOR,
|
||||
index_table_name + table_name_length,
|
||||
strlen(SEPARATOR)) != 0)) {
|
||||
DBUG_RETURN(true);
|
||||
}
|
||||
|
||||
@ -63,6 +67,12 @@ namespace mrn {
|
||||
encoded_mysql_index_name_multibyte + MRN_MAX_KEY_SIZE,
|
||||
mysql_index_name_multibyte,
|
||||
mysql_index_name_multibyte + strlen(mysql_index_name_));
|
||||
snprintf(old_name_, MRN_MAX_KEY_SIZE,
|
||||
"%s%s%s",
|
||||
table_name_,
|
||||
OLD_SEPARATOR,
|
||||
encoded_mysql_index_name_multibyte);
|
||||
old_length_ = strlen(old_name_);
|
||||
snprintf(name_, MRN_MAX_KEY_SIZE,
|
||||
"%s%s%s",
|
||||
table_name_,
|
||||
@ -79,6 +89,14 @@ namespace mrn {
|
||||
return length_;
|
||||
}
|
||||
|
||||
const char *IndexTableName::old_c_str() {
|
||||
return old_name_;
|
||||
}
|
||||
|
||||
size_t IndexTableName::old_length() {
|
||||
return old_length_;
|
||||
}
|
||||
|
||||
uint IndexTableName::encode(uchar *encoded_start,
|
||||
uchar *encoded_end,
|
||||
const uchar *mysql_string_start,
|
||||
|
@ -1,7 +1,7 @@
|
||||
/* -*- c-basic-offset: 2 -*- */
|
||||
/*
|
||||
Copyright(C) 2011 Kentoku SHIBA
|
||||
Copyright(C) 2011-2012 Kouhei Sutou <kou@clear-code.com>
|
||||
Copyright(C) 2011-2015 Kouhei Sutou <kou@clear-code.com>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
@ -27,6 +27,7 @@ namespace mrn {
|
||||
class IndexTableName {
|
||||
public:
|
||||
static const char *SEPARATOR;
|
||||
static const char *OLD_SEPARATOR;
|
||||
|
||||
static bool is_custom_name(const char *table_name,
|
||||
size_t table_name_length,
|
||||
@ -36,9 +37,13 @@ namespace mrn {
|
||||
IndexTableName(const char *table_name, const char *mysql_index_name);
|
||||
const char *c_str();
|
||||
size_t length();
|
||||
const char *old_c_str();
|
||||
size_t old_length();
|
||||
private:
|
||||
const char *table_name_;
|
||||
const char *mysql_index_name_;
|
||||
char old_name_[MRN_MAX_KEY_SIZE];
|
||||
size_t old_length_;
|
||||
char name_[MRN_MAX_KEY_SIZE];
|
||||
size_t length_;
|
||||
|
||||
|
@ -288,6 +288,7 @@ namespace mrn {
|
||||
decode_long_long_int(current_grn_key, &grn_time);
|
||||
TimeConverter time_converter;
|
||||
MYSQL_TIME mysql_time;
|
||||
mysql_time.neg = FALSE;
|
||||
mysql_time.time_type = MYSQL_TIMESTAMP_DATETIME;
|
||||
time_converter.grn_time_to_mysql_time(grn_time, &mysql_time);
|
||||
long long int mysql_datetime_packed =
|
||||
@ -518,6 +519,14 @@ namespace mrn {
|
||||
*data_type = TYPE_BYTE_SEQUENCE;
|
||||
*data_size = key_part->length;
|
||||
break;
|
||||
#ifdef MRN_HAVE_MYSQL_TYPE_JSON
|
||||
case MYSQL_TYPE_JSON:
|
||||
// TODO
|
||||
DBUG_PRINT("info", ("mroonga: MYSQL_TYPE_JSON"));
|
||||
*data_type = TYPE_BYTE_SEQUENCE;
|
||||
*data_size = key_part->length;
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
@ -20,11 +20,11 @@
|
||||
#ifndef MRN_MULTIPLE_COLUMN_KEY_CODEC_HPP_
|
||||
#define MRN_MULTIPLE_COLUMN_KEY_CODEC_HPP_
|
||||
|
||||
#include <groonga.h>
|
||||
|
||||
#include <mrn_mysql.h>
|
||||
#include <mrn_mysql_compat.h>
|
||||
|
||||
#include <groonga.h>
|
||||
|
||||
namespace mrn {
|
||||
class MultipleColumnKeyCodec {
|
||||
public:
|
||||
|
51
storage/mroonga/lib/mrn_operation.cpp
Normal file
51
storage/mroonga/lib/mrn_operation.cpp
Normal file
@ -0,0 +1,51 @@
|
||||
/* -*- c-basic-offset: 2 -*- */
|
||||
/*
|
||||
Copyright(C) 2015 Kouhei Sutou <kou@clear-code.com>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <mrn_mysql.h>
|
||||
|
||||
#include "mrn_operation.hpp"
|
||||
|
||||
// for debug
|
||||
#define MRN_CLASS_NAME "mrn::Operation"
|
||||
|
||||
namespace mrn {
|
||||
Operation::Operation(mrn::Operations *operations,
|
||||
const char *type,
|
||||
const char *table_name,
|
||||
size_t table_name_size)
|
||||
: operations_(operations),
|
||||
id_(operations_->start(type, table_name, table_name_size)) {
|
||||
}
|
||||
|
||||
Operation::~Operation() {
|
||||
MRN_DBUG_ENTER_METHOD();
|
||||
|
||||
operations_->finish(id_);
|
||||
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
void Operation::record_target(grn_id record_id) {
|
||||
MRN_DBUG_ENTER_METHOD();
|
||||
|
||||
operations_->record_target(id_, record_id);
|
||||
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
}
|
42
storage/mroonga/lib/mrn_operation.hpp
Normal file
42
storage/mroonga/lib/mrn_operation.hpp
Normal file
@ -0,0 +1,42 @@
|
||||
/* -*- c-basic-offset: 2 -*- */
|
||||
/*
|
||||
Copyright(C) 2015 Kouhei Sutou <kou@clear-code.com>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef MRN_OPERATION_HPP_
|
||||
#define MRN_OPERATION_HPP_
|
||||
|
||||
#include <mrn_operations.hpp>
|
||||
|
||||
namespace mrn {
|
||||
class Operation {
|
||||
public:
|
||||
Operation(mrn::Operations *operations,
|
||||
const char *type,
|
||||
const char *table_name,
|
||||
size_t table_name_size);
|
||||
~Operation();
|
||||
|
||||
void record_target(grn_id record_id);
|
||||
|
||||
private:
|
||||
mrn::Operations *operations_;
|
||||
grn_id id_;
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* MRN_OPERATION_HPP_ */
|
401
storage/mroonga/lib/mrn_operations.cpp
Normal file
401
storage/mroonga/lib/mrn_operations.cpp
Normal file
@ -0,0 +1,401 @@
|
||||
/* -*- c-basic-offset: 2 -*- */
|
||||
/*
|
||||
Copyright(C) 2015 Kouhei Sutou <kou@clear-code.com>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <mrn_mysql.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "mrn_operations.hpp"
|
||||
|
||||
// for debug
|
||||
#define MRN_CLASS_NAME "mrn::Operations"
|
||||
|
||||
#define TABLE_NAME "mroonga_operations"
|
||||
#define COLUMN_TYPE_NAME "type"
|
||||
#define COLUMN_TABLE_NAME "table"
|
||||
#define COLUMN_RECORD_NAME "record"
|
||||
|
||||
namespace mrn {
|
||||
Operations::Operations(grn_ctx *ctx)
|
||||
: ctx_(ctx) {
|
||||
MRN_DBUG_ENTER_METHOD();
|
||||
|
||||
GRN_TEXT_INIT(&text_buffer_, GRN_OBJ_DO_SHALLOW_COPY);
|
||||
GRN_UINT32_INIT(&id_buffer_, 0);
|
||||
|
||||
table_ = grn_ctx_get(ctx_, TABLE_NAME, -1);
|
||||
if (!table_) {
|
||||
table_ = grn_table_create(ctx_,
|
||||
TABLE_NAME, strlen(TABLE_NAME),
|
||||
NULL,
|
||||
GRN_OBJ_TABLE_NO_KEY | GRN_OBJ_PERSISTENT,
|
||||
NULL, NULL);
|
||||
columns_.type_ =
|
||||
grn_column_create(ctx_, table_,
|
||||
COLUMN_TYPE_NAME, strlen(COLUMN_TYPE_NAME),
|
||||
NULL,
|
||||
GRN_OBJ_COLUMN_SCALAR | GRN_OBJ_PERSISTENT,
|
||||
grn_ctx_at(ctx_, GRN_DB_SHORT_TEXT));
|
||||
columns_.table_ =
|
||||
grn_column_create(ctx_, table_,
|
||||
COLUMN_TABLE_NAME, strlen(COLUMN_TABLE_NAME),
|
||||
NULL,
|
||||
GRN_OBJ_COLUMN_SCALAR | GRN_OBJ_PERSISTENT,
|
||||
grn_ctx_at(ctx_, GRN_DB_SHORT_TEXT));
|
||||
columns_.record_ =
|
||||
grn_column_create(ctx_, table_,
|
||||
COLUMN_RECORD_NAME, strlen(COLUMN_RECORD_NAME),
|
||||
NULL,
|
||||
GRN_OBJ_COLUMN_SCALAR | GRN_OBJ_PERSISTENT,
|
||||
grn_ctx_at(ctx_, GRN_DB_UINT32));
|
||||
} else {
|
||||
columns_.type_ = grn_ctx_get(ctx_, TABLE_NAME "." COLUMN_TYPE_NAME, -1);
|
||||
columns_.table_ = grn_ctx_get(ctx_, TABLE_NAME "." COLUMN_TABLE_NAME, -1);
|
||||
columns_.record_ = grn_ctx_get(ctx_, TABLE_NAME "." COLUMN_RECORD_NAME, -1);
|
||||
}
|
||||
|
||||
is_enabled_recording_ = true;
|
||||
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
Operations::~Operations() {
|
||||
MRN_DBUG_ENTER_METHOD();
|
||||
|
||||
GRN_OBJ_FIN(ctx_, &id_buffer_);
|
||||
GRN_OBJ_FIN(ctx_, &text_buffer_);
|
||||
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
bool Operations::is_locked() {
|
||||
MRN_DBUG_ENTER_METHOD();
|
||||
|
||||
if (grn_obj_is_locked(ctx_, table_) > 0)
|
||||
DBUG_RETURN(true);
|
||||
|
||||
if (grn_obj_is_locked(ctx_, columns_.type_) > 0)
|
||||
DBUG_RETURN(true);
|
||||
|
||||
if (grn_obj_is_locked(ctx_, columns_.table_) > 0)
|
||||
DBUG_RETURN(true);
|
||||
|
||||
if (grn_obj_is_locked(ctx_, columns_.record_) > 0)
|
||||
DBUG_RETURN(true);
|
||||
|
||||
DBUG_RETURN(false);
|
||||
}
|
||||
|
||||
grn_id Operations::start(const char *type,
|
||||
const char *table_name, size_t table_name_size) {
|
||||
MRN_DBUG_ENTER_METHOD();
|
||||
|
||||
if (!is_enabled_recording_) {
|
||||
DBUG_RETURN(GRN_ID_NIL);
|
||||
}
|
||||
|
||||
grn_id id = grn_table_add(ctx_, table_, NULL, 0, NULL);
|
||||
|
||||
GRN_TEXT_SETS(ctx_, &text_buffer_, type);
|
||||
grn_obj_set_value(ctx_, columns_.type_, id, &text_buffer_, GRN_OBJ_SET);
|
||||
|
||||
GRN_TEXT_SET(ctx_, &text_buffer_, table_name, table_name_size);
|
||||
grn_obj_set_value(ctx_, columns_.table_, id, &text_buffer_, GRN_OBJ_SET);
|
||||
|
||||
DBUG_RETURN(id);
|
||||
}
|
||||
|
||||
void Operations::record_target(grn_id id, grn_id record_id) {
|
||||
MRN_DBUG_ENTER_METHOD();
|
||||
|
||||
if (!is_enabled_recording_) {
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
GRN_UINT32_SET(ctx_, &id_buffer_, record_id);
|
||||
grn_obj_set_value(ctx_, columns_.record_, id, &id_buffer_, GRN_OBJ_SET);
|
||||
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
void Operations::finish(grn_id id) {
|
||||
MRN_DBUG_ENTER_METHOD();
|
||||
|
||||
if (!is_enabled_recording_) {
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
grn_table_delete_by_id(ctx_, table_, id);
|
||||
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
void Operations::enable_recording() {
|
||||
MRN_DBUG_ENTER_METHOD();
|
||||
|
||||
is_enabled_recording_ = true;
|
||||
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
void Operations::disable_recording() {
|
||||
MRN_DBUG_ENTER_METHOD();
|
||||
|
||||
is_enabled_recording_ = false;
|
||||
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
grn_hash *Operations::collect_processing_table_names() {
|
||||
MRN_DBUG_ENTER_METHOD();
|
||||
|
||||
grn_hash *table_names =
|
||||
grn_hash_create(ctx_, NULL, GRN_TABLE_MAX_KEY_SIZE, 0,
|
||||
GRN_OBJ_TABLE_HASH_KEY | GRN_OBJ_KEY_VAR_SIZE);
|
||||
|
||||
grn_table_cursor *cursor;
|
||||
cursor = grn_table_cursor_open(ctx_, table_, NULL, 0, NULL, 0, 0, -1, 0);
|
||||
if (!cursor) {
|
||||
GRN_LOG(ctx_, GRN_LOG_NOTICE,
|
||||
"[operations] failed to open cursor: %s",
|
||||
ctx_->errbuf);
|
||||
DBUG_RETURN(table_names);
|
||||
}
|
||||
|
||||
grn_id id;
|
||||
while ((id = grn_table_cursor_next(ctx_, cursor))) {
|
||||
GRN_BULK_REWIND(&text_buffer_);
|
||||
grn_obj_get_value(ctx_, columns_.table_, id, &text_buffer_);
|
||||
if (GRN_TEXT_LEN(&text_buffer_) > 0) {
|
||||
grn_hash_add(ctx_, table_names,
|
||||
GRN_TEXT_VALUE(&text_buffer_),
|
||||
GRN_TEXT_LEN(&text_buffer_),
|
||||
NULL,
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
grn_table_cursor_close(ctx_, cursor);
|
||||
|
||||
DBUG_RETURN(table_names);
|
||||
}
|
||||
|
||||
int Operations::repair(const char *table_name, size_t table_name_size) {
|
||||
MRN_DBUG_ENTER_METHOD();
|
||||
|
||||
int error = 0;
|
||||
|
||||
grn_table_cursor *cursor;
|
||||
cursor = grn_table_cursor_open(ctx_, table_, NULL, 0, NULL, 0, 0, -1, 0);
|
||||
if (!cursor) {
|
||||
error = HA_ERR_CRASHED_ON_USAGE;
|
||||
if (ctx_->rc) {
|
||||
my_message(error, ctx_->errbuf, MYF(0));
|
||||
} else {
|
||||
my_message(error,
|
||||
"mroonga: repair: "
|
||||
"failed to open cursor for operations table",
|
||||
MYF(0));
|
||||
}
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
|
||||
grn_obj *target_table = grn_ctx_get(ctx_, table_name, table_name_size);
|
||||
if (!target_table) {
|
||||
GRN_LOG(ctx_, GRN_LOG_WARNING,
|
||||
"table doesn't exist for auto repair: <%.*s>",
|
||||
static_cast<int>(table_name_size), table_name);
|
||||
}
|
||||
|
||||
grn_id id;
|
||||
while ((id = grn_table_cursor_next(ctx_, cursor))) {
|
||||
GRN_BULK_REWIND(&text_buffer_);
|
||||
grn_obj_get_value(ctx_, columns_.table_, id, &text_buffer_);
|
||||
if (!((static_cast<size_t>(GRN_TEXT_LEN(&text_buffer_)) ==
|
||||
table_name_size) &&
|
||||
memcmp(GRN_TEXT_VALUE(&text_buffer_),
|
||||
table_name,
|
||||
table_name_size) == 0)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!target_table) {
|
||||
grn_rc rc = grn_table_cursor_delete(ctx_, cursor);
|
||||
if (rc != GRN_SUCCESS) {
|
||||
GRN_BULK_REWIND(&text_buffer_);
|
||||
grn_obj_get_value(ctx_, columns_.type_, id, &text_buffer_);
|
||||
GRN_TEXT_PUTC(ctx_, &text_buffer_, '\0');
|
||||
char error_message[MRN_MESSAGE_BUFFER_SIZE];
|
||||
snprintf(error_message, MRN_MESSAGE_BUFFER_SIZE,
|
||||
"mroonga: repair: failed to delete an orphan operation: "
|
||||
"[%u]: <%.*s>[%s]: <%s>(%d)",
|
||||
id,
|
||||
static_cast<int>(table_name_size), table_name,
|
||||
GRN_TEXT_VALUE(&text_buffer_),
|
||||
ctx_->errbuf,
|
||||
rc);
|
||||
my_message(error, error_message, MYF(0));
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
GRN_BULK_REWIND(&id_buffer_);
|
||||
grn_obj_get_value(ctx_, columns_.record_, id, &id_buffer_);
|
||||
grn_id record_id = GRN_UINT32_VALUE(&id_buffer_);
|
||||
if (record_id == GRN_ID_NIL) {
|
||||
grn_rc rc = grn_table_cursor_delete(ctx_, cursor);
|
||||
if (rc != GRN_SUCCESS) {
|
||||
GRN_BULK_REWIND(&text_buffer_);
|
||||
grn_obj_get_value(ctx_, columns_.type_, id, &text_buffer_);
|
||||
GRN_TEXT_PUTC(ctx_, &text_buffer_, '\0');
|
||||
char error_message[MRN_MESSAGE_BUFFER_SIZE];
|
||||
snprintf(error_message, MRN_MESSAGE_BUFFER_SIZE,
|
||||
"mroonga: repair: "
|
||||
"failed to delete an operation that has no related record: "
|
||||
"[%u]: <%.*s>[%s]: <%s>(%d)",
|
||||
id,
|
||||
static_cast<int>(table_name_size), table_name,
|
||||
GRN_TEXT_VALUE(&text_buffer_),
|
||||
ctx_->errbuf,
|
||||
rc);
|
||||
my_message(error, error_message, MYF(0));
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
GRN_BULK_REWIND(&text_buffer_);
|
||||
grn_obj_get_value(ctx_, columns_.type_, id, &text_buffer_);
|
||||
GRN_TEXT_PUTC(ctx_, &text_buffer_, '\0');
|
||||
if (strcmp(GRN_TEXT_VALUE(&text_buffer_), "write") == 0 ||
|
||||
strcmp(GRN_TEXT_VALUE(&text_buffer_), "delete") == 0) {
|
||||
grn_rc rc = grn_table_delete_by_id(ctx_, target_table, record_id);
|
||||
if (rc != GRN_SUCCESS) {
|
||||
error = HA_ERR_CRASHED_ON_USAGE;
|
||||
char error_message[MRN_MESSAGE_BUFFER_SIZE];
|
||||
snprintf(error_message, MRN_MESSAGE_BUFFER_SIZE,
|
||||
"mroonga: repair: failed to delete an incomplete record: "
|
||||
"[%u]: <%.*s>[%u]: <%s>(%d)",
|
||||
id,
|
||||
static_cast<int>(table_name_size), table_name,
|
||||
record_id,
|
||||
ctx_->errbuf,
|
||||
rc);
|
||||
my_message(error, error_message, MYF(0));
|
||||
break;
|
||||
}
|
||||
|
||||
rc = grn_table_cursor_delete(ctx_, cursor);
|
||||
if (rc != GRN_SUCCESS) {
|
||||
error = HA_ERR_CRASHED_ON_USAGE;
|
||||
char error_message[MRN_MESSAGE_BUFFER_SIZE];
|
||||
snprintf(error_message, MRN_MESSAGE_BUFFER_SIZE,
|
||||
"mroonga: repair: failed to delete an incomplete operation: "
|
||||
"[%u]: <%.*s>[%u][%s]: <%s>(%d)",
|
||||
id,
|
||||
static_cast<int>(table_name_size), table_name,
|
||||
record_id,
|
||||
GRN_TEXT_VALUE(&text_buffer_),
|
||||
ctx_->errbuf,
|
||||
rc);
|
||||
my_message(error, error_message, MYF(0));
|
||||
break;
|
||||
}
|
||||
} else if (strcmp(GRN_TEXT_VALUE(&text_buffer_), "update") == 0) {
|
||||
error = HA_ERR_CRASHED_ON_USAGE;
|
||||
my_message(error,
|
||||
"mroonga: repair: can't recover from crash while updating",
|
||||
MYF(0));
|
||||
break;
|
||||
} else {
|
||||
error = HA_ERR_CRASHED_ON_USAGE;
|
||||
char error_message[MRN_MESSAGE_BUFFER_SIZE];
|
||||
snprintf(error_message, MRN_MESSAGE_BUFFER_SIZE,
|
||||
"mroonga: repair: unknown operation type: "
|
||||
"[%u]: <%.*s>[%u]: <%s>",
|
||||
id,
|
||||
static_cast<int>(table_name_size), table_name,
|
||||
record_id,
|
||||
GRN_TEXT_VALUE(&text_buffer_));
|
||||
my_message(error, error_message, MYF(0));
|
||||
break;
|
||||
}
|
||||
}
|
||||
grn_table_cursor_close(ctx_, cursor);
|
||||
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
|
||||
int Operations::clear(const char *table_name, size_t table_name_size) {
|
||||
MRN_DBUG_ENTER_METHOD();
|
||||
|
||||
int error = 0;
|
||||
|
||||
grn_table_cursor *cursor;
|
||||
cursor = grn_table_cursor_open(ctx_, table_, NULL, 0, NULL, 0, 0, -1, 0);
|
||||
if (!cursor) {
|
||||
error = HA_ERR_CRASHED_ON_USAGE;
|
||||
if (ctx_->rc) {
|
||||
my_message(error, ctx_->errbuf, MYF(0));
|
||||
} else {
|
||||
my_message(error,
|
||||
"mroonga: clear: "
|
||||
"failed to open cursor for operations table",
|
||||
MYF(0));
|
||||
}
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
|
||||
grn_id id;
|
||||
while ((id = grn_table_cursor_next(ctx_, cursor))) {
|
||||
GRN_BULK_REWIND(&text_buffer_);
|
||||
grn_obj_get_value(ctx_, columns_.table_, id, &text_buffer_);
|
||||
if ((static_cast<size_t>(GRN_TEXT_LEN(&text_buffer_)) ==
|
||||
table_name_size) &&
|
||||
memcmp(GRN_TEXT_VALUE(&text_buffer_),
|
||||
table_name,
|
||||
table_name_size) == 0) {
|
||||
grn_rc rc = grn_table_cursor_delete(ctx_, cursor);
|
||||
if (rc != GRN_SUCCESS) {
|
||||
error = HA_ERR_CRASHED_ON_USAGE;
|
||||
GRN_BULK_REWIND(&id_buffer_);
|
||||
grn_obj_get_value(ctx_, columns_.record_, id, &id_buffer_);
|
||||
GRN_BULK_REWIND(&text_buffer_);
|
||||
grn_obj_get_value(ctx_, columns_.type_, id, &text_buffer_);
|
||||
GRN_TEXT_PUTC(ctx_, &text_buffer_, '\0');
|
||||
char error_message[MRN_MESSAGE_BUFFER_SIZE];
|
||||
snprintf(error_message, MRN_MESSAGE_BUFFER_SIZE,
|
||||
"mroonga: clear: failed to delete an operation: "
|
||||
"[%u]: <%.*s>[%u][%s]: <%s>(%d)",
|
||||
id,
|
||||
static_cast<int>(table_name_size), table_name,
|
||||
GRN_UINT32_VALUE(&id_buffer_),
|
||||
GRN_TEXT_VALUE(&text_buffer_),
|
||||
ctx_->errbuf,
|
||||
rc);
|
||||
my_message(error, error_message, MYF(0));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
grn_table_cursor_close(ctx_, cursor);
|
||||
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
}
|
60
storage/mroonga/lib/mrn_operations.hpp
Normal file
60
storage/mroonga/lib/mrn_operations.hpp
Normal file
@ -0,0 +1,60 @@
|
||||
/* -*- c-basic-offset: 2 -*- */
|
||||
/*
|
||||
Copyright(C) 2015 Kouhei Sutou <kou@clear-code.com>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef MRN_OPERATIONS_HPP_
|
||||
#define MRN_OPERATIONS_HPP_
|
||||
|
||||
#include <groonga.h>
|
||||
|
||||
namespace mrn {
|
||||
class Operations {
|
||||
public:
|
||||
Operations(grn_ctx *ctx);
|
||||
~Operations();
|
||||
|
||||
bool is_locked();
|
||||
|
||||
grn_id start(const char *type,
|
||||
const char *table_name, size_t table_name_size);
|
||||
void record_target(grn_id id, grn_id target_id);
|
||||
void finish(grn_id id);
|
||||
|
||||
void enable_recording();
|
||||
void disable_recording();
|
||||
|
||||
grn_hash *collect_processing_table_names();
|
||||
|
||||
int repair(const char *table_name, size_t table_name_size);
|
||||
int clear(const char *table_name, size_t table_name_size);
|
||||
|
||||
private:
|
||||
grn_ctx *ctx_;
|
||||
grn_obj text_buffer_;
|
||||
grn_obj id_buffer_;
|
||||
grn_obj *table_;
|
||||
struct {
|
||||
grn_obj *type_;
|
||||
grn_obj *table_;
|
||||
grn_obj *record_;
|
||||
} columns_;
|
||||
bool is_enabled_recording_;
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* MRN_OPERATIONS_HPP_ */
|
@ -222,4 +222,8 @@ namespace mrn {
|
||||
mysql_path_[i] = '\0';
|
||||
return mysql_path_;
|
||||
}
|
||||
|
||||
bool PathMapper::is_internal_table_name() {
|
||||
return mysql_table_name()[0] == '#';
|
||||
}
|
||||
}
|
||||
|
@ -38,6 +38,8 @@ namespace mrn {
|
||||
const char *table_name();
|
||||
const char *mysql_table_name();
|
||||
const char *mysql_path();
|
||||
bool is_internal_table_name();
|
||||
bool is_temporary_table_name();
|
||||
private:
|
||||
const char *original_mysql_path_;
|
||||
const char *path_prefix_;
|
||||
|
361
storage/mroonga/lib/mrn_query_parser.cpp
Normal file
361
storage/mroonga/lib/mrn_query_parser.cpp
Normal file
@ -0,0 +1,361 @@
|
||||
/* -*- c-basic-offset: 2 -*- */
|
||||
/*
|
||||
Copyright(C) 2017 Kouhei Sutou <kou@clear-code.com>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "mrn_query_parser.hpp"
|
||||
|
||||
#include <mrn_variables.hpp>
|
||||
|
||||
extern "C" {
|
||||
/* Groonga's internal functions */
|
||||
int grn_atoi(const char *nptr, const char *end, const char **rest);
|
||||
uint grn_atoui(const char *nptr, const char *end, const char **rest);
|
||||
}
|
||||
|
||||
#define MRN_CLASS_NAME "mrn::QueryParser"
|
||||
|
||||
namespace mrn {
|
||||
QueryParser::QueryParser(grn_ctx *ctx,
|
||||
THD *thd,
|
||||
grn_obj *expression,
|
||||
grn_obj *default_column,
|
||||
uint n_sections,
|
||||
grn_obj *match_columns)
|
||||
: ctx_(ctx),
|
||||
thd_(thd),
|
||||
expression_(expression),
|
||||
default_column_(default_column),
|
||||
n_sections_(n_sections),
|
||||
match_columns_(match_columns) {
|
||||
}
|
||||
|
||||
QueryParser::~QueryParser() {
|
||||
}
|
||||
|
||||
grn_rc QueryParser::parse(const char *query, size_t query_length) {
|
||||
MRN_DBUG_ENTER_METHOD();
|
||||
|
||||
const char *raw_query = NULL;
|
||||
size_t raw_query_length = 0;
|
||||
grn_operator default_operator = GRN_OP_OR;
|
||||
grn_expr_flags expression_flags = 0;
|
||||
parse_pragma(query,
|
||||
query_length,
|
||||
&raw_query,
|
||||
&raw_query_length,
|
||||
&default_operator,
|
||||
&expression_flags);
|
||||
|
||||
grn_obj *default_column = default_column_;
|
||||
if (match_columns_) {
|
||||
default_column = match_columns_;
|
||||
}
|
||||
grn_rc rc = grn_expr_parse(ctx_,
|
||||
expression_,
|
||||
raw_query,
|
||||
raw_query_length,
|
||||
default_column,
|
||||
GRN_OP_MATCH,
|
||||
default_operator,
|
||||
expression_flags);
|
||||
if (rc != GRN_SUCCESS) {
|
||||
char error_message[MRN_MESSAGE_BUFFER_SIZE];
|
||||
snprintf(error_message, MRN_MESSAGE_BUFFER_SIZE,
|
||||
"failed to parse fulltext search keyword: <%.*s>: <%s>",
|
||||
static_cast<int>(query_length),
|
||||
query,
|
||||
ctx_->errbuf);
|
||||
variables::ActionOnError action =
|
||||
variables::get_action_on_fulltext_query_error(thd_);
|
||||
switch (action) {
|
||||
case variables::ACTION_ON_ERROR_ERROR:
|
||||
my_message(ER_PARSE_ERROR, error_message, MYF(0));
|
||||
break;
|
||||
case variables::ACTION_ON_ERROR_ERROR_AND_LOG:
|
||||
my_message(ER_PARSE_ERROR, error_message, MYF(0));
|
||||
GRN_LOG(ctx_, GRN_LOG_ERROR, "%s", error_message);
|
||||
break;
|
||||
case variables::ACTION_ON_ERROR_IGNORE:
|
||||
break;
|
||||
case variables::ACTION_ON_ERROR_IGNORE_AND_LOG:
|
||||
GRN_LOG(ctx_, GRN_LOG_ERROR, "%s", error_message);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
DBUG_RETURN(rc);
|
||||
}
|
||||
|
||||
void QueryParser::parse_pragma(const char *query,
|
||||
size_t query_length,
|
||||
const char **raw_query,
|
||||
size_t *raw_query_length,
|
||||
grn_operator *default_operator,
|
||||
grn_expr_flags *flags) {
|
||||
MRN_DBUG_ENTER_METHOD();
|
||||
|
||||
const char *current_query = query;
|
||||
size_t current_query_length = query_length;
|
||||
|
||||
*default_operator = GRN_OP_OR;
|
||||
|
||||
if (current_query_length >= 4 && memcmp(current_query, "*SS ", 4) == 0) {
|
||||
*raw_query = current_query + 4;
|
||||
*raw_query_length = current_query_length - 4;
|
||||
*flags = GRN_EXPR_SYNTAX_SCRIPT;
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
bool weight_specified = false;
|
||||
*raw_query = query;
|
||||
*raw_query_length = query_length;
|
||||
*flags = default_expression_flags();
|
||||
if (current_query_length >= 2 && current_query[0] == '*') {
|
||||
bool parsed = false;
|
||||
bool done = false;
|
||||
current_query++;
|
||||
current_query_length--;
|
||||
while (!done) {
|
||||
size_t consumed_query_length = 0;
|
||||
switch (current_query[0]) {
|
||||
case 'D':
|
||||
if (parse_pragma_d(current_query + 1,
|
||||
current_query_length - 1,
|
||||
default_operator,
|
||||
&consumed_query_length)) {
|
||||
parsed = true;
|
||||
consumed_query_length += 1;
|
||||
current_query += consumed_query_length;
|
||||
current_query_length -= consumed_query_length;
|
||||
} else {
|
||||
done = true;
|
||||
}
|
||||
break;
|
||||
case 'W':
|
||||
if (parse_pragma_w(current_query + 1,
|
||||
current_query_length - 1,
|
||||
&consumed_query_length)) {
|
||||
parsed = true;
|
||||
weight_specified = true;
|
||||
consumed_query_length += 1;
|
||||
current_query += consumed_query_length;
|
||||
current_query_length -= consumed_query_length;
|
||||
} else {
|
||||
done = true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (parsed) {
|
||||
*raw_query = current_query;
|
||||
*raw_query_length = current_query_length;
|
||||
}
|
||||
}
|
||||
|
||||
// WORKAROUND: ignore the first '+' to support "+apple macintosh" pattern.
|
||||
while (*raw_query_length > 0 && (*raw_query)[0] == ' ') {
|
||||
(*raw_query)++;
|
||||
(*raw_query_length)--;
|
||||
}
|
||||
if (*raw_query_length > 0 && (*raw_query)[0] == '+') {
|
||||
(*raw_query)++;
|
||||
(*raw_query_length)--;
|
||||
}
|
||||
if (!weight_specified && match_columns_) {
|
||||
grn_expr_append_obj(ctx_, match_columns_, default_column_, GRN_OP_PUSH, 1);
|
||||
}
|
||||
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
bool QueryParser::parse_pragma_w(const char *query,
|
||||
size_t query_length,
|
||||
size_t *consumed_query_length) {
|
||||
MRN_DBUG_ENTER_METHOD();
|
||||
|
||||
*consumed_query_length = 0;
|
||||
|
||||
grn_obj section_value_buffer;
|
||||
GRN_UINT32_INIT(§ion_value_buffer, 0);
|
||||
|
||||
MRN_ALLOCATE_VARIABLE_LENGTH_ARRAYS(bool, specified_sections, n_sections_);
|
||||
for (uint i = 0; i < n_sections_; ++i) {
|
||||
specified_sections[i] = false;
|
||||
}
|
||||
|
||||
uint n_weights = 0;
|
||||
while (query_length >= 1) {
|
||||
if (n_weights >= 1) {
|
||||
if (query[0] != ',') {
|
||||
break;
|
||||
}
|
||||
size_t n_used_query_length = 1;
|
||||
*consumed_query_length += n_used_query_length;
|
||||
query_length -= n_used_query_length;
|
||||
query += n_used_query_length;
|
||||
if (query_length == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uint section = 0;
|
||||
if ('1' <= query[0] && query[0] <= '9') {
|
||||
const char *section_start = query;
|
||||
const char *query_end = query + query_length;
|
||||
const char *query_rest;
|
||||
section = grn_atoui(section_start, query_end, &query_rest);
|
||||
if (section_start == query_rest) {
|
||||
break;
|
||||
}
|
||||
if (!(0 < section && section <= n_sections_)) {
|
||||
break;
|
||||
}
|
||||
section -= 1;
|
||||
specified_sections[section] = true;
|
||||
size_t n_used_query_length = query_rest - query;
|
||||
*consumed_query_length += n_used_query_length;
|
||||
query_length -= n_used_query_length;
|
||||
query += n_used_query_length;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
||||
int weight = 1;
|
||||
if (query_length >= 2 && query[0] == ':') {
|
||||
const char *weight_start = query + 1;
|
||||
const char *query_end = query + query_length;
|
||||
const char *query_rest;
|
||||
weight = grn_atoi(weight_start, query_end, &query_rest);
|
||||
if (weight_start == query_rest) {
|
||||
break;
|
||||
}
|
||||
size_t n_used_query_length = query_rest - query;
|
||||
*consumed_query_length += n_used_query_length;
|
||||
query_length -= n_used_query_length;
|
||||
query += n_used_query_length;
|
||||
}
|
||||
|
||||
n_weights++;
|
||||
|
||||
append_section(section,
|
||||
§ion_value_buffer,
|
||||
weight,
|
||||
n_weights);
|
||||
}
|
||||
|
||||
for (uint section = 0; section < n_sections_; ++section) {
|
||||
if (specified_sections[section]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
++n_weights;
|
||||
|
||||
int default_weight = 1;
|
||||
append_section(section,
|
||||
§ion_value_buffer,
|
||||
default_weight,
|
||||
n_weights);
|
||||
}
|
||||
MRN_FREE_VARIABLE_LENGTH_ARRAYS(specified_sections);
|
||||
|
||||
GRN_OBJ_FIN(ctx_, §ion_value_buffer);
|
||||
|
||||
DBUG_RETURN(n_weights > 0);
|
||||
}
|
||||
|
||||
void QueryParser::append_section(uint section,
|
||||
grn_obj *section_value_buffer,
|
||||
int weight,
|
||||
uint n_weights) {
|
||||
MRN_DBUG_ENTER_METHOD();
|
||||
|
||||
if (!match_columns_) {
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
grn_expr_append_obj(ctx_, match_columns_, default_column_, GRN_OP_PUSH, 1);
|
||||
GRN_UINT32_SET(ctx_, section_value_buffer, section);
|
||||
grn_expr_append_const(ctx_, match_columns_, section_value_buffer,
|
||||
GRN_OP_PUSH, 1);
|
||||
grn_expr_append_op(ctx_, match_columns_, GRN_OP_GET_MEMBER, 2);
|
||||
|
||||
if (weight != 1) {
|
||||
grn_expr_append_const_int(ctx_, match_columns_, weight, GRN_OP_PUSH, 1);
|
||||
grn_expr_append_op(ctx_, match_columns_, GRN_OP_STAR, 2);
|
||||
}
|
||||
|
||||
if (n_weights >= 2) {
|
||||
grn_expr_append_op(ctx_, match_columns_, GRN_OP_OR, 2);
|
||||
}
|
||||
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
bool QueryParser::parse_pragma_d(const char *query,
|
||||
size_t query_length,
|
||||
grn_operator *default_operator,
|
||||
size_t *consumed_query_length) {
|
||||
MRN_DBUG_ENTER_METHOD();
|
||||
|
||||
bool succeeded = true;
|
||||
if (query_length >= 1 && query[0] == '+') {
|
||||
*default_operator = GRN_OP_AND;
|
||||
*consumed_query_length = 1;
|
||||
} else if (query_length >= 1 && query[0] == '-') {
|
||||
*default_operator = GRN_OP_AND_NOT;
|
||||
*consumed_query_length = 1;
|
||||
} else if (query_length >= 2 && memcmp(query, "OR", 2) == 0) {
|
||||
*default_operator = GRN_OP_OR;
|
||||
*consumed_query_length = 2;
|
||||
} else {
|
||||
succeeded = false;
|
||||
}
|
||||
|
||||
DBUG_RETURN(succeeded);
|
||||
}
|
||||
|
||||
grn_expr_flags QueryParser::default_expression_flags() {
|
||||
MRN_DBUG_ENTER_METHOD();
|
||||
|
||||
ulonglong syntax_flags = variables::get_boolean_mode_syntax_flags(thd_);
|
||||
grn_expr_flags expression_flags = 0;
|
||||
if (syntax_flags == variables::BOOLEAN_MODE_SYNTAX_FLAG_DEFAULT) {
|
||||
expression_flags = GRN_EXPR_SYNTAX_QUERY | GRN_EXPR_ALLOW_LEADING_NOT;
|
||||
} else {
|
||||
if (syntax_flags & variables::BOOLEAN_MODE_SYNTAX_FLAG_SYNTAX_SCRIPT) {
|
||||
expression_flags |= GRN_EXPR_SYNTAX_SCRIPT;
|
||||
} else {
|
||||
expression_flags |= GRN_EXPR_SYNTAX_QUERY;
|
||||
}
|
||||
if (syntax_flags & variables::BOOLEAN_MODE_SYNTAX_FLAG_ALLOW_COLUMN) {
|
||||
expression_flags |= GRN_EXPR_ALLOW_COLUMN;
|
||||
}
|
||||
if (syntax_flags & variables::BOOLEAN_MODE_SYNTAX_FLAG_ALLOW_UPDATE) {
|
||||
expression_flags |= GRN_EXPR_ALLOW_UPDATE;
|
||||
}
|
||||
if (syntax_flags & variables::BOOLEAN_MODE_SYNTAX_FLAG_ALLOW_LEADING_NOT) {
|
||||
expression_flags |= GRN_EXPR_ALLOW_LEADING_NOT;
|
||||
}
|
||||
}
|
||||
|
||||
DBUG_RETURN(expression_flags);
|
||||
}
|
||||
}
|
67
storage/mroonga/lib/mrn_query_parser.hpp
Normal file
67
storage/mroonga/lib/mrn_query_parser.hpp
Normal file
@ -0,0 +1,67 @@
|
||||
/* -*- c-basic-offset: 2 -*- */
|
||||
/*
|
||||
Copyright(C) 2017 Kouhei Sutou <kou@clear-code.com>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <mrn_mysql.h>
|
||||
#include <mrn_mysql_compat.h>
|
||||
|
||||
#include <groonga.h>
|
||||
|
||||
namespace mrn {
|
||||
class QueryParser {
|
||||
public:
|
||||
QueryParser(grn_ctx *ctx,
|
||||
THD *thd,
|
||||
grn_obj *expression,
|
||||
grn_obj *default_column,
|
||||
uint n_sections,
|
||||
grn_obj *match_columns=NULL);
|
||||
~QueryParser();
|
||||
|
||||
grn_rc parse(const char *query, size_t query_length);
|
||||
void parse_pragma(const char *query,
|
||||
size_t query_length,
|
||||
const char **raw_query,
|
||||
size_t *raw_query_length,
|
||||
grn_operator *default_operator,
|
||||
grn_expr_flags *flags);
|
||||
|
||||
private:
|
||||
grn_ctx *ctx_;
|
||||
THD *thd_;
|
||||
grn_obj *expression_;
|
||||
grn_obj *default_column_;
|
||||
uint n_sections_;
|
||||
grn_obj *match_columns_;
|
||||
|
||||
bool parse_pragma_w(const char *query,
|
||||
size_t query_length,
|
||||
size_t *consumed_query_length);
|
||||
void append_section(uint section,
|
||||
grn_obj *section_value_buffer,
|
||||
int weight,
|
||||
uint n_weights);
|
||||
bool parse_pragma_d(const char *query,
|
||||
size_t query_length,
|
||||
grn_operator *default_operator,
|
||||
size_t *consumed_query_length);
|
||||
grn_expr_flags default_expression_flags();
|
||||
};
|
||||
}
|
42
storage/mroonga/lib/mrn_smart_bitmap.cpp
Normal file
42
storage/mroonga/lib/mrn_smart_bitmap.cpp
Normal file
@ -0,0 +1,42 @@
|
||||
/* -*- c-basic-offset: 2 -*- */
|
||||
/*
|
||||
Copyright(C) 2017 Kouhei Sutou <kou@clear-code.com>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "mrn_smart_bitmap.hpp"
|
||||
|
||||
namespace mrn {
|
||||
SmartBitmap::SmartBitmap(MY_BITMAP *bitmap)
|
||||
: bitmap_(bitmap) {
|
||||
}
|
||||
|
||||
SmartBitmap::~SmartBitmap() {
|
||||
if (bitmap_) {
|
||||
bitmap_free(bitmap_);
|
||||
}
|
||||
}
|
||||
|
||||
MY_BITMAP *SmartBitmap::get() {
|
||||
return bitmap_;
|
||||
}
|
||||
|
||||
MY_BITMAP *SmartBitmap::release() {
|
||||
MY_BITMAP *bitmap = bitmap_;
|
||||
bitmap_ = NULL;
|
||||
return bitmap;
|
||||
}
|
||||
}
|
36
storage/mroonga/lib/mrn_smart_bitmap.hpp
Normal file
36
storage/mroonga/lib/mrn_smart_bitmap.hpp
Normal file
@ -0,0 +1,36 @@
|
||||
/* -*- c-basic-offset: 2 -*- */
|
||||
/*
|
||||
Copyright(C) 2017 Kouhei Sutou <kou@clear-code.com>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <mrn_mysql.h>
|
||||
#include <my_bitmap.h>
|
||||
|
||||
namespace mrn {
|
||||
class SmartBitmap {
|
||||
public:
|
||||
SmartBitmap(MY_BITMAP *bitmap);
|
||||
~SmartBitmap();
|
||||
|
||||
MY_BITMAP *get();
|
||||
MY_BITMAP *release();
|
||||
private:
|
||||
MY_BITMAP *bitmap_;
|
||||
};
|
||||
}
|
41
storage/mroonga/lib/mrn_table_fields_offset_mover.cpp
Normal file
41
storage/mroonga/lib/mrn_table_fields_offset_mover.cpp
Normal file
@ -0,0 +1,41 @@
|
||||
/* -*- c-basic-offset: 2 -*- */
|
||||
/*
|
||||
Copyright(C) 2017 Kouhei Sutou <kou@clear-code.com>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "mrn_table_fields_offset_mover.hpp"
|
||||
|
||||
namespace mrn {
|
||||
TableFieldsOffsetMover::TableFieldsOffsetMover(TABLE *table,
|
||||
my_ptrdiff_t diff)
|
||||
: table_(table),
|
||||
diff_(diff) {
|
||||
uint n_columns = table_->s->fields;
|
||||
for (uint i = 0; i < n_columns; ++i) {
|
||||
Field *field = table_->field[i];
|
||||
field->move_field_offset(diff_);
|
||||
}
|
||||
}
|
||||
|
||||
TableFieldsOffsetMover::~TableFieldsOffsetMover() {
|
||||
uint n_columns = table_->s->fields;
|
||||
for (uint i = 0; i < n_columns; ++i) {
|
||||
Field *field = table_->field[i];
|
||||
field->move_field_offset(-diff_);
|
||||
}
|
||||
}
|
||||
}
|
33
storage/mroonga/lib/mrn_table_fields_offset_mover.hpp
Normal file
33
storage/mroonga/lib/mrn_table_fields_offset_mover.hpp
Normal file
@ -0,0 +1,33 @@
|
||||
/* -*- c-basic-offset: 2 -*- */
|
||||
/*
|
||||
Copyright(C) 2017 Kouhei Sutou <kou@clear-code.com>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <mrn_mysql.h>
|
||||
|
||||
namespace mrn {
|
||||
class TableFieldsOffsetMover {
|
||||
public:
|
||||
TableFieldsOffsetMover(TABLE *table, my_ptrdiff_t diff);
|
||||
~TableFieldsOffsetMover();
|
||||
private:
|
||||
TABLE *table_;
|
||||
my_ptrdiff_t diff_;
|
||||
};
|
||||
}
|
@ -39,5 +39,8 @@
|
||||
#define ER_MRN_INVALID_INDEX_FLAG_NUM 16508
|
||||
#define ER_MRN_INVALID_INDEX_FLAG_STR \
|
||||
"The index flag '%-.64s' is invalid. It is ignored"
|
||||
#define ER_MRN_KEY_BASED_ON_GENERATED_VIRTUAL_COLUMN_NUM 16509
|
||||
#define ER_MRN_KEY_BASED_ON_GENERATED_VIRTUAL_COLUMN_STR \
|
||||
"Index for virtual generated column is not supported: %s"
|
||||
|
||||
#endif /* MRN_ERR_H_ */
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user