Class: SmqlToAR::QueryBuilder

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

Overview

Baut die Queries zusammen.

Defined Under Namespace

Classes: Aliases, Vid

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(model, prefix = nil) ⇒ QueryBuilder

Returns a new instance of QueryBuilder.



70
71
72
73
74
75
76
77
78
79
80
# File 'lib/smql_to_ar/query_builder.rb', line 70

def initialize model, prefix = nil
	@prefix = "smql"
	@logger = SmqlToAR.logger
	@table_alias = Aliases.new @prefix
	@_vid, @_where, @_wobs, @model, @quote = 0, SmqlToAR::And[], {}, model, model.connection
	@base_table = [Column::Col.new( model.table_name)]
	@table_alias[ @base_table] = @base_table.first
	t = quote_table_name @base_table.first.col
	@_select, @_joins, @_joined, @_includes, @_order = ["DISTINCT #{t}.*"], "", [@base_table], [], []
	@table_model = {@base_table => @model}
end

Instance Attribute Details

#_joinsObject (readonly)

Returns the value of attribute _joins.



67
68
69
# File 'lib/smql_to_ar/query_builder.rb', line 67

def _joins
  @_joins
end

#_selectObject (readonly)

Returns the value of attribute _select.



67
68
69
# File 'lib/smql_to_ar/query_builder.rb', line 67

def _select
  @_select
end

#_vidObject (readonly)

Returns the value of attribute _vid.



67
68
69
# File 'lib/smql_to_ar/query_builder.rb', line 67

def _vid
  @_vid
end

#_whereObject (readonly)

Returns the value of attribute _where.



67
68
69
# File 'lib/smql_to_ar/query_builder.rb', line 67

def _where
  @_where
end

#_wobsObject (readonly)

Returns the value of attribute _wobs.



67
68
69
# File 'lib/smql_to_ar/query_builder.rb', line 67

def _wobs
  @_wobs
end

#base_tableObject (readonly)

Returns the value of attribute base_table.



67
68
69
# File 'lib/smql_to_ar/query_builder.rb', line 67

def base_table
  @base_table
end

#limitObject

Returns the value of attribute limit.



68
69
70
# File 'lib/smql_to_ar/query_builder.rb', line 68

def limit
  @limit
end

#loggerObject

Returns the value of attribute logger.



68
69
70
# File 'lib/smql_to_ar/query_builder.rb', line 68

def logger
  @logger
end

#modelObject (readonly)

Returns the value of attribute model.



67
68
69
# File 'lib/smql_to_ar/query_builder.rb', line 67

def model
  @model
end

#offsetObject

Returns the value of attribute offset.



68
69
70
# File 'lib/smql_to_ar/query_builder.rb', line 68

def offset
  @offset
end

#prefixObject (readonly)

Returns the value of attribute prefix.



67
68
69
# File 'lib/smql_to_ar/query_builder.rb', line 67

def prefix
  @prefix
end

#table_aliasObject (readonly)

Returns the value of attribute table_alias.



67
68
69
# File 'lib/smql_to_ar/query_builder.rb', line 67

def table_alias
  @table_alias
end

#table_modelObject (readonly)

Returns the value of attribute table_model.



67
68
69
# File 'lib/smql_to_ar/query_builder.rb', line 67

def table_model
  @table_model
end

Class Method Details

.calculate(operation, column_name, options = nil) ⇒ Object



204
205
206
207
208
209
# File 'lib/smql_to_ar/query_builder.rb', line 204

def @model.calculate operation, column_name, options = nil
	options = options.try(:dup) || {}
	options[:distinct] = true  unless options.except(:distinct).present?
	column_name = klass.primary_key  unless column_name.present?
	super operation, column_name, options
end

Instance Method Details

#build_arObject



185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
# File 'lib/smql_to_ar/query_builder.rb', line 185

def build_ar
	where_str = @_where.type_correction!.optimize!.build_where
	incls = {}
	@_includes.each do |inc|
		b = incls
		inc[1..-1].collect {|rel| b = b[rel] ||= {} }
	end
	@model = @model.
		select( @_select.join( ', ')).
		joins( @_joins).
		where( where_str, @_wobs).
		order( @_order.join( ', ')).
		includes( incls)
	@model = @model.limit @limit  if @limit
	@model = @model.offset @offset  if @offset
	@model
end

#build_join(orig, pretable, table, prekey, key) ⇒ Object



118
119
120
# File 'lib/smql_to_ar/query_builder.rb', line 118

def build_join orig, pretable, table, prekey, key
	"\tLEFT JOIN #{orig} AS #{quote_table_name table}\n\tON #{column pretable, prekey} = #{column table, key}\n"
end

#column(table, name) ⇒ Object



114
115
116
# File 'lib/smql_to_ar/query_builder.rb', line 114

def column table, name
	"#{quote_table_name table}.#{quote_column_name name}"
end

#fix_calculateObject



203
204
205
206
207
208
209
210
211
# File 'lib/smql_to_ar/query_builder.rb', line 203

def fix_calculate
	def @model.calculate operation, column_name, options = nil
		options = options.try(:dup) || {}
		options[:distinct] = true  unless options.except(:distinct).present?
		column_name = klass.primary_key  unless column_name.present?
		super operation, column_name, options
	end
	self
