datamapper 0.2.0 → 0.2.1

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 (72) hide show
  1. data/CHANGELOG +20 -1
  2. data/environment.rb +5 -3
  3. data/lib/data_mapper.rb +42 -23
  4. data/lib/data_mapper/adapters/data_object_adapter.rb +76 -73
  5. data/lib/data_mapper/adapters/mysql_adapter.rb +15 -1
  6. data/lib/data_mapper/adapters/postgresql_adapter.rb +1 -1
  7. data/lib/data_mapper/adapters/sql/commands/load_command.rb +242 -28
  8. data/lib/data_mapper/adapters/sql/mappings/column.rb +18 -1
  9. data/lib/data_mapper/adapters/sql/mappings/table.rb +20 -32
  10. data/lib/data_mapper/adapters/sql/quoting.rb +40 -7
  11. data/lib/data_mapper/adapters/sqlite3_adapter.rb +7 -1
  12. data/lib/data_mapper/associations/has_and_belongs_to_many_association.rb +6 -1
  13. data/lib/data_mapper/associations/has_many_association.rb +1 -1
  14. data/lib/data_mapper/context.rb +4 -2
  15. data/lib/data_mapper/database.rb +2 -12
  16. data/lib/data_mapper/support/active_record_impersonation.rb +1 -1
  17. data/lib/data_mapper/support/blank.rb +2 -2
  18. data/lib/data_mapper/support/serialization.rb +60 -4
  19. data/lib/data_mapper/support/string.rb +24 -2
  20. data/lib/data_mapper/validations/validation_errors.rb +6 -3
  21. data/performance.rb +20 -5
  22. data/plugins/dataobjects/Rakefile +2 -0
  23. data/plugins/dataobjects/do.rb +18 -8
  24. data/plugins/dataobjects/do_mysql.rb +57 -24
  25. data/plugins/dataobjects/do_postgres.rb +3 -7
  26. data/plugins/dataobjects/do_sqlite3.rb +18 -17
  27. data/plugins/dataobjects/swig_mysql/Makefile +146 -0
  28. data/plugins/dataobjects/swig_mysql/extconf.rb +13 -1
  29. data/plugins/dataobjects/swig_mysql/mkmf.log +24 -0
  30. data/plugins/dataobjects/swig_mysql/mysql_c.bundle +0 -0
  31. data/plugins/dataobjects/swig_mysql/mysql_c.c +303 -2501
  32. data/plugins/dataobjects/swig_mysql/mysql_c.i +63 -4
  33. data/plugins/dataobjects/swig_mysql/mysql_c.o +0 -0
  34. data/profile_data_mapper.rb +4 -4
  35. data/rakefile.rb +13 -7
  36. data/spec/acts_as_tree_spec.rb +2 -0
  37. data/spec/associations_spec.rb +12 -0
  38. data/spec/attributes_spec.rb +2 -0
  39. data/spec/base_spec.rb +2 -0
  40. data/spec/callbacks_spec.rb +2 -0
  41. data/spec/can_has_sphinx.rb +0 -1
  42. data/spec/coersion_spec.rb +10 -3
  43. data/spec/column_spec.rb +23 -0
  44. data/spec/conditions_spec.rb +18 -18
  45. data/spec/count_command_spec.rb +2 -0
  46. data/spec/dataobjects_spec.rb +26 -0
  47. data/spec/delete_command_spec.rb +2 -0
  48. data/spec/embedded_value_spec.rb +2 -0
  49. data/spec/fixtures/people.yaml +1 -1
  50. data/spec/fixtures/posts.yaml +3 -0
  51. data/spec/legacy_spec.rb +2 -0
  52. data/spec/load_command_spec.rb +28 -2
  53. data/spec/magic_columns_spec.rb +2 -0
  54. data/spec/models/person.rb +1 -1
  55. data/spec/models/post.rb +8 -0
  56. data/spec/query_spec.rb +2 -0
  57. data/spec/save_command_spec.rb +2 -0
  58. data/spec/schema_spec.rb +2 -0
  59. data/spec/serialization_spec.rb +58 -0
  60. data/spec/single_table_inheritance_spec.rb +2 -0
  61. data/spec/symbolic_operators_spec.rb +2 -0
  62. data/spec/validates_confirmation_of_spec.rb +2 -0
  63. data/spec/validates_format_of_spec.rb +2 -0
  64. data/spec/validates_length_of_spec.rb +2 -0
  65. data/spec/validates_uniqueness_of_spec.rb +2 -0
  66. data/spec/validations_spec.rb +2 -0
  67. data/tasks/fixtures.rb +15 -10
  68. metadata +10 -13
  69. data/lib/data_mapper/adapters/sql/commands/conditions.rb +0 -130
  70. data/lib/data_mapper/adapters/sql/commands/loader.rb +0 -99
  71. data/plugins/dataobjects/swig_mysql/do_mysql.bundle +0 -0
  72. data/spec/conversions_to_yaml_spec.rb +0 -17
