| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
##### |
|
2
|
|
|
|
|
|
|
# |
|
3
|
|
|
|
|
|
|
# $Id: RDB.pm,v 1.1 2003/04/18 00:33:17 trostler Exp $ |
|
4
|
|
|
|
|
|
|
# |
|
5
|
|
|
|
|
|
|
# COPYRIGHT AND LICENSE |
|
6
|
|
|
|
|
|
|
# Copyright (c) 2001, 2003, Juniper Networks, Inc. All rights reserved. |
|
7
|
|
|
|
|
|
|
# Redistribution and use in source and binary forms, with or without |
|
8
|
|
|
|
|
|
|
# modification, are permitted provided that the following conditions are |
|
9
|
|
|
|
|
|
|
# met: |
|
10
|
|
|
|
|
|
|
# 1. Redistributions of source code must retain the above |
|
11
|
|
|
|
|
|
|
# copyright notice, this list of conditions and the following |
|
12
|
|
|
|
|
|
|
# disclaimer. |
|
13
|
|
|
|
|
|
|
# 2. Redistributions in binary form must reproduce the above |
|
14
|
|
|
|
|
|
|
# copyright notice, this list of conditions and the following disclaimer |
|
15
|
|
|
|
|
|
|
# in the documentation and/or other materials provided with the |
|
16
|
|
|
|
|
|
|
# distribution. |
|
17
|
|
|
|
|
|
|
# 3. The name of the copyright owner may not be used to |
|
18
|
|
|
|
|
|
|
# endorse or promote products derived from this software without specific |
|
19
|
|
|
|
|
|
|
# prior written permission. |
|
20
|
|
|
|
|
|
|
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
|
21
|
|
|
|
|
|
|
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
|
22
|
|
|
|
|
|
|
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
|
23
|
|
|
|
|
|
|
# DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, |
|
24
|
|
|
|
|
|
|
# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
|
25
|
|
|
|
|
|
|
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
|
26
|
|
|
|
|
|
|
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
|
27
|
|
|
|
|
|
|
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, |
|
28
|
|
|
|
|
|
|
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING |
|
29
|
|
|
|
|
|
|
# IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|
30
|
|
|
|
|
|
|
# POSSIBILITY OF SUCH DAMAGE. |
|
31
|
|
|
|
|
|
|
# |
|
32
|
|
|
|
|
|
|
##### |
|
33
|
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
package XML::RDB; |
|
35
|
|
|
|
|
|
|
|
|
36
|
1
|
|
|
1
|
|
52549
|
use XML::DOM; |
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
use XML::RDB::MakeTables; |
|
38
|
|
|
|
|
|
|
use XML::RDB::PopulateTables; |
|
39
|
|
|
|
|
|
|
use XML::RDB::UnpopulateTables; |
|
40
|
|
|
|
|
|
|
use XML::RDB::UnpopulateSchema; |
|
41
|
|
|
|
|
|
|
use strict; |
|
42
|
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
##### |
|
44
|
|
|
|
|
|
|
# |
|
45
|
|
|
|
|
|
|
# Copyright (c) 2001-2003 Juniper Networks, Inc. |
|
46
|
|
|
|
|
|
|
# All rights reserved. |
|
47
|
|
|
|
|
|
|
# |
|
48
|
|
|
|
|
|
|
# Set of common routines & constants |
|
49
|
|
|
|
|
|
|
# |
|
50
|
|
|
|
|
|
|
##### |
|
51
|
|
|
|
|
|
|
BEGIN { |
|
52
|
|
|
|
|
|
|
use Exporter (); |
|
53
|
|
|
|
|
|
|
use vars qw($VERSION); # @ISA @EXPORT); |
|
54
|
|
|
|
|
|
|
$VERSION = "1.3"; |
|
55
|
|
|
|
|
|
|
# @ISA = qw(Exporter); |
|
56
|
|
|
|
|
|
|
# @EXPORT = qw( |
|
57
|
|
|
|
|
|
|
# ); |
|
58
|
|
|
|
|
|
|
} |
|
59
|
|
|
|
|
|
|
|
|
60
|
|
|
|
|
|
|
sub new { |
|
61
|
|
|
|
|
|
|
my ($class, %arg) = @_; |
|
62
|
|
|
|
|
|
|
my $config; |
|
63
|
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
if ($arg{config_file}) { |
|
65
|
|
|
|
|
|
|
open(C, "$arg{config_file}") || die "$!"; |
|
66
|
|
|
|
|
|
|
while() { |
|
67
|
|
|
|
|
|
|
next if (/^(#|$)/); |
|
68
|
|
|
|
|
|
|
next unless (my ($key, $value) = $_ =~ /^([A-Z_]+)=(.+)/); |
|
69
|
|
|
|
|
|
|
chomp $value; |
|
70
|
|
|
|
|
|
|
$key =~ s/\s//g; |
|
71
|
|
|
|
|
|
|
$value =~ s/\s//g; |
|
72
|
|
|
|
|
|
|
$config->{$key} = $value if ($key); |
|
73
|
|
|
|
|
|
|
} |
|
74
|
|
|
|
|
|
|
close(C); |
|
75
|
|
|
|
|
|
|
} |
|
76
|
|
|
|
|
|
|
elsif ( scalar(keys(%arg)) > 0 ) { |
|
77
|
|
|
|
|
|
|
$config = \%arg; |
|
78
|
|
|
|
|
|
|
} |
|
79
|
|
|
|
|
|
|
else { |
|
80
|
|
|
|
|
|
|
warn "$class requires a DSN for DBI->connect\n"; |
|
81
|
|
|
|
|
|
|
return undef; |
|
82
|
|
|
|
|
|
|
} |
|
83
|
|
|
|
|
|
|
|
|
84
|
|
|
|
|
|
|
# setup connection |
|
85
|
|
|
|
|
|
|
my $dbh = DBI->connect( |
|
86
|
|
|
|
|
|
|
$config->{DSN}, |
|
87
|
|
|
|
|
|
|
($config->{DB_USERNAME} || ''), |
|
88
|
|
|
|
|
|
|
($config->{DB_PASSWORD} || ''), |
|
89
|
|
|
|
|
|
|
{ RaiseError => $config->{DB_RAISEERROR} || 0, |
|
90
|
|
|
|
|
|
|
PrintError => $config->{DB_PRINTERROR} || 0, |
|
91
|
|
|
|
|
|
|
# NOTE : |
|
92
|
|
|
|
|
|
|
# autocommit needs to be on for this app in its current state. |
|
93
|
|
|
|
|
|
|
# 1. the method of inserts, and updates |
|
94
|
|
|
|
|
|
|
# 2. DBIx::Sequence |
|
95
|
|
|
|
|
|
|
AutoCommit => 1 } |
|
96
|
|
|
|
|
|
|
) or (( warn $!) and ( return undef)); |
|
97
|
|
|
|
|
|
|
|
|
98
|
|
|
|
|
|
|
if ( $config->{DSN} =~ /dbi:sqlite/i) { |
|
99
|
|
|
|
|
|
|
warn("SQLite detected...setting SQLite PRAGMA: synchronus = OFF; locking_mode = EXCLUSIVE\n") |
|
100
|
|
|
|
|
|
|
if ($config->{DB_PRINTERR}); |
|
101
|
|
|
|
|
|
|
$dbh->do('PRAGMA synchronous = OFF') || warn $dbh->errstr; |
|
102
|
|
|
|
|
|
|
$dbh->do('PRAGMA locking_mode = EXCLUSIVE') || warn $dbh->errstr; |
|
103
|
|
|
|
|
|
|
} |
|
104
|
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
$DBIx::Recordset::Debug = $config->{DBIX_DEBUG} || 0; |
|
106
|
|
|
|
|
|
|
$DBIx::Recordset::FetchsizeWarn = $config->{DBIX_FETCHSIZEWARN} || 0; |
|
107
|
|
|
|
|
|
|
|
|
108
|
|
|
|
|
|
|
my $self = bless { |
|
109
|
|
|
|
|
|
|
DSN => $config->{DSN}, |
|
110
|
|
|
|
|
|
|
DB_CATALOG => (defined $config->{DB_CATALOG}) |
|
111
|
|
|
|
|
|
|
? $config->{DB_CATALOG} |
|
112
|
|
|
|
|
|
|
: undef, |
|
113
|
|
|
|
|
|
|
DBH => $dbh, |
|
114
|
|
|
|
|
|
|
TEXT_COLUMN => ($config->{TEXT_WIDTH}) |
|
115
|
|
|
|
|
|
|
? 'varchar('. $config->{TEXT_WIDTH} .')' |
|
116
|
|
|
|
|
|
|
: 'varchar(50)', |
|
117
|
|
|
|
|
|
|
TEXT_WIDTH => $config->{TEXT_WIDTH} || 50, |
|
118
|
|
|
|
|
|
|
TAB => ($config->{TAB}) ? ' ' x $config->{TAB} : ' ', |
|
119
|
|
|
|
|
|
|
PK_NAME => $config->{PK_NAME} || 'id', |
|
120
|
|
|
|
|
|
|
FK_NAME => $config->{FK_NAME} || 'fk', |
|
121
|
|
|
|
|
|
|
TABLE_PREFIX => $config->{TABLE_PREFIX} || 'gen', |
|
122
|
|
|
|
|
|
|
DB_USERNAME => $config->{DB_USERNAME} || '', |
|
123
|
|
|
|
|
|
|
DB_PASSWORD => $config->{DB_PASSWORD} || '', |
|
124
|
|
|
|
|
|
|
_HEADERS => (defined $config->{SQL_HEADERS}) |
|
125
|
|
|
|
|
|
|
? $config->{SQL_HEADERS} : 1, |
|
126
|
|
|
|
|
|
|
_SELECTS => (defined $config->{SQL_SELECTS}) |
|
127
|
|
|
|
|
|
|
? $config->{SQL_SELECTS} : 1, |
|
128
|
|
|
|
|
|
|
_SQLITE => ($config->{DSN} =~ /dbi:sqlite/i) ? 1 : 0, |
|
129
|
|
|
|
|
|
|
}, $class; |
|
130
|
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
$self->{REAL_ELEMENT_NAME_TABLE} = $self->mtn('element_names'); |
|
132
|
|
|
|
|
|
|
$self->{LINK_TABLE_NAMES_TABLE} = $self->mtn('link_tables'); |
|
133
|
|
|
|
|
|
|
$self->{ROOT_TABLE_N_PK_TABLE} = $self->mtn('root_n_pk'); |
|
134
|
|
|
|
|
|
|
return $self; |
|
135
|
|
|
|
|
|
|
} |
|
136
|
|
|
|
|
|
|
|
|
137
|
|
|
|
|
|
|
sub done { my $self = shift; $self->DESTROY; return $self}; |
|
138
|
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
sub DESTROY { |
|
140
|
|
|
|
|
|
|
my $self = shift; |
|
141
|
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
# NOTE : Recordset specific |
|
143
|
|
|
|
|
|
|
# Undef takes the name of a typglob and will destroy the array, the |
|
144
|
|
|
|
|
|
|
# hash, and the object. All unwritten data is written to the db. |
|
145
|
|
|
|
|
|
|
# All db connections are closed and all memory is freed. |
|
146
|
|
|
|
|
|
|
# DBIx::Recordset::Undef ($name) |
|
147
|
|
|
|
|
|
|
# DBIx::Recordset->Flush(); |
|
148
|
|
|
|
|
|
|
$self->{DBH}->disconnect() if ($self->{DBH}); |
|
149
|
|
|
|
|
|
|
$self->{_DOC}->dispose if ($self->{_DOC}); |
|
150
|
|
|
|
|
|
|
} |
|
151
|
|
|
|
|
|
|
|
|
152
|
|
|
|
|
|
|
sub drop_tables { |
|
153
|
|
|
|
|
|
|
my $self = shift; |
|
154
|
|
|
|
|
|
|
return warn "Please add DB_CATALOG for the dsn supplied for dropping tables.\n" |
|
155
|
|
|
|
|
|
|
unless ( defined $self->{DB_CATALOG} ); |
|
156
|
|
|
|
|
|
|
my $dbh = $self->{DBH}; |
|
157
|
|
|
|
|
|
|
my ($driver, $dbname) = $self->{DSN} =~ /dbi:(\w+):\w+=(\w+)/i; |
|
158
|
|
|
|
|
|
|
my $sth; |
|
159
|
|
|
|
|
|
|
|
|
160
|
|
|
|
|
|
|
if ( $self->{DB_CATALOG} == 0 ) { |
|
161
|
|
|
|
|
|
|
$sth = $dbh->table_info(undef, $dbname, undef, undef); |
|
162
|
|
|
|
|
|
|
} |
|
163
|
|
|
|
|
|
|
elsif ( $self->{DB_CATALOG} == 1 ) { |
|
164
|
|
|
|
|
|
|
$sth = $dbh->table_info($dbname, 'public', undef, undef); |
|
165
|
|
|
|
|
|
|
} |
|
166
|
|
|
|
|
|
|
else { |
|
167
|
|
|
|
|
|
|
return warn 'Please fix DB_CATALOG to boolean (1|0) in your dsn config file.' |
|
168
|
|
|
|
|
|
|
.'examples : Postgres 1, SQLite 0, Mysql 0' ."\n"; |
|
169
|
|
|
|
|
|
|
} |
|
170
|
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
my $d_tables; |
|
172
|
|
|
|
|
|
|
my $regex = '^'. $self->{TABLE_PREFIX} .'_\w+'; |
|
173
|
|
|
|
|
|
|
for my $rel (@{$sth->fetchall_arrayref({})}) { |
|
174
|
|
|
|
|
|
|
if ($rel->{TABLE_NAME} =~ /$regex/o) { |
|
175
|
|
|
|
|
|
|
push(@{ $d_tables }, $rel->{TABLE_NAME}); |
|
176
|
|
|
|
|
|
|
$dbh->do('DROP TABLE '. $rel->{TABLE_NAME}) |
|
177
|
|
|
|
|
|
|
} |
|
178
|
|
|
|
|
|
|
} |
|
179
|
|
|
|
|
|
|
return $d_tables; |
|
180
|
|
|
|
|
|
|
} |
|
181
|
|
|
|
|
|
|
|
|
182
|
|
|
|
|
|
|
sub create_tables { |
|
183
|
|
|
|
|
|
|
my ($self, $file) = @_; |
|
184
|
|
|
|
|
|
|
my $statement; |
|
185
|
|
|
|
|
|
|
|
|
186
|
|
|
|
|
|
|
open (F, $file) || die $!; |
|
187
|
|
|
|
|
|
|
while () { |
|
188
|
|
|
|
|
|
|
next if (/^(-|$)/); chomp; |
|
189
|
|
|
|
|
|
|
|
|
190
|
|
|
|
|
|
|
if (s/;$//) { |
|
191
|
|
|
|
|
|
|
$self->{DBH}->do($statement . $_) || die $self->{DBH}->errstr; |
|
192
|
|
|
|
|
|
|
$statement = ''; |
|
193
|
|
|
|
|
|
|
} |
|
194
|
|
|
|
|
|
|
else { |
|
195
|
|
|
|
|
|
|
$statement .= $_; |
|
196
|
|
|
|
|
|
|
} |
|
197
|
|
|
|
|
|
|
} |
|
198
|
|
|
|
|
|
|
close(F); |
|
199
|
|
|
|
|
|
|
return $self; |
|
200
|
|
|
|
|
|
|
} |
|
201
|
|
|
|
|
|
|
|
|
202
|
|
|
|
|
|
|
sub _get_xml { |
|
203
|
|
|
|
|
|
|
my $self = shift; |
|
204
|
|
|
|
|
|
|
my $xmlfile = shift; |
|
205
|
|
|
|
|
|
|
|
|
206
|
|
|
|
|
|
|
if (($self->{_XMLFILE}) and |
|
207
|
|
|
|
|
|
|
((!$xmlfile) or ($self->{_XMLFILE} eq $xmlfile))) { |
|
208
|
|
|
|
|
|
|
undef; |
|
209
|
|
|
|
|
|
|
} |
|
210
|
|
|
|
|
|
|
elsif ($self->{DOC}) { |
|
211
|
|
|
|
|
|
|
$self->{_DOC}->dispose; |
|
212
|
|
|
|
|
|
|
$self->{_XMLFILE} = $xmlfile; |
|
213
|
|
|
|
|
|
|
$self->{_DOC} = $self->{_XMLPARSER}->parsefile($xmlfile); |
|
214
|
|
|
|
|
|
|
$self->{_HEAD} = $self->{_DOC}->getDocumentElement; |
|
215
|
|
|
|
|
|
|
} |
|
216
|
|
|
|
|
|
|
else { |
|
217
|
|
|
|
|
|
|
$self->{_XMLFILE} = $xmlfile; |
|
218
|
|
|
|
|
|
|
$self->{_XMLPARSER} = new XML::DOM::Parser; |
|
219
|
|
|
|
|
|
|
$self->{_DOC} = $self->{_XMLPARSER}->parsefile($xmlfile) || die "$!"; |
|
220
|
|
|
|
|
|
|
$self->{_HEAD} = $self->{_DOC}->getDocumentElement; |
|
221
|
|
|
|
|
|
|
} |
|
222
|
|
|
|
|
|
|
return ($self->{_DOC},$self->{_HEAD}); |
|
223
|
|
|
|
|
|
|
} |
|
224
|
|
|
|
|
|
|
|
|
225
|
|
|
|
|
|
|
sub make_tables { |
|
226
|
|
|
|
|
|
|
my ($self, $xmlfile, $outfile) = @_; |
|
227
|
|
|
|
|
|
|
my ($doc, $head) = $self->_get_xml($xmlfile); |
|
228
|
|
|
|
|
|
|
my $mt = new XML::RDB::MakeTables($self, $doc, $head, $outfile); |
|
229
|
|
|
|
|
|
|
$mt->go; |
|
230
|
|
|
|
|
|
|
} |
|
231
|
|
|
|
|
|
|
|
|
232
|
|
|
|
|
|
|
sub populate_tables { |
|
233
|
|
|
|
|
|
|
my ($self, $xmlfile) = @_; |
|
234
|
|
|
|
|
|
|
my ($doc, $head) = $self->_get_xml($xmlfile); |
|
235
|
|
|
|
|
|
|
my $pt = new XML::RDB::PopulateTables($self, $doc, $head); |
|
236
|
|
|
|
|
|
|
$pt->go; |
|
237
|
|
|
|
|
|
|
} |
|
238
|
|
|
|
|
|
|
|
|
239
|
|
|
|
|
|
|
sub unpopulate_tables { |
|
240
|
|
|
|
|
|
|
my $self = shift; |
|
241
|
|
|
|
|
|
|
my $outfile = shift; |
|
242
|
|
|
|
|
|
|
my $root_n_pk = $self->get_root_n_pk_db(); |
|
243
|
|
|
|
|
|
|
my $ut = new XML::RDB::UnpopulateTables($self,$outfile); |
|
244
|
|
|
|
|
|
|
$ut->go($root_n_pk->{root}, $root_n_pk->{pk}); |
|
245
|
|
|
|
|
|
|
} |
|
246
|
|
|
|
|
|
|
|
|
247
|
|
|
|
|
|
|
sub unpopulate_schema { |
|
248
|
|
|
|
|
|
|
my $us = new XML::RDB::UnpopulateSchema(@_); |
|
249
|
|
|
|
|
|
|
$us->go; |
|
250
|
|
|
|
|
|
|
} |
|
251
|
|
|
|
|
|
|
|
|
252
|
|
|
|
|
|
|
# |
|
253
|
|
|
|
|
|
|
# Blow thru all nodes & find 1:N relationships between them |
|
254
|
|
|
|
|
|
|
# Need to pass the root of yer XML::DOM tree |
|
255
|
|
|
|
|
|
|
# Quite pleasant really |
|
256
|
|
|
|
|
|
|
# Basically just count the number of duplicate elements under |
|
257
|
|
|
|
|
|
|
# this one - if > 1 then 1:N relationship |
|
258
|
|
|
|
|
|
|
# |
|
259
|
|
|
|
|
|
|
sub find_one_to_n_relationships { |
|
260
|
|
|
|
|
|
|
# NOTE : Replaced the recursive loop with goto's with a @stack |
|
261
|
|
|
|
|
|
|
my($self, $head) = @_; |
|
262
|
|
|
|
|
|
|
my (@stack,%saw,$one_to_n); |
|
263
|
|
|
|
|
|
|
TOP_REL: |
|
264
|
|
|
|
|
|
|
my $nodes = [ $head->getChildNodes ]; |
|
265
|
|
|
|
|
|
|
%saw = (); |
|
266
|
|
|
|
|
|
|
|
|
267
|
|
|
|
|
|
|
# Count duplicates |
|
268
|
|
|
|
|
|
|
grep($saw{$_->getNodeName}++, @{$nodes}); |
|
269
|
|
|
|
|
|
|
foreach (keys %saw) { |
|
270
|
|
|
|
|
|
|
next if /#text/; |
|
271
|
|
|
|
|
|
|
next if /#comment/; |
|
272
|
|
|
|
|
|
|
next if ($one_to_n->{$head->getNodeName}{$_}); |
|
273
|
|
|
|
|
|
|
if ($saw{$_} > 1) { |
|
274
|
|
|
|
|
|
|
$one_to_n->{$head->getNodeName}{$_} = 1; |
|
275
|
|
|
|
|
|
|
} |
|
276
|
|
|
|
|
|
|
} |
|
277
|
|
|
|
|
|
|
|
|
278
|
|
|
|
|
|
|
TOPLESS_REL: |
|
279
|
|
|
|
|
|
|
# And recurse on down the road |
|
280
|
|
|
|
|
|
|
while (scalar(@{$nodes})) { |
|
281
|
|
|
|
|
|
|
my $sub_node = shift(@{$nodes}); |
|
282
|
|
|
|
|
|
|
next if ($sub_node->getNodeType == XML::DOM::TEXT_NODE); |
|
283
|
|
|
|
|
|
|
push(@stack, $nodes); |
|
284
|
|
|
|
|
|
|
$head = $sub_node; |
|
285
|
|
|
|
|
|
|
goto TOP_REL; |
|
286
|
|
|
|
|
|
|
} |
|
287
|
|
|
|
|
|
|
|
|
288
|
|
|
|
|
|
|
if (scalar(@stack) > 0) { |
|
289
|
|
|
|
|
|
|
$nodes = pop(@stack); |
|
290
|
|
|
|
|
|
|
goto TOPLESS_REL; |
|
291
|
|
|
|
|
|
|
} |
|
292
|
|
|
|
|
|
|
|
|
293
|
|
|
|
|
|
|
# Done is Done |
|
294
|
|
|
|
|
|
|
return $one_to_n; |
|
295
|
|
|
|
|
|
|
} |
|
296
|
|
|
|
|
|
|
|
|
297
|
|
|
|
|
|
|
# |
|
298
|
|
|
|
|
|
|
# Helper function to dump the 'one_to_n' datastructure out |
|
299
|
|
|
|
|
|
|
# |
|
300
|
|
|
|
|
|
|
sub dump_otn { |
|
301
|
|
|
|
|
|
|
my $self = shift; |
|
302
|
|
|
|
|
|
|
my($otn, $char) = @_; |
|
303
|
|
|
|
|
|
|
my $ret; |
|
304
|
|
|
|
|
|
|
|
|
305
|
|
|
|
|
|
|
foreach my $one (keys %$otn) { |
|
306
|
|
|
|
|
|
|
foreach my $many (keys %{$otn->{$one}}) { |
|
307
|
|
|
|
|
|
|
$ret .= "${char}\t$one -> $many\n"; |
|
308
|
|
|
|
|
|
|
} |
|
309
|
|
|
|
|
|
|
} |
|
310
|
|
|
|
|
|
|
return $ret; |
|
311
|
|
|
|
|
|
|
} |
|
312
|
|
|
|
|
|
|
|
|
313
|
|
|
|
|
|
|
# |
|
314
|
|
|
|
|
|
|
# 'mtn' = 'Make Table Name' - cleans up text so it's a valid |
|
315
|
|
|
|
|
|
|
# DB table name & adds TABLE_PREFIX |
|
316
|
|
|
|
|
|
|
# |
|
317
|
|
|
|
|
|
|
sub mtn { |
|
318
|
|
|
|
|
|
|
my($self, $base, $out) = @_; |
|
319
|
|
|
|
|
|
|
($out = $self->{TABLE_PREFIX} . "_$base") =~ y/#:\.-/_____/; |
|
320
|
|
|
|
|
|
|
lc $out; |
|
321
|
|
|
|
|
|
|
} |
|
322
|
|
|
|
|
|
|
|
|
323
|
|
|
|
|
|
|
# Normalize column/table names - No ':' or '-' & all lower case |
|
324
|
|
|
|
|
|
|
sub normalize { |
|
325
|
|
|
|
|
|
|
my($in,$out) = shift; |
|
326
|
|
|
|
|
|
|
|
|
327
|
|
|
|
|
|
|
# Get rid of funny stuff |
|
328
|
|
|
|
|
|
|
# ($out = $in) =~ s/[#:\.-]/_/go; |
|
329
|
|
|
|
|
|
|
($out = $in) =~ y/#:\.-/_____/; |
|
330
|
|
|
|
|
|
|
lc $out; |
|
331
|
|
|
|
|
|
|
} |
|
332
|
|
|
|
|
|
|
|
|
333
|
|
|
|
|
|
|
# |
|
334
|
|
|
|
|
|
|
# Pulls out root_n_pk data from the DB itself |
|
335
|
|
|
|
|
|
|
# |
|
336
|
|
|
|
|
|
|
sub get_root_n_pk_db { |
|
337
|
|
|
|
|
|
|
my $self = shift; |
|
338
|
|
|
|
|
|
|
my $rt_n_pk; |
|
339
|
|
|
|
|
|
|
|
|
340
|
|
|
|
|
|
|
if ($self->{_SQLITE}) { |
|
341
|
|
|
|
|
|
|
my $sth = $self->{DBH}->prepare('select * from '. $self->{ROOT_TABLE_N_PK_TABLE}); |
|
342
|
|
|
|
|
|
|
$sth->execute(); |
|
343
|
|
|
|
|
|
|
my $row = $sth->fetch(); |
|
344
|
|
|
|
|
|
|
$rt_n_pk = { root => $row->[1], pk => $row->[0] } |
|
345
|
|
|
|
|
|
|
if ($row); |
|
346
|
|
|
|
|
|
|
} |
|
347
|
|
|
|
|
|
|
else { |
|
348
|
|
|
|
|
|
|
use vars qw(*root_n_pk); |
|
349
|
|
|
|
|
|
|
*root_n_pk = DBIx::Recordset->Search({'!DataSource' => $self->{DBH}, |
|
350
|
|
|
|
|
|
|
'!Table' => $self->{ROOT_TABLE_N_PK_TABLE}}); |
|
351
|
|
|
|
|
|
|
my $root; |
|
352
|
|
|
|
|
|
|
$root = $root_n_pk[0] if (@root_n_pk); |
|
353
|
|
|
|
|
|
|
$rt_n_pk = { root => $root->{root}, pk => $root->{pk} } if ($root); |
|
354
|
|
|
|
|
|
|
DBIx::Recordset::Undef ('*root_n_pk'); |
|
355
|
|
|
|
|
|
|
} |
|
356
|
|
|
|
|
|
|
return $rt_n_pk; |
|
357
|
|
|
|
|
|
|
} |
|
358
|
|
|
|
|
|
|
|
|
359
|
|
|
|
|
|
|
# |
|
360
|
|
|
|
|
|
|
# Pulls out one_to_n data structures from the DB itself |
|
361
|
|
|
|
|
|
|
# |
|
362
|
|
|
|
|
|
|
sub get_one_to_n_db { |
|
363
|
|
|
|
|
|
|
my $self = shift; |
|
364
|
|
|
|
|
|
|
my %one_to_n; |
|
365
|
|
|
|
|
|
|
|
|
366
|
|
|
|
|
|
|
if ($self->{_SQLITE}) { |
|
367
|
|
|
|
|
|
|
my $sth = $self->{DBH}->prepare('select * from '. $self->{LINK_TABLE_NAMES_TABLE}); |
|
368
|
|
|
|
|
|
|
$sth->execute(); |
|
369
|
|
|
|
|
|
|
while (my $row = $sth->fetch()) { |
|
370
|
|
|
|
|
|
|
$one_to_n{$row->[0]}{$row->[1]} = 1; |
|
371
|
|
|
|
|
|
|
} |
|
372
|
|
|
|
|
|
|
} |
|
373
|
|
|
|
|
|
|
else { |
|
374
|
|
|
|
|
|
|
use vars qw(*link_tables); |
|
375
|
|
|
|
|
|
|
*link_tables = DBIx::Recordset->Search({'!DataSource' => $self->{DBH}, |
|
376
|
|
|
|
|
|
|
'!Table' => $self->{LINK_TABLE_NAMES_TABLE}}); |
|
377
|
|
|
|
|
|
|
foreach my $links (@link_tables) { |
|
378
|
|
|
|
|
|
|
$one_to_n{$links->{one_table}}{$links->{many_table}} = 1; |
|
379
|
|
|
|
|
|
|
} |
|
380
|
|
|
|
|
|
|
# *link_tables->Flush(); |
|
381
|
|
|
|
|
|
|
DBIx::Recordset::Undef ('*link_tables'); |
|
382
|
|
|
|
|
|
|
} |
|
383
|
|
|
|
|
|
|
return \%one_to_n; |
|
384
|
|
|
|
|
|
|
} |
|
385
|
|
|
|
|
|
|
|
|
386
|
|
|
|
|
|
|
sub get_real_element_names_db { |
|
387
|
|
|
|
|
|
|
my $self = shift; |
|
388
|
|
|
|
|
|
|
my $names; |
|
389
|
|
|
|
|
|
|
|
|
390
|
|
|
|
|
|
|
if ($self->{_SQLITE}) { |
|
391
|
|
|
|
|
|
|
my $sth = $self->{DBH}->prepare('select * from '. $self->{REAL_ELEMENT_NAME_TABLE}); |
|
392
|
|
|
|
|
|
|
$sth->execute(); |
|
393
|
|
|
|
|
|
|
while (my $row = $sth->fetch()) { |
|
394
|
|
|
|
|
|
|
$names->{$row->[0]} = $row->[1]; |
|
395
|
|
|
|
|
|
|
} |
|
396
|
|
|
|
|
|
|
} |
|
397
|
|
|
|
|
|
|
else { |
|
398
|
|
|
|
|
|
|
use vars qw(*set); |
|
399
|
|
|
|
|
|
|
*set = DBIx::Recordset->Search({'!DataSource' => $self->{DBH}, |
|
400
|
|
|
|
|
|
|
'!Table' => $self->{REAL_ELEMENT_NAME_TABLE}}); |
|
401
|
|
|
|
|
|
|
foreach my $n (@set) { |
|
402
|
|
|
|
|
|
|
$names->{$n->{db_name}} = $n->{xml_name}; |
|
403
|
|
|
|
|
|
|
} |
|
404
|
|
|
|
|
|
|
# *link_tables->Flush(); |
|
405
|
|
|
|
|
|
|
DBIx::Recordset::Undef ('*set'); |
|
406
|
|
|
|
|
|
|
} |
|
407
|
|
|
|
|
|
|
return $names; |
|
408
|
|
|
|
|
|
|
} |
|
409
|
|
|
|
|
|
|
|
|
410
|
|
|
|
|
|
|
|
|
411
|
|
|
|
|
|
|
# |
|
412
|
|
|
|
|
|
|
# Get the corresponding 'xml_name' from this 'db_name' |
|
413
|
|
|
|
|
|
|
# |
|
414
|
|
|
|
|
|
|
#sub get_xml_name { |
|
415
|
|
|
|
|
|
|
# my($self, $db_name) = @_; |
|
416
|
|
|
|
|
|
|
# my @set = DBIx::Recordset->Search({ |
|
417
|
|
|
|
|
|
|
# '!DataSource' => $self->{DBH}, |
|
418
|
|
|
|
|
|
|
# '!Table' => $self->{REAL_ELEMENT_NAME_TABLE}, |
|
419
|
|
|
|
|
|
|
# '$where' => 'db_name = ?', |
|
420
|
|
|
|
|
|
|
# '$values' => [ $db_name ], |
|
421
|
|
|
|
|
|
|
# }); |
|
422
|
|
|
|
|
|
|
# |
|
423
|
|
|
|
|
|
|
# $set[0]{xml_name}; |
|
424
|
|
|
|
|
|
|
#} |
|
425
|
|
|
|
|
|
|
|
|
426
|
|
|
|
|
|
|
# |
|
427
|
|
|
|
|
|
|
# Recursive routine to unpopulate DB into in-memory data structure |
|
428
|
|
|
|
|
|
|
# |
|
429
|
|
|
|
|
|
|
# Takes a table name, PK of a row, & a hash ref of where in this |
|
430
|
|
|
|
|
|
|
# giant monstrous data in-memory data-structure we've created to |
|
431
|
|
|
|
|
|
|
# stick this row's values |
|
432
|
|
|
|
|
|
|
# |
|
433
|
|
|
|
|
|
|
|
|
434
|
|
|
|
|
|
|
sub un_populate_table { |
|
435
|
|
|
|
|
|
|
my($self, $one_to_n, $table_name, $id, $put_it_here) = @_; |
|
436
|
|
|
|
|
|
|
my $match = "_" . $self->{PK_NAME}; |
|
437
|
|
|
|
|
|
|
my(@stack, $schema_names, $jj, $other_table, $fk_field, $links, $kk, $i ); |
|
438
|
|
|
|
|
|
|
use vars qw(*schema); # DBIx::Recordset likes GLOBs, yummy |
|
439
|
|
|
|
|
|
|
|
|
440
|
|
|
|
|
|
|
TOP_TBL: |
|
441
|
|
|
|
|
|
|
( $jj, $other_table, $fk_field, $links, $kk, $i ) = (); |
|
442
|
|
|
|
|
|
|
|
|
443
|
|
|
|
|
|
|
# This'll get the ball rolling... |
|
444
|
|
|
|
|
|
|
*schema = DBIx::Recordset->Search({'!DataSource' => $self->{DBH}, |
|
445
|
|
|
|
|
|
|
'!Table' => $table_name, |
|
446
|
|
|
|
|
|
|
$self->{PK_NAME} => $id |
|
447
|
|
|
|
|
|
|
}); |
|
448
|
|
|
|
|
|
|
# Any column that ends in '_id' we gotta assume is a 1:1 map |
|
449
|
|
|
|
|
|
|
# Any column that ends in '_value' is text in this element |
|
450
|
|
|
|
|
|
|
# Any column that ends in '_attribute' is an attribute |
|
451
|
|
|
|
|
|
|
|
|
452
|
|
|
|
|
|
|
$schema_names = $schema->Names; |
|
453
|
|
|
|
|
|
|
|
|
454
|
|
|
|
|
|
|
# foreach my $col (@{$schema->Names}) { |
|
455
|
|
|
|
|
|
|
for ($jj = 0; scalar(@{$schema_names}) > $jj; $jj++) { |
|
456
|
|
|
|
|
|
|
my $col = $schema_names->[$jj]; |
|
457
|
|
|
|
|
|
|
my $val = $schema[0]{$col}; |
|
458
|
|
|
|
|
|
|
|
|
459
|
|
|
|
|
|
|
if ($col =~ /${match}$/o) { |
|
460
|
|
|
|
|
|
|
# 1:1 |
|
461
|
|
|
|
|
|
|
next if (!$val); |
|
462
|
|
|
|
|
|
|
|
|
463
|
|
|
|
|
|
|
# Unpopulate sub table since this is a foreign key |
|
464
|
|
|
|
|
|
|
my $this_table; |
|
465
|
|
|
|
|
|
|
($this_table = $col) =~ s/${match}$//; |
|
466
|
|
|
|
|
|
|
# $self->un_populate_table($one_to_n, $other_table, $val, \%{$put_it_here->{$other_table}}); |
|
467
|
|
|
|
|
|
|
|
|
468
|
|
|
|
|
|
|
push(@stack, [ $table_name, $id, $put_it_here, $schema_names, $jj, |
|
469
|
|
|
|
|
|
|
$other_table, $fk_field, $links, $kk, $i ]); |
|
470
|
|
|
|
|
|
|
($table_name, $id, $put_it_here ) = |
|
471
|
|
|
|
|
|
|
($this_table, $val, \%{$put_it_here->{$this_table}}); |
|
472
|
|
|
|
|
|
|
goto TOP_TBL; |
|
473
|
|
|
|
|
|
|
TOPLESS_TBL_1to1: |
|
474
|
|
|
|
|
|
|
|
|
475
|
|
|
|
|
|
|
# Put the candle - back |
|
476
|
|
|
|
|
|
|
*schema = DBIx::Recordset->Search({'!DataSource' => $self->{DBH}, |
|
477
|
|
|
|
|
|
|
'!Table' => $table_name, |
|
478
|
|
|
|
|
|
|
$self->{PK_NAME} => $id}); |
|
479
|
|
|
|
|
|
|
|
|
480
|
|
|
|
|
|
|
} |
|
481
|
|
|
|
|
|
|
elsif ($col =~ /_value$/o) { |
|
482
|
|
|
|
|
|
|
# text between tag |
|
483
|
|
|
|
|
|
|
$put_it_here->{value} = $val if (defined $val); |
|
484
|
|
|
|
|
|
|
} |
|
485
|
|
|
|
|
|
|
elsif ($col =~ /_attribute$/o) { |
|
486
|
|
|
|
|
|
|
# attribute |
|
487
|
|
|
|
|
|
|
$put_it_here->{attribute}{$col} = $val if (defined $val); |
|
488
|
|
|
|
|
|
|
} |
|
489
|
|
|
|
|
|
|
elsif ($col eq $self->{PK_NAME}) { |
|
490
|
|
|
|
|
|
|
# PK - don't do anything |
|
491
|
|
|
|
|
|
|
} |
|
492
|
|
|
|
|
|
|
elsif ($col =~ /_$self->{FK_NAME}$/o ) { |
|
493
|
|
|
|
|
|
|
# FK - don't do anything |
|
494
|
|
|
|
|
|
|
} |
|
495
|
|
|
|
|
|
|
else { |
|
496
|
|
|
|
|
|
|
# Keep us honest |
|
497
|
|
|
|
|
|
|
die "I don't know what to do with column name $col = $val!\n"; |
|
498
|
|
|
|
|
|
|
} |
|
499
|
|
|
|
|
|
|
} |
|
500
|
|
|
|
|
|
|
|
|
501
|
|
|
|
|
|
|
# Now get 1:N relationships |
|
502
|
|
|
|
|
|
|
if ($one_to_n->{$table_name}) { |
|
503
|
|
|
|
|
|
|
# Go thru each 'N' relationship table to this one |
|
504
|
|
|
|
|
|
|
|
|
505
|
|
|
|
|
|
|
$links = [ keys %{$one_to_n->{$table_name}} ]; |
|
506
|
|
|
|
|
|
|
|
|
507
|
|
|
|
|
|
|
for ($kk = 0; scalar(@{$links}) > $kk; $kk++) { |
|
508
|
|
|
|
|
|
|
my $link = $links->[$kk]; |
|
509
|
|
|
|
|
|
|
|
|
510
|
|
|
|
|
|
|
# Look up other PK via our PK (which is an FK in the sub_table) |
|
511
|
|
|
|
|
|
|
$other_table = $self->mtn($link); |
|
512
|
|
|
|
|
|
|
$fk_field = $table_name."_" . $self->{FK_NAME}; |
|
513
|
|
|
|
|
|
|
|
|
514
|
|
|
|
|
|
|
# Look up matching row in other (linked) table |
|
515
|
|
|
|
|
|
|
# Get rows from other table with a $fk_field matching |
|
516
|
|
|
|
|
|
|
# this one's |
|
517
|
|
|
|
|
|
|
*schema = DBIx::Recordset->Search({'!DataSource' => $self->{DBH}, |
|
518
|
|
|
|
|
|
|
'!Table' => $other_table, |
|
519
|
|
|
|
|
|
|
"$fk_field" => $id}); |
|
520
|
|
|
|
|
|
|
|
|
521
|
|
|
|
|
|
|
$i = 0; |
|
522
|
|
|
|
|
|
|
while(my $other_pk = $schema[$i]{$self->{PK_NAME}}) { |
|
523
|
|
|
|
|
|
|
next if (!$other_pk); |
|
524
|
|
|
|
|
|
|
# use $i in name to keep 'em seperate |
|
525
|
|
|
|
|
|
|
# & recursively unpopulate that other table |
|
526
|
|
|
|
|
|
|
# $self->un_populate_table($one_to_n, $other_table, $other_pk, \%{$put_it_here->{$i}{"${other_table}"}}); |
|
527
|
|
|
|
|
|
|
|
|
528
|
|
|
|
|
|
|
push(@stack, [ $table_name, $id, $put_it_here, $schema_names, $jj, |
|
529
|
|
|
|
|
|
|
$other_table, $fk_field, $links, $kk, $i ]); |
|
530
|
|
|
|
|
|
|
($table_name, $id, $put_it_here ) = |
|
531
|
|
|
|
|
|
|
($other_table, $other_pk, \%{$put_it_here->{$i}{"${other_table}"}}); |
|
532
|
|
|
|
|
|
|
|
|
533
|
|
|
|
|
|
|
goto TOP_TBL; |
|
534
|
|
|
|
|
|
|
TOPLESS_TBL_FK: |
|
535
|
|
|
|
|
|
|
|
|
536
|
|
|
|
|
|
|
# Put The Candle - Back |
|
537
|
|
|
|
|
|
|
*schema = DBIx::Recordset->Search({'!DataSource'=>$self->{DBH}, |
|
538
|
|
|
|
|
|
|
'!Table' => $other_table, |
|
539
|
|
|
|
|
|
|
"$fk_field" => $id}); |
|
540
|
|
|
|
|
|
|
$i++; |
|
541
|
|
|
|
|
|
|
} |
|
542
|
|
|
|
|
|
|
} |
|
543
|
|
|
|
|
|
|
} |
|
544
|
|
|
|
|
|
|
|
|
545
|
|
|
|
|
|
|
if (scalar(@stack) > 0) { |
|
546
|
|
|
|
|
|
|
( $table_name, $id, $put_it_here, $schema_names, $jj, |
|
547
|
|
|
|
|
|
|
$other_table, $fk_field, $links, $kk, $i ) = @{pop(@stack)}; |
|
548
|
|
|
|
|
|
|
unless ($other_table) { goto TOPLESS_TBL_1to1; } |
|
549
|
|
|
|
|
|
|
else { goto TOPLESS_TBL_FK; } |
|
550
|
|
|
|
|
|
|
} |
|
551
|
|
|
|
|
|
|
|
|
552
|
|
|
|
|
|
|
DBIx::Recordset::Undef ('*schema'); |
|
553
|
|
|
|
|
|
|
} |
|
554
|
|
|
|
|
|
|
|
|
555
|
|
|
|
|
|
|
|
|
556
|
|
|
|
|
|
|
|
|
557
|
|
|
|
|
|
|
|
|
558
|
|
|
|
|
|
|
#sub un_populate_table { |
|
559
|
|
|
|
|
|
|
# my($self, $one_to_n, $table_name, $id, $put_it_here) = @_; |
|
560
|
|
|
|
|
|
|
# use vars qw(*schema); # DBIx::Recordset likes GLOBs, yummy |
|
561
|
|
|
|
|
|
|
# |
|
562
|
|
|
|
|
|
|
# # This'll get the ball rolling... |
|
563
|
|
|
|
|
|
|
# *schema = DBIx::Recordset->Search({'!DataSource' => $self->{DBH}, |
|
564
|
|
|
|
|
|
|
# '!Table' => $table_name, |
|
565
|
|
|
|
|
|
|
# $self->{PK_NAME} => $id |
|
566
|
|
|
|
|
|
|
# }); |
|
567
|
|
|
|
|
|
|
# # Any column that ends in '_id' we gotta assume is a 1:1 map |
|
568
|
|
|
|
|
|
|
# # Any column that ends in '_value' is text in this element |
|
569
|
|
|
|
|
|
|
# # Any column that ends in '_attribute' is an attribute |
|
570
|
|
|
|
|
|
|
# foreach my $col (@{$schema->Names}) { |
|
571
|
|
|
|
|
|
|
# my $val = $schema[0]{$col}; |
|
572
|
|
|
|
|
|
|
# my $match = "_" . $self->{PK_NAME}; |
|
573
|
|
|
|
|
|
|
# |
|
574
|
|
|
|
|
|
|
# if ($col =~ /${match}$/) { |
|
575
|
|
|
|
|
|
|
# # 1:1 |
|
576
|
|
|
|
|
|
|
# next if (!$val); |
|
577
|
|
|
|
|
|
|
# |
|
578
|
|
|
|
|
|
|
# # Unpopulate sub table since this is a foreign key |
|
579
|
|
|
|
|
|
|
# my $other_table; |
|
580
|
|
|
|
|
|
|
# ($other_table = $col) =~ s/${match}$//; |
|
581
|
|
|
|
|
|
|
# $self->un_populate_table($one_to_n, $other_table, $val, \%{$put_it_here->{$other_table}}); |
|
582
|
|
|
|
|
|
|
# # Put the candle - back |
|
583
|
|
|
|
|
|
|
# *schema = DBIx::Recordset->Search({'!DataSource' => $self->{DBH}, |
|
584
|
|
|
|
|
|
|
# '!Table' => $table_name, |
|
585
|
|
|
|
|
|
|
# $self->{PK_NAME} => $id}); |
|
586
|
|
|
|
|
|
|
# |
|
587
|
|
|
|
|
|
|
# } |
|
588
|
|
|
|
|
|
|
# elsif ($col =~ /_value$/) { |
|
589
|
|
|
|
|
|
|
# # text between tag |
|
590
|
|
|
|
|
|
|
# $put_it_here->{value} = $val if (defined $val); |
|
591
|
|
|
|
|
|
|
# } |
|
592
|
|
|
|
|
|
|
# elsif ($col =~ /_attribute$/) { |
|
593
|
|
|
|
|
|
|
# # attribute |
|
594
|
|
|
|
|
|
|
# $put_it_here->{attribute}{$col} = $val if (defined $val); |
|
595
|
|
|
|
|
|
|
# } |
|
596
|
|
|
|
|
|
|
# elsif ($col eq $self->{PK_NAME}) { |
|
597
|
|
|
|
|
|
|
# # PK - don't do anything |
|
598
|
|
|
|
|
|
|
# } |
|
599
|
|
|
|
|
|
|
# elsif ($col =~ /_$self->{FK_NAME}$/ ) { |
|
600
|
|
|
|
|
|
|
# # FK - don't do anything |
|
601
|
|
|
|
|
|
|
# } |
|
602
|
|
|
|
|
|
|
# else { |
|
603
|
|
|
|
|
|
|
# # Keep us honest |
|
604
|
|
|
|
|
|
|
# die "I don't know what to do with column name $col = $val!\n"; |
|
605
|
|
|
|
|
|
|
# } |
|
606
|
|
|
|
|
|
|
# } |
|
607
|
|
|
|
|
|
|
# |
|
608
|
|
|
|
|
|
|
# # Now get 1:N relationships |
|
609
|
|
|
|
|
|
|
# if ($one_to_n->{$table_name}) { |
|
610
|
|
|
|
|
|
|
# # Go thru each 'N' relationship table to this one |
|
611
|
|
|
|
|
|
|
# foreach my $link (keys %{$one_to_n->{$table_name}}) { |
|
612
|
|
|
|
|
|
|
# # Look up other PK via our PK (which is an FK in the sub_table) |
|
613
|
|
|
|
|
|
|
# my $other_table = $self->mtn($link); |
|
614
|
|
|
|
|
|
|
# my $fk_field = $table_name."_" . $self->{FK_NAME}; |
|
615
|
|
|
|
|
|
|
# |
|
616
|
|
|
|
|
|
|
# # Look up matching row in other (linked) table |
|
617
|
|
|
|
|
|
|
# # Get rows from other table with a $fk_field matching |
|
618
|
|
|
|
|
|
|
# # this one's |
|
619
|
|
|
|
|
|
|
# *schema = DBIx::Recordset->Search({'!DataSource' => $self->{DBH}, |
|
620
|
|
|
|
|
|
|
# '!Table' => $other_table, |
|
621
|
|
|
|
|
|
|
# "$fk_field" => $id}); |
|
622
|
|
|
|
|
|
|
# my $i = 0; |
|
623
|
|
|
|
|
|
|
# while(my $other_pk = $schema[$i]{$self->{PK_NAME}}) { |
|
624
|
|
|
|
|
|
|
# next if (!$other_pk); |
|
625
|
|
|
|
|
|
|
# # use $i in name to keep 'em seperate |
|
626
|
|
|
|
|
|
|
# # & recursively unpopulate that other table |
|
627
|
|
|
|
|
|
|
# $self->un_populate_table($one_to_n, $other_table, $other_pk, \%{$put_it_here->{$i}{"${other_table}"}}); |
|
628
|
|
|
|
|
|
|
# |
|
629
|
|
|
|
|
|
|
# # Put The Candle - Back |
|
630
|
|
|
|
|
|
|
# *schema = DBIx::Recordset->Search({'!DataSource'=>$self->{DBH}, |
|
631
|
|
|
|
|
|
|
# '!Table' => $other_table, |
|
632
|
|
|
|
|
|
|
# "$fk_field" => $id}); |
|
633
|
|
|
|
|
|
|
# $i++; |
|
634
|
|
|
|
|
|
|
# } |
|
635
|
|
|
|
|
|
|
# } |
|
636
|
|
|
|
|
|
|
# } |
|
637
|
|
|
|
|
|
|
## *schema->Flush(); |
|
638
|
|
|
|
|
|
|
# DBIx::Recordset::Undef ('*schema'); |
|
639
|
|
|
|
|
|
|
#} |
|
640
|
|
|
|
|
|
|
|
|
641
|
|
|
|
|
|
|
1; |
|
642
|
|
|
|
|
|
|
__END__ |