1#!/usr/bin/perl -w
2
3use strict;
4
5use Rose::DateTime::Util qw(parse_date);
6
7BEGIN
8{
9  require Test::More;
10  eval { require DBD::Pg };
11
12  if($@)
13  {
14    Test::More->import(skip_all => 'Missing DBD::Pg');
15  }
16  else
17  {
18    Test::More->import(tests => 292);
19  }
20}
21
22BEGIN
23{
24  require 't/test-lib.pl';
25  use_ok('Rose::DB');
26}
27
28Rose::DB->default_domain('test');
29Rose::DB->default_type('pg');
30
31my $db = Rose::DB->new();
32
33ok(ref $db && $db->isa('Rose::DB'), 'new()');
34
35SKIP:
36{
37  skip("Could not connect to db", 15)  unless(have_db('pg'));
38
39  my $dbh = $db->dbh;
40
41  ok($dbh, 'dbh() 1');
42
43  ok($db->has_dbh, 'has_dbh() 1');
44
45  my $db2 = Rose::DB->new();
46
47  $db2->dbh($dbh);
48
49  foreach my $field (qw(dsn driver database host port username password))
50  {
51    is($db2->$field(), $db->$field(), "$field()");
52  }
53
54  # In DBD::Pg 3.5.0 and later, the default is -1 instead of false
55  ok((!$db->pg_enable_utf8 || $db->pg_enable_utf8 == -1), 'pg_enable_utf8 default');
56
57  $db->pg_enable_utf8(1);
58
59  ok($db->pg_enable_utf8 && $db->dbh->{'pg_enable_utf8'}, 'pg_enable_utf8 true');
60
61  SEQUENCE_PREP:
62  {
63    my $dbh = $db->dbh;
64    local $dbh->{'PrintError'} = 0;
65    local $dbh->{'RaiseError'} = 0;
66    $dbh->do('DROP SEQUENCE rose_db_sequence_test');
67  }
68
69  $dbh->do('CREATE SEQUENCE rose_db_sequence_test MINVALUE 5');
70
71  ok($db->sequence_exists('rose_db_sequence_test'), 'sequence_exists 1');
72  ok(!$db->sequence_exists('rose_db_sequence_testx'), 'sequence_exists 2');
73  is($db->current_value_in_sequence('rose_db_sequence_test'), 5, 'current_value_in_sequence 1');
74  is($db->next_value_in_sequence('rose_db_sequence_test'), 5, 'next_value_in_sequence 1');
75  is($db->current_value_in_sequence('rose_db_sequence_test'), 5, 'current_value_in_sequence 2');
76  is($db->next_value_in_sequence('rose_db_sequence_test'), 6, 'next_value_in_sequence 2');
77  is($db->current_value_in_sequence('rose_db_sequence_test'), 6, 'current_value_in_sequence 3');
78
79  $dbh->do('DROP SEQUENCE rose_db_sequence_test');
80  $db->disconnect;
81  $db2->disconnect;
82}
83
84$db = Rose::DB->new();
85
86$db->sslmode('allow');
87is($db->dsn, 'dbi:Pg:dbname=test;host=localhost;sslmode=allow', 'sslmode()');
88
89$db->options('opts');
90is($db->dsn, 'dbi:Pg:dbname=test;host=localhost;options=opts;sslmode=allow', 'options()');
91
92$db->service('srv');
93is($db->dsn, 'dbi:Pg:dbname=test;host=localhost;options=opts;service=srv;sslmode=allow', 'service()');
94
95$db = Rose::DB->new();
96
97ok(ref $db && $db->isa('Rose::DB'), "new()");
98
99$db->init_db_info;
100
101ok($db->supports_limit_with_offset, 'supports_limit_with_offset');
102
103ok($db->validate_timestamp_keyword('now'), 'validate_timestamp_keyword (now)');
104ok($db->validate_timestamp_keyword('infinity'), 'validate_timestamp_keyword (infinity)');
105ok($db->validate_timestamp_keyword('-infinity'), 'validate_timestamp_keyword (-infinity)');
106ok($db->validate_timestamp_keyword('epoch'), 'validate_timestamp_keyword (epoch)');
107ok($db->validate_timestamp_keyword('today'), 'validate_timestamp_keyword (today)');
108ok($db->validate_timestamp_keyword('tomorrow'), 'validate_timestamp_keyword (tomorrow)');
109ok($db->validate_timestamp_keyword('yesterday'), 'validate_timestamp_keyword (yesterday)');
110ok($db->validate_timestamp_keyword('allballs'), 'validate_timestamp_keyword (allballs)');
111
112is($db->format_timestamp('now'), 'now', 'format_timestamp (now)');
113is($db->format_timestamp('infinity'), 'infinity', 'format_timestamp (infinity)');
114is($db->format_timestamp('-infinity'), '-infinity', 'format_timestamp (-infinity)');
115is($db->format_timestamp('epoch'), 'epoch', 'format_timestamp (epoch)');
116is($db->format_timestamp('today'), 'today', 'format_timestamp (today)');
117is($db->format_timestamp('tomorrow'), 'tomorrow', 'format_timestamp (tomorrow)');
118is($db->format_timestamp('yesterday'), 'yesterday', 'format_timestamp (yesterday)');
119is($db->format_timestamp('allballs'), 'allballs', 'format_timestamp (allballs)');
120
121ok($db->validate_datetime_keyword('now'), 'validate_datetime_keyword (now)');
122ok($db->validate_datetime_keyword('infinity'), 'validate_datetime_keyword (infinity)');
123ok($db->validate_datetime_keyword('-infinity'), 'validate_datetime_keyword (-infinity)');
124ok($db->validate_datetime_keyword('epoch'), 'validate_datetime_keyword (epoch)');
125ok($db->validate_datetime_keyword('today'), 'validate_datetime_keyword (today)');
126ok($db->validate_datetime_keyword('tomorrow'), 'validate_datetime_keyword (tomorrow)');
127ok($db->validate_datetime_keyword('yesterday'), 'validate_datetime_keyword (yesterday)');
128ok($db->validate_datetime_keyword('allballs'), 'validate_datetime_keyword (allballs)');
129
130is($db->format_datetime('now'), 'now', 'format_datetime (now)');
131is($db->format_datetime('infinity'), 'infinity', 'format_datetime (infinity)');
132is($db->format_datetime('-infinity'), '-infinity', 'format_datetime (-infinity)');
133is($db->format_datetime('epoch'), 'epoch', 'format_datetime (epoch)');
134is($db->format_datetime('today'), 'today', 'format_datetime (today)');
135is($db->format_datetime('tomorrow'), 'tomorrow', 'format_datetime (tomorrow)');
136is($db->format_datetime('yesterday'), 'yesterday', 'format_datetime (yesterday)');
137is($db->format_datetime('allballs'), 'allballs', 'format_datetime (allballs)');
138
139ok($db->validate_date_keyword('now'), 'validate_date_keyword (now)');
140ok($db->validate_date_keyword('epoch'), 'validate_date_keyword (epoch)');
141ok($db->validate_date_keyword('today'), 'validate_date_keyword (today)');
142ok($db->validate_date_keyword('tomorrow'), 'validate_date_keyword (tomorrow)');
143ok($db->validate_date_keyword('yesterday'), 'validate_date_keyword (yesterday)');
144
145is($db->format_date('now'), 'now', 'format_date (now)');
146is($db->format_date('epoch'), 'epoch', 'format_date (epoch)');
147is($db->format_date('today'), 'today', 'format_date (today)');
148is($db->format_date('tomorrow'), 'tomorrow', 'format_date (tomorrow)');
149is($db->format_date('yesterday'), 'yesterday', 'format_date (yesterday)');
150
151ok($db->validate_time_keyword('now'), 'validate_time_keyword (now)');
152ok($db->validate_time_keyword('allballs'), 'validate_time_keyword (allballs)');
153
154is($db->format_time('now'), 'now', 'format_time (now)');
155is($db->format_time('allballs'), 'allballs', 'format_time (allballs)');
156
157is($db->parse_boolean('t'), 1, 'parse_boolean (t)');
158is($db->parse_boolean('true'), 1, 'parse_boolean (true)');
159is($db->parse_boolean('y'), 1, 'parse_boolean (y)');
160is($db->parse_boolean('yes'), 1, 'parse_boolean (yes)');
161is($db->parse_boolean('1'), 1, 'parse_boolean (1)');
162is($db->parse_boolean('TRUE'), 'TRUE', 'parse_boolean (TRUE)');
163
164is($db->parse_boolean('f'), 0, 'parse_boolean (f)');
165is($db->parse_boolean('false'), 0, 'parse_boolean (false)');
166is($db->parse_boolean('n'), 0, 'parse_boolean (n)');
167is($db->parse_boolean('no'), 0, 'parse_boolean (no)');
168is($db->parse_boolean('0'), 0, 'parse_boolean (0)');
169is($db->parse_boolean('FALSE'), 'FALSE', 'parse_boolean (FALSE)');
170
171ok(!$db->validate_boolean_keyword('Foo(Bar)'), 'validate_boolean_keyword (Foo(Bar))');
172$db->keyword_function_calls(1);
173is($db->parse_boolean('Foo(Bar)'), 'Foo(Bar)', 'parse_boolean (Foo(Bar))');
174$db->keyword_function_calls(0);
175
176foreach my $name (qw(date datetime time timestamp))
177{
178  my $method = "validate_${name}_keyword";
179
180  ok(!$db->$method('Foo(Bar)'), "$method (Foo(Bar)) 1");
181  $db->keyword_function_calls(1);
182  ok($db->$method('Foo(Bar)'), "$method (Foo(Bar)) 2");
183  $db->keyword_function_calls(0);
184
185
186  foreach my $value (qw(current_date current_time current_time()
187                        current_time(1) current_timestamp
188                        current_timestamp() current_timestamp(2)
189                        localtime localtime() localtime(3)
190                        localtimestamp localtimestamp()
191                        localtimestamp(4) now now() timeofday()))
192  {
193    my $new_value = $value;
194    my $i = int(rand(length($new_value) - 3)); # 3 = 1 + 2 (for possible parens)
195    substr($new_value, $i, 1) = uc substr($new_value, $i, 1);
196    ok($db->$method($new_value), "$method ($new_value)");
197  }
198}
199
200# Interval values
201
202isa_ok($db->parse_interval('00:00:00'), 'DateTime::Duration');
203
204SKIP:
205{
206  if($DateTime::Format::Pg::VERSION < 0.16011)
207  {
208    skip('interval tests - DateTime::Format::Pg version too low', 35);
209  }
210
211  my @Intervals =
212  (
213    '+0::'               => '@ 0',
214    '1 D'                => '@ 1 days',
215    '-1 d 2 s'           => '@ -1 days 2 seconds',
216    '-1 y 2 mons  3 d'   => '@ -10 months 3 days',
217    '-1 y 2 mons -3 d'   => '@ -10 months -3 days',
218
219    '5 h -208 m -495 s'  => '@ 92 minutes -495 seconds',
220    '-208 m -495 s'      => '@ -208 minutes -495 seconds',
221    '5 h 208 m 495 s'    => '@ 508 minutes 495 seconds',
222
223    '1 d 2 d'   => undef,
224
225    '1 ys 2 h 3 m 4 s'  => undef,
226
227    '1 mil 2 c 3 dec 4 y 5 mon 1 w -1 d 7 h 8 m 9 s' =>
228      '@ 14813 months 6 days 428 minutes 9 seconds',
229
230    '-1 mil -2 c -3 dec -4 y -5 mon -1 w 1 d -7 h -8 m -9 s' =>
231      '@ -14813 months -6 days -428 minutes -9 seconds',
232
233    '-1 mil -2 c -3 dec -4 y -5 mon -1 w 1 d -7 h -8 m -9 s ago' =>
234      '@ 14813 months 6 days 428 minutes 9 seconds',
235
236    '1 mils 2 cents 3 decs 4 years 5 mons 1 weeks -1 days 7 hours 8 mins 9 secs' =>
237      '@ 14813 months 6 days 428 minutes 9 seconds',
238    '1 millenniums 2 centuries 3 decades 4 years 5 months 1 weeks -1 days 7 hours 8 minutes 9 seconds' =>
239      '@ 14813 months 6 days 428 minutes 9 seconds',
240
241    '1 mil -1 d ago'     => '@ -12000 months 1 days',
242    '1 mil ago -1 d ago' => '@ -12000 months 1 days',
243  );
244
245  my %Alt_Intervals =
246  (
247    '+0::'               => '',
248    '-0:1:'              => '-00:01:00',
249    '2:'                 => '02:00:00',
250    '1 D'                => '1 day',
251    '-1 d 2 s'           => '-1 days +00:00:02',
252    '-1 y 2 mons  3 d'   => '-10 mons +3 days',
253    '-1 y 2 mons -3 d'   => '-10 mons -3 days',
254
255    '5 h -208 m -495 s' => '01:23:45',
256    '-208 m -495 s'     => '-03:36:15',
257    '5 h 208 m 495 s'   => '08:36:15',
258
259    '1 d 2 d'   => undef,
260
261    '1 ys 2 h 3 m 4 s'  => undef,
262    '1s ago'            => undef,
263
264    '1 mil 2 c 3 dec 4 y 5 mon 1 w -1 d 7 h 8 m 9 s'             => '1234 years 5 mons 6 days 07:08:09',
265    '-1 mil -2 c -3 dec -4 y -5 mon -1 w 1 d -7 h -8 m -9 s'     => '-1234 years -5 mons -6 days -07:08:09',
266    '-1 mil -2 c -3 dec -4 y -5 mon -1 w 1 d -7 h -8 m -9 s ago' => '1234 years 5 mons 6 days 07:08:09',
267
268    '1 mils 2 cents 3 decs 4 years 5 mons 1 weeks -1 days 7 hours 8 mins 9 secs' => '1234 years 5 mons 6 days 07:08:09',
269
270    '1 millenniums 2 centuries 3 decades 4 years 5 months 1 weeks -1 days 7 hours 8 minutes 9 seconds' =>
271        '1234 years 5 mons 6 days 07:08:09',
272
273    '1 mil -1 d ago'     => '-1000 years +1 day',
274    '1 mil ago -1 d ago' => '-1000 years +1 day',
275  );
276
277  my $i = 0;
278
279  while($i < @Intervals)
280  {
281    my($val, $formatted) = ($Intervals[$i], $Intervals[$i + 1]);
282    $i += 2;
283
284    my $d = $db->parse_interval($val, 'preserve');
285
286    is($db->format_interval($d), $formatted, "parse_interval ($val)");
287    my $alt_d = $db->parse_interval($Alt_Intervals{$val}, 'preserve');
288
289    ok((!defined $d && !defined $alt_d) || DateTime::Duration->compare($d, $alt_d) == 0, "parse_interval alt check $i ($val)");
290  }
291
292  $db->keyword_function_calls(1);
293  is($db->parse_interval('foo()'), 'foo()', 'parse_interval (foo())');
294  $db->keyword_function_calls(0);
295}
296
297# Time vaues
298
299my $tc;
300
301ok($tc = $db->parse_time('12:34:56.123456789'), 'parse time 12:34:56.123456789');
302is($tc->as_string, '12:34:56.123456789', 'check time 12:34:56.123456789');
303is($db->format_time($tc), '12:34:56.123456789', 'format time 12:34:56.123456789');
304
305ok($tc = $db->parse_time('12:34:56.123456789 pm'), 'parse time 12:34:56.123456789 pm');
306is($tc->as_string, '12:34:56.123456789', 'check time 12:34:56.123456789 pm');
307is($db->format_time($tc), '12:34:56.123456789', 'format time 12:34:56.123456789 pm');
308
309ok($tc = $db->parse_time('12:34:56. A.m.'), 'parse time 12:34:56. A.m.');
310is($tc->as_string, '00:34:56', 'check time 12:34:56 am');
311is($db->format_time($tc), '00:34:56', 'format time 12:34:56 am');
312
313ok($tc = $db->parse_time('12:34:56 pm'), 'parse time 12:34:56 pm');
314is($tc->as_string, '12:34:56', 'check time 12:34:56 pm');
315is($db->format_time($tc), '12:34:56', 'format time 12:34:56 pm');
316
317ok($tc = $db->parse_time('2:34:56 pm'), 'parse time 2:34:56 pm');
318is($tc->as_string, '14:34:56', 'check time 14:34:56 pm');
319is($db->format_time($tc), '14:34:56', 'format time 14:34:56 pm');
320
321ok($tc = $db->parse_time('2:34 pm'), 'parse time 2:34 pm');
322is($tc->as_string, '14:34:00', 'check time 2:34 pm');
323is($db->format_time($tc), '14:34:00', 'format time 2:34 pm');
324
325ok($tc = $db->parse_time('2 pm'), 'parse time 2 pm');
326is($tc->as_string, '14:00:00', 'check time 2 pm');
327is($db->format_time($tc), '14:00:00', 'format time 2 pm');
328
329ok($tc = $db->parse_time('3pm'), 'parse time 3pm');
330is($tc->as_string, '15:00:00', 'check time 3pm');
331is($db->format_time($tc), '15:00:00', 'format time 3pm');
332
333ok($tc = $db->parse_time('4 p.M.'), 'parse time 4 p.M.');
334is($tc->as_string, '16:00:00', 'check time 4 p.M.');
335is($db->format_time($tc), '16:00:00', 'format time 4 p.M.');
336
337ok($tc = $db->parse_time('24:00:00'), 'parse time 24:00:00');
338is($tc->as_string, '24:00:00', 'check time 24:00:00');
339is($db->format_time($tc), '24:00:00', 'format time 24:00:00');
340
341ok($tc = $db->parse_time('24:00:00 PM'), 'parse time 24:00:00 PM');
342is($tc->as_string, '24:00:00', 'check time 24:00:00 PM');
343is($db->format_time($tc), '24:00:00', 'format time 24:00:00 PM');
344
345ok($tc = $db->parse_time('24:00'), 'parse time 24:00');
346is($tc->as_string, '24:00:00', 'check time 24:00');
347is($db->format_time($tc), '24:00:00', 'format time 24:00');
348
349ok(!defined $db->parse_time('24:00:00.000000001'), 'parse time fail 24:00:00.000000001');
350ok(!defined $db->parse_time('24:00:01'), 'parse time fail 24:00:01');
351ok(!defined $db->parse_time('24:01'), 'parse time fail 24:01');
352
353SKIP:
354{
355  unless(have_db('pg'))
356  {
357    skip('pg tests', 48);
358  }
359
360  eval { $db->connect };
361  skip("Could not connect to db 'test', 'pg' - $@", 43)  if($@);
362  my $dbh = $db->dbh;
363
364  is($db->domain, 'test', "domain()");
365  is($db->type, 'pg', "type()");
366
367  is($db->print_error, $dbh->{'PrintError'}, 'print_error() 2');
368  is($db->print_error, $db->connect_option('PrintError'), 'print_error() 3');
369
370  is($db->null_date, '0000-00-00', "null_date()");
371  is($db->null_datetime, '0000-00-00 00:00:00', "null_datetime()");
372
373  is($db->format_date(parse_date('12/31/2002', 'floating')), '2002-12-31', "format_date() floating");
374  is($db->format_datetime(parse_date('12/31/2002 12:34:56.123456789', 'floating')), '2002-12-31 12:34:56.123456789', "format_datetime() floating");
375
376  is($db->format_timestamp(parse_date('12/31/2002 12:34:56.12345', 'floating')), '2002-12-31 12:34:56.123450000', "format_timestamp() floating");
377  is($db->format_datetime(parse_date('12/31/2002 12:34:56', 'floating')), '2002-12-31 12:34:56', "format_datetime() floating");
378
379  $db->server_time_zone('UTC');
380
381  is($db->format_date(parse_date('12/31/2002', 'UTC')), '2002-12-31', "format_date()");
382  is($db->format_datetime(parse_date('12/31/2002 12:34:56', 'UTC')), '2002-12-31 12:34:56+0000', "format_datetime()");
383
384  is($db->format_timestamp(parse_date('12/31/2002 12:34:56')), '2002-12-31 12:34:56', "format_timestamp()");
385  is($db->format_datetime(parse_date('12/31/2002 12:34:56')), '2002-12-31 12:34:56', "format_datetime()");
386
387  is($db->parse_date('12-31-2002'), parse_date('12/31/2002', 'UTC'),  "parse_date()");
388  is($db->parse_datetime('2002-12-31 12:34:56'), parse_date('12/31/2002 12:34:56', 'UTC'),  "parse_datetime()");
389  is($db->parse_timestamp('2002-12-31 12:34:56'), parse_date('12/31/2002 12:34:56', 'UTC'),  "parse_timestamp()");
390  like($db->parse_timestamp_with_time_zone('2002-12-31 12:34:56-05')->time_zone->name, qr/^-0*50*$/,  "parse_timestamp_with_time_zone()");
391  #is($db->parse_time('12:34:56'), parse_date('12/31/2002 12:34:56', 'UTC')->strftime('%H:%M:%S'),  "parse_time()");
392
393  $db->european_dates(1);
394
395  is($db->parse_date('31-12-2002'), parse_date('12/31/2002', 'UTC'),  "parse_date() european");
396  is($db->parse_datetime('2002-12-31 12:34:56'), parse_date('12/31/2002 12:34:56', 'UTC'),  "parse_datetime() european");
397  is($db->parse_timestamp('2002-12-31 12:34:56'), parse_date('12/31/2002 12:34:56', 'UTC'),  "parse_timestamp() european");
398
399  is($db->format_bitfield($db->parse_bitfield('1010')),
400     q(1010), "format_bitfield() 1");
401
402  is($db->format_bitfield($db->parse_bitfield(q(B'1010'))),
403     q(1010), "format_bitfield() 2");
404
405  is($db->format_bitfield($db->parse_bitfield(2), 4),
406     q(0010), "format_bitfield() 3");
407
408  is($db->format_bitfield($db->parse_bitfield('0xA'), 4),
409     q(1010), "format_bitfield() 4");
410
411  my $str = $db->format_array([ undef, 'a' .. 'c' ]);
412  is($str, '{NULL,"a","b","c"}', 'format_array() 1.0');
413
414  $str = $db->format_array([ 'a' .. 'c' ]);
415  is($str, '{"a","b","c"}', 'format_array() 2');
416
417  my $str2 = $db->format_array([ [ 'a' .. 'c' ], [ 'd', 'e' ] ]);
418  is($str2, '{{"a","b","c"},{"d","e"}}', 'format_array() 3');
419
420  my $ar = $db->parse_array('[-3:3]={1,2,3}');
421  ok(ref $ar eq 'ARRAY' && @$ar == 3 && $ar->[0] eq '1' && $ar->[1] eq '2' && $ar->[2] eq '3',
422     'parse_array() 1');
423
424  $ar = $db->parse_array('{NULL,"a","b"}');
425  ok(ref $ar eq 'ARRAY' && !defined $ar->[0] && $ar->[1] eq 'a' && $ar->[2] eq 'b',
426     'parse_array() 2');
427
428  $ar = $db->parse_array('{"a",NULL}');
429  ok(ref $ar eq 'ARRAY' && $ar->[0] eq 'a' && !defined $ar->[1],
430     'parse_array() 3');
431
432  $ar = $db->parse_array($str);
433  ok(ref $ar eq 'ARRAY' && $ar->[0] eq 'a' && $ar->[1] eq 'b' && $ar->[2] eq 'c',
434     'parse_array() 4');
435
436  $str = $db->format_array($ar);
437  is($str, '{"a","b","c"}', 'format_array() 2');
438
439  $str = $db->format_array([ 1, -2, 3.5 ]);
440  is($str, '{1,-2,3.5}', 'format_array() 3');
441
442  $ar = $db->parse_array($str);
443  ok(ref $ar eq 'ARRAY' && $ar->[0] == 1 && $ar->[1] == -2 && $ar->[2] == 3.5,
444     'parse_array() 2');
445
446  $str = $db->format_array($ar);
447  is($str, '{1,-2,3.5}', 'format_array() 4');
448
449  $str = $db->format_array(1, -2, 3.5);
450  is($str, '{1,-2,3.5}', 'format_array() 5');
451
452  $ar = $db->parse_array($str);
453  ok(ref $ar eq 'ARRAY' && $ar->[0] == 1 && $ar->[1] == -2 && $ar->[2] == 3.5,
454     'parse_array() 3');
455
456  #is($db->autocommit + 0, $dbh->{'AutoCommit'} + 0, 'autocommit() 1');
457
458  $db->autocommit(1);
459
460  is($db->autocommit + 0, 1, 'autocommit() 2');
461  is($dbh->{'AutoCommit'} + 0, 1, 'autocommit() 3');
462
463  $db->autocommit(0);
464
465  is($db->autocommit + 0, 0, 'autocommit() 4');
466  is($dbh->{'AutoCommit'} + 0, 0, 'autocommit() 5');
467
468  eval { $db->sequence_name(table => 'foo') };
469  ok($@, 'auto_sequence_name() 1');
470
471  eval { $db->sequence_name(column => 'bar') };
472  ok($@, 'auto_sequence_name() 2');
473
474  is($db->auto_sequence_name(table => 'foo.goo', column => 'bar'), 'foo.goo_bar_seq', 'auto_sequence_name() 3');
475
476  my $dbh_copy = $db->retain_dbh;
477
478  $db->disconnect;
479}
480
481(my $version = $DBI::VERSION) =~ s/_//g;
482
483if(have_db('pg') && $version >= 1.24)
484{
485  my $x = 0;
486  my $handler = sub { $x++ };
487
488  Rose::DB->register_db(
489    type         => 'error_handler',
490    driver       => 'pg',
491    database     => 'test',
492    host         => 'localhost',
493    print_error  => 0,
494    raise_error  => 1,
495    handle_error => $handler,
496  );
497
498  $db = Rose::DB->new('error_handler');
499
500  ok($db->raise_error, 'raise_error 1');
501  ok(!$db->print_error, 'print_error 1');
502  is($db->handle_error, $handler, 'handle_error 1');
503
504  $db->connect;
505
506  ok($db->raise_error, 'raise_error 2');
507  ok(!$db->print_error, 'print_error 2');
508  is($db->handle_error, $handler, 'handle_error 2');
509  is($db->dbh->{'HandleError'}, $handler, 'HandleError 1');
510
511  eval
512  {
513  	my $sth = $db->dbh->prepare('select nonesuch from ?');
514  	$sth->execute;
515  };
516
517  ok($@, 'handle_error 3');
518  is($x, 1, 'handle_error 4');
519
520  eval
521  {
522  	my $sth = $db->dbh->prepare('select nonesuch from ?');
523  	$sth->execute;
524  };
525
526  is($x, 2, 'handle_error 5');
527}
528else
529{
530  SKIP: { skip("HandleError tests (DBI $DBI::VERSION)", 10) }
531}
532
533SELECT_LOCK: {
534  no warnings 'once';
535  local *Rose::DB_Test::Object::table_sql_from_lock_on_value = sub { 'my_table' };
536
537  Rose::DB->register_db(
538    type     => 'select_lock',
539    driver   => 'pg',
540    database => 'test',
541  );
542
543  $db = Rose::DB->new('select_lock');
544
545  my $sql = $db->format_select_lock('Rose::DB_Test::Object', { type => 'shared', nowait => 1, skip_locked => 1 });
546  is($sql, 'FOR SHARE NOWAIT SKIP LOCKED', 'shared, nowait, skip_locked');
547
548  $sql = $db->format_select_lock('Rose::DB_Test::Object', { type => 'for update', nowait => 1, skip_locked => 1 });
549  is($sql, 'FOR UPDATE NOWAIT SKIP LOCKED', 'for update, nowait, skip_locked');
550
551  $sql = $db->format_select_lock('Rose::DB_Test::Object', { type => 'for update', nowait => 1 });
552  is($sql, 'FOR UPDATE NOWAIT', 'for update, nowait');
553
554  $sql = $db->format_select_lock('Rose::DB_Test::Object', { type => 'for update', skip_locked => 1 });
555  is($sql, 'FOR UPDATE SKIP LOCKED', 'for update, skip_locked');
556
557  $sql = $db->format_select_lock('Rose::DB_Test::Object', { type => 'shared' });
558  is($sql, 'FOR SHARE', 'shared');
559}
560