@@ -1,5 +1,7 @@
1
1
  require 'spec/rake/spectask'
2
2
 
3
+ task :default => 'specs'
4
+
3
5
  desc "Run all specs"
4
6
  Spec::Rake::SpecTask.new('specs') do |t|
5
7
  t.spec_opts = ["--format", "specdoc", "--colour"]
@@ -87,15 +87,14 @@ module DataObject
87
87
  class Reader
88
88
  include Enumerable
89
89
 
90
- attr_reader :field_count, :has_rows, :records_affected, :fields
91
- alias_method :has_rows?, :has_rows
90
+ attr_reader :field_count, :records_affected, :fields
92
91
 
93
92
  def each
94
- return nil unless has_rows
95
- while(true) do
96
- yield
97
- break unless self.next
98
- end
93
+ raise NotImplementedError
94
+ end
95
+
96
+ def has_rows?
97
+ @has_rows
99
98
  end
100
99
 
101
100
  def current_row
@@ -106,7 +105,18 @@ module DataObject
106
105
  ret
107
106
  end
108
107
 
109
- def close
108
+ def open?
109
+ @state != STATE_CLOSED
110
+ end
111
+
112
+ def close
113
+ real_close
114
+ @reader = nil
115
+ @state = STATE_CLOSED
116
+ true
117
+ end
118
+
119
+ def real_close
110
120
  raise NotImplementedError
111
121
  end
112
122
 
@@ -9,9 +9,22 @@ module DataObject
9
9
  QUOTE_COLUMN = "`"
10
10
 
11
11
  class Connection < DataObject::Connection
12
+
13
+ def self.conns
14
+ @conns
15
+ end
16
+
17
+ def self.conns=(val)
18
+ @conns = val
19
+ end
20
+
21
+ self.conns = 0
22
+
12
23
  attr_reader :db
13
24
 
14
25
  def initialize(connection_string)
26
+ @num = (self.class.conns += 1)
27
+
15
28
  @state = STATE_CLOSED
16
29
  @connection_string = connection_string
17
30
  opts = connection_string.split(" ")
@@ -52,9 +65,17 @@ module DataObject
52
65
 
53
66
  end
54
67
 
55
- class Reader < DataObject::Reader
68
+ class Field
69
+ attr_reader :name, :type
70
+
71
+ def initialize(ptr)
72
+ @name, @type = ptr.name.to_s, ptr.type.to_s
73
+ end
74
+ end
56
75
 
57
- def initialize(db, reader)
76
+ class Reader < DataObject::Reader
77
+
78
+ def initialize(db, reader)
58
79
  @reader = reader
59
80
  unless @reader
60
81
  if Mysql_c.mysql_field_count(db) == 0
@@ -64,20 +85,19 @@ module DataObject
64
85
  raise UnknownError, "An unknown error has occured while trying to process a MySQL query.\n#{Mysql_c.mysql_error(db)}"
