datamapper 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +31 -1
- data/MIT-LICENSE +1 -1
- data/README +9 -1
- data/example.rb +23 -15
- data/lib/data_mapper.rb +5 -0
- data/lib/data_mapper/adapters/abstract_adapter.rb +9 -207
- data/lib/data_mapper/adapters/mysql_adapter.rb +132 -108
- data/lib/data_mapper/adapters/postgresql_adapter.rb +242 -0
- data/lib/data_mapper/adapters/sql/coersion.rb +74 -0
- data/lib/data_mapper/adapters/sql/commands/advanced_load_command.rb +140 -0
- data/lib/data_mapper/adapters/sql/commands/conditions.rb +161 -0
- data/lib/data_mapper/adapters/sql/commands/delete_command.rb +113 -0
- data/lib/data_mapper/adapters/sql/commands/load_command.rb +296 -0
- data/lib/data_mapper/adapters/sql/commands/save_command.rb +141 -0
- data/lib/data_mapper/adapters/sql/commands/table_exists_command.rb +33 -0
- data/lib/data_mapper/adapters/sql/mappings/column.rb +91 -0
- data/lib/data_mapper/adapters/sql/mappings/schema.rb +30 -0
- data/lib/data_mapper/adapters/sql/mappings/table.rb +143 -0
- data/lib/data_mapper/adapters/sql/quoting.rb +38 -0
- data/lib/data_mapper/adapters/sql_adapter.rb +163 -0
- data/lib/data_mapper/adapters/sqlite3_adapter.rb +155 -116
- data/lib/data_mapper/associations.rb +2 -0
- data/lib/data_mapper/associations/advanced_has_many_association.rb +55 -0
- data/lib/data_mapper/associations/belongs_to_association.rb +2 -2
- data/lib/data_mapper/associations/has_many_association.rb +3 -3
- data/lib/data_mapper/associations/has_one_association.rb +2 -2
- data/lib/data_mapper/base.rb +30 -11
- data/lib/data_mapper/callbacks.rb +4 -1
- data/lib/data_mapper/database.rb +8 -41
- data/lib/data_mapper/identity_map.rb +23 -3
- data/lib/data_mapper/session.rb +34 -186
- data/lib/data_mapper/{extensions → support}/active_record_impersonation.rb +16 -12
- data/lib/data_mapper/support/blank.rb +35 -0
- data/lib/data_mapper/support/connection_pool.rb +2 -1
- data/lib/data_mapper/support/string.rb +27 -0
- data/lib/data_mapper/support/struct.rb +26 -0
- data/lib/data_mapper/validations/unique_validator.rb +1 -3
- data/lib/data_mapper/validations/validation_helper.rb +1 -1
- data/performance.rb +24 -7
- data/profile_data_mapper.rb +24 -2
- data/rakefile.rb +2 -2
- data/spec/basic_finder.rb +2 -2
- data/spec/belongs_to.rb +1 -1
- data/spec/delete_command_spec.rb +9 -0
- data/spec/fixtures/zoos.yaml +4 -0
- data/spec/has_many.rb +1 -1
- data/spec/load_command_spec.rb +44 -0
- data/spec/models/zoo.rb +2 -0
- data/spec/save_command_spec.rb +13 -0
- data/spec/spec_helper.rb +10 -1
- data/spec/support/string_spec.rb +7 -0
- data/spec/validates_confirmation_of.rb +1 -1
- data/spec/validates_format_of.rb +1 -1
- data/spec/validates_length_of.rb +1 -1
- data/spec/validations.rb +1 -1
- metadata +23 -20
- data/lib/data_mapper/extensions/callback_helpers.rb +0 -35
- data/lib/data_mapper/loaded_set.rb +0 -45
- data/lib/data_mapper/mappings/column.rb +0 -78
- data/lib/data_mapper/mappings/schema.rb +0 -28
- data/lib/data_mapper/mappings/table.rb +0 -99
- data/lib/data_mapper/queries/conditions.rb +0 -141
- data/lib/data_mapper/queries/connection.rb +0 -34
- data/lib/data_mapper/queries/create_table_statement.rb +0 -38
- data/lib/data_mapper/queries/delete_statement.rb +0 -17
- data/lib/data_mapper/queries/drop_table_statement.rb +0 -17
- data/lib/data_mapper/queries/insert_statement.rb +0 -29
- data/lib/data_mapper/queries/reader.rb +0 -42
- data/lib/data_mapper/queries/result.rb +0 -19
- data/lib/data_mapper/queries/select_statement.rb +0 -103
- data/lib/data_mapper/queries/table_exists_statement.rb +0 -17
- data/lib/data_mapper/queries/truncate_table_statement.rb +0 -17
- data/lib/data_mapper/queries/update_statement.rb +0 -25
@@ -1,141 +0,0 @@
|
|
1
|
-
module DataMapper
|
2
|
-
module Queries
|
3
|
-
|
4
|
-
class Conditions
|
5
|
-
|
6
|
-
def initialize(database, options)
|
7
|
-
@database, @options = database, options
|
8
|
-
@has_id = false
|
9
|
-
end
|
10
|
-
|
11
|
-
class NormalizationError < StandardError
|
12
|
-
|
13
|
-
attr_reader :inner_error
|
14
|
-
|
15
|
-
def initialize(clause, inner_error = nil)
|
16
|
-
@clause = clause
|
17
|
-
@inner_error = inner_error
|
18
|
-
|
19
|
-
message = "Failed to normalize clause: #{clause.inspect}"
|
20
|
-
message << ", Error: #{inner_error.inspect}" unless inner_error.nil?
|
21
|
-
|
22
|
-
super(message)
|
23
|
-
end
|
24
|
-
|
25
|
-
end
|
26
|
-
|
27
|
-
def normalize(clause, collector)
|
28
|
-
case clause
|
29
|
-
when Hash then
|
30
|
-
clause.each_pair do |k,v|
|
31
|
-
if k.kind_of?(Symbol::Operator)
|
32
|
-
if k.type == :select
|
33
|
-
k.options[:class] ||= @options[:class]
|
34
|
-
|
35
|
-
k.options[:select] ||= if k.value.to_s == @database[k.options[:class]].default_foreign_key
|
36
|
-
@database[k.options[:class]].key.column_name
|
37
|
-
else
|
38
|
-
k.value
|
39
|
-
end
|
40
|
-
|
41
|
-
sub_select = @database.select_statement(k.options.merge(v))
|
42
|
-
normalize(["#{@database[@options[:class]][k.value.to_sym].to_sql} IN ?", sub_select], collector)
|
43
|
-
else
|
44
|
-
@has_id = true if k.value == :id
|
45
|
-
op = case k.type
|
46
|
-
when :gt then '>'
|
47
|
-
when :gte then '>='
|
48
|
-
when :lt then '<'
|
49
|
-
when :lte then '<='
|
50
|
-
when :not then v.nil? ? 'IS NOT' : (v.kind_of?(Array) ? 'NOT IN' : '<>')
|
51
|
-
when :eql then v.nil? ? 'IS' : (v.kind_of?(Array) ? 'IN' : '=')
|
52
|
-
when :like then 'LIKE'
|
53
|
-
when :in then 'IN'
|
54
|
-
else raise ArgumentError.new('Operator type not supported')
|
55
|
-
end
|
56
|
-
normalize(["#{@database[@options[:class]][k.value.to_sym].to_sql} #{op} ?", v], collector)
|
57
|
-
end
|
58
|
-
else
|
59
|
-
@has_id = true if k == :id
|
60
|
-
case v
|
61
|
-
when Array then
|
62
|
-
normalize(["#{@database[@options[:class]][k.to_sym].to_sql} IN ?", v], collector)
|
63
|
-
when SelectStatement then
|
64
|
-
normalize(["#{@database[@options[:class]][k.to_sym].to_sql} IN ?", v], collector)
|
65
|
-
else
|
66
|
-
normalize(["#{@database[@options[:class]][k.to_sym].to_sql} = ?", v], collector)
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|
70
|
-
when Array then
|
71
|
-
return collector if clause.empty?
|
72
|
-
@has_id = true if clause.first =~ /(^|\s|\`)id(\`|\s|\=|\<)/ && !clause[1].kind_of?(SelectStatement)
|
73
|
-
collector << escape(clause)
|
74
|
-
when String then
|
75
|
-
@has_id = true if clause =~ /(^|\s|\`)id(\`|\s|\=|\<)/
|
76
|
-
collector << clause
|
77
|
-
else raise NormalizationError.new(clause)
|
78
|
-
end
|
79
|
-
|
80
|
-
return collector
|
81
|
-
end
|
82
|
-
|
83
|
-
def escape(conditions)
|
84
|
-
clause = conditions.shift
|
85
|
-
|
86
|
-
clause.gsub(/\?/) do |x|
|
87
|
-
# Check if the condition is an in, clause.
|
88
|
-
case conditions.first
|
89
|
-
when Array then
|
90
|
-
'(' << conditions.shift.map { |c| @database.quote_value(c) }.join(', ') << ')'
|
91
|
-
when SelectStatement then
|
92
|
-
'(' << conditions.shift.to_sql << ')'
|
93
|
-
else
|
94
|
-
@database.quote_value(conditions.shift)
|
95
|
-
end
|
96
|
-
end
|
97
|
-
end
|
98
|
-
|
99
|
-
def has_id?
|
100
|
-
normalized_conditions
|
101
|
-
@has_id
|
102
|
-
end
|
103
|
-
|
104
|
-
def normalized_conditions
|
105
|
-
|
106
|
-
if @normalized_conditions.nil?
|
107
|
-
@normalized_conditions = []
|
108
|
-
|
109
|
-
table = @database[@options[:class]]
|
110
|
-
invalid_keys = nil
|
111
|
-
|
112
|
-
implicits = @options.reject do |k,v|
|
113
|
-
standard_key = DataMapper::Session::FIND_OPTIONS.include?(k)
|
114
|
-
(invalid_keys ||= []) << k if !standard_key && table[k.to_sym].nil?
|
115
|
-
standard_key
|
116
|
-
end
|
117
|
-
|
118
|
-
raise "Invalid options: #{invalid_keys.inspect}" unless invalid_keys.nil?
|
119
|
-
|
120
|
-
normalize(implicits, @normalized_conditions)
|
121
|
-
|
122
|
-
if @options.has_key?(:conditions)
|
123
|
-
normalize(@options[:conditions], @normalized_conditions)
|
124
|
-
end
|
125
|
-
|
126
|
-
end
|
127
|
-
|
128
|
-
return @normalized_conditions
|
129
|
-
end
|
130
|
-
|
131
|
-
def empty?
|
132
|
-
normalized_conditions.empty?
|
133
|
-
end
|
134
|
-
|
135
|
-
def to_a
|
136
|
-
normalized_conditions
|
137
|
-
end
|
138
|
-
end
|
139
|
-
|
140
|
-
end
|
141
|
-
end
|
@@ -1,34 +0,0 @@
|
|
1
|
-
require File.dirname(__FILE__) + '/result'
|
2
|
-
require File.dirname(__FILE__) + '/reader'
|
3
|
-
|
4
|
-
module DataMapper
|
5
|
-
module Queries
|
6
|
-
|
7
|
-
class Connection
|
8
|
-
|
9
|
-
def initialize(logger)
|
10
|
-
@logger = logger
|
11
|
-
end
|
12
|
-
|
13
|
-
def log
|
14
|
-
@logger
|
15
|
-
end
|
16
|
-
|
17
|
-
def execute(sql)
|
18
|
-
raise NotImplementedError.new
|
19
|
-
Results.new
|
20
|
-
end
|
21
|
-
|
22
|
-
def query(sql)
|
23
|
-
raise NotImplementedError.new
|
24
|
-
Reader.new
|
25
|
-
end
|
26
|
-
|
27
|
-
def close
|
28
|
-
raise NotImplementedError.new
|
29
|
-
end
|
30
|
-
|
31
|
-
end
|
32
|
-
|
33
|
-
end # module Queries
|
34
|
-
end # module DataMapper
|
@@ -1,38 +0,0 @@
|
|
1
|
-
module DataMapper
|
2
|
-
module Queries
|
3
|
-
|
4
|
-
class CreateTableStatement
|
5
|
-
|
6
|
-
def initialize(database, klass)
|
7
|
-
@database, @klass = database, klass
|
8
|
-
end
|
9
|
-
|
10
|
-
def to_sql
|
11
|
-
table = @database[@klass]
|
12
|
-
|
13
|
-
sql = "CREATE TABLE " << table.to_sql << " ("
|
14
|
-
|
15
|
-
sql << table.columns.map do |column|
|
16
|
-
column_long_form(column)
|
17
|
-
end.join(', ')
|
18
|
-
|
19
|
-
sql << ", PRIMARY KEY (#{table.key.to_sql}))"
|
20
|
-
|
21
|
-
return sql
|
22
|
-
end
|
23
|
-
|
24
|
-
def column_long_form(column)
|
25
|
-
long_form = "#{column.to_sql} #{@database.adapter.class::TYPES[column.type] || column.type}"
|
26
|
-
|
27
|
-
long_form << "(#{column.size})" unless column.size.nil?
|
28
|
-
long_form << " NOT NULL" unless column.nullable?
|
29
|
-
long_form << " " << @database.syntax(:auto_increment) if column.key?
|
30
|
-
long_form << " default #{column.options[:default]}" if column.options.has_key?(:default)
|
31
|
-
|
32
|
-
return long_form
|
33
|
-
end
|
34
|
-
|
35
|
-
end
|
36
|
-
|
37
|
-
end
|
38
|
-
end
|
@@ -1,17 +0,0 @@
|
|
1
|
-
module DataMapper
|
2
|
-
module Queries
|
3
|
-
|
4
|
-
class DeleteStatement
|
5
|
-
|
6
|
-
def initialize(database, instance)
|
7
|
-
@database, @instance = database, instance
|
8
|
-
end
|
9
|
-
|
10
|
-
def to_sql
|
11
|
-
"DELETE FROM " << @database[@instance.class].to_sql << " WHERE id = " << @database.quote_value(@instance.key)
|
12
|
-
end
|
13
|
-
|
14
|
-
end
|
15
|
-
|
16
|
-
end
|
17
|
-
end
|
@@ -1,29 +0,0 @@
|
|
1
|
-
module DataMapper
|
2
|
-
module Queries
|
3
|
-
|
4
|
-
class InsertStatement
|
5
|
-
|
6
|
-
def initialize(database, instance)
|
7
|
-
@database, @instance = database, instance
|
8
|
-
end
|
9
|
-
|
10
|
-
# The only thing this method is responsible for is generating the insert statement.
|
11
|
-
# It is the database adapters responsibility to get the last inserted id
|
12
|
-
def to_sql
|
13
|
-
|
14
|
-
table = @database[@instance.class]
|
15
|
-
|
16
|
-
keys = []
|
17
|
-
values = []
|
18
|
-
|
19
|
-
@instance.dirty_attributes.each_pair { |k,v| keys << table[k].to_sql; values << v }
|
20
|
-
|
21
|
-
# Formatting is a bit off here, but it looks nicer in the log this way.
|
22
|
-
sql = "INSERT INTO #{table.to_sql} (#{keys.join(', ')}) \
|
23
|
-
VALUES (#{values.map { |v| @database.quote_value(v) }.join(', ')})"
|
24
|
-
end
|
25
|
-
|
26
|
-
end
|
27
|
-
|
28
|
-
end
|
29
|
-
end
|
@@ -1,42 +0,0 @@
|
|
1
|
-
module DataMapper
|
2
|
-
module Queries
|
3
|
-
|
4
|
-
class Reader
|
5
|
-
|
6
|
-
attr_reader :columns
|
7
|
-
|
8
|
-
def initialize(database_result_set)
|
9
|
-
end
|
10
|
-
|
11
|
-
def eof?
|
12
|
-
raise NotImplementedError.new
|
13
|
-
end
|
14
|
-
|
15
|
-
def records_affected
|
16
|
-
raise NotImplementedError.new
|
17
|
-
end
|
18
|
-
|
19
|
-
def each
|
20
|
-
raise NotImplementedError.new
|
21
|
-
end
|
22
|
-
|
23
|
-
def entries
|
24
|
-
raise NotImplementedError.new
|
25
|
-
end
|
26
|
-
|
27
|
-
def [](column)
|
28
|
-
raise NotImplementedError.new
|
29
|
-
end
|
30
|
-
|
31
|
-
def each_pair
|
32
|
-
raise NotImplementedError.new
|
33
|
-
end
|
34
|
-
|
35
|
-
def close
|
36
|
-
raise NotImplementedError.new
|
37
|
-
end
|
38
|
-
|
39
|
-
end
|
40
|
-
|
41
|
-
end # module Queries
|
42
|
-
end # module DataMapper
|
@@ -1,19 +0,0 @@
|
|
1
|
-
module DataMapper
|
2
|
-
module Queries
|
3
|
-
|
4
|
-
class Result
|
5
|
-
|
6
|
-
attr_accessor :size, :last_inserted_id
|
7
|
-
|
8
|
-
def initialize(size, last_inserted_id = nil)
|
9
|
-
@size, @last_inserted_id = size, last_inserted_id
|
10
|
-
end
|
11
|
-
|
12
|
-
def success?
|
13
|
-
size > 0
|
14
|
-
end
|
15
|
-
|
16
|
-
end # class Result
|
17
|
-
|
18
|
-
end # module Queries
|
19
|
-
end # module DataMapper
|
@@ -1,103 +0,0 @@
|
|
1
|
-
require 'data_mapper/queries/conditions'
|
2
|
-
|
3
|
-
module DataMapper
|
4
|
-
module Queries
|
5
|
-
|
6
|
-
class SelectStatement
|
7
|
-
|
8
|
-
def initialize(database, options)
|
9
|
-
@database, @options = database, options
|
10
|
-
end
|
11
|
-
|
12
|
-
def limit
|
13
|
-
@options[:limit]
|
14
|
-
end
|
15
|
-
|
16
|
-
def order
|
17
|
-
@options[:order]
|
18
|
-
end
|
19
|
-
|
20
|
-
def klass
|
21
|
-
@options[:class]
|
22
|
-
end
|
23
|
-
|
24
|
-
def has_id?
|
25
|
-
conditions.has_id?
|
26
|
-
end
|
27
|
-
|
28
|
-
def escape(conditions)
|
29
|
-
@database.escape(conditions)
|
30
|
-
end
|
31
|
-
|
32
|
-
def inspect
|
33
|
-
@options.inspect
|
34
|
-
end
|
35
|
-
|
36
|
-
def include?(association_name)
|
37
|
-
return false if includes.empty?
|
38
|
-
includes.include?(association_name)
|
39
|
-
end
|
40
|
-
|
41
|
-
def includes
|
42
|
-
list = @options[:include] ||= []
|
43
|
-
list.kind_of?(Array) ? list : [list]
|
44
|
-
end
|
45
|
-
|
46
|
-
def reload?
|
47
|
-
@options[:reload]
|
48
|
-
end
|
49
|
-
|
50
|
-
def select
|
51
|
-
select_columns = @options[:select]
|
52
|
-
unless select_columns.nil?
|
53
|
-
select_columns = select_columns.kind_of?(Array) ? select_columns : (@options[:select] = [select_columns])
|
54
|
-
select_columns.map { |column| @database.quote_column_name(column.to_s) }
|
55
|
-
else
|
56
|
-
@options[:select] = @database[klass].columns.select do |column|
|
57
|
-
include?(column.name) || !column.lazy?
|
58
|
-
end.map { |column| column.to_sql }
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
def instance_id
|
63
|
-
@options[:id]
|
64
|
-
end
|
65
|
-
|
66
|
-
def conditions
|
67
|
-
@conditions ||= Conditions.new(@database, @options)
|
68
|
-
end
|
69
|
-
|
70
|
-
def table
|
71
|
-
@table_name || @table_name = if @options.has_key?(:table)
|
72
|
-
@database.quote_table_name(@options[:table])
|
73
|
-
else
|
74
|
-
@database[klass].to_sql
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
|
-
def to_sql
|
79
|
-
sql = 'SELECT ' << select.join(', ') << ' FROM ' << table
|
80
|
-
|
81
|
-
where = []
|
82
|
-
|
83
|
-
where += conditions.to_a unless conditions.empty?
|
84
|
-
|
85
|
-
unless where.empty?
|
86
|
-
sql << ' WHERE (' << where.join(') AND (') << ')'
|
87
|
-
end
|
88
|
-
|
89
|
-
unless order.nil?
|
90
|
-
sql << ' ORDER BY ' << order.to_s
|
91
|
-
end
|
92
|
-
|
93
|
-
unless limit.nil?
|
94
|
-
sql << ' LIMIT ' << limit.to_s
|
95
|
-
end
|
96
|
-
|
97
|
-
return sql
|
98
|
-
end
|
99
|
-
|
100
|
-
end
|
101
|
-
|
102
|
-
end
|
103
|
-
end
|