[svn-upgrade] Integrating new upstream version, libjifty-dbi-perl (0.57)
Yves Agostini
15 years ago
0 | MANIFEST | |
1 | MANIFEST.bak | |
2 | META.yml | |
3 | Makefile | |
4 | Makefile.old | |
5 | SIGNATURE | |
6 | blib/ | |
7 | inc/ | |
8 | pm_to_blib | |
9 |
0 | 0 | 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 | ||
1 | 40 | |
2 | 41 | 0.53 Wed Mar 25 15:27:03 EDT 2009 |
3 | 42 | - Major bugfixes: |
0 | .gitignore | |
0 | 1 | Changes |
1 | 2 | debian/changelog |
2 | 3 | debian/compat |
68 | 69 | t/02records_object.t |
69 | 70 | t/02searches_joins.t |
70 | 71 | t/03rebless.t |
72 | t/03rename_column.t | |
73 | t/03rename_table.t | |
71 | 74 | t/04memcached.t |
72 | 75 | t/05raw_value.t |
73 | 76 | t/06filter.t |
74 | 77 | t/06filter_boolean.t |
75 | 78 | t/06filter_datetime.t |
76 | 79 | t/06filter_duration.t |
80 | t/06filter_salthash.t | |
77 | 81 | t/06filter_storable.t |
78 | 82 | t/06filter_truncate.t |
79 | 83 | t/06filter_utf8.t |
13 | 13 | -----BEGIN PGP SIGNED MESSAGE----- |
14 | 14 | Hash: SHA1 |
15 | 15 | |
16 | SHA1 dff41b1fc8b74cb89e2e268e3ccb15132f0b7a65 Changes | |
17 | SHA1 6244026b27f75e581c672d49327905888b088629 MANIFEST | |
16 | SHA1 f29ac6543498d1b0e81f387b7284a039f83e7d29 .gitignore | |
17 | SHA1 85746120ae35bfdb3811297cfc3331a0d1c56343 Changes | |
18 | SHA1 006b044e48cc925d04f620f317a907d459b2d128 MANIFEST | |
18 | 19 | SHA1 d3897bc376b40669acb9171adfd51f321d184fd8 META.yml |
19 | 20 | SHA1 48bd6ca8a37ec79b7cae91028d7e9489ad33a03b Makefile.PL |
20 | 21 | SHA1 ae8407c841f230c353f683bd5c257815aed9b9f0 README |
39 | 40 | SHA1 7ad1da4fff7a1e7a634c9d734111c8292be08884 inc/Module/Install/Metadata.pm |
40 | 41 | SHA1 e9aa83f3e8b16ccfce544a90a57b63b70a497759 inc/Module/Install/Win32.pm |
41 | 42 | SHA1 ade2ac0b0246d4d8e28fa46942e53f6925abda46 inc/Module/Install/WriteAll.pm |
42 | SHA1 071207f492e64cafed55c2c65f3d12b43408395b lib/Jifty/DBI.pm | |
43 | SHA1 249e7173876dca5ea914281036c853f7c9226991 lib/Jifty/DBI.pm | |
43 | 44 | SHA1 f181211220602d2883fd8d006fdb3c79ca417b05 lib/Jifty/DBI/Collection.pm |
44 | 45 | SHA1 639ef9c81f03fb084b312a5f9a6f6a3ff63b36b7 lib/Jifty/DBI/Collection/Union.pm |
45 | 46 | SHA1 bcba77fd2bacf0475aea1de97f57365c8de92ca6 lib/Jifty/DBI/Collection/Unique.pm |
46 | SHA1 fe97ce175ebf6e001773449531b1971d86c3ec5b lib/Jifty/DBI/Column.pm | |
47 | SHA1 6d59ec1286f3ed887494753d01ed1f4760fd0a9b lib/Jifty/DBI/Column.pm | |
47 | 48 | SHA1 c21a985a5b799e50f2624e0fa6daee0895313825 lib/Jifty/DBI/Filter.pm |
48 | 49 | SHA1 e030c3ef5c723ba6dce2e3fc23afecf2a6dfe260 lib/Jifty/DBI/Filter/Boolean.pm |
49 | 50 | SHA1 d0addaa43cfa8950cb33d42a364a3c3c56a2dd59 lib/Jifty/DBI/Filter/Date.pm |
57 | 58 | SHA1 67ffe7188a1f529d7594f4fa3803bcbe15ba6485 lib/Jifty/DBI/Filter/YAML.pm |
58 | 59 | SHA1 9a6fd17e677321904436fefec4d434e17a4685b1 lib/Jifty/DBI/Filter/base64.pm |
59 | 60 | SHA1 deb33fa7b35f3542aac3e2d7fb4b5d3070dc3917 lib/Jifty/DBI/Filter/utf8.pm |
60 | SHA1 319dd0ee5a65b40ca41c0223db6c4acd13ab9f6f lib/Jifty/DBI/Handle.pm | |
61 | SHA1 ac3555c9ec6bdf462e24d043e34b977625ca6407 lib/Jifty/DBI/Handle.pm | |
61 | 62 | SHA1 bcc7c456e1c4d0dddd5564f03c8bb03a6c7e261f lib/Jifty/DBI/Handle/Informix.pm |
62 | 63 | SHA1 338116a45f8eb6bfca5e76e8d3be78fb61fffe81 lib/Jifty/DBI/Handle/ODBC.pm |
63 | 64 | SHA1 960fd0b63f3de11924c5d47a3c0c6d1db105ed5b lib/Jifty/DBI/Handle/Oracle.pm |
64 | 65 | 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 | |
66 | 67 | 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 | |
68 | 69 | 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 | |
71 | 72 | SHA1 3853ce268985b129f2175251fb369d9689837f39 lib/Jifty/DBI/Record/Cachable.pm |
72 | 73 | SHA1 1aac77960c508d3b2e5188e15825ad5b04391d76 lib/Jifty/DBI/Record/Memcached.pm |
73 | 74 | 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 | |
76 | 77 | SHA1 32834b7c4cf5a8d131382fccc8db341be8768291 t/00.load.t |
77 | 78 | SHA1 9aa7fed2b2409faa4c71d2a45db210721f47403e t/01-version_checks.t |
78 | 79 | SHA1 13c9fe3eeec0d000a7c86ea2474e30186cbc37e2 t/01basics.t |
81 | 82 | SHA1 df97ee4e5bcb4ef0663dcc1a8db86dc66e8d9206 t/02-column_constraints.t |
82 | 83 | SHA1 1c2bd056c575bc74caf2e59bdda8d8eb2731a3e7 t/02records_cachable.t |
83 | 84 | SHA1 33642a61fd4b5a88436a82c6dd0fef359ba74a2b t/02records_object.t |
84 | SHA1 a5b0e1f214e029ee41e822a19cf07a3250264d3f t/02searches_joins.t | |
85 | SHA1 ac42d8f2eea9f4856bee130b3ca557ef13940ad4 t/02searches_joins.t | |
85 | 86 | SHA1 f1f330dd8b4144e3437aba1455053903306bd0bc t/03rebless.t |
87 | SHA1 4a4ed7341a37aa1ba4ecc03ad73e120a4052eac9 t/03rename_column.t | |
88 | SHA1 cb788b5336ae7c6f1fbf7795e38e2c4441f5c216 t/03rename_table.t | |
86 | 89 | SHA1 62c42d8458d73898f47f1b72d757239747321ef5 t/04memcached.t |
87 | 90 | SHA1 4d2b42f80c2adaab70aa236a720cf57fa4b65677 t/05raw_value.t |
88 | 91 | SHA1 f0371e275879019e2abe732bbb5626d0d05049a0 t/06filter.t |
89 | 92 | SHA1 646947b41cfcddf80b627505940244aed2c6c5ea t/06filter_boolean.t |
90 | 93 | SHA1 8d464426f2c5b0ab5ecc5a0a0331e5f77669c2dc t/06filter_datetime.t |
91 | 94 | SHA1 172f655a7fdb4771e6e8b3aee45e93b1264a5567 t/06filter_duration.t |
95 | SHA1 94ed632ca88c6094236eec59cffdb1f3fd39f551 t/06filter_salthash.t | |
92 | 96 | SHA1 1c0727c29fb58462710e4578a237d557b8453a07 t/06filter_storable.t |
93 | 97 | SHA1 f0f6ce9d48f419de6ac6154684f9065f32e30ddd t/06filter_truncate.t |
94 | 98 | SHA1 2e9777a47e3a920d063bfbf9d56375c67c5b89c5 t/06filter_utf8.t |
109 | 113 | SHA1 59c44900b1cb957d262f96363ceff21b46e0d598 t/pod-coverage.t |
110 | 114 | SHA1 e9c6a5881fc60173fbc8d479c1afd2ce3b43bef1 t/pod.t |
111 | 115 | SHA1 62742c946808f35bcc8b2777e975c1ce068a0a71 t/testmodels.pl |
112 | SHA1 2cf6ba23eb00dfed6f10533830da066c774c030c t/utils.pl | |
116 | SHA1 b11b0df92ffef5a617cf77b74c8b963be577e3c0 t/utils.pl | |
113 | 117 | -----BEGIN PGP SIGNATURE----- |
114 | Version: GnuPG v2.0.9 (GNU/Linux) | |
118 | Version: GnuPG v1.4.7 (Darwin) | |
115 | 119 | |
116 | iEYEARECAAYFAknKhi8ACgkQMflWJZZAbqA9NgCgpEvp0YR8wmewsAjdivLnuTBC | |
117 | 7+oAnAlaNaoZzLoGESkZy5LGG4ZLeZJE | |
118 | =XNEb | |
120 | iD8DBQFKEqZ7sxfQtHhyRPoRAojSAJsFA4i59HHzcODcLP1I8DldBgijBQCdGsQ1 | |
121 | zTjK+DO/zkobfCE4js2KjII= | |
122 | =cRri | |
119 | 123 | -----END PGP SIGNATURE----- |
36 | 36 | my @handy_attrs = qw/ |
37 | 37 | container |
38 | 38 | label hints render_as |
39 | display_length | |
39 | 40 | documentation |
40 | 41 | valid_values |
41 | 42 | available_values |
140 | 141 | |
141 | 142 | =item label hints render_as |
142 | 143 | |
144 | =item display_length | |
145 | ||
143 | 146 | =item valid_values |
144 | 147 | |
145 | 148 | =item available_values |
97 | 97 | return("$column COLLATE NOCASE", $operator, $value); |
98 | 98 | } |
99 | 99 | |
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 | } | |
100 | 164 | |
101 | 165 | 1; |
102 | 166 |
80 | 80 | return; |
81 | 81 | } |
82 | 82 | |
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 | ||
83 | 116 | 1; |
84 | 117 | |
85 | 118 | __END__ |
237 | 237 | return $self->dbh->{PrintError}; |
238 | 238 | } |
239 | 239 | |
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 | ||
240 | 255 | =head2 log_sql_statements BOOL |
241 | 256 | |
242 | 257 | Takes a boolean argument. If the boolean is true, it will log all SQL |
509 | 524 | |
510 | 525 | my $sth = $self->dbh->prepare($query_string); |
511 | 526 | unless ($sth) { |
527 | my $message = "$self couldn't prepare the query '$query_string': " | |
528 | . $self->dbh->errstr; | |
512 | 529 | if ($DEBUG) { |
513 | die "$self couldn't prepare the query '$query_string'" | |
514 | . $self->dbh->errstr . "\n"; | |
530 | die "$message\n"; | |
515 | 531 | } else { |
516 | warn "$self couldn't prepare the query '$query_string'" | |
517 | . $self->dbh->errstr . "\n"; | |
532 | warn "$message\n"; | |
518 | 533 | my $ret = Class::ReturnValue->new(); |
519 | 534 | $ret->as_error( |
520 | 535 | errno => '-1', |
521 | message => "Couldn't prepare the query '$query_string'." | |
522 | . $self->dbh->errstr, | |
536 | message => $message, | |
523 | 537 | do_backtrace => undef |
524 | 538 | ); |
525 | 539 | return ( $ret->return_value ); |
1249 | 1263 | |
1250 | 1264 | } |
1251 | 1265 | |
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 | ||
1267 | 1266 | =head2 canonical_true |
1268 | 1267 | |
1269 | 1268 | This returns the canonical true value for this database. For example, in SQLite |
1286 | 1285 | |
1287 | 1286 | sub canonical_false { 0 } |
1288 | 1287 | |
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 | ||
1289 | 1321 | =head2 DESTROY |
1290 | 1322 | |
1291 | 1323 | When we get rid of the L<Jifty::DBI::Handle>, we need to disconnect |
1295 | 1327 | |
1296 | 1328 | sub DESTROY { |
1297 | 1329 | 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} }; | |
1299 | 1341 | delete $DBIHandle{$self}; |
1300 | 1342 | } |
1301 | 1343 |
42 | 42 | my $self = shift; |
43 | 43 | if (@_) { # setting |
44 | 44 | my @values = map { UNIVERSAL::isa( $_, 'ARRAY' ) ? @$_ : $_ } @_; |
45 | $self->_input_filters_accessor( \@values ); | |
45 | $self->{input_filters} = \@values; | |
46 | 46 | return @values; |
47 | 47 | } |
48 | 48 | |
49 | return @{ $self->_input_filters_accessor || [] }; | |
49 | return @{ $self->{input_filters} || [] }; | |
50 | 50 | } |
51 | 51 | |
52 | 52 | =head2 output_filters |
63 | 63 | my $self = shift; |
64 | 64 | if (@_) { # setting |
65 | 65 | my @values = map { UNIVERSAL::isa( $_, 'ARRAY' ) ? @$_ : $_ } @_; |
66 | $self->_output_filters_accessor( \@values ); | |
66 | $self->{output_filters} = \@values; | |
67 | 67 | return @values; |
68 | 68 | } |
69 | 69 | |
70 | my $values = $self->_output_filters_accessor; | |
70 | my $values = $self->{output_filters}; | |
71 | 71 | return @$values if $values && @$values; |
72 | 72 | |
73 | 73 | return reverse $self->input_filters; |
8 | 8 | use UNIVERSAL::require (); |
9 | 9 | use Scalar::Util qw(blessed); |
10 | 10 | use Class::Trigger; # exports by default |
11 | use Scalar::Defer 'force'; | |
11 | 12 | |
12 | 13 | use base qw/ |
13 | 14 | Class::Data::Inheritable |
1412 | 1413 | and defined $column->default |
1413 | 1414 | and not ref $column->default ) |
1414 | 1415 | { |
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; | |
1416 | 1421 | |
1417 | 1422 | $self->_apply_input_filters( |
1418 | 1423 | column => $column, |
705 | 705 | might go in this column. Correct usage is C<hints is 'Used by the |
706 | 706 | frobnicator to do strange things'>. |
707 | 707 | |
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 | ||
708 | 714 | =head2 render_as |
709 | 715 | |
710 | 716 | Used in user interface generation to know how to render the column. |
278 | 278 | |
279 | 279 | # Encode default values |
280 | 280 | 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) { | |
282 | 284 | $model->_handle($self->handle); |
283 | 285 | $model->_apply_input_filters( |
284 | 286 | column => $column, |
1 | 1 | use warnings; |
2 | 2 | use strict; |
3 | 3 | |
4 | $Jifty::DBI::VERSION = '0.53'; | |
4 | $Jifty::DBI::VERSION = '0.57'; | |
5 | 5 | |
6 | 6 | =head1 NAME |
7 | 7 |
220 | 220 | } |
221 | 221 | |
222 | 222 | cleanup_schema( 'TestApp', $handle ); |
223 | disconnect_handle($handle); | |
224 | 223 | }} # SKIP, foreach blocks |
225 | 224 | |
226 | 225 | 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 |
33 | 33 | |
34 | 34 | our @available_drivers = grep { eval "require DBD::". $_ } @supported_drivers; |
35 | 35 | |
36 | =head1 functionS | |
36 | =head1 FUNCTIONS | |
37 | 37 | |
38 | 38 | =head2 get_handle |
39 | 39 | |
286 | 286 | } |
287 | 287 | |
288 | 288 | =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 | ) } | |
289 | 307 | |
290 | 308 | =cut |
291 | 309 | |
308 | 326 | return $count; |
309 | 327 | } |
310 | 328 | |
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 | ||
311 | 352 | 1; |