65
86
  end
66
87
  else
67
- @field_count = Mysql_c.mysql_num_fields(@reader)
88
+ @field_count = @reader.field_count
68
89
  @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
90
+
91
+ @native_fields, @fields = Mysql_c.mysql_c_fetch_field_types(@reader, @field_count), Mysql_c.mysql_c_fetch_field_names(@reader, @field_count)
92
+
93
+ 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)}" if @native_fields.empty?
94
+
95
+ @has_rows = !(@row = Mysql_c.mysql_c_fetch_row(@reader)).nil?
76
96
  end
77
97
  end
78
98
 
79
99
  def close
80
- if @state != STATE_CLOSED
100
+ if @state == STATE_OPEN
81
101
  Mysql_c.mysql_free_result(@reader)
82
102
  @state = STATE_CLOSED
83
103
  true
@@ -101,6 +121,10 @@ module DataObject
101
121
  @row[idx] == nil
102
122
  end
103
123
 
124
+ def current_row
125
+ @row
126
+ end
127
+
104
128
  def item(idx)
105
129
  super
106
130
  typecast(@row[idx], idx)
@@ -108,9 +132,18 @@ module DataObject
108
132
 
109
133
  def next
110
134
  super
111
- @row = Mysql_c.mysql_fetch_row(@reader)
135
+ @row = Mysql_c.mysql_c_fetch_row(@reader)
112
136
  close if @row.nil?
113
137
  @row ? true : nil
138
+ end
139
+
140
+ def each
141
+ return unless has_rows?
142
+
143
+ while(true) do
144
+ yield
145
+ break unless self.next
146
+ end
114
147
  end
115
148
 
116
149
  protected
@@ -122,13 +155,9 @@ module DataObject
122
155
  def typecast(val, idx)
123
156
  return nil if val.nil?
124
157
  field = @native_fields[idx]
125
- case TYPES[field.type]
158
+ case TYPES[field]
126
159
  when "TINY"
127
- if field.max_length == 1
128
- val != "0"
129
- else
130
- val.to_i
131
- end
160
+ val != "0"
132
161
  when "BIT"
133
162
  val.to_i(2)
134
163
  when "SHORT", "LONG", "INT24", "LONGLONG"
@@ -146,9 +175,7 @@ module DataObject
146
175
  else
147
176
  val
148
177
  end
149
- end
150
-
151
-
178
+ end
152
179
  end
153
180
 
154
181
  class Command < DataObject::Command
@@ -157,9 +184,15 @@ module DataObject
157
184
  super
158
185
  result = Mysql_c.mysql_query(@connection.db, @text)
159
186
  # 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)
187
+ raise QueryError, "Your query failed.\n#{Mysql_c.mysql_error(@connection.db)}\n#{@text}" unless result == 0
188
+ reader = Reader.new(@connection.db, Mysql_c.mysql_use_result(@connection.db))
189
+ if block_given?
190
+ result = yield(reader)
191
+ reader.close
192
+ result
193
+ else
194
+ reader
195
+ end
163
196
  end
164
197
 
165
198
  def execute_non_query
@@ -61,13 +61,9 @@ module DataObject
61
61
  end
62
62
 
63
63
  def close
64
- if @state != STATE_CLOSED
65
- Postgres_c.PQclear(@reader)
66
- @state = STATE_CLOSED
67
- true
68
- else
69
- false
70
- end
64
+ Postgres_c.PQclear(@reader)
65
+ @state = STATE_CLOSED
66
+ true
71
67
  end
72
68
 
73
69
  def data_type_name(col)
@@ -69,14 +69,8 @@ module DataObject
69
69
  end
70
70
  end
71
71
 
72
- def close
73
- if @state != STATE_CLOSED
74
- Sqlite3_c.sqlite3_finalize(@reader)
75
- @state = STATE_CLOSED
76
- true
77
- else
78
- false
79
- end
72
+ def real_close
73
+ Sqlite3_c.sqlite3_finalize(@reader)
80
74
  end
