File Coverage

blib/lib/SQL/Translator/Parser/DBI/Sybase.pm
Criterion Covered Total %
statement 18 100 18.0
branch 0 30 0.0
condition 0 4 0.0
subroutine 6 7 85.7
pod 0 1 0.0
total 24 142 16.9


line stmt bran cond sub pod time code
1             package SQL::Translator::Parser::DBI::Sybase;
2              
3             =head1 NAME
4              
5             SQL::Translator::Parser::DBI::Sybase - parser for DBD::Sybase
6              
7             =head1 SYNOPSIS
8              
9             See SQL::Translator::Parser::DBI.
10              
11             =head1 DESCRIPTION
12              
13             Uses DBI Catalog Methods.
14              
15             =cut
16              
17 1     1   5 use strict;
  1         2  
  1         31  
18 1     1   3 use warnings;
  1         2  
  1         34  
19 1     1   1341 use DBI;
  1         17017  
  1         58  
20 1     1   545 use SQL::Translator::Schema;
  1         7  
  1         58  
21 1     1   923 use Data::Dumper;
  1         16642  
  1         209  
22              
23             our ($DEBUG, @EXPORT_OK);
24             our $VERSION = '1.66';
25             $DEBUG = 0 unless defined $DEBUG;
26              
27 1     1   11 no strict 'refs';
  1         2  
  1         1780  
