rails_age 0.6.2 → 0.6.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +7 -7
- data/lib/apache_age/entities/class_methods.rb +2 -2
- data/lib/apache_age/entities/query_builder.rb +67 -33
- data/lib/rails_age/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz: '
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: '0856a8b6ebd00d824cb655f76712731b5f1034250520ddf90008099863ce70ff'
|
4
|
+
data.tar.gz: 38bfd628af67308dc59ec42eb3c7e89e6f2391c9bc4d84fd27fd24dfba89a4cd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c7f10fc55865bda5020d850470e103b1e8172e3b6fcf1be8a9fe7ecbac2b8617326cdbd3048bf241b5f5fe5a72a414d67f1f58bc2d6d06df4faa7d426ab49e86
|
7
|
+
data.tar.gz: ba30bcf0dabd7a66e68038d0314379663e1a6058f2b433947d961588cd593b3c318f3eec81ef7691d007029efbafa64d3cc2ba7fe8d92b56f9d51b31a7cf8d7b
|
data/CHANGELOG.md
CHANGED
@@ -35,21 +35,21 @@ breaking change?: namespaces (by default) will use their own schema? (add to dat
|
|
35
35
|
- **Age Path** - nodes and edges combined
|
36
36
|
* add `rails generate apache_age:path_scaffold HasJob employee_role start_node:person end_node:company`
|
37
37
|
|
38
|
+
## VERSION 0.6.4 - 2024-10-30
|
38
39
|
|
39
|
-
|
40
|
+
- **Query Sanitize**:
|
41
|
+
* allow and sanitize query strings with multiple attributes, ie: `Person.where("find.first_name = ? AND find.last_name = ?", 'John', 'Doe')`
|
42
|
+
|
43
|
+
## VERSION 0.6.3 - 2024-10-27
|
40
44
|
|
41
45
|
- **Query Sanitize**:
|
42
|
-
* reject attributes not defined in model
|
43
46
|
* sanitize strings using: id(find) = ?, 23 & find.first_name = ?, 'John'
|
47
|
+
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
|
44
48
|
|
45
49
|
## VERSION 0.6.2 - 2024-09-30
|
46
50
|
|
47
51
|
- **Query Sanitize**
|
48
|
-
*
|
49
|
-
|
50
|
-
- **TODO**:
|
51
|
-
* reject attributes not defined in model
|
52
|
-
* sanitize strings using: id(find) = ?, 23 & find.first_name = ?, 'John'
|
52
|
+
* hash queries sanitized
|
53
53
|
|
54
54
|
## VERSION 0.6.1 - 2024-09-29
|
55
55
|
|
@@ -29,6 +29,7 @@ module ApacheAge
|
|
29
29
|
@graph_name = graph_name || model_class.age_graph
|
30
30
|
end
|
31
31
|
|
32
|
+
# TODO: allow for multiple graphs
|
32
33
|
# def cypher(graph_name = 'age_schema')
|
33
34
|
# return self if graph_name.blank?
|
34
35
|
|
@@ -41,27 +42,37 @@ module ApacheAge
|
|
41
42
|
self
|
42
43
|
end
|
43
44
|
|
44
|
-
|
45
|
-
|
46
|
-
# we can have: "id(find) = ?", id & "find.name = ?", name
|
47
|
-
# ActiveRecord::Base.sanitize_sql([query_string, v])
|
48
|
-
def where(attributes)
|
49
|
-
return self if attributes.blank?
|
45
|
+
def where(*args)
|
46
|
+
return self if args.blank?
|
50
47
|
|
51
48
|
@where_clauses <<
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
49
|
+
# not able to sanitize the query string in this case: `["first_name = 'Barney'"]`
|
50
|
+
if args.length == 1 && args.first.is_a?(String)
|
51
|
+
raw_query_string = args.first
|
52
|
+
transform_cypher_sql(raw_query_string)
|
53
|
+
|
54
|
+
# Handling & sanitizing parameterized string queries
|
55
|
+
elsif args.length > 1 && args.first.is_a?(String)
|
56
|
+
raw_query_string = args.first
|
57
|
+
# Replace `id = ?` with `id(find) = ?` and `first_name = ?` with `find.first_name = ?`
|
58
|
+
query_string = transform_cypher_sql(raw_query_string)
|
59
|
+
values = args[1..-1]
|
60
|
+
# sanitize sql input values
|
61
|
+
ActiveRecord::Base.sanitize_sql_array([query_string, *values])
|
62
|
+
|
63
|
+
# Hashes are sanitized in the model class
|
64
|
+
# [{:first_name=>"Barney", :last_name=>"Rubble", :gender=>"male"}]
|
65
|
+
elsif args.first.is_a?(Hash)
|
66
|
+
attributes = args.first
|
59
67
|
edge_keys = [:start_id, :start_node, :end_id, :end_node]
|
60
68
|
if edge_keys.any? { |key| attributes.include?(key) }
|
61
|
-
model_class.send(:where_edge_clause, attributes)
|
69
|
+
model_class.send(:where_edge_clause, **attributes)
|
62
70
|
else
|
63
|
-
model_class.send(:where_node_clause, attributes)
|
71
|
+
model_class.send(:where_node_clause, **attributes)
|
64
72
|
end
|
73
|
+
|
74
|
+
else
|
75
|
+
raise ArgumentError, "Invalid arguments for `where` method"
|
65
76
|
end
|
66
77
|
|
67
78
|
self
|
@@ -72,8 +83,6 @@ module ApacheAge
|
|
72
83
|
return self if variables.blank?
|
73
84
|
|
74
85
|
@return_variables = variables
|
75
|
-
# @return_names = variables.empty? ? ['find'] : variables
|
76
|
-
# @return_clause = variables.empty? ? 'find' : "find.#{variables.join(', find.')}"
|
77
86
|
self
|
78
87
|
end
|
79
88
|
|
@@ -159,22 +168,47 @@ module ApacheAge
|
|
159
168
|
$$) AS (#{return_names.join(' agtype, ')} agtype);
|
160
169
|
SQL
|
161
170
|
end
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
171
|
+
|
172
|
+
def transform_cypher_sql(raw_sql_string)
|
173
|
+
# Define the logical operators and order multi-word operators first to avoid partial splits
|
174
|
+
operators = ['=', '>', '<', '<>', '>=', '<=', '=~', 'ENDS WITH', 'CONTAINS', 'STARTS WITH', 'IN', 'IS NULL', 'IS NOT NULL']
|
175
|
+
separators = ["AND NOT", "OR NOT", "AND", "OR", "NOT"]
|
176
|
+
|
177
|
+
# Combine the operators and separators into a regex pattern
|
178
|
+
pattern = /(#{(operators + separators).map { |s| Regexp.escape(s) }.join('|')})/
|
179
|
+
|
180
|
+
# Split the raw_sql_string string based on the pattern for operators and separators
|
181
|
+
parts = raw_sql_string.split(pattern)
|
182
|
+
|
183
|
+
# Process each part to identify and transform the attributes
|
184
|
+
transformed_parts = parts.map do |part|
|
185
|
+
# Skip transformation if part is one of the logical operators or separators
|
186
|
+
next part if operators.include?(part.strip) || separators.include?(part.strip)
|
187
|
+
|
188
|
+
if part.include?(".")
|
189
|
+
part # Keep parts with prefixes as they are
|
190
|
+
elsif part =~ /\s*(\w+)\s*$/
|
191
|
+
attribute = $1
|
192
|
+
if attribute == 'end_id'
|
193
|
+
"id(end_node)"
|
194
|
+
elsif attribute == 'start_id'
|
195
|
+
"id(start_node)"
|
196
|
+
elsif attribute == 'id'
|
197
|
+
"id(find)"
|
198
|
+
# attributes must start with a letter
|
199
|
+
elsif attribute =~ /^[a-z]\w*$/
|
200
|
+
"find.#{attribute}"
|
201
|
+
else
|
202
|
+
attribute
|
203
|
+
end
|
204
|
+
else
|
205
|
+
part
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
# Reassemble the string with the transformed parts
|
210
|
+
transformed_parts.join(" ").gsub(/\s+/, ' ').strip
|
211
|
+
end
|
178
212
|
end
|
179
213
|
end
|
180
214
|
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.4
|
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-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|