81
75
 
82
76
  def name(idx)
@@ -106,13 +100,12 @@ module DataObject
106
100
  end
107
101
  end
108
102
 
109
- def next
110
- result = Sqlite3_c.sqlite3_step(@reader)
111
- unless result == Sqlite3_c::SQLITE_ROW
112
- close
113
- nil
114
- else
115
- true
103
+ def each
104
+ return unless has_rows?
105
+
106
+ while(true) do
107
+ yield
108
+ break unless Sqlite3_c.sqlite3_step(@reader) == Sqlite3_c::SQLITE_ROW
116
109
  end
117
110
  end
118
111
 
@@ -122,11 +115,19 @@ module DataObject
122
115
 
123
116
  def execute_reader
124
117
  super
125
- result, reader = Sqlite3_c.sqlite3_prepare_v2(@connection.db, @text, @text.size + 1)
118
+ result, ptr = Sqlite3_c.sqlite3_prepare_v2(@connection.db, @text, @text.size + 1)
126
119
  unless result == Sqlite3_c::SQLITE_OK
127
120
  raise QueryError, "Your query failed.\n#{Sqlite3_c.sqlite3_errmsg(@connection.db)}\nQUERY: \"#{@text}\""
128
121
  else
129
- Reader.new(@connection.db, reader)
122
+ reader = Reader.new(@connection.db, ptr)
123
+
124
+ if block_given?
125
+ return_value = yield(reader)
126
+ reader.close
127
+ return_value
128
+ else
129
+ reader
130
+ end
130
131
  end
131
132
  end
132
133
 
