rails_age 0.6.1 → 0.6.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +18 -5
- data/README.md +1 -1
- data/lib/apache_age/entities/class_methods.rb +26 -16
- data/lib/apache_age/entities/common_methods.rb +5 -3
- data/lib/apache_age/entities/edge.rb +30 -7
- data/lib/apache_age/entities/entity.rb +21 -10
- data/lib/apache_age/entities/node.rb +27 -7
- data/lib/apache_age/entities/query_builder.rb +122 -17
- data/lib/rails_age/version.rb +1 -1
- metadata +2 -3
- data/lib/apache_age/entities/vertex.rb +0 -53
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e8bae6566d3be3dc932bc834d67b969ddab46efb5bc72dfde5b245a861f9c09f
|
4
|
+
data.tar.gz: 04ab7c0d236560abefbe9d637a24e5e027ada6a2f3c0279d4aace865262c5808
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6e2b16c1934dbdf79dce10028ee5d6066e93416a0ea2a31f378b2239db72383b11dec44a892a254721c75130f2b0fad5c4ab4a4dda0bdbf747ecb66bc695c8b7
|
7
|
+
data.tar.gz: 5883fcd0e9a36c965683ec01702b9a8e6b8d31e66d991ef2331c21ab11aa49c894965f666937d456dbd5fc7aaea1b35577f9f9c9b8115c4775a83bf18eed4354
|
data/CHANGELOG.md
CHANGED
@@ -22,22 +22,35 @@
|
|
22
22
|
* paths support
|
23
23
|
* select attributes support
|
24
24
|
|
25
|
+
## VERSION 0.8.0 - 2024-xx-xx
|
26
|
+
|
27
|
+
breaking change?: namespaces (by default) will use their own schema? (add to database.yml & schema.rb ?)
|
28
|
+
|
29
|
+
- **AGE Schema override**
|
30
|
+
|
31
|
+
- **Multiple AGE Schema**
|
32
|
+
|
25
33
|
## VERSION 0.7.0 - 2024-xx-xx
|
26
34
|
|
27
35
|
- **Age Path** - nodes and edges combined
|
28
36
|
* add `rails generate apache_age:path_scaffold HasJob employee_role start_node:person end_node:company`
|
29
37
|
|
30
|
-
## VERSION 0.6.
|
38
|
+
## VERSION 0.6.4 - 2024-xx-xx
|
31
39
|
|
32
|
-
|
40
|
+
- **Query Sanitize**:
|
41
|
+
* reject attributes not defined in model (throw error?)
|
42
|
+
* allow and sanitize query strings with multiple attributes, ie: `Person.where("find.first_name = ? AND find.last_name = ?", 'John', 'Doe')`
|
33
43
|
|
34
|
-
|
44
|
+
## VERSION 0.6.3 - 2024-10-27
|
35
45
|
|
36
|
-
- **
|
46
|
+
- **Query Sanitize**:
|
47
|
+
* sanitize strings using: id(find) = ?, 23 & find.first_name = ?, 'John'
|
48
|
+
NOTE: this sanitization only works (so far) for strings containing ONE attribute. ie: `Person.where("find.first_name = ?", 'John')` or `Person.where("first_name = ?", 'John')` works but `Person.where("find.first_name = ? AND find.last_name = ?", 'John', 'Doe')` does not yet work
|
37
49
|
|
38
|
-
## VERSION 0.6.2 - 2024-
|
50
|
+
## VERSION 0.6.2 - 2024-09-30
|
39
51
|
|
40
52
|
- **Query Sanitize**
|
53
|
+
* hash queries sanitized
|
41
54
|
|
42
55
|
## VERSION 0.6.1 - 2024-09-29
|
43
56
|
|
data/README.md
CHANGED
@@ -8,9 +8,9 @@ module ApacheAge
|
|
8
8
|
instance
|
9
9
|
end
|
10
10
|
|
11
|
-
def where(attributes)
|
11
|
+
def where(*attributes)
|
12
12
|
query_builder = QueryBuilder.new(self)
|
13
|
-
query_builder.where(attributes)
|
13
|
+
query_builder.where(*attributes)
|
14
14
|
end
|
15
15
|
|
16
16
|
def all = QueryBuilder.new(self).all
|
@@ -25,18 +25,20 @@ module ApacheAge
|
|
25
25
|
|
26
26
|
# Private stuff
|
27
27
|
|
28
|
+
# used? or dead code?
|
28
29
|
def where_edge(attributes)
|
29
30
|
where_attribs =
|
30
31
|
attributes
|
31
|
-
|
32
|
-
|
33
|
-
|
32
|
+
.compact
|
33
|
+
.except(:end_id, :start_id, :end_node, :start_node)
|
34
|
+
.map { |k, v| ActiveRecord::Base.sanitize_sql(["find.#{k} = ?", v]) }
|
35
|
+
.join(' AND ')
|
34
36
|
where_attribs = where_attribs.empty? ? nil : where_attribs
|
35
37
|
|
36
38
|
end_id = attributes[:end_id] || attributes[:end_node]&.id
|
37
39
|
start_id = attributes[:start_id] || attributes[:start_node]&.id
|
38
|
-
where_end_id = end_id ? "id(end_node) =
|
39
|
-
where_start_id = start_id ? "id(start_node) =
|
40
|
+
where_end_id = end_id ? ActiveRecord::Base.sanitize_sql(["id(end_node) = ?", end_id]) : nil
|
41
|
+
where_start_id = start_id ? ActiveRecord::Base.sanitize_sql(["id(start_node) = ?", start_id]) : nil
|
40
42
|
|
41
43
|
where_clause = [where_attribs, where_start_id, where_end_id].compact.join(' AND ')
|
42
44
|
return nil if where_clause.empty?
|
@@ -115,33 +117,41 @@ module ApacheAge
|
|
115
117
|
|
116
118
|
end_id =
|
117
119
|
if attributes[:end_id]
|
118
|
-
|
120
|
+
attributes[:end_id]
|
119
121
|
elsif attributes[:end_node].is_a?(Node)
|
120
|
-
|
122
|
+
attributes[:end_node]&.id
|
121
123
|
end
|
122
|
-
where_end_id = end_id ? "id(end_node) =
|
124
|
+
where_end_id = end_id ? ActiveRecord::Base.sanitize_sql(["id(end_node) = ?", end_id]) : nil
|
123
125
|
|
124
126
|
start_id =
|
125
127
|
if attributes[:start_id]
|
126
|
-
|
128
|
+
attributes[:start_id]
|
127
129
|
elsif attributes[:start_node].is_a?(Node)
|
128
|
-
|
130
|
+
attributes[:start_node]&.id
|
129
131
|
end
|
130
|
-
where_start_id = start_id ? "id(start_node) =
|
132
|
+
where_start_id = start_id ? ActiveRecord::Base.sanitize_sql(["id(start_node) = ?", start_id]) : nil
|
131
133
|
|
132
134
|
where_end_attrs =
|
133
|
-
|
135
|
+
if attributes[:end_node].is_a?(Hash)
|
136
|
+
attributes[:end_node].map { |k, v| ActiveRecord::Base.sanitize_sql(["end_node.#{k} = ?", v]) }
|
137
|
+
end
|
134
138
|
where_start_attrs =
|
135
|
-
|
139
|
+
if attributes[:start_node].is_a?(Hash)
|
140
|
+
attributes[:start_node].map { |k, v| ActiveRecord::Base.sanitize_sql(["start_node.#{k} = ?", v]) }
|
141
|
+
end
|
136
142
|
|
137
143
|
[core_clauses, where_start_id, where_end_id, where_start_attrs, where_end_attrs]
|
138
144
|
.flatten.compact.join(' AND ')
|
139
145
|
end
|
140
146
|
|
147
|
+
|
141
148
|
def build_core_where_clause(attributes)
|
142
149
|
attributes
|
143
150
|
.compact
|
144
|
-
.map
|
151
|
+
.map do |k, v|
|
152
|
+
query_string = k == :id ? "id(find) = #{v}" : "find.#{k} = '#{v}'"
|
153
|
+
ActiveRecord::Base.sanitize_sql([query_string, v])
|
154
|
+
end
|
145
155
|
.join(' AND ')
|
146
156
|
end
|
147
157
|
end
|
@@ -57,13 +57,14 @@ module ApacheAge
|
|
57
57
|
def destroy
|
58
58
|
match_clause = (age_type == 'vertex' ? "(done:#{age_label})" : "()-[done:#{age_label}]->()")
|
59
59
|
delete_clause = (age_type == 'vertex' ? 'DETACH DELETE done' : 'DELETE done')
|
60
|
+
sanitized_id = ActiveRecord::Base.sanitize_sql(["id(done) = ?", id])
|
60
61
|
cypher_sql =
|
61
62
|
<<-SQL
|
62
63
|
SELECT *
|
63
64
|
FROM cypher('#{age_graph}', $$
|
64
65
|
MATCH #{match_clause}
|
65
|
-
WHERE
|
66
|
-
|
66
|
+
WHERE #{sanitized_id}
|
67
|
+
#{delete_clause}
|
67
68
|
return done
|
68
69
|
$$) as (deleted agtype);
|
69
70
|
SQL
|
@@ -99,7 +100,8 @@ module ApacheAge
|
|
99
100
|
def properties_to_s
|
100
101
|
string_values =
|
101
102
|
age_properties.each_with_object([]) do |(key, val), array|
|
102
|
-
|
103
|
+
sanitized_val = ActiveRecord::Base.sanitize_sql(["?", val])
|
104
|
+
array << "#{key}: #{sanitized_val}"
|
103
105
|
end
|
104
106
|
"{#{string_values.join(', ')}}"
|
105
107
|
end
|
@@ -70,12 +70,25 @@ module ApacheAge
|
|
70
70
|
def create_sql
|
71
71
|
self.start_node = start_node.save unless start_node.persisted?
|
72
72
|
self.end_node = end_node.save unless end_node.persisted?
|
73
|
+
|
74
|
+
start_node_age_label = ActiveRecord::Base.sanitize_sql(start_node.age_label)
|
75
|
+
end_node_age_label = ActiveRecord::Base.sanitize_sql(end_node.age_label)
|
76
|
+
sanitized_start_id = ActiveRecord::Base.sanitize_sql(["?", start_node.id])
|
77
|
+
sanitized_end_id = ActiveRecord::Base.sanitize_sql(["?", end_node.id])
|
78
|
+
# cant use sanitize_sql_like because it escapes the % and _ characters
|
79
|
+
# label_name = ActiveRecord::Base.sanitize_sql_like(age_label)
|
80
|
+
|
81
|
+
reject_keys = %i[id start_id end_id start_node end_node]
|
82
|
+
sanitized_properties =
|
83
|
+
self.to_h.reject { |k, _v| reject_keys.include?(k) }.reject { |_k, v| v.nil? }
|
84
|
+
.map { |k, v| "#{k}: #{ActiveRecord::Base.sanitize_sql(["?", v])}" }
|
85
|
+
.join(', ')
|
73
86
|
<<-SQL
|
74
87
|
SELECT *
|
75
88
|
FROM cypher('#{age_graph}', $$
|
76
|
-
MATCH (from_node:#{
|
77
|
-
WHERE id(from_node) = #{
|
78
|
-
CREATE (from_node)-[edge#{
|
89
|
+
MATCH (from_node:#{start_node_age_label}), (to_node:#{end_node_age_label})
|
90
|
+
WHERE id(from_node) = #{sanitized_start_id} AND id(to_node) = #{sanitized_end_id}
|
91
|
+
CREATE (from_node)-[edge:#{age_label} {#{sanitized_properties}}]->(to_node)
|
79
92
|
RETURN edge
|
80
93
|
$$) as (edge agtype);
|
81
94
|
SQL
|
@@ -84,14 +97,24 @@ module ApacheAge
|
|
84
97
|
# So far just properties of string type with '' around them
|
85
98
|
def update_sql
|
86
99
|
alias_name = age_alias || age_label.downcase
|
87
|
-
|
88
|
-
age_properties.map
|
100
|
+
set_clause =
|
101
|
+
age_properties.map do |k, v|
|
102
|
+
if v
|
103
|
+
sanitized_value = ActiveRecord::Base.sanitize_sql(["?", v])
|
104
|
+
"#{alias_name}.#{k} = #{sanitized_value}"
|
105
|
+
else
|
106
|
+
"#{alias_name}.#{k} = NULL"
|
107
|
+
end
|
108
|
+
end.join(', ')
|
109
|
+
|
110
|
+
sanitized_id = ActiveRecord::Base.sanitize_sql(["?", id])
|
111
|
+
|
89
112
|
<<-SQL
|
90
113
|
SELECT *
|
91
114
|
FROM cypher('#{age_graph}', $$
|
92
115
|
MATCH ()-[#{alias_name}:#{age_label}]->()
|
93
|
-
WHERE id(#{alias_name}) = #{
|
94
|
-
SET #{
|
116
|
+
WHERE id(#{alias_name}) = #{sanitized_id}
|
117
|
+
SET #{set_clause}
|
95
118
|
RETURN #{alias_name}
|
96
119
|
$$) as (#{age_label} agtype);
|
97
120
|
SQL
|
@@ -3,14 +3,20 @@ module ApacheAge
|
|
3
3
|
class Entity
|
4
4
|
class << self
|
5
5
|
def find_by(attributes)
|
6
|
-
where_clause =
|
6
|
+
where_clause =
|
7
|
+
attributes
|
8
|
+
.map do |k, v|
|
9
|
+
if k == :id
|
10
|
+
ActiveRecord::Base.sanitize_sql(["id(find) = ?", v])
|
11
|
+
else
|
12
|
+
ActiveRecord::Base.sanitize_sql(["find.#{k} = ?", v])
|
13
|
+
end
|
14
|
+
end
|
15
|
+
.join(' AND ')
|
7
16
|
handle_find(where_clause)
|
8
17
|
end
|
9
18
|
|
10
|
-
def find(id)
|
11
|
-
where_clause = "id(find) = #{id}"
|
12
|
-
handle_find(where_clause)
|
13
|
-
end
|
19
|
+
def find(id) = find_by(id: id)
|
14
20
|
|
15
21
|
private
|
16
22
|
|
@@ -46,19 +52,24 @@ module ApacheAge
|
|
46
52
|
json_data = JSON.parse(json_string)
|
47
53
|
|
48
54
|
age_label = json_data['label']
|
49
|
-
attribs =
|
50
|
-
|
51
|
-
|
55
|
+
attribs =
|
56
|
+
json_data
|
57
|
+
.except('label', 'properties')
|
58
|
+
.merge(json_data['properties'])
|
59
|
+
.symbolize_keys
|
52
60
|
|
53
61
|
"#{json_data['label'].gsub('__', '::')}".constantize.new(**attribs)
|
54
62
|
end
|
55
63
|
|
56
64
|
def find_sql(match_clause, where_clause)
|
65
|
+
sanitized_match_clause = ActiveRecord::Base.sanitize_sql(match_clause)
|
66
|
+
sanitized_where_clause = where_clause # Already sanitized in `find_by` or `find`
|
67
|
+
|
57
68
|
<<-SQL
|
58
69
|
SELECT *
|
59
70
|
FROM cypher('#{age_graph}', $$
|
60
|
-
MATCH #{
|
61
|
-
WHERE #{
|
71
|
+
MATCH #{sanitized_match_clause}
|
72
|
+
WHERE #{sanitized_where_clause}
|
62
73
|
RETURN find
|
63
74
|
$$) as (found agtype);
|
64
75
|
SQL
|
@@ -25,11 +25,21 @@ module ApacheAge
|
|
25
25
|
# RETURN company
|
26
26
|
# $$) as (Company agtype);
|
27
27
|
def create_sql
|
28
|
+
# can't use sanitiye without a solution for '_' in the alias name & label
|
29
|
+
# alias_name = ActiveRecord::Base.sanitize_sql_like(age_alias || age_label.downcase)
|
30
|
+
# label_name = ActiveRecord::Base.sanitize_sql_like(age_label)
|
31
|
+
|
28
32
|
alias_name = age_alias || age_label.downcase
|
29
|
-
|
33
|
+
sanitized_properties =
|
34
|
+
self
|
35
|
+
.to_h.reject { |k, v| k == :id }.reject { |k, v| v.nil? }
|
36
|
+
.map { |k, v| "#{k}: #{ActiveRecord::Base.sanitize_sql(["?", v])}" }
|
37
|
+
.join(', ')
|
38
|
+
|
39
|
+
<<~SQL.squish
|
30
40
|
SELECT *
|
31
41
|
FROM cypher('#{age_graph}', $$
|
32
|
-
CREATE (#{alias_name}#{
|
42
|
+
CREATE (#{alias_name}:#{age_label} {#{sanitized_properties}})
|
33
43
|
RETURN #{alias_name}
|
34
44
|
$$) as (#{age_label} agtype);
|
35
45
|
SQL
|
@@ -37,19 +47,29 @@ module ApacheAge
|
|
37
47
|
|
38
48
|
# So far just properties of string type with '' around them
|
39
49
|
def update_sql
|
40
|
-
alias_name = age_alias || age_label.downcase
|
41
|
-
|
42
|
-
|
50
|
+
alias_name = ActiveRecord::Base.sanitize_sql_like(age_alias || age_label.downcase)
|
51
|
+
sanitized_set_clause = age_properties.map do |k, v|
|
52
|
+
if v
|
53
|
+
sanitized_value = ActiveRecord::Base.sanitize_sql(["?", v])
|
54
|
+
"#{alias_name}.#{k} = #{sanitized_value}"
|
55
|
+
else
|
56
|
+
"#{alias_name}.#{k} = NULL"
|
57
|
+
end
|
58
|
+
end.join(', ')
|
59
|
+
|
60
|
+
sanitized_id = ActiveRecord::Base.sanitize_sql(["?", id])
|
61
|
+
|
43
62
|
<<-SQL
|
44
63
|
SELECT *
|
45
64
|
FROM cypher('#{age_graph}', $$
|
46
65
|
MATCH (#{alias_name}:#{age_label})
|
47
|
-
WHERE id(#{alias_name}) = #{
|
48
|
-
SET #{
|
66
|
+
WHERE id(#{alias_name}) = #{sanitized_id}
|
67
|
+
SET #{sanitized_set_clause}
|
49
68
|
RETURN #{alias_name}
|
50
69
|
$$) as (#{age_label} agtype);
|
51
70
|
SQL
|
52
71
|
end
|
72
|
+
|
53
73
|
end
|
54
74
|
end
|
55
75
|
end
|
@@ -41,29 +41,116 @@ module ApacheAge
|
|
41
41
|
self
|
42
42
|
end
|
43
43
|
|
44
|
-
# need to handle string inputs too:
|
45
|
-
|
46
|
-
|
44
|
+
# # TODO: need to handle string inputs too: instead of: \
|
45
|
+
# # "id(find) = #{id}" & "find.name = #{name}"
|
46
|
+
# # we can have: "id(find) = ?", id & "find.name = ?", name
|
47
|
+
# # ActiveRecord::Base.sanitize_sql([query_string, v])
|
48
|
+
def where(*args)
|
49
|
+
return self if args.blank?
|
47
50
|
|
48
51
|
@where_clauses <<
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
+
# not able to sanitize the query string in this case
|
53
|
+
# ["first_name = 'Barney'"]
|
54
|
+
if args.length == 1 && args.first.is_a?(String)
|
55
|
+
string_query = args.first
|
56
|
+
if string_query.include?('id = ?')
|
57
|
+
"id(find) = ?"
|
58
|
+
elsif string_query.include?('id(') || string_query.include?('find.')
|
59
|
+
string_query
|
52
60
|
else
|
53
|
-
"find.#{
|
61
|
+
"find.#{string_query}"
|
54
62
|
end
|
55
|
-
|
63
|
+
|
64
|
+
# Handling & sanitizing parameterized string queries
|
65
|
+
elsif args.length > 1 && args.first.is_a?(String)
|
66
|
+
raw_query_string = args.first
|
67
|
+
query_string =
|
68
|
+
if raw_query_string.include?('id = ?')
|
69
|
+
"id(find) = ?"
|
70
|
+
elsif raw_query_string.include?('id(') || raw_query_string.include?('find.')
|
71
|
+
raw_query_string
|
72
|
+
else
|
73
|
+
"find.#{raw_query_string}"
|
74
|
+
end
|
75
|
+
values = args[1..-1]
|
76
|
+
ActiveRecord::Base.sanitize_sql_array([query_string, *values])
|
77
|
+
|
78
|
+
# Hashes are sanitized in the model class
|
79
|
+
# [{:first_name=>"Barney", :last_name=>"Rubble", :gender=>"male"}]
|
80
|
+
elsif args.first.is_a?(Hash)
|
81
|
+
attributes = args.first
|
56
82
|
edge_keys = [:start_id, :start_node, :end_id, :end_node]
|
57
83
|
if edge_keys.any? { |key| attributes.include?(key) }
|
58
|
-
model_class.send(:where_edge_clause, attributes)
|
84
|
+
model_class.send(:where_edge_clause, **attributes)
|
59
85
|
else
|
60
|
-
model_class.send(:where_node_clause, attributes)
|
86
|
+
model_class.send(:where_node_clause, **attributes)
|
61
87
|
end
|
88
|
+
|
89
|
+
else
|
90
|
+
raise ArgumentError, "Invalid arguments for `where` method"
|
62
91
|
end
|
63
92
|
|
64
93
|
self
|
65
94
|
end
|
66
95
|
|
96
|
+
# # where is sanitized in the model class with hash values
|
97
|
+
# def where(attributes)
|
98
|
+
# return self if attributes.blank?
|
99
|
+
|
100
|
+
# @where_clauses <<
|
101
|
+
# if attributes.is_a?(String)
|
102
|
+
# puts "HANDLE PURE STRING QUERIES"
|
103
|
+
# if attributes.include?('id(') || attributes.include?('find.')
|
104
|
+
# attributes
|
105
|
+
# else
|
106
|
+
# "find.#{attributes}"
|
107
|
+
# end
|
108
|
+
# else
|
109
|
+
# puts "HANDLE HASHES"
|
110
|
+
# pp attributes
|
111
|
+
# edge_keys = [:start_id, :start_node, :end_id, :end_node]
|
112
|
+
# if edge_keys.any? { |key| attributes.include?(key) }
|
113
|
+
# puts "HANDLE EDGE CLAUSES"
|
114
|
+
# model_class.send(:where_edge_clause, attributes)
|
115
|
+
# else
|
116
|
+
# puts "HANDLE NODE CLAUSES"
|
117
|
+
# model_class.send(:where_node_clause, attributes)
|
118
|
+
# end
|
119
|
+
# end
|
120
|
+
|
121
|
+
# self
|
122
|
+
# end
|
123
|
+
|
124
|
+
# # Pre-sanitize where statements
|
125
|
+
# # def where(*args)
|
126
|
+
# # return self if args.blank?
|
127
|
+
|
128
|
+
# # # Handling parameterized query strings with values
|
129
|
+
# # if args.length == 1 && args.first.is_a?(Hash)
|
130
|
+
# # # If a hash of attributes is provided, use the existing logic
|
131
|
+
# # attributes = args.first
|
132
|
+
# # edge_keys = [:start_id, :start_node, :end_id, :end_node]
|
133
|
+
# # if edge_keys.any? { |key| attributes.include?(key) }
|
134
|
+
# # @where_clauses << model_class.send(:where_edge_clause, attributes)
|
135
|
+
# # else
|
136
|
+
# # @where_clauses << model_class.send(:where_node_clause, attributes)
|
137
|
+
# # end
|
138
|
+
# # elsif args.length > 1 && args.first.is_a?(String)
|
139
|
+
# # # If a query string with placeholders and values is provided
|
140
|
+
# # query_string = args.first
|
141
|
+
# # values = args[1..-1]
|
142
|
+
# # sanitized_query = ActiveRecord::Base.send(:sanitize_sql_array, [query_string, *values])
|
143
|
+
# # @where_clauses << sanitized_query
|
144
|
+
# # elsif args.length == 1 && args.first.is_a?(String)
|
145
|
+
# # # If a single string is provided, use it directly (assuming it is already sanitized or trusted)
|
146
|
+
# # @where_clauses << args.first
|
147
|
+
# # else
|
148
|
+
# # raise ArgumentError, "Invalid arguments for `where` method"
|
149
|
+
# # end
|
150
|
+
|
151
|
+
# # self
|
152
|
+
# # end
|
153
|
+
|
67
154
|
# New return method
|
68
155
|
def return(*variables)
|
69
156
|
return self if variables.blank?
|
@@ -112,21 +199,23 @@ module ApacheAge
|
|
112
199
|
|
113
200
|
private
|
114
201
|
|
202
|
+
# TODO: ensure ordering keys are present in the model
|
115
203
|
def parse_ordering(ordering)
|
116
204
|
if ordering.is_a?(Hash)
|
117
|
-
|
118
|
-
|
205
|
+
ordering =
|
206
|
+
ordering
|
207
|
+
.map { |k, v| "find.#{k} #{ActiveRecord::Base.sanitize_sql_like(v.to_s)}" }
|
208
|
+
.join(', ')
|
119
209
|
elsif ordering.is_a?(Symbol)
|
120
|
-
# If it's a symbol, simply prepend "find."
|
121
210
|
ordering = "find.#{ordering}"
|
122
211
|
elsif ordering.is_a?(String)
|
123
|
-
|
124
|
-
ordering = ordering
|
212
|
+
ordering
|
125
213
|
elsif ordering.is_a?(Array)
|
126
|
-
# If it's an array, process each element recursively
|
127
214
|
ordering = ordering.map do |order|
|
128
215
|
if order.is_a?(Hash)
|
129
|
-
order
|
216
|
+
order
|
217
|
+
.map { |k, v| "find.#{k} #{ActiveRecord::Base.sanitize_sql_like(v.to_s)}" }
|
218
|
+
.join(', ')
|
130
219
|
elsif order.is_a?(Symbol)
|
131
220
|
"find.#{order}"
|
132
221
|
elsif order.is_a?(String)
|
@@ -154,6 +243,22 @@ module ApacheAge
|
|
154
243
|
$$) AS (#{return_names.join(' agtype, ')} agtype);
|
155
244
|
SQL
|
156
245
|
end
|
246
|
+
# def build_query(_extra_clause = nil)
|
247
|
+
# sanitized_where_sql = where_clauses.any? ? "WHERE #{where_clauses.map { |clause| ActiveRecord::Base.sanitize_sql_like(clause) }.join(' AND ')}" : ''
|
248
|
+
# sanitized_order_by = order_clause.present? ? ActiveRecord::Base.sanitize_sql_like(order_clause) : ''
|
249
|
+
# sanitized_limit_clause = limit_clause.present? ? ActiveRecord::Base.sanitize_sql_like(limit_clause) : ''
|
250
|
+
|
251
|
+
# <<-SQL.squish
|
252
|
+
# SELECT *
|
253
|
+
# FROM cypher('#{graph_name}', $$
|
254
|
+
# MATCH #{ActiveRecord::Base.sanitize_sql_like(match_clause)}
|
255
|
+
# #{sanitized_where_sql}
|
256
|
+
# RETURN #{ActiveRecord::Base.sanitize_sql_like(return_clause)}
|
257
|
+
# #{sanitized_order_by}
|
258
|
+
# #{sanitized_limit_clause}
|
259
|
+
# $$) AS (#{return_names.map { |name| "#{ActiveRecord::Base.sanitize_sql_like(name)} agtype" }.join(', ')});
|
260
|
+
# SQL
|
261
|
+
# end
|
157
262
|
end
|
158
263
|
end
|
159
264
|
end
|
data/lib/rails_age/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rails_age
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.6.
|
4
|
+
version: 0.6.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bill Tihen
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-10-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -119,7 +119,6 @@ files:
|
|
119
119
|
- lib/apache_age/entities/node.rb
|
120
120
|
- lib/apache_age/entities/path.rb
|
121
121
|
- lib/apache_age/entities/query_builder.rb
|
122
|
-
- lib/apache_age/entities/vertex.rb
|
123
122
|
- lib/apache_age/node.rb
|
124
123
|
- lib/apache_age/path.rb
|
125
124
|
- lib/apache_age/types/factory.rb
|
@@ -1,53 +0,0 @@
|
|
1
|
-
# module ApacheAge
|
2
|
-
# module Entities
|
3
|
-
# module Vertex
|
4
|
-
# extend ActiveSupport::Concern
|
5
|
-
|
6
|
-
# included do
|
7
|
-
# include ActiveModel::Model
|
8
|
-
# include ActiveModel::Dirty
|
9
|
-
# include ActiveModel::Attributes
|
10
|
-
|
11
|
-
# attribute :id, :integer
|
12
|
-
|
13
|
-
# extend ApacheAge::Entities::ClassMethods
|
14
|
-
# include ApacheAge::Entities::CommonMethods
|
15
|
-
# end
|
16
|
-
|
17
|
-
# def age_type = 'vertex'
|
18
|
-
|
19
|
-
# # AgeSchema::Nodes::Company.create(company_name: 'Bedrock Quarry')
|
20
|
-
# # SELECT *
|
21
|
-
# # FROM cypher('age_schema', $$
|
22
|
-
# # CREATE (company:Company {company_name: 'Bedrock Quarry'})
|
23
|
-
# # RETURN company
|
24
|
-
# # $$) as (Company agtype);
|
25
|
-
# def create_sql
|
26
|
-
# alias_name = age_alias || age_label.downcase
|
27
|
-
# <<-SQL
|
28
|
-
# SELECT *
|
29
|
-
# FROM cypher('#{age_graph}', $$
|
30
|
-
# CREATE (#{alias_name}#{self})
|
31
|
-
# RETURN #{alias_name}
|
32
|
-
# $$) as (#{age_label} agtype);
|
33
|
-
# SQL
|
34
|
-
# end
|
35
|
-
|
36
|
-
# # So far just properties of string type with '' around them
|
37
|
-
# def update_sql
|
38
|
-
# alias_name = age_alias || age_label.downcase
|
39
|
-
# set_caluse =
|
40
|
-
# age_properties.map { |k, v| v ? "#{alias_name}.#{k} = '#{v}'" : "#{alias_name}.#{k} = NULL" }.join(', ')
|
41
|
-
# <<-SQL
|
42
|
-
# SELECT *
|
43
|
-
# FROM cypher('#{age_graph}', $$
|
44
|
-
# MATCH (#{alias_name}:#{age_label})
|
45
|
-
# WHERE id(#{alias_name}) = #{id}
|
46
|
-
# SET #{set_caluse}
|
47
|
-
# RETURN #{alias_name}
|
48
|
-
# $$) as (#{age_label} agtype);
|
49
|
-
# SQL
|
50
|
-
# end
|
51
|
-
# end
|
52
|
-
# end
|
53
|
-
# end
|