gqlite 0.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/ext/gqlite/extconf.rb +19 -0
- data/ext/gqlite/gqlite-amalgamate.cpp +6874 -0
- data/ext/gqlite/gqlite-c.h +90 -0
- data/ext/gqlite/gqlite.h +152 -0
- data/lib/gqlite.rb +57 -0
- metadata +65 -0
@@ -0,0 +1,90 @@
|
|
1
|
+
#pragma once
|
2
|
+
|
3
|
+
#include <stdbool.h>
|
4
|
+
|
5
|
+
#ifdef __cplusplus
|
6
|
+
extern "C" {
|
7
|
+
#endif
|
8
|
+
|
9
|
+
/**
|
10
|
+
* The context is needed for most call to the API, it currently is mainly used to handle error reporting.
|
11
|
+
* It also manage the memory for any string value returned by the API.
|
12
|
+
*/
|
13
|
+
typedef struct gqlite_api_context* gqlite_api_context_t;
|
14
|
+
|
15
|
+
/**
|
16
|
+
* Connection to the database.
|
17
|
+
*/
|
18
|
+
typedef struct gqlite_connection* gqlite_connection_t;
|
19
|
+
|
20
|
+
/**
|
21
|
+
* Represent a value (integer, double, string, map, array).
|
22
|
+
*/
|
23
|
+
typedef struct gqlite_value* gqlite_value_t;
|
24
|
+
|
25
|
+
/**
|
26
|
+
* Create a new context.
|
27
|
+
*/
|
28
|
+
gqlite_api_context_t gqlite_api_context_create();
|
29
|
+
/**
|
30
|
+
* Free context memory.
|
31
|
+
*/
|
32
|
+
void gqlite_api_context_destroy(gqlite_api_context_t);
|
33
|
+
/**
|
34
|
+
* Return the error message. The memory is owned by the context,
|
35
|
+
* it will be cleared when the context is freed or after the next function call.
|
36
|
+
*/
|
37
|
+
const char* gqlite_api_context_get_message(gqlite_api_context_t);
|
38
|
+
/**
|
39
|
+
* Return true if an error has occured in the last call.
|
40
|
+
*/
|
41
|
+
bool gqlite_api_context_has_error(gqlite_api_context_t);
|
42
|
+
/**
|
43
|
+
* Clear the error message.
|
44
|
+
*/
|
45
|
+
void gqlite_api_context_clear_error(gqlite_api_context_t);
|
46
|
+
|
47
|
+
/**
|
48
|
+
* Create a connection, using the sqlite backend. Expect as argument an handle to a sqlite connection.
|
49
|
+
*/
|
50
|
+
gqlite_connection_t gqlite_connection_create_from_sqlite(gqlite_api_context_t, void* _handle, gqlite_value_t _options);
|
51
|
+
|
52
|
+
/**
|
53
|
+
* Create a connection, using the sqlite backend. Using the database specified by the filename.
|
54
|
+
*/
|
55
|
+
gqlite_connection_t gqlite_connection_create_from_sqlite_file(gqlite_api_context_t, const char* _filename, gqlite_value_t _options);
|
56
|
+
|
57
|
+
/**
|
58
|
+
* Destroy the connection. Does not delete any connection handle passed as an argument.
|
59
|
+
*/
|
60
|
+
void gqlite_connection_destroy(gqlite_api_context_t, gqlite_connection_t);
|
61
|
+
|
62
|
+
/**
|
63
|
+
* Execute an OpenCypher query on the connection.
|
64
|
+
* Return a null value if an error has occured during execution.
|
65
|
+
*/
|
66
|
+
gqlite_value_t gqlite_connection_oc_query(gqlite_api_context_t, gqlite_connection_t, const char*, gqlite_value_t);
|
67
|
+
|
68
|
+
/**
|
69
|
+
* Create a value object to use in a query.
|
70
|
+
*/
|
71
|
+
gqlite_value_t gqlite_value_create(gqlite_api_context_t);
|
72
|
+
|
73
|
+
/**
|
74
|
+
* Destroy a value.
|
75
|
+
*/
|
76
|
+
void gqlite_value_destroy(gqlite_api_context_t, gqlite_value_t);
|
77
|
+
|
78
|
+
/**
|
79
|
+
* Convert value to json. The returned string is only valid until the next API call with the given context.
|
80
|
+
*/
|
81
|
+
const char* gqlite_value_to_json(gqlite_api_context_t, gqlite_value_t);
|
82
|
+
|
83
|
+
/**
|
84
|
+
* Check if the value is valid.
|
85
|
+
*/
|
86
|
+
bool gqlite_value_is_valid(gqlite_api_context_t, gqlite_value_t);
|
87
|
+
|
88
|
+
#ifdef __cplusplus
|
89
|
+
}
|
90
|
+
#endif
|
data/ext/gqlite/gqlite.h
ADDED
@@ -0,0 +1,152 @@
|
|
1
|
+
#pragma once
|
2
|
+
|
3
|
+
#include <exception>
|
4
|
+
#include <memory>
|
5
|
+
#include <string>
|
6
|
+
#include <unordered_map>
|
7
|
+
#include <vector>
|
8
|
+
|
9
|
+
namespace gqlite
|
10
|
+
{
|
11
|
+
class backend;
|
12
|
+
struct debug_stats;
|
13
|
+
/**
|
14
|
+
* Represents an error that occurs during the execution of a query.
|
15
|
+
*/
|
16
|
+
class exception : public std::exception
|
17
|
+
{
|
18
|
+
public:
|
19
|
+
exception(const std::string& _error) : m_error(_error), m_c_error(m_error.c_str()) {}
|
20
|
+
exception(const char* _error) : m_c_error(_error) {}
|
21
|
+
template<typename _T_, typename... _TOther_>
|
22
|
+
inline exception(const char* _format, const _T_& _value, const _TOther_&... _other);
|
23
|
+
template<typename _T_, typename... _TOther_>
|
24
|
+
inline exception(const std::string& _format, const _T_& _value, const _TOther_&... _other);
|
25
|
+
exception(const exception& _rhs);
|
26
|
+
exception& operator=(const exception& _rhs);
|
27
|
+
/**
|
28
|
+
* @return the error message
|
29
|
+
*/
|
30
|
+
const char* what() const throw() override
|
31
|
+
{
|
32
|
+
return m_c_error;
|
33
|
+
}
|
34
|
+
private:
|
35
|
+
std::string m_error;
|
36
|
+
const char* m_c_error;
|
37
|
+
};
|
38
|
+
/**
|
39
|
+
* Represent the value type.
|
40
|
+
*/
|
41
|
+
enum class value_type
|
42
|
+
{
|
43
|
+
invalid,
|
44
|
+
boolean,
|
45
|
+
integer,
|
46
|
+
number, ///< aka float
|
47
|
+
string,
|
48
|
+
map,
|
49
|
+
vector
|
50
|
+
};
|
51
|
+
class value;
|
52
|
+
using value_map = std::unordered_map<std::string, value>;
|
53
|
+
using value_vector = std::vector<value>;
|
54
|
+
/**
|
55
|
+
* Represent a value (boolean, integer, number, string, map or vector)
|
56
|
+
*/
|
57
|
+
class value
|
58
|
+
{
|
59
|
+
public:
|
60
|
+
value();
|
61
|
+
value(const value& _rhs);
|
62
|
+
value& operator=(const value& _rhs);
|
63
|
+
~value();
|
64
|
+
public:
|
65
|
+
value(int _v);
|
66
|
+
value(double _v);
|
67
|
+
value(const std::string& _v);
|
68
|
+
value(const value_map& _v);
|
69
|
+
/// not part of the public API
|
70
|
+
template<typename _T_>
|
71
|
+
value(const std::initializer_list<typename std::unordered_map<std::string, _T_>::value_type>& _v);
|
72
|
+
value(const value_vector& _v);
|
73
|
+
/// not part of the public API
|
74
|
+
template<typename _T_>
|
75
|
+
value(const std::vector<_T_>& _v);
|
76
|
+
bool operator==(const value& _rhs) const;
|
77
|
+
public:
|
78
|
+
/**
|
79
|
+
* @return the type hold by this value
|
80
|
+
*/
|
81
|
+
value_type get_type() const;
|
82
|
+
/**
|
83
|
+
* Attempt to return a bool. Throw an exception if not possible.
|
84
|
+
*/
|
85
|
+
bool to_bool() const;
|
86
|
+
/**
|
87
|
+
* Attempt to return an integer. Throw an exception if not possible.
|
88
|
+
*/
|
89
|
+
int to_integer() const;
|
90
|
+
/**
|
91
|
+
* Attempt to return a double. Throw an exception if not possible.
|
92
|
+
*/
|
93
|
+
double to_double() const;
|
94
|
+
/**
|
95
|
+
* Attempt to return a string. Throw an exception if not possible.
|
96
|
+
*/
|
97
|
+
std::string to_string() const;
|
98
|
+
/**
|
99
|
+
* Attempt to return a map. Throw an exception if not possible.
|
100
|
+
*/
|
101
|
+
value_map to_map() const;
|
102
|
+
/**
|
103
|
+
* Attempt to return a vector. Throw an exception if not possible.
|
104
|
+
*/
|
105
|
+
value_vector to_vector() const;
|
106
|
+
public:
|
107
|
+
/**
|
108
|
+
* Attempt to return a json string to represent a value.
|
109
|
+
*/
|
110
|
+
std::string to_json() const;
|
111
|
+
/**
|
112
|
+
* Construct a value from a json string. Throw an exception if not possible.
|
113
|
+
*/
|
114
|
+
static value from_json(const std::string& _json);
|
115
|
+
private:
|
116
|
+
struct data;
|
117
|
+
std::shared_ptr<data> d;
|
118
|
+
};
|
119
|
+
/**
|
120
|
+
* Main class for connecting to a gqlite database.
|
121
|
+
*/
|
122
|
+
class connection
|
123
|
+
{
|
124
|
+
connection(backend* _backend);
|
125
|
+
public:
|
126
|
+
connection();
|
127
|
+
connection(const connection& _rhs);
|
128
|
+
connection& operator=(const connection& _rhs);
|
129
|
+
~connection();
|
130
|
+
/**
|
131
|
+
* Create a sqlite connection from a \p _pointer to a valid sqlite handle.
|
132
|
+
*/
|
133
|
+
static connection create_from_sqlite(void* _pointer, const value& _options = value());
|
134
|
+
/**
|
135
|
+
* Create a sqlite connection from a file.
|
136
|
+
*/
|
137
|
+
static connection create_from_sqlite_file(const std::string& _filename, const value& _options = value());
|
138
|
+
/**
|
139
|
+
* @internal
|
140
|
+
* Part of the private API, what is returned by this function may change at any time.
|
141
|
+
*/
|
142
|
+
gqlite::value get_debug_stats() const;
|
143
|
+
public:
|
144
|
+
/**
|
145
|
+
* Execute a query.
|
146
|
+
*/
|
147
|
+
value execute_oc_query(const std::string& _string, const value_map& _variant = {});
|
148
|
+
private:
|
149
|
+
struct data;
|
150
|
+
std::shared_ptr<data> d;
|
151
|
+
};
|
152
|
+
}
|
data/lib/gqlite.rb
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'ffi'
|
2
|
+
require 'objspace'
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
module Gqlite
|
6
|
+
class Error < StandardError
|
7
|
+
end
|
8
|
+
module CApi
|
9
|
+
extend FFI::Library
|
10
|
+
ffi_lib 'gqlite'
|
11
|
+
attach_function :gqlite_api_context_create, [], :pointer
|
12
|
+
attach_function :gqlite_api_context_destroy, [:pointer], :void
|
13
|
+
attach_function :gqlite_api_context_clear_error, [:pointer], :void
|
14
|
+
attach_function :gqlite_api_context_has_error, [:pointer], :bool
|
15
|
+
attach_function :gqlite_api_context_get_message, [:pointer], :string
|
16
|
+
attach_function :gqlite_connection_create_from_sqlite_file, [:pointer, :string, :pointer], :pointer
|
17
|
+
attach_function :gqlite_connection_destroy, [:pointer, :pointer], :void
|
18
|
+
attach_function :gqlite_connection_oc_query, [:pointer, :pointer, :string, :pointer], :pointer
|
19
|
+
attach_function :gqlite_value_create, [:pointer], :pointer
|
20
|
+
attach_function :gqlite_value_destroy, [:pointer, :pointer], :void
|
21
|
+
attach_function :gqlite_value_to_json, [:pointer, :pointer], :string
|
22
|
+
attach_function :gqlite_value_is_valid, [:pointer, :pointer], :bool
|
23
|
+
ApiError = CApi.gqlite_api_context_create()
|
24
|
+
def CApi.call_function(fname, *args)
|
25
|
+
r = CApi.send fname, ApiError, *args
|
26
|
+
if CApi.gqlite_api_context_has_error(ApiError)
|
27
|
+
err = CApi.gqlite_api_context_get_message ApiError
|
28
|
+
CApi.gqlite_api_context_clear_error ApiError
|
29
|
+
raise Error.new err
|
30
|
+
end
|
31
|
+
return r
|
32
|
+
end
|
33
|
+
end
|
34
|
+
class Connection
|
35
|
+
attr_reader :dbhandle
|
36
|
+
def initialize(sqlite_filename: nil)
|
37
|
+
if sqlite_filename != nil
|
38
|
+
@dbhandle = CApi.call_function :gqlite_connection_create_from_sqlite_file, sqlite_filename, nil
|
39
|
+
else
|
40
|
+
raise Error.new "No connection backend was selected."
|
41
|
+
end
|
42
|
+
ObjectSpace.define_finalizer @dbhandle, proc {|id|
|
43
|
+
CApi.call_function :gqlite_connection_destroy, @dbhandle
|
44
|
+
}
|
45
|
+
end
|
46
|
+
def execute_oc_query(query, bindings: nil)
|
47
|
+
ret = CApi.call_function :gqlite_connection_oc_query, @dbhandle, query, nil
|
48
|
+
if CApi.call_function(:gqlite_value_is_valid, ret)
|
49
|
+
val = JSON.parse CApi.call_function :gqlite_value_to_json, ret
|
50
|
+
else
|
51
|
+
ret = nil
|
52
|
+
end
|
53
|
+
CApi.call_function :gqlite_value_destroy, ret
|
54
|
+
return val
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
metadata
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: gqlite
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: '0.9'
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Cyrille Berger
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2023-09-14 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: ffi
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.15'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.15'
|
27
|
+
description: |2
|
28
|
+
GQLite aims to be the equivalent to SQLite for graph database: an easy to embedd query engine, with the data stored in a single file. To achieve that, GQLite uses SQLite to store data, and come as a library implementing a translation between graph query languages and SQL.
|
29
|
+
|
30
|
+
This is an experimental release.
|
31
|
+
email:
|
32
|
+
executables: []
|
33
|
+
extensions:
|
34
|
+
- ext/gqlite/extconf.rb
|
35
|
+
extra_rdoc_files: []
|
36
|
+
files:
|
37
|
+
- ext/gqlite/extconf.rb
|
38
|
+
- ext/gqlite/gqlite-amalgamate.cpp
|
39
|
+
- ext/gqlite/gqlite-c.h
|
40
|
+
- ext/gqlite/gqlite.h
|
41
|
+
- lib/gqlite.rb
|
42
|
+
homepage: https://gitlab.com/cyloncore/gqlite
|
43
|
+
licenses:
|
44
|
+
- MIT
|
45
|
+
metadata: {}
|
46
|
+
post_install_message:
|
47
|
+
rdoc_options: []
|
48
|
+
require_paths:
|
49
|
+
- lib
|
50
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
56
|
+
requirements:
|
57
|
+
- - ">="
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: '0'
|
60
|
+
requirements: []
|
61
|
+
rubygems_version: 3.3.5
|
62
|
+
signing_key:
|
63
|
+
specification_version: 4
|
64
|
+
summary: Ruby bindings for GQLite, a Graph Query library.
|
65
|
+
test_files: []
|