datamapper 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (131) hide show
  1. data/CHANGELOG +65 -0
  2. data/README +193 -1
  3. data/do_performance.rb +153 -0
  4. data/environment.rb +45 -0
  5. data/example.rb +119 -22
  6. data/lib/data_mapper.rb +36 -16
  7. data/lib/data_mapper/adapters/abstract_adapter.rb +8 -0
  8. data/lib/data_mapper/adapters/data_object_adapter.rb +360 -0
  9. data/lib/data_mapper/adapters/mysql_adapter.rb +30 -179
  10. data/lib/data_mapper/adapters/postgresql_adapter.rb +90 -199
  11. data/lib/data_mapper/adapters/sql/coersion.rb +32 -3
  12. data/lib/data_mapper/adapters/sql/commands/conditions.rb +97 -128
  13. data/lib/data_mapper/adapters/sql/commands/load_command.rb +234 -231
  14. data/lib/data_mapper/adapters/sql/commands/loader.rb +99 -0
  15. data/lib/data_mapper/adapters/sql/mappings/associations_set.rb +30 -0
  16. data/lib/data_mapper/adapters/sql/mappings/column.rb +68 -6
  17. data/lib/data_mapper/adapters/sql/mappings/schema.rb +6 -3
  18. data/lib/data_mapper/adapters/sql/mappings/table.rb +71 -42
  19. data/lib/data_mapper/adapters/sql/quoting.rb +8 -2
  20. data/lib/data_mapper/adapters/sqlite3_adapter.rb +32 -201
  21. data/lib/data_mapper/associations.rb +21 -7
  22. data/lib/data_mapper/associations/belongs_to_association.rb +96 -80
  23. data/lib/data_mapper/associations/has_and_belongs_to_many_association.rb +158 -67
  24. data/lib/data_mapper/associations/has_many_association.rb +96 -78
  25. data/lib/data_mapper/associations/has_n_association.rb +64 -0
  26. data/lib/data_mapper/associations/has_one_association.rb +49 -79
  27. data/lib/data_mapper/associations/reference.rb +47 -0
  28. data/lib/data_mapper/base.rb +216 -50
  29. data/lib/data_mapper/callbacks.rb +71 -24
  30. data/lib/data_mapper/{session.rb → context.rb} +20 -8
  31. data/lib/data_mapper/database.rb +176 -45
  32. data/lib/data_mapper/embedded_value.rb +65 -0
  33. data/lib/data_mapper/identity_map.rb +12 -4
  34. data/lib/data_mapper/support/active_record_impersonation.rb +12 -8
  35. data/lib/data_mapper/support/enumerable.rb +8 -0
  36. data/lib/data_mapper/support/serialization.rb +13 -0
  37. data/lib/data_mapper/support/string.rb +1 -12
  38. data/lib/data_mapper/support/symbol.rb +3 -0
  39. data/lib/data_mapper/validations/unique_validator.rb +1 -2
  40. data/lib/data_mapper/validations/validation_helper.rb +18 -1
  41. data/performance.rb +109 -34
  42. data/plugins/can_has_sphinx/LICENSE +23 -0
  43. data/plugins/can_has_sphinx/README +4 -0
  44. data/plugins/can_has_sphinx/REVISION +1 -0
  45. data/plugins/can_has_sphinx/Rakefile +22 -0
  46. data/plugins/can_has_sphinx/init.rb +1 -0
  47. data/plugins/can_has_sphinx/install.rb +1 -0
  48. data/plugins/can_has_sphinx/lib/acts_as_sphinx.rb +123 -0
  49. data/plugins/can_has_sphinx/lib/sphinx.rb +460 -0
  50. data/plugins/can_has_sphinx/scripts/sphinx.sh +47 -0
  51. data/plugins/can_has_sphinx/tasks/acts_as_sphinx_tasks.rake +41 -0
  52. data/plugins/dataobjects/REVISION +1 -0
  53. data/plugins/dataobjects/Rakefile +7 -0
  54. data/plugins/dataobjects/do.rb +246 -0
  55. data/plugins/dataobjects/do_mysql.rb +179 -0
  56. data/plugins/dataobjects/do_postgres.rb +181 -0
  57. data/plugins/dataobjects/do_sqlite3.rb +153 -0
  58. data/plugins/dataobjects/spec/do_spec.rb +150 -0
  59. data/plugins/dataobjects/spec/spec_helper.rb +81 -0
  60. data/plugins/dataobjects/swig_mysql/do_mysql.bundle +0 -0
  61. data/plugins/dataobjects/swig_mysql/extconf.rb +33 -0
  62. data/plugins/dataobjects/swig_mysql/mysql_c.c +18800 -0
  63. data/plugins/dataobjects/swig_mysql/mysql_c.i +8 -0
  64. data/plugins/dataobjects/swig_mysql/mysql_supp.i +46 -0
  65. data/plugins/dataobjects/swig_postgres/Makefile +146 -0
  66. data/plugins/dataobjects/swig_postgres/extconf.rb +29 -0
  67. data/plugins/dataobjects/swig_postgres/postgres_c.bundle +0 -0
  68. data/plugins/dataobjects/swig_postgres/postgres_c.c +8185 -0
  69. data/plugins/dataobjects/swig_postgres/postgres_c.i +73 -0
  70. data/plugins/dataobjects/swig_sqlite/db +0 -0
  71. data/plugins/dataobjects/swig_sqlite/extconf.rb +9 -0
  72. data/plugins/dataobjects/swig_sqlite/sqlite3_c.c +4725 -0
  73. data/plugins/dataobjects/swig_sqlite/sqlite_c.i +168 -0
  74. data/rakefile.rb +45 -23
  75. data/spec/acts_as_tree_spec.rb +39 -0
  76. data/spec/associations_spec.rb +220 -0
  77. data/spec/attributes_spec.rb +15 -0
  78. data/spec/base_spec.rb +44 -0
  79. data/spec/callbacks_spec.rb +45 -0
  80. data/spec/can_has_sphinx.rb +6 -0
  81. data/spec/coersion_spec.rb +34 -0
  82. data/spec/conditions_spec.rb +49 -0
  83. data/spec/conversions_to_yaml_spec.rb +17 -0
  84. data/spec/count_command_spec.rb +11 -0
  85. data/spec/delete_command_spec.rb +1 -1
  86. data/spec/embedded_value_spec.rb +23 -0
  87. data/spec/fixtures/animals_exhibits.yaml +2 -0
  88. data/spec/fixtures/people.yaml +18 -1
  89. data/spec/{legacy.rb → legacy_spec.rb} +3 -3
  90. data/spec/load_command_spec.rb +157 -20
  91. data/spec/magic_columns_spec.rb +9 -0
  92. data/spec/mock_adapter.rb +20 -0
  93. data/spec/models/animal.rb +1 -1
  94. data/spec/models/animals_exhibit.rb +6 -0
  95. data/spec/models/exhibit.rb +2 -0
  96. data/spec/models/person.rb +26 -1
  97. data/spec/models/project.rb +19 -0
  98. data/spec/models/sales_person.rb +1 -0
  99. data/spec/models/section.rb +6 -0
  100. data/spec/models/zoo.rb +3 -1
  101. data/spec/query_spec.rb +9 -0
  102. data/spec/save_command_spec.rb +65 -1
  103. data/spec/schema_spec.rb +89 -0
  104. data/spec/single_table_inheritance_spec.rb +27 -0
  105. data/spec/spec_helper.rb +9 -55
  106. data/spec/{symbolic_operators.rb → symbolic_operators_spec.rb} +9 -5
  107. data/spec/{validates_confirmation_of.rb → validates_confirmation_of_spec.rb} +4 -3
  108. data/spec/{validates_format_of.rb → validates_format_of_spec.rb} +5 -4
  109. data/spec/{validates_length_of.rb → validates_length_of_spec.rb} +8 -7
  110. data/spec/{validates_uniqueness_of.rb → validates_uniqueness_of_spec.rb} +7 -10
  111. data/spec/{validations.rb → validations_spec.rb} +24 -6
  112. data/tasks/drivers.rb +20 -0
  113. data/tasks/fixtures.rb +42 -0
  114. metadata +181 -42
  115. data/lib/data_mapper/adapters/sql/commands/advanced_load_command.rb +0 -140
  116. data/lib/data_mapper/adapters/sql/commands/delete_command.rb +0 -113
  117. data/lib/data_mapper/adapters/sql/commands/save_command.rb +0 -141
  118. data/lib/data_mapper/adapters/sql/commands/table_exists_command.rb +0 -33
  119. data/lib/data_mapper/adapters/sql_adapter.rb +0 -163
  120. data/lib/data_mapper/associations/advanced_has_many_association.rb +0 -55
  121. data/lib/data_mapper/support/blank_slate.rb +0 -3
  122. data/lib/data_mapper/support/proc.rb +0 -69
  123. data/lib/data_mapper/support/struct.rb +0 -26
  124. data/lib/data_mapper/unit_of_work.rb +0 -38
  125. data/spec/basic_finder.rb +0 -67
  126. data/spec/belongs_to.rb +0 -47
  127. data/spec/has_and_belongs_to_many.rb +0 -25
  128. data/spec/has_many.rb +0 -34
  129. data/spec/new_record.rb +0 -24
  130. data/spec/sub_select.rb +0 -16
  131. data/spec/support/string_spec.rb +0 -7
