developers
Threads by month
- ----- 2025 -----
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- 6871 discussions

[Maria-developers] bzr commit into MariaDB 5.1, with Maria 1.5:maria branch (knielsen:2764)
by knielsenīŧ knielsen-hq.org 04 Jan '10
by knielsenīŧ knielsen-hq.org 04 Jan '10
04 Jan '10
#At lp:maria
2764 knielsen(a)knielsen-hq.org 2010-01-04
Import OQGraph engine into MariaDB.
added:
mysql-test/suite/oqgraph/
mysql-test/suite/oqgraph/include/
mysql-test/suite/oqgraph/include/have_oqgraph_engine.inc
mysql-test/suite/oqgraph/r/
mysql-test/suite/oqgraph/r/basic.result
mysql-test/suite/oqgraph/t/
mysql-test/suite/oqgraph/t/basic-master.opt
mysql-test/suite/oqgraph/t/basic.test
storage/oqgraph/
storage/oqgraph/CMakeFiles.txt
storage/oqgraph/Makefile.am
storage/oqgraph/graphcore-graph.h
storage/oqgraph/graphcore-types.h
storage/oqgraph/graphcore.cc
storage/oqgraph/graphcore.h
storage/oqgraph/graphstore.c
storage/oqgraph/graphstore.h
storage/oqgraph/ha_oqgraph.cc
storage/oqgraph/ha_oqgraph.h
storage/oqgraph/oqgraph_config.h.in
storage/oqgraph/oqgraph_probes.d
storage/oqgraph/oqgraph_probes.h
storage/oqgraph/plug.in
modified:
BUILD/SETUP.sh
mysql-test/mysql-test-run.pl
=== modified file 'BUILD/SETUP.sh'
--- a/BUILD/SETUP.sh 2009-10-29 00:04:56 +0000
+++ b/BUILD/SETUP.sh 2010-01-04 08:27:50 +0000
@@ -202,7 +202,7 @@ if test -z "$CC" ; then
fi
if test -z "$CXX" ; then
- CXX=gcc
+ CXX=g++
fi
# If ccache (a compiler cache which reduces build time)
=== modified file 'mysql-test/mysql-test-run.pl'
--- a/mysql-test/mysql-test-run.pl 2009-11-06 17:24:38 +0000
+++ b/mysql-test/mysql-test-run.pl 2010-01-04 08:27:50 +0000
@@ -126,7 +126,7 @@ my $path_config_file; # The ge
# executables will be used by the test suite.
our $opt_vs_config = $ENV{'MTR_VS_CONFIG'};
-my $DEFAULT_SUITES= "binlog,federated,main,maria,rpl,innodb,parts";
+my $DEFAULT_SUITES= "binlog,federated,main,maria,rpl,innodb,parts,oqgraph";
our $opt_usage;
our $opt_list_options;
@@ -1933,6 +1933,33 @@ sub environment_setup {
$ENV{'EXAMPLE_PLUGIN_LOAD'}="--plugin_load=;EXAMPLE=".$plugin_filename.";";
}
+ # --------------------------------------------------------------------------
+ # Add the path where mysqld will find graph_engine.so
+ # --------------------------------------------------------------------------
+ if ($mysql_version_id >= 50100 && !(IS_WINDOWS && $opt_embedded_server)) {
+ my $plugin_filename;
+ if (IS_WINDOWS)
+ {
+ $plugin_filename = "oqgraph_engine.dll";
+ }
+ else
+ {
+ $plugin_filename = "oqgraph_engine.so";
+ }
+ my $lib_oqgraph_plugin=
+ mtr_file_exists(vs_config_dirs('storage/oqgraph',$plugin_filename),
+ "$basedir/storage/oqgraph/.libs/".$plugin_filename,
+ "$basedir/lib/mariadb/plugin/".$plugin_filename,
+ "$basedir/lib/mysql/plugin/".$plugin_filename);
+ $ENV{'OQGRAPH_PLUGIN'}=
+ ($lib_oqgraph_plugin ? basename($lib_oqgraph_plugin) : "");
+ $ENV{'OQGRAPH_PLUGIN_OPT'}= "--plugin-dir=".
+ ($lib_oqgraph_plugin ? dirname($lib_oqgraph_plugin) : "");
+
+ $ENV{'GRAPH_ENGINE_SO'}="'".$plugin_filename."'";
+ $ENV{'OQGRAPH_PLUGIN_LOAD'}="--plugin_load=;OQGRAPH=".$plugin_filename.";";
+ }
+
# ----------------------------------------------------
# Add the path where mysqld will find mypluglib.so
# ----------------------------------------------------
=== added directory 'mysql-test/suite/oqgraph'
=== added directory 'mysql-test/suite/oqgraph/include'
=== added file 'mysql-test/suite/oqgraph/include/have_oqgraph_engine.inc'
--- a/mysql-test/suite/oqgraph/include/have_oqgraph_engine.inc 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/oqgraph/include/have_oqgraph_engine.inc 2010-01-04 08:27:50 +0000
@@ -0,0 +1,4 @@
+disable_query_log;
+--require r/true.require
+select (PLUGIN_LIBRARY LIKE 'oqgraph_engine%') as `TRUE` from information_schema.plugins where PLUGIN_NAME='OQGRAPH';
+enable_query_log;
=== added directory 'mysql-test/suite/oqgraph/r'
=== added file 'mysql-test/suite/oqgraph/r/basic.result'
--- a/mysql-test/suite/oqgraph/r/basic.result 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/oqgraph/r/basic.result 2010-01-04 08:27:50 +0000
@@ -0,0 +1,63 @@
+drop table if exists graph;
+Warnings:
+Note 1051 Unknown table 'graph'
+CREATE TABLE graph (
+latch SMALLINT UNSIGNED NULL,
+origid BIGINT UNSIGNED NULL,
+destid BIGINT UNSIGNED NULL,
+weight DOUBLE NULL,
+seq BIGINT UNSIGNED NULL,
+linkid BIGINT UNSIGNED NULL,
+KEY (latch, origid, destid) USING HASH,
+KEY (latch, destid, origid) USING HASH
+) ENGINE=OQGRAPH;
+delete from graph;
+insert into graph(origid, destid) values (1,2), (2,1);
+insert into graph(origid, destid) values (1,3), (3,1);
+insert into graph(origid, destid) values (3,4), (4,3);
+insert into graph(origid, destid) values (3,5), (5,3);
+insert into graph(origid, destid) values (5,6), (6,5);
+select * from graph where latch = 2 and origid = 1 and weight = 1;
+latch origid destid weight seq linkid
+2 1 NULL 1 3 3
+2 1 NULL 1 2 2
+select * from graph where latch = 2 and origid = 1 and weight = 2;
+latch origid destid weight seq linkid
+2 1 NULL 2 5 5
+2 1 NULL 2 4 4
+select * from graph
+where latch = 2 and origid = 1 and (weight = 1 or weight = 2);
+latch origid destid weight seq linkid
+2 1 NULL 2 5 5
+2 1 NULL 2 4 4
+2 1 NULL 1 3 3
+2 1 NULL 1 2 2
+select * from graph where latch=1 and origid=1 and destid=6;
+latch origid destid weight seq linkid
+1 1 6 NULL 0 1
+1 1 6 1 1 3
+1 1 6 1 2 5
+1 1 6 1 3 6
+select * from graph where latch=1 and origid=1 and destid=4;
+latch origid destid weight seq linkid
+1 1 4 NULL 0 1
+1 1 4 1 1 3
+1 1 4 1 2 4
+select * from graph where latch=1 and origid=4 and destid=1;
+latch origid destid weight seq linkid
+1 4 1 NULL 0 4
+1 4 1 1 1 3
+1 4 1 1 2 1
+insert into graph (origid,destid) values (4,6);
+delete from graph where origid=5;
+delete from graph where origid=3 and destid=5;
+select * from graph where latch=1 and origid=1 and destid=6;
+latch origid destid weight seq linkid
+1 1 6 NULL 0 1
+1 1 6 1 1 3
+1 1 6 1 2 4
+1 1 6 1 3 6
+select * from graph where latch=1 and origid=6 and destid=1;
+latch origid destid weight seq linkid
+truncate table graph;
+drop table graph;
=== added directory 'mysql-test/suite/oqgraph/t'
=== added file 'mysql-test/suite/oqgraph/t/basic-master.opt'
--- a/mysql-test/suite/oqgraph/t/basic-master.opt 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/oqgraph/t/basic-master.opt 2010-01-04 08:27:50 +0000
@@ -0,0 +1,2 @@
+$OQGRAPH_PLUGIN_OPT
+$OQGRAPH_PLUGIN_LOAD
=== added file 'mysql-test/suite/oqgraph/t/basic.test'
--- a/mysql-test/suite/oqgraph/t/basic.test 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/oqgraph/t/basic.test 2010-01-04 08:27:50 +0000
@@ -0,0 +1,45 @@
+-- source suite/oqgraph/include/have_oqgraph_engine.inc
+
+drop table if exists graph;
+
+CREATE TABLE graph (
+ latch SMALLINT UNSIGNED NULL,
+ origid BIGINT UNSIGNED NULL,
+ destid BIGINT UNSIGNED NULL,
+ weight DOUBLE NULL,
+ seq BIGINT UNSIGNED NULL,
+ linkid BIGINT UNSIGNED NULL,
+ KEY (latch, origid, destid) USING HASH,
+ KEY (latch, destid, origid) USING HASH
+ ) ENGINE=OQGRAPH;
+
+delete from graph;
+
+insert into graph(origid, destid) values (1,2), (2,1);
+insert into graph(origid, destid) values (1,3), (3,1);
+insert into graph(origid, destid) values (3,4), (4,3);
+insert into graph(origid, destid) values (3,5), (5,3);
+insert into graph(origid, destid) values (5,6), (6,5);
+
+select * from graph where latch = 2 and origid = 1 and weight = 1;
+
+select * from graph where latch = 2 and origid = 1 and weight = 2;
+
+select * from graph
+where latch = 2 and origid = 1 and (weight = 1 or weight = 2);
+
+select * from graph where latch=1 and origid=1 and destid=6;
+select * from graph where latch=1 and origid=1 and destid=4;
+select * from graph where latch=1 and origid=4 and destid=1;
+
+insert into graph (origid,destid) values (4,6);
+
+delete from graph where origid=5;
+delete from graph where origid=3 and destid=5;
+
+select * from graph where latch=1 and origid=1 and destid=6;
+select * from graph where latch=1 and origid=6 and destid=1;
+
+truncate table graph;
+
+drop table graph;
=== added directory 'storage/oqgraph'
=== added file 'storage/oqgraph/CMakeFiles.txt'
--- a/storage/oqgraph/CMakeFiles.txt 1970-01-01 00:00:00 +0000
+++ b/storage/oqgraph/CMakeFiles.txt 2010-01-04 08:27:50 +0000
@@ -0,0 +1,22 @@
+# Copyright (C) 2006 MySQL AB
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX")
+SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX")
+
+INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/sql
+ ${CMAKE_SOURCE_DIR}/regex
+ ${CMAKE_SOURCE_DIR}/extra/yassl/include)
+ADD_LIBRARY(oqgraph ha_oqgraph.cc)
=== added file 'storage/oqgraph/Makefile.am'
--- a/storage/oqgraph/Makefile.am 1970-01-01 00:00:00 +0000
+++ b/storage/oqgraph/Makefile.am 2010-01-04 08:27:50 +0000
@@ -0,0 +1,96 @@
+# Copyright (C) 2007-2009 Arjen G Lentz & Antony T Curtis for Open Query
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+# ======================================================================
+# Open Query Graph Computation Engine, based on a concept by Arjen Lentz
+# Mk.II implementation by Antony Curtis & Arjen Lentz
+# For more information, documentation, support, enhancement engineering,
+# and non-GPL licensing, see http://openquery.com/graph
+# or contact graph(a)openquery.com
+# For packaged binaries, see http://ourdelta.org
+# ======================================================================
+
+mysqlplugindir= $(pkglibdir)/plugin
+
+BOOST_CXXFLAGS = -frtti -fexceptions -fimplicit-templates
+#BOOST_CXXFLAGS+= -g
+#original flags before 2009-11-10
+#BOOST_CXXFLAGS+= -O3 -fomit-frame-pointer -fstrict-aliasing
+#BOOST_CXXFLAGS+= -momit-leaf-frame-pointer -falign-loops
+#modified flags:
+# - remove omit-frame-pointer, x86 specific (fails on PPC) + hinders debugging
+# Option details from gcc man:
+# Don't keep the frame pointer in a register for functions that don't need one.
+# This avoids the instructions to save, set up and restore frame pointers;
+# it also makes an extra register available in many functions.
+# It also makes debugging impossible on some machines.
+# (automatically gets enabled anyway by -O* on some architectures)
+BOOST_CXXFLAGS+= -O3 -fstrict-aliasing
+BOOST_CXXFLAGS+= -falign-loops
+BOOST_CXXFLAGS+= -fvisibility-inlines-hidden
+BOOST_CXXFLAGS+= -funroll-loops -fno-trapping-math
+
+EXTRA_DIST = ha_oqgraph.h ha_oqgraph.cc graphcore.cc \
+ graphcore-graph.h graphcore-types.h graphcore.h \
+ CMakeFiles.txt plug.in oqgraph_probes.d
+
+DTRACE = @DTRACE@
+DTRACEFLAGS = @DTRACEFLAGS@
+DTRACEFILES = .libs/liboqgraph_engine_la-ha_oqgraph.o
+
+ORIG_CXXFLAGS = @CXXFLAGS@
+CXXFLAGS=
+noinst_HEADERS = ha_oqgraph.h \
+ graphcore-graph.h graphcore-types.h graphcore.h \
+ oqgraph_probes.h
+
+noinst_LTLIBRARIES = libgraphcore.la
+libgraphcore_la_SOURCES = graphcore.cc
+libgraphcore_la_CXXFLAGS = $(ORIG_CXXFLAGS) $(BOOST_CXXFLAGS)
+
+if BUILD_OQGRAPH_FOR_MYSQL
+
+if BUILD_OQGRAPH_STANDALONE
+INCLUDES = -DDBUG_ON -DSAFE_MUTEX -DUNIV_MUST_NOT_INLINE -DEXTRA_DEBUG -DFORCE_INIT_OF_VARS -DSAFEMALLOC -DPEDANTIC_SAFEMALLOC -DSAFE_MUTEX -DHAVE_OQGRAPH $(MYSQL_INC)
+else
+INCLUDES = -I$(top_srcdir)/include -I$(top_builddir)/include -I$(top_srcdir)/regex -I$(top_srcdir)/sql -I$(srcdir) -DHAVE_OQGRAPH
+endif !BUILD_OQGRAPH_STANDALONE
+
+EXTRA_LTLIBRARIES = oqgraph_engine.la
+mysqlplugin_LTLIBRARIES = @plugin_oqgraph_shared_target@
+oqgraph_engine_la_SOURCES = ha_oqgraph.cc
+oqgraph_engine_la_LIBADD = libgraphcore.la
+
+if HAVE_DTRACE
+ oqgraph_engine_la_LIBADD += oqgraph_probes.o
+endif
+
+oqgraph_engine_la_LDFLAGS = -module -rpath $(mysqlplugindir)
+oqgraph_engine_la_CFLAGS = $(ORIG_CFLAGS) -DMYSQL_DYNAMIC_PLUGIN
+oqgraph_engine_la_CXXFLAGS = $(ORIG_CXXFLAGS) -DMYSQL_DYNAMIC_PLUGIN
+
+oqgraph_probes.h: oqgraph_probes.d
+ $(DTRACE) $(DTRACEFLAGS) -h -s oqgraph_probes.d
+ mv oqgraph_probes.h oqgraph_probes.h.bak
+ sed "s/#include <unistd.h>//g" oqgraph_probes.h.bak > oqgraph_probes.h
+ rm oqgraph_probes.h.bak
+
+oqgraph_probes.o:
+ $(DTRACE) $(DTRACEFLAGS) -G -s oqgraph_probes.d $(DTRACEFILES)
+
+endif BUILD_OQGRAPH_FOR_MYSQL
+
+# End
=== added file 'storage/oqgraph/graphcore-graph.h'
--- a/storage/oqgraph/graphcore-graph.h 1970-01-01 00:00:00 +0000
+++ b/storage/oqgraph/graphcore-graph.h 2010-01-04 08:27:50 +0000
@@ -0,0 +1,48 @@
+/* Copyright (C) 2007-2009 Arjen G Lentz & Antony T Curtis for Open Query
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+/* ======================================================================
+ Open Query Graph Computation Engine, based on a concept by Arjen Lentz
+ Mk.II implementation by Antony Curtis & Arjen Lentz
+ For more information, documentation, support, enhancement engineering,
+ and non-GPL licensing, see http://openquery.com/graph
+ or contact graph(a)openquery.com
+ For packaged binaries, see http://ourdelta.org
+ ======================================================================
+*/
+
+#ifndef oq_graphcore_graph_h_
+#define oq_graphcore_graph_h_
+
+typedef adjacency_list
+<
+ vecS,
+ vecS,
+ bidirectionalS,
+ VertexInfo,
+ EdgeInfo
+> Graph;
+
+#define GRAPH_WEIGHTMAP(G) get(&EdgeInfo::weight, G)
+typedef property_map<Graph, EdgeWeight EdgeInfo::*>::type weightmap_type;
+
+#define GRAPH_INDEXMAP(G) get(vertex_index, G)
+typedef property_map<Graph, vertex_index_t>::type indexmap_type;
+
+#define GRAPH_IDMAP(G) get(&VertexInfo::id, G)
+typedef property_map<Graph, VertexID VertexInfo::*>::type idmap_type;
+
+#endif
=== added file 'storage/oqgraph/graphcore-types.h'
--- a/storage/oqgraph/graphcore-types.h 1970-01-01 00:00:00 +0000
+++ b/storage/oqgraph/graphcore-types.h 2010-01-04 08:27:50 +0000
@@ -0,0 +1,36 @@
+/* Copyright (C) 2007-2009 Arjen G Lentz & Antony T Curtis for Open Query
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+/* ======================================================================
+ Open Query Graph Computation Engine, based on a concept by Arjen Lentz
+ Mk.II implementation by Antony Curtis & Arjen Lentz
+ For more information, documentation, support, enhancement engineering,
+ and non-GPL licensing, see http://openquery.com/graph
+ or contact graph(a)openquery.com
+ For packaged binaries, see http://ourdelta.org
+ ======================================================================
+*/
+
+#ifndef oq_graphcore_types_h_
+#define oq_graphcore_types_h_
+namespace open_query
+{
+
+ typedef unsigned long long VertexID;
+ typedef double EdgeWeight;
+
+}
+#endif
=== added file 'storage/oqgraph/graphcore.cc'
--- a/storage/oqgraph/graphcore.cc 1970-01-01 00:00:00 +0000
+++ b/storage/oqgraph/graphcore.cc 2010-01-04 08:27:50 +0000
@@ -0,0 +1,1099 @@
+/* Copyright (C) 2007-2009 Arjen G Lentz & Antony T Curtis for Open Query
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+/* ======================================================================
+ Open Query Graph Computation Engine, based on a concept by Arjen Lentz
+ Mk.II implementation by Antony Curtis & Arjen Lentz
+ For more information, documentation, support, enhancement engineering,
+ and non-GPL licensing, see http://openquery.com/graph
+ or contact graph(a)openquery.com
+ For packaged binaries, see http://ourdelta.org
+ ======================================================================
+*/
+
+#include <strings.h>
+
+#define BOOST_ALL_NO_LIB 1
+
+#include <boost/config.hpp>
+
+#include <set>
+#include <stack>
+
+#include <boost/property_map.hpp>
+
+#include <boost/graph/graph_concepts.hpp>
+#include <boost/graph/graph_archetypes.hpp>
+#include <boost/graph/adjacency_list.hpp>
+#include <boost/graph/breadth_first_search.hpp>
+#include <boost/graph/dijkstra_shortest_paths.hpp>
+#include <boost/graph/iteration_macros.hpp>
+#include <boost/graph/reverse_graph.hpp>
+#include <boost/graph/graph_utility.hpp>
+
+#include "graphcore.h"
+
+using namespace open_query;
+using namespace boost;
+
+static const row empty_row = { 0 };
+
+namespace open_query
+{
+ enum vertex_id_t { vertex_id };
+
+ struct VertexInfo {
+ inline VertexInfo() { }
+
+ inline VertexInfo(VertexID _id)
+ : id(_id) { }
+
+ VertexID id;
+ };
+
+ struct EdgeInfo {
+ EdgeWeight weight;
+ };
+}
+
+namespace boost
+{
+ BOOST_INSTALL_PROPERTY(vertex, id);
+
+ namespace graph
+ {
+ template<>
+ struct internal_vertex_name<VertexInfo>
+ {
+ typedef multi_index::member<VertexInfo, VertexID, &VertexInfo::id> type;
+ };
+
+ template<>
+ struct internal_vertex_constructor<VertexInfo>
+ {
+ typedef vertex_from_name<VertexInfo> type;
+ };
+ }
+}
+
+namespace open_query
+{
+
+ #include "graphcore-graph.h"
+
+ typedef graph_traits<Graph>::vertex_descriptor Vertex;
+ typedef graph_traits<Graph>::edge_descriptor Edge;
+
+ typedef std::list<std::pair<Vertex,optional<EdgeWeight> > > shortest_path_list;
+ typedef shortest_path_list::iterator shortest_path_iterator;
+
+ template<typename ID, typename IDMap>
+ class id_equals_t
+ {
+ public:
+ id_equals_t(ID id, IDMap map)
+ : m_id(id), m_map(map)
+ { }
+ template<typename V>
+ bool operator()(V u) const
+ {
+ return m_map[u] == m_id;
+ }
+ private:
+ ID m_id;
+ IDMap m_map;
+ };
+
+ template<typename ID, typename IDMap>
+ inline id_equals_t<ID,IDMap>
+ id_equals(ID id, IDMap idmap)
+ {
+ return id_equals_t<ID,IDMap>(id, idmap);
+ }
+
+ template<typename T, typename Graph>
+ class target_equals_t
+ {
+ public:
+ target_equals_t(T target, Graph &g)
+ : m_target(target), m_g(g)
+ { }
+ template<typename V>
+ bool operator()(V u) const
+ {
+ return target(u, m_g) == m_target;
+ }
+ private:
+ T m_target;
+ Graph &m_g;
+ };
+
+ template<typename T, typename Graph>
+ inline target_equals_t<T,Graph>
+ target_equals(T target, Graph &g)
+ {
+ return target_equals_t<T,Graph>(target, g);
+ }
+
+ template<typename T, typename Graph>
+ class source_equals_t
+ {
+ public:
+ source_equals_t(T source, Graph &g)
+ : m_source(source), m_g(g)
+ { }
+ template<typename V>
+ bool operator()(V u) const
+ {
+ return source(u, m_g) == m_source;
+ }
+ private:
+ T m_source;
+ Graph &m_g;
+ };
+
+ template<typename T, typename Graph>
+ inline source_equals_t<T,Graph>
+ source_equals(T source, Graph &g)
+ {
+ return source_equals_t<T,Graph>(source, g);
+ }
+
+ struct reference
+ {
+ int m_flags;
+ int m_sequence;
+ Vertex m_vertex;
+ Edge m_edge;
+ EdgeWeight m_weight;
+
+ enum
+ {
+ HAVE_SEQUENCE = 1,
+ HAVE_WEIGHT = 2,
+ HAVE_EDGE = 4,
+ };
+
+ inline reference()
+ : m_flags(0), m_sequence(0),
+ m_vertex(graph_traits<Graph>::null_vertex()),
+ m_edge(), m_weight(0)
+ { }
+
+ inline reference(int s, Edge e)
+ : m_flags(HAVE_SEQUENCE | HAVE_EDGE), m_sequence(s),
+ m_vertex(graph_traits<Graph>::null_vertex()),
+ m_edge(e), m_weight(0)
+ { }
+
+ inline reference(int s, Vertex v, const optional<Edge> &e,
+ const optional<EdgeWeight> &w)
+ : m_flags(HAVE_SEQUENCE | (w ? HAVE_WEIGHT : 0) | (e ? HAVE_EDGE : 0)),
+ m_sequence(s), m_vertex(v)
+ {
+ if (w) m_weight= *w;
+ if (e) m_edge= *e;
+ }
+
+ inline reference(int s, Vertex v, Edge e, EdgeWeight w)
+ : m_flags(HAVE_SEQUENCE | HAVE_WEIGHT | HAVE_EDGE),
+ m_sequence(s), m_vertex(v), m_edge(e), m_weight(w)
+ { }
+
+ inline reference(int s, Vertex v, EdgeWeight w)
+ : m_flags(HAVE_SEQUENCE | HAVE_WEIGHT),
+ m_sequence(s), m_vertex(v), m_edge(), m_weight(w)
+ { }
+
+ inline reference(int s, Vertex v)
+ : m_flags(HAVE_SEQUENCE), m_sequence(s), m_vertex(v), m_edge(),
+ m_weight(0)
+ { }
+
+ optional<int> sequence() const
+ {
+ if (m_flags & HAVE_SEQUENCE)
+ {
+ return m_sequence;
+ }
+ return optional<int>();
+ }
+
+ optional<Vertex> vertex() const
+ {
+ if (m_vertex != graph_traits<Graph>::null_vertex())
+ return m_vertex;
+ return optional<Vertex>();
+ }
+
+ optional<Edge> edge() const
+ {
+ if (m_flags & HAVE_EDGE)
+ return m_edge;
+ return optional<Edge>();
+ };
+
+ optional<EdgeWeight> weight() const
+ {
+ if (m_flags & HAVE_WEIGHT)
+ return m_weight;
+ return optional<EdgeWeight>();
+ }
+ };
+}
+
+namespace open_query {
+ class GRAPHCORE_INTERNAL oqgraph_share
+ {
+ public:
+ Graph g;
+
+ weightmap_type weightmap;
+ idmap_type idmap;
+ indexmap_type indexmap;
+
+ optional<Vertex> find_vertex(VertexID id) const;
+ optional<Edge> find_edge(Vertex, Vertex) const;
+
+ inline oqgraph_share() throw()
+ : g(),
+ weightmap(GRAPH_WEIGHTMAP(g)),
+ idmap(GRAPH_IDMAP(g)),
+ indexmap(GRAPH_INDEXMAP(g))
+ { }
+ inline ~oqgraph_share()
+ { }
+ };
+
+ class GRAPHCORE_INTERNAL oqgraph_cursor
+ {
+ public:
+ oqgraph_share *const share;
+
+ inline oqgraph_cursor(oqgraph_share *arg)
+ : share(arg)
+ { }
+ virtual ~oqgraph_cursor()
+ { }
+
+ virtual int fetch_row(const row &, row&) = 0;
+ virtual int fetch_row(const row &, row&, const reference&) = 0;
+ virtual void current(reference& ref) const = 0;
+ };
+}
+
+namespace open_query {
+ class GRAPHCORE_INTERNAL stack_cursor : public oqgraph_cursor
+ {
+ private:
+ optional<EdgeWeight> no_weight;
+ public:
+ int sequence;
+ std::stack<reference> results;
+ reference last;
+
+ inline stack_cursor(oqgraph_share *arg)
+ : oqgraph_cursor(arg), no_weight(), sequence(0), results(), last()
+ { }
+
+ int fetch_row(const row &, row&);
+ int fetch_row(const row &, row&, const reference&);
+
+ void current(reference& ref) const
+ {
+ ref= last;
+ }
+ };
+
+ class GRAPHCORE_INTERNAL vertices_cursor : public oqgraph_cursor
+ {
+ typedef graph_traits<Graph>::vertex_iterator vertex_iterator;
+
+ size_t position;
+ reference last;
+ public:
+ inline vertices_cursor(oqgraph_share *arg)
+ : oqgraph_cursor(arg), position(0)
+ { }
+
+ int fetch_row(const row &, row&);
+ int fetch_row(const row &, row&, const reference&);
+
+ void current(reference& ref) const
+ {
+ ref= last;
+ }
+
+ };
+
+ class GRAPHCORE_INTERNAL edges_cursor : public oqgraph_cursor
+ {
+ typedef graph_traits<Graph>::edge_iterator edge_iterator;
+ typedef edge_iterator::difference_type edge_difference;
+
+ edge_difference position;
+ reference last;
+ public:
+ inline edges_cursor(oqgraph_share *arg)
+ : oqgraph_cursor(arg), position(0), last()
+ { }
+
+ int fetch_row(const row &, row&);
+ int fetch_row(const row &, row&, const reference&);
+
+ void current(reference& ref) const
+ {
+ ref= last;
+ }
+ };
+
+ struct GRAPHCORE_INTERNAL oqgraph_visit_dist
+ : public base_visitor<oqgraph_visit_dist>
+ {
+ typedef on_finish_vertex event_filter;
+
+ oqgraph_visit_dist(std::vector<Vertex>::iterator p,
+ std::vector<EdgeWeight>::iterator d,
+ stack_cursor *cursor)
+ : seq(0), m_cursor(*cursor), m_p(p), m_d(d)
+ { assert(cursor); }
+
+ template<class T, class Graph>
+ void operator()(T u, Graph &g)
+ {
+ m_cursor.results.push(reference(++seq, u, m_d[GRAPH_INDEXMAP(g)[u]]));
+ }
+ private:
+ int seq;
+ stack_cursor &m_cursor;
+ std::vector<Vertex>::iterator m_p;
+ std::vector<EdgeWeight>::iterator m_d;
+ };
+
+ template<bool record_weight, typename goal_filter>
+ struct GRAPHCORE_INTERNAL oqgraph_goal
+ : public base_visitor<oqgraph_goal<record_weight,goal_filter> >
+ {
+ typedef goal_filter event_filter;
+
+ oqgraph_goal(Vertex goal, std::vector<Vertex>::iterator p,
+ stack_cursor *cursor)
+ : m_goal(goal), m_cursor(*cursor), m_p(p)
+ { assert(cursor); }
+
+ template<class T, class Graph>
+ void operator()(T u, Graph &g)
+ {
+ if (u == m_goal)
+ {
+ int seq= 0;
+ indexmap_type indexmap= GRAPH_INDEXMAP(g);
+
+ for (Vertex q, v= u;; v = q, seq++)
+ if ((q= m_p[ indexmap[v] ]) == v)
+ break;
+
+ for (Vertex v= u;; u= v)
+ {
+ optional<Edge> edge;
+ optional<EdgeWeight> weight;
+ v= m_p[ indexmap[u] ];
+ if (record_weight && u != v)
+ {
+ typename graph_traits<Graph>::out_edge_iterator ei, ei_end;
+ for (tie(ei, ei_end)= out_edges(v, g); ei != ei_end; ++ei)
+ {
+ if (target(*ei, g) == u)
+ {
+ edge= *ei;
+ weight= GRAPH_WEIGHTMAP(g)[*ei];
+ break;
+ }
+ }
+ }
+ else if (u != v)
+ weight= 1;
+ m_cursor.results.push(reference(seq--, u, edge, weight));
+ if (u == v)
+ break;
+ }
+ throw this;
+ }
+ }
+
+ private:
+ Vertex m_goal;
+ stack_cursor &m_cursor;
+ std::vector<Vertex>::iterator m_p;
+ };
+}
+
+namespace open_query
+{
+ inline oqgraph::oqgraph(oqgraph_share *arg) throw()
+ : share(arg), cursor(0)
+ { }
+
+ inline oqgraph::~oqgraph() throw()
+ {
+ delete cursor;
+ }
+
+ unsigned oqgraph::edges_count() const throw()
+ {
+ return num_edges(share->g);
+ }
+
+ unsigned oqgraph::vertices_count() const throw()
+ {
+ return num_vertices(share->g);
+ }
+
+ oqgraph* oqgraph::create(oqgraph_share *share) throw()
+ {
+ assert(share != NULL);
+ return new (std::nothrow) oqgraph(share);
+ }
+
+ oqgraph_share* oqgraph::create() throw()
+ {
+ return new (std::nothrow) oqgraph_share();
+ }
+
+ optional<Edge>
+ oqgraph_share::find_edge(Vertex orig, Vertex dest) const
+ {
+ if (in_degree(dest, g) >= out_degree(orig, g))
+ {
+ graph_traits<Graph>::out_edge_iterator ei, ei_end;
+ tie(ei, ei_end)= out_edges(orig, g);
+ if ((ei= find_if(ei, ei_end, target_equals(dest, g))) != ei_end)
+ return *ei;
+ }
+ else
+ {
+ graph_traits<Graph>::in_edge_iterator ei, ei_end;
+ tie(ei, ei_end)= in_edges(dest, g);
+ if ((ei= find_if(ei, ei_end, source_equals(orig, g))) != ei_end)
+ return *ei;
+ }
+ return optional<Edge>();
+ }
+
+ optional<Vertex>
+ oqgraph_share::find_vertex(VertexID id) const
+ {
+ return boost::graph::find_vertex(id, g);
+ }
+
+ int oqgraph::delete_all() throw()
+ {
+ share->g.clear();
+ return 0;
+ }
+
+ int oqgraph::insert_edge(
+ VertexID orig_id, VertexID dest_id, EdgeWeight weight, bool replace) throw()
+ {
+ optional<Vertex> orig, dest;
+ optional<Edge> edge;
+ bool inserted= 0;
+
+ if (weight < 0)
+ return INVALID_WEIGHT;
+ if (!(orig= share->find_vertex(orig_id)))
+ {
+ try
+ {
+ orig= add_vertex(VertexInfo(orig_id), share->g);
+ if (orig == graph_traits<Graph>::null_vertex())
+ return CANNOT_ADD_VERTEX;
+ }
+ catch (...)
+ {
+ return CANNOT_ADD_VERTEX;
+ }
+ }
+ if (!(dest= share->find_vertex(dest_id)))
+ {
+ try
+ {
+ dest= add_vertex(VertexInfo(dest_id), share->g);
+ if (dest == graph_traits<Graph>::null_vertex())
+ return CANNOT_ADD_VERTEX;
+ }
+ catch (...)
+ {
+ return CANNOT_ADD_VERTEX;
+ }
+ }
+ if (!(edge= share->find_edge(*orig, *dest)))
+ {
+ try
+ {
+ tie(edge, inserted)= add_edge(*orig, *dest, share->g);
+ if (!inserted)
+ return CANNOT_ADD_EDGE;
+ }
+ catch (...)
+ {
+ return CANNOT_ADD_EDGE;
+ }
+ }
+ else
+ {
+ if (!replace)
+ return DUPLICATE_EDGE;
+ }
+ share->weightmap[*edge]= weight;
+ return OK;
+ }
+
+ int oqgraph::delete_edge(current_row_st) throw()
+ {
+ reference ref;
+ if (cursor)
+ return EDGE_NOT_FOUND;
+ cursor->current(ref);
+ optional<Edge> edge;
+ if (!(edge= ref.edge()))
+ return EDGE_NOT_FOUND;
+ Vertex orig= source(*edge, share->g);
+ Vertex dest= target(*edge, share->g);
+ remove_edge(*edge, share->g);
+ if (!degree(orig, share->g))
+ remove_vertex(orig, share->g);
+ if (!degree(dest, share->g))
+ remove_vertex(dest, share->g);
+ return OK;
+ }
+
+ int oqgraph::modify_edge(current_row_st,
+ VertexID *orig_id, VertexID *dest_id, EdgeWeight *weight,
+ bool replace) throw()
+ {
+ if (!cursor)
+ return EDGE_NOT_FOUND;
+ reference ref;
+ cursor->current(ref);
+ optional<Edge> edge;
+ if (!(edge= ref.edge()))
+ return EDGE_NOT_FOUND;
+ if (weight && *weight < 0)
+ return INVALID_WEIGHT;
+
+ optional<Vertex> orig= source(*edge, share->g),
+ dest= target(*edge, share->g);
+
+ bool orig_neq= orig_id ? share->idmap[*orig] != *orig_id : 0;
+ bool dest_neq= dest_id ? share->idmap[*dest] != *dest_id : 0;
+ if (orig_neq || dest_neq)
+ {
+ optional<Edge> new_edge;
+ if (orig_neq && !(orig= share->find_vertex(*orig_id)))
+ {
+ try
+ {
+ orig= add_vertex(VertexInfo(*orig_id), share->g);
+ if (orig == graph_traits<Graph>::null_vertex())
+ return CANNOT_ADD_VERTEX;
+ }
+ catch (...)
+ {
+ return CANNOT_ADD_VERTEX;
+ }
+ }
+ if (dest_neq && !(dest= share->find_vertex(*dest_id)))
+ {
+ try
+ {
+ dest= add_vertex(VertexInfo(*dest_id), share->g);
+ if (dest == graph_traits<Graph>::null_vertex())
+ return CANNOT_ADD_VERTEX;
+ }
+ catch (...)
+ {
+ return CANNOT_ADD_VERTEX;
+ }
+ }
+ if (!(new_edge= share->find_edge(*orig, *dest)))
+ {
+ try
+ {
+ bool inserted;
+ tie(new_edge, inserted)= add_edge(*orig, *dest, share->g);
+ if (!inserted)
+ return CANNOT_ADD_EDGE;
+ }
+ catch (...)
+ {
+ return CANNOT_ADD_EDGE;
+ }
+ }
+ else
+ {
+ if (!replace)
+ return DUPLICATE_EDGE;
+ }
+ share->weightmap[*new_edge]= share->weightmap[*edge];
+ remove_edge(*edge, share->g);
+ edge= new_edge;
+ }
+ if (weight)
+ share->weightmap[*edge]= *weight;
+ return OK;
+ }
+
+ int oqgraph::modify_edge(
+ VertexID orig_id, VertexID dest_id, EdgeWeight weight) throw()
+ {
+ optional<Vertex> orig, dest;
+ optional<Edge> edge;
+
+ if (weight < 0)
+ return INVALID_WEIGHT;
+ if (!(orig= share->find_vertex(orig_id)))
+ return EDGE_NOT_FOUND;
+ if (!(dest= share->find_vertex(dest_id)))
+ return EDGE_NOT_FOUND;
+ if (!(edge= share->find_edge(*orig, *dest)))
+ return EDGE_NOT_FOUND;
+ share->weightmap[*edge]= weight;
+ return OK;
+ }
+
+
+ int oqgraph::delete_edge(VertexID orig_id, VertexID dest_id) throw()
+ {
+ optional<Vertex> orig, dest;
+ optional<Edge> edge;
+
+ if (!(orig= share->find_vertex(orig_id)))
+ return EDGE_NOT_FOUND;
+ if (!(dest= share->find_vertex(dest_id)))
+ return EDGE_NOT_FOUND;
+ if (!(edge= share->find_edge(*orig, *dest)))
+ return EDGE_NOT_FOUND;
+ remove_edge(*edge, share->g);
+ if (!degree(*orig, share->g))
+ remove_vertex(*orig, share->g);
+ if (!degree(*dest, share->g))
+ remove_vertex(*dest, share->g);
+ return OK;
+ }
+
+
+ int oqgraph::search(int *latch, VertexID *orig_id, VertexID *dest_id) throw()
+ {
+ optional<Vertex> orig, dest;
+ int op= 0, seq= 0;
+ enum {
+ NO_SEARCH = 0,
+ DIJKSTRAS = 1,
+ BREADTH_FIRST = 2,
+
+ ALGORITHM = 0x0ffff,
+ HAVE_ORIG = 0x10000,
+ HAVE_DEST = 0x20000,
+ };
+
+ delete cursor; cursor= 0;
+ row_info= empty_row;
+ if ((row_info.latch_indicator= latch))
+ op= ALGORITHM & (row_info.latch= *latch);
+ if ((row_info.orig_indicator= orig_id) && (op|= HAVE_ORIG))
+ orig= share->find_vertex((row_info.orig= *orig_id));
+ if ((row_info.dest_indicator= dest_id) && (op|= HAVE_DEST))
+ dest= share->find_vertex((row_info.dest= *dest_id));
+ //try
+ //{
+ switch (op)
+ {
+ case NO_SEARCH | HAVE_ORIG | HAVE_DEST:
+ case NO_SEARCH | HAVE_ORIG:
+ if ((cursor= new (std::nothrow) stack_cursor(share)) && orig)
+ {
+ graph_traits<Graph>::out_edge_iterator ei, ei_end;
+ for (tie(ei, ei_end)= out_edges(*orig, share->g); ei != ei_end; ++ei)
+ {
+ Vertex v= target(*ei, share->g);
+ static_cast<stack_cursor*>(cursor)->
+ results.push(reference(++seq, v, *ei, share->weightmap[*ei]));
+ }
+ }
+ /* fall through */
+ case NO_SEARCH | HAVE_DEST:
+ if ((op & HAVE_DEST) &&
+ (cursor || (cursor= new (std::nothrow) stack_cursor(share))) &&
+ dest)
+ {
+ graph_traits<Graph>::in_edge_iterator ei, ei_end;
+ for (tie(ei, ei_end)= in_edges(*dest, share->g); ei != ei_end; ++ei)
+ {
+ Vertex v= source(*ei, share->g);
+ static_cast<stack_cursor*>(cursor)->
+ results.push(reference(++seq, v, *ei, share->weightmap[*ei]));
+ }
+ }
+ break;
+
+ case NO_SEARCH:
+ cursor= new (std::nothrow) vertices_cursor(share);
+ break;
+
+ case DIJKSTRAS | HAVE_ORIG | HAVE_DEST:
+ if ((cursor= new (std::nothrow) stack_cursor(share)) && orig && dest)
+ {
+ std::vector<Vertex> p(num_vertices(share->g));
+ std::vector<EdgeWeight> d(num_vertices(share->g));
+ oqgraph_goal<true, on_finish_vertex>
+ vis(*dest, p.begin(), static_cast<stack_cursor*>(cursor));
+ p[share->indexmap[*orig]]= *orig;
+ try
+ {
+ dijkstra_shortest_paths(share->g, *orig,
+ weight_map(
+ share->weightmap
+ ).
+ distance_map(
+ make_iterator_property_map(d.begin(), share->indexmap)
+ ).
+ predecessor_map(
+ make_iterator_property_map(p.begin(), share->indexmap)
+ ).
+ visitor(
+ make_dijkstra_visitor(vis)
+ )
+ );
+ }
+ catch (...)
+ { /* printf("found\n"); */ }
+ }
+ break;
+
+ case BREADTH_FIRST | HAVE_ORIG | HAVE_DEST:
+ if ((cursor= new (std::nothrow) stack_cursor(share)) && orig && dest)
+ {
+ std::vector<Vertex> p(num_vertices(share->g));
+ oqgraph_goal<false, on_discover_vertex>
+ vis(*dest, p.begin(), static_cast<stack_cursor*>(cursor));
+ p[share->indexmap[*orig]]= *orig;
+ try
+ {
+ breadth_first_search(share->g, *orig,
+ visitor(make_bfs_visitor(
+ std::make_pair(
+ record_predecessors(
+ make_iterator_property_map(p.begin(), share->indexmap),
+ on_tree_edge()
+ ),
+ vis)
+ )
+ )
+ );
+ }
+ catch (...)
+ { /* printf("found\n"); */ }
+ }
+ break;
+
+ case DIJKSTRAS | HAVE_ORIG:
+ case BREADTH_FIRST | HAVE_ORIG:
+ if ((cursor= new (std::nothrow) stack_cursor(share)) && (orig || dest))
+ {
+ std::vector<Vertex> p(num_vertices(share->g));
+ std::vector<EdgeWeight> d(num_vertices(share->g));
+ oqgraph_visit_dist vis(p.begin(), d.begin(),
+ static_cast<stack_cursor*>(cursor));
+ p[share->indexmap[*orig]]= *orig;
+ switch (ALGORITHM & op)
+ {
+ case DIJKSTRAS:
+ dijkstra_shortest_paths(share->g, *orig,
+ weight_map(
+ share->weightmap
+ ).
+ distance_map(
+ make_iterator_property_map(d.begin(), share->indexmap)
+ ).
+ predecessor_map(
+ make_iterator_property_map(p.begin(), share->indexmap)
+ ).
+ visitor(
+ make_dijkstra_visitor(vis)
+ )
+ );
+ break;
+ case BREADTH_FIRST:
+ breadth_first_search(share->g, *orig,
+ visitor(make_bfs_visitor(
+ std::make_pair(
+ record_predecessors(
+ make_iterator_property_map(p.begin(),
+ share->indexmap),
+ on_tree_edge()
+ ),
+ std::make_pair(
+ record_distances(
+ make_iterator_property_map(d.begin(),
+ share->indexmap),
+ on_tree_edge()
+ ),
+ vis
+ ))
+ ))
+ );
+ break;
+ default:
+ abort();
+ }
+ }
+ break;
+
+ case BREADTH_FIRST | HAVE_DEST:
+ case DIJKSTRAS | HAVE_DEST:
+ if ((cursor= new (std::nothrow) stack_cursor(share)) && (orig || dest))
+ {
+ std::vector<Vertex> p(num_vertices(share->g));
+ std::vector<EdgeWeight> d(num_vertices(share->g));
+ oqgraph_visit_dist vis(p.begin(), d.begin(),
+ static_cast<stack_cursor*>(cursor));
+ reverse_graph<Graph> r(share->g);
+ p[share->indexmap[*dest]]= *dest;
+ switch (ALGORITHM & op)
+ {
+ case DIJKSTRAS:
+ dijkstra_shortest_paths(r, *dest,
+ weight_map(
+ share->weightmap
+ ).
+ distance_map(
+ make_iterator_property_map(d.begin(), share->indexmap)
+ ).
+ predecessor_map(
+ make_iterator_property_map(p.begin(), share->indexmap)
+ ).
+ visitor(
+ make_dijkstra_visitor(vis)
+ )
+ );
+ break;
+ case BREADTH_FIRST:
+ breadth_first_search(r, *dest,
+ visitor(make_bfs_visitor(
+ std::make_pair(
+ record_predecessors(
+ make_iterator_property_map(p.begin(),
+ share->indexmap),
+ on_tree_edge()
+ ),
+ std::make_pair(
+ record_distances(
+ make_iterator_property_map(d.begin(),
+ share->indexmap),
+ on_tree_edge()
+ ),
+ vis
+ ))
+ ))
+ );
+ break;
+ default:
+ abort();
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+ return 0;
+ //}
+ //catch (...)
+ //{
+ // return MISC_FAIL;
+ //}
+ }
+
+ int oqgraph::fetch_row(row& result) throw()
+ {
+ if (!cursor)
+ return NO_MORE_DATA;
+ return cursor->fetch_row(row_info, result);
+ }
+
+ int oqgraph::fetch_row(row& result, const void* ref_ptr) throw()
+ {
+ const reference &ref= *(const reference*) ref_ptr;
+ if (!cursor)
+ return NO_MORE_DATA;
+ return cursor->fetch_row(row_info, result, ref);
+ }
+
+ void oqgraph::row_ref(void *ref_ptr) throw()
+ {
+ reference &ref= *(reference*) ref_ptr;
+ if (cursor)
+ cursor->current(ref);
+ else
+ ref= reference();
+ }
+
+ int oqgraph::random(bool scan) throw()
+ {
+ if (scan || !cursor)
+ {
+ delete cursor; cursor= 0;
+ if (!(cursor= new (std::nothrow) edges_cursor(share)))
+ return MISC_FAIL;
+ }
+ row_info= empty_row;
+ return OK;
+ }
+
+ void oqgraph::free(oqgraph *graph) throw()
+ {
+ delete graph;
+ }
+
+ void oqgraph::free(oqgraph_share *graph) throw()
+ {
+ delete graph;
+ }
+
+ const size_t oqgraph::sizeof_ref= sizeof(reference);
+}
+
+int stack_cursor::fetch_row(const row &row_info, row &result)
+{
+ if (!results.empty())
+ {
+ if (int res= fetch_row(row_info, result, results.top()))
+ return res;
+ results.pop();
+ return oqgraph::OK;
+ }
+ else
+ {
+ last= reference();
+ return oqgraph::NO_MORE_DATA;
+ }
+}
+
+int stack_cursor::fetch_row(const row &row_info, row &result,
+ const reference &ref)
+{
+ last= ref;
+ if (optional<Vertex> v= last.vertex())
+ {
+ optional<int> seq;
+ optional<EdgeWeight> w;
+ optional<Vertex> v;
+ result= row_info;
+ if ((result.seq_indicator= seq= last.sequence()))
+ result.seq= *seq;
+ if ((result.link_indicator= v= last.vertex()))
+ result.link= share->idmap[*v];
+ if ((result.weight_indicator= w= last.weight()))
+ result.weight= *w;
+ return oqgraph::OK;
+ }
+ else
+ return oqgraph::NO_MORE_DATA;
+}
+
+
+int vertices_cursor::fetch_row(const row &row_info, row &result)
+{
+ vertex_iterator it, end;
+ reference ref;
+ size_t count= position;
+ for (tie(it, end)= vertices(share->g); count && it != end; ++it, --count);
+ if (it != end)
+ ref= reference(position+1, *it);
+ if (int res= fetch_row(row_info, result, ref))
+ return res;
+ position++;
+ return oqgraph::OK;
+}
+
+int vertices_cursor::fetch_row(const row &row_info, row &result,
+ const reference &ref)
+{
+ last= ref;
+ optional<Vertex> v= last.vertex();
+ result= row_info;
+ if (v)
+ {
+ result.link_indicator= 1;
+ result.link= share->idmap[*v];
+#ifdef DISPLAY_VERTEX_INFO
+ result.seq_indicator= 1;
+ if ((result.seq= degree(*v, share->g)))
+ {
+ EdgeWeight weight= 0;
+ graph_traits<Graph>::in_edge_iterator iei, iei_end;
+ for (tie(iei, iei_end)= in_edges(*v, share->g); iei != iei_end; ++iei)
+ weight+= share->weightmap[*iei];
+ graph_traits<Graph>::out_edge_iterator oei, oei_end;
+ for (tie(oei, oei_end)= out_edges(*v, share->g); oei != oei_end; ++oei)
+ weight+= share->weightmap[*oei];
+ result.weight_indicator= 1;
+ result.weight= weight / result.seq;
+ }
+#endif
+ return oqgraph::OK;
+ }
+ else
+ return oqgraph::NO_MORE_DATA;
+}
+
+int edges_cursor::fetch_row(const row &row_info, row &result)
+{
+ edge_iterator it, end;
+ reference ref;
+ size_t count= position;
+ for (tie(it, end)= edges(share->g); count && it != end; ++it, --count);
+ if (it != end)
+ ref= reference(position+1, *it);
+ if (int res= fetch_row(row_info, result, ref))
+ return res;
+ ++position;
+ return oqgraph::OK;
+}
+
+int edges_cursor::fetch_row(const row &row_info, row &result,
+ const reference &ref)
+{
+ optional<Edge> edge;
+ if ((edge= (last= ref).edge()))
+ {
+ result= row_info;
+ result.orig_indicator= result.dest_indicator= result.weight_indicator= 1;
+ result.orig= share->idmap[ source( *edge, share->g ) ];
+ result.dest= share->idmap[ target( *edge, share->g ) ];
+ result.weight= share->weightmap[ *edge ];
+ return oqgraph::OK;
+ }
+ return oqgraph::NO_MORE_DATA;
+}
+
+namespace boost {
+ GRAPHCORE_INTERNAL void throw_exception(std::exception const&)
+ {
+ abort();
+ }
+}
=== added file 'storage/oqgraph/graphcore.h'
--- a/storage/oqgraph/graphcore.h 1970-01-01 00:00:00 +0000
+++ b/storage/oqgraph/graphcore.h 2010-01-04 08:27:50 +0000
@@ -0,0 +1,116 @@
+/* Copyright (C) 2007-2009 Arjen G Lentz & Antony T Curtis for Open Query
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+/* ======================================================================
+ Open Query Graph Computation Engine, based on a concept by Arjen Lentz
+ Mk.II implementation by Antony Curtis & Arjen Lentz
+ For more information, documentation, support, enhancement engineering,
+ and non-GPL licensing, see http://openquery.com/graph
+ or contact graph(a)openquery.com
+ For packaged binaries, see http://ourdelta.org
+ ======================================================================
+*/
+
+#ifndef oq_graphcore_h_
+#define oq_graphcore_h_
+
+/* #define GRAPHCORE_INTERNAL __attribute__((visibility("hidden"))) */
+#define GRAPHCORE_INTERNAL
+
+#include "graphcore-types.h"
+
+namespace open_query
+{
+ class oqgraph_share;
+ class oqgraph_cursor;
+
+ struct row
+ {
+ bool latch_indicator;
+ bool orig_indicator;
+ bool dest_indicator;
+ bool weight_indicator;
+ bool seq_indicator;
+ bool link_indicator;
+
+ int latch;
+ VertexID orig;
+ VertexID dest;
+ EdgeWeight weight;
+ unsigned seq;
+ VertexID link;
+ };
+
+ class oqgraph
+ {
+ oqgraph_share *const share;
+ oqgraph_cursor *cursor;
+ row row_info;
+
+ inline oqgraph(oqgraph_share*) throw();
+ inline ~oqgraph() throw();
+ public:
+
+ enum error_code
+ {
+ OK= 0,
+ NO_MORE_DATA,
+ EDGE_NOT_FOUND,
+ INVALID_WEIGHT,
+ DUPLICATE_EDGE,
+ CANNOT_ADD_VERTEX,
+ CANNOT_ADD_EDGE,
+ MISC_FAIL
+ };
+
+ struct current_row_st {};
+ static inline current_row_st current_row()
+ { return current_row_st(); }
+
+ unsigned vertices_count() const throw();
+ unsigned edges_count() const throw();
+
+ int delete_all(void) throw();
+
+ int insert_edge(VertexID, VertexID, EdgeWeight, bool=0) throw();
+ int modify_edge(VertexID, VertexID, EdgeWeight) throw();
+ int delete_edge(VertexID, VertexID) throw();
+
+ int modify_edge(current_row_st,
+ VertexID*, VertexID*, EdgeWeight*, bool=0) throw();
+ int delete_edge(current_row_st) throw();
+
+ int replace_edge(VertexID orig, VertexID dest, EdgeWeight weight) throw()
+ { return insert_edge(orig, dest, weight, true); }
+
+ int search(int*, VertexID*, VertexID*) throw();
+ int random(bool) throw();
+
+ int fetch_row(row&) throw();
+ int fetch_row(row&, const void*) throw();
+ void row_ref(void*) throw();
+
+ static oqgraph* create(oqgraph_share*) throw();
+ static oqgraph_share *create() throw();
+
+ static void free(oqgraph*) throw();
+ static void free(oqgraph_share*) throw();
+
+ static const size_t sizeof_ref;
+ };
+
+}
+#endif
=== added file 'storage/oqgraph/graphstore.c'
--- a/storage/oqgraph/graphstore.c 1970-01-01 00:00:00 +0000
+++ b/storage/oqgraph/graphstore.c 2010-01-04 08:27:50 +0000
@@ -0,0 +1,356 @@
+/*
+ * Graph Engine - Copyright (C) 2007 by Arjen Lentz (arjen(a)openquery.com.au)
+ * graphstore.c internal storage system
+ */
+#include <stdlib.h>
+#include <string.h>
+#include <my_global.h>
+#include <my_sys.h>
+#include "graphstore.h"
+
+
+/*
+ create a new vertex, and add it to the list (or start a list)
+ NOTE! gspp is ptr to base ptr
+
+ returns 1 for ok, 0 for error
+*/
+static int _add_vertex (GRAPHSTORE **gspp, GRAPH_VERTEXID id)
+{
+ GRAPHSTORE *newgsp;
+ GRAPHSTORE *gscurp;
+
+ if (gspp == NULL)
+ return 0;
+
+ /* not allowing 0 */
+ if (!id)
+ return 0;
+
+ if (*gspp != NULL) {
+ for (gscurp = *gspp; gscurp != NULL; gscurp = gscurp->next) {
+ if (gscurp->vertex->id == id)
+ return 1; /* we can ignore, id already exists */
+ }
+ }
+
+ /* allocate and initialise */
+ if ((newgsp = my_malloc(sizeof (GRAPHSTORE),MYF(MY_ZEROFILL))) == NULL)
+ return 0;
+
+ if ((newgsp->vertex = my_malloc(sizeof (GRAPH_VERTEX),MYF(MY_ZEROFILL))) == NULL) {
+ my_free(newgsp,MYF(0));
+ return 0;
+ }
+
+ newgsp->vertex->id = id;
+ /* add new vertex to end of list */
+ if (*gspp != NULL) {
+ for (gscurp = *gspp; gscurp->next != NULL; gscurp = gscurp->next);
+ gscurp->next = newgsp;
+ }
+ else /* new list */
+ *gspp = newgsp;
+
+ /* ok */
+ return 1;
+}
+
+
+/*
+ find a vertex by id
+
+ returns ptr or NULL
+*/
+static GRAPH_VERTEX *_find_vertex (GRAPHSTORE *gsp, GRAPH_VERTEXID id)
+{
+ /* just loop through the list to find id */
+ while (gsp != NULL && gsp->vertex->id != id)
+ gsp = gsp->next;
+
+ /* return ptr to vertex, or NULL */
+ return (gsp != NULL ? gsp->vertex : NULL);
+}
+
+
+/*
+ add edge
+ both vertices must already exist; graphstore_insert() does this
+
+ return 1 for ok, 0 for error (already exists, alloc error, etc)
+*/
+static int _add_edge (GRAPHSTORE *gsp, GRAPH_VERTEXID origid, GRAPH_VERTEXID destid, GRAPH_WEIGHT weight)
+{
+ GRAPH_VERTEX *origvp, *destvp;
+ GRAPH_EDGE *ep, *newep;
+
+ /* find both vertices */
+ if ((origvp = _find_vertex(gsp,origid)) == NULL ||
+ (destvp = _find_vertex(gsp,destid)) == NULL)
+ return 0;
+
+ /* check if edge already exists */
+ for (ep = origvp->forward_edge; ep != NULL; ep = ep->next_edge) {
+ if (ep->vertex->id == destid)
+ return 0;
+ }
+
+ /* allocate and initialise new edge */
+ if ((newep = my_malloc(sizeof (GRAPH_EDGE),MYF(MY_ZEROFILL))) == NULL)
+ return 0;
+
+ newep->vertex = destvp;
+ newep->weight = weight;
+
+ /* insert new edge at start of chain, that's easiest */
+ ep = origvp->forward_edge;
+ origvp->forward_edge = newep;
+ newep->next_edge = ep;
+
+ /* ok */
+ return 1;
+}
+
+
+/*
+ create a new row, and add it to the graph set (or start set)
+ NOTE! gsetpp is ptr to base ptr
+
+ returns 1 for ok, 0 for error
+*/
+static int _add_graph_set (GRAPH_SET **gsetpp, GRAPH_TUPLE *gtp)
+{
+ GRAPH_SET *newgsetp;
+ GRAPH_SET *gsetcurp;
+
+ if (gsetpp == NULL || gtp == NULL)
+ return 0;
+
+ /* allocate and initialise */
+ if ((newgsetp = my_malloc(sizeof (GRAPH_SET),MYF(MY_ZEROFILL))) == NULL)
+ return 0;
+
+ /* put in the data */
+ memcpy(&newgsetp->tuple,gtp,sizeof (GRAPH_TUPLE));
+
+ /* add new row to end of set */
+ if (*gsetpp != NULL) {
+ for (gsetcurp = *gsetpp; gsetcurp->next != NULL; gsetcurp = gsetcurp->next);
+ gsetcurp->next = newgsetp;
+ }
+ else { /* new set */
+ *gsetpp = newgsetp;
+ }
+
+ /* ok */
+ return 1;
+}
+
+
+/*
+ free a graph set (release memory)
+
+ returns 1 for ok, 0 for error
+*/
+int free_graph_set (GRAPH_SET *gsetp)
+{
+ GRAPH_SET *nextgsetp;
+
+ if (gsetp == NULL)
+ return 0;
+
+ while (gsetp != NULL) {
+ nextgsetp = gsetp->next;
+ /* free() is a void function, nothing to check */
+ my_free(gsetp,MYF(0));
+ gsetp = nextgsetp;
+ }
+
+ /* ok */
+ return 1;
+}
+
+
+/*
+ insert new data into graphstore
+ this can be either a vertex or an edge, depending on the params
+ NOTE! gspp is ptr to base ptr
+
+ returns 1 for ok, 0 for error
+*/
+int graphstore_insert (GRAPHSTORE **gspp, GRAPH_TUPLE *gtp)
+{
+ if (gspp == NULL)
+ return 0;
+
+ /* if nada or no orig vertex, we can't do anything */
+ if (gtp == NULL || !gtp->origid)
+ return 0;
+
+#if 0
+printf("inserting: origid=%lu destid=%lu weight=%lu\n",gtp->origid,gtp->destid,gtp->weight);
+#endif
+
+ if (!gtp->destid) /* no edge param so just adding vertex */
+ return _add_vertex(gspp,gtp->origid);
+
+ /*
+ add an edge
+ first add both vertices just in case they didn't yet exist...
+ not checking result there: if there's a prob, _add_edge() will catch.
+ */
+ _add_vertex(gspp,gtp->origid);
+ _add_vertex(gspp,gtp->destid);
+ return _add_edge(*gspp,gtp->origid,gtp->destid,gtp->weight);
+}
+
+
+/*
+ this is an internal function used by graphstore_query()
+
+ find any path from originating vertex to destid
+ if found, add to the result set on the way back
+ NOTE: recursive function!
+
+ returns 1 for hit, 0 for nothing, -1 for error
+*/
+int _find_any_path(GRAPH_SET **gsetpp, GRAPH_VERTEXID origid, GRAPH_VERTEXID destid, GRAPH_VERTEX *gvp, GRAPH_SEQ depth)
+{
+ GRAPH_EDGE *gep;
+ GRAPH_TUPLE tup;
+ int res;
+
+ if (gvp->id == destid) {
+ /* found target! */
+ bzero(&tup,sizeof (GRAPH_TUPLE));
+ tup.origid = origid;
+ tup.destid = destid;
+ tup.seq = depth;
+ tup.linkid = gvp->id;
+ return (_add_graph_set(gsetpp,&tup) ? 1 : -1);
+ }
+
+ /* walk through all edges for this vertex */
+ for (gep = gvp->forward_edge; gep; gep = gep->next_edge) {
+ /* recurse */
+ res = _find_any_path(gsetpp,origid,destid,gep->vertex,depth+1);
+ if (res < 0)
+ return res;
+ if (res > 0) {
+ /* found somewhere below this one, insert ourselves and return */
+ bzero(&tup,sizeof (GRAPH_TUPLE));
+ tup.origid = origid;
+ tup.destid = destid;
+ tup.weight = gep->weight;
+ tup.seq = depth;
+ tup.linkid = gvp->id;
+ return (_add_graph_set(gsetpp,&tup) ? 1 : -1);
+ }
+ }
+
+ /* nothing found but no error */
+ return 0;
+}
+
+
+/*
+ query graphstore
+ latch specifies what operation to perform
+
+ we need to feed the conditions in... (through engine condition pushdown)
+ for now we just presume one condition per field so we just feed in a tuple
+ this also means we can just find constants, not ranges
+
+ return ptr to GRAPH_SET
+ caller must free with free_graph_set()
+*/
+GRAPH_SET *graphstore_query (GRAPHSTORE *gsp, GRAPH_TUPLE *gtp)
+{
+ GRAPH_SET *gsetp = NULL;
+ GRAPH_SET *gsetcurp;
+ GRAPH_SET *newgsetp;
+
+ if (gsp == NULL || gtp == NULL)
+ return (NULL);
+
+ switch (gtp->latch) {
+ case 0: /* return all vertices/edges */
+ {
+ GRAPHSTORE *gscurp;
+ GRAPH_EDGE *gep;
+ GRAPH_TUPLE tup;
+
+ /* walk through all vertices */
+ for (gscurp = gsp; gscurp != NULL; gscurp = gscurp->next) {
+ /* check for condition */
+ if (gtp->origid && gscurp->vertex->id != gtp->origid)
+ continue;
+
+ bzero(&tup,sizeof (GRAPH_TUPLE));
+ tup.origid = gscurp->vertex->id;
+
+ /* no edges? */
+ if (gscurp->vertex->forward_edge == NULL) {
+ /* just add vertex to set */
+ if (!_add_graph_set(&gsetp,&tup)) {
+ if (gsetp != NULL) /* clean up */
+ my_free(gsetp,MYF(0));
+ return (NULL);
+ }
+ }
+ else {
+ /* walk through all edges */
+ for (gep = gscurp->vertex->forward_edge; gep; gep = gep->next_edge) {
+ tup.destid = gep->vertex->id;
+ tup.weight = gep->weight;
+
+ /* just add vertex to set */
+ if (!_add_graph_set(&gsetp,&tup)) {
+ if (gsetp != NULL) /* clean up */
+ my_free(gsetp,MYF(0));
+ return (NULL);
+ }
+ }
+ }
+ }
+ }
+ break;
+
+ case 1: /* find a path between origid and destid */
+ /* yes it'll just go with the first path it finds! */
+ {
+ GRAPHSTORE *gscurp;
+ GRAPH_VERTEX *origvp;
+ GRAPH_TUPLE tup;
+
+ if (!gtp->origid || !gtp->destid)
+ return NULL;
+
+ /* find both vertices */
+ if ((origvp = _find_vertex(gsp,gtp->origid)) == NULL ||
+ _find_vertex(gsp,gtp->destid) == NULL)
+ return NULL;
+
+ if (_find_any_path(&gsetp,gtp->origid,gtp->destid,origvp,0) < 0) { /* error? */
+ if (gsetp != NULL) /* clean up */
+ my_free(gsetp,MYF(0));
+ return NULL;
+ }
+ }
+ break;
+
+ default:
+ /* this ends up being an empty set */
+ break;
+ }
+
+ /* Fix up latch column with the proper value - to be relationally correct */
+ for (gsetcurp = gsetp; gsetcurp != NULL; gsetcurp = gsetcurp->next)
+ gsetcurp->tuple.latch = gtp->latch;
+
+ return gsetp;
+}
+
+
+
+/* end of graphstore.c */
\ No newline at end of file
=== added file 'storage/oqgraph/graphstore.h'
--- a/storage/oqgraph/graphstore.h 1970-01-01 00:00:00 +0000
+++ b/storage/oqgraph/graphstore.h 2010-01-04 08:27:50 +0000
@@ -0,0 +1,90 @@
+/*
+ * Graph Engine - Copyright (C) 2007 by Arjen Lentz (arjen(a)openquery.com.au)
+ * graphstore.h internal storage system
+ */
+//typedef unsigned short uint16;
+//typedef unsigned long long uint64;
+
+
+/*
+ This is essentially what a GRAPH engine table looks like on the MySQL end:
+ CREATE TABLE foo (
+ latch SMALLINT UNSIGNED NULL,
+ origid BIGINT UNSIGNED NULL,
+ destid BIGINT UNSIGNED NULL,
+ weight BIGINT UNSIGNED NULL,
+ seq BIGINT UNSIGNED NULL,
+ linkid BIGINT UNSIGNED NULL
+ ) ENGINE=OQGRAPH
+*/
+
+
+/*
+ We represent the above in C in the following way:
+*/
+typedef uint16 GRAPH_LATCH;
+typedef uint64 GRAPH_VERTEXID;
+typedef uint64 GRAPH_WEIGHT;
+typedef uint64 GRAPH_SEQ;
+
+typedef struct graph_tuple {
+ GRAPH_LATCH latch; /* function */
+ GRAPH_VERTEXID origid; /* vertex (should be != 0) */
+ GRAPH_VERTEXID destid; /* edge */
+ GRAPH_WEIGHT weight; /* weight */
+ GRAPH_SEQ seq; /* seq# within (origid) */
+ GRAPH_VERTEXID linkid; /* current step between origid/destid */
+} GRAPH_TUPLE;
+
+typedef struct graph_set {
+ GRAPH_TUPLE tuple;
+ struct graph_set *next;
+} GRAPH_SET;
+
+
+/*
+ Internally, sets look nothing like the above
+
+ - We have vertices, connected by edges.
+ - Each vertex' edges are maintained in a linked list.
+ - Edges can be weighted.
+
+ There are some issues with this structure, it'd be a pest to do a delete
+ So for now, let's just not support deletes!
+*/
+/* the below is half-gross and will likely change */
+typedef struct graph_edge {
+ struct graph_vertex {
+ GRAPH_VERTEXID id;
+ struct graph_edge *forward_edge;
+ } *vertex;
+ GRAPH_WEIGHT weight;
+ struct graph_edge *next_edge;
+} GRAPH_EDGE;
+
+typedef struct graph_vertex GRAPH_VERTEX;
+
+
+/*
+ A rough internal storage system for a set
+*/
+/* this below is fully gross and will definitely change */
+typedef struct graphstore {
+ GRAPH_VERTEX *vertex; /* changed to ptr when integrating into MySQL */
+ struct graphstore *next;
+} GRAPHSTORE;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* public function declarations */
+int graphstore_insert (GRAPHSTORE **gspp, GRAPH_TUPLE *gtp);
+GRAPH_SET *graphstore_query (GRAPHSTORE *gsp, GRAPH_TUPLE *gtp);
+int free_graph_set (GRAPH_SET *gsetp);
+
+#ifdef __cplusplus
+}
+#endif
+
+/* end of graphstore.h */
\ No newline at end of file
=== added file 'storage/oqgraph/ha_oqgraph.cc'
--- a/storage/oqgraph/ha_oqgraph.cc 1970-01-01 00:00:00 +0000
+++ b/storage/oqgraph/ha_oqgraph.cc 2010-01-04 08:27:50 +0000
@@ -0,0 +1,1040 @@
+/* Copyright (C) 2007-2009 Arjen G Lentz & Antony T Curtis for Open Query
+ Portions of this file copyright (C) 2000-2006 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+/* ======================================================================
+ Open Query Graph Computation Engine, based on a concept by Arjen Lentz
+ Mk.II implementation by Antony Curtis & Arjen Lentz
+ For more information, documentation, support, enhancement engineering,
+ and non-GPL licensing, see http://openquery.com/graph
+ or contact graph(a)openquery.com
+ For packaged binaries, see http://ourdelta.org
+ ======================================================================
+*/
+
+#ifdef USE_PRAGMA_IMPLEMENTATION
+#pragma implementation // gcc: Class implementation
+#endif
+
+#define MYSQL_SERVER // to have THD
+#include "mysql_priv.h"
+#if MYSQL_VERSION_ID >= 50100
+#include <mysql/plugin.h>
+#endif
+
+#ifdef HAVE_OQGRAPH
+
+#include "ha_oqgraph.h"
+#include "graphcore.h"
+
+#define OQGRAPH_STATS_UPDATE_THRESHOLD 10
+
+using namespace open_query;
+
+
+struct oqgraph_info_st
+{
+ THR_LOCK lock;
+ oqgraph_share *graph;
+ uint use_count;
+ uint key_stat_version;
+ uint records;
+ bool dropped;
+ char name[FN_REFLEN+1];
+};
+
+static const char oqgraph_description[]=
+ "Open Query Graph Computation Engine, stored in memory "
+ "(http://openquery.com/graph)";
+
+#if MYSQL_VERSION_ID < 50100
+static bool oqgraph_init();
+
+handlerton oqgraph_hton= {
+ "OQGRAPH",
+ SHOW_OPTION_YES,
+ oqgraph_description,
+ DB_TYPE_OQGRAPH,
+ oqgraph_init,
+ 0, /* slot */
+ 0, /* savepoint size. */
+ NULL, /* close_connection */
+ NULL, /* savepoint */
+ NULL, /* rollback to savepoint */
+ NULL, /* release savepoint */
+ NULL, /* commit */
+ NULL, /* rollback */
+ NULL, /* prepare */
+ NULL, /* recover */
+ NULL, /* commit_by_xid */
+ NULL, /* rollback_by_xid */
+ NULL, /* create_cursor_read_view */
+ NULL, /* set_cursor_read_view */
+ NULL, /* close_cursor_read_view */
+ HTON_NO_FLAGS
+};
+
+#define STATISTIC_INCREMENT(X) \
+statistic_increment(table->in_use->status_var.X, &LOCK_status)
+#define MOVE(X) move_field(X)
+#define RECORDS records
+#else
+#define STATISTIC_INCREMENT(X) ha_statistic_increment(&SSV::X)
+#define MOVE(X) move_field_offset(X)
+#define RECORDS stats.records
+#endif
+
+static HASH oqgraph_open_tables;
+static pthread_mutex_t LOCK_oqgraph;
+static bool oqgraph_init_done= 0;
+
+#if MYSQL_VERSION_ID >= 50130
+#define HASH_KEY_LENGTH size_t
+#else
+#define HASH_KEY_LENGTH uint
+#endif
+
+static uchar* get_key(const uchar *ptr, HASH_KEY_LENGTH *length,
+ my_bool)
+{
+ const OQGRAPH_INFO *share= (const OQGRAPH_INFO*) ptr;
+ *length= strlen(share->name);
+ return (uchar*) share->name;
+}
+
+#if MYSQL_VERSION_ID >= 50100
+static handler* oqgraph_create_handler(handlerton *hton, TABLE_SHARE *table,
+ MEM_ROOT *mem_root)
+{
+ return new (mem_root) ha_oqgraph(hton, table);
+}
+
+static int oqgraph_init(handlerton *hton)
+{
+#else
+static bool oqgraph_init()
+{
+ if (have_oqgraph == SHOW_OPTION_DISABLED)
+ return 1;
+#endif
+ if (pthread_mutex_init(&LOCK_oqgraph, MY_MUTEX_INIT_FAST))
+ goto error;
+ if (hash_init(&oqgraph_open_tables, &my_charset_bin, 32, 0, 0,
+ get_key, 0, 0))
+ {
+ pthread_mutex_destroy(&LOCK_oqgraph);
+ goto error;
+ }
+#if MYSQL_VERSION_ID >= 50100
+ hton->state= SHOW_OPTION_YES;
+ hton->db_type= DB_TYPE_DEFAULT;
+ hton->create= oqgraph_create_handler;
+ hton->flags= HTON_NO_FLAGS;
+#endif
+ oqgraph_init_done= TRUE;
+ return 0;
+error:
+#if MYSQL_VERSION_ID < 50100
+ have_oqgraph= SHOW_OPTION_DISABLED;
+#endif
+ return 1;
+}
+
+#if MYSQL_VERSION_ID >= 50100
+static int oqgraph_fini(void *)
+{
+ hash_free(&oqgraph_open_tables);
+ pthread_mutex_destroy(&LOCK_oqgraph);
+ oqgraph_init_done= FALSE;
+ return 0;
+}
+#endif
+
+static OQGRAPH_INFO *get_share(const char *name, TABLE *table=0)
+{
+ OQGRAPH_INFO *share;
+ uint length= strlen(name);
+
+ safe_mutex_assert_owner(&LOCK_oqgraph);
+ if (!(share= (OQGRAPH_INFO*) hash_search(&oqgraph_open_tables,
+ (byte*) name, length)))
+ {
+ if (!table ||
+ !(share= new OQGRAPH_INFO))
+ return 0;
+ share->use_count= share->key_stat_version= share->records= 0;
+ share->dropped= 0;
+ strmov(share->name, name);
+ if (!(share->graph= oqgraph::create()))
+ {
+ delete share;
+ return 0;
+ }
+ if (my_hash_insert(&oqgraph_open_tables, (byte*) share))
+ {
+ oqgraph::free(share->graph);
+ delete share;
+ return 0;
+ }
+ thr_lock_init(&share->lock);
+ }
+ share->use_count++;
+ return share;
+}
+
+static int free_share(OQGRAPH_INFO *share, bool drop=0)
+{
+ safe_mutex_assert_owner(&LOCK_oqgraph);
+ if (!share)
+ return 0;
+ if (drop)
+ {
+ share->dropped= true;
+ hash_delete(&oqgraph_open_tables, (byte*) share);
+ }
+ if (!--share->use_count)
+ {
+ if (share->dropped)
+ {
+ thr_lock_delete(&share->lock);
+ oqgraph::free(share->graph);
+ delete share;
+ }
+ }
+ return 0;
+}
+
+static int error_code(int res)
+{
+ switch (res)
+ {
+ case oqgraph::OK:
+ return 0;
+ case oqgraph::NO_MORE_DATA:
+ return HA_ERR_END_OF_FILE;
+ case oqgraph::EDGE_NOT_FOUND:
+ return HA_ERR_KEY_NOT_FOUND;
+ case oqgraph::INVALID_WEIGHT:
+ return HA_ERR_AUTOINC_ERANGE;
+ case oqgraph::DUPLICATE_EDGE:
+ return HA_ERR_FOUND_DUPP_KEY;
+ case oqgraph::CANNOT_ADD_VERTEX:
+ case oqgraph::CANNOT_ADD_EDGE:
+ return HA_ERR_RECORD_FILE_FULL;
+ case oqgraph::MISC_FAIL:
+ default:
+ return HA_ERR_CRASHED_ON_USAGE;
+ }
+}
+
+/**
+ * Check if table complies with our designated structure
+ *
+ * ColName Type Attributes
+ * ======= ======== =============
+ * latch SMALLINT UNSIGNED NULL
+ * origid BIGINT UNSIGNED NULL
+ * destid BIGINT UNSIGNED NULL
+ * weight DOUBLE NULL
+ * seq BIGINT UNSIGNED NULL
+ * linkid BIGINT UNSIGNED NULL
+ * =================================
+ *
+ CREATE TABLE foo (
+ latch SMALLINT UNSIGNED NULL,
+ origid BIGINT UNSIGNED NULL,
+ destid BIGINT UNSIGNED NULL,
+ weight DOUBLE NULL,
+ seq BIGINT UNSIGNED NULL,
+ linkid BIGINT UNSIGNED NULL,
+ KEY (latch, origid, destid) USING HASH,
+ KEY (latch, destid, origid) USING HASH
+ ) ENGINE=OQGRAPH
+
+ */
+static int oqgraph_check_table_structure (TABLE *table_arg)
+{
+ int i;
+ struct { const char *colname; int coltype; } skel[] = {
+ { "latch" , MYSQL_TYPE_SHORT },
+ { "origid", MYSQL_TYPE_LONGLONG },
+ { "destid", MYSQL_TYPE_LONGLONG },
+ { "weight", MYSQL_TYPE_DOUBLE },
+ { "seq" , MYSQL_TYPE_LONGLONG },
+ { "linkid", MYSQL_TYPE_LONGLONG },
+ { NULL , 0}
+ };
+
+ DBUG_ENTER("ha_oqgraph::table_structure_ok");
+
+ Field **field= table_arg->field;
+ for (i= 0; *field && skel[i].colname; i++, field++) {
+ /* Check Column Type */
+ if ((*field)->type() != skel[i].coltype)
+ DBUG_RETURN(-1);
+ if (skel[i].coltype != MYSQL_TYPE_DOUBLE) {
+ /* Check Is UNSIGNED */
+ if (!((*field)->flags & UNSIGNED_FLAG ))
+ DBUG_RETURN(-1);
+ }
+ /* Check THAT NOT NULL isn't set */
+ if ((*field)->flags & NOT_NULL_FLAG)
+ DBUG_RETURN(-1);
+ /* Check the column name */
+ if (strcmp(skel[i].colname,(*field)->field_name))
+ DBUG_RETURN(-1);
+ }
+
+ if (skel[i].colname || *field || !table_arg->key_info || !table_arg->s->keys)
+ DBUG_RETURN(-1);
+
+ KEY *key= table_arg->key_info;
+ for (uint i= 0; i < table_arg->s->keys; ++i, ++key)
+ {
+ Field **field= table_arg->field;
+ /* check that the first key part is the latch and it is a hash key */
+ if (!(field[0] == key->key_part[0].field &&
+ HA_KEY_ALG_HASH == key->algorithm))
+ DBUG_RETURN(-1);
+ if (key->key_parts == 3)
+ {
+ /* KEY (latch, origid, destid) USING HASH */
+ /* KEY (latch, destid, origid) USING HASH */
+ if (!(field[1] == key->key_part[1].field &&
+ field[2] == key->key_part[2].field) &&
+ !(field[1] == key->key_part[2].field &&
+ field[2] == key->key_part[1].field))
+ DBUG_RETURN(-1);
+ }
+ else
+ DBUG_RETURN(-1);
+ }
+
+ DBUG_RETURN(0);
+}
+
+/*****************************************************************************
+** OQGRAPH tables
+*****************************************************************************/
+
+#if MYSQL_VERSION_ID >= 50100
+ha_oqgraph::ha_oqgraph(handlerton *hton, TABLE_SHARE *table_arg)
+ : handler(hton, table_arg),
+#else
+ha_oqgraph::ha_oqgraph(TABLE *table_arg)
+ : handler(&oqgraph_hton, table_arg),
+#endif
+ share(0), graph(0), records_changed(0), key_stat_version(0)
+{ }
+
+
+static const char *ha_oqgraph_exts[] =
+{
+ NullS
+};
+
+const char **ha_oqgraph::bas_ext() const
+{
+ return ha_oqgraph_exts;
+}
+
+#if MYSQL_VERSION_ID >= 50100
+ulonglong ha_oqgraph::table_flags() const
+#else
+ulong ha_oqgraph::table_flags() const
+#endif
+{
+ return (HA_NO_BLOBS | HA_NULL_IN_KEY |
+ HA_REC_NOT_IN_SEQ | HA_CAN_INSERT_DELAYED);
+}
+
+ulong ha_oqgraph::index_flags(uint inx, uint part, bool all_parts) const
+{
+ return HA_ONLY_WHOLE_INDEX | HA_KEY_SCAN_NOT_ROR;
+}
+
+int ha_oqgraph::open(const char *name, int mode, uint test_if_locked)
+{
+ pthread_mutex_lock(&LOCK_oqgraph);
+ if ((share = get_share(name, table)))
+ {
+ ref_length= oqgraph::sizeof_ref;
+ }
+
+ if (share)
+ {
+ /* Initialize variables for the opened table */
+ thr_lock_data_init(&share->lock, &lock, NULL);
+
+ graph= oqgraph::create(share->graph);
+
+ /*
+ We cannot run update_key_stats() here because we do not have a
+ lock on the table. The 'records' count might just be changed
+ temporarily at this moment and we might get wrong statistics (Bug
+ #10178). Instead we request for update. This will be done in
+ ha_oqgraph::info(), which is always called before key statistics are
+ used.
+ */
+ key_stat_version= share->key_stat_version-1;
+ }
+ pthread_mutex_unlock(&LOCK_oqgraph);
+
+ return (share ? 0 : 1);
+}
+
+int ha_oqgraph::close(void)
+{
+ pthread_mutex_lock(&LOCK_oqgraph);
+ oqgraph::free(graph); graph= 0;
+ int res= free_share(share);
+ pthread_mutex_unlock(&LOCK_oqgraph);
+ return error_code(res);
+}
+
+void ha_oqgraph::update_key_stats()
+{
+ for (uint i= 0; i < table->s->keys; i++)
+ {
+ KEY *key=table->key_info+i;
+ if (!key->rec_per_key)
+ continue;
+ if (key->algorithm != HA_KEY_ALG_BTREE)
+ {
+ if (key->flags & HA_NOSAME)
+ key->rec_per_key[key->key_parts-1]= 1;
+ else
+ {
+ unsigned vertices= graph->vertices_count();
+ unsigned edges= graph->edges_count();
+ uint no_records= vertices ? 2 * (edges + vertices) / vertices : 2;
+ if (no_records < 2)
+ no_records= 2;
+ key->rec_per_key[key->key_parts-1]= no_records;
+ }
+ }
+ }
+ records_changed= 0;
+ /* At the end of update_key_stats() we can proudly claim they are OK. */
+ key_stat_version= share->key_stat_version;
+}
+
+
+int ha_oqgraph::write_row(byte * buf)
+{
+ int res= oqgraph::MISC_FAIL;
+ Field ** const field= table->field;
+ STATISTIC_INCREMENT(ha_write_count);
+
+#if MYSQL_VERSION_ID >= 50100
+ my_bitmap_map *old_map= dbug_tmp_use_all_columns(table, table->read_set);
+#endif
+ my_ptrdiff_t ptrdiff= buf - table->record[0];
+
+ if (ptrdiff)
+ {
+ field[1]->MOVE(ptrdiff);
+ field[2]->MOVE(ptrdiff);
+ field[3]->MOVE(ptrdiff);
+ }
+
+ if (!field[1]->is_null() && !field[2]->is_null())
+ {
+ VertexID orig_id= (VertexID) field[1]->val_int();
+ VertexID dest_id= (VertexID) field[2]->val_int();
+ EdgeWeight weight= 1;
+
+ if (!field[3]->is_null())
+ weight= (EdgeWeight) field[3]->val_real();
+
+ if (!(res= graph->insert_edge(orig_id, dest_id, weight, replace_dups)))
+ {
+ ++records_changed;
+ share->records++;
+ }
+ if (res == oqgraph::DUPLICATE_EDGE && ignore_dups && !insert_dups)
+ res= oqgraph::OK;
+ }
+
+ if (ptrdiff)
+ {
+ field[1]->MOVE(-ptrdiff);
+ field[2]->MOVE(-ptrdiff);
+ field[3]->MOVE(-ptrdiff);
+ }
+#if MYSQL_VERSION_ID >= 50100
+ dbug_tmp_restore_column_map(table->read_set, old_map);
+#endif
+
+ if (!res && records_changed*OQGRAPH_STATS_UPDATE_THRESHOLD > share->records)
+ {
+ /*
+ We can perform this safely since only one writer at the time is
+ allowed on the table.
+ */
+ share->key_stat_version++;
+ }
+
+ return error_code(res);
+}
+
+int ha_oqgraph::update_row(const byte * old, byte * buf)
+{
+ int res= oqgraph::MISC_FAIL;
+ VertexID orig_id, dest_id;
+ EdgeWeight weight= 1;
+ Field **field= table->field;
+ STATISTIC_INCREMENT(ha_update_count);
+
+#if MYSQL_VERSION_ID >= 50100
+ my_bitmap_map *old_map= dbug_tmp_use_all_columns(table, table->read_set);
+#endif
+ my_ptrdiff_t ptrdiff= buf - table->record[0];
+
+ if (ptrdiff)
+ {
+ field[0]->MOVE(ptrdiff);
+ field[1]->MOVE(ptrdiff);
+ field[2]->MOVE(ptrdiff);
+ field[3]->MOVE(ptrdiff);
+ }
+
+ if (inited == INDEX || inited == RND)
+ {
+ VertexID *origp= 0, *destp= 0;
+ EdgeWeight *weightp= 0;
+ if (!field[1]->is_null())
+ *(origp= &orig_id)= (VertexID) field[1]->val_int();
+ if (!field[2]->is_null())
+ *(destp= &dest_id)= (VertexID) field[2]->val_int();
+ if (!field[3]->is_null())
+ *(weightp= &weight)= (EdgeWeight) field[3]->val_real();
+
+ my_ptrdiff_t ptrdiff2= old - buf;
+
+ field[0]->MOVE(ptrdiff2);
+ field[1]->MOVE(ptrdiff2);
+ field[2]->MOVE(ptrdiff2);
+ field[3]->MOVE(ptrdiff2);
+
+ if (field[0]->is_null())
+ {
+ if (!origp == field[1]->is_null() &&
+ *origp == (VertexID) field[1]->val_int())
+ origp= 0;
+ if (!destp == field[2]->is_null() &&
+ *destp == (VertexID) field[2]->val_int())
+ origp= 0;
+ if (!weightp == field[3]->is_null() &&
+ *weightp == (VertexID) field[3]->val_real())
+ weightp= 0;
+
+ if (!(res= graph->modify_edge(oqgraph::current_row(),
+ origp, destp, weightp, replace_dups)))
+ ++records_changed;
+ else if (ignore_dups && res == oqgraph::DUPLICATE_EDGE)
+ res= oqgraph::OK;
+ }
+
+ field[0]->MOVE(-ptrdiff2);
+ field[1]->MOVE(-ptrdiff2);
+ field[2]->MOVE(-ptrdiff2);
+ field[3]->MOVE(-ptrdiff2);
+ }
+
+ if (ptrdiff)
+ {
+ field[0]->MOVE(-ptrdiff);
+ field[1]->MOVE(-ptrdiff);
+ field[2]->MOVE(-ptrdiff);
+ field[3]->MOVE(-ptrdiff);
+ }
+#if MYSQL_VERSION_ID >= 50100
+ dbug_tmp_restore_column_map(table->read_set, old_map);
+#endif
+
+ if (!res && records_changed*OQGRAPH_STATS_UPDATE_THRESHOLD > share->records)
+ {
+ /*
+ We can perform this safely since only one writer at the time is
+ allowed on the table.
+ */
+ share->key_stat_version++;
+ }
+ return error_code(res);
+}
+
+int ha_oqgraph::delete_row(const byte * buf)
+{
+ int res= oqgraph::EDGE_NOT_FOUND;
+ Field **field= table->field;
+ STATISTIC_INCREMENT(ha_delete_count);
+
+ if (inited == INDEX || inited == RND)
+ {
+ if ((res= graph->delete_edge(oqgraph::current_row())) == oqgraph::OK)
+ {
+ ++records_changed;
+ share->records--;
+ }
+ }
+ if (res != oqgraph::OK)
+ {
+#if MYSQL_VERSION_ID >= 50100
+ my_bitmap_map *old_map= dbug_tmp_use_all_columns(table, table->read_set);
+#endif
+ my_ptrdiff_t ptrdiff= buf - table->record[0];
+
+ if (ptrdiff)
+ {
+ field[0]->MOVE(ptrdiff);
+ field[1]->MOVE(ptrdiff);
+ field[2]->MOVE(ptrdiff);
+ }
+
+ if (field[0]->is_null() && !field[1]->is_null() && !field[2]->is_null())
+ {
+ VertexID orig_id= (VertexID) field[1]->val_int();
+ VertexID dest_id= (VertexID) field[2]->val_int();
+
+ if ((res= graph->delete_edge(orig_id, dest_id)) == oqgraph::OK)
+ {
+ ++records_changed;
+ share->records--;
+ }
+ }
+
+ if (ptrdiff)
+ {
+ field[0]->MOVE(-ptrdiff);
+ field[1]->MOVE(-ptrdiff);
+ field[2]->MOVE(-ptrdiff);
+ }
+#if MYSQL_VERSION_ID >= 50100
+ dbug_tmp_restore_column_map(table->read_set, old_map);
+#endif
+ }
+
+ if (!res && table->s->tmp_table == NO_TMP_TABLE &&
+ records_changed*OQGRAPH_STATS_UPDATE_THRESHOLD > share->records)
+ {
+ /*
+ We can perform this safely since only one writer at the time is
+ allowed on the table.
+ */
+ share->key_stat_version++;
+ }
+ return error_code(res);
+}
+
+int ha_oqgraph::index_read(byte * buf, const byte * key, uint key_len,
+ enum ha_rkey_function find_flag)
+{
+ DBUG_ASSERT(inited==INDEX);
+ return index_read_idx(buf, active_index, key, key_len, find_flag);
+}
+
+int ha_oqgraph::index_next_same(byte *buf, const byte *key, uint key_len)
+{
+ int res;
+ open_query::row row;
+ DBUG_ASSERT(inited==INDEX);
+ STATISTIC_INCREMENT(ha_read_key_count);
+ if (!(res= graph->fetch_row(row)))
+ res= fill_record(buf, row);
+ table->status= res ? STATUS_NOT_FOUND : 0;
+ return error_code(res);
+}
+
+int ha_oqgraph::index_read_idx(byte * buf, uint index, const byte * key,
+ uint key_len, enum ha_rkey_function find_flag)
+{
+ Field **field= table->field;
+ KEY *key_info= table->key_info + index;
+ int res;
+ VertexID orig_id, dest_id;
+ int latch;
+ VertexID *orig_idp=0, *dest_idp=0;
+ int *latchp=0;
+ open_query::row row;
+ STATISTIC_INCREMENT(ha_read_key_count);
+
+ bmove_align(buf, table->s->default_values, table->s->reclength);
+ key_restore(buf, (byte*) key, key_info, key_len);
+
+#if MYSQL_VERSION_ID >= 50100
+ my_bitmap_map *old_map= dbug_tmp_use_all_columns(table, table->read_set);
+#endif
+ my_ptrdiff_t ptrdiff= buf - table->record[0];
+
+ if (ptrdiff)
+ {
+ field[0]->MOVE(ptrdiff);
+ field[1]->MOVE(ptrdiff);
+ field[2]->MOVE(ptrdiff);
+ }
+
+ if (!field[0]->is_null())
+ {
+ latch= (int) field[0]->val_int();
+ latchp= &latch;
+ }
+
+ if (!field[1]->is_null())
+ {
+ orig_id= (VertexID) field[1]->val_int();
+ orig_idp= &orig_id;
+ }
+
+ if (!field[2]->is_null())
+ {
+ dest_id= (VertexID) field[2]->val_int();
+ dest_idp= &dest_id;
+ }
+
+ if (ptrdiff)
+ {
+ field[0]->MOVE(-ptrdiff);
+ field[1]->MOVE(-ptrdiff);
+ field[2]->MOVE(-ptrdiff);
+ }
+#if MYSQL_VERSION_ID >= 50100
+ dbug_tmp_restore_column_map(table->read_set, old_map);
+#endif
+
+ res= graph->search(latchp, orig_idp, dest_idp);
+
+ if (!res && !(res= graph->fetch_row(row)))
+ res= fill_record(buf, row);
+ table->status = res ? STATUS_NOT_FOUND : 0;
+ return error_code(res);
+}
+
+int ha_oqgraph::fill_record(byte *record, const open_query::row &row)
+{
+ Field **field= table->field;
+
+ bmove_align(record, table->s->default_values, table->s->reclength);
+
+#if MYSQL_VERSION_ID >= 50100
+ my_bitmap_map *old_map= dbug_tmp_use_all_columns(table, table->write_set);
+#endif
+ my_ptrdiff_t ptrdiff= record - table->record[0];
+
+ if (ptrdiff)
+ {
+ field[0]->MOVE(ptrdiff);
+ field[1]->MOVE(ptrdiff);
+ field[2]->MOVE(ptrdiff);
+ field[3]->MOVE(ptrdiff);
+ field[4]->MOVE(ptrdiff);
+ field[5]->MOVE(ptrdiff);
+ }
+
+ // just each field specifically, no sense iterating
+ if (row.latch_indicator)
+ {
+ field[0]->set_notnull();
+ field[0]->store((longlong) row.latch);
+ }
+
+ if (row.orig_indicator)
+ {
+ field[1]->set_notnull();
+ field[1]->store((longlong) row.orig);
+ }
+
+ if (row.dest_indicator)
+ {
+ field[2]->set_notnull();
+ field[2]->store((longlong) row.dest);
+ }
+
+ if (row.weight_indicator)
+ {
+ field[3]->set_notnull();
+ field[3]->store((double) row.weight);
+ }
+
+ if (row.seq_indicator)
+ {
+ field[4]->set_notnull();
+ field[4]->store((longlong) row.seq);
+ }
+
+ if (row.link_indicator)
+ {
+ field[5]->set_notnull();
+ field[5]->store((longlong) row.link);
+ }
+
+ if (ptrdiff)
+ {
+ field[0]->MOVE(-ptrdiff);
+ field[1]->MOVE(-ptrdiff);
+ field[2]->MOVE(-ptrdiff);
+ field[3]->MOVE(-ptrdiff);
+ field[4]->MOVE(-ptrdiff);
+ field[5]->MOVE(-ptrdiff);
+ }
+#if MYSQL_VERSION_ID >= 50100
+ dbug_tmp_restore_column_map(table->write_set, old_map);
+#endif
+
+ return 0;
+}
+
+int ha_oqgraph::rnd_init(bool scan)
+{
+ return error_code(graph->random(scan));
+}
+
+int ha_oqgraph::rnd_next(byte *buf)
+{
+ int res;
+ open_query::row row;
+ STATISTIC_INCREMENT(ha_read_rnd_next_count);
+ if (!(res= graph->fetch_row(row)))
+ res= fill_record(buf, row);
+ table->status= res ? STATUS_NOT_FOUND: 0;
+ return error_code(res);
+}
+
+int ha_oqgraph::rnd_pos(byte * buf, byte *pos)
+{
+ int res;
+ open_query::row row;
+ STATISTIC_INCREMENT(ha_read_rnd_count);
+ if (!(res= graph->fetch_row(row, pos)))
+ res= fill_record(buf, row);
+ table->status=res ? STATUS_NOT_FOUND: 0;
+ return error_code(res);
+}
+
+void ha_oqgraph::position(const byte *record)
+{
+ graph->row_ref((void*) ref); // Ref is aligned
+}
+
+int ha_oqgraph::cmp_ref(const byte *ref1, const byte *ref2)
+{
+ return memcmp(ref1, ref2, oqgraph::sizeof_ref);
+}
+
+int ha_oqgraph::info(uint flag)
+{
+ RECORDS= graph->vertices_count() + graph->edges_count();
+#if 0
+ records= hp_info.records;
+ deleted= hp_info.deleted;
+ errkey= hp_info.errkey;
+ mean_rec_length= hp_info.reclength;
+ data_file_length= hp_info.data_length;
+ index_file_length= hp_info.index_length;
+ max_data_file_length= hp_info.max_records* hp_info.reclength;
+ delete_length= hp_info.deleted * hp_info.reclength;
+#endif
+ /*
+ If info() is called for the first time after open(), we will still
+ have to update the key statistics. Hoping that a table lock is now
+ in place.
+ */
+ if (key_stat_version != share->key_stat_version)
+ update_key_stats();
+ return 0;
+}
+
+int ha_oqgraph::extra(enum ha_extra_function operation)
+{
+ switch (operation)
+ {
+ case HA_EXTRA_IGNORE_DUP_KEY:
+ ignore_dups= true;
+ break;
+ case HA_EXTRA_NO_IGNORE_DUP_KEY:
+ ignore_dups= false;
+ insert_dups= false;
+ break;
+ case HA_EXTRA_WRITE_CAN_REPLACE:
+ replace_dups= true;
+ break;
+ case HA_EXTRA_WRITE_CANNOT_REPLACE:
+ replace_dups= false;
+ break;
+ case HA_EXTRA_INSERT_WITH_UPDATE:
+ insert_dups= true;
+ break;
+ default:
+ break;
+ }
+ return 0;
+}
+
+int ha_oqgraph::delete_all_rows()
+{
+ int res;
+ if (!(res= graph->delete_all()))
+ {
+ share->records= 0;
+ }
+
+ if (!res && table->s->tmp_table == NO_TMP_TABLE)
+ {
+ /*
+ We can perform this safely since only one writer at the time is
+ allowed on the table.
+ */
+ share->key_stat_version++;
+ }
+ return error_code(res);
+}
+
+int ha_oqgraph::external_lock(THD *thd, int lock_type)
+{
+ return 0; // No external locking
+}
+
+
+THR_LOCK_DATA **ha_oqgraph::store_lock(THD *thd,
+ THR_LOCK_DATA **to,
+ enum thr_lock_type lock_type)
+{
+ if (lock_type != TL_IGNORE && lock.type == TL_UNLOCK)
+ lock.type=lock_type;
+ *to++= &lock;
+ return to;
+}
+
+/*
+ We have to ignore ENOENT entries as the HEAP table is created on open and
+ not when doing a CREATE on the table.
+*/
+
+int ha_oqgraph::delete_table(const char *name)
+{
+ int res= 0;
+ OQGRAPH_INFO *share;
+ pthread_mutex_lock(&LOCK_oqgraph);
+ if ((share= get_share(name)))
+ {
+ res= free_share(share, true);
+ }
+ pthread_mutex_unlock(&LOCK_oqgraph);
+ return error_code(res);
+}
+
+int ha_oqgraph::rename_table(const char * from, const char * to)
+{
+ pthread_mutex_lock(&LOCK_oqgraph);
+ if (OQGRAPH_INFO *share= get_share(from))
+ {
+ strmov(share->name, to);
+ hash_update(&oqgraph_open_tables, (byte*) share,
+ (byte*) from, strlen(from));
+ }
+ pthread_mutex_unlock(&LOCK_oqgraph);
+ return 0;
+}
+
+
+ha_rows ha_oqgraph::records_in_range(uint inx, key_range *min_key,
+ key_range *max_key)
+{
+ KEY *key=table->key_info+inx;
+ //if (key->algorithm == HA_KEY_ALG_BTREE)
+ // return btree_records_in_range(file, inx, min_key, max_key);
+
+ if (!min_key || !max_key ||
+ min_key->length != max_key->length ||
+ min_key->length < key->key_length - key->key_part[2].store_length ||
+ min_key->flag != HA_READ_KEY_EXACT ||
+ max_key->flag != HA_READ_AFTER_KEY)
+ {
+ if (min_key->length == key->key_part[0].store_length)
+ {
+ // If latch is not null and equals 0, return # nodes
+ DBUG_ASSERT(key->key_part[0].store_length == 3);
+ if (key->key_part[0].null_bit && !min_key->key[0] &&
+ !min_key->key[1] && !min_key->key[2])
+ return graph->vertices_count();
+ }
+ return HA_POS_ERROR; // Can only use exact keys
+ }
+
+ if (RECORDS <= 1)
+ return RECORDS;
+
+ /* Assert that info() did run. We need current statistics here. */
+ DBUG_ASSERT(key_stat_version == share->key_stat_version);
+ ha_rows result= key->rec_per_key[key->key_parts-1];
+
+ return result;
+}
+
+
+int ha_oqgraph::create(const char *name, TABLE *table_arg,
+ HA_CREATE_INFO *create_info)
+{
+ int res = -1;
+ OQGRAPH_INFO *share;
+
+ pthread_mutex_lock(&LOCK_oqgraph);
+ if ((share= get_share(name)))
+ {
+ free_share(share);
+ }
+ else
+ {
+ if (!oqgraph_check_table_structure(table_arg))
+ res= 0;;
+ }
+ pthread_mutex_unlock(&LOCK_oqgraph);
+
+ if (this->share)
+ info(HA_STATUS_NO_LOCK | HA_STATUS_CONST | HA_STATUS_VARIABLE);
+ return error_code(res);
+}
+
+
+void ha_oqgraph::update_create_info(HA_CREATE_INFO *create_info)
+{
+ table->file->info(HA_STATUS_AUTO);
+ //if (!(create_info->used_fields & HA_CREATE_USED_AUTO))
+ // create_info->auto_increment_value= auto_increment_value;
+}
+
+#if MYSQL_VERSION_ID >= 50100
+struct st_mysql_storage_engine oqgraph_storage_engine=
+{ MYSQL_HANDLERTON_INTERFACE_VERSION };
+
+mysql_declare_plugin(oqgraph)
+{
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &oqgraph_storage_engine,
+ "OQGRAPH",
+ "Arjen Lentz & Antony T Curtis, Open Query",
+ oqgraph_description,
+ PLUGIN_LICENSE_GPL,
+ (int (*)(void*)) oqgraph_init, /* Plugin Init */
+ oqgraph_fini, /* Plugin Deinit */
+ 0x0200, /* Version: 2.0 */
+ NULL, /* status variables */
+ NULL, /* system variables */
+ NULL /* config options */
+}
+mysql_declare_plugin_end;
+#endif
+
+#endif
=== added file 'storage/oqgraph/ha_oqgraph.h'
--- a/storage/oqgraph/ha_oqgraph.h 1970-01-01 00:00:00 +0000
+++ b/storage/oqgraph/ha_oqgraph.h 2010-01-04 08:27:50 +0000
@@ -0,0 +1,114 @@
+/* Copyright (C) 2007-2009 Arjen G Lentz & Antony T Curtis for Open Query
+ Portions of this file copyright (C) 2000-2006 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+/* ======================================================================
+ Open Query Graph Computation Engine, based on a concept by Arjen Lentz
+ Mk.II implementation by Antony Curtis & Arjen Lentz
+ For more information, documentation, support, enhancement engineering,
+ and non-GPL licensing, see http://openquery.com/graph
+ or contact graph(a)openquery.com
+ For packaged binaries, see http://ourdelta.org
+ ======================================================================
+*/
+
+#ifdef USE_PRAGMA_INTERFACE
+#pragma interface /* gcc class implementation */
+#endif
+
+
+typedef struct oqgraph_info_st OQGRAPH_INFO;
+
+#if MYSQL_VERSION_ID >= 50120
+typedef uchar byte;
+#endif
+
+namespace open_query
+{
+ struct row;
+ class oqgraph;
+}
+
+/* class for the the Open Query Graph handler */
+
+class ha_oqgraph: public handler
+{
+ OQGRAPH_INFO *share;
+ open_query::oqgraph *graph;
+ THR_LOCK_DATA lock;
+ /* number of records changed since last statistics update */
+ uint records_changed;
+ uint key_stat_version;
+ bool replace_dups, ignore_dups, insert_dups;
+
+ int fill_record(byte*, const open_query::row&);
+
+public:
+#if MYSQL_VERSION_ID >= 50100
+ ha_oqgraph(handlerton *hton, TABLE_SHARE *table);
+ ulonglong table_flags() const;
+#else
+ ha_oqgraph(TABLE *table);
+ ulong table_flags() const;
+#endif
+ ~ha_oqgraph() {}
+ const char *table_type() const
+ {
+ return "OQGRAPH";
+ }
+ const char *index_type(uint inx)
+ {
+ return "HASH";
+ }
+ /* Rows also use a fixed-size format */
+ enum row_type get_row_type() const { return ROW_TYPE_FIXED; }
+ const char **bas_ext() const;
+ ulong index_flags(uint inx, uint part, bool all_parts) const;
+ uint max_supported_keys() const { return MAX_KEY; }
+ uint max_supported_key_part_length() const { return MAX_KEY_LENGTH; }
+ double scan_time() { return (double) 1000000000; }
+ double read_time(uint index, uint ranges, ha_rows rows)
+ { return 1; }
+
+ int open(const char *name, int mode, uint test_if_locked);
+ int close(void);
+ int write_row(byte * buf);
+ int update_row(const byte * old_data, byte * new_data);
+ int delete_row(const byte * buf);
+ int index_read(byte * buf, const byte * key,
+ uint key_len, enum ha_rkey_function find_flag);
+ int index_read_idx(byte * buf, uint idx, const byte * key,
+ uint key_len, enum ha_rkey_function find_flag);
+ int index_next_same(byte * buf, const byte * key, uint key_len);
+ int rnd_init(bool scan);
+ int rnd_next(byte *buf);
+ int rnd_pos(byte * buf, byte *pos);
+ void position(const byte *record);
+ int info(uint);
+ int extra(enum ha_extra_function operation);
+ int external_lock(THD *thd, int lock_type);
+ int delete_all_rows(void);
+ ha_rows records_in_range(uint inx, key_range *min_key, key_range *max_key);
+ int delete_table(const char *from);
+ int rename_table(const char * from, const char * to);
+ int create(const char *name, TABLE *form, HA_CREATE_INFO *create_info);
+ void update_create_info(HA_CREATE_INFO *create_info);
+
+ THR_LOCK_DATA **store_lock(THD *thd, THR_LOCK_DATA **to,
+ enum thr_lock_type lock_type);
+ int cmp_ref(const byte *ref1, const byte *ref2);
+private:
+ void update_key_stats();
+};
=== added file 'storage/oqgraph/oqgraph_config.h.in'
--- a/storage/oqgraph/oqgraph_config.h.in 1970-01-01 00:00:00 +0000
+++ b/storage/oqgraph/oqgraph_config.h.in 2010-01-04 08:27:50 +0000
@@ -0,0 +1,73 @@
+/* src/oqgraph_config.h.in. Generated from configure.in by autoheader. */
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#undef HAVE_DLFCN_H
+
+/* Enables DTRACE Support */
+#undef HAVE_DTRACE
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define to 1 if you have the <limits.h> header file. */
+#undef HAVE_LIMITS_H
+
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define to 1 if you have the <syslimits.h> header file. */
+#undef HAVE_SYSLIMITS_H
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Source directory for MySQL */
+#undef MYSQL_SRC
+
+/* Name of package */
+#undef PACKAGE
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Version number of package */
+#undef VERSION
+
+/* Define to empty if `const' does not conform to ANSI C. */
+#undef const
+
+/* Define to `unsigned int' if <sys/types.h> does not define. */
+#undef size_t
=== added file 'storage/oqgraph/oqgraph_probes.d'
--- a/storage/oqgraph/oqgraph_probes.d 1970-01-01 00:00:00 +0000
+++ b/storage/oqgraph/oqgraph_probes.d 2010-01-04 08:27:50 +0000
@@ -0,0 +1,19 @@
+/* Copyright (C) 2004-2005 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+provider oqgraph {
+ probe open();
+ probe close();
+};
=== added file 'storage/oqgraph/oqgraph_probes.h'
--- a/storage/oqgraph/oqgraph_probes.h 1970-01-01 00:00:00 +0000
+++ b/storage/oqgraph/oqgraph_probes.h 2010-01-04 08:27:50 +0000
@@ -0,0 +1,45 @@
+/*
+ * Generated by dtrace(1M).
+ */
+
+#ifndef _OQGRAPH_PROBES_H
+#define _OQGRAPH_PROBES_H
+
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if _DTRACE_VERSION
+
+#define OQGRAPH_CLOSE() \
+ __dtrace_oqgraph___close()
+#define OQGRAPH_CLOSE_ENABLED() \
+ __dtraceenabled_oqgraph___close()
+#define OQGRAPH_OPEN() \
+ __dtrace_oqgraph___open()
+#define OQGRAPH_OPEN_ENABLED() \
+ __dtraceenabled_oqgraph___open()
+
+
+extern void __dtrace_oqgraph___close(void);
+extern int __dtraceenabled_oqgraph___close(void);
+extern void __dtrace_oqgraph___open(void);
+extern int __dtraceenabled_oqgraph___open(void);
+
+#else
+
+#define OQGRAPH_CLOSE()
+#define OQGRAPH_CLOSE_ENABLED() (0)
+#define OQGRAPH_OPEN()
+#define OQGRAPH_OPEN_ENABLED() (0)
+
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _OQGRAPH_PROBES_H */
=== added file 'storage/oqgraph/plug.in'
--- a/storage/oqgraph/plug.in 1970-01-01 00:00:00 +0000
+++ b/storage/oqgraph/plug.in 2010-01-04 08:27:50 +0000
@@ -0,0 +1,32 @@
+MYSQL_STORAGE_ENGINE(oqgraph,,[Graph Storage Engine],
+ [Open Query Graph Computation Engine], [])
+MYSQL_PLUGIN_DYNAMIC(oqgraph, [oqgraph_engine.la])
+MYSQL_PLUGIN_DEPENDS_ON_MYSQL_INTERNALS(oqgraph, [ha_oqgraph.cc])
+AM_CONDITIONAL([BUILD_OQGRAPH_FOR_MYSQL], true)
+AM_CONDITIONAL([BUILD_OQGRAPH_STANDALONE], false)
+AM_CONDITIONAL([HAVE_DTRACE], false)
+
+AC_LANG_PUSH([C++])
+AC_CHECK_HEADER([boost/graph/properties.hpp],[:],[
+ mysql_plugin_oqgraph=no
+ with_plugin_oqgraph=no
+])
+
+save_CXXFLAGS="${CXXFLAGS}"
+CXXFLAGS="-fexceptions -fimplicit-templates -O3 -fstrict-aliasing -falign-loops -fvisibility-inlines-hidden -funroll-loops -fno-trapping-math"
+
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+ #include <boost/graph/graph_traits.hpp>
+ #include <boost/graph/adjacency_list.hpp>
+ #include <boost/graph/dijkstra_shortest_paths.hpp>
+
+ using namespace boost;
+]],[[
+ typedef adjacency_list<vecS, vecS, bidirectionalS> Graph;
+ Graph g(10);
+]])],[],[
+ mysql_plugin_oqgraph=no
+ with_plugin_oqgraph=no
+])
+CXXFLAGS="${save_CXXFLAGS}"
+AC_LANG_POP()
1
0

