don't set result_namespace if it's 'Result'
[dbsrgits/DBIx-Class-Schema-Loader.git] / lib / DBIx / Class / Schema / Loader / DBI / InterBase.pm
CommitLineData
4cbddf8d 1package DBIx::Class::Schema::Loader::DBI::InterBase;
2
3use strict;
4use warnings;
4145a6f3 5use namespace::autoclean;
4cbddf8d 6use Class::C3;
7use base qw/DBIx::Class::Schema::Loader::DBI/;
8use Carp::Clan qw/^DBIx::Class/;
4145a6f3 9use List::Util 'first';
4cbddf8d 10
18e84656 11__PACKAGE__->mk_group_ro_accessors('simple', qw/
12 unquoted_ddl
13/);
14
2a8e93e9 15our $VERSION = '0.06000';
4cbddf8d 16
17=head1 NAME
18
19DBIx::Class::Schema::Loader::DBI::InterBase - DBIx::Class::Schema::Loader::DBI
20Firebird Implementation.
21
22=head1 DESCRIPTION
23
243c6ebc 24See L<DBIx::Class::Schema::Loader::Base> for available options.
4cbddf8d 25
18e84656 26By default column names from unquoted DDL will be generated in uppercase, as
27that is the only way they will work with quoting on.
28
29See the L</unquoted_ddl> option in this driver if you would like to have
30lowercase column names.
31
32=head1 DRIVER OPTIONS
33
34=head2 unquoted_ddl
35
36Set this loader option if your DDL uses unquoted identifiers and you will not
37use quoting (the L<quote_char|DBIx::Class::Storage::DBI/quote_char> option in
38L<connect_info|DBIx::Class::Storage::DBI/connect_info>.)
39
40This will generate lowercase column names (as opposed to the actual uppercase
41names) in your Result classes that will only work with quoting off.
42
43Mixed-case table and column names will be ignored when this option is on and
44will not work with quoting turned off.
45
4cbddf8d 46=cut
47
18e84656 48sub _is_case_sensitive {
49 my $self = shift;
50
51 return $self->unquoted_ddl ? 0 : 1;
52}
243c6ebc 53
ffb03c96 54sub _setup {
55 my $self = shift;
56
18e84656 57 $self->next::method;
58
ffb03c96 59 $self->schema->storage->sql_maker->name_sep('.');
18e84656 60
61 if (not $self->unquoted_ddl) {
62 $self->schema->storage->sql_maker->quote_char('"');
63 }
64 else {
65 $self->schema->storage->sql_maker->quote_char(undef);
66 }
67}
68
69sub _lc {
70 my ($self, $name) = @_;
71
72 return $self->unquoted_ddl ? lc($name) : $name;
73}
74
75sub _uc {
76 my ($self, $name) = @_;
77
78 return $self->unquoted_ddl ? uc($name) : $name;
ffb03c96 79}
80
4cbddf8d 81sub _table_pk_info {
82 my ($self, $table) = @_;
83
84 my $dbh = $self->schema->storage->dbh;
85 my $sth = $dbh->prepare(<<'EOF');
86SELECT iseg.rdb$field_name
87FROM rdb$relation_constraints rc
88JOIN rdb$index_segments iseg ON rc.rdb$index_name = iseg.rdb$index_name
89WHERE rc.rdb$constraint_type = 'PRIMARY KEY' and rc.rdb$relation_name = ?
90ORDER BY iseg.rdb$field_position
91EOF
92 $sth->execute($table);
93
94 my @keydata;
95
96 while (my ($col) = $sth->fetchrow_array) {
97 s/^\s+//, s/\s+\z// for $col;
98
18e84656 99 push @keydata, $self->_lc($col);
4cbddf8d 100 }
101
102 return \@keydata;
103}
104
105sub _table_fk_info {
106 my ($self, $table) = @_;
107
108 my ($local_cols, $remote_cols, $remote_table, @rels);
109 my $dbh = $self->schema->storage->dbh;
110 my $sth = $dbh->prepare(<<'EOF');
111SELECT rc.rdb$constraint_name fk, iseg.rdb$field_name local_col, ri.rdb$relation_name remote_tab, riseg.rdb$field_name remote_col
112FROM rdb$relation_constraints rc
113JOIN rdb$index_segments iseg ON rc.rdb$index_name = iseg.rdb$index_name
114JOIN rdb$indices li ON rc.rdb$index_name = li.rdb$index_name
115JOIN rdb$indices ri ON li.rdb$foreign_key = ri.rdb$index_name
116JOIN rdb$index_segments riseg ON iseg.rdb$field_position = riseg.rdb$field_position and ri.rdb$index_name = riseg.rdb$index_name
117WHERE rc.rdb$constraint_type = 'FOREIGN KEY' and rc.rdb$relation_name = ?
118ORDER BY iseg.rdb$field_position
119EOF
120 $sth->execute($table);
121
122 while (my ($fk, $local_col, $remote_tab, $remote_col) = $sth->fetchrow_array) {
123 s/^\s+//, s/\s+\z// for $fk, $local_col, $remote_tab, $remote_col;
124
18e84656 125 push @{$local_cols->{$fk}}, $self->_lc($local_col);
126 push @{$remote_cols->{$fk}}, $self->_lc($remote_col);
4cbddf8d 127 $remote_table->{$fk} = $remote_tab;
128 }
129
130 foreach my $fk (keys %$remote_table) {
131 push @rels, {
132 local_columns => $local_cols->{$fk},
133 remote_columns => $remote_cols->{$fk},
134 remote_table => $remote_table->{$fk},
135 };
136 }
137 return \@rels;
138}
139
140sub _table_uniq_info {
141 my ($self, $table) = @_;
142
143 my $dbh = $self->schema->storage->dbh;
144 my $sth = $dbh->prepare(<<'EOF');
145SELECT rc.rdb$constraint_name, iseg.rdb$field_name
146FROM rdb$relation_constraints rc
147JOIN rdb$index_segments iseg ON rc.rdb$index_name = iseg.rdb$index_name
148WHERE rc.rdb$constraint_type = 'UNIQUE' and rc.rdb$relation_name = ?
149ORDER BY iseg.rdb$field_position
150EOF
151 $sth->execute($table);
152
153 my $constraints;
154 while (my ($constraint_name, $column) = $sth->fetchrow_array) {
155 s/^\s+//, s/\s+\z// for $constraint_name, $column;
156
18e84656 157 push @{$constraints->{$constraint_name}}, $self->_lc($column);
4cbddf8d 158 }
159
160 my @uniqs = map { [ $_ => $constraints->{$_} ] } keys %$constraints;
161 return \@uniqs;
162}
163
45be2ce7 164sub _extra_column_info {
165 my ($self, $table, $column, $info, $dbi_info) = @_;
166 my %extra_info;
167
168 my $dbh = $self->schema->storage->dbh;
169
170 local $dbh->{LongReadLen} = 100000;
171 local $dbh->{LongTruncOk} = 1;
172
173 my $sth = $dbh->prepare(<<'EOF');
174SELECT t.rdb$trigger_source
175FROM rdb$triggers t
176WHERE t.rdb$relation_name = ?
93e8c513 177AND t.rdb$system_flag = 0 -- user defined
178AND t.rdb$trigger_type = 1 -- BEFORE INSERT
45be2ce7 179EOF
45be2ce7 180 $sth->execute($table);
181
182 while (my ($trigger) = $sth->fetchrow_array) {
243c6ebc 183 my @trig_cols = map {
184 /^"([^"]+)/ ? $1 : uc($1)
185 } $trigger =~ /new\.("?\w+"?)/ig;
186
187 my ($quoted, $generator) = $trigger =~
188/(?:gen_id\s* \( \s* |next \s* value \s* for \s*)(")?(\w+)/ix;
4145a6f3 189
0e0a4941 190 if ($generator) {
191 $generator = uc $generator unless $quoted;
192
18e84656 193 if (first { $self->_uc($_) eq $self->_uc($column) } @trig_cols) {
0e0a4941 194 $extra_info{is_auto_increment} = 1;
195 $extra_info{sequence} = $generator;
196 last;
197 }
45be2ce7 198 }
199 }
200
4145a6f3 201# fix up DT types, no idea which other types are fucked
202 if ($info->{data_type} eq '11') {
203 $extra_info{data_type} = 'TIMESTAMP';
204 }
205 elsif ($info->{data_type} eq '9') {
206 $extra_info{data_type} = 'DATE';
207 }
208
209# get default
210 $sth = $dbh->prepare(<<'EOF');
211SELECT rf.rdb$default_source
212FROM rdb$relation_fields rf
213WHERE rf.rdb$relation_name = ?
214AND rf.rdb$field_name = ?
215EOF
18e84656 216 $sth->execute($table, $self->_uc($column));
4145a6f3 217 my ($default_src) = $sth->fetchrow_array;
218
219 if ($default_src && (my ($def) = $default_src =~ /^DEFAULT \s+ (\S+)/ix)) {
220 if (my ($quoted) = $def =~ /^'(.*?)'\z/) {
221 $extra_info{default_value} = $quoted;
222 }
223 else {
224 $extra_info{default_value} = $def =~ /^\d/ ? $def : \$def;
225 }
226 }
227
45be2ce7 228 return \%extra_info;
229}
230
4cbddf8d 231=head1 SEE ALSO
232
233L<DBIx::Class::Schema::Loader>, L<DBIx::Class::Schema::Loader::Base>,
234L<DBIx::Class::Schema::Loader::DBI>
235
236=head1 AUTHOR
237
238See L<DBIx::Class::Schema::Loader/AUTHOR> and L<DBIx::Class::Schema::Loader/CONTRIBUTORS>.
239
240=head1 LICENSE
241
242This library is free software; you can redistribute it and/or modify it under
243the same terms as Perl itself.
244
245=cut
246
2471;