mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
Import OQGraph engine into MariaDB.
This commit is contained in:
@ -202,7 +202,7 @@ if test -z "$CC" ; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
if test -z "$CXX" ; then
|
if test -z "$CXX" ; then
|
||||||
CXX=gcc
|
CXX=g++
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# If ccache (a compiler cache which reduces build time)
|
# If ccache (a compiler cache which reduces build time)
|
||||||
|
@ -126,7 +126,7 @@ my $path_config_file; # The generated config file, var/my.cnf
|
|||||||
# executables will be used by the test suite.
|
# executables will be used by the test suite.
|
||||||
our $opt_vs_config = $ENV{'MTR_VS_CONFIG'};
|
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_usage;
|
||||||
our $opt_list_options;
|
our $opt_list_options;
|
||||||
@ -1933,6 +1933,33 @@ sub environment_setup {
|
|||||||
$ENV{'EXAMPLE_PLUGIN_LOAD'}="--plugin_load=;EXAMPLE=".$plugin_filename.";";
|
$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
|
# Add the path where mysqld will find mypluglib.so
|
||||||
# ----------------------------------------------------
|
# ----------------------------------------------------
|
||||||
|
4
mysql-test/suite/oqgraph/include/have_oqgraph_engine.inc
Normal file
4
mysql-test/suite/oqgraph/include/have_oqgraph_engine.inc
Normal file
@ -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;
|
63
mysql-test/suite/oqgraph/r/basic.result
Normal file
63
mysql-test/suite/oqgraph/r/basic.result
Normal file
@ -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;
|
2
mysql-test/suite/oqgraph/t/basic-master.opt
Normal file
2
mysql-test/suite/oqgraph/t/basic-master.opt
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
$OQGRAPH_PLUGIN_OPT
|
||||||
|
$OQGRAPH_PLUGIN_LOAD
|
45
mysql-test/suite/oqgraph/t/basic.test
Normal file
45
mysql-test/suite/oqgraph/t/basic.test
Normal file
@ -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;
|
22
storage/oqgraph/CMakeFiles.txt
Normal file
22
storage/oqgraph/CMakeFiles.txt
Normal file
@ -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)
|
96
storage/oqgraph/Makefile.am
Normal file
96
storage/oqgraph/Makefile.am
Normal file
@ -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@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
|
48
storage/oqgraph/graphcore-graph.h
Normal file
48
storage/oqgraph/graphcore-graph.h
Normal file
@ -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@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
|
36
storage/oqgraph/graphcore-types.h
Normal file
36
storage/oqgraph/graphcore-types.h
Normal file
@ -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@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
|
1099
storage/oqgraph/graphcore.cc
Normal file
1099
storage/oqgraph/graphcore.cc
Normal file
File diff suppressed because it is too large
Load Diff
116
storage/oqgraph/graphcore.h
Normal file
116
storage/oqgraph/graphcore.h
Normal file
@ -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@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
|
356
storage/oqgraph/graphstore.c
Normal file
356
storage/oqgraph/graphstore.c
Normal file
@ -0,0 +1,356 @@
|
|||||||
|
/*
|
||||||
|
* Graph Engine - Copyright (C) 2007 by Arjen Lentz (arjen@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 */
|
90
storage/oqgraph/graphstore.h
Normal file
90
storage/oqgraph/graphstore.h
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
/*
|
||||||
|
* Graph Engine - Copyright (C) 2007 by Arjen Lentz (arjen@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 */
|
1040
storage/oqgraph/ha_oqgraph.cc
Normal file
1040
storage/oqgraph/ha_oqgraph.cc
Normal file
File diff suppressed because it is too large
Load Diff
114
storage/oqgraph/ha_oqgraph.h
Normal file
114
storage/oqgraph/ha_oqgraph.h
Normal file
@ -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@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();
|
||||||
|
};
|
73
storage/oqgraph/oqgraph_config.h.in
Normal file
73
storage/oqgraph/oqgraph_config.h.in
Normal file
@ -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
|
19
storage/oqgraph/oqgraph_probes.d
Normal file
19
storage/oqgraph/oqgraph_probes.d
Normal file
@ -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();
|
||||||
|
};
|
45
storage/oqgraph/oqgraph_probes.h
Normal file
45
storage/oqgraph/oqgraph_probes.h
Normal file
@ -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 */
|
32
storage/oqgraph/plug.in
Normal file
32
storage/oqgraph/plug.in
Normal file
@ -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()
|
Reference in New Issue
Block a user