File Coverage

blib/lib/DBIx/PgLink/Adapter/MSSQL.pm
Criterion Covered Total %
statement 4 6 66.6
branch n/a
condition n/a
subroutine 2 2 100.0
pod n/a
total 6 8 75.0


line stmt bran cond sub pod time code
1             package DBIx::PgLink::Adapter::MSSQL;
2              
3             # tested on MSSQL2000 sp4
4              
5 1     1   1982 use Carp;
  1         3  
  1         75  
6 1     1   553 use Moose;
  0            
  0            
7             use MooseX::Method;
8             use Data::Dumper;
9              
10             extends 'DBIx::PgLink::Adapter::SQLServer';
11              
12              
13             # for Reconnect role
14             sub is_disconnected {
15             my ($self, $exception) = @_;
16             return
17             $exception =~ /General network error/i
18             # SQLSTATE code
19             || $self->dbh->state =~ /^.8...$/; # Class 08 - Connection Exception
20             }
21              
22              
23             # ---------------------------- data conversion
24             sub pg_bool_to_mssql_bit {
25             $_[1] = defined $_[1] ? $_[1] eq 't' ? 1 : 0 : undef; # NULL allowed
26             }
27              
28              
29             around 'expand_table_info' => sub {
30             my ($next, $self, $info) = @_;
31              
32             # bug: some system views in list
33             return 0 if $info->{TABLE_NAME} =~ /^sys/ && $info->{TABLE_TYPE} eq 'VIEW'; # skip
34             $next->($self, $info);
35             };
36              
37              
38             sub routine_info {
39             my ($self, $catalog, $schema, $routine, $type) = @_;
40              
41             if (!$catalog || $catalog eq '%') {
42             $catalog = $self->current_database;
43             }
44              
45             my $type_cond = do {
46             if (!defined $type || $type eq '%') {
47             ''
48             } elsif ($type =~ /('\w+',)*('\w+')/) {
49             "AND ROUTINE_TYPE IN ($type)"
50             } else {
51             "AND ROUTINE_TYPE IN ('" . join("','", split /,/, $type) . "')"
52             }
53             };
54              
55             my $sth = eval {
56             $self->prepare(<<END_OF_SQL);
57             SELECT
58             SPECIFIC_CATALOG,
59             SPECIFIC_SCHEMA,
60             SPECIFIC_NAME,
61             ROUTINE_CATALOG,
62             ROUTINE_SCHEMA,
63             ROUTINE_NAME,
64             ROUTINE_TYPE,
65             DATA_TYPE
66             FROM $catalog.INFORMATION_SCHEMA.ROUTINES
67             WHERE SPECIFIC_CATALOG like ?
68             AND SPECIFIC_SCHEMA like ?
69             AND SPECIFIC_NAME like ?
70             $type_cond
71             ORDER BY 1,2,3
72             END_OF_SQL
73             };
74             return undef if $@;
75             $sth->execute($catalog, $schema, $routine);
76             return $sth;
77             };
78              
79              
80             around 'routine_column_info_arrayref' => sub {
81             my ($next, $self, $info) = @_;
82              
83             if ($info->{ROUTINE_TYPE} eq 'FUNCTION'
84             && $info->{DATA_TYPE} ne 'TABLE') {
85             # scalar-valued function
86             my $ci = {
87             COLUMN_NAME => 'RESULT',
88             ORDINAL_POSITION => 1,
89             TYPE_NAME => $info->{DATA_TYPE},
90             };
91             $self->expand_column_info($ci);
92              
93             return [ $ci ];
94              
95             } else { #
96             # table-valued function has INFORMATION_SCHEMA.ROUTINE_COLUMNS
97             # procedure resultset handled by parent SQLServer class
98             return $next->($self, $info);
99             }
100             };
101              
102              
103             around 'expand_routine_info' => sub {
104             my ($next, $self, $info) = @_;
105              
106             # skip Visual Studio VCS procedures
107             return 0 if $info->{ROUTINE_NAME} =~ /^dt_/ && $info->{ROUTINE_TYPE} eq 'PROCEDURE'; # skip
108             $next->($self, $info);
109             };
110              
111              
112             around 'expand_column_info' => sub {
113             my ($next, $self, $column) = @_;
114              
115             # convert INFORMATION_SCHEMA.xxx to DBI::column_info
116              
117             if (!exists $column->{COLUMN_SIZE}) {
118             $column->{COLUMN_SIZE} = $column->{CHARACTER_MAXIMUM_LENGTH}
119             || $column->{NUMERIC_PRECISION};
120             $column->{DECIMAL_DIGITS} = $column->{NUMERIC_SCALE};
121             }
122              
123             $next->($self, $column);
124             };
125              
126             1;