our
$VERSION
=
'1.59_01'
;
my
%VALID_CONSTRAINT_TYPE
= (
PRIMARY_KEY, 1,
UNIQUE, 1,
CHECK_C, 1,
FOREIGN_KEY, 1,
NOT_NULL, 1,
);
around
BUILDARGS
=>
sub
{
my
$orig
=
shift
;
my
$self
=
shift
;
my
$args
=
$self
->
$orig
(
@_
);
foreach
my
$arg
(
keys
%{
$args
}) {
delete
$args
->{
$arg
}
if
ref
(
$args
->{
$arg
}) eq
"ARRAY"
&& !@{
$args
->{
$arg
}};
}
if
(
exists
$args
->{fields}) {
$args
->{field_names} =
delete
$args
->{fields};
}
return
$args
;
};
has
deferrable
=> (
is
=>
'rw'
,
coerce
=> quote_sub(
q{ $_[0] ? 1 : 0 }
),
default
=> quote_sub(
q{ 1 }
),
);
has
expression
=> (
is
=>
'rw'
,
default
=> quote_sub(
q{ '' }
) );
around
expression
=>
sub
{
my
(
$orig
,
$self
,
$arg
) =
@_
;
$self
->
$orig
(
$arg
|| ());
};
sub
is_valid {
my
$self
=
shift
;
my
$type
=
$self
->type or
return
$self
->error(
'No type'
);
my
$table
=
$self
->table or
return
$self
->error(
'No table'
);
my
@fields
=
$self
->fields or
return
$self
->error(
'No fields'
);
my
$table_name
=
$table
->name or
return
$self
->error(
'No table name'
);
for
my
$f
(
@fields
) {
next
if
$table
->get_field(
$f
);
return
$self
->error(
"Constraint references non-existent field '$f' "
,
"in table '$table_name'"
);
}
my
$schema
=
$table
->schema or
return
$self
->error(
'Table '
,
$table
->name,
' has no schema object'
);
if
(
$type
eq FOREIGN_KEY ) {
return
$self
->error(
'Only one field allowed for foreign key'
)
if
scalar
@fields
> 1;
my
$ref_table_name
=
$self
->reference_table or
return
$self
->error(
'No reference table'
);
my
$ref_table
=
$schema
->get_table(
$ref_table_name
) or
return
$self
->error(
"No table named '$ref_table_name' in schema"
);
my
@ref_fields
=
$self
->reference_fields or
return
;
return
$self
->error(
'Only one field allowed for foreign key reference'
)
if
scalar
@ref_fields
> 1;
for
my
$ref_field
(
@ref_fields
) {
next
if
$ref_table
->get_field(
$ref_field
);
return
$self
->error(
"Constraint from field(s) "
.
join
(
', '
,
map
{
qq['$table_name.$_']
}
@fields
).
" to non-existent field '$ref_table_name.$ref_field'"
);
}
}
elsif
(
$type
eq CHECK_C ) {
return
$self
->error(
'No expression for CHECK'
)
unless
$self
->expression;
}
return
1;
}
sub
fields {
my
$self
=
shift
;
my
$table
=
$self
->table;
my
@fields
=
map
{
$table
->get_field(
$_
) ||
$_
} @{
$self
->field_names(
@_
) || []};
return
wantarray
?
@fields
:
@fields
? \
@fields
:
undef
;
}
with
ListAttr
field_names
=> (
uniq
=> 1,
undef_if_empty
=> 1 );
has
match_type
=> (
is
=>
'rw'
,
default
=> quote_sub(
q{ '' }
),
coerce
=> quote_sub(
q{ lc $_[0] }
),
isa
=> enum([
qw(full partial simple)
], {
msg
=>
"Invalid match type: %s"
,
allow_false
=> 1,
}),
);
around
match_type
=> \
&ex2err
;
has
name
=> (
is
=>
'rw'
,
default
=> quote_sub(
q{ '' }
) );
around
name
=>
sub
{
my
(
$orig
,
$self
,
$arg
) =
@_
;
$self
->
$orig
(
$arg
|| ());
};
with
ListAttr
options
=> ();
has
on_delete
=> (
is
=>
'rw'
,
default
=> quote_sub(
q{ '' }
) );
around
on_delete
=>
sub
{
my
(
$orig
,
$self
,
$arg
) =
@_
;
$self
->
$orig
(
$arg
|| ());
};
has
on_update
=> (
is
=>
'rw'
,
default
=> quote_sub(
q{ '' }
) );
around
on_update
=>
sub
{
my
(
$orig
,
$self
,
$arg
) =
@_
;
$self
->
$orig
(
$arg
|| ());
};
with
ListAttr
reference_fields
=> (
may_throw
=> 1,
builder
=> 1,
lazy
=> 1,
);
sub
_build_reference_fields {
my
(
$self
) =
@_
;
my
$table
=
$self
->table or throw(
'No table'
);
my
$schema
=
$table
->schema or throw(
'No schema'
);
if
(
my
$ref_table_name
=
$self
->reference_table ) {
my
$ref_table
=
$schema
->get_table(
$ref_table_name
) or
throw(
"Can't find table '$ref_table_name'"
);
if
(
my
$constraint
=
$ref_table
->primary_key ) {
return
[
$constraint
->fields ];
}
else
{
throw(
'No reference fields defined and cannot find primary key in '
,
"reference table '$ref_table_name'"
);
}
}
}
has
reference_table
=> (
is
=>
'rw'
,
default
=> quote_sub(
q{ '' }
) );
has
table
=> (
is
=>
'rw'
,
isa
=> schema_obj(
'Table'
),
weak_ref
=> 1 );
around
table
=> \
&ex2err
;
has
type
=> (
is
=>
'rw'
,
default
=> quote_sub(
q{ '' }
),
coerce
=> quote_sub(
q{ (my $t = $_[0]) =~ s/_/ /g; uc $t }
),
isa
=> enum([
keys
%VALID_CONSTRAINT_TYPE
], {
msg
=>
"Invalid constraint type: %s"
,
allow_false
=> 1,
}),
);
around
type
=> \
&ex2err
;
around
equals
=>
sub
{
my
$orig
=
shift
;
my
$self
=
shift
;
my
$other
=
shift
;
my
$case_insensitive
=
shift
;
my
$ignore_constraint_names
=
shift
;
return
0
unless
$self
->
$orig
(
$other
);
return
0
unless
$self
->type eq
$other
->type;
unless
(
$ignore_constraint_names
) {
return
0
unless
$case_insensitive
?
uc
(
$self
->name) eq
uc
(
$other
->name) :
$self
->name eq
$other
->name;
}
return
0
unless
$self
->deferrable eq
$other
->deferrable;
return
0
unless
$case_insensitive
?
uc
(
$self
->table->name) eq
uc
(
$other
->table->name)
:
$self
->table->name eq
$other
->table->name;
return
0
unless
$self
->expression eq
$other
->expression;
my
%otherFields
= ();
foreach
my
$otherField
(
$other
->fields) {
$otherField
=
uc
(
$otherField
)
if
$case_insensitive
;
$otherFields
{
$otherField
} = 1;
}
foreach
my
$selfField
(
$self
->fields) {
$selfField
=
uc
(
$selfField
)
if
$case_insensitive
;
return
0
unless
$otherFields
{
$selfField
};
delete
$otherFields
{
$selfField
};
}
return
0
unless
keys
%otherFields
== 0;
my
%otherRefFields
= ();
foreach
my
$otherRefField
(
$other
->reference_fields) {
$otherRefField
=
uc
(
$otherRefField
)
if
$case_insensitive
;
$otherRefFields
{
$otherRefField
} = 1;
}
foreach
my
$selfRefField
(
$self
->reference_fields) {
$selfRefField
=
uc
(
$selfRefField
)
if
$case_insensitive
;
return
0
unless
$otherRefFields
{
$selfRefField
};
delete
$otherRefFields
{
$selfRefField
};
}
return
0
unless
keys
%otherRefFields
== 0;
return
0
unless
$case_insensitive
?
uc
(
$self
->reference_table) eq
uc
(
$other
->reference_table) :
$self
->reference_table eq
$other
->reference_table;
return
0
unless
$self
->match_type eq
$other
->match_type;
return
0
unless
$self
->on_delete eq
$other
->on_delete;
return
0
unless
$self
->on_update eq
$other
->on_update;
return
0
unless
$self
->_compare_objects(
scalar
$self
->options,
scalar
$other
->options);
return
0
unless
$self
->_compare_objects(
scalar
$self
->extra,
scalar
$other
->extra);
return
1;
};
around
new
=> \
&ex2err
;
1;