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
@@ -0,0 +1,47 @@
1
+ #!/bin/sh
2
+ #
3
+ # start/stop searchd server.
4
+
5
+ if ! [ -x /usr/local/bin/searchd ]; then
6
+ exit 0
7
+ fi
8
+
9
+ case "$1" in
10
+ start)
11
+ echo -n "Starting sphinx searchd server:"
12
+ echo -n " searchd" ;
13
+ /sbin/start-stop-daemon --start --quiet --pidfile /var/run/searchd.pid --chdir /etc --exec /usr/local/bin/searchd
14
+ echo "."
15
+ ;;
16
+ stop)
17
+ echo -n "Stopping sphinx searchd server:"
18
+ echo -n " searchd" ;
19
+ /sbin/start-stop-daemon --stop --quiet --oknodo --pidfile /var/run/searchd.pid --exec /usr/local/bin/searchd
20
+ echo "."
21
+ ;;
22
+ reload)
23
+ echo -n "Reloading sphinx searchd server:"
24
+ echo -n " searchd"
25
+ /sbin/start-stop-daemon --stop --quiet --oknodo --pidfile /var/run/searchd.pid --signal 1
26
+ echo "."
27
+ ;;
28
+ force-reload)
29
+ $0 reload
30
+ ;;
31
+ reindex)
32
+ cd /etc
33
+ /usr/local/bin/indexer --rotate --quiet --all
34
+ ;;
35
+ restart)
36
+ echo -n "Restarting sphinx searchd server:"
37
+ echo -n " searchd"
38
+ /sbin/start-stop-daemon --stop --quiet --oknodo --pidfile /var/run/searchd.pid --exec /usr/local/bin/searchd
39
+ /sbin/start-stop-daemon --start --quiet --pidfile /var/run/searchd.pid --chdir /etc --exec /usr/local/bin/searchd
40
+ echo "."
41
+ ;;
42
+ *)
43
+ echo "Usage: /etc/init.d/searchd {start|stop|reload|restart|reindex}"
44
+ exit 1
45
+ ;;
46
+ esac
47
+ exit 0
@@ -0,0 +1,41 @@
1
+ namespace :sphinx do
2
+ desc "Run indexer"
3
+ task :index do
4
+ cd 'config' do
5
+ system 'indexer --all'
6
+ end
7
+ end
8
+
9
+ desc "Rotate idendexes and restart searchd server"
10
+ task :rotate do
11
+ cd 'config' do
12
+ system 'indexer --rotate --all'
13
+ end
14
+ end
15
+
16
+ desc "Start searchd server"
17
+ task :start do
18
+ if File.exists?('/var/run/searchd.pid')
19
+ puts 'Sphinx searchd server is already started.'
20
+ else
21
+ cd 'config' do
22
+ system 'searchd'
23
+ puts 'Sphinx searchd server started.'
24
+ end
25
+ end
26
+ end
27
+
28
+ desc "Stop searchd server"
29
+ task :stop do
30
+ unless File.exists?('/var/run/searchd.pid')
31
+ puts 'Sphinx searchd server is not running.'
32
+ else
33
+ pid = File.read('/var/run/searchd.pid').chomp
34
+ system "kill #{pid}"
35
+ puts 'Sphinx searchd server stopped.'
36
+ end
37
+ end
38
+
39
+ desc "Restart searchd server"
40
+ task :restart => [:stop, :start]
41
+ end
@@ -0,0 +1 @@
1
+ 18
@@ -0,0 +1,7 @@
1
+ require 'spec/rake/spectask'
2
+
3
+ desc "Run all specs"
4
+ Spec::Rake::SpecTask.new('specs') do |t|
5
+ t.spec_opts = ["--format", "specdoc", "--colour"]
6
+ t.spec_files = Dir['spec/*_spec.rb'].sort
7
+ end
@@ -0,0 +1,246 @@
1
+ require 'date'
2
+
3
+ # Thanks http://www.rubyweeklynews.org/20051120
4
+ class DateTime
5
+ def to_time
6
+ Time.mktime(year, mon, day, hour, min, sec)
7
+ end
8
+
9
+ def to_date
10
+ Date.new(year, mon, day)
11
+ end
12
+ end
13
+
14
+ class Time
15
+ def to_datetime
16
+ DateTime.civil(year, mon, day, hour, min, sec)
17
+ end
18
+
19
+ def to_s_db
20
+ strftime("%Y-%m-%d %X")
21
+ end
22
+ end
23
+
24
+ module DataObject
25
+ STATE_OPEN = 0
26
+ STATE_CLOSED = 1
27
+
28
+ class Connection
29
+
30
+ attr_reader :timeout, :database, :datasource, :server_version, :state
31
+
32
+ def initialize(connection_string)
33
+ end
34
+
35
+ def begin_transaction
36
+ # TODO: Hook this up
37
+ Transaction.new
38
+ end
39
+
40
+ def change_database(database_name)
41
+ raise NotImplementedError
42
+ end
43
+
44
+ def open
45
+ raise NotImplementedError
46
+ end
47
+
48
+ def close
49
+ raise NotImplementedError
50
+ end
51
+
52
+ def create_command(text)
53
+ Command.new(self, text)
54
+ end
55
+
56
+ def closed?
57
+ @state == STATE_CLOSED
58
+ end
59
+
60
+ end
61
+
62
+ class Transaction
63
+
64
+ attr_reader :connection
65
+
66
+ def initialize(conn)
67
+ @connection = conn
68
+ end
69
+
70
+ # Commits the transaction
71
+ def commit
72
+ raise NotImplementedError
73
+ end
74
+
75
+ # Rolls back the transaction
76
+ def rollback(savepoint = nil)
77
+ raise NotImplementedError
78
+ end
79
+
80
+ # Creates a savepoint for rolling back later (not commonly supported)
81
+ def save(name)
82
+ raise NotImplementedError
83
+ end
84
+
85
+ end
86
+
87
+ class Reader
88
+ include Enumerable
89
+
90
+ attr_reader :field_count, :has_rows, :records_affected, :fields
91
+ alias_method :has_rows?, :has_rows
92
+
93
+ def each
94
+ return nil unless has_rows
95
+ while(true) do
96
+ yield
97
+ break unless self.next
98
+ end
99
+ end
100
+
101
+ def current_row
102
+ ret = []
103
+ field_count.times do |i|
104
+ ret[i] = item(i)
105
+ end
106
+ ret
107
+ end
108
+
109
+ def close
110
+ raise NotImplementedError
111
+ end
112
+
113
+ # retrieves the Ruby data type for a particular column number
114
+ def data_type_name(col)
115
+ raise ReaderClosed, "You cannot ask for metadata once the reader is closed" if state_closed?
116
+ end
117
+
118
+ # retrieves the name of a particular column number
119
+ def name(col)
120
+ raise ReaderClosed, "You cannot ask for metadata once the reader is closed" if state_closed?
121
+ end
122
+
123
+ # retrives the index of the column with a particular name
124
+ def get_index(name)
125
+ raise ReaderClosed, "You cannot ask for metadata once the reader is closed" if state_closed?
126
+ end
127
+
128
+ def item(idx)
129
+ raise ReaderClosed, "You cannot ask for information once the reader is closed" if state_closed?
130
+ end
131
+
132
+ # returns an array of hashes containing the following information
133
+ #
134
+ # name: the column name
135
+ # index: the index of the column
136
+ # max_size: the maximum allowed size of the data in the column
137
+ # precision: the precision (for column types that support it)
138
+ # scale: the scale (for column types that support it)
139
+ # unique: boolean specifying whether the values must be unique
140
+ # key: boolean specifying whether this column is, or is part
141
+ # of, the primary key
142
+ # catalog: the name of the database this column is part of
143
+ # base_name: the original name of the column (if AS was used,
144
+ # this will provide the original name)
145
+ # schema: the name of the schema (if supported)
146
+ # table: the name of the table this column is part of
147
+ # data_type: the name of the Ruby data type used
148
+ # allow_null: boolean specifying whether nulls are allowed
149
+ # db_type: the type specified by the DB
150
+ # aliased: boolean specifying whether the column has been
151
+ # renamed using AS
152
+ # calculated: boolean specifying whether the field is calculated
153
+ # serial: boolean specifying whether the field is a serial
154
+ # column
155
+ # blob: boolean specifying whether the field is a BLOB
156
+ # readonly: boolean specifying whether the field is readonly
157
+ def get_schema
158
+ raise ReaderClosed, "You cannot ask for metadata once the reader is closed" if state_closed?
159
+ end
160
+
161
+ # specifies whether the column identified by the passed in index
162
+ # is null.
163
+ def null?(idx)
164
+ raise ReaderClosed, "You cannot ask for column information once the reader is closed" if state_closed?
165
+ end
166
+
167
+ # Consumes the next result. Returns true if a result is consumed and
168
+ # false if none is
169
+ def next
170
+ raise ReaderClosed, "You cannot increment the cursor once the reader is closed" if state_closed?
171
+ end
172
+
173
+ protected
174
+ def state_closed?
175
+ @state == STATE_CLOSED
176
+ end
177
+
178
+ def native_type
179
+ raise ReaderClosed, "You cannot check the type of a column once the reader is closed" if state_closed?
180
+ end
181
+
182
+ end
183
+
184
+ class ResultData
185
+
186
+ def initialize(conn, affected_rows, last_insert_row = nil)
187
+ @conn, @affected_rows, @last_insert_row = conn, affected_rows, last_insert_row
188
+ end
189
+
190
+ attr_reader :affected_rows, :last_insert_row
191
+ alias_method :to_i, :affected_rows
192
+
193
+ end
194
+
195
+ class Schema < Array
196
+
197
+ end
198
+
199
+ class Command
200
+
201
+ attr_reader :text, :timeout, :connection
202
+
203
+ # initialize creates a new Command object
204
+ def initialize(connection, text)
205
+ @connection, @text = connection, text
206
+ end
207
+
208
+ def execute_non_query
209
+ raise LostConnectionError, "the connection to the database has been lost" if @connection.closed?
210
+ end
211
+
212
+ def execute_reader
213
+ raise LostConnectionError, "the connection to the database has been lost" if @connection.closed?
214
+ end
215
+
216
+ def prepare
217
+ raise NotImplementedError
218
+ end
219
+
220
+ end
221
+
222
+ class NotImplementedError < StandardError
223
+ end
224
+
225
+ class ConnectionFailed < StandardError
226
+ end
227
+
228
+ class ReaderClosed < StandardError
229
+ end
230
+
231
+ class ReaderError < StandardError
232
+ end
233
+
234
+ class QueryError < StandardError
235
+ end
236
+
237
+ class NoInsertError < StandardError
238
+ end
239
+
240
+ class LostConnectionError < StandardError
241
+ end
242
+
243
+ class UnknownError < StandardError
244
+ end
245
+
246
+ end
@@ -0,0 +1,179 @@
1
+ require 'mysql_c'
2
+ require 'do'
3
+
4
+ module DataObject
5
+ module Mysql
6
+ TYPES = Hash[*Mysql_c.constants.select {|x| x.include?("MYSQL_TYPE")}.map {|x| [Mysql_c.const_get(x), x.gsub(/^MYSQL_TYPE_/, "")]}.flatten]
7
+
8
+ QUOTE_STRING = "\""
9
+ QUOTE_COLUMN = "`"
10
+
11
+ class Connection < DataObject::Connection
12
+ attr_reader :db
13
+
14
+ def initialize(connection_string)
15
+ @state = STATE_CLOSED
16
+ @connection_string = connection_string
17
+ opts = connection_string.split(" ")
18
+ opts.each do |opt|
19
+ k, v = opt.split("=")
20
+ raise ArgumentError, "you specified an invalid connection component: #{opt}" unless k && v
21
+ instance_variable_set("@#{k}", v)
22
+ end
23
+ end
24
+
25
+ def change_database(database_name)
26
+ @dbname = database_name
27
+ @connection_string.gsub(/db_name=[^ ]*/, "db_name=#{database_name}")
28
+ end
29
+
30
+ def open
31
+ @db = Mysql_c.mysql_init(nil)
32
+ raise ConnectionFailed, "could not allocate a MySQL connection" unless @db
33
+ conn = Mysql_c.mysql_real_connect(@db, @host, @user, @password, @dbname, @port || 0, @socket, @flags || 0)
34
+ raise ConnectionFailed, "The connection with connection string #{@connection_string} failed\n#{Mysql_c.mysql_error(@db)}" unless conn
35
+ @state = STATE_OPEN
36
+ true
37
+ end
38
+
39
+ def close
40
+ if @state == STATE_OPEN
41
+ Mysql_c.mysql_close(@db)
42
+ @state = STATE_CLOSED
43
+ true
44
+ else
45
+ false
46
+ end
47
+ end
48
+
49
+ def create_command(text)
50
+ Command.new(self, text)
51
+ end
52
+
53
+ end
54
+
55
+ class Reader < DataObject::Reader
56
+
57
+ def initialize(db, reader)
58
+ @reader = reader
59
+ unless @reader
60
+ if Mysql_c.mysql_field_count(db) == 0
61
+ @records_affected = Mysql_c.mysql_affected_rows(db)
62
+ close
63
+ else
64
+ raise UnknownError, "An unknown error has occured while trying to process a MySQL query.\n#{Mysql_c.mysql_error(db)}"
65
+ end
66
+ else
67
+ @field_count = Mysql_c.mysql_num_fields(@reader)
68
+ @state = STATE_OPEN
69
+ self.next
70
+ fields = Mysql_c.mysql_fetch_fields(@reader)
71
+ @native_fields = fields
72
+ raise UnknownError, "An unknown error has occured while trying to process a MySQL query. There were no fields in the resultset\n#{Mysql_c.mysql_error(db)}" unless fields
73
+ @fields = fields.map {|field| field.name}
74
+ @rows = Mysql_c.mysql_num_rows(@reader)
75
+ @has_rows = @rows > 0
76
+ end
77
+ end
78
+
79
+ def close
80
+ if @state != STATE_CLOSED
81
+ Mysql_c.mysql_free_result(@reader)
82
+ @state = STATE_CLOSED
83
+ true
84
+ else
85
+ false
86
+ end
87
+ end
88
+
89
+ def name(col)
90
+ super
91
+ @fields[col]
92
+ end
93
+
94
+ def get_index(name)
95
+ super
96
+ @fields.index(name)
97
+ end
98
+
99
+ def null?(idx)
100
+ super
101
+ @row[idx] == nil
102
+ end
103
+
104
+ def item(idx)
105
+ super
106
+ typecast(@row[idx], idx)
107
+ end
108
+
109
+ def next
110
+ super
111
+ @row = Mysql_c.mysql_fetch_row(@reader)
112
+ close if @row.nil?
113
+ @row ? true : nil
114
+ end
115
+
116
+ protected
117
+ def native_type(col)
118
+ super
119
+ TYPES[@native_fields[col].type]
120
+ end
121
+
122
+ def typecast(val, idx)
123
+ return nil if val.nil?
124
+ field = @native_fields[idx]
125
+ case TYPES[field.type]
126
+ when "TINY"
127
+ if field.max_length == 1
128
+ val != "0"
129
+ else
130
+ val.to_i
131
+ end
132
+ when "BIT"
133
+ val.to_i(2)
134
+ when "SHORT", "LONG", "INT24", "LONGLONG"
135
+ val.to_i
136
+ when "DECIMAL", "NEWDECIMAL", "FLOAT", "DOUBLE", "YEAR"
137
+ val.to_f
138
+ when "TIMESTAMP", "DATETIME"
139
+ DateTime.parse(val) rescue nil
140
+ when "TIME"
141
+ DateTime.parse(val).to_time rescue nil
142
+ when "DATE"
143
+ Date.parse(val) rescue nil
144
+ when "NULL"
145
+ nil
146
+ else
147
+ val
148
+ end
149
+ end
150
+
151
+
152
+ end
153
+
154
+ class Command < DataObject::Command
155
+
156
+ def execute_reader
157
+ super
158
+ result = Mysql_c.mysql_query(@connection.db, @text)
159
+ # TODO: Real Error
160
+ raise QueryError, "Your query failed.\n#{Mysql_c.mysql_error(@connection.db)}\n#{@text}" unless result == 0
161
+ reader = Mysql_c.mysql_store_result(@connection.db)
162
+ Reader.new(@connection.db, reader)
163
+ end
164
+
165
+ def execute_non_query
166
+ super
167
+ result = Mysql_c.mysql_query(@connection.db, @text)
168
+ raise QueryError, "Your query failed.\n#{Mysql_c.mysql_error(@connection.db)}\n#{@text}" unless result == 0
169
+ reader = Mysql_c.mysql_store_result(@connection.db)
170
+ raise QueryError, "You called execute_non_query on a query: #{@text}" if reader
171
+ rows_affected = Mysql_c.mysql_affected_rows(@connection.db)
172
+ Mysql_c.mysql_free_result(reader)
173
+ return ResultData.new(@connection, rows_affected, Mysql_c.mysql_insert_id(@connection.db))
174
+ end
175
+
176
+ end
177
+
178
+ end
179
+ end