@@ -0,0 +1,146 @@
1
+
2
+ SHELL = /bin/sh
3
+
4
+ #### Start of system configuration section. ####
5
+
6
+ srcdir = .
7
+ topdir = /opt/local/lib/ruby/1.8/i686-darwin8.9.1
8
+ hdrdir = $(topdir)
9
+ VPATH = $(srcdir):$(topdir):$(hdrdir)
10
+ prefix = $(DESTDIR)/opt/local
11
+ exec_prefix = $(DESTDIR)/opt/local
12
+ sitedir = $(prefix)/lib/ruby/site_ruby
13
+ rubylibdir = $(libdir)/ruby/$(ruby_version)
14
+ archdir = $(rubylibdir)/$(arch)
15
+ sbindir = $(exec_prefix)/sbin
16
+ vendordir = $(prefix)/lib/ruby/vendor_ruby
17
+ datadir = $(prefix)/share
18
+ includedir = $(prefix)/include
19
+ infodir = $(prefix)/info
20
+ sysconfdir = $(prefix)/etc
21
+ mandir = $(DESTDIR)/opt/local/share/man
22
+ libdir = $(DESTDIR)/opt/local/lib
23
+ sharedstatedir = $(prefix)/com
24
+ oldincludedir = $(DESTDIR)/usr/include
25
+ sitearchdir = $(sitelibdir)/$(sitearch)
26
+ vendorarchdir = $(vendorlibdir)/$(vendorarch)
27
+ bindir = $(exec_prefix)/bin
28
+ localstatedir = $(prefix)/var
29
+ vendorlibdir = $(vendordir)/$(ruby_version)
30
+ sitelibdir = $(sitedir)/$(ruby_version)
31
+ libexecdir = $(exec_prefix)/libexec
32
+
33
+ CC = gcc
34
+ LIBRUBY = $(LIBRUBY_SO)
35
+ LIBRUBY_A = lib$(RUBY_SO_NAME)-static.a
36
+ LIBRUBYARG_SHARED = -l$(RUBY_SO_NAME)
37
+ LIBRUBYARG_STATIC = -l$(RUBY_SO_NAME)-static
38
+
39
+ RUBY_EXTCONF_H =
40
+ CFLAGS = -fno-common -O -pipe -I/opt/local/include -fno-common -pipe -fno-common -Wall
41
+ INCFLAGS = -I. -I. -I/opt/local/lib/ruby/1.8/i686-darwin8.9.1 -I.
42
+ CPPFLAGS = -I/usr/local/mysql/include -O -pipe -I/opt/local/include
43
+ CXXFLAGS = $(CFLAGS)
44
+ DLDFLAGS = -L/opt/local/lib
45
+ LDSHARED = cc -dynamic -bundle -undefined suppress -flat_namespace
46
+ AR = ar
47
+ EXEEXT =
48
+
49
+ RUBY_INSTALL_NAME = ruby
50
+ RUBY_SO_NAME = ruby
51
+ arch = i686-darwin8.9.1
52
+ sitearch = i686-darwin8.9.1
53
+ vendorarch = i686-darwin8.9.1
54
+ ruby_version = 1.8
55
+ ruby = /opt/local/bin/ruby
56
+ RUBY = $(ruby)
57
+ RM = rm -f
58
+ MAKEDIRS = mkdir -p
59
+ INSTALL = /usr/bin/install -c
60
+ INSTALL_PROG = $(INSTALL) -m 0755
61
+ INSTALL_DATA = $(INSTALL) -m 644
62
+ COPY = cp
63
+
64
+ #### End of system configuration section. ####
65
+
66
+ preload =
67
+
68
+ libpath = $(libdir) /usr/local/mysql/lib -lmysqlclient_r -lz -lm
69
+ LIBPATH = -L"$(libdir)" -L""/usr/local/mysql/lib -lmysqlclient_r -lz -lm""
70
+ DEFFILE =
71
+
72
+ CLEANFILES =
73
+ DISTCLEANFILES =
74
+
75
+ extout =
76
+ extout_prefix =
77
+ target_prefix =
78
+ LOCAL_LIBS =
79
+ LIBS = $(LIBRUBYARG_SHARED) -lmysqlclient -lpthread -ldl -lobjc
80
+ SRCS = mysql_c.c
81
+ OBJS = mysql_c.o
82
+ TARGET = mysql_c
83
+ DLLIB = $(TARGET).bundle
84
+ EXTSTATIC =
85
+ STATIC_LIB =
86
+
87
+ RUBYCOMMONDIR = $(sitedir)$(target_prefix)
88
+ RUBYLIBDIR = $(sitelibdir)$(target_prefix)
89
+ RUBYARCHDIR = $(sitearchdir)$(target_prefix)
90
+
91
+ TARGET_SO = $(DLLIB)
92
+ CLEANLIBS = $(TARGET).bundle $(TARGET).il? $(TARGET).tds $(TARGET).map
93
+ CLEANOBJS = *.o *.a *.s[ol] *.pdb *.exp *.bak
94
+
95
+ all: $(DLLIB)
96
+ static: $(STATIC_LIB)
97
+
98
+ clean:
99
+ @-$(RM) $(CLEANLIBS) $(CLEANOBJS) $(CLEANFILES)
100
+
101
+ distclean: clean
102
+ @-$(RM) Makefile $(RUBY_EXTCONF_H) conftest.* mkmf.log
103
+ @-$(RM) core ruby$(EXEEXT) *~ $(DISTCLEANFILES)
104
+
105
+ realclean: distclean
106
+ install: install-so install-rb
107
+
108
+ install-so: $(RUBYARCHDIR)
109
+ install-so: $(RUBYARCHDIR)/$(DLLIB)
110
+ $(RUBYARCHDIR)/$(DLLIB): $(DLLIB)
111
+ $(INSTALL_PROG) $(DLLIB) $(RUBYARCHDIR)
112
+ install-rb: pre-install-rb install-rb-default
113
+ install-rb-default: pre-install-rb-default
114
+ pre-install-rb: Makefile
115
+ pre-install-rb-default: Makefile
116
+ $(RUBYARCHDIR):
117
+ $(MAKEDIRS) $@
118
+
119
+ site-install: site-install-so site-install-rb
120
+ site-install-so: install-so
121
+ site-install-rb: install-rb
122
+
123
+ .SUFFIXES: .c .m .cc .cxx .cpp .C .o
124
+
125
+ .cc.o:
126
+ $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c $<
127
+
128
+ .cxx.o:
129
+ $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c $<
130
+
131
+ .cpp.o:
132
+ $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c $<
133
+
134
+ .C.o:
135
+ $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c $<
136
+
137
+ .c.o:
138
+ $(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) -c $<
139
+
140
+ $(DLLIB): $(OBJS)
141
+ @-$(RM) $@
142
+ $(LDSHARED) $(DLDFLAGS) $(LIBPATH) -o $@ $(OBJS) $(LOCAL_LIBS) $(LIBS)
143
+
144
+
145
+
146
+ $(OBJS): ruby.h defines.h
@@ -1,11 +1,23 @@
1
1
  require 'mkmf'
