rails-nl2sql 0.1.7 → 0.1.8
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/lib/rails/nl2sql/query_generator.rb +43 -1
- data/lib/rails/nl2sql/query_validator.rb +25 -6
- data/lib/rails/nl2sql/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4c85af69e2b9d5c60665676f6b1aa853220bb44e98484bd0968b9e659528fa31
|
4
|
+
data.tar.gz: 8423aaec96729c329dad2fe601ba11ef84545054f84ab1f3e0fc32ac181a7a8f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 91739a9e2c4456f0232da6f614a5f9b7647b77267bc8d9eb49b3bb36a7d64542cca9ebf5e02897424bd8dc68b20a71a2d336ffd7eededd3b4b05cc2879d25fd4
|
7
|
+
data.tar.gz: 4e4540b9939bbb22bb093cf15482215016817b5cee95dbefaf6713cce048e5464136c62aeef0116659f378f020443e409b92d927bd4755a22c2c3829d6c9d022
|
@@ -27,6 +27,9 @@ module Rails
|
|
27
27
|
|
28
28
|
generated_query = response.dig("choices", 0, "text")&.strip
|
29
29
|
|
30
|
+
# Clean up the response to remove markdown formatting
|
31
|
+
generated_query = clean_sql_response(generated_query)
|
32
|
+
|
30
33
|
# Safety check
|
31
34
|
validate_query_safety(generated_query)
|
32
35
|
|
@@ -92,7 +95,7 @@ module Rails
|
|
92
95
|
* This is essential
|
93
96
|
6. **Ambiguity:** If a user question is ambiguous or requires more information to form a precise SQL query, clearly state that you need clarification and ask for more details. Do not guess.
|
94
97
|
|
95
|
-
**RESPOND WITH ONLY THE SQL QUERY - NO EXPLANATIONS
|
98
|
+
**RESPOND WITH ONLY THE SQL QUERY - NO EXPLANATIONS, NO MARKDOWN FORMATTING, NO CODE BLOCKS, NO ADDITIONAL TEXT.**
|
96
99
|
PROMPT
|
97
100
|
end
|
98
101
|
|
@@ -103,6 +106,45 @@ module Rails
|
|
103
106
|
PROMPT
|
104
107
|
end
|
105
108
|
|
109
|
+
def clean_sql_response(query)
|
110
|
+
return query unless query
|
111
|
+
|
112
|
+
# Remove markdown code blocks
|
113
|
+
query = query.gsub(/```sql\n?/, '')
|
114
|
+
query = query.gsub(/```\n?/, '')
|
115
|
+
|
116
|
+
# Remove any leading/trailing whitespace
|
117
|
+
query = query.strip
|
118
|
+
|
119
|
+
# Remove any explanatory text before or after the query
|
120
|
+
# Look for common patterns like "Here's the SQL query:" or "The query is:"
|
121
|
+
query = query.gsub(/^.*?(SELECT|WITH|INSERT|UPDATE|DELETE|CREATE|DROP|ALTER)/i, '\1')
|
122
|
+
|
123
|
+
# Remove any trailing explanatory text after the query
|
124
|
+
# Split by newlines and take only the SQL part
|
125
|
+
lines = query.split("\n")
|
126
|
+
sql_lines = []
|
127
|
+
|
128
|
+
lines.each do |line|
|
129
|
+
line = line.strip
|
130
|
+
# Skip empty lines or lines that look like explanations
|
131
|
+
next if line.empty?
|
132
|
+
next if line.match(/^(here|this|the query|explanation|note)/i)
|
133
|
+
|
134
|
+
sql_lines << line
|
135
|
+
end
|
136
|
+
|
137
|
+
# Rejoin the SQL lines
|
138
|
+
cleaned_query = sql_lines.join("\n").strip
|
139
|
+
|
140
|
+
# Ensure it ends with a semicolon if it's a complete query
|
141
|
+
if cleaned_query.match(/^(SELECT|WITH)/i) && !cleaned_query.end_with?(';')
|
142
|
+
cleaned_query += ';'
|
143
|
+
end
|
144
|
+
|
145
|
+
cleaned_query
|
146
|
+
end
|
147
|
+
|
106
148
|
def validate_query_safety(query)
|
107
149
|
return unless query
|
108
150
|
|
@@ -2,17 +2,36 @@ module Rails
|
|
2
2
|
module Nl2sql
|
3
3
|
class QueryValidator
|
4
4
|
def self.validate(query)
|
5
|
+
return false unless query && !query.strip.empty?
|
6
|
+
|
7
|
+
# Clean the query first
|
8
|
+
query = query.strip
|
9
|
+
|
10
|
+
# Check if query is malformed (contains markdown or other formatting)
|
11
|
+
if query.include?('```') || query.include?('```sql')
|
12
|
+
raise Rails::Nl2sql::Error, "Query contains markdown formatting and could not be cleaned properly"
|
13
|
+
end
|
14
|
+
|
5
15
|
# Basic validation: prevent destructive commands
|
6
|
-
disallowed_keywords = %w(DROP DELETE UPDATE INSERT TRUNCATE ALTER CREATE)
|
7
|
-
|
8
|
-
|
16
|
+
disallowed_keywords = %w(DROP DELETE UPDATE INSERT TRUNCATE ALTER CREATE EXEC EXECUTE MERGE REPLACE)
|
17
|
+
query_upper = query.upcase
|
18
|
+
|
19
|
+
if disallowed_keywords.any? { |keyword| query_upper.include?(keyword) }
|
20
|
+
raise Rails::Nl2sql::Error, "Query contains disallowed keywords."
|
21
|
+
end
|
22
|
+
|
23
|
+
# Ensure it's a SELECT query
|
24
|
+
unless query_upper.strip.start_with?('SELECT', 'WITH')
|
25
|
+
raise Rails::Nl2sql::Error, "Only SELECT queries are allowed."
|
9
26
|
end
|
10
27
|
|
11
|
-
# Use Rails' built-in
|
28
|
+
# Use Rails' built-in validation with EXPLAIN
|
12
29
|
begin
|
13
|
-
|
30
|
+
# Remove trailing semicolon for EXPLAIN
|
31
|
+
explain_query = query.gsub(/;\s*$/, '')
|
32
|
+
ActiveRecord::Base.connection.execute("EXPLAIN #{explain_query}")
|
14
33
|
rescue ActiveRecord::StatementInvalid => e
|
15
|
-
raise "Invalid SQL query: #{e.message}"
|
34
|
+
raise Rails::Nl2sql::Error, "Invalid SQL query: #{e.message}"
|
16
35
|
end
|
17
36
|
|
18
37
|
true
|
data/lib/rails/nl2sql/version.rb
CHANGED