diff --git a/app/models/report/filter/base.rb b/app/models/report/filter/base.rb index 43aa02af7a..ca02852f84 100644 --- a/app/models/report/filter/base.rb +++ b/app/models/report/filter/base.rb @@ -1,6 +1,8 @@ class Report::Filter class Base < Report::Chainable - Report::Operator.load + include Report::QueryUtils + + engine::Operator.load inherited_attribute :available_operators, :list => true, :map => :to_operator, @@ -30,8 +32,8 @@ class Report::Filter names.each do |name| dont_inherit :available_operators if skip_inherited_operators.include? name case name - when String, Report::Operator then operators << name.to_operator - when Symbol then operators.push(*Report::Operator.send(name)) + when String, engine::Operator then operators << name.to_operator + when Symbol then operators.push(*engine::Operator.send(name)) else fail "dunno what to do with #{name.inspect}" end end @@ -93,7 +95,7 @@ class Report::Filter end def operator - (@operator || self.class.default_operator || Report::Operator.default_operator).to_operator + (@operator || self.class.default_operator || engine::Operator.default_operator).to_operator end def operator=(value) diff --git a/app/models/report/filter/no_filter.rb b/app/models/report/filter/no_filter.rb index 4922861eb6..c92a3238c1 100644 --- a/app/models/report/filter/no_filter.rb +++ b/app/models/report/filter/no_filter.rb @@ -3,5 +3,6 @@ class Report::Filter::NoFilter < Report::Filter::Base singleton def sql_statement + raise NotImplementedError, "My subclass should have overwritten 'sql_statement'" end end diff --git a/app/models/report/group_by.rb b/app/models/report/group_by.rb index e32cb390fb..a480e7deae 100644 --- a/app/models/report/group_by.rb +++ b/app/models/report/group_by.rb @@ -1,8 +1,10 @@ require "set" class Report::GroupBy + include Report::QueryUtils + def self.all - Set[CostQuery::GroupBy::SingletonValue] + Set[engine::GroupBy::SingletonValue] end def self.all_grouped diff --git a/app/models/report/group_by/base.rb b/app/models/report/group_by/base.rb index 966976e0c0..9833700178 100644 --- a/app/models/report/group_by/base.rb +++ b/app/models/report/group_by/base.rb @@ -1,5 +1,7 @@ class Report::GroupBy class Base < Report::Chainable + include Report::QueryUtils + inherited_attributes :group_fields, :list => true, :merge => false def self.inherited(klass) @@ -8,7 +10,7 @@ class Report::GroupBy end def correct_position? - type == :row or !child.is_a?(Report::GroupBy::Base) or child.type == :column + type == :row or !child.is_a?(engine::GroupBy::Base) or child.type == :column end def filter? @@ -37,7 +39,7 @@ class Report::GroupBy def aggregation_mixin sql_aggregation? ? SqlAggregation : RubyAggregation - end + end def initialize(child = nil, optios = {}) super diff --git a/app/models/report/inherited_namespace.rb b/app/models/report/inherited_namespace.rb index e6480ff934..1c3382dd7e 100644 --- a/app/models/report/inherited_namespace.rb +++ b/app/models/report/inherited_namespace.rb @@ -1,5 +1,5 @@ module Report::InheritedNamespace - NESTED_NAMESPACES = %w[Validation Filter GroupBy Result Operator] + NESTED_NAMESPACES = %w[Validation Filter GroupBy Result Operator QueryUtils] module Hook def const_missing(name, *) @@ -18,12 +18,12 @@ module Report::InheritedNamespace super propagate klass end - + def included(klass) super propagate klass end - + def propagate(klass) klass.extend Report::InheritedNamespace klass.extend Hook diff --git a/app/models/report/operator.rb b/app/models/report/operator.rb index 323f802f82..72f7d2c8b4 100644 --- a/app/models/report/operator.rb +++ b/app/models/report/operator.rb @@ -189,6 +189,7 @@ class Report::Operator all[name.to_s] ||= super end + #TODO: this should be inheritable by subclasses def self.all @@all_operators ||= {} end diff --git a/app/models/report/query_utils.rb b/app/models/report/query_utils.rb index 73cad7fafe..abbe04425e 100644 --- a/app/models/report/query_utils.rb +++ b/app/models/report/query_utils.rb @@ -22,23 +22,27 @@ module Report::QueryUtils end ## - # Graceful, internationalized quoted string. + # Creates a SQL fragment representing a collection/array. # # @see quote_string - # @param [Object] str String to quote/translate - # @return [Object] Quoted, translated version - def quoted_label(ident) - "'#{quote_string l(ident)}'" + # @param [#flatten] *values Ruby collection + # @return [String] SQL collection + def collection(*values) + if values.empty? + "" + else + "(#{values.flatten.map { |v| "'#{quote_string(v)}'" }.join ", "})" + end end ## - # Creates a SQL fragment representing a collection/array. + # Graceful, internationalized quoted string. # # @see quote_string - # @param [#flatten] *values Ruby collection - # @return [String] SQL collection - def collection(*values) - "(#{values.flatten.map { |v| "'#{quote_string(v)}'" }.join ", "})" + # @param [Object] str String to quote/translate + # @return [Object] Quoted, translated version + def quoted_label(ident) + "'#{quote_string l(ident)}'" end def quoted_date(date) @@ -84,6 +88,7 @@ module Report::QueryUtils # @return [String] Field name. def field_name_for(arg, default_table = nil) return 'NULL' unless arg + return field_name_for(arg.keys.first, default_table) if arg.is_a? Hash return arg if arg.is_a? String and arg =~ /\.| |\(.*\)/ return table_name_for(arg.first || default_table) + '.' << arg.last.to_s if arg.is_a? Array and arg.size == 2 return arg.to_s unless default_table @@ -97,10 +102,11 @@ module Report::QueryUtils # @param [Object] statement Not sanitized statement. # @return [String] Sanitized statement. def sanitize_sql_for_conditions(statement) - Report.send :sanitize_sql_for_conditions, statement + engine.send :sanitize_sql_for_conditions, statement end ## + # FIXME: This is redmine # Generates string representation for a currency. # # @see CostRate.clean_currency diff --git a/app/models/report/result.rb b/app/models/report/result.rb index b41b72b4ac..81e59ba9b2 100644 --- a/app/models/report/result.rb +++ b/app/models/report/result.rb @@ -41,11 +41,11 @@ module Report::Result fields.inject({}) { |hash, key| hash.merge key => entry.fields[key] } end # map group back to array, all fields with same key get grouped into one list - data.keys.map { |f| Report::Result.new data[f], f, type, important_fields } + data.keys.map { |f| engine::Result.new data[f], f, type, important_fields } end end # create a single result from that list - Report::Result.new list, {}, type, important_fields + engine::Result.new list, {}, type, important_fields end def inspect diff --git a/app/models/report/sql_statement.rb b/app/models/report/sql_statement.rb index 6757305f4a..3aded2e7ef 100644 --- a/app/models/report/sql_statement.rb +++ b/app/models/report/sql_statement.rb @@ -150,6 +150,11 @@ class Report::SqlStatement end end + def default_select(value = nil) + @default_select = value if value + @default_select ||= ["*"] + end + ## # @overload select # @return [Array] All fields/statements for select part @@ -165,7 +170,7 @@ class Report::SqlStatement # @param [Array, Hash, String, Symbol, SqlStatement] fields Fields to add to select part # @return [Array] All fields/statements for select part def select(*fields) - return(@select || ["*"]) if fields.empty? + return(@select || default_select) if fields.empty? returning(@select ||= []) do @sql = nil fields.each do |f| @@ -176,7 +181,7 @@ class Report::SqlStatement end when Hash then select f.map { |k,v| "#{field_name_for v} as #{field_name_for k}" } when String, Symbol then @select << field_name_for(f) - when Report::SqlStatement then @select << f.to_s + when engine::SqlStatement then @select << f.to_s else raise ArgumentError, "cannot handle #{f.inspect}" end end