28              
29             sub parse {
30 0     0 0   my ($tr, $dbh) = @_;
31              
32 0 0         if ($dbh->{FetchHashKeyName} ne 'NAME_uc') {
33 0           warn "setting dbh attribute {FetchHashKeyName} to NAME_uc";
34 0           $dbh->{FetchHashKeyName} = 'NAME_uc';
35             }
36              
37 0 0         if ($dbh->{ChopBlanks} != 1) {
38 0           warn "setting dbh attribute {ChopBlanks} to 1";
39 0           $dbh->{ChopBlanks} = 1;
40             }
41              
42 0           my $schema = $tr->schema;
43              
44 0           my ($sth, @tables, $columns);
45 0           my $stuff;
46              
47             ### Columns
48              
49             # it is much quicker to slurp back everything all at once rather
50             # than make repeated calls
51              
52 0           $sth = $dbh->column_info(undef, undef, undef, undef);
53              
54 0           foreach my $c (@{ $sth->fetchall_arrayref({}) }) {
  0            
55             $columns->{ $c->{TABLE_CAT} }->{ $c->{TABLE_SCHEM} }
56 0           ->{ $c->{TABLE_NAME} }->{columns}->{ $c->{COLUMN_NAME} } = $c;
57             }
58              
59             ### Tables and views
60              
61             # Get a list of the tables and views.
62 0           $sth = $dbh->table_info();
63 0           @tables = @{ $sth->fetchall_arrayref({}) };
  0            
64              
65 0           my $h = $dbh->selectall_arrayref(
66             q{
67             SELECT o.name, colid,colid2,c.text
68             FROM syscomments c
69             JOIN sysobjects o
70             ON c.id = o.id
71             WHERE o.type ='V'
72             ORDER BY o.name,
73             c.colid,
74             c.colid2
75             }
76             );
77              
78             # View text
79             # I had always thought there was something 'hard' about
80             # reconstructing text from syscomments ..
81             # this seems to work fine and is certainly not complicated!
82              
83 0           foreach (@{$h}) {
  0            
84 0           $stuff->{view}->{ $_->[0] }->{text} .= $_->[3];
85             }
86              
87             #### objects with indexes.
88 0 0         map { $stuff->{indexes}->{ $_->[0] }++ if defined; } @{
89 0           $dbh->selectall_arrayref(
  0            
90             "SELECT DISTINCT object_name(id) AS name
91             FROM sysindexes
92             WHERE indid > 0"
93             )
94             };
95              
96             ## slurp objects
97 0           map { $stuff->{ $_->[1] }->{ $_->[0] } = $_; } @{ $dbh->selectall_arrayref("SELECT name,type, id FROM sysobjects") };
  0            
  0            
98              
99             ### Procedures
100              
101             # This gets legitimate procedures by used the 'supported' API: sp_stored_procedures
102             map {
103 0           my $n = $_->{PROCEDURE_NAME};
104 0           $n =~ s/;\d+$//; # Ignore versions for now
105 0           $_->{name} = $n;
106 0           $stuff->{procedures}->{$n} = $_;
107 0           } values %{ $dbh->selectall_hashref("sp_stored_procedures", 'PROCEDURE_NAME') };
  0            
108              
109             # And this blasts in the text of 'legit' stored procedures. Do
110             # this rather than calling sp_helptext in a loop.
111              
112 0           $h = $dbh->selectall_arrayref(
113             q{
114             SELECT o.name, colid,colid2,c.text
115             FROM syscomments c
116             JOIN sysobjects o
117             ON c.id = o.id
118             WHERE o.type ='P'
119             ORDER BY o.name,
120             c.colid,
121             c.colid2
122             }
123             );
124              
125 0           foreach (@{$h}) {
  0            
126             $stuff->{procedures}->{ $_->[0] }->{text} .= $_->[3]
127 0 0         if (defined($stuff->{procedures}->{ $_->[0] }));
128             }
129              
130             ### Defaults
131             ### Rules
132             ### Bind Defaults
133             ### Bind Rules
134              
135             ### Triggers
136             # Since the 'target' of the trigger is defined in the text, we will
137             # just create them independently for now rather than associating them
138             # with a table.
139              
140 0           $h = $dbh->selectall_arrayref(
141             q{
142             SELECT o.name, colid,colid2,c.text
143             FROM syscomments c
144             JOIN sysobjects o
145             ON c.id = o.id
146             JOIN sysobjects o1
147             ON (o.id = o1.instrig OR o.id = o1.deltrig or o.id = o1.updtrig)
148             WHERE o.type ='TR'
149             ORDER BY o.name,
150             c.colid,
151             c.colid2
152             }
153             );
154 0           foreach (@{$h}) {
  0            
155 0           $stuff->{triggers}->{ $_->[0] }->{text} .= $_->[3];
156             }
157              
158             ### References
159             ### Keys
160              
161             ### Types
162             # Not sure what to do with these?
163 0           $stuff->{type_info_all} = $dbh->type_info_all;
164              
165             ### Tables
166             # According to the DBI docs, these can be
167              
168             # "TABLE"
169             # "VIEW"
170             # "SYSTEM TABLE"
171             # "GLOBAL TEMPORARY",
172             # "LOCAL TEMPORARY"
173             # "ALIAS"
174             # "SYNONYM"
175              
176 0           foreach my $table_info (@tables) {
177             next
178 0 0         unless (defined($table_info->{TABLE_TYPE}));
179              
180 0 0         if ($table_info->{TABLE_TYPE} =~ /TABLE/) {
    0          
181             my $table = $schema->add_table(
182             name => $table_info->{TABLE_NAME},
183             type => $table_info->{TABLE_TYPE},
184 0   0       ) || die $schema->error;
185              
186             # find the associated columns
187              
188             my $cols = $columns->{ $table_info->{TABLE_QUALIFIER} }
189             ->{ $table_info->{TABLE_OWNER} }->{ $table_info->{TABLE_NAME} }
190 0           ->{columns};
191              
192 0           foreach my $c (values %{$cols}) {
  0            
193             my $f = $table->add_field(
194             name => $c->{COLUMN_NAME},
195             data_type => $c->{TYPE_NAME},
196             order => $c->{ORDINAL_POSITION},
197             size => $c->{COLUMN_SIZE},
198 0   0       ) || die $table->error;
199              
200             $f->is_nullable(1)
201 0 0         if ($c->{NULLABLE} == 1);
202             }
203              
204             # add in primary key
205 0           my $h = $dbh->selectall_hashref(
206             "sp_pkeys
207             [$table_info->{TABLE_NAME}]", 'COLUMN_NAME'
208             );
209 0 0         if (scalar keys %{$h} > 1) {
  0            
210 0           my @c = map { $_->{COLUMN_NAME} }
211 0           sort { $a->{KEY_SEQ} <=> $b->{KEY_SEQ} } values %{$h};
  0            
  0            
212              
213 0 0         $table->primary_key(@c)
214             if (scalar @c);
215             }
216              
217             # add in any indexes ... how do we tell if the index has
218             # already been created as part of a primary key or other
219             # constraint?
220              
221 0 0         if (defined($stuff->{indexes}->{ $table_info->{TABLE_NAME} })) {
222 0           my $h = $dbh->selectall_hashref(
223             "sp_helpindex
224             [$table_info->{TABLE_NAME}]", 'INDEX_NAME'
225             );
226 0           foreach (values %{$h}) {
  0            
227 0           my $fields = $_->{'INDEX_KEYS'};
228 0           $fields =~ s/\s*//g;
229             my $i = $table->add_index(
230             name => $_->{INDEX_NAME},
231 0           fields => $fields,
232             );
233 0 0         if ($_->{'INDEX_DESCRIPTION'} =~ /unique/i) {
234 0           $i->type('unique');
235              
236             # we could make this a primary key if there
237             # isn't already one defined and if there
238             # aren't any nullable columns in thisindex.
239              
240 0 0         if (!defined($table->primary_key())) {
241             $table->primary_key($fields)
242 0 0         unless grep { $table->get_field($_)->is_nullable() }
  0            
243             split(/,\s*/, $fields);
244             }
245             }
246             }
247             }
248             } elsif ($table_info->{TABLE_TYPE} eq 'VIEW') {
249 0           my $view = $schema->add_view(name => $table_info->{TABLE_NAME},);
250              
251             my $cols = $columns->{ $table_info->{TABLE_QUALIFIER} }
252             ->{ $table_info->{TABLE_OWNER} }->{ $table_info->{TABLE_NAME} }
253 0           ->{columns};
254              
255             $view->fields(
256 0           map { $_->{COLUMN_NAME} }
257 0           sort { $a->{ORDINAL_POSITION} <=> $b->{ORDINAL_POSITION} } values %{$cols}
  0            
  0            
258             );
259              
260             $view->sql($stuff->{view}->{ $table_info->{TABLE_NAME} }->{text})
261 0 0         if (defined($stuff->{view}->{ $table_info->{TABLE_NAME} }->{text}));
262             }
263             }
264              
265 0           foreach my $p (values %{ $stuff->{procedures} }) {
  0            
266             my $proc = $schema->add_procedure(
267             name => $p->{name},
268             owner => $p->{PROCEDURE_OWNER},
269             comments => $p->{REMARKS},
270             sql => $p->{text},
271 0           );
272              
273             }
274              
275             ### Permissions
276             ### Groups
277             ### Users
278             ### Aliases
279             ### Logins
280 0           return 1;
281             }
282              
283             1;
284              
285             =pod
286              
287             =head1 AUTHOR
288              
289             Paul Harrington Eharringp@deshaw.comE.
290              
291             =head1 SEE ALSO
292              
293             DBI, DBD::Sybase, SQL::Translator::Schema.
294              
295             =cut