2
+ require 'open3'
2
3
 
3
4
  def config_value(type)
4
5
  ENV["MYSQL_#{type.upcase}"] || mysql_config(type)
5
6
  end
6
7
 
7
8
  def mysql_config(type)
8
- IO.popen("mysql_config5 --#{type}").readline.chomp[2..-1] rescue IO.popen("mysql_config --#{type}").readline.chomp[2..-1] rescue nil
9
+
10
+ sin, sout, serr = Open3.popen3("mysql_config5 --#{type}")
11
+
12
+ unless serr.read.empty?
13
+ sin, sout, serr = Open3.popen3("mysql_config --#{type}")
14
+ end
15
+
16
+ unless serr.read.empty?
17
+ raise "mysql_config not found"
18
+ end
19
+
20
+ sout.readline.chomp[2..-1]
9
21
  end
10
22
 
11
23
  $inc, $lib = dir_config('mysql', config_value('include'), config_value('libs_r'))
@@ -0,0 +1,24 @@
1
+ find_library: checking for mysql_query() in -lmysqlclient... -------------------- yes
2
+
3
+ "gcc -o conftest -I. -I/opt/local/lib/ruby/1.8/i686-darwin8.9.1 -I. -I/usr/local/mysql/include -O -pipe -I/opt/local/include -O -pipe -I/opt/local/include -fno-common -pipe -fno-common conftest.c -L"/opt/local/lib" -L""/usr/local/mysql/lib -lmysqlclient_r -lz -lm"" -L/opt/local/lib -lruby-static -lmysqlclient -lpthread -ldl -lobjc "
4
+ conftest.c: In function ‘t’:
5
+ conftest.c:3: error: ‘mysql_query’ undeclared (first use in this function)
6
+ conftest.c:3: error: (Each undeclared identifier is reported only once
7
+ conftest.c:3: error: for each function it appears in.)
8
+ checked program was:
9
+ /* begin */
10
+ 1: /*top*/
11
+ 2: int main() { return 0; }
12
+ 3: int t() { void ((*volatile p)()); p = (void ((*)()))mysql_query; return 0; }
13
+ /* end */
14
+
15
+ "gcc -o conftest -I. -I/opt/local/lib/ruby/1.8/i686-darwin8.9.1 -I. -I/usr/local/mysql/include -O -pipe -I/opt/local/include -O -pipe -I/opt/local/include -fno-common -pipe -fno-common conftest.c -L"/opt/local/lib" -L""/usr/local/mysql/lib -lmysqlclient_r -lz -lm"" -L/opt/local/lib -lruby-static -lmysqlclient -lpthread -ldl -lobjc "
16
+ checked program was:
17
+ /* begin */
18
+ 1: /*top*/
19
+ 2: int main() { return 0; }
20
+ 3: int t() { mysql_query(); return 0; }
21
+ /* end */
22
+
23
+ --------------------
24
+