Class: Epoxy

Inherits:
Object
  • Object
show all
Defined in:
lib/epoxy.rb

Overview

Epoxy - bind data to queries for any query language.

Let me hit ya with some science!

ep = Epoxy.new("select * from foo where bar=?")
binds = %W[foo]
bound_query = ep.quote { |x| "'" + binds[x] + "'" }
"select * from foo where bar='foo'"

Epoxy handles:

  • ? for numbered binds (named binds coming soon!)

  • ?? for a real question mark

  • ‘?’ for a real question mark

  • comments, weird quoting styles (look at the “holy shit” test for examples)

  • not telling you how to quote your data. This solution works for any query language and any database.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(query) ⇒ Epoxy

Takes a query as a string. The binding rules are as follows:

  • ? for numbered binds (named binds coming soon!)

  • ?? for a real question mark

  • ‘?’ for a real question mark

  • comments, weird quoting styles are unaffected.



61
62
63
64
# File 'lib/epoxy.rb', line 61

def initialize(query)
    @query  = query
    @tokens = self.class.parse_tokens(query) 
end

Instance Attribute Details

#queryObject (readonly)

the original query, before quoting.



51
52
53
# File 'lib/epoxy.rb', line 51

def query
  @query
end

#tokensObject (readonly)

tokens generated by Epoxy.parse_tokens. Just use Epoxy#quote for now.



49
50
51
# File 'lib/epoxy.rb', line 49

def tokens
  @tokens
end

Class Method Details

.parse_tokens(query) ⇒ Object

Token parser, isolates components of the query into parts to where they can be managed indepdently.

Probably not the easiest thing to deal with by itself. Use the standard methods plox.



25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/epoxy.rb', line 25

def self.parse_tokens(query)
    query.scan(%r{
        (
            -- .*                               (?# matches "--" style comments to the end of line or string )
            |   -                                   (?# matches single "-" )
            |
            /[*] .*? [*]/                       (?# matches C-style comments )
            |   /                                   (?# matches single slash )    
            |
            ' ( [^'\\]  |  ''  |  \\. )* '      (?# match strings surrounded by apostophes )
            |
            " ( [^"\\]  |  ""  |  \\. )* "      (?# match strings surrounded by " )
            |
            ['"]                                (?# match a loose quote ) 
            |
            \?\??                               (?# match one or two question marks )
            |
            [^-/'"?]+                           (?# match all characters except ' " ? - and / )

        )
    }x).collect(&:first)
end

Instance Method Details

#quote(&block) ⇒ Object

Processes your query for quoting. Provide a block that emulates how your data should be quoted, and it will yield on each successive bound element with the index of that element passed.

You are responsible for quoting your data properly. Epoxy just makes it easier to get the places you need to quote out of the query.



74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/epoxy.rb', line 74

def quote(&block)
    result = ""
    bind_pos = 0

    tokens.each do |part|
        case part
        when '?'
            result << block.call(bind_pos)
            bind_pos += 1
        when '??'
            result << "?"
        else
            result << part
        end
    end

    return result
end