@@ -1,140 +0,0 @@
1
- module DataMapper
2
- module Adapters
3
- module Sql
4
- module Commands
5
-
6
- class AdvancedLoadCommand
7
-
8
- attr_reader :conditions, :options
9
-
10
- def initialize(adapter, session, primary_class, options = {})
11
- @adapter, @session, @primary_class, @options = adapter, session, primary_class, options
12
-
13
- @order = @options[:order]
14
- @limit = @options[:limit]
15
- @offset = @options[:offset]
16
- @reload = @options[:reload]
17
- @include = @options[:include]
18
- @instance_id = @options[:id]
19
- @conditions = @options[:conditions]
20
- @join_fetch = false
21
- @joins = []
22
- end
23
-
24
- # If +true+ then force the command to reload any objects
25
- # already existing in the IdentityMap when executing.
26
- def reload?
27
- @reload
28
- end
29
-
30
- # Determine if there is a limitation on the number of
31
- # instances returned in the results. If +nil+, no limit
32
- # is set. Can be used in conjunction with #offset for
33
- # paging through a set of results.
34
- def limit
35
- @limit
36
- end
37
-
38
- # Used in conjunction with #limit to page through a set
39
- # of results.
40
- def offset
41
- @offset
42
- end
43
-
44
- # Generate a select statement based on the initialization
45
- # arguments.
46
- def to_sql
47
- sql = 'SELECT ' << columns_for_select.join(', ')
48
- sql << ' FROM ' << from_table_name
49
-
50
- if @join_fetch
51
- @joins.each do |entry|
52
- primary_table, association_table, association = entry
53
- sql << ' JOIN ' << association_table.to_sql << ' ON '
54
- sql << association_table.to_sql << '.'
55
- sql << @adapter.quote_column_name(association.foreign_key)
56
- sql << ' = ' << primary_table.key.to_sql(true)
57
- end
58
- end
59
-
60
- return sql
61
- end
62
-
63
- private
64
-
65
- # Return the Sql-escaped columns names to be selected in the results.
66
- def columns_for_select
67
- @columns_for_select || @columns_for_select = begin
68
- columns.map { |column| column.to_sql(@join_fetch) }
69
- end
70
- end
71
-
72
- # Returns the DataMapper::Adapters::Sql::Mappings::Column instances to
73
- # be selected in the results.
74
- def columns
75
- @columns || begin
76
- @columns = if @options.has_key?(:select)
77
- primary_class_table.columns.select do |column|
78
- @options[:select].include?(column.name)
79
- end
80
- else
81
- primary_class_table.columns.select do |column|
82
- include_column?(column.name) || !column.lazy?
83
- end
84
- end
85
-
86
- # Return if there is no +:include+ option to evaluate.
87
- return @columns if @include.nil?
88
-
89
- if @include.kind_of?(Array)
90
- # Return if all +:include+ parameters are columns in
91
- # the primary_class_table.
92
- return @columns if @include.all? do |name|
93
- !primary_class_table[name].nil?
94
- end
95
- elsif @include.kind_of?(Symbol)
96
- # Return if the include is a column in the primary_class_table.
97
- return @columns if primary_class_table[@include]
98
-
99
- primary_class_table.associations.each do |association|
100
- next unless association.name == @include
101
- association_table = @adapter[association.constant]
102
- @columns += association_table.columns
103
- @joins << [ primary_class_table, association_table, association ]
104
- end
105
-
106
- @join_fetch = true
107
- else
108
- raise ':include option must be a Symbol or Array of Symbols'
109
- end
110
-
111
- @columns
112
- end
113
- end
114
-
115
- # Determine if a Column should be included based on the
116
- # value of the +:include+ option.
117
- def include_column?(name)
118
- case @include
119
- when nil then false
120
- when Symbol then @include == name
121
- when Array then @include.includes?(name)
122
- else raise ':include option must be a Symbol or Array of Symbols'
123
- end
124
- end
125
-
126
- # Return the Sql-escaped table name of the +primary_class+.
127
- def from_table_name
128
- @from_table_name || (@from_table_name = @adapter[@primary_class].to_sql)
129
- end
130
-
131
- # Returns the DataMapper::Adapters::Sql::Mappings::Table for the +primary_class+.
132
- def primary_class_table
133
- @primary_class_table || (@primary_class_table = @adapter[@primary_class])
134
- end
135
-
136
- end # class LoadCommand
137
- end # module Commands
138
- end # module Sql
139
- end # module Adapters
140
- end # module DataMapper
@@ -1,113 +0,0 @@
1
- module DataMapper
2
- module Adapters
3
- module Sql
4
- module Commands
5
-
6
- class DeleteCommand
7
-
8
- def initialize(adapter, klass_or_instance, options = nil)
9
- @adapter, @klass_or_instance, @options = adapter, klass_or_instance, options
10
- end
11
-
12
- def truncate?
13
- return false if @options.nil?
14
- @options[:truncate]
15
- end
16
-
17
- def drop?
18
- return false if @options.nil?
19
- @options[:drop]
20
- end
21
-
22
- def delete_all?
23
- return !truncate? && !drop? && @klass_or_instance.kind_of?(Class)
24
- end
25
-
26
- def klass
27
- @klass_or_instance.kind_of?(Class) ? @klass_or_instance : @klass_or_instance.class
28
- end
29
-
30
- def to_truncate_sql
31
- "TRUNCATE TABLE " << @adapter[@klass_or_instance].to_sql
32
- end
33
-
34
- def to_drop_sql
35
- "DROP TABLE #{@adapter[@klass_or_instance].to_sql}"
36
- end
37
-
38
- def to_delete_sql
39
- sql = "DELETE FROM " << @adapter[klass].to_sql
40
- sql << " WHERE id = " << @adapter.quote_value(@klass_or_instance.key) unless delete_all?
41
- return sql
42
- end
43
-
44
- def to_sql
45
- if truncate?
46
- to_truncate_sql
47
- elsif drop?
48
- to_drop_sql
49
- else
50
- to_delete_sql
51
- end
52
- end
53
-
54
- def session
55
- return nil if @options.nil?
56
- @options[:session]
57
- end
58
-
59
- def call
60
- result = nil
61
-
62
- if truncate?
63
- result = execute_truncate(to_sql)
64
- session.identity_map.clear!(klass) unless session.nil?
65
- elsif drop?
66
- result = execute_drop(to_sql)
67
- session.identity_map.clear!(klass) unless session.nil?
68
- elsif delete_all?
69
- result = execute_delete_all(to_sql)
70
- session.identity_map.clear!(klass) unless session.nil?
71
- else
72
- @klass_or_instance.class.callbacks.execute(:before_destroy, @klass_or_instance)
73
-
74
- result = execute(to_sql)
75
-
76
- if result
77
- @klass_or_instance.instance_variable_set(:@new_record, true)
78
- @klass_or_instance.session = session
79
- @klass_or_instance.original_hashes.clear
80
- session.identity_map.delete(@klass_or_instance) unless session.nil?
81
- @klass_or_instance.class.callbacks.execute(:after_destroy, @klass_or_instance)
82
- end
83
- end
84
-
85
- return result
86
- rescue => error
87
- @adapter.log.error(error)
88
- raise error
89
- end
90
-
91
- protected
92
- def execute_truncate(sql)
93
- execute(sql)
94
- end
95
-
96
- def execute_drop(sql)
97
- execute(sql)
98
- end
99
-
100
- def execute_delete_all(sql)
101
- execute(sql)
102
- end
103
-
104
- def execute(sql)
105
- raise NotImplementedError.new
106
- end
107
-
108
- end
109
-
110
- end
111
- end
112
- end
113
- end
@@ -1,141 +0,0 @@
1
- module DataMapper
2
- module Adapters
3
- module Sql
4
- module Commands
5
-
6
- class SaveCommand
7
-
8
- def initialize(adapter, session, instance)
9
- @adapter, @session, @instance = adapter, session, instance
10
- end
11
-
12
- def to_update_sql
13
- table = @adapter[@instance.class]
14
-
15
- sql = "UPDATE " << table.to_sql << " SET "
16
-
17
- @instance.dirty_attributes.map do |k, v|
18
- sql << table[k].to_sql << " = " << @adapter.quote_value(v) << ", "
19
- end
20
-
21
- sql[0, sql.size - 2] << " WHERE #{table.key.to_sql} = " << @adapter.quote_value(@instance.key)
22
- end
23
-
24
- def to_insert_sql
25
-
26
- table = @adapter[@instance.class]
27
-
28
- keys = []
29
- values = []
30
-
31
- @instance.dirty_attributes.each_pair { |k,v| keys << table[k].to_sql; values << v }
32
-
33
- # Formatting is a bit off here, but it looks nicer in the log this way.
34
- sql = "INSERT INTO #{table.to_sql} (#{keys.join(', ')}) \
35
- VALUES (#{values.map { |v| @adapter.quote_value(v) }.join(', ')})"
36
- end
37
-
38
- def to_create_table_sql
39
- table = @adapter[@instance]
40
-
41
- sql = "CREATE TABLE " << table.to_sql << " ("
42
-
43
- sql << table.columns.map do |column|
44
- column_long_form(column)
45
- end.join(', ')
46
-
47
- sql << ", PRIMARY KEY (#{table.key.to_sql}))"
48
-
49
- return sql
50
- end
51
-
52
- def column_long_form(column)
53
- long_form = "#{column.to_sql} #{@adapter.class::TYPES[column.type] || column.type}"
54
-
55
- long_form << "(#{column.size})" unless column.size.nil?
56
- long_form << " NOT NULL" unless column.nullable?
57
- long_form << " auto_increment" if column.key?
58
- long_form << " default #{column.options[:default]}" if column.options.has_key?(:default)
59
-
60
- return long_form
61
- end
62
-
63
- def callback(name)
64
- @instance.class.callbacks.execute(name, @instance)
65
- end
66
-
67
- def insert!
68
- callback(:before_create)
69
-
70
- result = execute_insert(to_insert_sql)
71
-
72
- if result
73
- @instance.instance_variable_set(:@new_record, false)
74
- @instance.instance_variable_set(:@id, result)
75
- calculate_original_hashes(@instance)
76
- @session.identity_map.set(@instance)
77
- callback(:after_create)
78
- end
79
-
80
- return result
81
- rescue => error
82
- @adapter.log.error(error)
83
- raise error
84
- end
85
-
86
- def update!
87
- callback(:before_update)
88
-
89
- result = execute_update(to_update_sql)
90
-
91
- calculate_original_hashes(@instance)
92
- callback(:after_update)
93
- return result
94
- rescue => error
95
- @adapter.log.error(error)
96
- raise error
97
- end
98
-
99
- def call
100
- if @instance.kind_of?(Class)
101
- return false if @adapter.table_exists?(@instance)
102
- execute_create_table(to_create_table_sql)
103
- else
104
- return false unless @instance.dirty?
105
- callback(:before_save)
106
- result = @instance.new_record? ? insert! : update!
107
- @instance.session = @session
108
- callback(:after_save)
109
- result
110
- end
111
- end
112
-
113
- protected
114
- def execute_insert(sql)
115
- raise NotImplementedError.new
116
- end
117
-
118
- def execute_update(sql)
119
- raise NotImplementedError.new
120
- end
121
-
122
- def execute_create_table(sql)
123
- raise NotImplementedError.new
124
- end
125
-
126
- private
127
- # Calculates the original hashes for each value
128
- # in an instance's set of attributes, and adds
129
- # them to the original_hashes hash.
130
- def calculate_original_hashes(instance)
131
- instance.attributes.each_pair do |name, value|
132
- instance.original_hashes[name] = value.hash
133
- end
134
- end
135
-
136
- end
137
-
138
- end
139
- end
140
- end
141
- end
@@ -1,33 +0,0 @@
1
- module DataMapper
2
- module Adapters
3
- module Sql
4
- module Commands
5
-
6
- class TableExistsCommand
7
-
8
- def initialize(adapter, klass_or_name)
9
- @adapter, @klass_or_name = adapter, klass_or_name
10
- end
11
-
12
- def table_name
13
- @table_name || @table_name = case @klass_or_name
14
- when String then @adapter.quote_value(@klass_or_name)
15
- when Class then @adapter.quote_value(@adapter[@klass_or_name].name)
16
- else raise ArgumentError.new('klass_or_name must be a mapped-class or a table name')
17
- end
18
- end
19
-
20
- def to_sql
21
- "SHOW TABLES LIKE #{table_name}"
22
- end
23
-
24
- def call
25
- raise NotImplementedError.new
26
- end
27
-
28
- end
29
-
30
- end
31
- end
32
- end
33
- end
@@ -1,163 +0,0 @@
1
- require 'data_mapper/adapters/abstract_adapter'
2
- require 'data_mapper/adapters/sql/commands/load_command'
3
- require 'data_mapper/adapters/sql/commands/advanced_load_command'
4
- require 'data_mapper/adapters/sql/commands/save_command'
5
- require 'data_mapper/adapters/sql/commands/delete_command'
6
- require 'data_mapper/adapters/sql/commands/table_exists_command'
7
- require 'data_mapper/adapters/sql/coersion'
8
- require 'data_mapper/adapters/sql/quoting'
9
- require 'data_mapper/adapters/sql/mappings/schema'
10
-
11
- module DataMapper
12
-
13
- # An Adapter is really a Factory for three types of object,
14
- # so they can be selectively sub-classed where needed.
15
- #
16
- # The first type is a Query. The Query is an object describing
17
- # the database-specific operations we wish to perform, in an
18
- # abstract manner. For example: While most if not all databases
19
- # support a mechanism for limiting the size of results returned,
20
- # some use a "LIMIT" keyword, while others use a "TOP" keyword.
21
- # We can set a SelectStatement#limit field then, and allow
22
- # the adapter to override the underlying SQL generated.
23
- # Refer to DataMapper::Queries.
24
- #
25
- # The second type provided by the Adapter is a DataMapper::Connection.
26
- # This allows us to execute queries and return results in a clear and
27
- # uniform manner we can use throughout the DataMapper.
28
- #
29
- # The final type provided is a DataMapper::Transaction.
30
- # Transactions are duck-typed Connections that span multiple queries.
31
- #
32
- # Note: It is assumed that the Adapter implements it's own
33
- # ConnectionPool if any since some libraries implement their own at
34
- # a low-level, and it wouldn't make sense to pay a performance
35
- # cost twice by implementing a secondary pool in the DataMapper itself.
36
- # If the library being adapted does not provide such functionality,
37
- # DataMapper::Support::ConnectionPool can be used.
38
- module Adapters
39
-
40
- # You must inherit from the SqlAdapter, and implement the
41
- # required methods to adapt a database library for use with the DataMapper.
42
- #
43
- # NOTE: By inheriting from SqlAdapter, you get a copy of all the
44
- # standard sub-modules (Quoting, Coersion and Queries) in your own Adapter.
45
- # You can extend and overwrite these copies without affecting the originals.
46
- class SqlAdapter < AbstractAdapter
47
-
48
- FIND_OPTIONS = [
49
- :select, :limit, :class, :include, :reload, :conditions, :order
50
- ]
51
-
52
- def initialize(configuration)
53
- super
54
- @single_threaded = configuration.single_threaded
55
- end
56
-
57
- def single_threaded?
58
- @single_threaded
59
- end
60
-
61
- def connection(&block)
62
- raise NotImplementedError.new
63
- end
64
-
65
- def transaction(&block)
66
- raise NotImplementedError.new
67
- end
68
-
69
- def query(sql)
70
- raise NotImplementedError.new
71
- end
72
-
73
- def schema
74
- @schema || ( @schema = Mappings::Schema.new(self) )
75
- end
76
-
77
- def table_exists?(name)
78
- self.class::Commands::TableExistsCommand.new(self, name).call
79
- end
80
-
81
- def delete(klass_or_instance, options = nil)
82
- self.class::Commands::DeleteCommand.new(self, klass_or_instance, options).call
83
- end
84
-
85
- def save(session, instance)
86
- self.class::Commands::SaveCommand.new(self, session, instance).call
87
- end
88
-
89
- def load(session, klass, options)
90
- self.class::Commands::LoadCommand.new(self, session, klass, options).call
91
- end
92
-
93
- def [](klass_or_table_name)
94
- schema[klass_or_table_name]
95
- end
96
-
97
- # Escape a string of SQL with a set of arguments.
98
- # The first argument is assumed to be the SQL to escape,
99
- # the remaining arguments (if any) are assumed to be
100
- # values to escape and interpolate.
101
- #
102
- # ==== Examples
103
- # escape_sql("SELECT * FROM zoos")
104
- # # => "SELECT * FROM zoos"
105
- #
106
- # escape_sql("SELECT * FROM zoos WHERE name = ?", "Dallas")
107
- # # => "SELECT * FROM zoos WHERE name = `Dallas`"
108
- #
109
- # escape_sql("SELECT * FROM zoos WHERE name = ? AND acreage > ?", "Dallas", 40)
110
- # # => "SELECT * FROM zoos WHERE name = `Dallas` AND acreage > 40"
111
- #
112
- # ==== Warning
113
- # This method is meant mostly for adapters that don't support
114
- # bind-parameters.
115
- def escape_sql(*args)
116
- sql = args.shift
117
-
118
- unless args.empty?
119
- sql.gsub!(/\?/) do |x|
120
- quote_value(args.shift)
121
- end
122
- end
123
-
124
- sql
125
- end
126
-
127
- # This callback copies and sub-classes modules and classes
128
- # in the AbstractAdapter to the inherited class so you don't
129
- # have to copy and paste large blocks of code from the
130
- # SqlAdapter.
131
- #
132
- # Basically, when inheriting from the AbstractAdapter, you
133
- # aren't just inheriting a single class, you're inheriting
134
- # a whole graph of Types. For convenience.
135
- def self.inherited(base)
136
-
137
- queries = base.const_set('Commands', Module.new)
138
-
139
- Sql::Commands.constants.each do |name|
140
- queries.const_set(name, Class.new(Sql::Commands.const_get(name)))
141
- end
142
-
143
- base.const_set('TYPES', TYPES.dup)
144
- base.const_set('FIND_OPTIONS', FIND_OPTIONS.dup)
145
-
146
- super
147
- end
148
-
149
- TYPES = {
150
- :integer => 'int'.freeze,
151
- :string => 'varchar'.freeze,
152
- :text => 'text'.freeze,
153
- :class => 'varchar'.freeze
154
- }
155
-
156
- include Sql
157
- include Quoting
158
- include Coersion
159
-
160
- end # class SqlAdapter
161
-
162
- end # module Adapters
163
- end # module DataMapper