Last active
August 29, 2015 14:05
-
-
Save mfpiccolo/66920e112fb15c3454c5 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# What I want to do is take a string like "some_attribute <= 5" and be able to parse that into SQL | |
# The string will only ever have one operation so I need to check for the inclusion of any valid opperator | |
# and build a SQL string based on that. | |
# initial conditional method | |
def build_sql_string | |
@final_sql_array = sql_array.map(&:strip).map do |string| | |
if string.include?(":") | |
q = string.split(":") | |
"(similarity((data->>'#{q[0].strip}')::text, '#{q[1].strip}') > .5 OR " + | |
"(data->>'#{q[0].strip}')::text ILIKE '%#{q[1].strip}%')" | |
elsif [">=", "<=", ">", "<"].any? { |join| string.include? join } | |
q = string.gsub(/\s+/m, ' ').strip.split(" ") | |
"(data->>'#{q[0].strip}')::int #{q[1]} #{q[2]}" | |
elsif ["=", "!="].any? {|equal_opp| string.include?(equal_opp) } | |
q = string.gsub(/\s+/m, ' ').strip.split(" ") | |
"(data->>'#{q[0].strip}')::text #{q[1]} '#{q[2]}'" | |
elsif string == "||" | |
" OR " | |
elsif string == "&&" | |
" AND " | |
else | |
string | |
end | |
end | |
end | |
# after refactor | |
def build_sql_string | |
@final_sql_array = sql_array.map(&:strip).map do |string| | |
SqlString.call(string) | |
end | |
end | |
class SqlString | |
OperatorMapping = { | |
"<=" => :compare_query, ">=" => :compare_query, "<" => :compare_query, | |
">" => :compare_query, "=" => :equal_query, "!=" => :equal_query, | |
"||" => :or_join, "&&" => :and_join, ":" => :like_query | |
} | |
attr_reader :sql_string | |
def self.call(sql_string) | |
new(sql_string).call | |
end | |
def initialize(sql_string) | |
@sql_string = sql_string | |
end | |
def call | |
operator = sql_string.scan(matchers) | |
if operator.size == 1 | |
send OperatorMapping[operator.first] | |
end | |
end | |
def like_query | |
# build sql here | |
end | |
private | |
def matchers | |
Regexp.union(/<=/, />=/, /</, />/, /=/, /!=/, /\|\|/, /&&/, /:/) | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hey Mike, perhaps you should look at this parser. It creates an AST for SQL which means you can go from string, to AST, back to an SQL string. https://github.com/rom-rb/sql