Commit | Line | Data |
b8657f04 |
1 | package SQL::Translator::Parser::DBI; |
abb2c327 |
2 | use namespace::autoclean; |
684763c1 |
3 | use Moose::Role; |
4 | use MooseX::Types::Moose qw(Maybe Str); |
b8657f04 |
5 | use DBI::Const::GetInfoType; |
c4ec1b63 |
6 | use DBI::Const::GetInfo::ANSI; |
7 | use DBI::Const::GetInfoReturn; |
44547961 |
8 | use aliased 'SQL::Translator::Object::Column'; |
47b211fd |
9 | use aliased 'SQL::Translator::Object::ForeignKey'; |
92403c5e |
10 | use aliased 'SQL::Translator::Object::Index'; |
47b211fd |
11 | use aliased 'SQL::Translator::Object::PrimaryKey'; |
44547961 |
12 | use aliased 'SQL::Translator::Object::Table'; |
13 | use aliased 'SQL::Translator::Object::View'; |
b8657f04 |
14 | |
684763c1 |
15 | has 'quoter' => ( |
44547961 |
16 | is => 'rw', |
17 | isa => Str, |
44547961 |
18 | lazy => 1, |
19 | default => sub { shift->dbh->get_info(29) || q{"} } |
b8657f04 |
20 | ); |
21 | |
684763c1 |
22 | has 'namesep' => ( |
44547961 |
23 | is => 'rw', |
24 | isa => Str, |
44547961 |
25 | lazy => 1, |
26 | default => sub { shift->dbh->get_info(41) || '.' } |
b8657f04 |
27 | ); |
28 | |
684763c1 |
29 | has 'schema_name' => ( |
44547961 |
30 | is => 'rw', |
31 | isa => Maybe[Str], |
44547961 |
32 | lazy => 1, |
33 | default => undef |
684763c1 |
34 | ); |
35 | |
36 | has 'catalog_name' => ( |
44547961 |
37 | is => 'rw', |
38 | isa => Maybe[Str], |
44547961 |
39 | lazy => 1, |
40 | default => undef |
b8657f04 |
41 | ); |
42 | |
684763c1 |
43 | sub _subclass { |
b8657f04 |
44 | my $self = shift; |
45 | |
684763c1 |
46 | my $dbtype = $self->dbh->get_info($GetInfoType{SQL_DBMS_NAME}) || $self->dbh->{Driver}{Name}; |
b8657f04 |
47 | |
684763c1 |
48 | my $class = __PACKAGE__ . '::'. $dbtype; |
49 | Class::MOP::load_class($class); |
50 | $class->meta->apply($self); |
51 | } |
52 | |
641ce7d8 |
53 | sub _is_auto_increment { 0 } |
54 | |
55 | sub _column_default_value { |
56 | my $self = shift; |
57 | my $column_info = shift; |
58 | |
59 | return $column_info->{COLUMN_DEF}; |
60 | } |
61 | |
684763c1 |
62 | sub _add_tables { |
63 | my $self = shift; |
64 | my $schema = shift; |
65 | |
66 | my $sth = $self->dbh->table_info($self->catalog_name, $self->schema_name, '%', 'TABLE,VIEW'); |
67 | while (my $table_info = $sth->fetchrow_hashref) { |
68 | if ($table_info->{TABLE_TYPE} eq 'TABLE') { |
44547961 |
69 | my $table = Table->new({ name => $table_info->{TABLE_NAME} }); |
684763c1 |
70 | $schema->add_table($table); |
71 | $self->_add_columns($table); |
72 | $self->_add_primary_key($table); |
92403c5e |
73 | $self->_add_indexes($table); |
684763c1 |
74 | } |
75 | elsif ($table_info->{TABLE_TYPE} eq 'VIEW') { |
76 | my $sql = $self->_get_view_sql($table_info->{TABLE_NAME}); |
44547961 |
77 | my $view = View->new({ name => $table_info->{TABLE_NAME}, sql => $sql }); |
78 | $schema->add_view($view); |
79 | $self->_add_columns($view); |
684763c1 |
80 | } |
81 | } |
2179164f |
82 | $self->_add_foreign_keys($schema->get_table($_), $schema) for $schema->table_ids; |
684763c1 |
83 | } |
b8657f04 |
84 | |
684763c1 |
85 | sub _add_columns { |
86 | my $self = shift; |
87 | my $table = shift; |
b8657f04 |
88 | |
684763c1 |
89 | my $sth = $self->dbh->column_info($self->catalog_name, $self->schema_name, $table->name, '%'); |
641ce7d8 |
90 | while (my $column_info = $sth->fetchrow_hashref) { |
91 | my $column = Column->new({ name => $column_info->{COLUMN_NAME}, |
92 | data_type => $column_info->{DATA_TYPE}, |
93 | size => $column_info->{COLUMN_SIZE}, |
94 | default_value => $self->_column_default_value($column_info), |
95 | is_auto_increment => $self->_is_auto_increment($column_info), |
96 | is_nullable => $column_info->{NULLABLE}, |
97 | }); |
684763c1 |
98 | $table->add_column($column); |
684763c1 |
99 | } |
100 | } |
101 | |
102 | sub _add_primary_key { |
103 | my $self = shift; |
104 | my $table = shift; |
b8657f04 |
105 | |
684763c1 |
106 | my $pk_info = $self->dbh->primary_key_info($self->catalog_name, $self->schema_name, $table->name); |
684763c1 |
107 | my ($pk_name, @pk_cols); |
108 | while (my $pk_col = $pk_info->fetchrow_hashref) { |
109 | $pk_name = $pk_col->{PK_NAME}; |
110 | push @pk_cols, $pk_col->{COLUMN_NAME}; |
aad333cd |
111 | } |
47b211fd |
112 | my $pk = PrimaryKey->new({ name => $pk_name }); |
113 | $pk->add_column($table->get_column($_)) for @pk_cols; |
114 | $table->add_index($pk); |
115 | } |
116 | |
2179164f |
117 | sub _add_foreign_keys { |
47b211fd |
118 | my $self = shift; |
119 | my $table = shift; |
120 | my $schema = shift; |
121 | |
122 | my $fk_info = $self->dbh->foreign_key_info($self->catalog_name, $self->schema_name, $table->name, $self->catalog_name, $self->schema_name, undef); |
123 | return unless $fk_info; |
124 | |
125 | my $fk_data; |
126 | while (my $fk_col = $fk_info->fetchrow_hashref) { |
127 | my $fk_name = $fk_col->{FK_NAME}; |
128 | |
129 | push @{$fk_data->{$fk_name}{columns}}, $fk_col->{FK_COLUMN_NAME}; |
130 | $fk_data->{$fk_name}{table} = $fk_col->{FK_TABLE_NAME}; |
131 | $fk_data->{$fk_name}{uk} = $schema->get_table($fk_col->{UK_TABLE_NAME})->get_index($fk_col->{UK_NAME}); |
132 | } |
133 | |
134 | foreach my $fk_name (keys %$fk_data) { |
135 | my $fk = ForeignKey->new({ name => $fk_name, references => $fk_data->{$fk_name}{uk} }); |
136 | $fk->add_column($schema->get_table($fk_data->{$fk_name}{table})->get_column($_)) for @{$fk_data->{$fk_name}{columns}}; |
137 | $table->add_constraint($fk); |
138 | } |
b8657f04 |
139 | } |
140 | |
92403c5e |
141 | sub _add_indexes { |
142 | my $self = shift; |
143 | my $table = shift; |
144 | |
145 | my $index_info = $self->dbh->statistics_info($self->catalog_name, $self->schema_name, $table->name, 1, 0); |
146 | |
147 | my ($index_name, $index_type, @index_cols); |
148 | while (my $index_col = $index_info->fetchrow_hashref) { |
149 | $index_name = $index_col->{INDEX_NAME}; |
8e50a529 |
150 | $index_type = $index_col->{NON_UNIQUE} ? 'NORMAL' : 'UNIQUE'; |
92403c5e |
151 | push @index_cols, $index_col->{COLUMN_NAME}; |
152 | } |
e283ffd7 |
153 | return if $table->exists_index($index_name); |
92403c5e |
154 | my $index = Index->new({ name => $index_name, type => $index_type }); |
155 | $index->add_column($table->get_column($_)) for @index_cols; |
156 | $table->add_index($index); |
157 | } |
158 | |
b8657f04 |
159 | 1; |