File Coverage

blib/lib/SQL/DB/Schema.pm
Criterion Covered Total %
statement 90 100 90.0
branch 9 12 75.0
condition n/a
subroutine 20 23 86.9
pod 5 5 100.0
total 124 140 88.5


line stmt bran cond sub pod time code
1             package SQL::DB::Schema;
2 5     5   15383 use strict;
  5         7  
  5         180  
3 5     5   19 use warnings;
  5         7  
  5         107  
4 5     5   520 use Moo;
  5         10475  
  5         29  
5 5     5   2626 use Log::Any qw/$log/;
  5         1411  
  5         31  
6 5     5   331 use Carp qw/confess/;
  5         7  
  5         307  
7 5     5   1942 use SQL::DB::Expr qw/_bval/;
  5         27  
  5         40  
8 5     5   1418 use Sub::Install qw/install_sub/;
  5         8  
  5         34  
9              
10             our $VERSION = '0.971.2';
11              
12             # Ordinals for DBI->column_info() results
13             use constant {
14 5         1155 TABLE_CAT => 0,
15             TABLE_SCHEM => 1,
16             TABLE_NAME => 2,
17             COLUMN_NAME => 3,
18             DATA_TYPE => 4,
19             TYPE_NAME => 5,
20             COLUMN_SIZE => 6,
21             BUFFER_LENGTH => 7,
22             DECIMAL_DIGITS => 8,
23             NUM_PREC_RADIX => 9,
24             NULLABLE => 10,
25             REMARKS => 11,
26             COLUMN_DEF => 12,
27             SQL_DATA_TYPE => 13,
28             SQL_DATETIME_SUB => 14,
29             CHAR_OCTET_LENGTH => 15,
30             ORDINAL_POSITION => 16,
31             IS_NULLABLE => 17,
32 5     5   610 };
  5         10  
33              
34             # Object definition
35              
36             has 'name' => (
37             is => 'ro',
38             required => 1,
39             );
40              
41             has 'package_root' => (
42             is => 'ro',
43             required => 1,
44             );
45              
46             has '_tables' => (
47             is => 'ro',
48             init_arg => undef,
49             default => sub { {} },
50             );
51              
52 5     5   27 sub _getglob { no strict 'refs'; \*{ $_[0] } }
  5     0   6  
  5         1910  
  0         0  
  0         0  
53              
54             around BUILDARGS => sub {
55             my $orig = shift;
56             my $class = shift;
57             my %args = @_;
58              
59             ( $args{package_root} = $args{name} ) =~ tr/a-zA-Z0-9/_/cs;
60             $args{package_root} = __PACKAGE__ . '::' . $args{package_root};
61              
62             return $class->$orig(%args);
63             };
64              
65             sub define {
66 3     3 1 614 my $self = shift;
67 3         8 my $data = shift;
68              
69 3         16 my $package_root = $self->package_root;
70 3         15 my $tables = $self->_tables;
71              
72 3         12 foreach my $colref (@$data) {
73 7         216 my $table = $colref->[TABLE_NAME];
74 7         22 my $srow = $package_root . '::Srow::' . $table;
75 7         15 my $urow = $package_root . '::Urow::' . $table;
76              
77 7 100       25 if ( !exists $tables->{$table} ) {
78              
79 3     3   29 eval "package $srow; use Moo; extends 'SQL::DB::Expr'";
  3         6  
  3         38  
  3         632  
80 3     3   20 eval "package $urow; use Moo; extends 'SQL::DB::Expr'";
  3         5  
  3         12  
  3         742  
81              
82             # @{ *{ _getglob( $srow . '::ISA' ) }{ARRAY} } = ('SQL::DB::Expr');
83             # @{ *{ _getglob( $urow . '::ISA' ) }{ARRAY} } = ('SQL::DB::Expr');
84              
85             install_sub(
86             {
87             code => sub {
88 0     0   0 my $table_expr = shift;
89 0         0 return $table_expr . '.*';
90             },
91 3         427 into => $urow,
92             as => '_columns',
93             }
94             );
95             install_sub(
96             {
97             code => sub {
98 0     0   0 my $table_expr = shift;
99 0         0 return SQL::DB::Expr->new(
100             _txt => [ $table_expr->_alias . '.*' ] );
101             },
102 3         322 into => $srow,
103             as => '_columns',
104             }
105             );
106             }
107 7         149 $tables->{$table}++;
108              
109 7         22 my $col = lc $colref->[COLUMN_NAME];
110              
111 7 50       27 if ( $col eq 'new' ) {
112 0         0 confess "Column name 'new' (table/view '$table') clashes with "
113             . __PACKAGE__ . '!!!';
114             }
115              
116 5     5   2980 use bytes;
  5         37  
  5         31  
117 7         17 my $type = lc $colref->[TYPE_NAME];
118              
119             install_sub(
120             {
121             code => sub {
122 40     40   1700 my $table_expr = shift;
123 40         1155 SQL::DB::Expr->new(
124             _txt => [ $table_expr->_alias . '.' . $col ],
125             _type => $type,
126             );
127             },
128 7         60 into => $srow,
129             as => $col,
130             }
131             );
132              
133             install_sub(
134             {
135             code => sub {
136 8     8   1290 my $table_expr = shift;
137              
138 8 50       33 if (@_) {
139 0         0 my $val = shift;
140 0         0 return SQL::DB::Expr->new(
141             _txt => [ $col . ' = ', _bval( $val, $type ) ],
142             _type => $type,
143             );
144             }
145              
146 8         188 return SQL::DB::Expr->new(
147             _txt => [$col],
148             _type => $type,
149             );
150             },
151 7         412 into => $urow,
152             as => $col,
153             }
154             );
155             }
156              
157 3         260 return;
158             }
159              
160             sub not_known {
161 6     6 1 1041 my $self = shift;
162 6         27 my $tables = $self->_tables;
163 6         14 return grep { !exists $tables->{$_} } @_;
  6         47  
164             }
165              
166             sub irows {
167 3     3 1 14 my $self = shift;
168              
169 3         5 my @ret;
170 3         9 foreach my $name (@_) {
171 3 100       29 if ( !exists $self->_tables->{$name} ) {
172 1         14 die "Table not defined in schema: $name";
173             }
174 2     2   17 push( @ret, sub { $name . '(' . join( ',', @_ ) . ')' } );
  2         526  
175             }
176 2         9 return @ret;
177             }
178              
179             sub srows {
180 7     7 1 15 my $self = shift;
181              
182 7         13 my @ret;
183 7         24 foreach my $name (@_) {
184 7 100       51 if ( !exists $self->_tables->{$name} ) {
185 2         28 die "Table not defined in schema: $name";
186             }
187 5         31 my $class = $self->package_root . '::Srow::' . $name;
188 5         180 my $srow = $class->new( _txt => [$name], _alias => $name );
189 5         174 push( @ret, $srow );
190             }
191 5         28 return @ret;
192             }
193              
194             sub urows {
195 4     4 1 8 my $self = shift;
196              
197 4         7 my @ret;
198 4         14 foreach my $name (@_) {
199 4 50       29 if ( !exists $self->_tables->{$name} ) {
200 0         0 die "Table not defined in schema: $name";
201             }
202 4         24 my $class = $self->package_root . '::Urow::' . $name;
203 4         161 my $urow = $class->new( _txt => [$name] );
204 4         26 push( @ret, $urow );
205             }
206 4         15 return @ret;
207             }
208              
209             1;
210              
211             # vim: set tabstop=4 expandtab: