From 054b0103a8a833e643c954fb31b9a5d88e29968e Mon Sep 17 00:00:00 2001 From: Emilio Tagua Date: Thu, 28 May 2009 18:08:48 -0300 Subject: This should be performed by the engine, if it does not exists, then create SQLLiteral not Attribute. --- lib/arel/engines/sql/formatters.rb | 1 - 1 file changed, 1 deletion(-) (limited to 'lib/arel/engines') diff --git a/lib/arel/engines/sql/formatters.rb b/lib/arel/engines/sql/formatters.rb index ae80feb18e..22935ebff1 100644 --- a/lib/arel/engines/sql/formatters.rb +++ b/lib/arel/engines/sql/formatters.rb @@ -13,7 +13,6 @@ module Arel class SelectClause < Formatter def attribute(attribute) - # FIXME this should check that the column exists "#{quote_table_name(name_for(attribute.original_relation))}.#{quote_column_name(attribute.name)}" + (attribute.alias ? " AS #{quote(attribute.alias.to_s)}" : "") end -- cgit v1.2.3 From dc09a633c37ca0b214e4d1dd1572cdb9070fc38d Mon Sep 17 00:00:00 2001 From: Emilio Tagua Date: Thu, 28 May 2009 18:24:40 -0300 Subject: Don't quote the table if it isn't a table name. By doing this Arel supports using custom SQL FROM like: edges USE INDEX(unique_edge_index) --- lib/arel/engines/sql/formatters.rb | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'lib/arel/engines') diff --git a/lib/arel/engines/sql/formatters.rb b/lib/arel/engines/sql/formatters.rb index 22935ebff1..626803a887 100644 --- a/lib/arel/engines/sql/formatters.rb +++ b/lib/arel/engines/sql/formatters.rb @@ -91,8 +91,12 @@ module Arel end def table(table) - quote_table_name(table.name) + - (table.name != name_for(table) ? " AS " + quote_table_name(name_for(table)) : '') + if table.name =~ /\s/ + table.name + else + quote_table_name(table.name) + + (table.name != name_for(table) ? " AS " + quote_table_name(name_for(table)) : '') + end end end -- cgit v1.2.3 From c55226bac0cfac67081b01860baa61f3acbb2ca9 Mon Sep 17 00:00:00 2001 From: Emilio Tagua Date: Thu, 28 May 2009 18:41:20 -0300 Subject: Allow expressions on literal SQL fragments --- lib/arel/engines/sql/primitives.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'lib/arel/engines') diff --git a/lib/arel/engines/sql/primitives.rb b/lib/arel/engines/sql/primitives.rb index bb3bed78e6..a08ca11c12 100644 --- a/lib/arel/engines/sql/primitives.rb +++ b/lib/arel/engines/sql/primitives.rb @@ -3,10 +3,12 @@ module Arel def relation nil end - + def to_sql(formatter = nil) self end + + include Attribute::Expressions end class Attribute -- cgit v1.2.3 From 3e6ad6e5838d20c946d7a286cb34be12aae177ff Mon Sep 17 00:00:00 2001 From: Emilio Tagua Date: Wed, 10 Jun 2009 19:53:51 -0300 Subject: Allow strings as update assignments --- lib/arel/engines/sql/relations/writes.rb | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'lib/arel/engines') diff --git a/lib/arel/engines/sql/relations/writes.rb b/lib/arel/engines/sql/relations/writes.rb index f1a9bfd2ac..f7073654e9 100644 --- a/lib/arel/engines/sql/relations/writes.rb +++ b/lib/arel/engines/sql/relations/writes.rb @@ -31,9 +31,13 @@ module Arel protected def assignment_sql - assignments.collect do |attribute, value| - "#{engine.quote_column_name(attribute.name)} = #{attribute.format(value)}" - end.join(",\n") + if assignments.respond_to?(:collect) + assignments.collect do |attribute, value| + "#{engine.quote_column_name(attribute.name)} = #{attribute.format(value)}" + end.join(",\n") + else + assignments.value + end end end end -- cgit v1.2.3 From ae0c58fed1cd3aca1edd75a249fa99bc9571a8a3 Mon Sep 17 00:00:00 2001 From: Emilio Tagua Date: Tue, 23 Jun 2009 17:18:37 -0300 Subject: Build valid SQL query for SQLite3 and PostgreSQL when updating records with limited conditions --- lib/arel/engines/sql/relations/writes.rb | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) (limited to 'lib/arel/engines') diff --git a/lib/arel/engines/sql/relations/writes.rb b/lib/arel/engines/sql/relations/writes.rb index f7073654e9..471fceabd8 100644 --- a/lib/arel/engines/sql/relations/writes.rb +++ b/lib/arel/engines/sql/relations/writes.rb @@ -24,8 +24,7 @@ module Arel build_query \ "UPDATE #{table_sql} SET", assignment_sql, - ("WHERE #{wheres.collect(&:to_sql).join('\n\tAND ')}" unless wheres.blank? ), - ("LIMIT #{taken}" unless taken.blank? ) + build_update_conditions_sql end protected @@ -39,5 +38,22 @@ module Arel assignments.value end end + + def build_update_conditions_sql + conditions = "" + conditions << " WHERE #{wheres.collect(&:to_sql).join('\n\tAND ')}" unless wheres.blank? + conditions << " ORDER BY #{order_clauses.join(', ')}" unless orders.blank? + + unless taken.blank? + conditions << " LIMIT #{taken}" + + if engine.adapter_name != "MySQL" + quote_primary_key = engine.quote_column_name(table.name.classify.constantize.primary_key) + conditions = "WHERE #{quote_primary_key} IN (SELECT #{quote_primary_key} FROM #{engine.connection.quote_table_name table.name} #{conditions})" + end + end + + conditions + end end end -- cgit v1.2.3 From a9486193c8c6250d56bfb0258be50025f7f62f5e Mon Sep 17 00:00:00 2001 From: Emilio Tagua Date: Tue, 23 Jun 2009 17:37:10 -0300 Subject: Build valid SQL query when using PostreSQL with given order and DISTINCT ON clause. TODO: refactoring to clean up components. --- lib/arel/engines/sql/relations/relation.rb | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'lib/arel/engines') diff --git a/lib/arel/engines/sql/relations/relation.rb b/lib/arel/engines/sql/relations/relation.rb index 4cfb83a601..ed7f19ddbd 100644 --- a/lib/arel/engines/sql/relations/relation.rb +++ b/lib/arel/engines/sql/relations/relation.rb @@ -5,6 +5,26 @@ module Arel end def select_sql + if engine.adapter_name == "PostgreSQL" && !orders.blank? && using_distinct_on? + # PostgreSQL does not allow arbitrary ordering when using DISTINCT ON, so we work around this + # by wrapping the +sql+ string as a sub-select and ordering in that query. + order = order_clauses.join(', ').split(',').map { |s| s.strip }.reject(&:blank?) + order = order.zip((0...order.size).to_a).map { |s,i| "id_list.alias_#{i} #{'DESC' if s =~ /\bdesc$/i}" }.join(', ') + + query = build_query \ + "SELECT #{select_clauses.to_s}", + "FROM #{table_sql(Sql::TableReference.new(self))}", + (joins(self) unless joins(self).blank? ), + ("WHERE #{where_clauses.join("\n\tAND ")}" unless wheres.blank? ), + ("GROUP BY #{group_clauses.join(', ')}" unless groupings.blank? ) + + build_query \ + "SELECT * FROM (#{query}) AS id_list", + "ORDER BY #{order}", + ("LIMIT #{taken}" unless taken.blank? ), + ("OFFSET #{skipped}" unless skipped.blank? ) + + else build_query \ "SELECT #{select_clauses.join(', ')}", "FROM #{table_sql(Sql::TableReference.new(self))}", @@ -14,6 +34,7 @@ module Arel ("ORDER BY #{order_clauses.join(', ')}" unless orders.blank? ), ("LIMIT #{taken}" unless taken.blank? ), ("OFFSET #{skipped}" unless skipped.blank? ) + end end def inclusion_predicate_sql @@ -46,5 +67,8 @@ module Arel orders.collect { |o| o.to_sql(Sql::OrderClause.new(self)) } end + def using_distinct_on? + select_clauses.any? { |x| x =~ /DISTINCT ON/ } + end end end -- cgit v1.2.3 From 97811698ab0e68b33fbf3067c3764e385dd75d53 Mon Sep 17 00:00:00 2001 From: Emilio Tagua Date: Tue, 23 Jun 2009 19:45:14 -0300 Subject: If the class or method isn't defined use "id" as primary_key. --- lib/arel/engines/sql/relations/writes.rb | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'lib/arel/engines') diff --git a/lib/arel/engines/sql/relations/writes.rb b/lib/arel/engines/sql/relations/writes.rb index 471fceabd8..b90d380c64 100644 --- a/lib/arel/engines/sql/relations/writes.rb +++ b/lib/arel/engines/sql/relations/writes.rb @@ -48,7 +48,12 @@ module Arel conditions << " LIMIT #{taken}" if engine.adapter_name != "MySQL" - quote_primary_key = engine.quote_column_name(table.name.classify.constantize.primary_key) + begin + quote_primary_key = engine.quote_column_name(table.name.classify.constantize.primary_key) + rescue NameError + quote_primary_key = engine.quote_column_name("id") + end + conditions = "WHERE #{quote_primary_key} IN (SELECT #{quote_primary_key} FROM #{engine.connection.quote_table_name table.name} #{conditions})" end end -- cgit v1.2.3 From 808b9e90a38c6c19e109da8eb5f2a264fd780d9a Mon Sep 17 00:00:00 2001 From: Emilio Tagua Date: Wed, 1 Jul 2009 20:29:33 -0300 Subject: Allow SQL strings to insert query. Insert should better return engine's result. --- lib/arel/engines/sql/relations/writes.rb | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'lib/arel/engines') diff --git a/lib/arel/engines/sql/relations/writes.rb b/lib/arel/engines/sql/relations/writes.rb index b90d380c64..d648a54d91 100644 --- a/lib/arel/engines/sql/relations/writes.rb +++ b/lib/arel/engines/sql/relations/writes.rb @@ -11,11 +11,17 @@ module Arel class Insert < Compound def to_sql(formatter = nil) + insertion_attributes_values_sql = if record.is_a?(Value) + record.value + else + build_query "(#{record.keys.collect { |key| engine.quote_column_name(key.name) }.join(', ')})", + "VALUES (#{record.collect { |key, value| key.format(value) }.join(', ')})" + end + build_query \ "INSERT", "INTO #{table_sql}", - "(#{record.keys.collect { |key| engine.quote_column_name(key.name) }.join(', ')})", - "VALUES (#{record.collect { |key, value| key.format(value) }.join(', ')})" + insertion_attributes_values_sql end end @@ -28,7 +34,6 @@ module Arel end protected - def assignment_sql if assignments.respond_to?(:collect) assignments.collect do |attribute, value| -- cgit v1.2.3 From 5dcbca25cef8e8f5809913977cfeb4366c8b44d0 Mon Sep 17 00:00:00 2001 From: Emilio Tagua Date: Fri, 14 Aug 2009 10:49:15 -0300 Subject: Allow joining a StringJoin with another join relation. --- lib/arel/engines/sql/relations/operations/join.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/arel/engines') diff --git a/lib/arel/engines/sql/relations/operations/join.rb b/lib/arel/engines/sql/relations/operations/join.rb index 7c5e13510a..a3aaaa163b 100644 --- a/lib/arel/engines/sql/relations/operations/join.rb +++ b/lib/arel/engines/sql/relations/operations/join.rb @@ -26,8 +26,8 @@ module Arel end class StringJoin < Join - def joins(_, __ = nil) - relation2 + def joins(environment, formatter = Sql::TableReference.new(environment)) + [relation1.joins(environment), relation2].compact.join(" ") end end end -- cgit v1.2.3