Class: I_Dig_Sql

Inherits:
Object
  • Object
show all
Includes:
Enumerable
Defined in:
lib/i_dig_sql.rb

Defined Under Namespace

Classes: H

Constant Summary collapse

HAS_VAR =
/(\{\{|\<\<)[^\}\>]+(\}\}|\>\>)/
Duplicate =
Class.new RuntimeError

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(*args) ⇒ I_Dig_Sql

Returns a new instance of I_Dig_Sql.



39
40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/i_dig_sql.rb', line 39

def initialize *args
  @digs = args.select { |a|
    a.is_a? I_Dig_Sql
  }

  @sqls = H.new
  @vars = H.new

  @sqls.merge_these *(@digs.map(&:sqls))
  @vars.merge_these *(@digs.map(&:vars))

  @string = args.select { |s| s.is_a? String }.join("\n")
end

Instance Attribute Details

#sqlsObject (readonly)

class H



38
39
40
# File 'lib/i_dig_sql.rb', line 38

def sqls
  @sqls
end

#varsObject (readonly)

class H



38
39
40
# File 'lib/i_dig_sql.rb', line 38

def vars
  @vars
end

Instance Method Details

#<<(str) ⇒ Object



69
70
71
72
73
74
75
76
77
# File 'lib/i_dig_sql.rb', line 69

def << str
  @string << (
    if @string.empty?
      str
    else
      "\n" << str
    end
  )
end

#[](name) ⇒ Object



53
54
55
# File 'lib/i_dig_sql.rb', line 53

def [] name
  @sqls[name]
end

#[]=(name, val) ⇒ Object



57
58
59
# File 'lib/i_dig_sql.rb', line 57

def []= name, val
  @sqls[name] = val
end

#eachObject



61
62
63
64
65
66
67
# File 'lib/i_dig_sql.rb', line 61

def each
  if block_given?
    @sqls.each { |k, v| yield k, v }
  else
    @sqls.each
  end
end

#to_pairObject



79
80
81
# File 'lib/i_dig_sql.rb', line 79

def to_pair
  [to_sql, vars]
end

#to_sqlObject



83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# File 'lib/i_dig_sql.rb', line 83

def to_sql
  s    = @string.dup
  ctes = []

  while s[HAS_VAR]
    s.gsub!(/\{\{\s?([a-zA-Z0-9\_]+)\s?\}\}/) do |match|
      key = $1.to_sym
      ctes << key
      key
    end

    s.gsub!(/\<\<\s?([a-zA-Z0-9\_\-\ \*]+)\s?\>\>/) do |match|
      tokens = $1.split
      key    = tokens.pop.to_sym
      field  = tokens.empty? ? nil : tokens.join(' ')

      case
      when field
        ctes << key
        "SELECT #{field} FROM #{key}"
      else
        self[key]
      end
    end
  end

  return s if ctes.empty?

  %^
    WITH
    #{ctes.uniq.map { |k| "#{k} AS (
      #{self[k]}
    )" }.join "
    ,
    "}
    #{s}
  ^
end