lib/mini_sql/builder.rb in mini_sql-1.4.0 vs lib/mini_sql/builder.rb in mini_sql-1.5.0

- old
+ new

@@ -9,12 +9,17 @@ @connection = connection @count_variables = 1 @is_prepared = false end + def initialize_copy(_original_builder) + @args = @args.transform_values { |v| v.dup } + @sections = @sections.transform_values { |v| v.dup } + end + literals1 = - [:set, :where2, :where, :order_by, :left_join, :join, :select, :group_by].each do |k| + [:set, :where2, :where2_or, :where, :where_or, :order_by, :left_join, :join, :select, :group_by].each do |k| define_method k do |sql_part, *args| if Hash === args[0] @args.merge!(args[0]) else # convert simple params to hash args.each do |v| @@ -46,11 +51,11 @@ def sql_literal(literals) literals.each do |name, part_sql| if PREDEFINED_SQL_LITERALS.include?(name) raise "/*#{name}*/ is predefined, use method `.#{name}` instead `sql_literal`" end - @sections[name] = part_sql.is_a?(::MiniSql::Builder) ? part_sql.to_sql : part_sql + @sections[name] = part_sql.respond_to?(:to_sql) ? part_sql.to_sql : part_sql end self end [:query, :query_single, :query_hash, :query_array, :exec].each do |m| @@ -73,46 +78,58 @@ def to_sql(hash_args = nil) @connection.param_encoder.encode(parametrized_sql, union_parameters(hash_args)) end + def count(field = '*') + dup.select("count(#{field})").query_single.first + end + private def connection_switcher if @is_prepared @connection.prepared else @connection end end + WHERE_SECTIONS = [%i[where where_or], %i[where2 where2_or]] private def parametrized_sql sql = @sql.dup - @sections.each do |k, v| - joined = nil - case k - when :select - joined = (+"SELECT ") << v.join(" , ") - when :where, :where2 - joined = (+"WHERE ") << v.map { |c| (+"(") << c << ")" }.join(" AND ") - when :join - joined = v.map { |item| (+"JOIN ") << item }.join("\n") - when :left_join - joined = v.map { |item| (+"LEFT JOIN ") << item }.join("\n") - when :limit - joined = (+"LIMIT :mq_auto_limit") - when :offset - joined = (+"OFFSET :mq_auto_offset") - when :order_by - joined = (+"ORDER BY ") << v.join(" , ") - when :group_by - joined = (+"GROUP BY ") << v.join(" , ") - when :set - joined = (+"SET ") << v.join(" , ") - else # for sql_literal - joined = v + WHERE_SECTIONS.each do |section_and, section_or| + if (or_values = @sections.delete(section_or)) + @sections[section_and] ||= [] + @sections[section_and] << or_values.map { |c| "(#{c})" }.join(" OR ") end + end - unless sql.sub!("/*#{k}*/", joined) + @sections.each do |k, v| + joined = + case k + when :select + "SELECT #{v.join(" , ")}" + when :where, :where2 + "WHERE #{v.map { |c| "(#{c})" }.join(" AND ")}" + when :join + v.map { |item| "JOIN #{item}" }.join("\n") + when :left_join + v.map { |item| "LEFT JOIN #{item}" }.join("\n") + when :limit + "LIMIT :mq_auto_limit" + when :offset + "OFFSET :mq_auto_offset" + when :order_by + "ORDER BY #{v.join(" , ")}" + when :group_by + "GROUP BY #{v.join(" , ")}" + when :set + "SET #{v.join(" , ")}" + else # for sql_literal + v + end + + unless sql.gsub!("/*#{k}*/", joined) raise "The section for the /*#{k}*/ clause was not found!" end end sql