Codebase list libjifty-dbi-perl / 3d2f462
[svn-upgrade] Integrating new upstream version, libjifty-dbi-perl (0.57) Yves Agostini 15 years ago
18 changed file(s) with 522 addition(s) and 48 deletion(s). Raw diff Collapse all Expand all
0 MANIFEST
1 MANIFEST.bak
2 META.yml
3 Makefile
4 Makefile.old
5 SIGNATURE
6 blib/
7 inc/
8 pm_to_blib
9
00 Revision history for Perl extension Jifty::DBI.
1
2 0.57 Tue May 19 08:02:03 EDT 2009
3 - Major bugfixes:
4 * Use eval {} in Jifty::DBI::Handle's DESTROY block when manipulating DBI
5 Alterations to the DBI object in the DESTROY block must be wrapped in
6 an eval {}, as object destruction order is not guaranteed during
7 global destruction, and this interacts poorly with DBI's tie'd object.
8 * During DESTROY, don't explicitly disconnect a dbh set InactiveDestroy
9 The InactiveDestroy flag on DBI objects prevent them from being
10 implicitly disconnected when they go out of scope -- for example, in
11 the case where a process has forked, and two processes hold the socket
12 open.
13 However, it does not prevent them from being _explicitly_
14 disconnected, as we were doing in Jifty::DBI::Handle's DESTROY method.
15 This caused InactiveDestroy to never kick in, causing either a shared
16 socket, or two closed handles after a fork. We prevent this by having
17 Jifty::DBI::Handle respect InactiveDestroy in its DESTROY method.
18 * Do not use Scalar::Defer defaults for columns' defaults in the db
19
20 - New features:
21 * Add a display_length attribute on columns
22 * add schema manipulation tables: rename_column and rename_table
23 * If a column's default is a record, call its id method
24
25 - Fixes:
26 * Improve SQL error message and avoid its duplication
27 * Pull the input_ and output_filters out of the instance hash
28
29 - Tests:
30 * Added a unit test for the SaltHash filter
31 * use drop_table_if_exists in tests
32 * add drop_table_if_exists in t/utils.t
33 * unconditionaly drop tables for testing
34 * test rename_table
35 * add tests for rename_column
36 * SaltHash test does not need an is_deeply()
37 * Don't explicitly disconnect the handle, DESTROY handles it better
38 * Test for warnings instead of letting them leak into the test output
39
140
241 0.53 Wed Mar 25 15:27:03 EDT 2009
342 - Major bugfixes:
0 .gitignore
01 Changes
12 debian/changelog
23 debian/compat
6869 t/02records_object.t
6970 t/02searches_joins.t
7071 t/03rebless.t
72 t/03rename_column.t
73 t/03rename_table.t
7174 t/04memcached.t
7275 t/05raw_value.t
7376 t/06filter.t
7477 t/06filter_boolean.t
7578 t/06filter_datetime.t
7679 t/06filter_duration.t
80 t/06filter_salthash.t
7781 t/06filter_storable.t
7882 t/06filter_truncate.t
7983 t/06filter_utf8.t
1313 -----BEGIN PGP SIGNED MESSAGE-----
1414 Hash: SHA1
1515
16 SHA1 dff41b1fc8b74cb89e2e268e3ccb15132f0b7a65 Changes
17 SHA1 6244026b27f75e581c672d49327905888b088629 MANIFEST
16 SHA1 f29ac6543498d1b0e81f387b7284a039f83e7d29 .gitignore
17 SHA1 85746120ae35bfdb3811297cfc3331a0d1c56343 Changes
18 SHA1 006b044e48cc925d04f620f317a907d459b2d128 MANIFEST
1819 SHA1 d3897bc376b40669acb9171adfd51f321d184fd8 META.yml
1920 SHA1 48bd6ca8a37ec79b7cae91028d7e9489ad33a03b Makefile.PL
2021 SHA1 ae8407c841f230c353f683bd5c257815aed9b9f0 README
3940 SHA1 7ad1da4fff7a1e7a634c9d734111c8292be08884 inc/Module/Install/Metadata.pm
4041 SHA1 e9aa83f3e8b16ccfce544a90a57b63b70a497759 inc/Module/Install/Win32.pm
4142 SHA1 ade2ac0b0246d4d8e28fa46942e53f6925abda46 inc/Module/Install/WriteAll.pm
42 SHA1 071207f492e64cafed55c2c65f3d12b43408395b lib/Jifty/DBI.pm
43 SHA1 249e7173876dca5ea914281036c853f7c9226991 lib/Jifty/DBI.pm
4344 SHA1 f181211220602d2883fd8d006fdb3c79ca417b05 lib/Jifty/DBI/Collection.pm
4445 SHA1 639ef9c81f03fb084b312a5f9a6f6a3ff63b36b7 lib/Jifty/DBI/Collection/Union.pm
4546 SHA1 bcba77fd2bacf0475aea1de97f57365c8de92ca6 lib/Jifty/DBI/Collection/Unique.pm
46 SHA1 fe97ce175ebf6e001773449531b1971d86c3ec5b lib/Jifty/DBI/Column.pm
47 SHA1 6d59ec1286f3ed887494753d01ed1f4760fd0a9b lib/Jifty/DBI/Column.pm
4748 SHA1 c21a985a5b799e50f2624e0fa6daee0895313825 lib/Jifty/DBI/Filter.pm
4849 SHA1 e030c3ef5c723ba6dce2e3fc23afecf2a6dfe260 lib/Jifty/DBI/Filter/Boolean.pm
4950 SHA1 d0addaa43cfa8950cb33d42a364a3c3c56a2dd59 lib/Jifty/DBI/Filter/Date.pm
5758 SHA1 67ffe7188a1f529d7594f4fa3803bcbe15ba6485 lib/Jifty/DBI/Filter/YAML.pm
5859 SHA1 9a6fd17e677321904436fefec4d434e17a4685b1 lib/Jifty/DBI/Filter/base64.pm
5960 SHA1 deb33fa7b35f3542aac3e2d7fb4b5d3070dc3917 lib/Jifty/DBI/Filter/utf8.pm
60 SHA1 319dd0ee5a65b40ca41c0223db6c4acd13ab9f6f lib/Jifty/DBI/Handle.pm
61 SHA1 ac3555c9ec6bdf462e24d043e34b977625ca6407 lib/Jifty/DBI/Handle.pm
6162 SHA1 bcc7c456e1c4d0dddd5564f03c8bb03a6c7e261f lib/Jifty/DBI/Handle/Informix.pm
6263 SHA1 338116a45f8eb6bfca5e76e8d3be78fb61fffe81 lib/Jifty/DBI/Handle/ODBC.pm
6364 SHA1 960fd0b63f3de11924c5d47a3c0c6d1db105ed5b lib/Jifty/DBI/Handle/Oracle.pm
6465 SHA1 23eeff073884c8951e004be4308ca946a1d5e205 lib/Jifty/DBI/Handle/Pg.pm
65 SHA1 d8b18e59ccc89ae80f4fdb4d0db70b85c3a76cd0 lib/Jifty/DBI/Handle/SQLite.pm
66 SHA1 1e850abb12a1d970eae373f452219c123be350e6 lib/Jifty/DBI/Handle/SQLite.pm
6667 SHA1 bba2314c20fcc3ef71cc69090f1cd6bd515cd9b4 lib/Jifty/DBI/Handle/Sybase.pm
67 SHA1 643cae4f858c4e7273e5c03f13b3cb910b0840bb lib/Jifty/DBI/Handle/mysql.pm
68 SHA1 cf80896a175702a157770f64ae469430678c3357 lib/Jifty/DBI/Handle/mysql.pm
6869 SHA1 f2cc4fcce79c9a88a023d4e6bd96c2089eef1ced lib/Jifty/DBI/Handle/mysqlPP.pm
69 SHA1 f2e9353e3f71443763509d52d9333a135b2cc56b lib/Jifty/DBI/HasFilters.pm
70 SHA1 d3cf1144c66a81f78144f45e10588451c34d11f6 lib/Jifty/DBI/Record.pm
70 SHA1 45d653e3a223599b50850010826bd835b80368d7 lib/Jifty/DBI/HasFilters.pm
71 SHA1 fc176a04f20301b698a390a014eda349d139d94f lib/Jifty/DBI/Record.pm
7172 SHA1 3853ce268985b129f2175251fb369d9689837f39 lib/Jifty/DBI/Record/Cachable.pm
7273 SHA1 1aac77960c508d3b2e5188e15825ad5b04391d76 lib/Jifty/DBI/Record/Memcached.pm
7374 SHA1 53834b3315a509ba33a8647681f472d3ae7b0557 lib/Jifty/DBI/Record/Plugin.pm
74 SHA1 57bc9b11c97dc13f538f7b210dc060b38fba2c2f lib/Jifty/DBI/Schema.pm
75 SHA1 8e7badfee526f44d09ba09641cf485ed601bd76a lib/Jifty/DBI/SchemaGenerator.pm
75 SHA1 501fe382b24b663c328fbb9c1cbf019c78e7bb53 lib/Jifty/DBI/Schema.pm
76 SHA1 a4d1a953ea4a29fe169b1c4c043ffff15b24c077 lib/Jifty/DBI/SchemaGenerator.pm
7677 SHA1 32834b7c4cf5a8d131382fccc8db341be8768291 t/00.load.t
7778 SHA1 9aa7fed2b2409faa4c71d2a45db210721f47403e t/01-version_checks.t
7879 SHA1 13c9fe3eeec0d000a7c86ea2474e30186cbc37e2 t/01basics.t
8182 SHA1 df97ee4e5bcb4ef0663dcc1a8db86dc66e8d9206 t/02-column_constraints.t
8283 SHA1 1c2bd056c575bc74caf2e59bdda8d8eb2731a3e7 t/02records_cachable.t
8384 SHA1 33642a61fd4b5a88436a82c6dd0fef359ba74a2b t/02records_object.t
84 SHA1 a5b0e1f214e029ee41e822a19cf07a3250264d3f t/02searches_joins.t
85 SHA1 ac42d8f2eea9f4856bee130b3ca557ef13940ad4 t/02searches_joins.t
8586 SHA1 f1f330dd8b4144e3437aba1455053903306bd0bc t/03rebless.t
87 SHA1 4a4ed7341a37aa1ba4ecc03ad73e120a4052eac9 t/03rename_column.t
88 SHA1 cb788b5336ae7c6f1fbf7795e38e2c4441f5c216 t/03rename_table.t
8689 SHA1 62c42d8458d73898f47f1b72d757239747321ef5 t/04memcached.t
8790 SHA1 4d2b42f80c2adaab70aa236a720cf57fa4b65677 t/05raw_value.t
8891 SHA1 f0371e275879019e2abe732bbb5626d0d05049a0 t/06filter.t
8992 SHA1 646947b41cfcddf80b627505940244aed2c6c5ea t/06filter_boolean.t
9093 SHA1 8d464426f2c5b0ab5ecc5a0a0331e5f77669c2dc t/06filter_datetime.t
9194 SHA1 172f655a7fdb4771e6e8b3aee45e93b1264a5567 t/06filter_duration.t
95 SHA1 94ed632ca88c6094236eec59cffdb1f3fd39f551 t/06filter_salthash.t
9296 SHA1 1c0727c29fb58462710e4578a237d557b8453a07 t/06filter_storable.t
9397 SHA1 f0f6ce9d48f419de6ac6154684f9065f32e30ddd t/06filter_truncate.t
9498 SHA1 2e9777a47e3a920d063bfbf9d56375c67c5b89c5 t/06filter_utf8.t
109113 SHA1 59c44900b1cb957d262f96363ceff21b46e0d598 t/pod-coverage.t
110114 SHA1 e9c6a5881fc60173fbc8d479c1afd2ce3b43bef1 t/pod.t
111115 SHA1 62742c946808f35bcc8b2777e975c1ce068a0a71 t/testmodels.pl
112 SHA1 2cf6ba23eb00dfed6f10533830da066c774c030c t/utils.pl
116 SHA1 b11b0df92ffef5a617cf77b74c8b963be577e3c0 t/utils.pl
113117 -----BEGIN PGP SIGNATURE-----
114 Version: GnuPG v2.0.9 (GNU/Linux)
118 Version: GnuPG v1.4.7 (Darwin)
115119
116 iEYEARECAAYFAknKhi8ACgkQMflWJZZAbqA9NgCgpEvp0YR8wmewsAjdivLnuTBC
117 7+oAnAlaNaoZzLoGESkZy5LGG4ZLeZJE
118 =XNEb
120 iD8DBQFKEqZ7sxfQtHhyRPoRAojSAJsFA4i59HHzcODcLP1I8DldBgijBQCdGsQ1
121 zTjK+DO/zkobfCE4js2KjII=
122 =cRri
119123 -----END PGP SIGNATURE-----
3636 my @handy_attrs = qw/
3737 container
3838 label hints render_as
39 display_length
3940 documentation
4041 valid_values
4142 available_values
140141
141142 =item label hints render_as
142143
144 =item display_length
145
143146 =item valid_values
144147
145148 =item available_values
9797 return("$column COLLATE NOCASE", $operator, $value);
9898 }
9999
100 =head2 rename_column ( table => $table, column => $old_column, to => $new_column )
101
102 rename column
103
104 =cut
105
106 sub rename_column {
107 my $self = shift;
108 my %args = (
109 table => undef,
110 column => undef,
111 to => undef,
112 @_
113 );
114
115 my $table = $args{'table'};
116
117 # Convert columns
118 my ($schema) = $self->fetch_result(
119 "SELECT sql FROM sqlite_master WHERE tbl_name = ? AND type = ?",
120 $table, 'table',
121 );
122 $schema =~ s/(.*create\s+table\s+)\S+(.*?\(\s*)//i
123 or die "Cannot find 'CREATE TABLE' statement in schema for '$table': $schema";
124
125 my $new_table = join( '_', $table, 'new', $$ );
126 my $new_create_clause = "$1$new_table$2";
127
128 my @column_info = ( split /,/, $schema );
129 my @column_names = map { /^\s*(\S+)/ ? $1 : () } @column_info;
130
131 s/^(\s*)\b\Q$args{column}\E\b/$1$args{to}/i for @column_info;
132
133 my $new_schema = $new_create_clause . join( ',', @column_info );
134 my $copy_columns = join(
135 ', ',
136 map {
137 ( lc($_) eq lc( $args{column} ) )
138 ? "$_ AS $args{to}"
139 : $_
140 } @column_names
141 );
142
143 # Convert indices
144 my $indice_sth = $self->simple_query(
145 "SELECT sql FROM sqlite_master WHERE tbl_name = ? AND type = ?",
146 $table, 'index'
147 );
148 my @indice_sql;
149 while ( my ($index) = $indice_sth->fetchrow_array ) {
150 $index =~ s/^(.*\(.*)\b\Q$args{column}\E\b/$1$args{to}/i;
151 push @indice_sql, $index;
152 }
153 $indice_sth->finish;
154
155 # Run the conversion SQLs
156 $self->begin_transaction;
157 $self->simple_query($new_schema);
158 $self->simple_query("INSERT INTO $new_table SELECT $copy_columns FROM $table");
159 $self->simple_query("DROP TABLE $table");
160 $self->simple_query("ALTER TABLE $new_table RENAME TO $table");
161 $self->simple_query($_) for @indice_sql;
162 $self->commit;
163 }
100164
101165 1;
102166
8080 return;
8181 }
8282
83 =head2 rename_column ( table => $table, column => $old_column, to => $new_column )
84
85 rename column, die if fails
86
87 =cut
88
89 sub rename_column {
90 my $self = shift;
91 my %args = (
92 table => undef,
93 column => undef,
94 to => undef,
95 @_
96 );
97
98 my ($table, $column, $to) = @args{'table', 'column', 'to'};
99
100 # XXX, FIXME, TODO: this is stupid parser of CREATE TABLE, this should be something based on
101 # column_info, schema tables and show fields. The closest thing is RT 3.8/etc/upgrade/upgrade-mysql-schema.pl
102
103 my $create_table = ($self->simple_query("SHOW CREATE TABLE $table")->fetchrow_array)[1];
104 $create_table =~ /create\s+table\s+\S+\s*\((.*)\)/ims
105 or die "Cannot find 'CREATE TABLE' statement in schema for '$table': $create_table";
106 $create_table = $1;
107
108 my ($column_info) = ($create_table =~ /`$column`(.*?)(?:,|$)/i)
109 or die "Cannot find column '$column' in $create_table";
110 my $sth = $self->simple_query("ALTER TABLE $table CHANGE $column $to $column_info");
111 die "Cannot rename column '$column' in table '$table' to '$to': ". $self->dbh->errstr
112 unless $sth;
113 return $sth;
114 }
115
83116 1;
84117
85118 __END__
237237 return $self->dbh->{PrintError};
238238 }
239239
240 =head2 log MESSAGE
241
242 Takes a single argument, a message to log.
243
244 Currently prints that message to STDERR
245
246 =cut
247
248 sub log {
249 my $self = shift;
250 my $msg = shift;
251 warn $msg . "\n";
252
253 }
254
240255 =head2 log_sql_statements BOOL
241256
242257 Takes a boolean argument. If the boolean is true, it will log all SQL
509524
510525 my $sth = $self->dbh->prepare($query_string);
511526 unless ($sth) {
527 my $message = "$self couldn't prepare the query '$query_string': "
528 . $self->dbh->errstr;
512529 if ($DEBUG) {
513 die "$self couldn't prepare the query '$query_string'"
514 . $self->dbh->errstr . "\n";
530 die "$message\n";
515531 } else {
516 warn "$self couldn't prepare the query '$query_string'"
517 . $self->dbh->errstr . "\n";
532 warn "$message\n";
518533 my $ret = Class::ReturnValue->new();
519534 $ret->as_error(
520535 errno => '-1',
521 message => "Couldn't prepare the query '$query_string'."
522 . $self->dbh->errstr,
536 message => $message,
523537 do_backtrace => undef
524538 );
525539 return ( $ret->return_value );
12491263
12501264 }
12511265
1252 =head2 log MESSAGE
1253
1254 Takes a single argument, a message to log.
1255
1256 Currently prints that message to STDERR
1257
1258 =cut
1259
1260 sub log {
1261 my $self = shift;
1262 my $msg = shift;
1263 warn $msg . "\n";
1264
1265 }
1266
12671266 =head2 canonical_true
12681267
12691268 This returns the canonical true value for this database. For example, in SQLite
12861285
12871286 sub canonical_false { 0 }
12881287
1288 =head2 Schema manipulation methods
1289
1290 =head3 rename_column
1291
1292 Rename a column in a table. Takes 'table', 'column' and new name in 'to'.
1293
1294 =cut
1295
1296 sub rename_column {
1297 my $self = shift;
1298 my %args = (table => undef, column => undef, to => undef, @_);
1299 # Oracle: since Oracle 9i R2
1300 # Pg: 7.4 can this and may be earlier
1301 return $self->simple_query(
1302 "ALTER TABLE $args{'table'} RENAME COLUMN $args{'column'} TO $args{'to'}"
1303 );
1304 }
1305
1306
1307 =head3 rename_table
1308
1309 Renames a table in the DB. Takes 'table' and new name of it in 'to'.
1310
1311 =cut
1312
1313 sub rename_table {
1314 my $self = shift;
1315 my %args = (table => undef, to => undef, @_);
1316 # mysql has RENAME TABLE, but alter can rename temporary
1317 # Oracle, Pg, SQLite are ok with this
1318 return $self->simple_query("ALTER TABLE $args{'table'} RENAME TO $args{'to'}");
1319 }
1320
12891321 =head2 DESTROY
12901322
12911323 When we get rid of the L<Jifty::DBI::Handle>, we need to disconnect
12951327
12961328 sub DESTROY {
12971329 my $self = shift;
1298 $self->disconnect;
1330
1331 # eval in DESTROY can cause $@ issues elsewhere
1332 local $@;
1333
1334 $self->disconnect
1335 unless $self->dbh
1336 and $self->dbh
1337 # We use an eval {} because DESTROY order during
1338 # global destruction is not guaranteed -- the dbh may
1339 # no longer be tied, which throws an error.
1340 and eval { $self->dbh->{InactiveDestroy} };
12991341 delete $DBIHandle{$self};
13001342 }
13011343
4242 my $self = shift;
4343 if (@_) { # setting
4444 my @values = map { UNIVERSAL::isa( $_, 'ARRAY' ) ? @$_ : $_ } @_;
45 $self->_input_filters_accessor( \@values );
45 $self->{input_filters} = \@values;
4646 return @values;
4747 }
4848
49 return @{ $self->_input_filters_accessor || [] };
49 return @{ $self->{input_filters} || [] };
5050 }
5151
5252 =head2 output_filters
6363 my $self = shift;
6464 if (@_) { # setting
6565 my @values = map { UNIVERSAL::isa( $_, 'ARRAY' ) ? @$_ : $_ } @_;
66 $self->_output_filters_accessor( \@values );
66 $self->{output_filters} = \@values;
6767 return @values;
6868 }
6969
70 my $values = $self->_output_filters_accessor;
70 my $values = $self->{output_filters};
7171 return @$values if $values && @$values;
7272
7373 return reverse $self->input_filters;
88 use UNIVERSAL::require ();
99 use Scalar::Util qw(blessed);
1010 use Class::Trigger; # exports by default
11 use Scalar::Defer 'force';
1112
1213 use base qw/
1314 Class::Data::Inheritable
14121413 and defined $column->default
14131414 and not ref $column->default )
14141415 {
1415 $attribs{ $column->name } = $column->default;
1416 my $default = force $column->default;
1417 $default = $default->id
1418 if UNIVERSAL::isa( $default, 'Jifty::DBI::Record' );
1419
1420 $attribs{ $column->name } = $default;
14161421
14171422 $self->_apply_input_filters(
14181423 column => $column,
705705 might go in this column. Correct usage is C<hints is 'Used by the
706706 frobnicator to do strange things'>.
707707
708 =head2 display_length
709
710 The displayed length of form fields. Though you may be able to fit
711 500 characters in the field, you would not want to display an HTML
712 form with a size 500 input box.
713
708714 =head2 render_as
709715
710716 Used in user interface generation to know how to render the column.
278278
279279 # Encode default values
280280 my $default = $column->default;
281 if (defined $default) {
281
282 # Scalar::Defer-powered defaults do not get a default in the database
283 if (ref($default) ne '0' && defined $default) {
282284 $model->_handle($self->handle);
283285 $model->_apply_input_filters(
284286 column => $column,
11 use warnings;
22 use strict;
33
4 $Jifty::DBI::VERSION = '0.53';
4 $Jifty::DBI::VERSION = '0.57';
55
66 =head1 NAME
77
220220 }
221221
222222 cleanup_schema( 'TestApp', $handle );
223 disconnect_handle($handle);
224223 }} # SKIP, foreach blocks
225224
226225 1;
0 #!/usr/bin/env perl -w
1
2
3 use strict;
4 use warnings;
5 use File::Spec;
6 use Test::More;
7 use Jifty::DBI::Handle;
8
9 BEGIN { require "t/utils.pl" }
10 our (@available_drivers);
11
12 use constant TESTS_PER_DRIVER => 11;
13
14 my $total = scalar(@available_drivers) * TESTS_PER_DRIVER;
15 plan tests => $total;
16
17 foreach my $d ( @available_drivers ) {
18 SKIP: {
19 unless( should_test( $d ) ) {
20 skip "ENV is not defined for driver '$d'", TESTS_PER_DRIVER;
21 }
22
23 my $handle = get_handle($d);
24 connect_handle($handle);
25 isa_ok( $handle->dbh, 'DBI::db' );
26
27 drop_table_if_exists( 'test', $handle );
28
29 my $sth = $handle->simple_query(
30 "CREATE TABLE test (a int, x integer not null default 1)"
31 );
32 ok $sth, 'created a table';
33
34 ok $handle->simple_query("insert into test values(2,2)"), "inserted a record";
35 $sth = $handle->simple_query("select * from test");
36 is $sth->fetchrow_hashref->{'x'}, 2, 'correct value';
37
38 $handle->rename_column( table => 'test', column => 'x', to => 'y' );
39 $sth = $handle->simple_query("select * from test");
40 is $sth->fetchrow_hashref->{'y'}, 2, 'correct value';
41 $sth->finish;
42 undef $sth;
43
44 my @warnings;
45 ok !eval {
46 local $SIG{__WARN__} = sub { push @warnings, @_ };
47 $handle->simple_query("insert into test(x) values(1)");
48 }, "no x anymore";
49 ok((splice @warnings), "we got warnings");
50
51 ok !eval {
52 local $SIG{__WARN__} = sub { push @warnings, @_ };
53 $handle->simple_query("insert into test(y) values(NULL)");
54 }, "NOT NULL is still there";
55 ok((splice @warnings), "we got warnings");
56
57 $handle->simple_query("delete from test");
58 ok $handle->simple_query("insert into test(a) values(1)"), "DEFAULT is still there";
59 is $handle->simple_query("select * from test")->fetchrow_hashref->{'y'},
60 1, 'correct value';
61 undef $handle;
62 }} # SKIP, foreach blocks
63
64 1;
0 #!/usr/bin/env perl -w
1
2
3 use strict;
4 use warnings;
5 use File::Spec;
6 use Test::More;
7 use Jifty::DBI::Handle;
8
9 BEGIN { require "t/utils.pl" }
10 our (@available_drivers);
11
12 use constant TESTS_PER_DRIVER => 7;
13
14 my $total = scalar(@available_drivers) * TESTS_PER_DRIVER;
15 plan tests => $total;
16
17 foreach my $d ( @available_drivers ) {
18 SKIP: {
19 unless( should_test( $d ) ) {
20 skip "ENV is not defined for driver '$d'", TESTS_PER_DRIVER;
21 }
22
23 my $handle = get_handle($d);
24 connect_handle($handle);
25 isa_ok( $handle->dbh, 'DBI::db' );
26
27 my $sth;
28 drop_table_if_exists( 'test', $handle );
29 drop_table_if_exists( 'test1', $handle );
30
31 $sth = $handle->simple_query("CREATE TABLE test (a int)");
32 ok $sth, 'created a table';
33
34 ok $handle->simple_query("insert into test values(1)"), "inserted a record";
35 is $handle->simple_query("select * from test")->fetchrow_hashref->{'a'},
36 1, 'correct value';
37
38 $handle->rename_table( table => 'test', to => 'test1' );
39
40 is $handle->simple_query("select * from test1")->fetchrow_hashref->{'a'},
41 1, 'correct value';
42
43 my @warnings;
44 ok !eval {
45 local $SIG{__WARN__} = sub { push @warnings, @_ };
46 $handle->simple_query("select * from test")
47 }, "no test table anymore";
48 ok(@warnings, "got some warnings");
49
50 }} # SKIP, foreach blocks
51
52 1;
0 #!/usr/bin/env perl
1 use strict;
2 use warnings;
3
4 use Test::More;
5 use Digest::MD5 qw( md5_hex );
6 BEGIN { require "t/utils.pl" }
7 our (@available_drivers);
8
9 use constant TESTS_PER_DRIVER => 10;
10
11 my $total = scalar(@available_drivers) * TESTS_PER_DRIVER;
12 plan tests => $total;
13
14 foreach my $d (@available_drivers) {
15 SKIP: {
16 unless (has_schema('TestApp::User', $d)) {
17 skip "No schema for '$d' driver", TESTS_PER_DRIVER;
18 }
19
20 unless (should_test($d)) {
21 skip "ENV is not defined for driver '$d'", TESTS_PER_DRIVER;
22 }
23
24 diag("start testing with '$d' handle") if $ENV{TEST_VERBOSE};
25
26 my $handle = get_handle($d);
27 connect_handle($handle);
28 isa_ok($handle->dbh, 'DBI::db');
29
30 {
31 my $ret = init_schema('TestApp::User', $handle);
32 isa_ok($ret, 'DBI::st', 'init schema');
33 }
34
35 my $rec = TestApp::User->new( handle => $handle );
36 isa_ok($rec, 'Jifty::DBI::Record');
37
38 my ($id) = $rec->create( password => 'very-very-secret' );
39 ok($id, 'created record');
40 ok($rec->load($id), 'loaded record');
41 is($rec->id, $id, 'record id matches');
42 is(ref $rec->password, 'ARRAY', 'password is an ARRAY');
43 is(scalar @{ $rec->password }, 2, 'password array has 2 elements');
44 my ($hash, $salt) = @{ $rec->password };
45 is($hash, md5_hex('very-very-secret', $salt), 'password matches encoding');
46
47 # undef/NULL
48 $rec->set_password;
49 is($rec->password, undef, 'set undef value');
50
51 cleanup_schema('TestApp', $handle);
52 disconnect_handle($handle);
53 }
54 }
55
56 package TestApp::User;
57 use base qw/ Jifty::DBI::Record /;
58
59 1;
60
61 sub schema_sqlite {
62
63 <<EOF;
64 CREATE table users (
65 id integer primary key,
66 password text
67 )
68 EOF
69
70 }
71
72 sub schema_mysql {
73
74 <<EOF;
75 CREATE TEMPORARY table users (
76 id integer auto_increment primary key,
77 password text
78 )
79 EOF
80
81 }
82
83 sub schema_pg {
84
85 <<EOF;
86 CREATE TEMPORARY table users (
87 id serial primary key,
88 password text
89 )
90 EOF
91
92 }
93
94 BEGIN {
95 use Jifty::DBI::Schema;
96
97 use Jifty::DBI::Record schema {
98 column password =>
99 type is 'text',
100 filters are qw/ Jifty::DBI::Filter::SaltHash /;
101 }
102 }
103
3333
3434 our @available_drivers = grep { eval "require DBD::". $_ } @supported_drivers;
3535
36 =head1 functionS
36 =head1 FUNCTIONS
3737
3838 =head2 get_handle
3939
286286 }
287287
288288 =head2 init_data
289
290 Takes a class to get data from and the handle, calls C<init_data>
291 method in the class, result is used to create new records of that
292 class. First row is used for columns names.
293
294 Example:
295
296 init_data('TestApp::User', $handle);
297
298 ...
299
300 package TestApp::User;
301 sub init_data { return (
302 ['name', 'email'],
303
304 ['ruz', 'ruz@localhost'],
305 ...
306 ) }
289307
290308 =cut
291309
308326 return $count;
309327 }
310328
329 =head2 drop_table_if_exists
330
331 Takes a table name and handle. Drops the table in the DB if it exists.
332 Returns nothing interesting, shouldn't die.
333
334 =cut
335
336 sub drop_table_if_exists {
337 my ($table, $handle) = @_;
338 my $d = handle_to_driver( $handle );
339 if ( $d eq 'Pg' ) {
340 my ($exists) = $handle->dbh->selectrow_array(
341 "select 1 from pg_tables where tablename = ?", undef, $table
342 );
343 $handle->simple_query("DROP TABLE $table") if $exists;
344 }
345 else {
346 local $@;
347 eval { $handle->simple_query("DROP TABLE IF EXISTS $table") };
348 }
349 return;
350 }
351
311352 1;