rails_age 0.6.1 → 0.6.3
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 +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
|