our
$VERSION
=
'1.66'
;
has
_order
=> (
is
=>
'ro'
,
default
=> quote_sub(
q{ +{ map { $_ => 0 }
qw/
table
view
trigger
proc
/
} }
),
);
sub
as_graph_pm {
my
$self
=
shift
;
my
$g
= Graph::Directed->new;
for
my
$table
(
$self
->get_tables) {
my
$tname
=
$table
->name;
$g
->add_vertex(
$tname
);
for
my
$field
(
$table
->get_fields) {
if
(
$field
->is_foreign_key) {
my
$fktable
=
$field
->foreign_key_reference->reference_table;
$g
->add_edge(
$fktable
,
$tname
);
}
}
}
return
$g
;
}
has
_tables
=> (
is
=>
'ro'
,
init_arg
=>
undef
,
default
=> quote_sub(
q{ +{}
}));
sub
add_table {
my
$self
=
shift
;
my
$table_class
=
'SQL::Translator::Schema::Table'
;
my
$table
;
if
(UNIVERSAL::isa(
$_
[0],
$table_class
)) {
$table
=
shift
;
$table
->schema(
$self
);
}
else
{
my
%args
=
ref
$_
[0] eq
'HASH'
? %{
$_
[0] } :
@_
;
$args
{
'schema'
} =
$self
;
$table
=
$table_class
->new(\
%args
)
or
return
$self
->error(
$table_class
->error);
}
$table
->order(++
$self
->_order->{table});
my
$table_name
=
$table
->name;
if
(
defined
$self
->_tables->{
$table_name
}) {
return
$self
->error(
qq[Can't use table name "$table_name": table exists]
);
}
else
{
$self
->_tables->{
$table_name
} =
$table
;
}
return
$table
;
}
sub
drop_table {
my
$self
=
shift
;
my
$table_class
=
'SQL::Translator::Schema::Table'
;
my
$table_name
;
if
(UNIVERSAL::isa(
$_
[0],
$table_class
)) {
$table_name
=
shift
->name;
}
else
{
$table_name
=
shift
;
}
my
%args
=
@_
;
my
$cascade
=
$args
{
'cascade'
};
if
(!
exists
$self
->_tables->{
$table_name
}) {
return
$self
->error(
qq[Can't drop table: "$table_name" doesn't exist]
);
}
my
$table
=
delete
$self
->_tables->{
$table_name
};
if
(
$cascade
) {
$self
->drop_trigger()
for
(
grep
{
$_
->on_table eq
$table_name
}
values
%{
$self
->_triggers });
}
return
$table
;
}
has
_procedures
=> (
is
=>
'ro'
,
init_arg
=>
undef
,
default
=> quote_sub(
q{ +{}
}));
sub
add_procedure {
my
$self
=
shift
;
my
$procedure_class
=
'SQL::Translator::Schema::Procedure'
;
my
$procedure
;
if
(UNIVERSAL::isa(
$_
[0],
$procedure_class
)) {
$procedure
=
shift
;
$procedure
->schema(
$self
);
}
else
{
my
%args
=
ref
$_
[0] eq
'HASH'
? %{
$_
[0] } :
@_
;
$args
{
'schema'
} =
$self
;
return
$self
->error(
'No procedure name'
)
unless
$args
{
'name'
};
$procedure
=
$procedure_class
->new(\
%args
)
or
return
$self
->error(
$procedure_class
->error);
}
$procedure
->order(++
$self
->_order->{proc});
my
$procedure_name
=
$procedure
->name
or
return
$self
->error(
'No procedure name'
);
if
(
defined
$self
->_procedures->{
$procedure_name
}) {
return
$self
->error(
qq[Can't create procedure: "$procedure_name" exists]
);
}
else
{
$self
->_procedures->{
$procedure_name
} =
$procedure
;
}
return
$procedure
;
}
sub
drop_procedure {
my
$self
=
shift
;
my
$proc_class
=
'SQL::Translator::Schema::Procedure'
;
my
$proc_name
;
if
(UNIVERSAL::isa(
$_
[0],
$proc_class
)) {
$proc_name
=
shift
->name;
}
else
{
$proc_name
=
shift
;
}
if
(!
exists
$self
->_procedures->{
$proc_name
}) {
return
$self
->error(
qq[Can't drop procedure: "$proc_name" doesn't exist]
);
}
my
$proc
=
delete
$self
->_procedures->{
$proc_name
};
return
$proc
;
}
has
_triggers
=> (
is
=>
'ro'
,
init_arg
=>
undef
,
default
=> quote_sub(
q{ +{}
}));
sub
add_trigger {
my
$self
=
shift
;
my
$trigger_class
=
'SQL::Translator::Schema::Trigger'
;
my
$trigger
;
if
(UNIVERSAL::isa(
$_
[0],
$trigger_class
)) {
$trigger
=
shift
;
$trigger
->schema(
$self
);
}
else
{
my
%args
=
ref
$_
[0] eq
'HASH'
? %{
$_
[0] } :
@_
;
$args
{
'schema'
} =
$self
;
return
$self
->error(
'No trigger name'
)
unless
$args
{
'name'
};
$trigger
=
$trigger_class
->new(\
%args
)
or
return
$self
->error(
$trigger_class
->error);
}
$trigger
->order(++
$self
->_order->{trigger});
my
$trigger_name
=
$trigger
->name or
return
$self
->error(
'No trigger name'
);
if
(
defined
$self
->_triggers->{
$trigger_name
}) {
return
$self
->error(
qq[Can't create trigger: "$trigger_name" exists]
);
}
else
{
$self
->_triggers->{
$trigger_name
} =
$trigger
;
}
return
$trigger
;
}
sub
drop_trigger {
my
$self
=
shift
;
my
$trigger_class
=
'SQL::Translator::Schema::Trigger'
;
my
$trigger_name
;
if
(UNIVERSAL::isa(
$_
[0],
$trigger_class
)) {
$trigger_name
=
shift
->name;
}
else
{
$trigger_name
=
shift
;
}
if
(!
exists
$self
->_triggers->{
$trigger_name
}) {
return
$self
->error(
qq[Can't drop trigger: "$trigger_name" doesn't exist]
);
}
my
$trigger
=
delete
$self
->_triggers->{
$trigger_name
};
return
$trigger
;
}
has
_views
=> (
is
=>
'ro'
,
init_arg
=>
undef
,
default
=> quote_sub(
q{ +{}
}));
sub
add_view {
my
$self
=
shift
;
my
$view_class
=
'SQL::Translator::Schema::View'
;
my
$view
;
if
(UNIVERSAL::isa(
$_
[0],
$view_class
)) {
$view
=
shift
;
$view
->schema(
$self
);
}
else
{
my
%args
=
ref
$_
[0] eq
'HASH'
? %{
$_
[0] } :
@_
;
$args
{
'schema'
} =
$self
;
return
$self
->error(
'No view name'
)
unless
$args
{
'name'
};
$view
=
$view_class
->new(\
%args
) or
return
$view_class
->error;
}
$view
->order(++
$self
->_order->{view});
my
$view_name
=
$view
->name or
return
$self
->error(
'No view name'
);
if
(
defined
$self
->_views->{
$view_name
}) {
return
$self
->error(
qq[Can't create view: "$view_name" exists]
);
}
else
{
$self
->_views->{
$view_name
} =
$view
;
}
return
$view
;
}
sub
drop_view {
my
$self
=
shift
;
my
$view_class
=
'SQL::Translator::Schema::View'
;
my
$view_name
;
if
(UNIVERSAL::isa(
$_
[0],
$view_class
)) {
$view_name
=
shift
->name;
}
else
{
$view_name
=
shift
;
}
if
(!
exists
$self
->_views->{
$view_name
}) {
return
$self
->error(
qq[Can't drop view: "$view_name" doesn't exist]
);
}
my
$view
=
delete
$self
->_views->{
$view_name
};
return
$view
;
}
has
database
=> (
is
=>
'rw'
,
default
=> quote_sub(
q{ '' }
));
sub
is_valid {
my
$self
=
shift
;
return
$self
->error(
'No tables'
)
unless
$self
->get_tables;
for
my
$object
(
$self
->get_tables,
$self
->get_views) {
return
$object
->error
unless
$object
->is_valid;
}
return
1;
}
sub
get_procedure {
my
$self
=
shift
;
my
$procedure_name
=
shift
or
return
$self
->error(
'No procedure name'
);
return
$self
->error(
qq[Table "$procedure_name" does not exist]
)
unless
exists
$self
->_procedures->{
$procedure_name
};
return
$self
->_procedures->{
$procedure_name
};
}
sub
get_procedures {
my
$self
=
shift
;
my
@procedures
=
map
{
$_
->[1] }
sort
{
$a
->[0] <=>
$b
->[0] }
map
{ [
$_
->order,
$_
] }
values
%{
$self
->_procedures };
if
(
@procedures
) {
return
wantarray
?
@procedures
: \
@procedures
;
}
else
{
$self
->error(
'No procedures'
);
return
;
}
}
sub
get_table {
my
$self
=
shift
;
my
$table_name
=
shift
or
return
$self
->error(
'No table name'
);
my
$case_insensitive
=
shift
;
if
(
$case_insensitive
) {
$table_name
=
uc
(
$table_name
);
foreach
my
$table
(
keys
%{
$self
->_tables }) {
return
$self
->_tables->{
$table
}
if
$table_name
eq
uc
(
$table
);
}
return
$self
->error(
qq[Table "$table_name" does not exist]
);
}
return
$self
->error(
qq[Table "$table_name" does not exist]
)
unless
exists
$self
->_tables->{
$table_name
};
return
$self
->_tables->{
$table_name
};
}
sub
get_tables {
my
$self
=
shift
;
my
@tables
=
map
{
$_
->[1] }
sort
{
$a
->[0] <=>
$b
->[0] }
map
{ [
$_
->order,
$_
] }
values
%{
$self
->_tables };
if
(
@tables
) {
return
wantarray
?
@tables
: \
@tables
;
}
else
{
$self
->error(
'No tables'
);
return
;
}
}
sub
get_trigger {
my
$self
=
shift
;
my
$trigger_name
=
shift
or
return
$self
->error(
'No trigger name'
);
return
$self
->error(
qq[Trigger "$trigger_name" does not exist]
)
unless
exists
$self
->_triggers->{
$trigger_name
};
return
$self
->_triggers->{
$trigger_name
};
}
sub
get_triggers {
my
$self
=
shift
;
my
@triggers
=
map
{
$_
->[1] }
sort
{
$a
->[0] <=>
$b
->[0] }
map
{ [
$_
->order,
$_
] }
values
%{
$self
->_triggers };
if
(
@triggers
) {
return
wantarray
?
@triggers
: \
@triggers
;
}
else
{
$self
->error(
'No triggers'
);
return
;
}
}
sub
get_view {
my
$self
=
shift
;
my
$view_name
=
shift
or
return
$self
->error(
'No view name'
);
return
$self
->error(
'View "$view_name" does not exist'
)
unless
exists
$self
->_views->{
$view_name
};
return
$self
->_views->{
$view_name
};
}
sub
get_views {
my
$self
=
shift
;
my
@views
=
map
{
$_
->[1] }
sort
{
$a
->[0] <=>
$b
->[0] }
map
{ [
$_
->order,
$_
] }
values
%{
$self
->_views };
if
(
@views
) {
return
wantarray
?
@views
: \
@views
;
}
else
{
$self
->error(
'No views'
);
return
;
}
}
sub
make_natural_joins {
my
$self
=
shift
;
my
%args
=
@_
;
my
$join_pk_only
=
$args
{
'join_pk_only'
} || 0;
my
%skip_fields
=
map
{ s/^\s+|\s+$//g;
$_
, 1 } @{ parse_list_arg(
$args
{
'skip_fields'
}) };
my
(
%common_keys
,
%pk
);
for
my
$table
(
$self
->get_tables) {
for
my
$field
(
$table
->get_fields) {
my
$field_name
=
$field
->name or
next
;
next
if
$skip_fields
{
$field_name
};
$pk
{
$field_name
} = 1
if
$field
->is_primary_key;
push
@{
$common_keys
{
$field_name
} },
$table
->name;
}
}
for
my
$field
(
keys
%common_keys
) {
next
if
$join_pk_only
and !
defined
$pk
{
$field
};
my
@table_names
= @{
$common_keys
{
$field
} };
next
unless
scalar
@table_names
> 1;
for
my
$i
(0 ..
$#table_names
) {
my
$table1
=
$self
->get_table(
$table_names
[
$i
]) or
next
;
for
my
$j
(1 ..
$#table_names
) {
my
$table2
=
$self
->get_table(
$table_names
[
$j
]) or
next
;
next
if
$table1
->name eq
$table2
->name;
$table1
->add_constraint(
type
=> FOREIGN_KEY,
fields
=>
$field
,
reference_table
=>
$table2
->name,
reference_fields
=>
$field
,
);
}
}
}
return
1;
}
has
name
=> (
is
=>
'rw'
,
default
=> quote_sub(
q{ '' }
));
has
translator
=> (
is
=>
'rw'
,
weak_ref
=> 1);
1;