datamapper 0.1.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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