class sealed
{
extends
=> [
qw/Ambrosia::BaseManager/
],
private
=> [
qw/__tableIdInc/
],
};
our
$VERSION
= 0.010;
sub
_init
{
$_
[0]->__tableIdInc = 1;
}
sub
prepare
{
my
$self
=
shift
;
Context->repository->set(
schema_list
=> [] );
storage->
foreach
(\
&processDataSource
,
$self
);
my
$path_to_app
= config->ProjectPath;
if
(
$path_to_app
)
{
$path_to_app
=~ s{/[^/]+$}{};
}
else
{
$path_to_app
=
''
;
}
my
$projectName
= config()->ID;
my
$message
=
<<MESSAGE;
#######################################################################
#
# ADL file ${projectName}.xml has been created successfully.
#
# Now you can additionally edit ${projectName}.xml and run:
# ambrosia -c ${projectName}.conf -d ${projectName}.xml -a xml2app
#
#######################################################################
MESSAGE
chomp
(
my
$hostname
= `hostname`);
Context->repository->set(
config
=> {
name
=> config->ID,
label
=> config->Label,
charset
=>
lc
(config->Charset ||
'utf-8'
),
hostname
=> config->hostname ||
$hostname
,
ServerName
=> config->ServerName,
ServerPort
=> config->ServerPort,
ProjectPath
=> abs_path(
$path_to_app
),
PerlLibPath
=>
join
(
' '
,
map
{abs_path(
$_
)}
split
/\s+/, config->PerlLibPath),
} );
Context->repository->set(
Message
=>
$message
);
}
sub
getDataSource
{
my
$t
=
shift
;
my
$sn
=
shift
;
if
(
ref
config->data_source->{
$t
} eq
'ARRAY'
)
{
foreach
( @{config->data_source->{
$t
}} )
{
return
$_
if
$_
->{source_name} eq
$sn
;
}
throw Ambrosia::error::Exception::BadParams
"Error: cannot find in config data_source source_name=$sn in type = $t"
;
}
elsif
( config->data_source->{
$t
}->{source_name} eq
$sn
)
{
return
config->data_source->{
$t
};
}
else
{
throw Ambrosia::error::Exception::BadParams
"Error: cannot find in config data_source source_name=$sn in type = $t"
;
}
}
sub
processDataSource
{
my
$driver
=
shift
;
my
$type
=
shift
;
my
$source_name
=
shift
;
my
$self
=
shift
;
my
$schema_list
= Context->repository->get(
'schema_list'
);
my
$schema
= {
type
=>
$type
,
(
$driver
->catalog ? (
catalog
=>
$driver
->catalog) : ()),
schema
=>
$driver
->schema,
tables
=> [],
config
=> {} };
push
@$schema_list
,
$schema
;
my
$ds
= getDataSource(
$type
,
$source_name
);
$schema
->{config} = {
db_engine
=>
$ds
->{engine_name},
db_source
=>
$source_name
,
db_params
=>
$ds
->{engine_params},
db_user
=>
$ds
->{user},
db_password
=>
$ds
->{password},
db_charset
=> (config->data_source_info->{
$type
}->{
$source_name
}->{charset} ||
'utf8'
),
};
my
$tables
= table_info(
$driver
);
my
%hTables
= ();
my
%foreign_keys
= ();
foreach
( @{foreign_key_info(
$driver
)} )
{
push
@{
$foreign_keys
{
$_
->{pktable_name}}}, {
fktable_name
=>
$_
->{fktable_name},
pkcolumn_name
=>
$_
->{pkcolumn_name},
fkcolumn_name
=>
$_
->{fkcolumn_name},
key_seq
=>
$_
->{key_seq},
};
}
foreach
my
$t
(
@$tables
)
{
my
%primary_keys
= ();
foreach
( @{primary_key_info(
$driver
,
$t
->{table_name})} )
{
$primary_keys
{
$_
->{column_name}} =
$_
->{key_seq};
}
my
$hasPK
=
scalar
keys
%primary_keys
;
my
%table
= (
tId
=>
$self
->__tableIdInc++);
$table
{type} =
uc
$t
->{table_type};
$table
{name} =
$t
->{table_name};
if
(
my
$has_one
=
$foreign_keys
{
$table
{name}} )
{
$table
{has_one} =
$has_one
;
}
if
(
$hasPK
== 1 )
{
$table
{AUTO_UNIQUE_VALUE} =
scalar
keys
%primary_keys
== 1;
$table
{KEY} = 1;
}
elsif
(
$hasPK
)
{
$table
{KEY} = 1;
}
elsif
(
$table
{has_one} )
{
$table
{KEY} = 1;
}
my
$columns
= column_info(
$driver
,
$t
->{table_name});
my
$tablePK
= 0;
$table
{column} = [
map
{
my
$cn
=
$_
->{column_name};
my
$h
= {
Default
=>
$_
->{column_def}||
''
,
Size
=>
$_
->{column_size}||
''
,
Name
=>
$_
->{column_name}||
''
,
Remarks
=>
$_
->{remarks}||
''
,
DecimalDigits
=>
$_
->{decimal_digits}||
''
,
IsNullable
=>
$_
->{is_nullable}||
''
,
Type
=>
$_
->{type_name}||
''
,
};
if
(
$_
->{sql}->[-3] &&
$_
->{sql}->[-3] =~ /unsigned/ )
{
$h
->{Unsigned} =
'YES'
;
}
if
(
my
$seq
=
$primary_keys
{
$cn
} )
{
$tablePK
= 1;
$h
->{primary_key} =
$seq
;
$h
->{Hidden} =
"YES"
;
}
if
( !
$tablePK
&&
$table
{has_one}
&& (
my
$i
= (
grep
{
$cn
eq
$_
->{pkcolumn_name} } @{
$table
{has_one}})[0] ) )
{
$h
->{Hidden} =
"YES"
;
$h
->{foreign_key} =
$i
->{key_seq};
}
$h
;
}
sort
{
(
$primary_keys
{
$b
->{column_name}} || 0) <=> (
$primary_keys
{
$b
->{column_name}} || 0)
||
$a
->{ordinal_position} <=>
$b
->{ordinal_position} }
@$columns
];
push
@{
$schema
->{tables}}, \
%table
;
$hTables
{
$t
->{table_name}} = \
%table
;
}
foreach
(
keys
%foreign_keys
)
{
foreach
( @{
$foreign_keys
{
$_
}} )
{
$_
->{fId} =
$hTables
{
$_
->{fktable_name}}->{tId};
}
}
}
sub
table_info
{
my
$driver
=
shift
;
my
@tables
= ();
my
$sth
=
$driver
->table_info(
''
);
while
(
my
(
$table_cat
,
$table_schem
,
$table_name
,
$table_type
,
$remarks
,) =
$sth
->fetchrow_array )
{
my
%h
;
@h
{
qw/table_cat table_schem table_name table_type remarks/
} = (
$table_cat
,
$table_schem
,
$table_name
,
$table_type
,
$remarks
, );
push
@tables
, \
%h
;
}
$sth
->finish;
return
\
@tables
;
}
sub
SQL_NO_NULLS() { 0 }
sub
SQL_NULLABLE() { 1 }
sub
SQL_NULLABLE_UNKNOWN() { 2 }
sub
column_info
{
my
$driver
=
shift
;
my
$table
=
shift
;
my
$sth
=
$driver
->column_info(
$table
,
''
);
my
@columns
= ();
while
(
my
(
$table_cat
,
$table_schem
,
$table_name
,
$column_name
,
$data_type
,
$type_name
,
$column_size
,
$buffer_length
,
$decimal_digits
,
$num_prec_radix
,
$nullable
,
$remarks
,
$column_def
,
$sql_data_type
,
$sql_datetime_sub
,
$char_octet_length
,
$ordinal_position
,
$is_nullable
,
@SQL
) =
$sth
->fetchrow_array )
{
my
%h
;
@h
{
qw/table_cat table_schem table_name column_name data_type
type_name column_size buffer_length decimal_digits num_prec_radix
nullable remarks column_def sql_data_type sql_datetime_sub
char_octet_length ordinal_position is_nullable sql/
} = (
$table_cat
,
$table_schem
,
$table_name
,
$column_name
,
$data_type
,
$type_name
,
$column_size
,
$buffer_length
,
$decimal_digits
,
$num_prec_radix
,
$nullable
,
$remarks
,
$column_def
,
$sql_data_type
,
$sql_datetime_sub
,
$char_octet_length
,
$ordinal_position
,
$is_nullable
, \
@SQL
);
push
@columns
, \
%h
;
}
$sth
->finish;
return
\
@columns
;
}
sub
primary_key_info
{
my
$driver
=
shift
;
my
$table
=
shift
;
my
$sth
=
$driver
->primary_key_info(
$table
);
my
@keys
= ();
while
(
my
(
$table_cat
,
$table_schem
,
$table_name
,
$column_name
,
$key_seq
,
$pk_name
,) =
$sth
->fetchrow_array )
{
my
%h
;
@h
{
qw/table_cat table_schem table_name column_name key_seq pk_name/
} = (
$table_cat
,
$table_schem
,
$table_name
,
$column_name
,
$key_seq
,
$pk_name
, );
push
@keys
, \
%h
;
}
$sth
->finish;
return
\
@keys
;
}
sub
CASCADE { 0 }
sub
RESTRICT { 1 }
sub
SET_NULL { 2 }
sub
NO_ACTION { 3 }
sub
SET_DEFAULT { 4 }
sub
INITIALLY_DEFERRED { 5 }
sub
INITIALLY_IMMEDIATE { 6 }
sub
NOT_DEFERRABLE { 7 }
sub
foreign_key_info
{
my
$driver
=
shift
;
my
$table
=
shift
;
my
$sth
=
$driver
->foreign_key_info(
$table
,
undef
,
undef
,
undef
,);
my
@fkeys
= ();
while
(
my
(
$pktable_cat
,
$pktable_schem
,
$pktable_name
,
$pkcolumn_name
,
$fktable_cat
,
$fktable_schem
,
$fktable_name
,
$fkcolumn_name
,
$key_seq
,
$update_rule
,
$delete_rule
,
$fk_name
,
$pk_name
,
$deferrability
,
$unique_or_primary
,
) =
$sth
->fetchrow_array )
{
my
%h
;
@h
{
qw/pktable_cat pktable_schem pktable_name pkcolumn_name fktable_cat
fktable_schem fktable_name fkcolumn_name key_seq update_rule
delete_rule fk_name pk_name deferrability unique_or_primary
/
} = (
$pktable_cat
,
$pktable_schem
,
$pktable_name
,
$pkcolumn_name
,
$fktable_cat
,
$fktable_schem
,
$fktable_name
,
$fkcolumn_name
,
$key_seq
,
$update_rule
,
$delete_rule
,
$fk_name
,
$pk_name
,
$deferrability
,
$unique_or_primary
,);
push
@fkeys
, \
%h
;
}
$sth
->finish;
return
\
@fkeys
;
}
1;