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