Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
M
MariaDB
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
nexedi
MariaDB
Commits
b965d031
Commit
b965d031
authored
Sep 30, 2012
by
Antony T Curtis
Browse files
Options
Browse Files
Download
Plain Diff
Merge OQGraph3 into MariaDB 5.5.27
parents
a0efc4bd
0fee6ce7
Changes
13
Show whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
2127 additions
and
552 deletions
+2127
-552
storage/oqgraph/graphcore-graph.cc
storage/oqgraph/graphcore-graph.cc
+28
-0
storage/oqgraph/graphcore-graph.h
storage/oqgraph/graphcore-graph.h
+137
-17
storage/oqgraph/graphcore-types.h
storage/oqgraph/graphcore-types.h
+6
-0
storage/oqgraph/graphcore.cc
storage/oqgraph/graphcore.cc
+165
-172
storage/oqgraph/graphcore.h
storage/oqgraph/graphcore.h
+1
-1
storage/oqgraph/ha_oqgraph.cc
storage/oqgraph/ha_oqgraph.cc
+240
-355
storage/oqgraph/ha_oqgraph.h
storage/oqgraph/ha_oqgraph.h
+15
-7
storage/oqgraph/oqgraph_judy.cc
storage/oqgraph/oqgraph_judy.cc
+126
-0
storage/oqgraph/oqgraph_judy.h
storage/oqgraph/oqgraph_judy.h
+123
-0
storage/oqgraph/oqgraph_shim.cc
storage/oqgraph/oqgraph_shim.cc
+76
-0
storage/oqgraph/oqgraph_shim.h
storage/oqgraph/oqgraph_shim.h
+488
-0
storage/oqgraph/oqgraph_thunk.cc
storage/oqgraph/oqgraph_thunk.cc
+553
-0
storage/oqgraph/oqgraph_thunk.h
storage/oqgraph/oqgraph_thunk.h
+169
-0
No files found.
storage/oqgraph/graphcore-graph.cc
0 → 100644
View file @
b965d031
/* Copyright (C) 2009-2011 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.III 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
======================================================================
*/
#include "graphcore-graph.h"
storage/oqgraph/graphcore-graph.h
View file @
b965d031
...
@@ -27,22 +27,142 @@
...
@@ -27,22 +27,142 @@
#ifndef oq_graphcore_graph_h_
#ifndef oq_graphcore_graph_h_
#define oq_graphcore_graph_h_
#define oq_graphcore_graph_h_
typedef
adjacency_list
#include "oqgraph_shim.h"
<
vecS
,
#include <boost/graph/two_bit_color_map.hpp>
vecS
,
bidirectionalS
,
namespace
boost
VertexInfo
,
{
EdgeInfo
typedef
oqgraph3
::
graph
Graph
;
>
Graph
;
template
<
typename
IndexMap
=
identity_property_map
>
#define GRAPH_WEIGHTMAP(G) get(&EdgeInfo::weight, G)
struct
two_bit_judy_map
typedef
property_map
<
Graph
,
EdgeWeight
EdgeInfo
::*>::
type
weightmap_type
;
{
typedef
typename
property_traits
<
IndexMap
>::
key_type
key_type
;
#define GRAPH_INDEXMAP(G) get(vertex_index, G)
typedef
two_bit_color_type
value_type
;
typedef
property_map
<
Graph
,
vertex_index_t
>::
type
indexmap_type
;
typedef
void
reference
;
typedef
read_write_property_map_tag
category
;
#define GRAPH_IDMAP(G) get(&VertexInfo::id, G)
typedef
property_map
<
Graph
,
VertexID
VertexInfo
::*>::
type
idmap_type
;
open_query
::
judy_bitset
msb
;
open_query
::
judy_bitset
lsb
;
IndexMap
index
;
two_bit_judy_map
(
const
IndexMap
&
i
)
:
index
(
i
)
{
}
friend
two_bit_color_type
get
(
const
two_bit_judy_map
<
IndexMap
>&
pm
,
typename
property_traits
<
IndexMap
>::
key_type
key
)
{
typename
property_traits
<
IndexMap
>::
value_type
i
=
get
(
pm
.
index
,
key
);
return
two_bit_color_type
((
2
*
int
(
pm
.
msb
.
test
(
i
)))
|
int
(
pm
.
lsb
.
test
(
i
)));
}
friend
void
put
(
two_bit_judy_map
<
IndexMap
>&
pm
,
typename
property_traits
<
IndexMap
>::
key_type
key
,
two_bit_color_type
value
)
{
typename
property_traits
<
IndexMap
>::
value_type
i
=
get
(
pm
.
index
,
key
);
pm
.
msb
.
set
(
i
,
value
&
2
);
pm
.
lsb
.
set
(
i
,
value
&
1
);
}
};
template
<
typename
IndexMap
>
inline
two_bit_judy_map
<
IndexMap
>
make_two_bit_judy_map
(
const
IndexMap
&
index
)
{
return
two_bit_judy_map
<
IndexMap
>
(
index
);
}
template
<
typename
Type
>
struct
default_lazy_initializer
{
template
<
typename
Key
>
Type
operator
()(
const
Key
&
)
const
{
return
Type
();
}
};
template
<
typename
Type
>
struct
copy_initializer
{
copy_initializer
(
const
Type
&
value
)
:
_
(
value
)
{
}
template
<
typename
Key
>
const
Type
&
operator
()(
const
Key
&
)
const
{
return
_
;
}
const
Type
&
_
;
};
template
<
typename
Type
>
copy_initializer
<
Type
>
make_copy_initializer
(
const
Type
&
value
)
{
return
copy_initializer
<
Type
>
(
value
);
}
template
<
typename
Type
>
struct
value_initializer
{
value_initializer
(
const
Type
&
value
)
:
_
(
value
)
{
}
template
<
typename
Key
>
const
Type
&
operator
()(
const
Key
&
)
const
{
return
_
;
}
const
Type
_
;
};
template
<
typename
Type
>
value_initializer
<
Type
>
make_value_initializer
(
const
Type
&
value
)
{
return
value_initializer
<
Type
>
(
value
);
}
template
<
typename
Key
>
struct
identity_initializer
{
const
Key
&
operator
()(
const
Key
&
_
)
const
{
return
_
;
}
};
template
<
class
Container
,
class
Generator
>
struct
lazy_property_map
{
typedef
lazy_property_map
<
Container
,
Generator
>
self
;
typedef
typename
Container
::
key_type
key_type
;
typedef
typename
Container
::
value_type
::
second_type
value_type
;
typedef
value_type
&
reference
;
typedef
lvalue_property_map_tag
category
;
lazy_property_map
(
Container
&
m
,
Generator
g
=
Generator
())
:
_m
(
m
)
,
_g
(
g
)
{
}
reference
operator
[](
const
key_type
&
k
)
const
{
typename
Container
::
iterator
found
=
_m
.
find
(
k
);
if
(
_m
.
end
()
==
found
)
{
found
=
_m
.
insert
(
std
::
make_pair
(
k
,
_g
(
k
))).
first
;
}
return
found
->
second
;
}
void
set
(
const
key_type
&
k
,
const
value_type
&
v
)
{
_m
[
k
]
=
v
;
}
friend
reference
get
(
const
self
&
s
,
const
key_type
&
k
)
{
return
s
[
k
];
}
friend
void
put
(
self
&
s
,
const
key_type
&
k
,
const
value_type
&
v
)
{
s
.
set
(
k
,
v
);
}
Container
&
_m
;
Generator
_g
;
};
template
<
class
Container
,
class
Generator
>
lazy_property_map
<
Container
,
Generator
>
make_lazy_property_map
(
Container
&
c
,
Generator
g
)
{
return
lazy_property_map
<
Container
,
Generator
>
(
c
,
g
);
}
}
#endif
#endif
storage/oqgraph/graphcore-types.h
View file @
b965d031
...
@@ -26,6 +26,7 @@
...
@@ -26,6 +26,7 @@
#ifndef oq_graphcore_types_h_
#ifndef oq_graphcore_types_h_
#define oq_graphcore_types_h_
#define oq_graphcore_types_h_
namespace
open_query
namespace
open_query
{
{
...
@@ -33,4 +34,9 @@ namespace open_query
...
@@ -33,4 +34,9 @@ namespace open_query
typedef
double
EdgeWeight
;
typedef
double
EdgeWeight
;
}
}
class
Field
;
typedef
struct
st_table
TABLE
;
#endif
#endif
storage/oqgraph/graphcore.cc
View file @
b965d031
...
@@ -30,14 +30,13 @@
...
@@ -30,14 +30,13 @@
#include <boost/config.hpp>
#include <boost/config.hpp>
#include "graphcore-graph.h"
#include <set>
#include <set>
#include <stack>
#include <stack>
#include <boost/property_map/property_map.hpp>
#include <boost/property_map/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/breadth_first_search.hpp>
#include <boost/graph/dijkstra_shortest_paths.hpp>
#include <boost/graph/dijkstra_shortest_paths.hpp>
#include <boost/graph/iteration_macros.hpp>
#include <boost/graph/iteration_macros.hpp>
...
@@ -46,6 +45,8 @@
...
@@ -46,6 +45,8 @@
#include "graphcore.h"
#include "graphcore.h"
#include <boost/unordered_map.hpp>
using
namespace
open_query
;
using
namespace
open_query
;
using
namespace
boost
;
using
namespace
boost
;
...
@@ -53,46 +54,6 @@ static const row empty_row = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
...
@@ -53,46 +54,6 @@ static const row empty_row = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
namespace
open_query
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
>::
vertex_descriptor
Vertex
;
typedef
graph_traits
<
Graph
>::
edge_descriptor
Edge
;
typedef
graph_traits
<
Graph
>::
edge_descriptor
Edge
;
...
@@ -261,18 +222,15 @@ namespace open_query {
...
@@ -261,18 +222,15 @@ namespace open_query {
public:
public:
Graph
g
;
Graph
g
;
weightmap_type
weightmap
;
idmap_type
idmap
;
indexmap_type
indexmap
;
optional
<
Vertex
>
find_vertex
(
VertexID
id
)
const
;
optional
<
Vertex
>
find_vertex
(
VertexID
id
)
const
;
optional
<
Edge
>
find_edge
(
Vertex
,
Vertex
)
const
;
optional
<
Edge
>
find_edge
(
Vertex
,
Vertex
)
const
;
inline
oqgraph_share
()
throw
()
inline
oqgraph_share
(
:
g
(),
TABLE
*
table
,
weightmap
(
GRAPH_WEIGHTMAP
(
g
)),
Field
*
origid
,
idmap
(
GRAPH_IDMAP
(
g
)),
Field
*
destid
,
indexmap
(
GRAPH_INDEXMAP
(
g
))
Field
*
weight
)
throw
()
:
g
(
table
,
origid
,
destid
,
weight
)
{
}
{
}
inline
~
oqgraph_share
()
inline
~
oqgraph_share
()
{
}
{
}
...
@@ -360,13 +318,13 @@ namespace open_query {
...
@@ -360,13 +318,13 @@ namespace open_query {
}
}
};
};
template
<
typename
P
,
typename
D
>
struct
GRAPHCORE_INTERNAL
oqgraph_visit_dist
struct
GRAPHCORE_INTERNAL
oqgraph_visit_dist
:
public
base_visitor
<
oqgraph_visit_dist
>
:
public
base_visitor
<
oqgraph_visit_dist
<
P
,
D
>
>
{
{
typedef
on_finish_vertex
event_filter
;
typedef
on_finish_vertex
event_filter
;
oqgraph_visit_dist
(
std
::
vector
<
Vertex
>::
iterator
p
,
oqgraph_visit_dist
(
const
P
&
p
,
const
D
&
d
,
std
::
vector
<
EdgeWeight
>::
iterator
d
,
stack_cursor
*
cursor
)
stack_cursor
*
cursor
)
:
seq
(
0
),
m_cursor
(
*
cursor
),
m_p
(
p
),
m_d
(
d
)
:
seq
(
0
),
m_cursor
(
*
cursor
),
m_p
(
p
),
m_d
(
d
)
{
assert
(
cursor
);
}
{
assert
(
cursor
);
}
...
@@ -374,22 +332,28 @@ namespace open_query {
...
@@ -374,22 +332,28 @@ namespace open_query {
template
<
class
T
,
class
Graph
>
template
<
class
T
,
class
Graph
>
void
operator
()(
T
u
,
Graph
&
g
)
void
operator
()(
T
u
,
Graph
&
g
)
{
{
m_cursor
.
results
.
push
(
reference
(
++
seq
,
u
,
m_d
[
GRAPH_INDEXMAP
(
g
)[
u
]
]));
m_cursor
.
results
.
push
(
reference
(
++
seq
,
u
,
m_d
[
u
]));
}
}
private:
private:
int
seq
;
int
seq
;
stack_cursor
&
m_cursor
;
stack_cursor
&
m_cursor
;
std
::
vector
<
Vertex
>::
iterator
m_p
;
P
m_p
;
std
::
vector
<
EdgeWeight
>::
iterator
m_d
;
D
m_d
;
};
};
template
<
bool
record_weight
,
typename
goal_filter
>
template
<
typename
P
,
typename
D
>
oqgraph_visit_dist
<
P
,
D
>
make_oqgraph_visit_dist
(
const
P
&
p
,
const
D
&
d
,
stack_cursor
*
cursor
)
{
return
oqgraph_visit_dist
<
P
,
D
>
(
p
,
d
,
cursor
);
}
template
<
bool
record_weight
,
typename
goal_filter
,
typename
P
>
struct
GRAPHCORE_INTERNAL
oqgraph_goal
struct
GRAPHCORE_INTERNAL
oqgraph_goal
:
public
base_visitor
<
oqgraph_goal
<
record_weight
,
goal_filter
>
>
:
public
base_visitor
<
oqgraph_goal
<
record_weight
,
goal_filter
,
P
>
>
{
{
typedef
goal_filter
event_filter
;
typedef
goal_filter
event_filter
;
oqgraph_goal
(
Vertex
goal
,
std
::
vector
<
Vertex
>::
iterator
p
,
oqgraph_goal
(
const
Vertex
&
goal
,
const
P
&
p
,
stack_cursor
*
cursor
)
stack_cursor
*
cursor
)
:
m_goal
(
goal
),
m_cursor
(
*
cursor
),
m_p
(
p
)
:
m_goal
(
goal
),
m_cursor
(
*
cursor
),
m_p
(
p
)
{
assert
(
cursor
);
}
{
assert
(
cursor
);
}
...
@@ -400,17 +364,16 @@ namespace open_query {
...
@@ -400,17 +364,16 @@ namespace open_query {
if
(
u
==
m_goal
)
if
(
u
==
m_goal
)
{
{
int
seq
=
0
;
int
seq
=
0
;
indexmap_type
indexmap
=
GRAPH_INDEXMAP
(
g
);
for
(
Vertex
q
,
v
=
u
;;
v
=
q
,
seq
++
)
for
(
Vertex
q
,
v
=
u
;;
v
=
q
,
seq
++
)
if
((
q
=
m_p
[
indexmap
[
v
]
])
==
v
)
if
((
q
=
m_p
[
v
])
==
v
)
break
;
break
;
for
(
Vertex
v
=
u
;;
u
=
v
)
for
(
Vertex
v
=
u
;;
u
=
v
)
{
{
optional
<
Edge
>
edge
;
optional
<
Edge
>
edge
;
optional
<
EdgeWeight
>
weight
;
optional
<
EdgeWeight
>
weight
;
v
=
m_p
[
indexmap
[
u
]
];
v
=
m_p
[
u
];
if
(
record_weight
&&
u
!=
v
)
if
(
record_weight
&&
u
!=
v
)
{
{
typename
graph_traits
<
Graph
>::
out_edge_iterator
ei
,
ei_end
;
typename
graph_traits
<
Graph
>::
out_edge_iterator
ei
,
ei_end
;
...
@@ -419,7 +382,7 @@ namespace open_query {
...
@@ -419,7 +382,7 @@ namespace open_query {
if
(
target
(
*
ei
,
g
)
==
u
)
if
(
target
(
*
ei
,
g
)
==
u
)
{
{
edge
=
*
ei
;
edge
=
*
ei
;
weight
=
GRAPH_WEIGHTMAP
(
g
)[
*
ei
]
;
weight
=
get
(
boost
::
edge_weight
,
g
,
*
ei
)
;
break
;
break
;
}
}
}
}
...
@@ -437,8 +400,14 @@ namespace open_query {
...
@@ -437,8 +400,14 @@ namespace open_query {
private:
private:
Vertex
m_goal
;
Vertex
m_goal
;
stack_cursor
&
m_cursor
;
stack_cursor
&
m_cursor
;
std
::
vector
<
Vertex
>::
iterator
m_p
;
P
m_p
;
};
};
template
<
bool
record_weight
,
typename
goal_filter
,
typename
P
>
oqgraph_goal
<
record_weight
,
goal_filter
,
P
>
make_oqgraph_goal
(
const
Vertex
&
goal
,
const
P
&
p
,
stack_cursor
*
cursor
)
{
return
oqgraph_goal
<
record_weight
,
goal_filter
,
P
>
(
goal
,
p
,
cursor
);
}
}
}
namespace
open_query
namespace
open_query
...
@@ -468,9 +437,14 @@ namespace open_query
...
@@ -468,9 +437,14 @@ namespace open_query
return
new
(
std
::
nothrow
)
oqgraph
(
share
);
return
new
(
std
::
nothrow
)
oqgraph
(
share
);
}
}
oqgraph_share
*
oqgraph
::
create
()
throw
()
oqgraph_share
*
oqgraph
::
create
(
TABLE
*
table
,
Field
*
origid
,
Field
*
destid
,
Field
*
weight
)
throw
()
{
{
return
new
(
std
::
nothrow
)
oqgraph_share
();
return
new
(
std
::
nothrow
)
oqgraph_share
(
table
,
origid
,
destid
,
weight
);
}
}
optional
<
Edge
>
optional
<
Edge
>
...
@@ -479,14 +453,14 @@ namespace open_query
...
@@ -479,14 +453,14 @@ namespace open_query
if
(
in_degree
(
dest
,
g
)
>=
out_degree
(
orig
,
g
))
if
(
in_degree
(
dest
,
g
)
>=
out_degree
(
orig
,
g
))
{
{
graph_traits
<
Graph
>::
out_edge_iterator
ei
,
ei_end
;
graph_traits
<
Graph
>::
out_edge_iterator
ei
,
ei_end
;
boost
::
tuples
::
tie
(
ei
,
ei_end
)
=
out_edges
(
orig
,
g
);
tie
(
ei
,
ei_end
)
=
out_edges
(
orig
,
g
);
if
((
ei
=
find_if
(
ei
,
ei_end
,
target_equals
(
dest
,
g
)))
!=
ei_end
)
if
((
ei
=
find_if
(
ei
,
ei_end
,
target_equals
(
dest
,
g
)))
!=
ei_end
)
return
*
ei
;
return
*
ei
;
}
}
else
else
{
{
graph_traits
<
Graph
>::
in_edge_iterator
ei
,
ei_end
;
graph_traits
<
Graph
>::
in_edge_iterator
ei
,
ei_end
;
boost
::
tuples
::
tie
(
ei
,
ei_end
)
=
in_edges
(
dest
,
g
);
tie
(
ei
,
ei_end
)
=
in_edges
(
dest
,
g
);
if
((
ei
=
find_if
(
ei
,
ei_end
,
source_equals
(
orig
,
g
)))
!=
ei_end
)
if
((
ei
=
find_if
(
ei
,
ei_end
,
source_equals
(
orig
,
g
)))
!=
ei_end
)
return
*
ei
;
return
*
ei
;
}
}
...
@@ -496,9 +470,10 @@ namespace open_query
...
@@ -496,9 +470,10 @@ namespace open_query
optional
<
Vertex
>
optional
<
Vertex
>
oqgraph_share
::
find_vertex
(
VertexID
id
)
const
oqgraph_share
::
find_vertex
(
VertexID
id
)
const
{
{
return
boost
::
graph
::
find_vertex
(
id
,
g
);
return
::
boost
::
find_vertex
(
id
,
g
);
}
}
#if 0
int oqgraph::delete_all() throw()
int oqgraph::delete_all() throw()
{
{
share->g.clear();
share->g.clear();
...
@@ -598,8 +573,9 @@ namespace open_query
...
@@ -598,8 +573,9 @@ namespace open_query
optional<Vertex> orig= source(*edge, share->g),
optional<Vertex> orig= source(*edge, share->g),
dest= target(*edge, share->g);
dest= target(*edge, share->g);
bool
orig_neq
=
orig_id
?
share
->
idmap
[
*
orig
]
!=
*
orig_id
:
0
;
bool orig_neq= orig_id ? get(boost::vertex_index, share->g, *orig) != *orig_id : 0;
bool
dest_neq
=
dest_id
?
share
->
idmap
[
*
dest
]
!=
*
dest_id
:
0
;
bool dest_neq= dest_id ? get(boost::vertex_index, share->g, *dest) != *dest_id : 0;
if (orig_neq || dest_neq)
if (orig_neq || dest_neq)
{
{
optional<Edge> new_edge;
optional<Edge> new_edge;
...
@@ -675,7 +651,6 @@ namespace open_query
...
@@ -675,7 +651,6 @@ namespace open_query
return OK;
return OK;
}
}
int oqgraph::delete_edge(VertexID orig_id, VertexID dest_id) throw()
int oqgraph::delete_edge(VertexID orig_id, VertexID dest_id) throw()
{
{
optional<Vertex> orig, dest;
optional<Vertex> orig, dest;
...
@@ -694,6 +669,7 @@ namespace open_query
...
@@ -694,6 +669,7 @@ namespace open_query
remove_vertex(*dest, share->g);
remove_vertex(*dest, share->g);
return OK;
return OK;
}
}
#endif
int
oqgraph
::
search
(
int
*
latch
,
VertexID
*
orig_id
,
VertexID
*
dest_id
)
throw
()
int
oqgraph
::
search
(
int
*
latch
,
VertexID
*
orig_id
,
VertexID
*
dest_id
)
throw
()
...
@@ -731,7 +707,8 @@ namespace open_query
...
@@ -731,7 +707,8 @@ namespace open_query
{
{
Vertex
v
=
target
(
*
ei
,
share
->
g
);
Vertex
v
=
target
(
*
ei
,
share
->
g
);
static_cast
<
stack_cursor
*>
(
cursor
)
->
static_cast
<
stack_cursor
*>
(
cursor
)
->
results
.
push
(
reference
(
++
seq
,
v
,
*
ei
,
share
->
weightmap
[
*
ei
]));
results
.
push
(
reference
(
++
seq
,
v
,
*
ei
,
get
(
boost
::
edge_weight
,
share
->
g
,
*
ei
)));
}
}
}
}
/* fall through */
/* fall through */
...
@@ -745,7 +722,8 @@ namespace open_query
...
@@ -745,7 +722,8 @@ namespace open_query
{
{
Vertex
v
=
source
(
*
ei
,
share
->
g
);
Vertex
v
=
source
(
*
ei
,
share
->
g
);
static_cast
<
stack_cursor
*>
(
cursor
)
->
static_cast
<
stack_cursor
*>
(
cursor
)
->
results
.
push
(
reference
(
++
seq
,
v
,
*
ei
,
share
->
weightmap
[
*
ei
]));
results
.
push
(
reference
(
++
seq
,
v
,
*
ei
,
get
(
boost
::
edge_weight
,
share
->
g
,
*
ei
)));
}
}
}
}
break
;
break
;
...
@@ -757,27 +735,29 @@ namespace open_query
...
@@ -757,27 +735,29 @@ namespace open_query
case
DIJKSTRAS
|
HAVE_ORIG
|
HAVE_DEST
:
case
DIJKSTRAS
|
HAVE_ORIG
|
HAVE_DEST
:
if
((
cursor
=
new
(
std
::
nothrow
)
stack_cursor
(
share
))
&&
orig
&&
dest
)
if
((
cursor
=
new
(
std
::
nothrow
)
stack_cursor
(
share
))
&&
orig
&&
dest
)
{
{
std
::
vector
<
Vertex
>
p
(
num_vertices
(
share
->
g
));
boost
::
unordered_map
<
Vertex
,
Vertex
>
p
;
std
::
vector
<
EdgeWeight
>
d
(
num_vertices
(
share
->
g
));
boost
::
unordered_map
<
Vertex
,
EdgeWeight
>
d
;
oqgraph_goal
<
true
,
on_finish_vertex
>
p
[
*
orig
]
=
*
orig
;
vis
(
*
dest
,
p
.
begin
(),
static_cast
<
stack_cursor
*>
(
cursor
));
d
[
*
orig
]
=
EdgeWeight
();
p
[
share
->
indexmap
[
*
orig
]]
=
*
orig
;
try
try
{
{
dijkstra_shortest_paths
(
share
->
g
,
*
orig
,
dijkstra_shortest_paths_no_init
(
share
->
g
,
*
orig
,
weight_map
(
make_lazy_property_map
(
p
,
identity_initializer
<
Vertex
>
()),
share
->
weightmap
make_lazy_property_map
(
d
,
value_initializer
<
EdgeWeight
>
(
).
(
std
::
numeric_limits
<
EdgeWeight
>::
max
)())),
distance_map
(
get
(
edge_weight
,
share
->
g
),
make_iterator_property_map
(
d
.
begin
(),
share
->
indexmap
)
get
(
vertex_index
,
share
->
g
),
).
std
::
less
<
EdgeWeight
>
(),
predecessor_map
(
closed_plus
<
EdgeWeight
>
(),
make_iterator_property_map
(
p
.
begin
(),
share
->
indexmap
)
EdgeWeight
(),
).
make_dijkstra_visitor
(
visitor
(
make_oqgraph_goal
<
true
,
on_finish_vertex
>
(
make_dijkstra_visitor
(
vis
)
*
dest
,
boost
::
make_assoc_property_map
(
p
),
static_cast
<
stack_cursor
*>
(
cursor
)
)
)
);
),
make_two_bit_judy_map
(
get
(
vertex_index
,
share
->
g
)));
}
}
catch
(...)
catch
(...)
{
/* printf("found\n"); */
}
{
/* printf("found\n"); */
}
...
@@ -787,23 +767,25 @@ namespace open_query
...
@@ -787,23 +767,25 @@ namespace open_query
case
BREADTH_FIRST
|
HAVE_ORIG
|
HAVE_DEST
:
case
BREADTH_FIRST
|
HAVE_ORIG
|
HAVE_DEST
:
if
((
cursor
=
new
(
std
::
nothrow
)
stack_cursor
(
share
))
&&
orig
&&
dest
)
if
((
cursor
=
new
(
std
::
nothrow
)
stack_cursor
(
share
))
&&
orig
&&
dest
)
{
{
std
::
vector
<
Vertex
>
p
(
num_vertices
(
share
->
g
));
boost
::
unordered_map
<
Vertex
,
Vertex
>
p
;
oqgraph_goal
<
false
,
on_discover_vertex
>
boost
::
queue
<
Vertex
>
Q
;
vis
(
*
dest
,
p
.
begin
(),
static_cast
<
stack_cursor
*>
(
cursor
));
p
[
*
orig
]
=
*
orig
;
p
[
share
->
indexmap
[
*
orig
]]
=
*
orig
;
try
try
{
{
breadth_first_
search
(
share
->
g
,
*
orig
,
breadth_first_
visit
(
share
->
g
,
*
orig
,
Q
,
visitor
(
make_bfs_visitor
(
make_bfs_visitor
(
std
::
make_pair
(
std
::
make_pair
(
record_predecessors
(
record_predecessors
(
make_iterator_property_map
(
p
.
begin
(),
share
->
indexma
p
),
boost
::
make_assoc_property_map
(
p
),
on_tree_edge
()
on_tree_edge
()
),
),
vis
)
make_oqgraph_goal
<
false
,
on_discover_vertex
>
(
*
dest
,
boost
::
make_assoc_property_map
(
p
),
static_cast
<
stack_cursor
*>
(
cursor
)
)
)
)
)
);
),
make_two_bit_judy_map
(
get
(
vertex_index
,
share
->
g
)));
}
}
catch
(...)
catch
(...)
{
/* printf("found\n"); */
}
{
/* printf("found\n"); */
}
...
@@ -814,109 +796,121 @@ namespace open_query
...
@@ -814,109 +796,121 @@ namespace open_query
case
BREADTH_FIRST
|
HAVE_ORIG
:
case
BREADTH_FIRST
|
HAVE_ORIG
:
if
((
cursor
=
new
(
std
::
nothrow
)
stack_cursor
(
share
))
&&
(
orig
||
dest
))
if
((
cursor
=
new
(
std
::
nothrow
)
stack_cursor
(
share
))
&&
(
orig
||
dest
))
{
{
std
::
vector
<
Vertex
>
p
(
num_vertices
(
share
->
g
))
;
boost
::
unordered_map
<
Vertex
,
Vertex
>
p
;
std
::
vector
<
EdgeWeight
>
d
(
num_vertices
(
share
->
g
))
;
boost
::
unordered_map
<
Vertex
,
EdgeWeight
>
d
;
oqgraph_visit_dist
vis
(
p
.
begin
(),
d
.
begin
(),
boost
::
queue
<
Vertex
>
Q
;
static_cast
<
stack_cursor
*>
(
cursor
))
;
p
[
*
orig
]
=
*
orig
;
p
[
share
->
indexmap
[
*
orig
]]
=
*
orig
;
d
[
*
orig
]
=
EdgeWeight
()
;
switch
(
ALGORITHM
&
op
)
switch
(
ALGORITHM
&
op
)
{
{
case
DIJKSTRAS
:
case
DIJKSTRAS
:
dijkstra_shortest_paths
(
share
->
g
,
*
orig
,
dijkstra_shortest_paths_no_init
(
share
->
g
,
*
orig
,
weight_map
(
make_lazy_property_map
(
p
,
identity_initializer
<
Vertex
>
()),
share
->
weightmap
make_lazy_property_map
(
d
,
value_initializer
<
EdgeWeight
>
(
).
(
std
::
numeric_limits
<
EdgeWeight
>::
max
)())),
distance_map
(
get
(
edge_weight
,
share
->
g
),
make_iterator_property_map
(
d
.
begin
(),
share
->
indexmap
)
get
(
vertex_index
,
share
->
g
),
).
std
::
less
<
EdgeWeight
>
(),
predecessor_map
(
closed_plus
<
EdgeWeight
>
(),
make_iterator_property_map
(
p
.
begin
(),
share
->
indexmap
)
EdgeWeight
(),
).
make_dijkstra_visitor
(
visitor
(
make_oqgraph_visit_dist
(
make_dijkstra_visitor
(
vis
)
boost
::
make_assoc_property_map
(
p
),
d
,
static_cast
<
stack_cursor
*>
(
cursor
)
)
)
);
),
make_two_bit_judy_map
(
get
(
vertex_index
,
share
->
g
)));
break
;
break
;
case
BREADTH_FIRST
:
case
BREADTH_FIRST
:
breadth_first_
search
(
share
->
g
,
*
orig
,
breadth_first_
visit
(
share
->
g
,
*
orig
,
Q
,
visitor
(
make_bfs_visitor
(
make_bfs_visitor
(
std
::
make_pair
(
std
::
make_pair
(
record_predecessors
(
record_predecessors
(
make_iterator_property_map
(
p
.
begin
(),
boost
::
make_assoc_property_map
(
p
),
share
->
indexmap
),
on_tree_edge
()
on_tree_edge
()
),
),
std
::
make_pair
(
std
::
make_pair
(
record_distances
(
record_distances
(
make_iterator_property_map
(
d
.
begin
(),
boost
::
make_assoc_property_map
(
d
),
share
->
indexmap
),
on_tree_edge
()
on_tree_edge
()
),
),
vis
make_oqgraph_visit_dist
(
))
boost
::
make_assoc_property_map
(
p
),
boost
::
make_assoc_property_map
(
d
),
static_cast
<
stack_cursor
*>
(
cursor
)
)
))
))
);
),
make_two_bit_judy_map
(
get
(
vertex_index
,
share
->
g
)));
break
;
break
;
default:
default:
abort
();
abort
();
}
}
}
}
break
;
break
;
#if 0
case BREADTH_FIRST | HAVE_DEST:
case BREADTH_FIRST | HAVE_DEST:
case DIJKSTRAS | HAVE_DEST:
case DIJKSTRAS | HAVE_DEST:
if ((cursor= new (std::nothrow) stack_cursor(share)) && (orig || dest))
if ((cursor= new (std::nothrow) stack_cursor(share)) && (orig || dest))
{
{
std
::
vector
<
Vertex
>
p
(
num_vertices
(
share
->
g
));
boost::unordered_map<Vertex, Vertex> p;
std
::
vector
<
EdgeWeight
>
d
(
num_vertices
(
share
->
g
));
boost::unordered_map<Vertex, EdgeWeight> d;
oqgraph_visit_dist
vis
(
p
.
begin
(),
d
.
begin
(),
boost::queue<Vertex> Q;
static_cast
<
stack_cursor
*>
(
cursor
));
reverse_graph<Graph> r(share->g);
reverse_graph<Graph> r(share->g);
p
[
share
->
indexmap
[
*
dest
]]
=
*
dest
;
p[ *dest ]= *dest;
d[ *dest ] = EdgeWeight();
switch (ALGORITHM & op)
switch (ALGORITHM & op)
{
{
case DIJKSTRAS:
case DIJKSTRAS:
dijkstra_shortest_paths
(
r
.
m_g
,
*
dest
,
dijkstra_shortest_paths_no_init(share->g, *dest,
weight_map
(
make_lazy_property_map(p, identity_initializer<Vertex>()),
share
->
weightmap
make_lazy_property_map(d, value_initializer<EdgeWeight>(
).
(std::numeric_limits<EdgeWeight>::max)())),
distance_map
(
get(edge_weight, share->g),
make_iterator_property_map
(
d
.
begin
(),
share
->
indexmap
)
get(vertex_index, share->g),
).
std::less<EdgeWeight>(),
predecessor_map
(
closed_plus<EdgeWeight>(),
make_iterator_property_map
(
p
.
begin
(),
share
->
indexmap
)
EdgeWeight(),
).
make_dijkstra_visitor(
visitor
(
make_dijkstra_visitor(
make_dijkstra_visitor
(
vis
)
make_oqgraph_visit_dist(
boost::make_assoc_property_map(p),
boost::make_assoc_property_map(d),
static_cast<stack_cursor*>(cursor)
)
)
)
);
),
make_two_bit_judy_map(get(vertex_index, share->g)));
break;
break;
case BREADTH_FIRST:
case BREADTH_FIRST:
breadth_first_
search
(
r
,
*
dest
,
breadth_first_
visit(share->g, *dest, Q
,
visitor
(
make_bfs_visitor
(
make_bfs_visitor(
std::make_pair(
std::make_pair(
record_predecessors(
record_predecessors(
make_iterator_property_map
(
p
.
begin
(),
boost::make_assoc_property_map(p),
share
->
indexmap
),
on_tree_edge()
on_tree_edge()
),
),
std::make_pair(
std::make_pair(
record_distances(
record_distances(
make_iterator_property_map
(
d
.
begin
(),
boost::make_assoc_property_map(d),
share
->
indexmap
),
on_tree_edge()
on_tree_edge()
),
),
vis
make_oqgraph_visit_dist(
))
boost::make_assoc_property_map(p),
boost::make_assoc_property_map(d),
static_cast<stack_cursor*>(cursor)
)
))
))
);
),
make_two_bit_judy_map(get(vertex_index, share->g)));
break;
break;
default:
default:
abort();
abort();
}
}
}
}
break;
break;
#endif
default:
default:
break
;
break
;
}
}
...
@@ -1006,7 +1000,7 @@ int stack_cursor::fetch_row(const row &row_info, row &result,
...
@@ -1006,7 +1000,7 @@ int stack_cursor::fetch_row(const row &row_info, row &result,
if
((
result
.
seq_indicator
=
seq
=
last
.
sequence
()))
if
((
result
.
seq_indicator
=
seq
=
last
.
sequence
()))
result
.
seq
=
*
seq
;
result
.
seq
=
*
seq
;
if
((
result
.
link_indicator
=
v
=
last
.
vertex
()))
if
((
result
.
link_indicator
=
v
=
last
.
vertex
()))
result
.
link
=
share
->
idmap
[
*
v
]
;
result
.
link
=
get
(
boost
::
vertex_index
,
share
->
g
,
*
v
)
;
if
((
result
.
weight_indicator
=
w
=
last
.
weight
()))
if
((
result
.
weight_indicator
=
w
=
last
.
weight
()))
result
.
weight
=
*
w
;
result
.
weight
=
*
w
;
return
oqgraph
::
OK
;
return
oqgraph
::
OK
;
...
@@ -1040,7 +1034,7 @@ int vertices_cursor::fetch_row(const row &row_info, row &result,
...
@@ -1040,7 +1034,7 @@ int vertices_cursor::fetch_row(const row &row_info, row &result,
if
(
v
)
if
(
v
)
{
{
result
.
link_indicator
=
1
;
result
.
link_indicator
=
1
;
result
.
link
=
share
->
idmap
[
*
v
]
;
result
.
link
=
get
(
boost
::
vertex_index
,
share
->
g
,
*
v
)
;
#ifdef DISPLAY_VERTEX_INFO
#ifdef DISPLAY_VERTEX_INFO
result
.
seq_indicator
=
1
;
result
.
seq_indicator
=
1
;
if
((
result
.
seq
=
degree
(
*
v
,
share
->
g
)))
if
((
result
.
seq
=
degree
(
*
v
,
share
->
g
)))
...
@@ -1048,10 +1042,10 @@ int vertices_cursor::fetch_row(const row &row_info, row &result,
...
@@ -1048,10 +1042,10 @@ int vertices_cursor::fetch_row(const row &row_info, row &result,
EdgeWeight
weight
=
0
;
EdgeWeight
weight
=
0
;
graph_traits
<
Graph
>::
in_edge_iterator
iei
,
iei_end
;
graph_traits
<
Graph
>::
in_edge_iterator
iei
,
iei_end
;
for
(
tie
(
iei
,
iei_end
)
=
in_edges
(
*
v
,
share
->
g
);
iei
!=
iei_end
;
++
iei
)
for
(
tie
(
iei
,
iei_end
)
=
in_edges
(
*
v
,
share
->
g
);
iei
!=
iei_end
;
++
iei
)
weight
+=
share
->
weightmap
[
*
iei
]
;
weight
+=
get
(
boost
::
edge_weight
,
share
->
g
,
*
iei
)
;
graph_traits
<
Graph
>::
out_edge_iterator
oei
,
oei_end
;
graph_traits
<
Graph
>::
out_edge_iterator
oei
,
oei_end
;
for
(
tie
(
oei
,
oei_end
)
=
out_edges
(
*
v
,
share
->
g
);
oei
!=
oei_end
;
++
oei
)
for
(
tie
(
oei
,
oei_end
)
=
out_edges
(
*
v
,
share
->
g
);
oei
!=
oei_end
;
++
oei
)
weight
+=
share
->
weightmap
[
*
oei
]
;
weight
+=
get
(
boost
::
edge_weight
,
share
->
g
,
*
oei
)
;
result
.
weight_indicator
=
1
;
result
.
weight_indicator
=
1
;
result
.
weight
=
weight
/
result
.
seq
;
result
.
weight
=
weight
/
result
.
seq
;
}
}
...
@@ -1066,9 +1060,8 @@ int edges_cursor::fetch_row(const row &row_info, row &result)
...
@@ -1066,9 +1060,8 @@ int edges_cursor::fetch_row(const row &row_info, row &result)
{
{
edge_iterator
it
,
end
;
edge_iterator
it
,
end
;
reference
ref
;
reference
ref
;
size_t
count
=
position
;
tie
(
it
,
end
)
=
edges
(
share
->
g
);
for
(
boost
::
tuples
::
tie
(
it
,
end
)
=
edges
(
share
->
g
);
count
&&
it
!=
end
;
++
it
,
--
count
)
it
+=
position
;
;
if
(
it
!=
end
)
if
(
it
!=
end
)
ref
=
reference
(
position
+
1
,
*
it
);
ref
=
reference
(
position
+
1
,
*
it
);
if
(
int
res
=
fetch_row
(
row_info
,
result
,
ref
))
if
(
int
res
=
fetch_row
(
row_info
,
result
,
ref
))
...
@@ -1085,9 +1078,9 @@ int edges_cursor::fetch_row(const row &row_info, row &result,
...
@@ -1085,9 +1078,9 @@ int edges_cursor::fetch_row(const row &row_info, row &result,
{
{
result
=
row_info
;
result
=
row_info
;
result
.
orig_indicator
=
result
.
dest_indicator
=
result
.
weight_indicator
=
1
;
result
.
orig_indicator
=
result
.
dest_indicator
=
result
.
weight_indicator
=
1
;
result
.
orig
=
share
->
idmap
[
source
(
*
edge
,
share
->
g
)
]
;
result
.
orig
=
get
(
boost
::
vertex_index
,
share
->
g
,
source
(
*
edge
,
share
->
g
)
)
;
result
.
dest
=
share
->
idmap
[
target
(
*
edge
,
share
->
g
)
]
;
result
.
dest
=
get
(
boost
::
vertex_index
,
share
->
g
,
target
(
*
edge
,
share
->
g
)
)
;
result
.
weight
=
share
->
weightmap
[
*
edge
]
;
result
.
weight
=
get
(
boost
::
edge_weight
,
share
->
g
,
*
edge
)
;
return
oqgraph
::
OK
;
return
oqgraph
::
OK
;
}
}
return
oqgraph
::
NO_MORE_DATA
;
return
oqgraph
::
NO_MORE_DATA
;
...
...
storage/oqgraph/graphcore.h
View file @
b965d031
...
@@ -104,7 +104,7 @@ namespace open_query
...
@@ -104,7 +104,7 @@ namespace open_query
void
row_ref
(
void
*
)
throw
();
void
row_ref
(
void
*
)
throw
();
static
oqgraph
*
create
(
oqgraph_share
*
)
throw
();
static
oqgraph
*
create
(
oqgraph_share
*
)
throw
();
static
oqgraph_share
*
create
()
throw
();
static
oqgraph_share
*
create
(
TABLE
*
,
Field
*
,
Field
*
,
Field
*
)
throw
();
static
void
free
(
oqgraph
*
)
throw
();
static
void
free
(
oqgraph
*
)
throw
();
static
void
free
(
oqgraph_share
*
)
throw
();
static
void
free
(
oqgraph_share
*
)
throw
();
...
...
storage/oqgraph/ha_oqgraph.cc
View file @
b965d031
...
@@ -29,6 +29,8 @@
...
@@ -29,6 +29,8 @@
#endif
#endif
#ifdef HAVE_OQGRAPH
#ifdef HAVE_OQGRAPH
#include <stdarg.h>
#include <stdio.h>
#include <mysql_version.h>
#include <mysql_version.h>
#include "ha_oqgraph.h"
#include "ha_oqgraph.h"
...
@@ -46,19 +48,27 @@
...
@@ -46,19 +48,27 @@
using
namespace
open_query
;
using
namespace
open_query
;
struct
oqgraph_
info_s
t
struct
oqgraph_
table_option_struc
t
{
{
THR_LOCK
lock
;
char
*
table_name
;
oqgraph_share
*
graph
;
uint
use_count
;
char
*
origid
;
// name of the origin id column
uint
key_stat_version
;
char
*
destid
;
// name of the target id column
uint
records
;
char
*
weight
;
// name of the weight column (optional)
bool
dropped
;
};
char
name
[
FN_REFLEN
+
1
];
#define ha_table_option_struct oqgraph_table_option_struct
ha_create_table_option
oqgraph_table_option_list
[]
=
{
HA_TOPTION_STRING
(
"data_table"
,
table_name
),
HA_TOPTION_STRING
(
"origid"
,
origid
),
HA_TOPTION_STRING
(
"destid"
,
destid
),
HA_TOPTION_STRING
(
"weight"
,
weight
),
HA_TOPTION_END
};
};
static
const
char
oqgraph_description
[]
=
static
const
char
oqgraph_description
[]
=
"Open Query Graph Computation Engine
, stored in memory
"
"Open Query Graph Computation Engine "
"(http://openquery.com/graph)"
;
"(http://openquery.com/graph)"
;
#if MYSQL_VERSION_ID < 50100
#if MYSQL_VERSION_ID < 50100
...
@@ -96,27 +106,10 @@ statistic_increment(table->in_use->status_var.X, &LOCK_status)
...
@@ -96,27 +106,10 @@ statistic_increment(table->in_use->status_var.X, &LOCK_status)
#define STATISTIC_INCREMENT(X)
/* nothing */
#define STATISTIC_INCREMENT(X)
/* nothing */
#define MOVE(X) move_field_offset(X)
#define MOVE(X) move_field_offset(X)
#define RECORDS stats.records
#define RECORDS stats.records
#endif
static
HASH
oqgraph_open_tables
;
static
pthread_mutex_t
LOCK_oqgraph
;
static
bool
oqgraph_init_done
=
0
;
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
,
static
handler
*
oqgraph_create_handler
(
handlerton
*
hton
,
TABLE_SHARE
*
table
,
MEM_ROOT
*
mem_root
)
MEM_ROOT
*
mem_root
)
{
{
...
@@ -130,7 +123,6 @@ static bool oqgraph_init()
...
@@ -130,7 +123,6 @@ static bool oqgraph_init()
{
{
if
(
have_oqgraph
==
SHOW_OPTION_DISABLED
)
if
(
have_oqgraph
==
SHOW_OPTION_DISABLED
)
return
1
;
return
1
;
#endif
if
(
pthread_mutex_init
(
&
LOCK_oqgraph
,
MY_MUTEX_INIT_FAST
))
if
(
pthread_mutex_init
(
&
LOCK_oqgraph
,
MY_MUTEX_INIT_FAST
))
goto
error
;
goto
error
;
if
(
my_hash_init
(
&
oqgraph_open_tables
,
&
my_charset_bin
,
32
,
0
,
0
,
if
(
my_hash_init
(
&
oqgraph_open_tables
,
&
my_charset_bin
,
32
,
0
,
0
,
...
@@ -144,17 +136,11 @@ static bool oqgraph_init()
...
@@ -144,17 +136,11 @@ static bool oqgraph_init()
hton
->
db_type
=
DB_TYPE_AUTOASSIGN
;
hton
->
db_type
=
DB_TYPE_AUTOASSIGN
;
hton
->
create
=
oqgraph_create_handler
;
hton
->
create
=
oqgraph_create_handler
;
hton
->
flags
=
HTON_NO_FLAGS
;
hton
->
flags
=
HTON_NO_FLAGS
;
#endif
hton
->
table_options
=
oqgraph_table_option_list
;
oqgraph_init_done
=
TRUE
;
oqgraph_init_done
=
TRUE
;
return
0
;
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
*
)
static
int
oqgraph_fini
(
void
*
)
{
{
my_hash_free
(
&
oqgraph_open_tables
);
my_hash_free
(
&
oqgraph_open_tables
);
...
@@ -264,6 +250,9 @@ static int error_code(int res)
...
@@ -264,6 +250,9 @@ static int error_code(int res)
KEY (latch, origid, destid) USING HASH,
KEY (latch, origid, destid) USING HASH,
KEY (latch, destid, origid) USING HASH
KEY (latch, destid, origid) USING HASH
) ENGINE=OQGRAPH
) ENGINE=OQGRAPH
READ_TABLE=bar
ORIGID=src_id
DESTID=tgt_id
*/
*/
static
int
oqgraph_check_table_structure
(
TABLE
*
table_arg
)
static
int
oqgraph_check_table_structure
(
TABLE
*
table_arg
)
...
@@ -331,16 +320,15 @@ static int oqgraph_check_table_structure (TABLE *table_arg)
...
@@ -331,16 +320,15 @@ static int oqgraph_check_table_structure (TABLE *table_arg)
** OQGRAPH tables
** OQGRAPH tables
*****************************************************************************/
*****************************************************************************/
#if MYSQL_VERSION_ID >= 50100
ha_oqgraph
::
ha_oqgraph
(
handlerton
*
hton
,
TABLE_SHARE
*
table_arg
)
ha_oqgraph
::
ha_oqgraph
(
handlerton
*
hton
,
TABLE_SHARE
*
table_arg
)
:
handler
(
hton
,
table_arg
),
:
handler
(
hton
,
table_arg
)
#else
,
graph_share
(
0
)
ha_oqgraph
::
ha_oqgraph
(
TABLE
*
table_arg
)
,
graph
(
0
)
:
handler
(
&
oqgraph_hton
,
table_arg
),
,
error_message
(
""
,
0
,
&
my_charset_latin1
)
#endif
share
(
0
),
graph
(
0
),
records_changed
(
0
),
key_stat_version
(
0
)
{
}
{
}
ha_oqgraph
::~
ha_oqgraph
()
{
}
static
const
char
*
ha_oqgraph_exts
[]
=
static
const
char
*
ha_oqgraph_exts
[]
=
{
{
...
@@ -352,11 +340,7 @@ const char **ha_oqgraph::bas_ext() const
...
@@ -352,11 +340,7 @@ const char **ha_oqgraph::bas_ext() const
return
ha_oqgraph_exts
;
return
ha_oqgraph_exts
;
}
}
#if MYSQL_VERSION_ID >= 50100
ulonglong
ha_oqgraph
::
table_flags
()
const
ulonglong
ha_oqgraph
::
table_flags
()
const
#else
ulong
ha_oqgraph
::
table_flags
()
const
#endif
{
{
return
(
HA_NO_BLOBS
|
HA_NULL_IN_KEY
|
return
(
HA_NO_BLOBS
|
HA_NULL_IN_KEY
|
HA_REC_NOT_IN_SEQ
|
HA_CAN_INSERT_DELAYED
|
HA_REC_NOT_IN_SEQ
|
HA_CAN_INSERT_DELAYED
|
...
@@ -368,278 +352,251 @@ ulong ha_oqgraph::index_flags(uint inx, uint part, bool all_parts) const
...
@@ -368,278 +352,251 @@ ulong ha_oqgraph::index_flags(uint inx, uint part, bool all_parts) const
return
HA_ONLY_WHOLE_INDEX
|
HA_KEY_SCAN_NOT_ROR
;
return
HA_ONLY_WHOLE_INDEX
|
HA_KEY_SCAN_NOT_ROR
;
}
}
int
ha_oqgraph
::
open
(
const
char
*
name
,
int
mode
,
uint
test_if_locked
)
bool
ha_oqgraph
::
get_error_message
(
int
error
,
String
*
buf
)
{
{
pthread_mutex_lock
(
&
LOCK_oqgraph
);
if
(
error
<
0
)
if
((
share
=
get_share
(
name
,
table
)))
{
{
ref_length
=
oqgraph
::
sizeof_ref
;
buf
->
append
(
error_message
);
buf
->
c_ptr_safe
();
error_message
.
length
(
0
);
}
}
return
false
;
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
)
void
ha_oqgraph
::
print_error
(
const
char
*
fmt
,
...
)
{
{
pthread_mutex_lock
(
&
LOCK_oqgraph
);
va_list
ap
;
oqgraph
::
free
(
graph
);
graph
=
0
;
va_start
(
ap
,
fmt
);
int
res
=
free_share
(
share
);
error_message
.
reserve
(
256
);
pthread_mutex_unlock
(
&
LOCK_oqgraph
);
size_t
len
=
error_message
.
length
();
return
error_code
(
res
);
len
+=
vsnprintf
(
&
error_message
[
len
],
255
,
fmt
,
ap
);
error_message
.
length
(
len
);
va_end
(
ap
);
}
}
void
ha_oqgraph
::
update_key_stats
()
int
ha_oqgraph
::
open
(
const
char
*
name
,
int
mode
,
uint
test_if_locked
)
{
{
for
(
uint
i
=
0
;
i
<
table
->
s
->
keys
;
i
++
)
THD
*
thd
=
current_thd
;
{
oqgraph_table_option_struct
*
options
=
KEY
*
key
=
table
->
key_info
+
i
;
reinterpret_cast
<
oqgraph_table_option_struct
*>
(
table
->
s
->
option_struct
);
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
;
}
error_message
.
length
(
0
);
int
ha_oqgraph
::
write_row
(
byte
*
buf
)
const
char
*
p
=
strend
(
name
)
-
1
;
{
while
(
p
>
name
&&
*
p
!=
'\\'
&&
*
p
!=
'/'
)
int
res
=
oqgraph
::
MISC_FAIL
;
--
p
;
Field
**
const
field
=
table
->
field
;
STATISTIC_INCREMENT
(
ha_write_count
);
#if MYSQL_VERSION_ID >= 50100
init_tmp_table_share
(
my_bitmap_map
*
old_map
=
dbug_tmp_use_all_columns
(
table
,
table
->
read_set
);
thd
,
share
,
table
->
s
->
db
.
str
,
table
->
s
->
db
.
length
,
#endif
options
->
table_name
,
""
);
my_ptrdiff_t
ptrdiff
=
buf
-
table
->
record
[
0
];
if
(
ptrdiff
)
size_t
tlen
=
strlen
(
options
->
table_name
);
size_t
plen
=
(
int
)(
p
-
name
)
+
tlen
;
share
->
path
.
str
=
(
char
*
)
alloc_root
(
&
share
->
mem_root
,
plen
+
1
);
strmov
(
strnmov
(
share
->
path
.
str
,
name
,
(
int
)(
p
-
name
)
+
1
),
options
->
table_name
);
share
->
normalized_path
.
str
=
share
->
path
.
str
;
share
->
path
.
length
=
share
->
normalized_path
.
length
=
plen
;
origid
=
destid
=
weight
=
0
;
while
(
open_table_def
(
thd
,
share
,
0
))
{
{
field
[
1
]
->
MOVE
(
ptrdiff
);
if
(
thd
->
is_error
()
&&
thd
->
main_da
.
sql_errno
()
!=
ER_NO_SUCH_TABLE
)
field
[
2
]
->
MOVE
(
ptrdiff
);
{
field
[
3
]
->
MOVE
(
ptrdiff
);
free_table_share
(
share
);
return
thd
->
main_da
.
sql_errno
();
}
}
if
(
!
field
[
1
]
->
is_null
()
&&
!
field
[
2
]
->
is_null
(
))
if
(
ha_create_table_from_engine
(
thd
,
table
->
s
->
db
.
str
,
options
->
table_name
))
{
{
VertexID
orig_id
=
(
VertexID
)
field
[
1
]
->
val_int
();
free_table_share
(
share
);
VertexID
dest_id
=
(
VertexID
)
field
[
2
]
->
val_int
();
return
thd
->
main_da
.
sql_errno
();
EdgeWeight
weight
=
1
;
}
mysql_reset_errors
(
thd
,
1
);
if
(
!
field
[
3
]
->
is_null
())
thd
->
clear_error
();
weight
=
(
EdgeWeight
)
field
[
3
]
->
val_real
();
continue
;
}
if
(
!
(
res
=
graph
->
insert_edge
(
orig_id
,
dest_id
,
weight
,
replace_dups
))
)
if
(
int
err
=
share
->
error
)
{
{
++
records_changed
;
open_table_error
(
share
,
share
->
error
,
share
->
open_errno
,
share
->
errarg
);
share
->
records
++
;
free_table_share
(
share
);
}
return
err
;
if
(
res
==
oqgraph
::
DUPLICATE_EDGE
&&
ignore_dups
&&
!
insert_dups
)
res
=
oqgraph
::
OK
;
}
}
if
(
ptrdiff
)
if
(
share
->
is_view
)
{
{
field
[
1
]
->
MOVE
(
-
ptrdiff
);
open_table_error
(
share
,
1
,
EMFILE
,
0
);
field
[
2
]
->
MOVE
(
-
ptrdiff
);
free_table_share
(
share
);
field
[
3
]
->
MOVE
(
-
ptrdiff
);
print_error
(
"VIEWs are not supported for a backing store"
);
return
-
1
;
}
}
#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
)
if
(
int
err
=
open_table_from_share
(
thd
,
share
,
""
,
(
uint
)
(
HA_OPEN_KEYFILE
|
HA_OPEN_RNDFILE
|
HA_GET_INDEX
|
HA_TRY_READ_ONLY
),
READ_KEYINFO
|
COMPUTE_TYPES
|
EXTRA_RECORD
,
thd
->
open_options
,
edges
,
FALSE
))
{
{
/*
open_table_error
(
share
,
err
,
EMFILE
,
0
);
We can perform this safely since only one writer at the time is
free_table_share
(
share
);
allowed on the table.
return
-
1
;
*/
share
->
key_stat_version
++
;
}
}
return
error_code
(
res
);
edges
->
reginfo
.
lock_type
=
TL_READ
;
}
int
ha_oqgraph
::
update_row
(
const
byte
*
old
,
byte
*
buf
)
edges
->
tablenr
=
thd
->
current_tablenr
++
;
{
edges
->
status
=
STATUS_NO_RECORD
;
int
res
=
oqgraph
::
MISC_FAIL
;
edges
->
file
->
ha_start_of_new_statement
();
VertexID
orig_id
,
dest_id
;
edges
->
file
->
ft_handler
=
0
;
EdgeWeight
weight
=
1
;
edges
->
pos_in_table_list
=
0
;
Field
**
field
=
table
->
field
;
edges
->
clear_column_bitmaps
();
STATISTIC_INCREMENT
(
ha_update_count
);
bfill
(
table
->
record
[
0
],
table
->
s
->
null_bytes
,
255
);
bfill
(
table
->
record
[
1
],
table
->
s
->
null_bytes
,
255
);
#if MYSQL_VERSION_ID >= 50100
// We expect fields origid, destid and optionally weight
my_bitmap_map
*
old_map
=
dbug_tmp_use_all_columns
(
table
,
table
->
read_set
);
origid
=
destid
=
weight
=
0
;
#endif
my_ptrdiff_t
ptrdiff
=
buf
-
table
->
record
[
0
];
if
(
ptrdiff
)
if
(
!
edges
->
file
)
{
{
field
[
0
]
->
MOVE
(
ptrdiff
);
print_error
(
"Some error occurred opening table '%s'"
,
options
->
table_name
);
field
[
1
]
->
MOVE
(
ptrdiff
);
free_table_share
(
share
);
field
[
2
]
->
MOVE
(
ptrdiff
);
return
-
1
;
field
[
3
]
->
MOVE
(
ptrdiff
);
}
}
if
(
inited
==
INDEX
||
inited
==
RND
)
for
(
Field
**
field
=
edges
->
field
;
*
field
;
++
field
)
{
{
VertexID
*
origp
=
0
,
*
destp
=
0
;
if
(
strcmp
(
options
->
origid
,
(
*
field
)
->
field_name
))
EdgeWeight
*
weightp
=
0
;
continue
;
if
(
!
field
[
1
]
->
is_null
())
if
((
*
field
)
->
cmp_type
()
!=
INT_RESULT
||
*
(
origp
=
&
orig_id
)
=
(
VertexID
)
field
[
1
]
->
val_int
();
!
((
*
field
)
->
flags
&
NOT_NULL_FLAG
))
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
()
&&
print_error
(
"Column '%s.%s' is not a not-null integer type"
,
*
origp
==
(
VertexID
)
field
[
1
]
->
val_int
())
options
->
table_name
,
options
->
origid
);
origp
=
0
;
closefrm
(
edges
,
0
);
if
(
!
destp
==
field
[
2
]
->
is_null
()
&&
free_table_share
(
share
);
*
destp
==
(
VertexID
)
field
[
2
]
->
val_int
())
return
-
1
;
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
;
}
}
origid
=
*
field
;
field
[
0
]
->
MOVE
(
-
ptrdiff2
);
break
;
field
[
1
]
->
MOVE
(
-
ptrdiff2
);
field
[
2
]
->
MOVE
(
-
ptrdiff2
);
field
[
3
]
->
MOVE
(
-
ptrdiff2
);
}
}
if
(
ptrdiff
)
for
(
Field
**
field
=
edges
->
field
;
*
field
;
++
field
)
{
{
field
[
0
]
->
MOVE
(
-
ptrdiff
);
if
(
strcmp
(
options
->
destid
,
(
*
field
)
->
field_name
))
field
[
1
]
->
MOVE
(
-
ptrdiff
);
continue
;
field
[
2
]
->
MOVE
(
-
ptrdiff
);
if
((
*
field
)
->
type
()
!=
origid
->
type
()
||
field
[
3
]
->
MOVE
(
-
ptrdiff
);
!
((
*
field
)
->
flags
&
NOT_NULL_FLAG
))
}
#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
)
{
{
/*
print_error
(
"Column '%s.%s' is not a not-null integer type"
,
We can perform this safely since only one writer at the time is
options
->
table_name
,
options
->
destid
);
allowed on the table.
closefrm
(
edges
,
0
);
*/
free_table_share
(
share
);
share
->
key_stat_version
++
;
return
-
1
;
}
destid
=
*
field
;
break
;
}
}
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
)
for
(
Field
**
field
=
edges
->
field
;
options
->
weight
&&
*
field
;
++
field
)
{
{
if
((
res
=
graph
->
delete_edge
(
oqgraph
::
current_row
()))
==
oqgraph
::
OK
)
if
(
strcmp
(
options
->
weight
,
(
*
field
)
->
field_name
))
continue
;
if
((
*
field
)
->
result_type
()
!=
REAL_RESULT
||
!
((
*
field
)
->
flags
&
NOT_NULL_FLAG
))
{
{
++
records_changed
;
print_error
(
"Column '%s.%s' is not a not-null real type"
,
share
->
records
--
;
options
->
table_name
,
options
->
weight
);
closefrm
(
edges
,
0
);
free_table_share
(
share
);
return
-
1
;
}
}
weight
=
*
field
;
break
;
}
}
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
)
if
(
!
origid
||
!
destid
||
(
!
weight
&&
options
->
weight
)
)
{
{
field
[
0
]
->
MOVE
(
ptrdiff
);
print_error
(
"Data columns missing on table '%s'"
,
options
->
table_name
);
field
[
1
]
->
MOVE
(
ptrdiff
);
closefrm
(
edges
,
0
);
field
[
2
]
->
MOVE
(
ptrdiff
);
free_table_share
(
share
);
return
-
1
;
}
}
if
(
field
[
0
]
->
is_null
()
&&
!
field
[
1
]
->
is_null
()
&&
!
field
[
2
]
->
is_null
(
))
if
(
!
(
graph_share
=
oqgraph
::
create
(
edges
,
origid
,
destid
,
weight
)
))
{
{
VertexID
orig_id
=
(
VertexID
)
field
[
1
]
->
val_int
();
print_error
(
"Unable to create graph instance."
);
VertexID
dest_id
=
(
VertexID
)
field
[
2
]
->
val_int
();
closefrm
(
edges
,
0
);
free_table_share
(
share
);
return
-
1
;
}
ref_length
=
oqgraph
::
sizeof_ref
;
graph
=
oqgraph
::
create
(
graph_share
);
return
0
;
}
if
((
res
=
graph
->
delete_edge
(
orig_id
,
dest_id
))
==
oqgraph
::
OK
)
int
ha_oqgraph
::
close
(
void
)
{
oqgraph
::
free
(
graph
);
graph
=
0
;
oqgraph
::
free
(
graph_share
);
graph_share
=
0
;
if
(
share
)
{
{
++
records_changed
;
if
(
edges
->
file
)
share
->
records
--
;
closefrm
(
edges
,
0
)
;
}
free_table_share
(
share
);
}
}
return
0
;
}
if
(
ptrdiff
)
void
ha_oqgraph
::
update_key_stats
()
{
for
(
uint
i
=
0
;
i
<
table
->
s
->
keys
;
i
++
)
{
{
field
[
0
]
->
MOVE
(
-
ptrdiff
);
KEY
*
key
=
table
->
key_info
+
i
;
field
[
1
]
->
MOVE
(
-
ptrdiff
);
if
(
!
key
->
rec_per_key
)
field
[
2
]
->
MOVE
(
-
ptrdiff
);
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)
uint
no_records
=
2
;
key
->
rec_per_key
[
key
->
key_parts
-
1
]
=
no_records
;
}
}
#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
);
/* At the end of update_key_stats() we can proudly claim they are OK. */
//skey_stat_version= share->key_stat_version;
}
int
ha_oqgraph
::
write_row
(
byte
*
buf
)
{
return
ER_OPEN_AS_READONLY
;
}
int
ha_oqgraph
::
update_row
(
const
byte
*
old
,
byte
*
buf
)
{
return
ER_OPEN_AS_READONLY
;
}
int
ha_oqgraph
::
delete_row
(
const
byte
*
buf
)
{
return
ER_OPEN_AS_READONLY
;
}
}
int
ha_oqgraph
::
index_read
(
byte
*
buf
,
const
byte
*
key
,
uint
key_len
,
int
ha_oqgraph
::
index_read
(
byte
*
buf
,
const
byte
*
key
,
uint
key_len
,
...
@@ -677,9 +634,7 @@ int ha_oqgraph::index_read_idx(byte * buf, uint index, const byte * key,
...
@@ -677,9 +634,7 @@ int ha_oqgraph::index_read_idx(byte * buf, uint index, const byte * key,
bmove_align
(
buf
,
table
->
s
->
default_values
,
table
->
s
->
reclength
);
bmove_align
(
buf
,
table
->
s
->
default_values
,
table
->
s
->
reclength
);
key_restore
(
buf
,
(
byte
*
)
key
,
key_info
,
key_len
);
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
);
my_bitmap_map
*
old_map
=
dbug_tmp_use_all_columns
(
table
,
table
->
read_set
);
#endif
my_ptrdiff_t
ptrdiff
=
buf
-
table
->
record
[
0
];
my_ptrdiff_t
ptrdiff
=
buf
-
table
->
record
[
0
];
if
(
ptrdiff
)
if
(
ptrdiff
)
...
@@ -713,9 +668,7 @@ int ha_oqgraph::index_read_idx(byte * buf, uint index, const byte * key,
...
@@ -713,9 +668,7 @@ int ha_oqgraph::index_read_idx(byte * buf, uint index, const byte * key,
field
[
1
]
->
MOVE
(
-
ptrdiff
);
field
[
1
]
->
MOVE
(
-
ptrdiff
);
field
[
2
]
->
MOVE
(
-
ptrdiff
);
field
[
2
]
->
MOVE
(
-
ptrdiff
);
}
}
#if MYSQL_VERSION_ID >= 50100
dbug_tmp_restore_column_map
(
table
->
read_set
,
old_map
);
dbug_tmp_restore_column_map
(
table
->
read_set
,
old_map
);
#endif
res
=
graph
->
search
(
latchp
,
orig_idp
,
dest_idp
);
res
=
graph
->
search
(
latchp
,
orig_idp
,
dest_idp
);
...
@@ -731,9 +684,7 @@ int ha_oqgraph::fill_record(byte *record, const open_query::row &row)
...
@@ -731,9 +684,7 @@ int ha_oqgraph::fill_record(byte *record, const open_query::row &row)
bmove_align
(
record
,
table
->
s
->
default_values
,
table
->
s
->
reclength
);
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
);
my_bitmap_map
*
old_map
=
dbug_tmp_use_all_columns
(
table
,
table
->
write_set
);
#endif
my_ptrdiff_t
ptrdiff
=
record
-
table
->
record
[
0
];
my_ptrdiff_t
ptrdiff
=
record
-
table
->
record
[
0
];
if
(
ptrdiff
)
if
(
ptrdiff
)
...
@@ -792,15 +743,14 @@ int ha_oqgraph::fill_record(byte *record, const open_query::row &row)
...
@@ -792,15 +743,14 @@ int ha_oqgraph::fill_record(byte *record, const open_query::row &row)
field
[
4
]
->
MOVE
(
-
ptrdiff
);
field
[
4
]
->
MOVE
(
-
ptrdiff
);
field
[
5
]
->
MOVE
(
-
ptrdiff
);
field
[
5
]
->
MOVE
(
-
ptrdiff
);
}
}
#if MYSQL_VERSION_ID >= 50100
dbug_tmp_restore_column_map
(
table
->
write_set
,
old_map
);
dbug_tmp_restore_column_map
(
table
->
write_set
,
old_map
);
#endif
return
0
;
return
0
;
}
}
int
ha_oqgraph
::
rnd_init
(
bool
scan
)
int
ha_oqgraph
::
rnd_init
(
bool
scan
)
{
{
edges
->
prepare_for_position
();
return
error_code
(
graph
->
random
(
scan
));
return
error_code
(
graph
->
random
(
scan
));
}
}
...
@@ -838,75 +788,31 @@ int ha_oqgraph::cmp_ref(const byte *ref1, const byte *ref2)
...
@@ -838,75 +788,31 @@ int ha_oqgraph::cmp_ref(const byte *ref1, const byte *ref2)
int
ha_oqgraph
::
info
(
uint
flag
)
int
ha_oqgraph
::
info
(
uint
flag
)
{
{
RECORDS
=
graph
->
vertices_count
()
+
graph
->
edges_count
();
RECORDS
=
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
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
have to update the key statistics. Hoping that a table lock is now
in place.
in place.
*/
*/
if
(
key_stat_version
!=
share
->
key_stat_version
)
//
if (key_stat_version != share->key_stat_version)
update_key_stats
();
//
update_key_stats();
return
0
;
return
0
;
}
}
int
ha_oqgraph
::
extra
(
enum
ha_extra_function
operation
)
int
ha_oqgraph
::
extra
(
enum
ha_extra_function
operation
)
{
{
switch
(
operation
)
return
edges
->
file
->
extra
(
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
ha_oqgraph
::
delete_all_rows
()
{
{
int
res
;
return
ER_OPEN_AS_READONLY
;
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
)
int
ha_oqgraph
::
external_lock
(
THD
*
thd
,
int
lock_type
)
{
{
return
0
;
// No external locking
return
edges
->
file
->
ha_external_lock
(
thd
,
lock_type
);
}
}
...
@@ -914,10 +820,7 @@ THR_LOCK_DATA **ha_oqgraph::store_lock(THD *thd,
...
@@ -914,10 +820,7 @@ THR_LOCK_DATA **ha_oqgraph::store_lock(THD *thd,
THR_LOCK_DATA
**
to
,
THR_LOCK_DATA
**
to
,
enum
thr_lock_type
lock_type
)
enum
thr_lock_type
lock_type
)
{
{
if
(
lock_type
!=
TL_IGNORE
&&
lock
.
type
==
TL_UNLOCK
)
return
edges
->
file
->
store_lock
(
thd
,
to
,
lock_type
);
lock
.
type
=
lock_type
;
*
to
++=
&
lock
;
return
to
;
}
}
/*
/*
...
@@ -925,20 +828,12 @@ THR_LOCK_DATA **ha_oqgraph::store_lock(THD *thd,
...
@@ -925,20 +828,12 @@ THR_LOCK_DATA **ha_oqgraph::store_lock(THD *thd,
not when doing a CREATE on the table.
not when doing a CREATE on the table.
*/
*/
int
ha_oqgraph
::
delete_table
(
const
char
*
name
)
int
ha_oqgraph
::
delete_table
(
const
char
*
)
{
{
int
res
=
0
;
return
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
)
int
ha_oqgraph
::
rename_table
(
const
char
*
,
const
char
*
)
{
{
pthread_mutex_lock
(
&
LOCK_oqgraph
);
pthread_mutex_lock
(
&
LOCK_oqgraph
);
if
(
OQGRAPH_INFO
*
share
=
get_share
(
from
))
if
(
OQGRAPH_INFO
*
share
=
get_share
(
from
))
...
@@ -980,8 +875,9 @@ ha_rows ha_oqgraph::records_in_range(uint inx, key_range *min_key,
...
@@ -980,8 +875,9 @@ ha_rows ha_oqgraph::records_in_range(uint inx, key_range *min_key,
return
RECORDS
;
return
RECORDS
;
/* Assert that info() did run. We need current statistics here. */
/* Assert that info() did run. We need current statistics here. */
DBUG_ASSERT
(
key_stat_version
==
share
->
key_stat_version
);
//DBUG_ASSERT(key_stat_version == share->key_stat_version);
ha_rows
result
=
key
->
rec_per_key
[
key
->
key_parts
-
1
];
//ha_rows result= key->rec_per_key[key->key_parts-1];
ha_rows
result
=
10
;
return
result
;
return
result
;
}
}
...
@@ -990,24 +886,14 @@ ha_rows ha_oqgraph::records_in_range(uint inx, key_range *min_key,
...
@@ -990,24 +886,14 @@ ha_rows ha_oqgraph::records_in_range(uint inx, key_range *min_key,
int
ha_oqgraph
::
create
(
const
char
*
name
,
TABLE
*
table_arg
,
int
ha_oqgraph
::
create
(
const
char
*
name
,
TABLE
*
table_arg
,
HA_CREATE_INFO
*
create_info
)
HA_CREATE_INFO
*
create_info
)
{
{
int
res
=
-
1
;
oqgraph_table_option_struct
*
options
=
OQGRAPH_INFO
*
share
;
reinterpret_cast
<
oqgraph_table_option_struct
*>
(
table
->
s
->
option_struct
)
;
pthread_mutex_lock
(
&
LOCK_oqgraph
);
if
(
int
res
=
oqgraph_check_table_structure
(
table_arg
))
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
);
return
error_code
(
res
);
(
void
)(
options
);
return
0
;
}
}
...
@@ -1018,7 +904,6 @@ void ha_oqgraph::update_create_info(HA_CREATE_INFO *create_info)
...
@@ -1018,7 +904,6 @@ void ha_oqgraph::update_create_info(HA_CREATE_INFO *create_info)
// create_info->auto_increment_value= auto_increment_value;
// create_info->auto_increment_value= auto_increment_value;
}
}
#if MYSQL_VERSION_ID >= 50100
struct
st_mysql_storage_engine
oqgraph_storage_engine
=
struct
st_mysql_storage_engine
oqgraph_storage_engine
=
{
MYSQL_HANDLERTON_INTERFACE_VERSION
};
{
MYSQL_HANDLERTON_INTERFACE_VERSION
};
...
@@ -1032,7 +917,7 @@ maria_declare_plugin(oqgraph)
...
@@ -1032,7 +917,7 @@ maria_declare_plugin(oqgraph)
PLUGIN_LICENSE_GPL
,
PLUGIN_LICENSE_GPL
,
(
int
(
*
)(
void
*
))
oqgraph_init
,
/* Plugin Init */
(
int
(
*
)(
void
*
))
oqgraph_init
,
/* Plugin Init */
oqgraph_fini
,
/* Plugin Deinit */
oqgraph_fini
,
/* Plugin Deinit */
0x0
200
,
/* Version: 2
.0 */
0x0
300
,
/* Version: 3s
.0 */
NULL
,
/* status variables */
NULL
,
/* status variables */
NULL
,
/* system variables */
NULL
,
/* system variables */
"2.0"
,
"2.0"
,
...
...
storage/oqgraph/ha_oqgraph.h
View file @
b965d031
...
@@ -37,19 +37,21 @@ namespace open_query
...
@@ -37,19 +37,21 @@ namespace open_query
{
{
struct
row
;
struct
row
;
class
oqgraph
;
class
oqgraph
;
class
oqgraph_share
;
}
}
/* class for the the Open Query Graph handler */
/* class for the the Open Query Graph handler */
class
ha_oqgraph
:
public
handler
class
ha_oqgraph
:
public
handler
{
{
OQGRAPH_INFO
*
share
;
TABLE_SHARE
share
[
1
];
TABLE
edges
[
1
];
Field
*
origid
;
Field
*
destid
;
Field
*
weight
;
open_query
::
oqgraph_share
*
graph_share
;
open_query
::
oqgraph
*
graph
;
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
&
);
int
fill_record
(
byte
*
,
const
open_query
::
row
&
);
...
@@ -61,7 +63,7 @@ class ha_oqgraph: public handler
...
@@ -61,7 +63,7 @@ class ha_oqgraph: public handler
ha_oqgraph
(
TABLE
*
table
);
ha_oqgraph
(
TABLE
*
table
);
Table_flags
table_flags
()
const
;
Table_flags
table_flags
()
const
;
#endif
#endif
~
ha_oqgraph
()
{}
~
ha_oqgraph
()
;
const
char
*
table_type
()
const
const
char
*
table_type
()
const
{
{
return
"OQGRAPH"
;
return
"OQGRAPH"
;
...
@@ -107,6 +109,12 @@ class ha_oqgraph: public handler
...
@@ -107,6 +109,12 @@ class ha_oqgraph: public handler
THR_LOCK_DATA
**
store_lock
(
THD
*
thd
,
THR_LOCK_DATA
**
to
,
THR_LOCK_DATA
**
store_lock
(
THD
*
thd
,
THR_LOCK_DATA
**
to
,
enum
thr_lock_type
lock_type
);
enum
thr_lock_type
lock_type
);
int
cmp_ref
(
const
byte
*
ref1
,
const
byte
*
ref2
);
int
cmp_ref
(
const
byte
*
ref1
,
const
byte
*
ref2
);
bool
get_error_message
(
int
error
,
String
*
buf
);
void
print_error
(
const
char
*
fmt
,
...);
private:
private:
void
update_key_stats
();
void
update_key_stats
();
String
error_message
;
};
};
storage/oqgraph/oqgraph_judy.cc
0 → 100644
View file @
b965d031
/* Copyright (C) 2009-2011 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.III 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
======================================================================
*/
#include "oqgraph_judy.h"
#include <Judy.h>
void
open_query
::
judy_bitset
::
clear
()
{
int
rc
;
J1FA
(
rc
,
array
);
}
bool
open_query
::
judy_bitset
::
test
(
size_type
n
)
const
{
int
rc
;
J1T
(
rc
,
array
,
n
);
return
rc
==
1
;
}
open_query
::
judy_bitset
&
open_query
::
judy_bitset
::
setbit
(
size_type
n
)
{
int
rc
;
J1S
(
rc
,
array
,
n
);
return
*
this
;
}
open_query
::
judy_bitset
&
open_query
::
judy_bitset
::
reset
(
size_type
n
)
{
int
rc
;
J1U
(
rc
,
array
,
n
);
return
*
this
;
}
open_query
::
judy_bitset
&
open_query
::
judy_bitset
::
flip
(
size_type
n
)
{
int
rc
;
J1U
(
rc
,
array
,
n
);
if
(
!
rc
)
{
J1S
(
rc
,
array
,
n
);
}
return
*
this
;
}
open_query
::
judy_bitset
::
size_type
open_query
::
judy_bitset
::
num_blocks
()
const
{
Word_t
rc
;
J1MU
(
rc
,
array
);
return
rc
;
}
open_query
::
judy_bitset
::
size_type
open_query
::
judy_bitset
::
size
()
const
{
int
rc
;
Word_t
index
=
(
Word_t
)
-
1
;
J1L
(
rc
,
array
,
index
);
if
(
!
rc
)
return
index
;
else
return
npos
;
}
open_query
::
judy_bitset
::
size_type
open_query
::
judy_bitset
::
count
()
const
{
Word_t
rc
;
J1C
(
rc
,
array
,
0
,
-
1
);
return
rc
;
}
open_query
::
judy_bitset
&
open_query
::
judy_bitset
::
set
(
const
judy_bitset
&
src
)
{
if
(
!
src
.
empty
())
{
for
(
size_type
pos
=
src
.
find_first
();
pos
!=
npos
;
pos
=
src
.
find_next
(
pos
))
{
set
(
pos
);
}
}
return
*
this
;
}
open_query
::
judy_bitset
::
size_type
open_query
::
judy_bitset
::
find_first
()
const
{
int
rc
;
Word_t
index
=
0
;
J1F
(
rc
,
array
,
index
);
if
(
!
rc
)
return
index
;
else
return
npos
;
}
open_query
::
judy_bitset
::
size_type
open_query
::
judy_bitset
::
find_next
(
size_type
n
)
const
{
int
rc
;
Word_t
index
=
(
Word_t
)
n
;
J1N
(
rc
,
array
,
index
);
if
(
!
rc
)
return
index
;
else
return
npos
;
}
storage/oqgraph/oqgraph_judy.h
0 → 100644
View file @
b965d031
/* Copyright (C) 2009-2011 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.III 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
======================================================================
*/
#pragma once
#include <cstddef>
namespace
open_query
{
class
judy_bitset
{
public:
typedef
std
::
size_t
size_type
;
enum
{
npos
=
(
size_type
)
-
1
};
judy_bitset
()
:
array
(
0
)
{
}
judy_bitset
(
const
judy_bitset
&
src
)
:
array
(
0
)
{
set
(
src
);
}
~
judy_bitset
()
{
clear
();
}
judy_bitset
&
operator
=
(
const
judy_bitset
&
src
)
{
clear
();
return
set
(
src
);
}
void
clear
();
bool
empty
()
const
{
return
!
array
;
}
bool
none
()
const
{
return
npos
==
find_first
();
}
inline
judy_bitset
&
set
(
size_type
n
,
bool
val
=
true
)
{
if
(
!
val
)
return
reset
(
n
);
else
return
setbit
(
n
);
}
judy_bitset
&
set
(
const
judy_bitset
&
src
);
judy_bitset
&
reset
(
size_type
n
);
judy_bitset
&
flip
(
size_type
n
);
bool
test
(
size_type
)
const
;
size_type
count
()
const
;
size_type
size
()
const
;
size_type
num_blocks
()
const
;
class
reference
{
friend
class
judy_bitset
;
reference
(
judy_bitset
&
array
,
size_type
pos
)
:
j
(
array
)
,
n
(
pos
)
{
}
void
operator
&
();
// not defined
public:
reference
&
operator
=
(
bool
value
)
{
j
.
set
(
n
,
value
);
return
*
this
;
}
reference
&
operator
=
(
const
reference
&
ref
)
{
j
.
set
(
n
,
ref
);
return
*
this
;
}
reference
&
operator
|=
(
bool
value
)
{
if
(
value
)
j
.
set
(
n
);
return
*
this
;
}
reference
&
operator
&=
(
bool
value
)
{
if
(
!
value
)
j
.
reset
(
n
);
return
*
this
;
}
reference
&
operator
^=
(
bool
value
)
{
if
(
value
)
j
.
flip
(
n
);
return
*
this
;
}
reference
&
operator
-=
(
bool
value
)
{
if
(
value
)
j
.
reset
(
n
);
return
*
this
;
}
bool
operator
~
()
const
{
return
!
j
.
test
(
n
);
}
operator
bool
()
const
{
return
j
.
test
(
n
);
}
reference
&
flip
()
{
j
.
flip
(
n
);
return
*
this
;
}
private:
judy_bitset
&
j
;
size_type
n
;
};
reference
operator
[](
size_type
n
)
{
return
reference
(
*
this
,
n
);
}
bool
operator
[](
size_type
n
)
const
{
return
test
(
n
);
}
size_type
find_first
()
const
;
size_type
find_next
(
size_type
n
)
const
;
private:
mutable
void
*
array
;
judy_bitset
&
setbit
(
size_type
n
);
};
}
storage/oqgraph/oqgraph_shim.cc
0 → 100644
View file @
b965d031
/* Copyright (C) 2009-2011 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.III 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
======================================================================
*/
#include "oqgraph_shim.h"
bool
oqgraph3
::
edge_iterator
::
seek
()
{
if
(
!
_graph
->
_cursor
||
_graph
->
_rnd_pos
>
_offset
||
_graph
->
_cursor
!=
_graph
->
_rnd_cursor
.
operator
->
())
{
_graph
->
_rnd_pos
=
0
;
_graph
->
_rnd_cursor
=
new
cursor
(
_graph
);
if
(
_graph
->
_rnd_cursor
->
seek_to
(
boost
::
none
,
boost
::
none
))
_graph
->
_rnd_pos
=
size_t
(
-
1
);
}
while
(
_graph
->
_rnd_pos
<
_offset
)
{
if
(
_graph
->
_rnd_cursor
->
seek_next
())
{
_offset
=
size_t
(
-
1
);
return
true
;
}
_graph
->
_rnd_pos
++
;
}
return
false
;
}
oqgraph3
::
edge_iterator
::
value_type
oqgraph3
::
edge_iterator
::
operator
*
()
{
seek
();
return
*
_graph
->
_rnd_cursor
;
}
bool
oqgraph3
::
edge_iterator
::
operator
==
(
const
self
&
x
)
{
if
(
_offset
==
size_t
(
-
1
)
&&
x
.
_offset
!=
size_t
(
-
1
))
return
const_cast
<
edge_iterator
&>
(
x
).
seek
();
if
(
_offset
!=
size_t
(
-
1
)
&&
x
.
_offset
==
size_t
(
-
1
))
return
seek
();
return
_offset
==
x
.
_offset
;
}
bool
oqgraph3
::
edge_iterator
::
operator
!=
(
const
self
&
x
)
{
if
(
_offset
==
size_t
(
-
1
)
&&
x
.
_offset
!=
size_t
(
-
1
))
return
!
const_cast
<
edge_iterator
&>
(
x
).
seek
();
if
(
_offset
!=
size_t
(
-
1
)
&&
x
.
_offset
==
size_t
(
-
1
))
return
!
seek
();
return
_offset
!=
x
.
_offset
;
}
storage/oqgraph/oqgraph_shim.h
0 → 100644
View file @
b965d031
/* Copyright (C) 2009-2011 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.III 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
======================================================================
*/
#pragma once
#include "oqgraph_thunk.h"
#include "oqgraph_judy.h"
#define BOOST_NO_HASH 1
#define BOOST_NO_SLIST 1
#include <boost/graph/directed_graph.hpp>
#include <boost/graph/adjacency_iterator.hpp>
namespace
open_query
{
struct
OQGraphTraversalCategory
:
public
boost
::
bidirectional_graph_tag
,
public
boost
::
adjacency_graph_tag
,
public
boost
::
edge_list_graph_tag
{
};
}
namespace
oqgraph3
{
struct
traversal_category
:
public
boost
::
adjacency_graph_tag
,
public
boost
::
bidirectional_graph_tag
,
public
boost
::
edge_list_graph_tag
{
};
struct
edge_iterator
{
typedef
edge_iterator
self
;
typedef
edge_info
value_type
;
typedef
edge_info
&
reference
;
typedef
edge_info
pointer
;
typedef
std
::
ptrdiff_t
difference_type
;
typedef
std
::
input_iterator_tag
iterator_category
;
edge_iterator
()
{
}
edge_iterator
(
const
graph_ptr
&
graph
,
size_t
offset
=
0
)
:
_graph
(
graph
)
,
_offset
(
offset
)
{
}
edge_iterator
(
const
edge_iterator
&
pos
)
:
_graph
(
pos
.
_graph
)
,
_offset
(
pos
.
_offset
)
{
}
value_type
operator
*
();
self
&
operator
+=
(
size_t
n
)
{
_offset
+=
n
;
return
*
this
;
}
self
&
operator
++
()
{
++
_offset
;
return
*
this
;
}
self
operator
++
(
int
)
{
size_t
temp
=
_offset
++
;
return
edge_iterator
(
_graph
,
temp
);
}
bool
seek
();
bool
operator
==
(
const
self
&
x
);
bool
operator
!=
(
const
self
&
x
);
graph_ptr
_graph
;
size_t
_offset
;
};
struct
vertex_iterator
{
typedef
vertex_iterator
self
;
typedef
vertex_id
value_type
;
typedef
vertex_id
&
reference
;
typedef
vertex_id
pointer
;
typedef
std
::
ptrdiff_t
difference_type
;
typedef
std
::
input_iterator_tag
iterator_category
;
vertex_iterator
()
{
}
vertex_iterator
(
const
cursor_ptr
&
pos
)
:
_cursor
(
pos
.
operator
->
())
{
}
vertex_id
operator
*
()
const
{
edge_info
edge
(
*
_cursor
);
if
(
!
_seen
.
test
(
edge
.
origid
()))
return
edge
.
origid
();
else
return
edge
.
destid
();
}
self
&
operator
++
()
{
edge_info
edge
(
*
_cursor
);
if
(
!
_seen
.
test
(
edge
.
origid
()))
{
_seen
.
set
(
edge
.
origid
());
}
else
{
_seen
.
set
(
edge
.
destid
());
}
while
(
_seen
.
test
(
edge
.
origid
())
&&
_seen
.
test
(
edge
.
destid
()))
{
if
(
_cursor
->
seek_next
())
break
;
edge
=
_cursor
;
}
return
*
this
;
}
self
operator
++
(
int
)
{
cursor
*
t
(
new
cursor
(
*
_cursor
));
++
(
*
this
);
return
vertex_iterator
(
t
);
}
bool
operator
==
(
const
self
&
x
)
{
return
*
_cursor
==
*
x
.
_cursor
;
}
bool
operator
!=
(
const
self
&
x
)
{
return
*
_cursor
!=
*
x
.
_cursor
;
}
cursor_ptr
_cursor
;
open_query
::
judy_bitset
_seen
;
};
struct
out_edge_iterator
{
typedef
out_edge_iterator
self
;
typedef
edge_info
value_type
;
typedef
edge_info
&
reference
;
typedef
edge_info
pointer
;
typedef
std
::
ptrdiff_t
difference_type
;
typedef
std
::
input_iterator_tag
iterator_category
;
out_edge_iterator
()
{
}
out_edge_iterator
(
const
cursor_ptr
&
cursor
)
:
_cursor
(
cursor
)
{
}
value_type
operator
*
()
{
return
value_type
(
_cursor
);
}
self
&
operator
++
()
{
_cursor
->
seek_next
();
return
*
this
;
}
self
operator
++
(
int
)
{
cursor_ptr
t
(
new
cursor
(
*
_cursor
));
++
(
*
this
);
return
out_edge_iterator
(
t
);
}
bool
operator
==
(
const
self
&
x
)
{
return
_cursor
==
x
.
_cursor
;
}
bool
operator
!=
(
const
self
&
x
)
{
return
_cursor
!=
x
.
_cursor
;
}
cursor_ptr
_cursor
;
};
struct
in_edge_iterator
{
typedef
in_edge_iterator
self
;
typedef
edge_info
value_type
;
typedef
edge_info
&
reference
;
typedef
edge_info
pointer
;
typedef
std
::
ptrdiff_t
difference_type
;
typedef
std
::
input_iterator_tag
iterator_category
;
in_edge_iterator
()
{
}
in_edge_iterator
(
const
cursor_ptr
&
cursor
)
:
_cursor
(
cursor
)
{
}
value_type
operator
*
()
{
return
value_type
(
_cursor
);
}
self
&
operator
++
()
{
_cursor
->
seek_next
();
return
*
this
;
}
self
operator
++
(
int
)
{
cursor_ptr
t
(
new
cursor
(
*
_cursor
));
++
(
*
this
);
return
in_edge_iterator
(
t
);
}
bool
operator
==
(
const
self
&
x
)
{
return
_cursor
==
x
.
_cursor
;
}
bool
operator
!=
(
const
self
&
x
)
{
return
_cursor
!=
x
.
_cursor
;
}
cursor_ptr
_cursor
;
};
struct
vertex_index_property_map
{
typedef
vertex_id
value_type
;
typedef
value_type
reference
;
typedef
vertex_id
key_type
;
typedef
boost
::
readable_property_map_tag
category
;
vertex_index_property_map
(
const
graph
&
g
)
:
_g
(
g
)
{
}
const
graph
&
_g
;
friend
inline
reference
get
(
const
vertex_index_property_map
&
,
key_type
key
)
{
return
key
;
}
};
struct
edge_weight_property_map
{
typedef
weight_t
value_type
;
typedef
value_type
reference
;
typedef
edge_info
key_type
;
typedef
boost
::
readable_property_map_tag
category
;
edge_weight_property_map
(
const
graph
&
g
)
:
_g
(
g
)
{
}
const
graph
&
_g
;
};
struct
edge_index_property_map
{
typedef
cursor_ptr
value_type
;
typedef
cursor_ptr
reference
;
typedef
edge_info
key_type
;
typedef
boost
::
readable_property_map_tag
category
;
edge_index_property_map
(
const
graph
&
g
)
:
_g
(
g
)
{
}
const
graph
&
_g
;
};
}
namespace
boost
{
template
<
>
struct
graph_traits
<
oqgraph3
::
graph
>
{
typedef
oqgraph3
::
vertex_id
vertex_descriptor
;
typedef
oqgraph3
::
edge_info
edge_descriptor
;
typedef
boost
::
adjacency_iterator_generator
<
oqgraph3
::
graph
,
oqgraph3
::
vertex_id
,
oqgraph3
::
out_edge_iterator
>::
type
adjacency_iterator
;
typedef
oqgraph3
::
out_edge_iterator
out_edge_iterator
;
typedef
oqgraph3
::
in_edge_iterator
in_edge_iterator
;
typedef
oqgraph3
::
vertex_iterator
vertex_iterator
;
typedef
oqgraph3
::
edge_iterator
edge_iterator
;
typedef
boost
::
directed_tag
directed_category
;
typedef
boost
::
allow_parallel_edge_tag
edge_parallel_category
;
typedef
oqgraph3
::
traversal_category
traversal_category
;
typedef
oqgraph3
::
vertices_size_type
vertices_size_type
;
typedef
oqgraph3
::
edges_size_type
edges_size_type
;
typedef
oqgraph3
::
degree_size_type
degree_size_type
;
static
inline
oqgraph3
::
vertex_id
null_vertex
()
{
return
oqgraph3
::
vertex_id
(
-
1
);
}
};
template
<
>
struct
graph_traits
<
const
oqgraph3
::
graph
>
:
public
graph_traits
<
oqgraph3
::
graph
>
{
};
template
<
>
struct
graph_property_type
<
oqgraph3
::
graph
>
{
typedef
no_property
type
;
};
template
<
>
struct
vertex_property_type
<
oqgraph3
::
graph
>
{
typedef
no_property
type
;
};
template
<
>
struct
edge_property_type
<
oqgraph3
::
graph
>
{
typedef
no_property
type
;
};
#if BOOST_VERSION >= 104601
template
<
>
struct
graph_bundle_type
<
oqgraph3
::
graph
>
{
typedef
no_graph_bundle
type
;
};
template
<
>
struct
vertex_bundle_type
<
oqgraph3
::
graph
>
{
typedef
no_vertex_bundle
type
;
};
template
<
>
struct
edge_bundle_type
<
oqgraph3
::
graph
>
{
typedef
no_edge_bundle
type
;
};
#endif
inline
graph_traits
<
oqgraph3
::
graph
>::
vertex_descriptor
source
(
const
graph_traits
<
oqgraph3
::
graph
>::
edge_descriptor
&
e
,
const
oqgraph3
::
graph
&
)
{
return
e
.
origid
();
}
inline
graph_traits
<
oqgraph3
::
graph
>::
vertex_descriptor
target
(
const
graph_traits
<
oqgraph3
::
graph
>::
edge_descriptor
&
e
,
const
oqgraph3
::
graph
&
)
{
return
e
.
destid
();
}
inline
std
::
pair
<
graph_traits
<
oqgraph3
::
graph
>::
out_edge_iterator
,
graph_traits
<
oqgraph3
::
graph
>::
out_edge_iterator
>
out_edges
(
graph_traits
<
oqgraph3
::
graph
>::
vertex_descriptor
v
,
const
oqgraph3
::
graph
&
g
)
{
oqgraph3
::
cursor
*
end
=
new
oqgraph3
::
cursor
(
const_cast
<
oqgraph3
::
graph
*>
(
&
g
));
oqgraph3
::
cursor
*
start
=
new
oqgraph3
::
cursor
(
const_cast
<
oqgraph3
::
graph
*>
(
&
g
));
start
->
seek_to
(
v
,
boost
::
none
);
return
std
::
make_pair
(
graph_traits
<
oqgraph3
::
graph
>::
out_edge_iterator
(
start
),
graph_traits
<
oqgraph3
::
graph
>::
out_edge_iterator
(
end
));
}
inline
graph_traits
<
oqgraph3
::
graph
>::
degree_size_type
out_degree
(
graph_traits
<
oqgraph3
::
graph
>::
vertex_descriptor
v
,
const
oqgraph3
::
graph
&
g
)
{
std
::
size_t
count
=
0
;
for
(
std
::
pair
<
graph_traits
<
oqgraph3
::
graph
>::
out_edge_iterator
,
graph_traits
<
oqgraph3
::
graph
>::
out_edge_iterator
>
i
=
out_edges
(
v
,
g
);
i
.
first
!=
i
.
second
;
++
i
.
first
)
{
++
count
;
}
return
count
;
}
inline
std
::
pair
<
graph_traits
<
oqgraph3
::
graph
>::
in_edge_iterator
,
graph_traits
<
oqgraph3
::
graph
>::
in_edge_iterator
>
in_edges
(
graph_traits
<
oqgraph3
::
graph
>::
vertex_descriptor
v
,
const
oqgraph3
::
graph
&
g
)
{
oqgraph3
::
cursor
*
end
=
new
oqgraph3
::
cursor
(
const_cast
<
oqgraph3
::
graph
*>
(
&
g
));
oqgraph3
::
cursor
*
start
=
new
oqgraph3
::
cursor
(
const_cast
<
oqgraph3
::
graph
*>
(
&
g
));
start
->
seek_to
(
boost
::
none
,
v
);
return
std
::
make_pair
(
graph_traits
<
oqgraph3
::
graph
>::
in_edge_iterator
(
start
),
graph_traits
<
oqgraph3
::
graph
>::
in_edge_iterator
(
end
));
}
inline
graph_traits
<
oqgraph3
::
graph
>::
degree_size_type
in_degree
(
graph_traits
<
oqgraph3
::
graph
>::
vertex_descriptor
v
,
const
oqgraph3
::
graph
&
g
)
{
std
::
size_t
count
=
0
;
for
(
std
::
pair
<
graph_traits
<
oqgraph3
::
graph
>::
in_edge_iterator
,
graph_traits
<
oqgraph3
::
graph
>::
in_edge_iterator
>
it
=
in_edges
(
v
,
g
);
it
.
first
!=
it
.
second
;
++
it
.
first
)
{
++
count
;
}
return
count
;
}
// EdgeListGraph concepts
inline
std
::
pair
<
graph_traits
<
oqgraph3
::
graph
>::
edge_iterator
,
graph_traits
<
oqgraph3
::
graph
>::
edge_iterator
>
edges
(
const
oqgraph3
::
graph
&
g
)
{
std
::
size_t
end
=
std
::
size_t
(
-
1
);
std
::
size_t
start
=
end
;
if
(
g
.
num_edges
())
start
=
0
;
return
std
::
make_pair
(
graph_traits
<
oqgraph3
::
graph
>::
edge_iterator
(
const_cast
<
oqgraph3
::
graph
*>
(
&
g
),
start
),
graph_traits
<
oqgraph3
::
graph
>::
edge_iterator
(
const_cast
<
oqgraph3
::
graph
*>
(
&
g
),
end
));
}
inline
std
::
pair
<
graph_traits
<
oqgraph3
::
graph
>::
vertex_iterator
,
graph_traits
<
oqgraph3
::
graph
>::
vertex_iterator
>
vertices
(
const
oqgraph3
::
graph
&
g
)
{
oqgraph3
::
cursor
*
start
=
new
oqgraph3
::
cursor
(
const_cast
<
oqgraph3
::
graph
*>
(
&
g
));
start
->
seek_to
(
boost
::
none
,
boost
::
none
);
return
std
::
make_pair
(
graph_traits
<
oqgraph3
::
graph
>::
vertex_iterator
(
start
),
graph_traits
<
oqgraph3
::
graph
>::
vertex_iterator
(
new
oqgraph3
::
cursor
(
const_cast
<
oqgraph3
::
graph
*>
(
&
g
))));
}
inline
graph_traits
<
oqgraph3
::
graph
>::
vertices_size_type
num_vertices
(
const
oqgraph3
::
graph
&
g
)
{
std
::
size_t
count
=
0
;
for
(
std
::
pair
<
graph_traits
<
oqgraph3
::
graph
>::
vertex_iterator
,
graph_traits
<
oqgraph3
::
graph
>::
vertex_iterator
>
i
=
vertices
(
g
);
i
.
first
!=
i
.
second
;
++
i
.
first
)
{
++
count
;
}
return
count
;
}
template
<
>
struct
property_map
<
oqgraph3
::
graph
,
edge_weight_t
>
{
typedef
void
type
;
typedef
oqgraph3
::
edge_weight_property_map
const_type
;
};
template
<
>
struct
property_map
<
oqgraph3
::
graph
,
vertex_index_t
>
{
typedef
void
type
;
typedef
oqgraph3
::
vertex_index_property_map
const_type
;
};
template
<
>
struct
property_map
<
oqgraph3
::
graph
,
edge_index_t
>
{
typedef
void
type
;
typedef
oqgraph3
::
edge_index_property_map
const_type
;
};
inline
property_map
<
oqgraph3
::
graph
,
edge_weight_t
>::
const_type
::
reference
get
(
edge_weight_t
,
const
oqgraph3
::
graph
&
g
,
const
property_map
<
oqgraph3
::
graph
,
edge_weight_t
>::
const_type
::
key_type
&
key
)
{
return
key
.
weight
();
}
inline
property_map
<
oqgraph3
::
graph
,
edge_weight_t
>::
const_type
get
(
edge_weight_t
,
const
oqgraph3
::
graph
&
g
)
{
return
property_map
<
oqgraph3
::
graph
,
edge_weight_t
>::
const_type
(
g
);
}
inline
property_map
<
oqgraph3
::
graph
,
edge_weight_t
>::
const_type
::
reference
get
(
const
property_map
<
oqgraph3
::
graph
,
edge_weight_t
>::
const_type
&
p
,
const
property_map
<
oqgraph3
::
graph
,
edge_weight_t
>::
const_type
::
key_type
&
key
)
{
return
key
.
weight
();
}
inline
property_map
<
oqgraph3
::
graph
,
edge_index_t
>::
const_type
::
reference
get
(
edge_index_t
,
const
oqgraph3
::
graph
&
,
const
property_map
<
oqgraph3
::
graph
,
edge_index_t
>::
const_type
::
key_type
&
key
)
{
return
key
.
_cursor
;
}
inline
property_map
<
oqgraph3
::
graph
,
edge_index_t
>::
const_type
get
(
edge_index_t
,
const
oqgraph3
::
graph
&
g
)
{
return
property_map
<
oqgraph3
::
graph
,
edge_index_t
>::
const_type
(
g
);
}
inline
property_map
<
oqgraph3
::
graph
,
edge_index_t
>::
const_type
::
reference
get
(
const
property_map
<
oqgraph3
::
graph
,
edge_index_t
>::
const_type
&
,
const
property_map
<
oqgraph3
::
graph
,
edge_index_t
>::
const_type
::
key_type
&
key
)
{
return
key
.
_cursor
;
}
inline
property_map
<
oqgraph3
::
graph
,
vertex_index_t
>::
const_type
::
reference
get
(
vertex_index_t
,
const
oqgraph3
::
graph
&
,
const
property_map
<
oqgraph3
::
graph
,
vertex_index_t
>::
const_type
::
key_type
&
key
)
{
return
key
;
}
inline
property_map
<
oqgraph3
::
graph
,
vertex_index_t
>::
const_type
get
(
vertex_index_t
,
const
oqgraph3
::
graph
&
g
)
{
return
property_map
<
oqgraph3
::
graph
,
vertex_index_t
>::
const_type
(
g
);
}
inline
optional
<
graph_traits
<
oqgraph3
::
graph
>::
vertex_descriptor
>
find_vertex
(
oqgraph3
::
vertex_id
id
,
const
oqgraph3
::
graph
&
g
)
{
return
id
;
}
}
storage/oqgraph/oqgraph_thunk.cc
0 → 100644
View file @
b965d031
/* Copyright (C) 2009-2011 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.III 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
======================================================================
*/
#include "oqgraph_thunk.h"
#include <boost/tuple/tuple.hpp>
#define MYSQL_SERVER
#include "mysql_priv.h"
static
int
debugid
=
0
;
oqgraph3
::
vertex_id
oqgraph3
::
edge_info
::
origid
()
const
{
return
_cursor
->
get_origid
();
}
oqgraph3
::
vertex_id
oqgraph3
::
edge_info
::
destid
()
const
{
return
_cursor
->
get_destid
();
}
oqgraph3
::
weight_t
oqgraph3
::
edge_info
::
weight
()
const
{
return
_cursor
->
get_weight
();
}
bool
oqgraph3
::
cursor_ptr
::
operator
==
(
const
cursor_ptr
&
x
)
const
{
if
(
get
()
==
x
.
get
())
return
true
;
return
(
*
this
)
->
record_position
()
==
x
->
_position
;
}
bool
oqgraph3
::
cursor_ptr
::
operator
!=
(
const
cursor_ptr
&
x
)
const
{
if
(
get
()
==
x
.
get
())
return
false
;
return
(
*
this
)
->
record_position
()
!=
x
->
_position
;
}
oqgraph3
::
cursor
::
cursor
(
const
graph_ptr
&
graph
)
:
_ref_count
(
0
)
,
_graph
(
graph
)
,
_index
(
-
1
)
,
_parts
(
0
)
,
_key
()
,
_position
()
,
_debugid
(
++
debugid
)
{
}
oqgraph3
::
cursor
::
cursor
(
const
cursor
&
src
)
:
_ref_count
(
0
)
,
_graph
(
src
.
_graph
)
,
_index
(
src
.
_index
)
,
_parts
(
src
.
_parts
)
,
_key
(
src
.
_key
)
,
_position
(
src
.
record_position
())
,
_debugid
(
++
debugid
)
{
}
oqgraph3
::
cursor
::~
cursor
()
{
if
(
this
==
_graph
->
_cursor
)
{
if
(
_graph
->
_cursor
->
_index
>=
0
)
_graph
->
_table
->
file
->
ha_index_end
();
else
_graph
->
_table
->
file
->
ha_rnd_end
();
_graph
->
_cursor
=
0
;
_graph
->
_stale
=
false
;
}
}
const
std
::
string
&
oqgraph3
::
cursor
::
record_position
()
const
{
if
(
_graph
->
_stale
&&
_graph
->
_cursor
)
{
TABLE
&
table
=
*
_graph
->
_table
;
table
.
file
->
position
(
table
.
record
[
0
]);
_graph
->
_cursor
->
_position
.
assign
(
(
const
char
*
)
table
.
file
->
ref
,
table
.
file
->
ref_length
);
if
(
_graph
->
_cursor
->
_index
>=
0
)
{
key_copy
((
uchar
*
)
_graph
->
_cursor
->
_key
.
data
(),
table
.
record
[
0
],
table
.
s
->
key_info
+
_index
,
table
.
s
->
key_info
[
_index
].
key_length
,
true
);
}
_graph
->
_stale
=
false
;
}
return
_position
;
}
void
oqgraph3
::
cursor
::
clear_position
()
{
_position
.
clear
();
if
(
this
==
_graph
->
_cursor
)
{
_graph
->
_cursor
=
0
;
_graph
->
_stale
=
false
;
}
}
void
oqgraph3
::
cursor
::
save_position
()
{
record_position
();
if
(
this
==
_graph
->
_cursor
)
{
TABLE
&
table
=
*
_graph
->
_table
;
if
(
_graph
->
_cursor
->
_index
>=
0
)
table
.
file
->
ha_index_end
();
else
table
.
file
->
ha_rnd_end
();
_graph
->
_cursor
=
0
;
_graph
->
_stale
=
false
;
}
}
int
oqgraph3
::
cursor
::
restore_position
()
{
TABLE
&
table
=
*
_graph
->
_table
;
if
(
!
_position
.
size
())
return
ENOENT
;
if
(
this
==
_graph
->
_cursor
)
return
0
;
if
(
_graph
->
_cursor
)
_graph
->
_cursor
->
save_position
();
if
(
_origid
||
_destid
)
{
if
(
int
rc
=
table
.
file
->
ha_index_init
(
_index
,
1
))
return
rc
;
restore_record
(
&
table
,
s
->
default_values
);
if
(
_origid
)
{
bitmap_set_bit
(
table
.
write_set
,
_graph
->
_source
->
field_index
);
_graph
->
_source
->
store
(
*
_origid
,
1
);
bitmap_clear_bit
(
table
.
write_set
,
_graph
->
_source
->
field_index
);
}
if
(
_destid
)
{
bitmap_set_bit
(
table
.
write_set
,
_graph
->
_target
->
field_index
);
_graph
->
_target
->
store
(
*
_destid
,
1
);
bitmap_clear_bit
(
table
.
write_set
,
_graph
->
_target
->
field_index
);
}
if
(
int
rc
=
table
.
file
->
ha_index_init
(
_index
,
1
))
return
rc
;
if
(
int
rc
=
table
.
file
->
ha_index_read_map
(
table
.
record
[
0
],
(
const
uchar
*
)
_key
.
data
(),
(
key_part_map
)(
1
<<
_parts
)
-
1
,
table
.
s
->
key_info
[
_index
].
key_parts
==
_parts
?
HA_READ_KEY_EXACT
:
HA_READ_KEY_OR_NEXT
))
{
table
.
file
->
ha_index_end
();
return
rc
;
}
update_virtual_fields
(
table
.
in_use
,
&
table
);
table
.
file
->
position
(
table
.
record
[
0
]);
while
(
memcmp
(
table
.
file
->
ref
,
_position
.
data
(),
table
.
file
->
ref_length
))
{
if
(
int
rc
=
table
.
file
->
ha_index_next
(
table
.
record
[
0
]))
{
table
.
file
->
ha_index_end
();
return
rc
;
}
update_virtual_fields
(
table
.
in_use
,
&
table
);
if
((
_origid
&&
vertex_id
(
_graph
->
_source
->
val_int
())
!=
*
_origid
)
||
(
_destid
&&
vertex_id
(
_graph
->
_target
->
val_int
())
!=
*
_destid
))
{
table
.
file
->
ha_index_end
();
return
ENOENT
;
}
table
.
file
->
position
(
table
.
record
[
0
]);
}
update_virtual_fields
(
table
.
in_use
,
&
table
);
}
else
{
if
(
int
rc
=
table
.
file
->
ha_rnd_init
(
1
))
return
rc
;
if
(
int
rc
=
table
.
file
->
ha_rnd_pos
(
table
.
record
[
0
],
(
uchar
*
)
_position
.
data
()))
{
table
.
file
->
ha_rnd_end
();
return
rc
;
}
update_virtual_fields
(
table
.
in_use
,
&
table
);
}
_graph
->
_cursor
=
this
;
_graph
->
_stale
=
false
;
return
0
;
}
oqgraph3
::
vertex_id
oqgraph3
::
cursor
::
get_origid
()
{
if
(
_origid
)
return
*
_origid
;
if
(
this
!=
_graph
->
_cursor
)
{
if
(
restore_position
())
return
-
1
;
}
return
static_cast
<
vertex_id
>
(
_graph
->
_source
->
val_int
());
}
oqgraph3
::
vertex_id
oqgraph3
::
cursor
::
get_destid
()
{
if
(
_destid
)
return
*
_destid
;
if
(
this
!=
_graph
->
_cursor
)
{
if
(
restore_position
())
return
-
1
;
}
return
static_cast
<
vertex_id
>
(
_graph
->
_target
->
val_int
());
}
oqgraph3
::
weight_t
oqgraph3
::
cursor
::
get_weight
()
{
if
(
!
_graph
->
_weight
)
return
1.0
;
if
(
this
!=
_graph
->
_cursor
)
{
if
(
restore_position
())
return
-
1
;
}
return
static_cast
<
vertex_id
>
(
_graph
->
_weight
->
val_int
());
}
int
oqgraph3
::
cursor
::
seek_next
()
{
if
(
this
!=
_graph
->
_cursor
)
{
if
(
int
rc
=
restore_position
())
return
rc
;
}
TABLE
&
table
=
*
_graph
->
_table
;
if
(
_index
<
0
)
{
if
(
int
rc
=
table
.
file
->
ha_rnd_next
(
table
.
record
[
0
]))
{
table
.
file
->
ha_rnd_end
();
return
clear_position
(
rc
);
}
return
0
;
}
if
(
int
rc
=
table
.
file
->
ha_index_next
(
table
.
record
[
0
]))
{
table
.
file
->
ha_index_end
();
return
clear_position
(
rc
);
}
update_virtual_fields
(
table
.
in_use
,
&
table
);
_graph
->
_stale
=
true
;
if
((
_origid
&&
vertex_id
(
_graph
->
_source
->
val_int
())
!=
*
_origid
)
||
(
_destid
&&
vertex_id
(
_graph
->
_target
->
val_int
())
!=
*
_destid
))
{
table
.
file
->
ha_index_end
();
return
clear_position
(
ENOENT
);
}
return
0
;
}
int
oqgraph3
::
cursor
::
seek_prev
()
{
if
(
this
!=
_graph
->
_cursor
)
{
if
(
int
rc
=
restore_position
())
return
rc
;
}
TABLE
&
table
=
*
_graph
->
_table
;
if
(
_index
<
0
)
{
return
-
1
;
// not supported
}
if
(
int
rc
=
table
.
file
->
ha_index_prev
(
table
.
record
[
0
]))
{
table
.
file
->
ha_index_end
();
return
clear_position
(
rc
);
}
update_virtual_fields
(
table
.
in_use
,
&
table
);
_graph
->
_stale
=
true
;
if
((
_origid
&&
vertex_id
(
_graph
->
_source
->
val_int
())
!=
*
_origid
)
||
(
_destid
&&
vertex_id
(
_graph
->
_target
->
val_int
())
!=
*
_destid
))
{
table
.
file
->
ha_index_end
();
return
clear_position
(
ENOENT
);
}
return
0
;
}
int
oqgraph3
::
cursor
::
seek_to
(
boost
::
optional
<
vertex_id
>
origid
,
boost
::
optional
<
vertex_id
>
destid
)
{
if
(
_graph
->
_cursor
&&
this
!=
_graph
->
_cursor
)
_graph
->
_cursor
->
save_position
();
TABLE
&
table
=
*
_graph
->
_table
;
_index
=
-
1
;
_origid
=
origid
;
_destid
=
destid
;
if
(
origid
||
destid
)
{
Field
*
source
=
_graph
->
_source
;
Field
*
target
=
_graph
->
_target
;
uint
source_fieldpos
=
_graph
->
_source
->
offset
(
table
.
record
[
0
]);
uint
target_fieldpos
=
_graph
->
_target
->
offset
(
table
.
record
[
0
]);
if
(
!
destid
)
{
int
i
=
0
;
for
(
::
KEY
*
key_info
=
table
.
s
->
key_info
,
*
key_end
=
key_info
+
table
.
s
->
keys
;
key_info
<
key_end
;
++
key_info
,
++
i
)
{
if
(
key_info
->
key_part
[
0
].
offset
!=
source_fieldpos
)
continue
;
if
(
table
.
file
->
ha_index_init
(
i
,
1
))
continue
;
restore_record
(
&
table
,
s
->
default_values
);
bitmap_set_bit
(
table
.
write_set
,
source
->
field_index
);
source
->
store
(
*
_origid
,
1
);
bitmap_clear_bit
(
table
.
write_set
,
source
->
field_index
);
uchar
*
buff
=
(
uchar
*
)
my_alloca
(
source
->
pack_length
());
source
->
get_key_image
(
buff
,
source
->
pack_length
(),
Field
::
itRAW
);
_key
.
clear
();
_key
.
append
((
char
*
)
buff
,
source
->
pack_length
());
_key
.
resize
(
key_info
->
key_length
,
'\0'
);
my_afree
(
buff
);
_parts
=
1
;
_index
=
i
;
break
;
}
}
else
if
(
!
origid
)
{
int
i
=
0
;
for
(
::
KEY
*
key_info
=
table
.
s
->
key_info
,
*
key_end
=
key_info
+
table
.
s
->
keys
;
key_info
<
key_end
;
++
key_info
,
++
i
)
{
if
(
key_info
->
key_part
[
0
].
offset
!=
target_fieldpos
)
continue
;
if
(
table
.
file
->
ha_index_init
(
i
,
1
))
continue
;
restore_record
(
&
table
,
s
->
default_values
);
bitmap_set_bit
(
table
.
write_set
,
target
->
field_index
);
target
->
store
(
*
_destid
,
1
);
bitmap_clear_bit
(
table
.
write_set
,
target
->
field_index
);
uchar
*
buff
=
(
uchar
*
)
my_alloca
(
target
->
pack_length
());
target
->
get_key_image
(
buff
,
target
->
pack_length
(),
Field
::
itRAW
);
_key
.
clear
();
_key
.
append
((
char
*
)
buff
,
target
->
pack_length
());
_key
.
resize
(
key_info
->
key_length
,
'\0'
);
my_afree
(
buff
);
_parts
=
1
;
_index
=
i
;
break
;
}
}
else
{
int
i
=
0
;
for
(
::
KEY
*
key_info
=
table
.
s
->
key_info
,
*
key_end
=
key_info
+
table
.
s
->
keys
;
key_info
<
key_end
;
++
key_info
,
++
i
)
{
if
(
key_info
->
key_parts
<
2
)
continue
;
if
(
!
((
key_info
->
key_part
[
0
].
offset
==
target_fieldpos
&&
key_info
->
key_part
[
1
].
offset
==
source_fieldpos
)
||
(
key_info
->
key_part
[
1
].
offset
==
target_fieldpos
&&
key_info
->
key_part
[
0
].
offset
==
source_fieldpos
)))
continue
;
if
(
table
.
file
->
ha_index_init
(
i
,
1
))
continue
;
restore_record
(
&
table
,
s
->
default_values
);
bitmap_set_bit
(
table
.
write_set
,
source
->
field_index
);
source
->
store
(
*
_origid
,
1
);
bitmap_clear_bit
(
table
.
write_set
,
source
->
field_index
);
bitmap_set_bit
(
table
.
write_set
,
target
->
field_index
);
target
->
store
(
*
_destid
,
1
);
bitmap_clear_bit
(
table
.
write_set
,
target
->
field_index
);
Field
*
first
=
key_info
->
key_part
[
0
].
offset
==
source_fieldpos
?
source
:
target
;
Field
*
second
=
key_info
->
key_part
[
0
].
offset
==
target_fieldpos
?
target
:
source
;
uchar
*
buff
=
(
uchar
*
)
my_alloca
(
source
->
pack_length
()
+
target
->
pack_length
());
first
->
get_key_image
(
buff
,
first
->
pack_length
(),
Field
::
itRAW
);
second
->
get_key_image
(
buff
+
first
->
pack_length
(),
second
->
pack_length
(),
Field
::
itRAW
);
_key
.
clear
();
_key
.
append
((
char
*
)
buff
,
source
->
pack_length
()
+
target
->
pack_length
());
_key
.
resize
(
key_info
->
key_length
,
'\0'
);
my_afree
(
buff
);
_parts
=
2
;
_index
=
i
;
break
;
}
}
if
(
_index
<
0
)
{
// no suitable index found
return
clear_position
(
ENXIO
);
}
if
(
int
rc
=
table
.
file
->
ha_index_read_map
(
table
.
record
[
0
],
(
uchar
*
)
_key
.
data
(),
(
key_part_map
)
((
1U
<<
_parts
)
-
1
),
table
.
s
->
key_info
[
_index
].
key_parts
==
_parts
?
HA_READ_KEY_EXACT
:
HA_READ_KEY_OR_NEXT
))
{
table
.
file
->
ha_index_end
();
return
clear_position
(
rc
);
}
update_virtual_fields
(
table
.
in_use
,
&
table
);
if
((
_origid
&&
vertex_id
(
_graph
->
_source
->
val_int
())
!=
*
_origid
)
||
(
_destid
&&
vertex_id
(
_graph
->
_target
->
val_int
())
!=
*
_destid
))
{
table
.
file
->
ha_index_end
();
return
clear_position
(
ENOENT
);
}
}
else
{
if
(
int
rc
=
table
.
file
->
ha_rnd_init
(
true
))
return
clear_position
(
rc
);
if
(
int
rc
=
table
.
file
->
ha_rnd_next
(
table
.
record
[
0
]))
{
table
.
file
->
ha_rnd_end
();
return
clear_position
(
rc
);
}
}
_graph
->
_cursor
=
this
;
_graph
->
_stale
=
true
;
return
0
;
}
bool
oqgraph3
::
cursor
::
operator
==
(
const
cursor
&
x
)
const
{
return
record_position
()
==
x
.
_position
;
}
bool
oqgraph3
::
cursor
::
operator
!=
(
const
cursor
&
x
)
const
{
return
record_position
()
!=
x
.
_position
;
}
oqgraph3
::
graph
::
graph
(
::
TABLE
*
table
,
::
Field
*
source
,
::
Field
*
target
,
::
Field
*
weight
)
:
_ref_count
(
0
)
,
_cursor
(
0
)
,
_stale
(
false
)
,
_table
(
table
)
,
_source
(
source
)
,
_target
(
target
)
,
_weight
(
weight
)
{
bitmap_set_bit
(
table
->
read_set
,
source
->
field_index
);
bitmap_set_bit
(
table
->
read_set
,
target
->
field_index
);
if
(
weight
)
bitmap_set_bit
(
table
->
read_set
,
weight
->
field_index
);
table
->
file
->
column_bitmaps_signal
();
}
oqgraph3
::
graph
::~
graph
()
{
}
oqgraph3
::
edges_size_type
oqgraph3
::
graph
::
num_edges
()
const
{
return
_table
->
file
->
stats
.
records
;
}
storage/oqgraph/oqgraph_thunk.h
0 → 100644
View file @
b965d031
/* Copyright (C) 2009-2011 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.III 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
======================================================================
*/
#pragma once
#include <list>
#include <queue>
#include <string>
#include <utility>
#include <boost/intrusive_ptr.hpp>
#include <boost/optional.hpp>
#include <boost/unordered_map.hpp>
#include <boost/unordered_set.hpp>
#include <boost/pending/queue.hpp>
#include <boost/ptr_container/ptr_deque.hpp>
#include "graphcore-types.h"
namespace
oqgraph3
{
typedef
open_query
::
VertexID
vertex_id
;
typedef
open_query
::
EdgeWeight
weight_t
;
typedef
size_t
vertices_size_type
;
typedef
size_t
edges_size_type
;
typedef
size_t
degree_size_type
;
struct
graph
;
struct
cursor
;
typedef
boost
::
intrusive_ptr
<
graph
>
graph_ptr
;
struct
cursor_ptr
:
public
boost
::
intrusive_ptr
<
cursor
>
{
cursor_ptr
()
:
boost
::
intrusive_ptr
<
cursor
>
()
{
}
cursor_ptr
(
cursor
*
pos
)
:
boost
::
intrusive_ptr
<
cursor
>
(
pos
)
{
}
operator
const
std
::
string
&
()
const
;
bool
operator
==
(
const
cursor_ptr
&
)
const
;
bool
operator
!=
(
const
cursor_ptr
&
)
const
;
};
struct
edge_info
{
cursor_ptr
_cursor
;
edge_info
()
:
_cursor
(
0
)
{
}
explicit
edge_info
(
const
cursor_ptr
&
pos
)
:
_cursor
(
pos
)
{
}
edge_info
&
operator
=
(
const
cursor_ptr
&
pos
)
{
_cursor
=
pos
;
return
*
this
;
}
vertex_id
origid
()
const
;
vertex_id
destid
()
const
;
weight_t
weight
()
const
;
bool
operator
==
(
const
edge_info
&
)
const
;
bool
operator
!=
(
const
edge_info
&
)
const
;
};
struct
cursor
{
mutable
int
_ref_count
;
graph_ptr
_graph
;
int
_index
;
unsigned
_parts
;
std
::
string
_key
;
std
::
string
_position
;
int
_debugid
;
boost
::
optional
<
vertex_id
>
_origid
;
boost
::
optional
<
vertex_id
>
_destid
;
cursor
(
const
graph_ptr
&
graph
);
cursor
(
const
cursor
&
src
);
~
cursor
();
operator
bool
()
const
{
return
!
_position
.
empty
();
}
operator
edge_info
()
const
{
return
edge_info
(
const_cast
<
cursor
*>
(
this
));
}
vertex_id
get_origid
();
vertex_id
get_destid
();
weight_t
get_weight
();
int
seek_to
(
boost
::
optional
<
vertex_id
>
origid
,
boost
::
optional
<
vertex_id
>
destid
);
int
seek_next
();
int
seek_prev
();
void
save_position
();
int
restore_position
();
const
std
::
string
&
record_position
()
const
;
void
clear_position
();
int
clear_position
(
int
rc
)
{
clear_position
();
return
rc
;
}
bool
operator
==
(
const
cursor
&
x
)
const
;
bool
operator
!=
(
const
cursor
&
x
)
const
;
friend
void
intrusive_ptr_add_ref
(
cursor
*
ptr
)
{
++
ptr
->
_ref_count
;
}
friend
void
intrusive_ptr_release
(
cursor
*
ptr
)
{
if
(
!--
(
ptr
->
_ref_count
))
delete
ptr
;
}
};
struct
graph
{
mutable
int
_ref_count
;
cursor
*
_cursor
;
bool
_stale
;
cursor_ptr
_rnd_cursor
;
size_t
_rnd_pos
;
::
TABLE
*
_table
;
::
Field
*
_source
;
::
Field
*
_target
;
::
Field
*
_weight
;
graph
(
::
TABLE
*
table
,
::
Field
*
source
,
::
Field
*
target
,
::
Field
*
weight
=
0
);
~
graph
();
edges_size_type
num_edges
()
const
;
friend
edges_size_type
num_edges
(
const
graph
&
g
)
{
return
g
.
num_edges
();
}
friend
void
intrusive_ptr_add_ref
(
graph
*
ptr
)
{
ptr
->
_ref_count
++
;
}
friend
void
intrusive_ptr_release
(
graph
*
ptr
)
{
ptr
->
_ref_count
--
;
}
};
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment