1#!/usr/bin/perl -w
2
3use strict;
4
5use Test::More tests => 1 + (2 * 13);
6
7BEGIN
8{
9  require 't/test-lib.pl';
10  use_ok('Rose::DB::Object::Loader');
11}
12
13our %Have;
14
15#
16# Tests
17#
18
19#$Rose::DB::Object::Manager::Debug = 1;
20
21foreach my $db_type (qw(pg mysql))
22{
23  SKIP:
24  {
25    skip("$db_type tests", 13)  unless($Have{$db_type});
26  }
27
28  next  unless($Have{$db_type});
29
30  Rose::DB->default_type($db_type);
31
32  my $class_prefix =  ucfirst($db_type);
33
34  my $loader =
35    Rose::DB::Object::Loader->new(
36      db           => Rose::DB->new,
37      class_prefix => $class_prefix);
38
39  my @classes = $loader->make_classes(include_tables => '^rose_db_object_test$');
40
41  my $object_class  = $class_prefix . '::RoseDbObjectTest';
42  my $manager_class = $object_class . '::Manager';
43
44  my $data = "\000\001\002\003\004\005" x 10;
45
46  # Standard save
47
48  my $o = $object_class->new(num => 123, data => $data);
49  $o->save;
50
51  $o = $object_class->new(id => $o->id)->load;
52  is($o->data, $data, "save 1 - $db_type");
53
54  $o->save;
55
56  $o = $object_class->new(id => $o->id)->load;
57  is($o->data, $data, "save 2 - $db_type");
58
59  # Changes only
60
61  my $short_data = "\000\001\002\003\004\005";
62
63  $o->data($short_data);
64  $o->save(changes_only => 1);
65
66  $o = $object_class->new(id => $o->id)->load;
67  is($o->data, $short_data, "update changes only - $db_type");
68
69  $o = $object_class->new(data => $short_data);
70  $o->save(changes_only => 1);
71
72  $o = $object_class->new(id => $o->id)->load;
73  is($o->data, $short_data, "insert changes only - $db_type");
74
75  # On duplicate key update
76
77  if($o->db->supports_on_duplicate_key_update)
78  {
79    # Force the bind_param code to be triggered (should be harmless)
80    local $object_class->meta->{'dbi_requires_bind_param'}{$o->db->{'id'}} = 1;
81
82    my $data = "\000\001\002";
83
84    $o->data($data);
85    $o->insert(on_duplicate_key_update => 1);
86
87    $o = $object_class->new(id => $o->id)->load;
88    is($o->data, $data, "on duplicate key update - $db_type");
89  }
90  else
91  {
92    ok(1, "on duplicate key update not supported - $db_type");
93  }
94
95  #
96  # Allow inline column values
97  #
98
99  $object_class->meta->allow_inline_column_values(1);
100  $manager_class->delete_rose_db_object_test(all => 1);
101
102  $data = "\000\001\002\003\004\005" x 10;
103
104  # Standard save
105
106  $o = $object_class->new(num => 123, data => $data);
107
108  $o->save;
109
110  $o = $object_class->new(id => $o->id)->load;
111  is($o->data, $data, "inline - save 1 - $db_type");
112
113  $o->save;
114
115  $o = $object_class->new(id => $o->id)->load;
116  is($o->data, $data, "inline - save 2 - $db_type");
117
118  # Changes only
119
120  $short_data = "\000\001\002\003\004\005";
121
122  $o->data($short_data);
123  $o->save(changes_only => 1);
124
125  $o = $object_class->new(id => $o->id)->load;
126  is($o->data, $short_data, "inline - update changes only - $db_type");
127
128  $o = $object_class->new(data => $short_data);
129  $o->save(changes_only => 1);
130
131  $o = $object_class->new(id => $o->id)->load;
132  is($o->data, $short_data, "inline - insert changes only - $db_type");
133
134  # On duplicate key update
135
136  if($o->db->supports_on_duplicate_key_update)
137  {
138    # Force the bind_param code to be triggered (should be harmless)
139    local $object_class->meta->{'dbi_requires_bind_param'}{$o->db->{'id'}} = 1;
140
141    my $data = "\000\001\002";
142
143    $o->data($data);
144    $o->insert(on_duplicate_key_update => 1);
145
146    $o = $object_class->new(id => $o->id)->load;
147    is($o->data, $data, "inline - on duplicate key update - $db_type");
148  }
149  else
150  {
151    ok(1, "inline - on duplicate key update not supported - $db_type");
152  }
153
154  #
155  # Manager
156  #
157
158  my $os =
159    $manager_class->get_rose_db_object_test(
160      query => [ data => $o->data, id => $o->id ]);
161
162  ok($os && @$os == 1 && $os->[0]->id == $o->id, "manager 1 - $db_type");
163
164  $os =
165    $manager_class->get_rose_db_object_test(
166      query =>
167      [
168        data => [ "\000\001", $o->data ],
169        or =>
170        [
171          data => [ "\000\002", $o->data ],
172          id   => { ne => [ 123, 456 ] },
173        ],
174        id => $o->id ]);
175
176  ok($os && @$os == 1 && $os->[0]->id == $o->id, "manager 2 - $db_type");
177
178  #local $Rose::DB::Object::Manager::Debug = 1;
179  $os =
180    $manager_class->get_rose_db_object_test(
181      query =>
182      [
183        data => [ "\000\001", $o->data ],
184        num  => undef,
185        or =>
186        [
187          data => [ "\000\002", $o->data ],
188          id   => { ne => [ 123, 456 ] },
189          or =>
190          [
191            data => [ "\001\003", $o->data ],
192            data => { ne => "\000" },
193            id   => { ne => undef },
194            num  => undef,
195            '!data' => "\002\003",
196            data => $o->data,
197          ]
198        ],
199        id => $o->id ]);
200
201  ok($os && @$os == 1 && $os->[0]->id == $o->id, "manager 3 - $db_type");
202}
203
204BEGIN
205{
206  our %Have;
207
208  #
209  # PostgreSQL
210  #
211
212  my $dbh;
213
214  eval
215  {
216    $dbh = Rose::DB->new('pg_admin')->retain_dbh()
217      or die Rose::DB->error;
218  };
219
220  if(!$@ && $dbh)
221  {
222    $Have{'pg'} = 1;
223    $Have{'pg_with_schema'} = 1;
224
225    # Drop existing tables and create schema, ignoring errors
226    {
227      local $dbh->{'RaiseError'} = 0;
228      local $dbh->{'PrintError'} = 0;
229      $dbh->do('DROP TABLE rose_db_object_test');
230    }
231
232    $dbh->do(<<"EOF");
233CREATE TABLE rose_db_object_test
234(
235  id    SERIAL PRIMARY KEY,
236  num   INT,
237  data  BYTEA
238)
239EOF
240
241    $dbh->disconnect;
242  }
243
244  #
245  # MySQL
246  #
247
248  eval
249  {
250    my $db = Rose::DB->new('mysql_admin');
251    $dbh = $db->retain_dbh or die Rose::DB->error;
252
253    # Drop existing tables, ignoring errors
254    {
255      local $dbh->{'RaiseError'} = 0;
256      local $dbh->{'PrintError'} = 0;
257      $dbh->do('DROP TABLE rose_db_object_test');
258    }
259  };
260
261  if(!$@ && $dbh)
262  {
263    $Have{'mysql'} = 1;
264
265    $dbh->do(<<"EOF");
266CREATE TABLE rose_db_object_test
267(
268  id    INT AUTO_INCREMENT PRIMARY KEY,
269  num   INT,
270  data  BLOB
271)
272EOF
273  }
274}
275
276END
277{
278  # Delete test table
279
280  if($Have{'pg'})
281  {
282    # PostgreSQL
283    my $dbh = Rose::DB->new('pg_admin')->retain_dbh()
284      or die Rose::DB->error;
285
286    $dbh->do('DROP TABLE rose_db_object_test');
287    $dbh->disconnect;
288  }
289
290  if($Have{'mysql'})
291  {
292    # MySQL
293    my $dbh = Rose::DB->new('mysql_admin')->retain_dbh()
294      or die Rose::DB->error;
295
296    $dbh->do('DROP TABLE rose_db_object_test');
297    $dbh->disconnect;
298  }
299}
300