end

#includes(table) ⇒ Object



168
169
170
171
# File 'lib/smql_to_ar/query_builder.rb', line 168

def includes table
	@_includes.push table
	self
end

#inspectObject



84
85
86
# File 'lib/smql_to_ar/query_builder.rb', line 84

def inspect
	"#<#{self.class.name}:#{"0x%x"% (self.object_id<<1)}|#{@prefix}:#{@base_table}:#{@model} vid=#{@_vid} where=#{@_where} wobs=#{@_wobs} select=#{@_select} aliases=#{@table_alias}>"
end

#join_(table, model, query, pretable = nil) ⇒ Object



127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
# File 'lib/smql_to_ar/query_builder.rb', line 127

def join_ table, model, query, pretable = nil
	pretable ||= table[0...-1]
	@table_model[ table] = model
	@table_model.rehash
	premodel = @table_model.find {|k,v| pretable == k }[1]
	t = @table_alias[ table]
	pt = quote_table_name table[ 0...-1]
	refl = premodel.reflections[table.last.to_sym]
	case refl
	when ActiveRecord::Reflection::ThroughReflection
		through = refl.through_reflection
		through_table = table[0...-1]+[Column::Col.new( through.name, table.last.as)]
		srctable = through_table+[Column::Col.new( refl.source_reflection.name, table.last.as)]
		@table_model[ srctable] = model
		@table_alias[ table] = @table_alias[ srctable]
		join_ through_table, through.klass, quote_table_name( through.table_name)
		join_ srctable, refl.klass, query, through_table
	when ActiveRecord::Reflection::AssociationReflection
		case refl.macro
		when :has_many, :has_one
			@_joins += build_join query, pretable, t, premodel.primary_key, refl.foreign_key
		when :belongs_to
			@_joins += build_join query, pretable, t, refl.foreign_key, premodel.primary_key
		when :has_and_belongs_to_many
			jointable = [Column::Col.new(',')] + table
			@_joins += build_join refl.options[:join_table], pretable, @table_alias[ jointable], premodel.primary_key, refl.foreign_key
			@_joins += build_join query, jointable, t, refl.association_foreign_key, refl.association_primary_key
		else raise BuilderError, "Unkown reflection macro: #{refl.macro.inspect}"
		end
	else raise BuilderError, "Unkown reflection type: #{refl.class.name} #{refl.macro.inspect}"
	end
	self
end

#joins(table, model) ⇒ Object



161
162
163
164
165
166
# File 'lib/smql_to_ar/query_builder.rb', line 161

def joins table, model
	table = table.flatten.compact
	return self  if @_joined.include? table # Already joined
	join_ table, model, quote_table_name( model.table_name)
	@_joined.push table
end

#order(table, col, o) ⇒ Object



178
179
180
181
182
183
# File 'lib/smql_to_ar/query_builder.rb', line 178

def order table, col, o
	ct = column table, col
	@_select.push ct
	@_order.push "#{ct} #{:DESC == o ? :DESC : :ASC}"
	self
end

#quote_column_name(name) ⇒ Object



102
103
104
# File 'lib/smql_to_ar/query_builder.rb', line 102

def quote_column_name name
	@quote.quote_column_name( name).gsub /"\."/, ','
end

#quote_table_name(name) ⇒ Object



106
107
108
109
110
111
112
# File 'lib/smql_to_ar/query_builder.rb', line 106

def quote_table_name name
	name = case name
		when Array, Column::Col then @table_alias[Array.wrap name]
		else name.to_s
		end
	@quote.quote_table_name name
end

#select(col) ⇒ Object



173
174
175
176
# File 'lib/smql_to_ar/query_builder.rb', line 173

def select col
	@_select.push quote_column_name( @table_alias[col])
	self
end

#sub_joins(table, col, model, query) ⇒ Object



122
123
124
125
# File 'lib/smql_to_ar/query_builder.rb', line 122

def sub_joins table, col, model, query
	prefix, base_table = "#{@prefix}_sub", col.relation.table_name
	join_ table, model, "(#{query.build( prefix).ar.to_sql})"
end

#to_arObject



213
214
215
216
217
# File 'lib/smql_to_ar/query_builder.rb', line 213

def to_ar
	build_ar
	fix_calculate
	@model
end

#vidObject



82
# File 'lib/smql_to_ar/query_builder.rb', line 82

def vid()  Vid.new( @_vid+=1)  end

#where(cond) ⇒ Object

Jede via where uebergebene Condition wird geodert und alle zusammen werden geundet. “Konjunktive Normalform”. Allerdings duerfen Conditions auch Komplexe Abfragen enthalten. Ex: builder.where( [‘a = a’, ‘b = c’]).where( [‘c = d’, ‘e = e’]).where( ‘x = y’).where( [‘( m = n AND o = p )’, ‘f = g’])

#=> WHERE ( a = a OR b = c ) AND ( c = d OR e = e ) AND x = y ( ( m = n AND o = p ) OR f = g )


92
93
94
95
# File 'lib/smql_to_ar/query_builder.rb', line 92

def where cond
	@_where.push cond
	self
end

#wobs(vals) ⇒ Object



97
98
99
100
# File 'lib/smql_to_ar/query_builder.rb', line 97

def wobs vals
	@_wobs.update vals
	self
end