[Maria-developers] Updated (by Guest): Add EXPLAIN for UPDATE/DELETE (51)
by worklog-noreplyīŧ askmonty.org 02 Jan '10
by worklog-noreplyīŧ askmonty.org 02 Jan '10
02 Jan '10
-----------------------------------------------------------------------
WORKLOG TASK
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
TASK...........: Add EXPLAIN for UPDATE/DELETE
CREATION DATE..: Tue, 18 Aug 2009, 16:24
SUPERVISOR.....: Monty
IMPLEMENTOR....:
COPIES TO......:
CATEGORY.......: Client-BackLog
TASK ID........: 51 (http://askmonty.org/worklog/?tid=51)
VERSION........: Server-9.x
STATUS.........: Assigned
PRIORITY.......: 60
WORKED HOURS...: 0
ESTIMATE.......: 0 (hours remain)
ORIG. ESTIMATE.: 0
PROGRESS NOTES:
-=-=(Guest - Sat, 02 Jan 2010, 21:34)=-=-
Supervisor updated.
--- /tmp/wklog.51.old.21991 2010-01-02 21:34:01.000000000 +0200
+++ /tmp/wklog.51.new.21991 2010-01-02 21:34:01.000000000 +0200
@@ -1 +1 @@
-Bothorsen
+Monty
-=-=(Guest - Sat, 02 Jan 2010, 21:34)=-=-
Privacy level updated.
--- /tmp/wklog.51.old.21991 2010-01-02 21:34:01.000000000 +0200
+++ /tmp/wklog.51.new.21991 2010-01-02 21:34:01.000000000 +0200
@@ -1 +1 @@
-y
+n
-=-=(Guest - Sat, 02 Jan 2010, 21:33)=-=-
Version updated.
--- /tmp/wklog.51.old.21935 2010-01-02 19:33:25.000000000 +0000
+++ /tmp/wklog.51.new.21935 2010-01-02 19:33:25.000000000 +0000
@@ -1 +1 @@
-Benchmarks-3.0
+Server-9.x
-=-=(Guest - Sat, 02 Jan 2010, 21:33)=-=-
Status updated.
--- /tmp/wklog.51.old.21935 2010-01-02 19:33:25.000000000 +0000
+++ /tmp/wklog.51.new.21935 2010-01-02 19:33:25.000000000 +0000
@@ -1 +1 @@
-Un-Assigned
+Assigned
-=-=(Psergey - Tue, 18 Aug 2009, 16:25)=-=-
High-Level Specification modified.
--- /tmp/wklog.51.old.12524 2009-08-18 16:25:52.000000000 +0300
+++ /tmp/wklog.51.new.12524 2009-08-18 16:25:52.000000000 +0300
@@ -1 +1,22 @@
+User interface
+--------------
+EXPLAIN UPDATE ... and EXPLAIN DELETE ... statements will work and produce
+a tabular output similar to EXPLAIN SELECT.
+
+Implementation
+--------------
+The primary challenge will be to change UPDATE/DELETE code to first produce
+action plan and then act on it (and not make decisions on the go as it
+currently does).
+
+What EXPLAIN will show
+----------------------
+* multi-table one will show the SELECT part as usual
+* single-table statements will show an equivalent of access method.
+
+Besides that, we want to know
+- if sorting will be used
+- whether the UPDATE will occur on the fly or not.
+
+(print or not "Using filesort"...)
DESCRIPTION:
Add support for EXPLAIN UPDATE/DELETE
(we'd like support for all potentially long statements, e.g. for ALTER
TABLE, but this WL entry is limited to UPDATE/DELETE as they are most
often requested, and code that handles them is similar and distinct from
other statements).
HIGH-LEVEL SPECIFICATION:
User interface
--------------
EXPLAIN UPDATE ... and EXPLAIN DELETE ... statements will work and produce
a tabular output similar to EXPLAIN SELECT.
Implementation
--------------
The primary challenge will be to change UPDATE/DELETE code to first produce
action plan and then act on it (and not make decisions on the go as it
currently does).
What EXPLAIN will show
----------------------
* multi-table one will show the SELECT part as usual
* single-table statements will show an equivalent of access method.
Besides that, we want to know
- if sorting will be used
- whether the UPDATE will occur on the fly or not.
(print or not "Using filesort"...)
ESTIMATED WORK TIME
ESTIMATED COMPLETION DATE
-----------------------------------------------------------------------
WorkLog (v3.5.9)
1
0

[Maria-developers] Updated (by Guest): Add EXPLAIN for UPDATE/DELETE (51)
by worklog-noreplyīŧ askmonty.org 02 Jan '10
by worklog-noreplyīŧ askmonty.org 02 Jan '10
02 Jan '10
-----------------------------------------------------------------------
WORKLOG TASK
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
TASK...........: Add EXPLAIN for UPDATE/DELETE
CREATION DATE..: Tue, 18 Aug 2009, 16:24
SUPERVISOR.....: Monty
IMPLEMENTOR....:
COPIES TO......:
CATEGORY.......: Client-BackLog
TASK ID........: 51 (http://askmonty.org/worklog/?tid=51)
VERSION........: Server-9.x
STATUS.........: Assigned
PRIORITY.......: 60
WORKED HOURS...: 0
ESTIMATE.......: 0 (hours remain)
ORIG. ESTIMATE.: 0
PROGRESS NOTES:
-=-=(Guest - Sat, 02 Jan 2010, 21:34)=-=-
Supervisor updated.
--- /tmp/wklog.51.old.21991 2010-01-02 21:34:01.000000000 +0200
+++ /tmp/wklog.51.new.21991 2010-01-02 21:34:01.000000000 +0200
@@ -1 +1 @@
-Bothorsen
+Monty
-=-=(Guest - Sat, 02 Jan 2010, 21:34)=-=-
Privacy level updated.
--- /tmp/wklog.51.old.21991 2010-01-02 21:34:01.000000000 +0200
+++ /tmp/wklog.51.new.21991 2010-01-02 21:34:01.000000000 +0200
@@ -1 +1 @@
-y
+n
-=-=(Guest - Sat, 02 Jan 2010, 21:33)=-=-
Version updated.
--- /tmp/wklog.51.old.21935 2010-01-02 19:33:25.000000000 +0000
+++ /tmp/wklog.51.new.21935 2010-01-02 19:33:25.000000000 +0000
@@ -1 +1 @@
-Benchmarks-3.0
+Server-9.x
-=-=(Guest - Sat, 02 Jan 2010, 21:33)=-=-
Status updated.
--- /tmp/wklog.51.old.21935 2010-01-02 19:33:25.000000000 +0000
+++ /tmp/wklog.51.new.21935 2010-01-02 19:33:25.000000000 +0000
@@ -1 +1 @@
-Un-Assigned
+Assigned
-=-=(Psergey - Tue, 18 Aug 2009, 16:25)=-=-
High-Level Specification modified.
--- /tmp/wklog.51.old.12524 2009-08-18 16:25:52.000000000 +0300
+++ /tmp/wklog.51.new.12524 2009-08-18 16:25:52.000000000 +0300
@@ -1 +1,22 @@
+User interface
+--------------
+EXPLAIN UPDATE ... and EXPLAIN DELETE ... statements will work and produce
+a tabular output similar to EXPLAIN SELECT.
+
+Implementation
+--------------
+The primary challenge will be to change UPDATE/DELETE code to first produce
+action plan and then act on it (and not make decisions on the go as it
+currently does).
+
+What EXPLAIN will show
+----------------------
+* multi-table one will show the SELECT part as usual
+* single-table statements will show an equivalent of access method.
+
+Besides that, we want to know
+- if sorting will be used
+- whether the UPDATE will occur on the fly or not.
+
+(print or not "Using filesort"...)
DESCRIPTION:
Add support for EXPLAIN UPDATE/DELETE
(we'd like support for all potentially long statements, e.g. for ALTER
TABLE, but this WL entry is limited to UPDATE/DELETE as they are most
often requested, and code that handles them is similar and distinct from
other statements).
HIGH-LEVEL SPECIFICATION:
User interface
--------------
EXPLAIN UPDATE ... and EXPLAIN DELETE ... statements will work and produce
a tabular output similar to EXPLAIN SELECT.
Implementation
--------------
The primary challenge will be to change UPDATE/DELETE code to first produce
action plan and then act on it (and not make decisions on the go as it
currently does).
What EXPLAIN will show
----------------------
* multi-table one will show the SELECT part as usual
* single-table statements will show an equivalent of access method.
Besides that, we want to know
- if sorting will be used
- whether the UPDATE will occur on the fly or not.
(print or not "Using filesort"...)
ESTIMATED WORK TIME
ESTIMATED COMPLETION DATE
-----------------------------------------------------------------------
WorkLog (v3.5.9)
1
0

[Maria-developers] Updated (by Guest): Add EXPLAIN for UPDATE/DELETE (51)
by worklog-noreplyīŧ askmonty.org 02 Jan '10
by worklog-noreplyīŧ askmonty.org 02 Jan '10
02 Jan '10
-----------------------------------------------------------------------
WORKLOG TASK
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
TASK...........: Add EXPLAIN for UPDATE/DELETE
CREATION DATE..: Tue, 18 Aug 2009, 16:24
SUPERVISOR.....: Bothorsen
IMPLEMENTOR....:
COPIES TO......:
CATEGORY.......: Client-BackLog
TASK ID........: 51 (http://askmonty.org/worklog/?tid=51)
VERSION........: Server-9.x
STATUS.........: Assigned
PRIORITY.......: 60
WORKED HOURS...: 0
ESTIMATE.......: 0 (hours remain)
ORIG. ESTIMATE.: 0
PROGRESS NOTES:
-=-=(Guest - Sat, 02 Jan 2010, 21:33)=-=-
Version updated.
--- /tmp/wklog.51.old.21935 2010-01-02 19:33:25.000000000 +0000
+++ /tmp/wklog.51.new.21935 2010-01-02 19:33:25.000000000 +0000
@@ -1 +1 @@
-Benchmarks-3.0
+Server-9.x
-=-=(Guest - Sat, 02 Jan 2010, 21:33)=-=-
Status updated.
--- /tmp/wklog.51.old.21935 2010-01-02 19:33:25.000000000 +0000
+++ /tmp/wklog.51.new.21935 2010-01-02 19:33:25.000000000 +0000
@@ -1 +1 @@
-Un-Assigned
+Assigned
-=-=(Psergey - Tue, 18 Aug 2009, 16:25)=-=-
High-Level Specification modified.
--- /tmp/wklog.51.old.12524 2009-08-18 16:25:52.000000000 +0300
+++ /tmp/wklog.51.new.12524 2009-08-18 16:25:52.000000000 +0300
@@ -1 +1,22 @@
+User interface
+--------------
+EXPLAIN UPDATE ... and EXPLAIN DELETE ... statements will work and produce
+a tabular output similar to EXPLAIN SELECT.
+
+Implementation
+--------------
+The primary challenge will be to change UPDATE/DELETE code to first produce
+action plan and then act on it (and not make decisions on the go as it
+currently does).
+
+What EXPLAIN will show
+----------------------
+* multi-table one will show the SELECT part as usual
+* single-table statements will show an equivalent of access method.
+
+Besides that, we want to know
+- if sorting will be used
+- whether the UPDATE will occur on the fly or not.
+
+(print or not "Using filesort"...)
DESCRIPTION:
Add support for EXPLAIN UPDATE/DELETE
(we'd like support for all potentially long statements, e.g. for ALTER
TABLE, but this WL entry is limited to UPDATE/DELETE as they are most
often requested, and code that handles them is similar and distinct from
other statements).
HIGH-LEVEL SPECIFICATION:
User interface
--------------
EXPLAIN UPDATE ... and EXPLAIN DELETE ... statements will work and produce
a tabular output similar to EXPLAIN SELECT.
Implementation
--------------
The primary challenge will be to change UPDATE/DELETE code to first produce
action plan and then act on it (and not make decisions on the go as it
currently does).
What EXPLAIN will show
----------------------
* multi-table one will show the SELECT part as usual
* single-table statements will show an equivalent of access method.
Besides that, we want to know
- if sorting will be used
- whether the UPDATE will occur on the fly or not.
(print or not "Using filesort"...)
ESTIMATED WORK TIME
ESTIMATED COMPLETION DATE
-----------------------------------------------------------------------
WorkLog (v3.5.9)
1
0

[Maria-developers] Updated (by Guest): Add EXPLAIN for UPDATE/DELETE (51)
by worklog-noreplyīŧ askmonty.org 02 Jan '10
by worklog-noreplyīŧ askmonty.org 02 Jan '10
02 Jan '10
-----------------------------------------------------------------------
WORKLOG TASK
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
TASK...........: Add EXPLAIN for UPDATE/DELETE
CREATION DATE..: Tue, 18 Aug 2009, 16:24
SUPERVISOR.....: Bothorsen
IMPLEMENTOR....:
COPIES TO......:
CATEGORY.......: Client-BackLog
TASK ID........: 51 (http://askmonty.org/worklog/?tid=51)
VERSION........: Server-9.x
STATUS.........: Assigned
PRIORITY.......: 60
WORKED HOURS...: 0
ESTIMATE.......: 0 (hours remain)
ORIG. ESTIMATE.: 0
PROGRESS NOTES:
-=-=(Guest - Sat, 02 Jan 2010, 21:33)=-=-
Version updated.
--- /tmp/wklog.51.old.21935 2010-01-02 19:33:25.000000000 +0000
+++ /tmp/wklog.51.new.21935 2010-01-02 19:33:25.000000000 +0000
@@ -1 +1 @@
-Benchmarks-3.0
+Server-9.x
-=-=(Guest - Sat, 02 Jan 2010, 21:33)=-=-
Status updated.
--- /tmp/wklog.51.old.21935 2010-01-02 19:33:25.000000000 +0000
+++ /tmp/wklog.51.new.21935 2010-01-02 19:33:25.000000000 +0000
@@ -1 +1 @@
-Un-Assigned
+Assigned
-=-=(Psergey - Tue, 18 Aug 2009, 16:25)=-=-
High-Level Specification modified.
--- /tmp/wklog.51.old.12524 2009-08-18 16:25:52.000000000 +0300
+++ /tmp/wklog.51.new.12524 2009-08-18 16:25:52.000000000 +0300
@@ -1 +1,22 @@
+User interface
+--------------
+EXPLAIN UPDATE ... and EXPLAIN DELETE ... statements will work and produce
+a tabular output similar to EXPLAIN SELECT.
+
+Implementation
+--------------
+The primary challenge will be to change UPDATE/DELETE code to first produce
+action plan and then act on it (and not make decisions on the go as it
+currently does).
+
+What EXPLAIN will show
+----------------------
+* multi-table one will show the SELECT part as usual
+* single-table statements will show an equivalent of access method.
+
+Besides that, we want to know
+- if sorting will be used
+- whether the UPDATE will occur on the fly or not.
+
+(print or not "Using filesort"...)
DESCRIPTION:
Add support for EXPLAIN UPDATE/DELETE
(we'd like support for all potentially long statements, e.g. for ALTER
TABLE, but this WL entry is limited to UPDATE/DELETE as they are most
often requested, and code that handles them is similar and distinct from
other statements).
HIGH-LEVEL SPECIFICATION:
User interface
--------------
EXPLAIN UPDATE ... and EXPLAIN DELETE ... statements will work and produce
a tabular output similar to EXPLAIN SELECT.
Implementation
--------------
The primary challenge will be to change UPDATE/DELETE code to first produce
action plan and then act on it (and not make decisions on the go as it
currently does).
What EXPLAIN will show
----------------------
* multi-table one will show the SELECT part as usual
* single-table statements will show an equivalent of access method.
Besides that, we want to know
- if sorting will be used
- whether the UPDATE will occur on the fly or not.
(print or not "Using filesort"...)
ESTIMATED WORK TIME
ESTIMATED COMPLETION DATE
-----------------------------------------------------------------------
WorkLog (v3.5.9)
1
0

[Maria-developers] Rev 2744: Backport of subquery optimizations to 5.3 in file:///home/psergey/dev/maria-5.3-subqueries-r2-commit/
by Sergey Petrunya 01 Jan '10
by Sergey Petrunya 01 Jan '10
01 Jan '10
At file:///home/psergey/dev/maria-5.3-subqueries-r2-commit/
------------------------------------------------------------
revno: 2744
revision-id: psergey(a)askmonty.org-20100101083655-abhuypjpebzvk33p
parent: psergey(a)askmonty.org-20091227202422-fs9fgo8x2wk9ry15
committer: Sergey Petrunya <psergey(a)askmonty.org>
branch nick: maria-5.3-subqueries-r2-commit
timestamp: Fri 2010-01-01 10:36:55 +0200
message:
Backport of subquery optimizations to 5.3
Diff too large for email (7544 lines, the limit is 1000).
1
0

[Maria-developers] Rev 4: Added wrapper scripts for automated runs of sql-bench. in file:///Users/hakan/work/monty_program/mariadb-tools/
by Hakan Kuecuekyilmaz 30 Dec '09
by Hakan Kuecuekyilmaz 30 Dec '09
30 Dec '09
At file:///Users/hakan/work/monty_program/mariadb-tools/
------------------------------------------------------------
revno: 4
revision-id: hakan(a)askmonty.org-20091229134253-zdbgd0ym9m7cokii
parent: knielsen(a)knielsen-hq.org-20091218103524-nof6wfpuku60r9rn
committer: Hakan Kuecuekyilmaz <hakan(a)askmonty.org>
branch nick: mariadb-tools
timestamp: Tue 2009-12-29 14:42:53 +0100
message:
Added wrapper scripts for automated runs of sql-bench.
=== added directory 'sql-bench'
=== added file 'sql-bench/run-sql-bench.sh'
--- a/sql-bench/run-sql-bench.sh 1970-01-01 00:00:00 +0000
+++ b/sql-bench/run-sql-bench.sh 2009-12-29 13:42:53 +0000
@@ -0,0 +1,236 @@
+#!/bin/bash
+#
+# Run sql-bench for every given configuration file
+# we find in the directory $SQL_BENCH_CONFIGS.
+#
+# Note: Do not run this script with root privileges.
+# We use killall -9, which can cause severe side effects!
+#
+# Hakan Kuecuekyilmaz <hakan at askmonty dot org> 2009-12-05.
+#
+
+if [ $# != 2 ]; then
+ echo '[ERROR]: Please provide exactly two options.'
+ echo " Example: $0 [/path/to/bzr/repository] [name_without_spaces]"
+ echo ' [name_without_spaces] is used as identifier in the result file.'
+
+ exit 1
+else
+ REPOSITORY="$1"
+ REPOSITORY_NAME="$2"
+fi
+
+#
+# Directories.
+#
+SQL_BENCH_CONFIGS='/home/hakan/sql-bench-configurations'
+SQL_BENCH_RESULTS='/home/hakan/sql-bench-results'
+WORK_DIR='/tmp'
+
+#
+# Variables.
+#
+# We need at least 1 GB disk space in our $WORK_DIR.
+SPACE_LIMIT=1000000
+MYSQLADMIN_OPTIONS='--no-defaults'
+MACHINE=$(hostname -s)
+RUN_DATE=$(date +%Y-%m-%d)
+
+# Timeout in seconds for waiting for mysqld to start.
+TIMEOUT=100
+
+#
+# Binaries.
+#
+BZR='/usr/local/bin/bzr'
+MYSQLADMIN='client/mysqladmin'
+
+#
+# Check system.
+#
+# We should at least have $SPACE_LIMIT in $WORKDIR.
+AVAILABLE=$(df $WORK_DIR | grep -v Filesystem | awk '{ print $4 }')
+
+if [ $AVAILABLE -lt $SPACE_LIMIT ]; then
+ echo "[ERROR]: We need at least $ONE_GB space in $WORK_DIR."
+ echo 'Exiting.'
+
+ exit 1
+fi
+
+#
+# Run sql-bench.
+#
+for i in ${SQL_BENCH_CONFIGS}/*.inc
+ do
+ # Set configuration and check that all required parameters are set.
+ source $i
+
+ if [ x"$MARIADB_CONFIG" == x"" ]; then
+ echo '[ERROR]: $MARIADB_CONFIG is not set.'
+ echo 'Exiting.'
+
+ exit 1
+ fi
+
+ if [ x"$SQLBENCH_OPTIONS" == x"" ]; then
+ echo '[ERROR]: $SQLBENCH_OPTIONS is not set.'
+ echo 'Exiting.'
+
+ exit 1
+ fi
+
+ if [ x"$MARIADB_OPTIONS" == x"" ]; then
+ echo '[ERROR]: $MARIADB_OPTIONS is not set.'
+ echo 'Exiting.'
+
+ exit 1
+ fi
+
+ # Check out and compile.
+ REVISION_ID=$($BZR version-info $REPOSITORY | grep revision-id)
+ if [ $? != 0 ]; then
+ echo '[ERROR]: bzr version-info failed. Please provide'
+ echo ' a working bzr repository'
+ echo 'Exiting.'
+
+ exit 1
+ fi
+
+ cd $WORK_DIR
+ # Clean up of previous runs
+ killall -9 mysqld
+
+ TEMP_DIR=$(mktemp --directory)
+ if [ $? != 0 ]; then
+ echo "[ERROR]: mktemp in $WORK_DIR failed."
+ echo 'Exiting.'
+
+ exit 1
+ fi
+
+ # bzr export refuses to export to an existing directory,
+ # therefore we use a build directory.
+ echo "Branching from $REPOSITORY to ${TEMP_DIR}/build"
+
+ $BZR export --format=dir ${TEMP_DIR}/build $REPOSITORY
+ if [ $? != 0 ]; then
+ echo '[ERROR]: bzr export failed.'
+ echo 'Exiting.'
+
+ exit 1
+ fi
+
+ cd ${TEMP_DIR}/build
+ BUILD/autorun.sh
+ if [ $? != 0 ]; then
+ echo '[ERROR]: BUILD/autorun.sh failed.'
+ echo ' Please check your development environment.'
+ echo 'Exiting.'
+
+ exit 1
+ fi
+
+ ./configure $MARIADB_CONFIG
+ if [ $? != 0 ]; then
+ echo "[ERROR]: ./configure $MARIADB_CONFIG failed."
+ echo " Please check your MARIADB_CONFIG in $i."
+ echo 'Exiting.'
+
+ exit 1
+ fi
+
+ make -j4
+ if [ $? != 0 ]; then
+ echo '[ERROR]: make failed.'
+ echo ' Please check your build logs.'
+ echo 'Exiting.'
+
+ exit 1
+ fi
+
+ # Start mysqld.
+ MARIADB_SOCKET="${TEMP_DIR}/mysql.sock"
+ MARIADB_OPTIONS="$MARIADB_OPTIONS \
+ --datadir=$TEMP_DIR \
+ --tmpdir=$TEMP_DIR \
+ --socket=$MARIADB_SOCKET"
+
+ MYSQLADMIN_OPTIONS="$MYSQLADMIN_OPTIONS \
+ --socket=$MARIADB_SOCKET"
+
+ sql/mysqld $MARIADB_OPTIONS &
+
+ j=0
+ STARTED=-1
+ while [ $j -le $TIMEOUT ]
+ do
+ $MYSQLADMIN $MYSQLADMIN_OPTIONS -uroot ping > /dev/null 2>&1
+ if [ $? = 0 ]; then
+ STARTED=0
+
+ break
+ fi
+
+ sleep 1
+ j=$(($j + 1))
+ done
+
+ if [ $STARTED != 0 ]; then
+ echo '[ERROR]: Start of mysqld failed.'
+ echo ' Please check your error log.'
+ echo 'Exiting.'
+
+ exit 1
+ fi
+
+ $MYSQLADMIN $MYSQLADMIN_OPTIONS create test
+ if [ $? != 0 ]; then
+ echo '[ERROR]: Create schema test failed.'
+ echo ' Please check your mysqld error log.'
+ echo 'Exiting.'
+
+ exit 1
+ fi
+
+ # Run sql-bench.
+ cd sql-bench
+ COMMENTS="Revision used: $REVISION_ID \
+ Configure: $MARIADB_CONFIG \
+ Server options: $MARIADB_OPTIONS"
+
+ # TODO: Adding --comments="$COMMENTS" does not work
+ SQLBENCH_OPTIONS="$SQLBENCH_OPTIONS \
+ --socket=$MARIADB_SOCKET"
+
+ ./run-all-tests $SQLBENCH_OPTIONS
+ if [ $? != 0 ]; then
+ echo '[ERROR]: run-all-tests produced errors.'
+ echo ' Please check your sql-bench error logs.'
+ echo 'Exiting.'
+
+ exit 1
+ fi
+
+ # Save result file for later usage and comparison.
+ RESULT_FILE=$(ls output/RUN-*)
+ if [ x"$RESULT_FILE" != x"" ]; then
+ NEW_FILE_NAME="RUN-${REPOSITORY_NAME}-$(basename $RESULT_FILE | awk -F 'RUN-' '{ print $2 }')"
+
+ CONFIGURATION=$(basename "$i" | awk -F . '{ print $1 }')
+ ARCHIVE_DIR="${SQL_BENCH_RESULTS}/${MACHINE}/${RUN_DATE}/${CONFIGURATION}"
+ mkdir -p $ARCHIVE_DIR
+
+ # Add comment to result file.
+ sed -e "s%Comments:%Comments: ${COMMENTS}%" $RESULT_FILE > foo.tmp
+ mv foo.tmp $RESULT_FILE
+ # TODO: check for failures and copy the logs in question.
+ cp $RESULT_FILE ${ARCHIVE_DIR}/$NEW_FILE_NAME
+
+ # Clean up for next round.
+ rm -rf $TEMP_DIR
+ else
+ echo '[ERROR]: Cannot find result file after sql-bench run!'
+ fi
+
+done
=== added directory 'sql-bench/sql-bench-configurations'
=== added file 'sql-bench/sql-bench-configurations/sql-bench-default-config.inc'
--- a/sql-bench/sql-bench-configurations/sql-bench-default-config.inc 1970-01-01 00:00:00 +0000
+++ b/sql-bench/sql-bench-configurations/sql-bench-default-config.inc 2009-12-29 13:42:53 +0000
@@ -0,0 +1,34 @@
+# Template configuration file for running sqlbench.
+#
+# We are using this configuration file for the wrapper
+# script run-sql-bench.sh. For every copy of this file we
+# are starting a sqlbench run.
+#
+# Hakan Kuecuekyilmaz <hakan at askmonty dot org> 2009-12-05.
+#
+
+#
+# Configure line for compiling MariaDB.
+#
+export MARIADB_CONFIG="--enable-thread-safe-client \
+ --enable-local-infile"
+
+#
+# Options for starting mysqld.
+#
+# Attention: Do not set --datadir, --tmpdir, and --socket.
+#
+export MARIADB_OPTIONS="--no-defaults \
+ --skip-grant-tables \
+ --language=./sql/share/english"
+
+#
+# Options for sql-bench.
+#
+# Attention: Do not set --socket.
+#
+export SQLBENCH_OPTIONS="--log \
+ --fast \
+ --server=mysql \
+ --small-test \
+ --user=root"
3
3

30 Dec '09
InnoDB fixed group commit in the InnoDB plugin. This performs as
expected when the binlog is disabled. This does not perform as I
expect when the binlog is enabled.
Is this a problem for PBXT?
The problems for InnoDB are:
1) commit is serialized on the binlog write/fsync
2) row locks are not released until the commit step of XA prepare/commit
3) per-table auto inc locks not released until the commit step of XA
I think that 2) and 3) can be fixed without significant changes. They
cause a lot of convoys today for high-throughput OLTP -- too many
connections needlessly wait on row locks and the per-table auto-inc
lock. Doing the binlog fsync one connection at a time also causes a
lot of convoys. This makes MySQL much slower than it should be for
some workloads even with battery backed RAID write caches.
Problem 1) occurs because:
* there is no group commit for the binlog fsync
* InnoDB locks prepare_commit_mutex in the prepare step
Even if there were group commit for the binlog fsync, it would be
useless for InnoDB because prepare_commit_mutex is locked in the
prepare step and not unlocked until the commit step and the binlog
write/fsync is done between these two steps.
There is a MySQL worklog for this (4007) that:
* doesn't intend to add group commit for the binlog fsync
* doesn't mention the problem of prepare_commit_mutex
I have started to work on this, but don't have any code to share yet.
Pseudo-code for commit with the InnoDB plugin when the binlog is enabled:
ha_commit_trans()
* ht->prepare() == innobase_xa_prepare()
o trx_prepare_for_mysql(trx)
+ force to disk the trx log buffer for all changes from this trx
+ fsync done here, group prepare may amortize that
o lock prepare_commit_mutex
* tc_log->log_xid(thd, xid)
o writes SQL to binlog, XID to binlog, optionally fsync binlog
* ha_commit_one_phase()
o ht->commit() == innobase_commit()
+ innobase_commit_low(()
# write commit record to trx log buffer, release
locks from this trx
# for auto-commit statements, the per-table
auto-inc lock is released here
+ unlock prepare_commit_mutex
+ trx_commit_complete_for_mysql()
# force to disk the trx log buffer including
commit record for this trx
# fsync done here, group commit may amortize that
--
Mark Callaghan
mdcallag(a)gmail.com
3
8
Hi Hakan, all
With PBXT and the latest merge, this should now technically be enabled
(again).
That is, a transaction should be consistent between InnoDB+PBXT
+binlog, that is either all or none should commit.
But as I understand, when this was last tried with Falcon it went
kaboom in MySQL, so likely there are some bugs.
I think it would be good to at least create/enable some tests for
this, then we can see what the exact code status is, and hopefully get
it all working as well.
Right now I don't think anybody really expects something like this to
work, but in theory it should work so presumptions *may* be made (I
know this sentence appears kinda contradictory, hope it makes sense
anyhow ;-).
Thus it's important for us to know what happens, so that we can tell
people "don't do this now, please track bug #", or "please try this".
Thanks
Cheers,
Arjen.
--
Arjen Lentz, Exec.Director @ Open Query (http://openquery.com)
Exceptional Services for MySQL at a fixed budget.
Follow our blog at http://openquery.com/blog/
OurDelta: packages for MySQL and MariaDB @ http://ourdelta.org
4
4

[Maria-developers] bzr commit into MariaDB 5.1, with Maria 1.5:maria branch (monty:2786)
by Michael Widenius 29 Dec '09
by Michael Widenius 29 Dec '09
29 Dec '09
#At lp:maria based on revid:knielsen@knielsen-hq.org-20091221162636-z5ycgu2uunkw8hvh
2786 Michael Widenius 2009-12-27
Fix test suite so that it works when doing configure --without-uca
Simplify testing of needed characterset
Remove ndb from --with-plugins=max build
mysqlbug now sends email to maria-developers(a)lists.launchpad.net
removed:
mysql-test/r/have_big5.require
mysql-test/r/have_cp1250_ch.require
mysql-test/r/have_cp1251.require
mysql-test/r/have_cp866.require
mysql-test/r/have_cp932.require
mysql-test/r/have_eucjpms.require
mysql-test/r/have_euckr.require
mysql-test/r/have_gb2312.require
mysql-test/r/have_gbk.require
mysql-test/r/have_koi8r.require
mysql-test/r/have_latin2_ch.require
mysql-test/r/have_sjis.require
mysql-test/r/have_tis620.require
mysql-test/r/have_ucs2.require
mysql-test/r/have_ujis.require
mysql-test/r/have_utf8.require
added:
mysql-test/include/have_collation.inc
mysql-test/r/create-uca.result
mysql-test/r/innodb_utf8.result
mysql-test/t/create-uca.test
mysql-test/t/innodb_utf8.test
modified:
client/mysqltest.cc
mysql-test/include/have_big5.inc
mysql-test/include/have_cp1250_ch.inc
mysql-test/include/have_cp1251.inc
mysql-test/include/have_cp866.inc
mysql-test/include/have_cp932.inc
mysql-test/include/have_eucjpms.inc
mysql-test/include/have_euckr.inc
mysql-test/include/have_gb2312.inc
mysql-test/include/have_gbk.inc
mysql-test/include/have_koi8r.inc
mysql-test/include/have_latin2_ch.inc
mysql-test/include/have_sjis.inc
mysql-test/include/have_tis620.inc
mysql-test/include/have_ucs2.inc
mysql-test/include/have_ujis.inc
mysql-test/include/have_utf8.inc
mysql-test/r/create.result
mysql-test/r/innodb.result
mysql-test/suite/rpl/t/rpl_ignore_table.test
mysql-test/t/create.test
mysql-test/t/ctype_utf8.test
mysql-test/t/ddl_i18n_koi8r.test
mysql-test/t/ddl_i18n_utf8.test
mysql-test/t/fulltext.test
mysql-test/t/fulltext2.test
mysql-test/t/innodb.test
mysql-test/t/query_cache_ps_no_prot.test
mysql-test/t/query_cache_ps_ps_prot.test
scripts/mysqlbug.sh
storage/ndb/plug.in
per-file messages:
client/mysqltest.cc
SKIP now expands variables (for better error messages)
mysql-test/include/have_big5.inc
Simplify by using have_collation.inc
mysql-test/include/have_collation.inc
Test if '$collation' is supported
mysql-test/include/have_cp1250_ch.inc
Simplify by using have_collation.inc
mysql-test/include/have_cp1251.inc
Simplify by using have_collation.inc
mysql-test/include/have_cp866.inc
Simplify by using have_collation.inc
mysql-test/include/have_cp932.inc
Simplify by using have_collation.inc
mysql-test/include/have_eucjpms.inc
Simplify by using have_collation.inc
mysql-test/include/have_euckr.inc
Simplify by using have_collation.inc
mysql-test/include/have_gb2312.inc
Simplify by using have_collation.inc
mysql-test/include/have_gbk.inc
Simplify by using have_collation.inc
mysql-test/include/have_koi8r.inc
Simplify by using have_collation.inc
mysql-test/include/have_latin2_ch.inc
Simplify by using have_collation.inc
mysql-test/include/have_sjis.inc
Simplify by using have_collation.inc
mysql-test/include/have_tis620.inc
Simplify by using have_collation.inc
mysql-test/include/have_ucs2.inc
Simplify by using have_collation.inc
mysql-test/include/have_ujis.inc
Simplify by using have_collation.inc
mysql-test/include/have_utf8.inc
Simplify by using have_collation.inc
mysql-test/r/create-uca.result
Create tests that uses unicode
mysql-test/r/create.result
Move test with unicode to create-uca.test
mysql-test/r/have_big5.require
Not needed anymore
mysql-test/r/have_cp1250_ch.require
Not needed anymore
mysql-test/r/have_cp1251.require
Not needed anymore
mysql-test/r/have_cp866.require
Not needed anymore
mysql-test/r/have_cp932.require
Not needed anymore
mysql-test/r/have_eucjpms.require
Not needed anymore
mysql-test/r/have_euckr.require
Not needed anymore
mysql-test/r/have_gb2312.require
Not needed anymore
mysql-test/r/have_gbk.require
Not needed anymore
mysql-test/r/have_koi8r.require
Not needed anymore
mysql-test/r/have_latin2_ch.require
Not needed anymore
mysql-test/r/have_sjis.require
Not needed anymore
mysql-test/r/have_tis620.require
Not needed anymore
mysql-test/r/have_ucs2.require
Not needed anymore
mysql-test/r/have_ujis.require
Not needed anymore
mysql-test/r/have_utf8.require
Not needed anymore
mysql-test/r/innodb.result
Move tests that depends on unicode to innodb_utf8.test
mysql-test/r/innodb_utf8.result
Test moved from innodb.test
mysql-test/suite/rpl/t/rpl_ignore_table.test
Test for required collations
mysql-test/t/create-uca.test
Create tests that uses unicode
mysql-test/t/create.test
Move test with unicode to create-uca.test
mysql-test/t/ctype_utf8.test
Test that require unicode
mysql-test/t/ddl_i18n_koi8r.test
Test for required collations
mysql-test/t/ddl_i18n_utf8.test
Test for required collations
mysql-test/t/fulltext.test
Test for required collations
mysql-test/t/fulltext2.test
Test for required collations
mysql-test/t/innodb.test
Move tests that depends on unicode to innodb_utf8.test
mysql-test/t/innodb_utf8.test
Tests that uses unicode
mysql-test/t/query_cache_ps_no_prot.test
Test for required collations
mysql-test/t/query_cache_ps_ps_prot.test
Test for required collations
scripts/mysqlbug.sh
Send emails to maria-developers(a)lists.launchpad.net
storage/ndb/plug.in
Don't include ndb in 'max' builds
=== modified file 'client/mysqltest.cc'
--- a/client/mysqltest.cc 2009-12-03 11:19:05 +0000
+++ b/client/mysqltest.cc 2009-12-27 13:54:41 +0000
@@ -1267,6 +1267,7 @@ void abort_not_supported_test(const char
DBUG_ENTER("abort_not_supported_test");
/* Print include filestack */
+ fflush(stdout);
fprintf(stderr, "The test '%s' is not supported by this installation\n",
file_stack->file_name);
fprintf(stderr, "Detected in file %s at line %d\n",
@@ -8098,7 +8099,10 @@ int main(int argc, char **argv)
abort_flag= 1;
break;
case Q_SKIP:
- abort_not_supported_test("%s", command->first_argument);
+ /* Eval the query, thus replacing all environment variables */
+ dynstr_set(&ds_res, 0);
+ do_eval(&ds_res, command->first_argument, command->end, FALSE);
+ abort_not_supported_test("%s",ds_res.str);
break;
case Q_RESULT:
=== modified file 'mysql-test/include/have_big5.inc'
--- a/mysql-test/include/have_big5.inc 2008-07-04 16:41:27 +0000
+++ b/mysql-test/include/have_big5.inc 2009-12-27 13:54:41 +0000
@@ -1,4 +1,2 @@
--- require r/have_big5.require
-disable_query_log;
-show collation like 'big5_chinese_ci';
-enable_query_log;
+let collation=big5_chinese_ci;
+--source include/have_collation.inc
=== added file 'mysql-test/include/have_collation.inc'
--- a/mysql-test/include/have_collation.inc 1970-01-01 00:00:00 +0000
+++ b/mysql-test/include/have_collation.inc 2009-12-27 13:54:41 +0000
@@ -0,0 +1,3 @@
+if (!`SELECT count(*) AS 'true' FROM information_schema.collations WHERE collation_name LIKE '$collation'`) {
+ skip Test needs character set '$collation';
+}
=== modified file 'mysql-test/include/have_cp1250_ch.inc'
--- a/mysql-test/include/have_cp1250_ch.inc 2008-07-04 16:41:27 +0000
+++ b/mysql-test/include/have_cp1250_ch.inc 2009-12-27 13:54:41 +0000
@@ -1,4 +1,2 @@
--- require r/have_cp1250_ch.require
-disable_query_log;
-show collation like 'cp1250_czech_cs';
-enable_query_log;
+let collation=cp1250_czech_cs;
+--source include/have_collation.inc
=== modified file 'mysql-test/include/have_cp1251.inc'
--- a/mysql-test/include/have_cp1251.inc 2007-06-28 17:34:54 +0000
+++ b/mysql-test/include/have_cp1251.inc 2009-12-27 13:54:41 +0000
@@ -1,7 +1,2 @@
---require r/have_cp1251.require
-
---disable_query_log
-
-SHOW COLLATION LIKE 'cp1251_general_ci';
-
---enable_query_log
+let collation=cp1251_general_ci;
+--source include/have_collation.inc
=== modified file 'mysql-test/include/have_cp866.inc'
--- a/mysql-test/include/have_cp866.inc 2007-06-28 17:34:54 +0000
+++ b/mysql-test/include/have_cp866.inc 2009-12-27 13:54:41 +0000
@@ -1,7 +1,2 @@
---require r/have_cp866.require
-
---disable_query_log
-
-SHOW COLLATION LIKE 'cp866_general_ci';
-
---enable_query_log
+let collation=cp866_general_ci;
+--source include/have_collation.inc
=== modified file 'mysql-test/include/have_cp932.inc'
--- a/mysql-test/include/have_cp932.inc 2008-07-04 16:41:27 +0000
+++ b/mysql-test/include/have_cp932.inc 2009-12-27 13:54:41 +0000
@@ -1,4 +1,2 @@
--- require r/have_cp932.require
-disable_query_log;
-show collation like 'cp932_japanese_ci';
-enable_query_log;
+let collation=cp932_japanese_ci;
+--source include/have_collation.inc
=== modified file 'mysql-test/include/have_eucjpms.inc'
--- a/mysql-test/include/have_eucjpms.inc 2008-07-04 16:41:27 +0000
+++ b/mysql-test/include/have_eucjpms.inc 2009-12-27 13:54:41 +0000
@@ -1,4 +1,2 @@
--- require r/have_eucjpms.require
-disable_query_log;
-show collation like 'eucjpms_japanese_ci';
-enable_query_log;
+let collation=eucjpms_japanese_ci;
+--source include/have_collation.inc
=== modified file 'mysql-test/include/have_euckr.inc'
--- a/mysql-test/include/have_euckr.inc 2008-07-04 16:41:27 +0000
+++ b/mysql-test/include/have_euckr.inc 2009-12-27 13:54:41 +0000
@@ -1,4 +1,2 @@
--- require r/have_euckr.require
-disable_query_log;
-show collation like 'euckr_korean_ci';
-enable_query_log;
+let collation=euckr_korean_ci;
+--source include/have_collation.inc
=== modified file 'mysql-test/include/have_gb2312.inc'
--- a/mysql-test/include/have_gb2312.inc 2008-07-04 16:41:27 +0000
+++ b/mysql-test/include/have_gb2312.inc 2009-12-27 13:54:41 +0000
@@ -1,4 +1,2 @@
--- require r/have_gb2312.require
-disable_query_log;
-show collation like 'gb2312_chinese_ci';
-enable_query_log;
+let collation=gb2312_chinese_ci;
+--source include/have_collation.inc
=== modified file 'mysql-test/include/have_gbk.inc'
--- a/mysql-test/include/have_gbk.inc 2008-07-04 16:41:27 +0000
+++ b/mysql-test/include/have_gbk.inc 2009-12-27 13:54:41 +0000
@@ -1,4 +1,2 @@
--- require r/have_gbk.require
-disable_query_log;
-show collation like 'gbk_chinese_ci';
-enable_query_log;
+let collation=gbk_chinese_ci;
+--source include/have_collation.inc
=== modified file 'mysql-test/include/have_koi8r.inc'
--- a/mysql-test/include/have_koi8r.inc 2007-06-28 17:34:54 +0000
+++ b/mysql-test/include/have_koi8r.inc 2009-12-27 13:54:41 +0000
@@ -1,7 +1,2 @@
---require r/have_koi8r.require
-
---disable_query_log
-
-SHOW COLLATION LIKE 'koi8r_general_ci';
-
---enable_query_log
+let collation=koi8r_general_ci;
+--source include/have_collation.inc
=== modified file 'mysql-test/include/have_latin2_ch.inc'
--- a/mysql-test/include/have_latin2_ch.inc 2008-07-04 16:41:27 +0000
+++ b/mysql-test/include/have_latin2_ch.inc 2009-12-27 13:54:41 +0000
@@ -1,4 +1,2 @@
--- require r/have_latin2_ch.require
-disable_query_log;
-show collation like 'latin2_czech_cs';
-enable_query_log;
+let collation=latin2_czech_cs;
+--source include/have_collation.inc
=== modified file 'mysql-test/include/have_sjis.inc'
--- a/mysql-test/include/have_sjis.inc 2008-07-04 16:41:27 +0000
+++ b/mysql-test/include/have_sjis.inc 2009-12-27 13:54:41 +0000
@@ -1,4 +1,2 @@
--- require r/have_sjis.require
-disable_query_log;
-show collation like 'sjis_japanese_ci';
-enable_query_log;
+let collation=sjis_japanese_ci;
+--source include/have_collation.inc
=== modified file 'mysql-test/include/have_tis620.inc'
--- a/mysql-test/include/have_tis620.inc 2008-07-04 16:41:27 +0000
+++ b/mysql-test/include/have_tis620.inc 2009-12-27 13:54:41 +0000
@@ -1,4 +1,2 @@
--- require r/have_tis620.require
-disable_query_log;
-show collation like 'tis620_thai_ci';
-enable_query_log;
+let collation=tis620_thai_ci;
+--source include/have_collation.inc
=== modified file 'mysql-test/include/have_ucs2.inc'
--- a/mysql-test/include/have_ucs2.inc 2008-07-04 16:41:27 +0000
+++ b/mysql-test/include/have_ucs2.inc 2009-12-27 13:54:41 +0000
@@ -1,4 +1,2 @@
--- require r/have_ucs2.require
-disable_query_log;
-show collation like 'ucs2_general_ci';
-enable_query_log;
+let collation=ucs2_general_ci;
+--source include/have_collation.inc
=== modified file 'mysql-test/include/have_ujis.inc'
--- a/mysql-test/include/have_ujis.inc 2008-07-04 16:41:27 +0000
+++ b/mysql-test/include/have_ujis.inc 2009-12-27 13:54:41 +0000
@@ -1,4 +1,2 @@
--- require r/have_ujis.require
-disable_query_log;
-show collation like 'ujis_japanese_ci';
-enable_query_log;
+let collation=ujis_japanese_ci;
+--source include/have_collation.inc
=== modified file 'mysql-test/include/have_utf8.inc'
--- a/mysql-test/include/have_utf8.inc 2007-06-28 17:34:54 +0000
+++ b/mysql-test/include/have_utf8.inc 2009-12-27 13:54:41 +0000
@@ -1,7 +1,2 @@
---require r/have_utf8.require
-
---disable_query_log
-
-SHOW COLLATION LIKE 'utf8_general_ci';
-
---enable_query_log
+let collation=utf8_general_ci;
+--source include/have_collation.inc
=== added file 'mysql-test/r/create-uca.result'
--- a/mysql-test/r/create-uca.result 1970-01-01 00:00:00 +0000
+++ b/mysql-test/r/create-uca.result 2009-12-27 13:54:41 +0000
@@ -0,0 +1,31 @@
+drop table if exists t1,t2;
+CREATE TABLE t1(
+c1 INT DEFAULT 12 COMMENT 'column1',
+c2 INT NULL COMMENT 'column2',
+c3 INT NOT NULL COMMENT 'column3',
+c4 VARCHAR(255) CHARACTER SET utf8 NOT NULL DEFAULT 'a',
+c5 VARCHAR(255) COLLATE utf8_unicode_ci NULL DEFAULT 'b',
+c6 VARCHAR(255))
+COLLATE latin1_bin;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `c1` int(11) DEFAULT '12' COMMENT 'column1',
+ `c2` int(11) DEFAULT NULL COMMENT 'column2',
+ `c3` int(11) NOT NULL COMMENT 'column3',
+ `c4` varchar(255) CHARACTER SET utf8 NOT NULL DEFAULT 'a',
+ `c5` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT 'b',
+ `c6` varchar(255) COLLATE latin1_bin DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_bin
+CREATE TABLE t2 AS SELECT * FROM t1;
+SHOW CREATE TABLE t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `c1` int(11) DEFAULT '12' COMMENT 'column1',
+ `c2` int(11) DEFAULT NULL COMMENT 'column2',
+ `c3` int(11) NOT NULL COMMENT 'column3',
+ `c4` varchar(255) CHARACTER SET utf8 NOT NULL DEFAULT 'a',
+ `c5` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT 'b',
+ `c6` varchar(255) CHARACTER SET latin1 COLLATE latin1_bin DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1,t2;
=== modified file 'mysql-test/r/create.result'
--- a/mysql-test/r/create.result 2009-12-03 11:19:05 +0000
+++ b/mysql-test/r/create.result 2009-12-27 13:54:41 +0000
@@ -1793,52 +1793,6 @@ t1 CREATE TABLE `t1` (
drop table t1;
# --
-# -- Bug#21380: DEFAULT definition not always transfered by CREATE
-# -- TABLE/SELECT to the new table.
-# --
-
-DROP TABLE IF EXISTS t1;
-DROP TABLE IF EXISTS t2;
-
-CREATE TABLE t1(
-c1 INT DEFAULT 12 COMMENT 'column1',
-c2 INT NULL COMMENT 'column2',
-c3 INT NOT NULL COMMENT 'column3',
-c4 VARCHAR(255) CHARACTER SET utf8 NOT NULL DEFAULT 'a',
-c5 VARCHAR(255) COLLATE utf8_unicode_ci NULL DEFAULT 'b',
-c6 VARCHAR(255))
-COLLATE latin1_bin;
-
-SHOW CREATE TABLE t1;
-Table Create Table
-t1 CREATE TABLE `t1` (
- `c1` int(11) DEFAULT '12' COMMENT 'column1',
- `c2` int(11) DEFAULT NULL COMMENT 'column2',
- `c3` int(11) NOT NULL COMMENT 'column3',
- `c4` varchar(255) CHARACTER SET utf8 NOT NULL DEFAULT 'a',
- `c5` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT 'b',
- `c6` varchar(255) COLLATE latin1_bin DEFAULT NULL
-) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_bin
-
-CREATE TABLE t2 AS SELECT * FROM t1;
-
-SHOW CREATE TABLE t2;
-Table Create Table
-t2 CREATE TABLE `t2` (
- `c1` int(11) DEFAULT '12' COMMENT 'column1',
- `c2` int(11) DEFAULT NULL COMMENT 'column2',
- `c3` int(11) NOT NULL COMMENT 'column3',
- `c4` varchar(255) CHARACTER SET utf8 NOT NULL DEFAULT 'a',
- `c5` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT 'b',
- `c6` varchar(255) CHARACTER SET latin1 COLLATE latin1_bin DEFAULT NULL
-) ENGINE=MyISAM DEFAULT CHARSET=latin1
-
-DROP TABLE t2;
-DROP TABLE t1;
-
-# -- End of test case for Bug#21380.
-
-# --
# -- Bug#18834: ALTER TABLE ADD INDEX on table with two timestamp fields
# --
=== removed file 'mysql-test/r/have_big5.require'
--- a/mysql-test/r/have_big5.require 2003-12-24 12:59:48 +0000
+++ b/mysql-test/r/have_big5.require 1970-01-01 00:00:00 +0000
@@ -1,2 +0,0 @@
-Collation Charset Id Default Compiled Sortlen
-big5_chinese_ci big5 1 Yes Yes 1
=== removed file 'mysql-test/r/have_cp1250_ch.require'
--- a/mysql-test/r/have_cp1250_ch.require 2005-03-03 10:15:37 +0000
+++ b/mysql-test/r/have_cp1250_ch.require 1970-01-01 00:00:00 +0000
@@ -1,2 +0,0 @@
-Collation Charset Id Default Compiled Sortlen
-cp1250_czech_cs cp1250 34 Yes 2
=== removed file 'mysql-test/r/have_cp1251.require'
--- a/mysql-test/r/have_cp1251.require 2007-06-28 17:34:54 +0000
+++ b/mysql-test/r/have_cp1251.require 1970-01-01 00:00:00 +0000
@@ -1,2 +0,0 @@
-Collation Charset Id Default Compiled Sortlen
-cp1251_general_ci cp1251 51 Yes 0
=== removed file 'mysql-test/r/have_cp866.require'
--- a/mysql-test/r/have_cp866.require 2007-06-28 17:34:54 +0000
+++ b/mysql-test/r/have_cp866.require 1970-01-01 00:00:00 +0000
@@ -1,2 +0,0 @@
-Collation Charset Id Default Compiled Sortlen
-cp866_general_ci cp866 36 Yes 0
=== removed file 'mysql-test/r/have_cp932.require'
--- a/mysql-test/r/have_cp932.require 2005-02-01 10:37:51 +0000
+++ b/mysql-test/r/have_cp932.require 1970-01-01 00:00:00 +0000
@@ -1,2 +0,0 @@
-Collation Charset Id Default Compiled Sortlen
-cp932_japanese_ci cp932 95 Yes Yes 1
=== removed file 'mysql-test/r/have_eucjpms.require'
--- a/mysql-test/r/have_eucjpms.require 2005-02-01 10:37:51 +0000
+++ b/mysql-test/r/have_eucjpms.require 1970-01-01 00:00:00 +0000
@@ -1,2 +0,0 @@
-Collation Charset Id Default Compiled Sortlen
-eucjpms_japanese_ci eucjpms 97 Yes Yes 1
=== removed file 'mysql-test/r/have_euckr.require'
--- a/mysql-test/r/have_euckr.require 2005-12-09 12:37:58 +0000
+++ b/mysql-test/r/have_euckr.require 1970-01-01 00:00:00 +0000
@@ -1,2 +0,0 @@
-Collation Charset Id Default Compiled Sortlen
-euckr_korean_ci euckr 19 Yes Yes 1
=== removed file 'mysql-test/r/have_gb2312.require'
--- a/mysql-test/r/have_gb2312.require 2005-12-09 12:37:58 +0000
+++ b/mysql-test/r/have_gb2312.require 1970-01-01 00:00:00 +0000
@@ -1,2 +0,0 @@
-Collation Charset Id Default Compiled Sortlen
-gb2312_chinese_ci gb2312 24 Yes Yes 1
=== removed file 'mysql-test/r/have_gbk.require'
--- a/mysql-test/r/have_gbk.require 2005-07-22 16:06:02 +0000
+++ b/mysql-test/r/have_gbk.require 1970-01-01 00:00:00 +0000
@@ -1,2 +0,0 @@
-Collation Charset Id Default Compiled Sortlen
-gbk_chinese_ci gbk 28 Yes Yes 1
=== removed file 'mysql-test/r/have_koi8r.require'
--- a/mysql-test/r/have_koi8r.require 2007-06-28 17:34:54 +0000
+++ b/mysql-test/r/have_koi8r.require 1970-01-01 00:00:00 +0000
@@ -1,2 +0,0 @@
-Collation Charset Id Default Compiled Sortlen
-koi8r_general_ci koi8r 7 Yes 0
=== removed file 'mysql-test/r/have_latin2_ch.require'
--- a/mysql-test/r/have_latin2_ch.require 2006-03-20 12:28:25 +0000
+++ b/mysql-test/r/have_latin2_ch.require 1970-01-01 00:00:00 +0000
@@ -1,2 +0,0 @@
-Collation Charset Id Default Compiled Sortlen
-latin2_czech_cs latin2 2 Yes 4
=== removed file 'mysql-test/r/have_sjis.require'
--- a/mysql-test/r/have_sjis.require 2004-03-25 10:29:56 +0000
+++ b/mysql-test/r/have_sjis.require 1970-01-01 00:00:00 +0000
@@ -1,2 +0,0 @@
-Collation Charset Id Default Compiled Sortlen
-sjis_japanese_ci sjis 13 Yes Yes 1
=== removed file 'mysql-test/r/have_tis620.require'
--- a/mysql-test/r/have_tis620.require 2003-12-25 16:11:01 +0000
+++ b/mysql-test/r/have_tis620.require 1970-01-01 00:00:00 +0000
@@ -1,2 +0,0 @@
-Collation Charset Id Default Compiled Sortlen
-tis620_thai_ci tis620 18 Yes Yes 4
=== removed file 'mysql-test/r/have_ucs2.require'
--- a/mysql-test/r/have_ucs2.require 2003-06-02 12:19:06 +0000
+++ b/mysql-test/r/have_ucs2.require 1970-01-01 00:00:00 +0000
@@ -1,2 +0,0 @@
-Collation Charset Id Default Compiled Sortlen
-ucs2_general_ci ucs2 35 Yes Yes 1
=== removed file 'mysql-test/r/have_ujis.require'
--- a/mysql-test/r/have_ujis.require 2003-09-19 10:18:19 +0000
+++ b/mysql-test/r/have_ujis.require 1970-01-01 00:00:00 +0000
@@ -1,2 +0,0 @@
-Collation Charset Id Default Compiled Sortlen
-ujis_japanese_ci ujis 12 Yes Yes 1
=== removed file 'mysql-test/r/have_utf8.require'
--- a/mysql-test/r/have_utf8.require 2007-06-28 17:34:54 +0000
+++ b/mysql-test/r/have_utf8.require 1970-01-01 00:00:00 +0000
@@ -1,2 +0,0 @@
-Collation Charset Id Default Compiled Sortlen
-utf8_general_ci utf8 33 Yes Yes 1
=== modified file 'mysql-test/r/innodb.result'
--- a/mysql-test/r/innodb.result 2009-11-13 21:26:08 +0000
+++ b/mysql-test/r/innodb.result 2009-12-27 13:54:41 +0000
@@ -3160,15 +3160,6 @@ ALTER TABLE t2 MODIFY a INT NOT NULL;
ERROR HY000: Error on rename of '#sql-temporary' to './test/t2' (errno: 150)
DELETE FROM t1;
DROP TABLE t2,t1;
-CREATE TABLE t1 (a VARCHAR(5) COLLATE utf8_unicode_ci PRIMARY KEY)
-ENGINE=InnoDB;
-INSERT INTO t1 VALUES (0xEFBCA4EFBCA4EFBCA4);
-DELETE FROM t1;
-INSERT INTO t1 VALUES ('DDD');
-SELECT * FROM t1;
-a
-DDD
-DROP TABLE t1;
CREATE TABLE t1 (id int PRIMARY KEY AUTO_INCREMENT) ENGINE=InnoDB
AUTO_INCREMENT=42;
INSERT INTO t1 VALUES (0),(347),(0);
=== added file 'mysql-test/r/innodb_utf8.result'
--- a/mysql-test/r/innodb_utf8.result 1970-01-01 00:00:00 +0000
+++ b/mysql-test/r/innodb_utf8.result 2009-12-27 13:54:41 +0000
@@ -0,0 +1,10 @@
+drop table if exists t1;
+CREATE TABLE t1 (a VARCHAR(5) COLLATE utf8_unicode_ci PRIMARY KEY)
+ENGINE=InnoDB;
+INSERT INTO t1 VALUES (0xEFBCA4EFBCA4EFBCA4);
+DELETE FROM t1;
+INSERT INTO t1 VALUES ('DDD');
+SELECT * FROM t1;
+a
+DDD
+DROP TABLE t1;
=== modified file 'mysql-test/suite/rpl/t/rpl_ignore_table.test'
--- a/mysql-test/suite/rpl/t/rpl_ignore_table.test 2008-11-13 19:19:00 +0000
+++ b/mysql-test/suite/rpl/t/rpl_ignore_table.test 2009-12-27 13:54:41 +0000
@@ -1,4 +1,6 @@
source include/master-slave.inc;
+let collation=utf8_unicode_ci;
+--source include/have_collation.inc
#
# BUG#16487
=== added file 'mysql-test/t/create-uca.test'
--- a/mysql-test/t/create-uca.test 1970-01-01 00:00:00 +0000
+++ b/mysql-test/t/create-uca.test 2009-12-27 13:54:41 +0000
@@ -0,0 +1,26 @@
+# Prerequisites
+let collation=utf8_unicode_ci;
+--source include/have_collation.inc
+
+# Initial cleanup
+--disable_warnings
+drop table if exists t1,t2;
+--enable_warnings
+
+#
+# Bug#21380: DEFAULT definition not always transfered by CREATE
+# TABLE/SELECT to the new table.
+#
+
+CREATE TABLE t1(
+ c1 INT DEFAULT 12 COMMENT 'column1',
+ c2 INT NULL COMMENT 'column2',
+ c3 INT NOT NULL COMMENT 'column3',
+ c4 VARCHAR(255) CHARACTER SET utf8 NOT NULL DEFAULT 'a',
+ c5 VARCHAR(255) COLLATE utf8_unicode_ci NULL DEFAULT 'b',
+ c6 VARCHAR(255))
+ COLLATE latin1_bin;
+SHOW CREATE TABLE t1;
+CREATE TABLE t2 AS SELECT * FROM t1;
+SHOW CREATE TABLE t2;
+DROP TABLE t1,t2;
=== modified file 'mysql-test/t/create.test'
--- a/mysql-test/t/create.test 2009-12-03 11:19:05 +0000
+++ b/mysql-test/t/create.test 2009-12-27 13:54:41 +0000
@@ -1400,52 +1400,6 @@ drop table t1;
--echo
--echo # --
---echo # -- Bug#21380: DEFAULT definition not always transfered by CREATE
---echo # -- TABLE/SELECT to the new table.
---echo # --
---echo
-
-
---disable_warnings
-DROP TABLE IF EXISTS t1;
-DROP TABLE IF EXISTS t2;
---enable_warnings
-
---echo
-
-CREATE TABLE t1(
- c1 INT DEFAULT 12 COMMENT 'column1',
- c2 INT NULL COMMENT 'column2',
- c3 INT NOT NULL COMMENT 'column3',
- c4 VARCHAR(255) CHARACTER SET utf8 NOT NULL DEFAULT 'a',
- c5 VARCHAR(255) COLLATE utf8_unicode_ci NULL DEFAULT 'b',
- c6 VARCHAR(255))
- COLLATE latin1_bin;
-
---echo
-
-SHOW CREATE TABLE t1;
-
---echo
-
-CREATE TABLE t2 AS SELECT * FROM t1;
-
---echo
-
-SHOW CREATE TABLE t2;
-
---echo
-
-DROP TABLE t2;
-DROP TABLE t1;
-
---echo
---echo # -- End of test case for Bug#21380.
-
-###########################################################################
-
---echo
---echo # --
--echo # -- Bug#18834: ALTER TABLE ADD INDEX on table with two timestamp fields
--echo # --
--echo
=== modified file 'mysql-test/t/ctype_utf8.test'
--- a/mysql-test/t/ctype_utf8.test 2009-01-26 21:19:13 +0000
+++ b/mysql-test/t/ctype_utf8.test 2009-12-27 13:54:41 +0000
@@ -2,6 +2,15 @@
# Tests with the utf8 character set
#
+let collation=utf8_unicode_ci;
+--source include/have_collation.inc
+
+--disable_warnings
+drop table if exists t1,t2,t3,t4;
+drop database if exists mysqltest;
+--enable_warnings
+
+
--disable_warnings
drop table if exists t1,t2;
--enable_warnings
=== modified file 'mysql-test/t/ddl_i18n_koi8r.test'
--- a/mysql-test/t/ddl_i18n_koi8r.test 2009-05-15 10:15:56 +0000
+++ b/mysql-test/t/ddl_i18n_koi8r.test 2009-12-27 13:54:41 +0000
@@ -36,6 +36,8 @@
--source include/have_cp866.inc
--source include/have_cp1251.inc
--source include/have_koi8r.inc
+let collation=utf8_unicode_ci;
+--source include/have_collation.inc
###########################################################################
=== modified file 'mysql-test/t/ddl_i18n_utf8.test'
--- a/mysql-test/t/ddl_i18n_utf8.test 2009-05-15 10:15:56 +0000
+++ b/mysql-test/t/ddl_i18n_utf8.test 2009-12-27 13:54:41 +0000
@@ -36,6 +36,8 @@
--source include/have_cp866.inc
--source include/have_cp1251.inc
--source include/have_koi8r.inc
+let collation=utf8_unicode_ci;
+--source include/have_collation.inc
###########################################################################
=== modified file 'mysql-test/t/fulltext.test'
--- a/mysql-test/t/fulltext.test 2009-09-07 20:50:10 +0000
+++ b/mysql-test/t/fulltext.test 2009-12-27 13:54:41 +0000
@@ -2,6 +2,9 @@
# Test of fulltext index
#
+let collation=utf8_unicode_ci;
+--source include/have_collation.inc
+
--disable_warnings
drop table if exists t1,t2,t3;
--enable_warnings
=== modified file 'mysql-test/t/fulltext2.test'
--- a/mysql-test/t/fulltext2.test 2009-10-28 07:52:34 +0000
+++ b/mysql-test/t/fulltext2.test 2009-12-27 13:54:41 +0000
@@ -2,6 +2,9 @@
# test of new fulltext search features
#
+let collation=utf8_unicode_ci;
+--source include/have_collation.inc
+
#
# two-level tree
#
=== modified file 'mysql-test/t/innodb.test'
--- a/mysql-test/t/innodb.test 2009-11-13 21:26:08 +0000
+++ b/mysql-test/t/innodb.test 2009-12-27 13:54:41 +0000
@@ -2353,18 +2353,6 @@ DELETE FROM t1;
DROP TABLE t2,t1;
#
-# Bug #26835: table corruption after delete+insert
-#
-
-CREATE TABLE t1 (a VARCHAR(5) COLLATE utf8_unicode_ci PRIMARY KEY)
-ENGINE=InnoDB;
-INSERT INTO t1 VALUES (0xEFBCA4EFBCA4EFBCA4);
-DELETE FROM t1;
-INSERT INTO t1 VALUES ('DDD');
-SELECT * FROM t1;
-DROP TABLE t1;
-
-#
# Bug #23313 (AUTO_INCREMENT=# not reported back for InnoDB tables)
# Bug #21404 (AUTO_INCREMENT value reset when Adding FKEY (or ALTER?))
#
=== added file 'mysql-test/t/innodb_utf8.test'
--- a/mysql-test/t/innodb_utf8.test 1970-01-01 00:00:00 +0000
+++ b/mysql-test/t/innodb_utf8.test 2009-12-27 13:54:41 +0000
@@ -0,0 +1,24 @@
+#
+# Tests for innodb that requires not default character sets
+#
+
+--source include/have_innodb.inc
+let collation=utf8_unicode_ci;
+--source include/have_collation.inc
+
+# Setup
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+
+#
+# Bug #26835: table corruption after delete+insert
+#
+
+CREATE TABLE t1 (a VARCHAR(5) COLLATE utf8_unicode_ci PRIMARY KEY)
+ENGINE=InnoDB;
+INSERT INTO t1 VALUES (0xEFBCA4EFBCA4EFBCA4);
+DELETE FROM t1;
+INSERT INTO t1 VALUES ('DDD');
+SELECT * FROM t1;
+DROP TABLE t1;
=== modified file 'mysql-test/t/query_cache_ps_no_prot.test'
--- a/mysql-test/t/query_cache_ps_no_prot.test 2007-05-24 20:13:49 +0000
+++ b/mysql-test/t/query_cache_ps_no_prot.test 2009-12-27 13:54:41 +0000
@@ -11,8 +11,9 @@
# We cannot run on embedded server because we use multiple sessions.
--source include/not_embedded.inc
-
--source include/have_query_cache.inc
+let collation=utf8_unicode_ci;
+--source include/have_collation.inc
# The file with expected results fits only to a run without
# ps-protocol/sp-protocol/cursor-protocol/view-protocol.
=== modified file 'mysql-test/t/query_cache_ps_ps_prot.test'
--- a/mysql-test/t/query_cache_ps_ps_prot.test 2007-05-24 20:13:49 +0000
+++ b/mysql-test/t/query_cache_ps_ps_prot.test 2009-12-27 13:54:41 +0000
@@ -11,8 +11,9 @@
# We cannot run on embedded server because we use multiple sessions.
--source include/not_embedded.inc
-
--source include/have_query_cache.inc
+let collation=utf8_unicode_ci;
+--source include/have_collation.inc
# The file with expected results fits only to a run with "--ps-protocol".
if (`SELECT $SP_PROTOCOL + $CURSOR_PROTOCOL + $VIEW_PROTOCOL > 0
=== modified file 'scripts/mysqlbug.sh'
--- a/scripts/mysqlbug.sh 2007-10-19 17:06:30 +0000
+++ b/scripts/mysqlbug.sh 2009-12-27 13:54:41 +0000
@@ -21,7 +21,7 @@ echo "Finding system information for a M
VERSION="@VERSION@@MYSQL_SERVER_SUFFIX@"
COMPILATION_COMMENT="@COMPILATION_COMMENT@"
-BUGmysql="mysql(a)lists.mysql.com"
+BUGmysql="maria-developers(a)lists.launchpad.net"
# This is set by configure
COMP_CALL_INFO="CC='@SAVE_CC@' CFLAGS='@SAVE_CFLAGS@' CXX='@SAVE_CXX@' CXXFLAGS='@SAVE_CXXFLAGS@' LDFLAGS='@SAVE_LDFLAGS@' ASFLAGS='@SAVE_ASFLAGS@'"
COMP_RUN_INFO="CC='@CC@' CFLAGS='@CFLAGS@' CXX='@CXX@' CXXFLAGS='@CXXFLAGS@' LDFLAGS='@LDFLAGS@' ASFLAGS='@ASFLAGS@'"
=== modified file 'storage/ndb/plug.in'
--- a/storage/ndb/plug.in 2006-08-19 04:19:19 +0000
+++ b/storage/ndb/plug.in 2009-12-27 13:54:41 +0000
@@ -1,5 +1,5 @@
MYSQL_STORAGE_ENGINE(ndbcluster, ndbcluster, [Cluster Storage Engine],
- [High Availability Clustered tables], [max])
+ [High Availability Clustered tables],)
MYSQL_PLUGIN_DIRECTORY(ndbcluster,[storage/ndb])
MYSQL_PLUGIN_STATIC(ndbcluster, [[\$(ndbcluster_libs) \$(ndbcluster_system_libs) \$(NDB_SCI_LIBS)]])
MYSQL_PLUGIN_ACTIONS(ndbcluster,[MYSQL_SETUP_NDBCLUSTER])
2
1