Commit da138f02 authored by unknown's avatar unknown

Merge OQGraph into MariaDB 5.2.

parents d0b32f1a 88b3697d
...@@ -204,7 +204,7 @@ if test -z "$CC" ; then ...@@ -204,7 +204,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)
......
...@@ -32,8 +32,7 @@ ...@@ -32,8 +32,7 @@
# .so files at runtime (either system stuff like NSS, or server # .so files at runtime (either system stuff like NSS, or server
# plugins). # plugins).
# #
# We link libgcc statically (and avoid linking libstdc++ at all by # We link libgcc statically to avoid reduce nasty library version dependencies.
# CXX=gcc), to avoid reduce nasty library version dependencies.
test -f Makefile && make distclean test -f Makefile && make distclean
...@@ -52,13 +51,12 @@ get_cpuopt ...@@ -52,13 +51,12 @@ get_cpuopt
get_make_parallel_flag get_make_parallel_flag
# Use gcc rather than g++ to avoid linking libstdc++.so (which we don't need). # Use gcc rather than g++ to avoid linking libstdc++.so (which we don't need).
COMP="gcc -static-libgcc"
FLAGS="-O2 -fno-omit-frame-pointer -g -pipe -Wall $CPUOPT" FLAGS="-O2 -fno-omit-frame-pointer -g -pipe -Wall $CPUOPT"
# Don't press on in case of error. # Don't press on in case of error.
set -e set -e
CC="$COMP" CXX="$COMP" CFLAGS="$FLAGS" CXXFLAGS="$FLAGS" \ CC="gcc -static-libgcc" CXX="g++ -static-libgcc" CFLAGS="$FLAGS" CXXFLAGS="$FLAGS" \
./configure \ ./configure \
--prefix=/usr/local/mysql \ --prefix=/usr/local/mysql \
--exec-prefix=/usr/local/mysql \ --exec-prefix=/usr/local/mysql \
......
...@@ -103,7 +103,8 @@ TEST_DIRS = t r include std_data std_data/parts collections \ ...@@ -103,7 +103,8 @@ TEST_DIRS = t r include std_data std_data/parts collections \
suite/parts suite/parts/t suite/parts/r suite/parts/inc \ suite/parts suite/parts/t suite/parts/r suite/parts/inc \
suite/pbxt/t suite/pbxt/r \ suite/pbxt/t suite/pbxt/r \
suite/innodb suite/innodb/t suite/innodb/r suite/innodb/include \ suite/innodb suite/innodb/t suite/innodb/r suite/innodb/include \
suite/vcol suite/vcol/t suite/vcol/r suite/vcol/inc suite/vcol suite/vcol/t suite/vcol/r suite/vcol/inc \
suite/oqgraph suite/oqgraph/t suite/oqgraph/r suite/oqgraph/include
# Used by dist-hook and install-data-local to copy all # Used by dist-hook and install-data-local to copy all
# test files into either dist or install directory # test files into either dist or install directory
......
...@@ -1150,6 +1150,16 @@ sub collect_one_test_case { ...@@ -1150,6 +1150,16 @@ sub collect_one_test_case {
} }
} }
if ( $tinfo->{'oqgraph_test'} )
{
if ( !$ENV{'OQGRAPH_PLUGIN'} )
{
$tinfo->{'skip'}= 1;
$tinfo->{'comment'}= "Test requires the OQGraph storage engine";
return $tinfo;
}
}
# Set extra config file to use # Set extra config file to use
if (defined $defaults_extra_file) { if (defined $defaults_extra_file) {
...@@ -1205,6 +1215,7 @@ my @tags= ...@@ -1205,6 +1215,7 @@ my @tags=
["include/not_embedded.inc", "not_embedded", 1], ["include/not_embedded.inc", "not_embedded", 1],
["include/not_valgrind.inc", "not_valgrind", 1], ["include/not_valgrind.inc", "not_valgrind", 1],
["include/have_example_plugin.inc", "example_plugin_test", 1], ["include/have_example_plugin.inc", "example_plugin_test", 1],
["include/have_oqgraph_engine.inc", "oqgraph_test", 1],
["include/have_ssl.inc", "need_ssl", 1], ["include/have_ssl.inc", "need_ssl", 1],
); );
......
...@@ -126,7 +126,7 @@ my $path_config_file; # The generated config file, var/my.cnf ...@@ -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= "main,binlog,federated,rpl,maria,parts,vcol"; my $DEFAULT_SUITES= "main,binlog,federated,rpl,maria,parts,vcol,oqgraph";
my $opt_suites; my $opt_suites;
our $opt_verbose= 0; # Verbose output, enable with --verbose our $opt_verbose= 0; # Verbose output, enable with --verbose
...@@ -1909,6 +1909,33 @@ sub detect_plugins { ...@@ -1909,6 +1909,33 @@ sub detect_plugins {
$ENV{'HA_EXAMPLE_SO'}="'".$plugin_filename."'"; $ENV{'HA_EXAMPLE_SO'}="'".$plugin_filename."'";
$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.";";
}
} }
# #
......
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;
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;
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;
SET binlog_format = row;
insert into graph(origid, destid) values (1,3), (3,1);
SET binlog_format = statement;
insert into graph(origid, destid) values (3,4), (4,3);
SET binlog_format = mixed;
insert into graph(origid, destid) values (3,5), (5,3);
drop table graph;
-- 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;
-- source suite/oqgraph/include/have_oqgraph_engine.inc
-- source include/have_log_bin.inc
--disable_warnings
drop table if exists graph;
--enable_warnings
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;
# MBug#524625: OQGraph error with binary logging enabled
# Test that OQGraph works with different binlogging modes.
SET binlog_format = row;
insert into graph(origid, destid) values (1,3), (3,1);
SET binlog_format = statement;
insert into graph(origid, destid) values (3,4), (4,3);
SET binlog_format = mixed;
insert into graph(origid, destid) values (3,5), (5,3);
drop table graph;
$OQGRAPH_PLUGIN_OPT
$OQGRAPH_PLUGIN_LOAD
# 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)
# 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
OQGraph storage engine
Copyright (C) 2007-2009 Arjen G Lentz & Antony T Curtis for Open Query
The Open Query GRAPH engine (OQGRAPH) is a computation engine allowing
hierarchies and more complex graph structures to be handled in a
relational fashion. In a nutshell, tree structures and
friend-of-a-friend style searches can now be done using standard SQL
syntax, and results joined onto other tables.
See http://openquery.com/graph for more information.
INSTALLATION
OQGraph requires at least version 1.40.0 of the Boost library. To
obtain a copy of the Boost library, see http://www.boost.org/
/* 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
/* 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
This diff is collapsed.
/* 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
/*
* 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 */
\ No newline at end of file
/*
* 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 */
\ No newline at end of file
This diff is collapsed.
/* 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();
};
/* 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
/* 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();
};
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_MSG_CHECKING([for Boost usable by OQGraph engine])
AC_PREPROC_IFELSE(
[
#include <boost/version.hpp>
#if BOOST_VERSION >= 104000
#else
#error oops
#endif
],
[AC_MSG_RESULT([yes])],
[AC_MSG_RESULT([no])
with_plugin_oqgraph=no])
AC_LANG_POP()
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment