{
my
$schema
= DBICTest->init_schema(
auto_savepoint
=> 1);
my
$ars
=
$schema
->resultset(
'Artist'
);
$schema
->txn_do(
sub
{
$ars
->create({
name
=>
'in_outer_transaction'
});
$schema
->txn_do(
sub
{
$ars
->create({
name
=>
'in_inner_transaction'
});
});
ok(
$ars
->search({
name
=>
'in_inner_transaction'
})->first,
'commit from inner transaction visible in outer transaction'
);
throws_ok {
$schema
->txn_do(
sub
{
$ars
->create({
name
=>
'in_inner_transaction_rolling_back'
});
die
'rolling back inner transaction'
;
});
}
qr/rolling back inner transaction/
,
'inner transaction rollback executed'
;
$ars
->create({
name
=>
'in_outer_transaction2'
});
});
ok(
$ars
->search({
name
=>
'in_outer_transaction'
})->first,
'commit from outer transaction'
);
ok(
$ars
->search({
name
=>
'in_outer_transaction2'
})->first,
'second commit from outer transaction'
);
ok(
$ars
->search({
name
=>
'in_inner_transaction'
})->first,
'commit from inner transaction'
);
is
$ars
->search({
name
=>
'in_inner_transaction_rolling_back'
})->first,
undef
,
'rollback from inner transaction'
;
}
my
$lit_txn_todo
= modver_gt_or_eq(
'DBD::SQLite'
,
'1.38_02'
)
?
undef
:
"DBD::SQLite before 1.38_02 is retarded wrt detecting literal BEGIN/COMMIT statements"
;
for
my
$prefix_comment
(
qw/Begin_only Commit_only Begin_and_Commit/
) {
note
"Testing with comment prefixes on $prefix_comment"
;
local
$SIG
{__WARN__} = sigwarn_silencer(
qr/Internal transaction state .+? does not seem to match/
)
if
(
$lit_txn_todo
&& !
$ENV
{TEST_VERBOSE} );
my
(
$c_begin
,
$c_commit
) =
map
{
$prefix_comment
=~
$_
? 1 : 0 } (
qr/Begin/
,
qr/Commit/
);
my
$schema
= DBICTest->init_schema(
no_deploy
=> 1 );
my
$ars
=
$schema
->resultset(
'Artist'
);
ok (!
$schema
->storage->connected,
'No connection yet'
);
$schema
->storage->dbh->
do
(
<<'DDL');
CREATE TABLE artist (
artistid INTEGER PRIMARY KEY NOT NULL,
name varchar(100),
rank integer DEFAULT 13,
charfield char(10) NULL
);
DDL
my
$artist
=
$ars
->create({
name
=>
'Artist_'
.
time
() });
is (
$ars
->count, 1,
'Inserted artist '
.
$artist
->name);
ok (
$schema
->storage->connected,
'Connected'
);
ok (
$schema
->storage->_dbh->{AutoCommit},
'DBD not in txn yet'
);
$schema
->storage->dbh->
do
(
join
"\n"
,
$c_begin
?
'-- comment'
: (),
'BEGIN TRANSACTION'
);
ok (
$schema
->storage->connected,
'Still connected'
);
{
local
$TODO
=
$lit_txn_todo
if
$c_begin
;
ok (!
$schema
->storage->_dbh->{AutoCommit},
"DBD aware of txn begin with comments on $prefix_comment"
);
}
$schema
->storage->dbh->
do
(
join
"\n"
,
$c_commit
?
'-- comment'
: (),
'COMMIT'
);
ok (
$schema
->storage->connected,
'Still connected'
);
{
local
$TODO
=
$lit_txn_todo
if
$c_commit
and !
$c_begin
;
ok (
$schema
->storage->_dbh->{AutoCommit},
"DBD aware txn ended with comments on $prefix_comment"
);
}
is (
$ars
->count, 1,
'Inserted artists still there'
);
{
local
$TODO
=
$lit_txn_todo
if
!
$c_begin
and
$c_commit
;
lives_ok {
$schema
->storage->txn_do (
sub
{
ok (
$_
[0]->find({
name
=>
$_
[1] }),
"Artist still where we left it after cycle with comments on $prefix_comment"
);
},
$ars
,
$artist
->name );
}
"Succesfull transaction with comments on $prefix_comment"
;
}
}
my
$schema
= DBICTest->init_schema();
my
$row
;
warnings_exist {
$row
=
$schema
->resultset(
'Artist'
)->create ({
name
=>
'alpha rank'
,
rank
=>
'abc'
}) }
[
qr/Non-integer value supplied for column 'rank' despite the integer datatype/
],
'proper warning on string insertion into an numeric column'
;
$row
->discard_changes;
is (
$row
->rank,
'abc'
,
'proper rank inserted into database'
);
{
__PACKAGE__->table(
'artist'
);
__PACKAGE__->add_column(
bigint
=> {
data_type
=>
'bigint'
});
}
$schema
->register_class(
BigIntArtist
=>
'DBICTest::BigIntArtist'
);
$schema
->storage->dbh_do(
sub
{
$_
[1]->
do
(
'ALTER TABLE artist ADD COLUMN bigint BIGINT'
);
});
my
$sqlite_broken_bigint
= (
modver_gt_or_eq(
'DBD::SQLite'
,
'1.34'
) and ! modver_gt_or_eq(
'DBD::SQLite'
,
'1.37'
)
);
my
$many_bits
= (Math::BigInt->new(2) ** 62);
for
my
$bi
(
qw(
-2
-1
0
+0
1
2
-9223372036854775808
-9223372036854775807
-8694837494948124658
-6848440844435891639
-5664812265578554454
-5380388020020483213
-2564279463598428141
2442753333597784273
4790993557925631491
6773854980030157393
7627910776496326154
8297530189347439311
9223372036854775806
9223372036854775807
4294967295
4294967296
-4294967296
-4294967295
-4294967294
-2147483649
-2147483648
-2147483647
-2147483646
2147483646
2147483647
)
,
$sqlite_broken_bigint
? ()
: (
'2147483648'
,
'2147483649'
)
) {
my
$v_bits
= (
$bi
> 0x7fff_ffff ||
$bi
< -0x8000_0000) ? 64 : 32;
my
$v_desc
=
sprintf
'%s (%d bit signed int)'
,
$bi
,
$v_bits
;
my
@w
;
local
$SIG
{__WARN__} =
sub
{
$_
[0] =~ /datatype mismatch/ ?
push
@w
,
@_
:
warn
@_
};
eval
{
$row
=
$schema
->resultset(
'BigIntArtist'
)->create({
bigint
=>
$bi
});
} or
do
{
fail(
"Exception on inserting $v_desc"
)
unless
$sqlite_broken_bigint
;
next
;
};
cmp_ok (
$row
->bigint,
'eq'
,
$bi
,
"value in object correct ($v_desc)"
);
$row
->discard_changes;
cmp_ok (
$row
->bigint,
(DBIx::Class::_ENV_::IV_SIZE < 8 and
$v_bits
> 32) ?
'eq'
:
'=='
,
(DBIx::Class::_ENV_::IV_SIZE < 8 and ! modver_gt_or_eq(
'DBD::SQLite'
,
'1.37'
)) ?
$bi
+0 :
$bi
,
"value in database correct ($v_desc)"
);
SKIP: {
skip
'Potential for false negatives - investigation pending'
, 1
if
DBICTest::RunMode->is_plain;
my
(
$sqlop
,
$expect
) =
$bi
< 0
? (
'(bigint + ? )'
, (
$bi
+
$many_bits
) )
: (
'(bigint - ? )'
, (
$bi
-
$many_bits
) )
;
$expect
= (
$expect
+ (
$expect
% 2)) / 2;
$sqlop
=
"( $sqlop + ( ((bigint % 2)+2)%2 ) ) / 2"
;
for
my
$dtype
(
undef
, \
'int'
, \
'bigint'
) {
$row
->update({
bigint
=>
$bi
});
$row
->discard_changes;
$row
->update({
bigint
=> \[
$sqlop
, [
$dtype
=>
$many_bits
] ] });
$row
->discard_changes;
ok (
$row
->bigint
==
(DBIx::Class::_ENV_::IV_SIZE < 8 and ! modver_gt_or_eq(
'DBD::SQLite'
,
'1.37'
)) ?
$expect
->bstr + 0 :
$expect
,
"simple integer math with@{[ $dtype ? '' : 'out' ]} bindtype in database correct (base $v_desc)"
)
or diag
sprintf
'%s != %s'
,
$row
->bigint,
$expect
;
}
}
is_deeply (\
@w
, [],
"No mismatch warnings on bigint operations ($v_desc)"
);
}
done_testing;