mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Merge remote branch 'miloops/master' into miloops
Conflicts: spec/connections/mysql_connection.rb spec/connections/postgresql_connection.rb spec/connections/sqlite3_connection.rb
This commit is contained in:
commit
58920bc508
69 changed files with 203 additions and 122 deletions
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
[submodule "vendor/rails"]
|
||||
path = vendor/rails
|
||||
url = git://github.com/rails/rails.git
|
|
@ -15,20 +15,20 @@ The long term goal, following both LINQ and DataMapper, is to have Arel adapt to
|
|||
Generating a query with ARel is simple. For example, in order to produce
|
||||
|
||||
SELECT * FROM users
|
||||
|
||||
|
||||
you construct a table relation and convert it to sql:
|
||||
|
||||
users = Table(:users)
|
||||
users.to_sql
|
||||
|
||||
|
||||
In fact, you will probably never call `#to_sql`. Rather, you'll work with data from the table directly. You can iterate through all rows in the `users` table like this:
|
||||
|
||||
users.each { |user| ... }
|
||||
|
||||
|
||||
In other words, Arel relations implement Ruby's Enumerable interface. Let's have a look at a concrete example:
|
||||
|
||||
users.first # => { users[:id] => 1, users[:name] => 'bob' }
|
||||
|
||||
|
||||
As you can see, Arel converts the rows from the database into a hash, the values of which are sublimated to the appropriate Ruby primitive (integers, strings, and so forth).
|
||||
|
||||
### More Sophisticated <strike>Queries</strike> Relations ###
|
||||
|
@ -43,7 +43,7 @@ First is the 'restriction' operator, `where`:
|
|||
What would, in SQL, be part of the `SELECT` clause is called in Arel a `projection`:
|
||||
|
||||
users.project(users[:id]) # => SELECT users.id FROM users
|
||||
|
||||
|
||||
Joins resemble SQL strongly:
|
||||
|
||||
users.join(photos).on(users[:id].eq(photos[:user_id]))
|
||||
|
@ -53,7 +53,7 @@ What are called `LIMIT` and `OFFSET` in SQL are called `take` and `skip` in Arel
|
|||
|
||||
users.take(5) # => SELECT * FROM users LIMIT 5
|
||||
users.skip(4) # => SELECT * FROM users OFFSET 4
|
||||
|
||||
|
||||
`GROUP BY` is called `group`:
|
||||
|
||||
users.group(users[:name]) # => SELECT * FROM users GROUP BY name
|
||||
|
@ -68,7 +68,7 @@ The best property of the Relational Algebra is its "composability", or closure u
|
|||
All operators are chainable in this way, and they are chainable any number of times, in any order.
|
||||
|
||||
users.where(users[:name].eq('bob')).where(users[:age].lt(25))
|
||||
|
||||
|
||||
Of course, many of the operators take multiple arguments, so the last example can be written more tersely:
|
||||
|
||||
users.where(users[:name].eq('bob'), users[:age].lt(25))
|
||||
|
@ -76,7 +76,7 @@ Of course, many of the operators take multiple arguments, so the last example ca
|
|||
The `OR` operator is not yet supported. It will work like this:
|
||||
|
||||
users.where(users[:name].eq('bob').or(users[:age].lt(25)))
|
||||
|
||||
|
||||
The `AND` operator will behave similarly.
|
||||
|
||||
Finally, most operations take a block form. For example:
|
||||
|
@ -96,7 +96,7 @@ The examples above are fairly simple and other libraries match or come close to
|
|||
Where Arel really shines in its ability to handle complex joins and aggregations. As a first example, let's consider an "adjacency list", a tree represented in a table. Suppose we have a table `comments`, representing a threaded discussion:
|
||||
|
||||
comments = Table(:comments)
|
||||
|
||||
|
||||
And this table has the following attributes:
|
||||
|
||||
comments.attributes # => [comments[:id], comments[:body], comments[:parent_id]]
|
||||
|
@ -107,23 +107,23 @@ The `parent_id` column is a foreign key from the `comments` table to itself. Now
|
|||
comments_with_replies = \
|
||||
comments.join(replies).on(replies[:parent_id].eq(comments[:id]))
|
||||
# => SELECT * FROM comments INNER JOIN comments AS comments_2 WHERE comments_2.parent_id = comments.id
|
||||
|
||||
|
||||
The call to `#alias` is actually optional: Arel will always produce a unique name for every table joined in the relation, and it will always do so deterministically to exploit query caching. Explicit aliasing is more common, however. When you want to extract specific slices of data, aliased tables are a necessity. For example to get just certain columns from the row, treat a row like a hash:
|
||||
|
||||
comments_with_replies.first[replies[:body]]
|
||||
|
||||
|
||||
This will return the first comment's reply's body.
|
||||
|
||||
If you don't need to extract the data later (for example, you're simply doing a join to find comments that have replies, you don't care what the content of the replies are), the block form may be preferable:
|
||||
|
||||
comments.join(comments) { |comments, replies| replies[:parent_id].eq(comments[:id]) }
|
||||
# => SELECT * FROM comments INNER JOIN comments AS comments_2 WHERE comments_2.parent_id = comments.id
|
||||
|
||||
|
||||
Note that you do NOT want to do something like:
|
||||
|
||||
comments.join(comments, comments[:parent_id].eq(comments[:id]))
|
||||
# => SELECT * FROM comments INNER JOIN comments AS comments_2 WHERE comments.parent_id = comments.id
|
||||
|
||||
|
||||
This does NOT have the same meaning as the previous query, since the comments[:parent_id] reference is effectively ambiguous.
|
||||
|
||||
#### Complex Aggregations ####
|
||||
|
@ -135,24 +135,24 @@ The easiest way to introduce this is in SQL. Your task is to get all users and t
|
|||
SELECT count(*)
|
||||
FROM photos
|
||||
GROUP BY user_id
|
||||
|
||||
|
||||
Now, we'd like to join this with the user table. Naively, you might try to do this:
|
||||
|
||||
SELECT users.*, count(photos.id)
|
||||
FROM users
|
||||
LEFT OUTER JOIN photos
|
||||
ON users.id = photos.id
|
||||
ON users.id = photos.user_id
|
||||
GROUP BY photos.user_id
|
||||
|
||||
|
||||
Of course, this has a slightly different meaning than our intended query. This is actually a fairly advanced topic in SQL so let's see why this doesn't work *step by step*. Suppose we have these records in our `users` table:
|
||||
|
||||
mysql> select * from users;
|
||||
+------+--------+
|
||||
| id | name |
|
||||
+------+--------+
|
||||
| 1 | hai |
|
||||
| 2 | bai |
|
||||
| 3 | dumpty |
|
||||
| 1 | hai |
|
||||
| 2 | bai |
|
||||
| 3 | dumpty |
|
||||
+------+--------+
|
||||
|
||||
And these in the photos table:
|
||||
|
@ -161,19 +161,19 @@ And these in the photos table:
|
|||
+------+---------+-----------+
|
||||
| id | user_id | camera_id |
|
||||
+------+---------+-----------+
|
||||
| 1 | 1 | 1 |
|
||||
| 2 | 1 | 1 |
|
||||
| 3 | 1 | 1 |
|
||||
| 1 | 1 | 1 |
|
||||
| 2 | 1 | 1 |
|
||||
| 3 | 1 | 1 |
|
||||
+------+---------+-----------+
|
||||
|
||||
|
||||
If we perform the above, incorrect query, we get the following:
|
||||
|
||||
mysql> select users.*, count(photos.id) from users left outer join photos on users.id = photos.user_id limit 3 group by user_id;
|
||||
+------+------+------------------+
|
||||
| id | name | count(photos.id) |
|
||||
+------+------+------------------+
|
||||
| 2 | bai | 0 |
|
||||
| 1 | hai | 3 |
|
||||
| 2 | bai | 0 |
|
||||
| 1 | hai | 3 |
|
||||
+------+------+------------------+
|
||||
|
||||
As you can see, we're completely missing data for user with id 3. `dumpty` has no photos, neither does `bai`. But strangely `bai` appeared and `dumpty` didn't! The reason is that the `GROUP BY` clause is aggregating on both tables, not just the `photos` table. All users without photos have a `photos.id` of `null` (thanks to the left outer join). These are rolled up together and an arbitrary user wins. In this case, `bai` not `dumpty`.
|
||||
|
@ -181,4 +181,4 @@ As you can see, we're completely missing data for user with id 3. `dumpty` has n
|
|||
SELECT users.*, photos_aggregation.cnt
|
||||
FROM users
|
||||
LEFT OUTER JOIN (SELECT user_id, count(*) as cnt FROM photos GROUP BY user_id) AS photos_aggregation
|
||||
ON photos_aggregation.user_id = users.id
|
||||
ON photos_aggregation.user_id = users.id
|
||||
|
|
2
Rakefile
2
Rakefile
|
@ -40,6 +40,8 @@ namespace :spec do
|
|||
for adapter in %w[mysql sqlite3 postgresql]
|
||||
desc "Run specs with the #{adapter} database adapter"
|
||||
Spec::Rake::SpecTask.new(adapter) do |t|
|
||||
t.libs << "#{File.dirname(__FILE__)}/vendor/rails/activerecord/lib"
|
||||
t.libs << "#{File.dirname(__FILE__)}/spec"
|
||||
t.spec_files =
|
||||
["spec/connections/#{adapter}_connection.rb"] +
|
||||
["spec/schemas/#{adapter}_schema.rb"] +
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
||||
require 'active_support/inflector'
|
||||
require 'active_support/core_ext/module/delegation'
|
||||
require 'active_support/core_ext/class/attribute_accessors'
|
||||
|
||||
require 'rubygems'
|
||||
require 'activesupport'
|
||||
require 'activerecord'
|
||||
require 'active_record'
|
||||
require 'active_record/connection_adapters/abstract/quoting'
|
||||
|
||||
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
||||
require 'arel/algebra'
|
||||
require 'arel/engines'
|
||||
require 'arel/session'
|
||||
|
|
BIN
lib/arel/.DS_Store
vendored
BIN
lib/arel/.DS_Store
vendored
Binary file not shown.
|
@ -110,7 +110,7 @@ module Arel
|
|||
private
|
||||
def matching_attributes(attribute)
|
||||
(@matching_attributes ||= attributes.inject({}) do |hash, a|
|
||||
(hash[a.root] ||= []) << a
|
||||
(hash[a.is_a?(Value) ? a.value : a.root] ||= []) << a
|
||||
hash
|
||||
end)[attribute.root] || []
|
||||
end
|
||||
|
|
|
@ -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
|
||||
|
@ -92,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
|
||||
|
||||
|
|
|
@ -7,6 +7,8 @@ module Arel
|
|||
def to_sql(formatter = nil)
|
||||
self
|
||||
end
|
||||
|
||||
include Attribute::Expressions
|
||||
end
|
||||
|
||||
class Attribute
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
@ -24,16 +30,40 @@ 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
|
||||
|
||||
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
|
||||
|
||||
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"
|
||||
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
|
||||
|
||||
conditions
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -24,7 +24,6 @@ module Arel
|
|||
module CRUD
|
||||
def create(insert)
|
||||
insert.call
|
||||
insert
|
||||
end
|
||||
|
||||
def read(select)
|
||||
|
@ -35,12 +34,10 @@ module Arel
|
|||
|
||||
def update(update)
|
||||
update.call
|
||||
update
|
||||
end
|
||||
|
||||
def delete(delete)
|
||||
delete.call
|
||||
delete
|
||||
end
|
||||
end
|
||||
include CRUD
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
require File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'spec_helper')
|
||||
require 'spec_helper'
|
||||
|
||||
module Arel
|
||||
describe Binary do
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
require File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'spec_helper')
|
||||
require 'spec_helper'
|
||||
|
||||
module Arel
|
||||
describe Equality do
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
require File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'spec_helper')
|
||||
require 'spec_helper'
|
||||
|
||||
module Arel
|
||||
describe In do
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
require File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'spec_helper')
|
||||
require 'spec_helper'
|
||||
|
||||
module Arel
|
||||
describe Attribute do
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
require File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'spec_helper')
|
||||
require 'spec_helper'
|
||||
|
||||
module Arel
|
||||
describe Expression do
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
require File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'spec_helper')
|
||||
require 'spec_helper'
|
||||
|
||||
module Arel
|
||||
describe Value do
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
require File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'spec_helper')
|
||||
require 'spec_helper'
|
||||
|
||||
module Arel
|
||||
describe Alias do
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
require File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'spec_helper')
|
||||
require 'spec_helper'
|
||||
|
||||
module Arel
|
||||
describe Deletion do
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
require File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'spec_helper')
|
||||
require 'spec_helper'
|
||||
|
||||
module Arel
|
||||
describe Group do
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
require File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'spec_helper')
|
||||
require 'spec_helper'
|
||||
|
||||
module Arel
|
||||
describe Insert do
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
require File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'spec_helper')
|
||||
require 'spec_helper'
|
||||
|
||||
module Arel
|
||||
describe Join do
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
require File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'spec_helper')
|
||||
require 'spec_helper'
|
||||
|
||||
module Arel
|
||||
describe Order do
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
require File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'spec_helper')
|
||||
require 'spec_helper'
|
||||
|
||||
module Arel
|
||||
describe Project do
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
require File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'spec_helper')
|
||||
require 'spec_helper'
|
||||
|
||||
module Arel
|
||||
describe Relation do
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
require File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'spec_helper')
|
||||
require 'spec_helper'
|
||||
|
||||
module Arel
|
||||
describe Skip do
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
require File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'spec_helper')
|
||||
require 'spec_helper'
|
||||
|
||||
module Arel
|
||||
describe Table do
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
require File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'spec_helper')
|
||||
require 'spec_helper'
|
||||
|
||||
module Arel
|
||||
describe Take do
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
require File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'spec_helper')
|
||||
require 'spec_helper'
|
||||
|
||||
module Arel
|
||||
describe Update do
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
require File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'spec_helper')
|
||||
require 'spec_helper'
|
||||
|
||||
module Arel
|
||||
describe Where do
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
require File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'spec_helper')
|
||||
require 'spec_helper'
|
||||
|
||||
module Arel
|
||||
describe Session do
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
require File.join(File.dirname(__FILE__), '..', '..', '..', '..', '..', 'spec_helper')
|
||||
require 'spec_helper'
|
||||
|
||||
module Arel
|
||||
describe Join do
|
||||
|
@ -10,9 +10,8 @@ module Arel
|
|||
], [:id, :name])
|
||||
@photos = Table.new(:photos)
|
||||
@photos.delete
|
||||
@photos \
|
||||
.insert(@photos[:id] => 1, @photos[:user_id] => 1, @photos[:camera_id] => 6) \
|
||||
.insert(@photos[:id] => 2, @photos[:user_id] => 2, @photos[:camera_id] => 42)
|
||||
@photos.insert(@photos[:id] => 1, @photos[:user_id] => 1, @photos[:camera_id] => 6)
|
||||
@photos.insert(@photos[:id] => 2, @photos[:user_id] => 2, @photos[:camera_id] => 42)
|
||||
end
|
||||
|
||||
describe 'when the in memory relation is on the left' do
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
require File.join(File.dirname(__FILE__), '..', '..', '..', '..', '..', 'spec_helper')
|
||||
require 'spec_helper'
|
||||
|
||||
module Arel
|
||||
describe Array do
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
require File.join(File.dirname(__FILE__), '..', '..', '..', '..', '..', 'spec_helper')
|
||||
require 'spec_helper'
|
||||
|
||||
module Arel
|
||||
describe Insert do
|
||||
|
@ -14,13 +14,13 @@ module Arel
|
|||
it "manufactures an array of hashes of attributes to values" do
|
||||
@relation \
|
||||
.insert(@relation[:id] => 4, @relation[:name] => 'guinea fowl') \
|
||||
.let do |relation|
|
||||
relation.call.should == [
|
||||
Row.new(relation, [1, 'duck']),
|
||||
Row.new(relation, [2, 'duck']),
|
||||
Row.new(relation, [3, 'goose']),
|
||||
Row.new(relation, [4, 'guinea fowl'])
|
||||
]
|
||||
do |relation|
|
||||
relation.should == [
|
||||
Row.new(relation, [1, 'duck']),
|
||||
Row.new(relation, [2, 'duck']),
|
||||
Row.new(relation, [3, 'goose']),
|
||||
Row.new(relation, [4, 'guinea fowl'])
|
||||
]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
require File.join(File.dirname(__FILE__), '..', '..', '..', '..', '..', 'spec_helper')
|
||||
require 'spec_helper'
|
||||
|
||||
module Arel
|
||||
describe Join do
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
require File.join(File.dirname(__FILE__), '..', '..', '..', '..', '..', 'spec_helper')
|
||||
require 'spec_helper'
|
||||
|
||||
module Arel
|
||||
describe Order do
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
require File.join(File.dirname(__FILE__), '..', '..', '..', '..', '..', 'spec_helper')
|
||||
require 'spec_helper'
|
||||
|
||||
module Arel
|
||||
describe Project do
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
require File.join(File.dirname(__FILE__), '..', '..', '..', '..', '..', 'spec_helper')
|
||||
require 'spec_helper'
|
||||
|
||||
module Arel
|
||||
describe Skip do
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
require File.join(File.dirname(__FILE__), '..', '..', '..', '..', '..', 'spec_helper')
|
||||
require 'spec_helper'
|
||||
|
||||
module Arel
|
||||
describe Take do
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
require File.join(File.dirname(__FILE__), '..', '..', '..', '..', '..', 'spec_helper')
|
||||
require 'spec_helper'
|
||||
|
||||
module Arel
|
||||
describe Where do
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
require File.join(File.dirname(__FILE__), '..', '..', '..', '..', '..', 'spec_helper')
|
||||
require 'spec_helper'
|
||||
|
||||
module Arel
|
||||
describe Join do
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
require File.join(File.dirname(__FILE__), '..', '..', '..', '..', '..', 'spec_helper')
|
||||
require 'spec_helper'
|
||||
|
||||
module Arel
|
||||
describe Join do
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
require File.join(File.dirname(__FILE__), '..', '..', '..', '..', '..', 'spec_helper')
|
||||
require 'spec_helper'
|
||||
|
||||
module Arel
|
||||
describe Join do
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
require File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'spec_helper')
|
||||
require 'spec_helper'
|
||||
|
||||
module Arel
|
||||
describe Sql::Engine do
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
require File.join(File.dirname(__FILE__), '..', '..', '..', '..', '..', 'spec_helper')
|
||||
require 'spec_helper'
|
||||
|
||||
module Arel
|
||||
describe Binary do
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
require File.join(File.dirname(__FILE__), '..', '..', '..', '..', '..', 'spec_helper')
|
||||
require 'spec_helper'
|
||||
|
||||
module Arel
|
||||
describe Equality do
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
require File.join(File.dirname(__FILE__), '..', '..', '..', '..', '..', 'spec_helper')
|
||||
require 'spec_helper'
|
||||
|
||||
module Arel
|
||||
describe In do
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
require File.join(File.dirname(__FILE__), '..', '..', '..', '..', '..', 'spec_helper')
|
||||
require 'spec_helper'
|
||||
|
||||
module Arel
|
||||
describe Predicate do
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
require File.join(File.dirname(__FILE__), '..', '..', '..', '..', '..', 'spec_helper')
|
||||
require 'spec_helper'
|
||||
|
||||
module Arel
|
||||
describe Attribute do
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
require File.join(File.dirname(__FILE__), '..', '..', '..', '..', '..', 'spec_helper')
|
||||
require 'spec_helper'
|
||||
|
||||
module Arel
|
||||
describe Expression do
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
require File.join(File.dirname(__FILE__), '..', '..', '..', '..', '..', 'spec_helper')
|
||||
require 'spec_helper'
|
||||
|
||||
module Arel
|
||||
describe SqlLiteral do
|
||||
|
@ -18,6 +18,18 @@ module Arel
|
|||
sql.should be_like(%Q{SELECT COUNT(*) AS count_id FROM "users"})
|
||||
end
|
||||
end
|
||||
|
||||
it "manufactures expressions on literal SQL fragment" do
|
||||
sql = @relation.project(SqlLiteral.new("2 * credit_limit").sum).to_sql
|
||||
|
||||
adapter_is :mysql do
|
||||
sql.should be_like(%Q{SELECT SUM(2 * credit_limit) AS sum_id FROM `users`})
|
||||
end
|
||||
|
||||
adapter_is_not :mysql do
|
||||
sql.should be_like(%Q{SELECT SUM(2 * credit_limit) AS sum_id FROM "users"})
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
require File.join(File.dirname(__FILE__), '..', '..', '..', '..', '..', 'spec_helper')
|
||||
require 'spec_helper'
|
||||
|
||||
module Arel
|
||||
describe Value do
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
require File.join(File.dirname(__FILE__), '..', '..', '..', '..', '..', 'spec_helper')
|
||||
require 'spec_helper'
|
||||
|
||||
module Arel
|
||||
describe Alias do
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
require File.join(File.dirname(__FILE__), '..', '..', '..', '..', '..', 'spec_helper')
|
||||
require 'spec_helper'
|
||||
|
||||
module Arel
|
||||
describe Deletion do
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
require File.join(File.dirname(__FILE__), '..', '..', '..', '..', '..', 'spec_helper')
|
||||
require 'spec_helper'
|
||||
|
||||
module Arel
|
||||
describe Group do
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
require File.join(File.dirname(__FILE__), '..', '..', '..', '..', '..', 'spec_helper')
|
||||
require 'spec_helper'
|
||||
|
||||
module Arel
|
||||
describe Insert do
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
require File.join(File.dirname(__FILE__), '..', '..', '..', '..', '..', 'spec_helper')
|
||||
require 'spec_helper'
|
||||
|
||||
module Arel
|
||||
describe Join do
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
require File.join(File.dirname(__FILE__), '..', '..', '..', '..', '..', 'spec_helper')
|
||||
require 'spec_helper'
|
||||
|
||||
module Arel
|
||||
describe Order do
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
require File.join(File.dirname(__FILE__), '..', '..', '..', '..', '..', 'spec_helper')
|
||||
require 'spec_helper'
|
||||
|
||||
module Arel
|
||||
describe Project do
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
require File.join(File.dirname(__FILE__), '..', '..', '..', '..', '..', 'spec_helper')
|
||||
require 'spec_helper'
|
||||
|
||||
module Arel
|
||||
describe Skip do
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
require File.join(File.dirname(__FILE__), '..', '..', '..', '..', '..', 'spec_helper')
|
||||
require 'spec_helper'
|
||||
|
||||
module Arel
|
||||
describe Table do
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
require File.join(File.dirname(__FILE__), '..', '..', '..', '..', '..', 'spec_helper')
|
||||
require 'spec_helper'
|
||||
|
||||
module Arel
|
||||
describe Take do
|
||||
|
|
|
@ -1,4 +1,10 @@
|
|||
require File.join(File.dirname(__FILE__), '..', '..', '..', '..', '..', 'spec_helper')
|
||||
require 'spec_helper'
|
||||
|
||||
class User
|
||||
def self.primary_key
|
||||
"id"
|
||||
end
|
||||
end
|
||||
|
||||
module Arel
|
||||
describe Update do
|
||||
|
@ -45,17 +51,17 @@ module Arel
|
|||
|
||||
adapter_is :sqlite3 do
|
||||
sql.should be_like(%Q{
|
||||
UPDATE "users"
|
||||
SET "name" = 'nick'
|
||||
LIMIT 1
|
||||
UPDATE "users" SET
|
||||
"name" = 'nick'
|
||||
WHERE "id" IN (SELECT "id" FROM "users" LIMIT 1)
|
||||
})
|
||||
end
|
||||
|
||||
adapter_is :postgresql do
|
||||
sql.should be_like(%Q{
|
||||
UPDATE "users"
|
||||
SET "name" = E'nick'
|
||||
LIMIT 1
|
||||
UPDATE "users" SET
|
||||
"name" = E'nick'
|
||||
WHERE "id" IN (SELECT "id" FROM "users" LIMIT 1)
|
||||
})
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
require File.join(File.dirname(__FILE__), '..', '..', '..', '..', '..', 'spec_helper')
|
||||
require 'spec_helper'
|
||||
|
||||
module Arel
|
||||
describe Where do
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
require "rubygems"
|
||||
require "activerecord"
|
||||
puts "Using native MySQL"
|
||||
require "active_record"
|
||||
require 'logger'
|
||||
|
||||
ActiveRecord::Base.logger = Logger.new("debug.log")
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
require "rubygems"
|
||||
require "activerecord"
|
||||
puts "Using native PostgreSQL"
|
||||
require "active_record"
|
||||
require 'logger'
|
||||
|
||||
ActiveRecord::Base.logger = Logger.new("debug.log")
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
require "rubygems"
|
||||
require "activerecord"
|
||||
puts "Using native SQLite3"
|
||||
require "active_record"
|
||||
require 'logger'
|
||||
|
||||
ActiveRecord::Base.logger = Logger.new("debug.log")
|
||||
|
||||
|
@ -16,6 +16,7 @@ ActiveRecord::Base.configurations = {
|
|||
|
||||
unless File.exist?(db_file)
|
||||
puts "SQLite3 database not found at #{db_file}. Rebuilding it."
|
||||
require 'fileutils'
|
||||
FileUtils.mkdir_p(File.dirname(db_file))
|
||||
sqlite_command = %Q{sqlite3 "#{db_file}" "create table a (a integer); drop table a;"}
|
||||
puts "Executing '#{sqlite_command}'"
|
||||
|
|
1
vendor/rails
vendored
Submodule
1
vendor/rails
vendored
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit 181cd109d9812d371e2d554a4846f0b2b25b1690
|
Loading…
Reference in a new issue