line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
=head1 NAME |
2
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
DBD::Sprite - Perl extension for DBI, providing database emmulation via flat files. |
4
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
=head1 AUTHOR |
6
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
This module is Copyright (C) 2000-2019 by |
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
Jim Turner |
10
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
Email: turnerjw784 att yahoo dot com |
12
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
All rights reserved. |
14
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
You may distribute this module under the terms of either the GNU General |
16
|
|
|
|
|
|
|
Public License or the Artistic License, as specified in the Perl README |
17
|
|
|
|
|
|
|
file. |
18
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
JSprite.pm is a derived work by Jim Turner from Sprite.pm, a module |
20
|
|
|
|
|
|
|
written and copyrighted (c) 1995-1998, by Shishir Gurdavaram |
21
|
|
|
|
|
|
|
(shishir@ora.com). |
22
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
=head1 SYNOPSIS |
24
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
use DBI; |
26
|
|
|
|
|
|
|
$dbh = DBI->connect("DBI:Sprite:spritedb",'user','password') |
27
|
|
|
|
|
|
|
or die "Cannot connect: " . $DBI::errstr; |
28
|
|
|
|
|
|
|
$sth = $dbh->prepare("CREATE TABLE a (id INTEGER, name CHAR(10))") |
29
|
|
|
|
|
|
|
or die "Cannot prepare: " . $dbh->errstr(); |
30
|
|
|
|
|
|
|
$sth->execute() or die "Cannot execute: " . $sth->errstr(); |
31
|
|
|
|
|
|
|
$sth->finish(); |
32
|
|
|
|
|
|
|
$dbh->disconnect(); |
33
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
=head1 DESCRIPTION |
35
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
DBD::Sprite is a DBI extension module adding database emulation via flat-files |
37
|
|
|
|
|
|
|
to Perl's database-independent database interface. Unlike other DBD::modules, |
38
|
|
|
|
|
|
|
DBD::Sprite does not require you to purchase or obtain a database. Every |
39
|
|
|
|
|
|
|
thing you need to prototype database-independent applications using Perl and |
40
|
|
|
|
|
|
|
DBI are included here. You will, however, probably wish to obtain a real |
41
|
|
|
|
|
|
|
database, such as "mysql", for your production and larger data needs. This |
42
|
|
|
|
|
|
|
is because emulating databases and SQL with flat text files gets very slow as |
43
|
|
|
|
|
|
|
the size of your "database" grows to a non-trivial size (a few dozen records |
44
|
|
|
|
|
|
|
or so per table). |
45
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
DBD::Sprite is built upon an old Perl module called "Sprite", written by |
47
|
|
|
|
|
|
|
Shishir Gurdavaram. This code was used as a starting point. It was completly |
48
|
|
|
|
|
|
|
reworked and many new features were added, producing a module called |
49
|
|
|
|
|
|
|
"JSprite.pm" (Jim Turner's Sprite). This was then merged in to DBI::DBD to |
50
|
|
|
|
|
|
|
produce what you are installing now. (DBD::Sprite). JSprite.pm is included |
51
|
|
|
|
|
|
|
in this module as a separate file, and is required. |
52
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
Many thanks go to Mr. Gurdavaram. |
54
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
The main advantage of DBD::Sprite is the ability to develop and test |
56
|
|
|
|
|
|
|
prototype applications on personal machines (or other machines which do not |
57
|
|
|
|
|
|
|
have an Oracle licence or some other "mainstream" database) before releasing |
58
|
|
|
|
|
|
|
them on "production" machines which do have a "real" database. This can all |
59
|
|
|
|
|
|
|
be done with minimal or no changes to your Perl code. |
60
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
Another advantage of DBD::Sprite is that you can use Perl's regular |
62
|
|
|
|
|
|
|
expressions to search through your data. Maybe, someday, more "real" |
63
|
|
|
|
|
|
|
databases will include this feature too! |
64
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
DBD::Sprite provides the ability to emulate basic database tables |
66
|
|
|
|
|
|
|
and SQL calls via flat-files. The primary use envisioned |
67
|
|
|
|
|
|
|
for this to permit website developers who can not afford |
68
|
|
|
|
|
|
|
to purchase an Oracle licence to prototype and develop Perl |
69
|
|
|
|
|
|
|
applications on their own equipment for later hosting at |
70
|
|
|
|
|
|
|
larger customer sites where Oracle is used. :-) |
71
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
DBD::Sprite attempts to do things in as database-independent manner as possible, |
73
|
|
|
|
|
|
|
but where differences occurr, JSprite most closely emmulates Oracle, for |
74
|
|
|
|
|
|
|
example "sequences/autonumbering". JSprite uses tiny one-line text files |
75
|
|
|
|
|
|
|
called "sequence files" (.seq). and "seq_file_name.NEXTVAL" function to |
76
|
|
|
|
|
|
|
insert into autonumbered fields. The reason for this is that the Author |
77
|
|
|
|
|
|
|
works in an Oracle shop and wrote this module to allow himself to work on |
78
|
|
|
|
|
|
|
code on his PC, and machines which did not have Oracle on them, since |
79
|
|
|
|
|
|
|
obtaining Oracle licences was sometimes time-consuming. |
80
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
DBD::Sprite is similar to DBD::CSV, but differs in the following ways: |
82
|
|
|
|
|
|
|
|
83
|
|
|
|
|
|
|
1) It creates and works on true "databases" with user-ids and passwords, |
84
|
|
|
|
|
|
|
real datatypes like numeric, varchar, blob, etc. with max. precisions and |
85
|
|
|
|
|
|
|
scales. |
86
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
2) The database author specifies the field delimiters, record delimiters, |
88
|
|
|
|
|
|
|
user, password, table file path, AND extension for each database. |
89
|
|
|
|
|
|
|
|
90
|
|
|
|
|
|
|
3) Transactions (commits and rollbacks) are fully supported! |
91
|
|
|
|
|
|
|
|
92
|
|
|
|
|
|
|
4) Autonumbering and user-defined functions are supported. |
93
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
5) You don't need any other modules or databases. (NO prerequisites |
95
|
|
|
|
|
|
|
except Perl 5 and the DBI module! |
96
|
|
|
|
|
|
|
|
97
|
|
|
|
|
|
|
6) Quotes are not used around data. |
98
|
|
|
|
|
|
|
|
99
|
|
|
|
|
|
|
7) It is not necessary to call the "$dbh->quote()" method all the time |
100
|
|
|
|
|
|
|
in your sql. |
101
|
|
|
|
|
|
|
|
102
|
|
|
|
|
|
|
8) NULL is handled as an empty string. |
103
|
|
|
|
|
|
|
|
104
|
|
|
|
|
|
|
9) Users can "register" their own data-conversion functions for use in |
105
|
|
|
|
|
|
|
sql. See "fn_register" method below. |
106
|
|
|
|
|
|
|
|
107
|
|
|
|
|
|
|
10) Optional data encryption. |
108
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
11) Optional table storage in XML format. |
110
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
12) Two-table joins now supported! |
112
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
|
114
|
|
|
|
|
|
|
=head1 INSTALLATION |
115
|
|
|
|
|
|
|
|
116
|
|
|
|
|
|
|
Installing this module (and the prerequisites from above) is quite |
117
|
|
|
|
|
|
|
simple. You just fetch the archive, extract it with |
118
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
gzip -cd DBD-Sprite-0.1000.tar.gz | tar xf - |
120
|
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
(this is for Unix users, Windows users would prefer WinZip or something |
122
|
|
|
|
|
|
|
similar) and then enter the following: |
123
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
cd DBD-Sprite-#.### |
125
|
|
|
|
|
|
|
perl Makefile.PL |
126
|
|
|
|
|
|
|
make |
127
|
|
|
|
|
|
|
make test |
128
|
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
If any tests fail, let me know. Otherwise go on with |
130
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
make install |
132
|
|
|
|
|
|
|
|
133
|
|
|
|
|
|
|
Note that you almost definitely need root or administrator permissions. |
134
|
|
|
|
|
|
|
If you don't have them, read the ExtUtils::MakeMaker man page for |
135
|
|
|
|
|
|
|
details on installing in your own directories. the ExtUtils::MakeMaker |
136
|
|
|
|
|
|
|
manpage. |
137
|
|
|
|
|
|
|
|
138
|
|
|
|
|
|
|
NOTE: You may also need to copy "makesdb.pl" to /usr/local/bin or |
139
|
|
|
|
|
|
|
somewhere in your path. |
140
|
|
|
|
|
|
|
|
141
|
|
|
|
|
|
|
=head1 GETTING STARTED: |
142
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
1) cd to where you wish to store your database. |
144
|
|
|
|
|
|
|
2) run makesdb.pl to create your database, ie. |
145
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
Database name: mydb |
147
|
|
|
|
|
|
|
Database user: me |
148
|
|
|
|
|
|
|
User password: mypassword |
149
|
|
|
|
|
|
|
Database path: . |
150
|
|
|
|
|
|
|
Table file extension (default .stb): |
151
|
|
|
|
|
|
|
Record delimiter (default \n): |
152
|
|
|
|
|
|
|
Field delimiter (default ::): |
153
|
|
|
|
|
|
|
|
154
|
|
|
|
|
|
|
This will create a new database text file (mydb.sdb) in the current |
155
|
|
|
|
|
|
|
directory. This ascii file contains the information you enterred |
156
|
|
|
|
|
|
|
above. To add additional user-spaces, simply rerun makesdb.pl with |
157
|
|
|
|
|
|
|
"mydb" as your database name, and enter additional users (name, |
158
|
|
|
|
|
|
|
password, path, extension, and delimiters). For an example, after |
159
|
|
|
|
|
|
|
running "make test", look at the file "test.sdb". |
160
|
|
|
|
|
|
|
|
161
|
|
|
|
|
|
|
When connecting to a Sprite database, Sprite will look in the current |
162
|
|
|
|
|
|
|
directory, then, if specified, the path in the SPRITE_HOME environment |
163
|
|
|
|
|
|
|
variable. |
164
|
|
|
|
|
|
|
|
165
|
|
|
|
|
|
|
The database name, user, and password are used in the "db->connect()" |
166
|
|
|
|
|
|
|
method described below. The "database path" is where your tables will |
167
|
|
|
|
|
|
|
be created and reside. Table files are ascii text files which will |
168
|
|
|
|
|
|
|
have, by default, the extension ".stb" (Sprite table). By default, |
169
|
|
|
|
|
|
|
each record will be written to a single line (separated by \n -- |
170
|
|
|
|
|
|
|
Windows users should probably use "\r\n"). Each field datum will be |
171
|
|
|
|
|
|
|
written without quotes separated by the "field delimiter (default: |
172
|
|
|
|
|
|
|
double-colon). The first line of the table file consists of the |
173
|
|
|
|
|
|
|
a field name, an equal ("=") sign, an asterisk if it is a key field, |
174
|
|
|
|
|
|
|
then the datatype and size. This information is included for each |
175
|
|
|
|
|
|
|
field and separated by the field separator. For an example, after |
176
|
|
|
|
|
|
|
running "make test", look at the file "testtable.stb". |
177
|
|
|
|
|
|
|
|
178
|
|
|
|
|
|
|
3) write your script to use DBI, ie: |
179
|
|
|
|
|
|
|
|
180
|
|
|
|
|
|
|
#!/usr/bin/perl |
181
|
|
|
|
|
|
|
use DBI; |
182
|
|
|
|
|
|
|
|
183
|
|
|
|
|
|
|
$dbh = DBI->connect('DBI:Sprite:mydb','me','mypassword') || |
184
|
|
|
|
|
|
|
die "Could not connect (".$DBI->err.':'.$DBI->errstr.")!"; |
185
|
|
|
|
|
|
|
... |
186
|
|
|
|
|
|
|
#CREATE A TABLE, INSERT SOME RECORDS, HAVE SOME FUN! |
187
|
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
4) get your application working. |
189
|
|
|
|
|
|
|
|
190
|
|
|
|
|
|
|
5) rehost your application on a "production" machine and change "Sprite" |
191
|
|
|
|
|
|
|
to a DBI driver for a "real" database! |
192
|
|
|
|
|
|
|
|
193
|
|
|
|
|
|
|
=head1 CREATING AND DROPPING TABLES |
194
|
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
You can create and drop tables with commands like the following: |
196
|
|
|
|
|
|
|
|
197
|
|
|
|
|
|
|
$dbh->do("CREATE TABLE $table (id INTEGER, name CHAR(64))"); |
198
|
|
|
|
|
|
|
$dbh->do("DROP TABLE $table"); |
199
|
|
|
|
|
|
|
|
200
|
|
|
|
|
|
|
Column names, datatypes, precision, scales, and autonumber sequences are |
201
|
|
|
|
|
|
|
stored on the top line as COLUNM_NAME(PRECISION[,SCALE])=DEFAULT_VALUE |
202
|
|
|
|
|
|
|
|
203
|
|
|
|
|
|
|
A drop just removes the file without any warning. |
204
|
|
|
|
|
|
|
|
205
|
|
|
|
|
|
|
See the DBI(3) manpage for more details. |
206
|
|
|
|
|
|
|
|
207
|
|
|
|
|
|
|
Table names cannot be arbitrary, due to restrictions of the SQL syntax. |
208
|
|
|
|
|
|
|
I recommend that table names are valid SQL identifiers: The first |
209
|
|
|
|
|
|
|
character is alphabetic, followed by an arbitrary number of alphanumeric |
210
|
|
|
|
|
|
|
characters. If you want to use other files, the file names must start |
211
|
|
|
|
|
|
|
with '/', './' or '../' and they must not contain white space. |
212
|
|
|
|
|
|
|
|
213
|
|
|
|
|
|
|
=head1 INSERTING, FETCHING AND MODIFYING DATA |
214
|
|
|
|
|
|
|
|
215
|
|
|
|
|
|
|
The following examples insert some data in a table and fetch it back: |
216
|
|
|
|
|
|
|
First all data in the string: |
217
|
|
|
|
|
|
|
|
218
|
|
|
|
|
|
|
$dbh->do("INSERT INTO $table VALUES (1, 'foobar')"); |
219
|
|
|
|
|
|
|
|
220
|
|
|
|
|
|
|
Note the use of the quote method for escaping the word 'foobar'. Any |
221
|
|
|
|
|
|
|
string must be escaped, even if it doesn't contain binary data. |
222
|
|
|
|
|
|
|
|
223
|
|
|
|
|
|
|
Next an example using parameters: |
224
|
|
|
|
|
|
|
|
225
|
|
|
|
|
|
|
$dbh->do("INSERT INTO $table VALUES (?, ?)", undef, |
226
|
|
|
|
|
|
|
2, "It's a string!"); |
227
|
|
|
|
|
|
|
|
228
|
|
|
|
|
|
|
To retrieve data, you can use the following: |
229
|
|
|
|
|
|
|
|
230
|
|
|
|
|
|
|
my($query) = "SELECT * FROM $table WHERE id > 1 ORDER BY id"; |
231
|
|
|
|
|
|
|
my($sth) = $dbh->prepare($query); |
232
|
|
|
|
|
|
|
$sth->execute(); |
233
|
|
|
|
|
|
|
while (my $row = $sth->fetchrow_hashref) { |
234
|
|
|
|
|
|
|
print("Found result row: id = ", $row->{'id'}, |
235
|
|
|
|
|
|
|
", name = ", $row->{'name'}); |
236
|
|
|
|
|
|
|
} |
237
|
|
|
|
|
|
|
$sth->finish(); |
238
|
|
|
|
|
|
|
|
239
|
|
|
|
|
|
|
Again, column binding works: The same example again. |
240
|
|
|
|
|
|
|
|
241
|
|
|
|
|
|
|
my($query) = "SELECT * FROM $table WHERE id > 1 ORDER BY id"; |
242
|
|
|
|
|
|
|
my($sth) = $dbh->prepare($query); |
243
|
|
|
|
|
|
|
$sth->execute(); |
244
|
|
|
|
|
|
|
my($id, $name); |
245
|
|
|
|
|
|
|
$sth->bind_columns(undef, \$id, \$name); |
246
|
|
|
|
|
|
|
while ($sth->fetch) { |
247
|
|
|
|
|
|
|
print("Found result row: id = $id, name = $name\n"); |
248
|
|
|
|
|
|
|
} |
249
|
|
|
|
|
|
|
$sth->finish(); |
250
|
|
|
|
|
|
|
|
251
|
|
|
|
|
|
|
Of course you can even use input parameters. Here's the same example for |
252
|
|
|
|
|
|
|
the third time: |
253
|
|
|
|
|
|
|
|
254
|
|
|
|
|
|
|
my($query) = "SELECT * FROM $table WHERE id = ?"; |
255
|
|
|
|
|
|
|
my($sth) = $dbh->prepare($query); |
256
|
|
|
|
|
|
|
$sth->bind_columns(undef, \$id, \$name); |
257
|
|
|
|
|
|
|
for (my($i) = 1; $i <= 2; $i++) { |
258
|
|
|
|
|
|
|
$sth->execute($id); |
259
|
|
|
|
|
|
|
if ($sth->fetch) { |
260
|
|
|
|
|
|
|
print("Found result row: id = $id, name = $name\n"); |
261
|
|
|
|
|
|
|
} |
262
|
|
|
|
|
|
|
$sth->finish(); |
263
|
|
|
|
|
|
|
} |
264
|
|
|
|
|
|
|
|
265
|
|
|
|
|
|
|
See the DBI(3) manpage for details on these methods. See the |
266
|
|
|
|
|
|
|
SQL::Statement(3) manpage for details on the WHERE clause. |
267
|
|
|
|
|
|
|
|
268
|
|
|
|
|
|
|
Data rows are modified with the UPDATE statement: |
269
|
|
|
|
|
|
|
|
270
|
|
|
|
|
|
|
$dbh->do("UPDATE $table SET id = 3 WHERE id = 1"); |
271
|
|
|
|
|
|
|
|
272
|
|
|
|
|
|
|
Likewise you use the DELETE statement for removing rows: |
273
|
|
|
|
|
|
|
|
274
|
|
|
|
|
|
|
$dbh->do("DELETE FROM $table WHERE id > 1"); |
275
|
|
|
|
|
|
|
|
276
|
|
|
|
|
|
|
I |
277
|
|
|
|
|
|
|
|
278
|
|
|
|
|
|
|
Method takes 2 arguments: Function name and optionally, a |
279
|
|
|
|
|
|
|
package name (default is "main"). |
280
|
|
|
|
|
|
|
|
281
|
|
|
|
|
|
|
$dbh->fn_register ('myfn','mypackage'); |
282
|
|
|
|
|
|
|
|
283
|
|
|
|
|
|
|
-or- |
284
|
|
|
|
|
|
|
|
285
|
|
|
|
|
|
|
use JSprite; |
286
|
|
|
|
|
|
|
JSprite::fn_register ('myfn',__PACKAGE__); |
287
|
|
|
|
|
|
|
|
288
|
|
|
|
|
|
|
Then, you could say in sql: |
289
|
|
|
|
|
|
|
|
290
|
|
|
|
|
|
|
insert into mytable values (myfn(?)) |
291
|
|
|
|
|
|
|
|
292
|
|
|
|
|
|
|
and bind some value to "?", which is passed to "myfn", and the return-value |
293
|
|
|
|
|
|
|
is inserted into the database. You could also say (without binding): |
294
|
|
|
|
|
|
|
|
295
|
|
|
|
|
|
|
insert into mytable values (myfn('mystring')) |
296
|
|
|
|
|
|
|
|
297
|
|
|
|
|
|
|
-or (if the function takes a number)- |
298
|
|
|
|
|
|
|
|
299
|
|
|
|
|
|
|
select field1, field2 from mytable where field3 = myfn(123) |
300
|
|
|
|
|
|
|
|
301
|
|
|
|
|
|
|
I |
302
|
|
|
|
|
|
|
|
303
|
|
|
|
|
|
|
None |
304
|
|
|
|
|
|
|
|
305
|
|
|
|
|
|
|
=head1 ERROR HANDLING |
306
|
|
|
|
|
|
|
|
307
|
|
|
|
|
|
|
In the above examples we have never cared about return codes. Of course, |
308
|
|
|
|
|
|
|
this cannot be recommended. Instead we should have written (for |
309
|
|
|
|
|
|
|
example): |
310
|
|
|
|
|
|
|
|
311
|
|
|
|
|
|
|
my($query) = "SELECT * FROM $table WHERE id = ?"; |
312
|
|
|
|
|
|
|
my($sth) = $dbh->prepare($query) |
313
|
|
|
|
|
|
|
or die "prepare: " . $dbh->errstr(); |
314
|
|
|
|
|
|
|
$sth->bind_columns(undef, \$id, \$name) |
315
|
|
|
|
|
|
|
or die "bind_columns: " . $dbh->errstr(); |
316
|
|
|
|
|
|
|
for (my($i) = 1; $i <= 2; $i++) { |
317
|
|
|
|
|
|
|
$sth->execute($id) |
318
|
|
|
|
|
|
|
or die "execute: " . $dbh->errstr(); |
319
|
|
|
|
|
|
|
if ($sth->fetch) { |
320
|
|
|
|
|
|
|
print("Found result row: id = $id, name = $name\n"); |
321
|
|
|
|
|
|
|
} |
322
|
|
|
|
|
|
|
} |
323
|
|
|
|
|
|
|
$sth->finish($id) |
324
|
|
|
|
|
|
|
or die "finish: " . $dbh->errstr(); |
325
|
|
|
|
|
|
|
|
326
|
|
|
|
|
|
|
Obviously this is tedious. Fortunately we have DBI's *RaiseError* |
327
|
|
|
|
|
|
|
attribute: |
328
|
|
|
|
|
|
|
|
329
|
|
|
|
|
|
|
$dbh->{'RaiseError'} = 1; |
330
|
|
|
|
|
|
|
$@ = ''; |
331
|
|
|
|
|
|
|
eval { |
332
|
|
|
|
|
|
|
my($query) = "SELECT * FROM $table WHERE id = ?"; |
333
|
|
|
|
|
|
|
my($sth) = $dbh->prepare($query); |
334
|
|
|
|
|
|
|
$sth->bind_columns(undef, \$id, \$name); |
335
|
|
|
|
|
|
|
for (my($i) = 1; $i <= 2; $i++) { |
336
|
|
|
|
|
|
|
$sth->execute($id); |
337
|
|
|
|
|
|
|
if ($sth->fetch) { |
338
|
|
|
|
|
|
|
print("Found result row: id = $id, name = $name\n"); |
339
|
|
|
|
|
|
|
} |
340
|
|
|
|
|
|
|
} |
341
|
|
|
|
|
|
|
$sth->finish($id); |
342
|
|
|
|
|
|
|
}; |
343
|
|
|
|
|
|
|
if ($@) { die "SQL database error: $@"; } |
344
|
|
|
|
|
|
|
|
345
|
|
|
|
|
|
|
This is not only shorter, it even works when using DBI methods within |
346
|
|
|
|
|
|
|
subroutines. |
347
|
|
|
|
|
|
|
|
348
|
|
|
|
|
|
|
=head1 METADATA |
349
|
|
|
|
|
|
|
|
350
|
|
|
|
|
|
|
The following attributes are handled by DBI itself and not by DBD::File, |
351
|
|
|
|
|
|
|
thus they should all work as expected: I have only used the last 3. |
352
|
|
|
|
|
|
|
|
353
|
|
|
|
|
|
|
I |
354
|
|
|
|
|
|
|
|
355
|
|
|
|
|
|
|
I |
356
|
|
|
|
|
|
|
|
357
|
|
|
|
|
|
|
I |
358
|
|
|
|
|
|
|
|
359
|
|
|
|
|
|
|
I (Not used) |
360
|
|
|
|
|
|
|
|
361
|
|
|
|
|
|
|
I |
362
|
|
|
|
|
|
|
|
363
|
|
|
|
|
|
|
I |
364
|
|
|
|
|
|
|
|
365
|
|
|
|
|
|
|
I |
366
|
|
|
|
|
|
|
|
367
|
|
|
|
|
|
|
I |
368
|
|
|
|
|
|
|
|
369
|
|
|
|
|
|
|
I |
370
|
|
|
|
|
|
|
|
371
|
|
|
|
|
|
|
The following DBI attributes are handled by DBD::Sprite: |
372
|
|
|
|
|
|
|
|
373
|
|
|
|
|
|
|
B |
374
|
|
|
|
|
|
|
|
375
|
|
|
|
|
|
|
Works |
376
|
|
|
|
|
|
|
|
377
|
|
|
|
|
|
|
B |
378
|
|
|
|
|
|
|
|
379
|
|
|
|
|
|
|
Should Work |
380
|
|
|
|
|
|
|
|
381
|
|
|
|
|
|
|
B |
382
|
|
|
|
|
|
|
|
383
|
|
|
|
|
|
|
Valid after `$sth->execute' |
384
|
|
|
|
|
|
|
|
385
|
|
|
|
|
|
|
B |
386
|
|
|
|
|
|
|
|
387
|
|
|
|
|
|
|
Valid after `$sth->prepare' |
388
|
|
|
|
|
|
|
|
389
|
|
|
|
|
|
|
B |
390
|
|
|
|
|
|
|
|
391
|
|
|
|
|
|
|
Valid after `$sth->execute'; undef for Non-Select statements. |
392
|
|
|
|
|
|
|
|
393
|
|
|
|
|
|
|
B |
394
|
|
|
|
|
|
|
|
395
|
|
|
|
|
|
|
Not really working. Always returns an array ref of one's, as |
396
|
|
|
|
|
|
|
DBD::Sprite always allows NULL (handled as an empty string). |
397
|
|
|
|
|
|
|
Valid after `$sth->execute'. |
398
|
|
|
|
|
|
|
|
399
|
|
|
|
|
|
|
B |
400
|
|
|
|
|
|
|
|
401
|
|
|
|
|
|
|
Works |
402
|
|
|
|
|
|
|
|
403
|
|
|
|
|
|
|
B |
404
|
|
|
|
|
|
|
|
405
|
|
|
|
|
|
|
Works |
406
|
|
|
|
|
|
|
|
407
|
|
|
|
|
|
|
B |
408
|
|
|
|
|
|
|
|
409
|
|
|
|
|
|
|
Should work |
410
|
|
|
|
|
|
|
|
411
|
|
|
|
|
|
|
B |
412
|
|
|
|
|
|
|
|
413
|
|
|
|
|
|
|
Works |
414
|
|
|
|
|
|
|
|
415
|
|
|
|
|
|
|
These attributes and methods are not supported: |
416
|
|
|
|
|
|
|
|
417
|
|
|
|
|
|
|
B |
418
|
|
|
|
|
|
|
|
419
|
|
|
|
|
|
|
B |
420
|
|
|
|
|
|
|
|
421
|
|
|
|
|
|
|
|
422
|
|
|
|
|
|
|
In addition to the DBI attributes, you can use the following dbh |
423
|
|
|
|
|
|
|
attributes. These attributes are read-only after "connect". |
424
|
|
|
|
|
|
|
|
425
|
|
|
|
|
|
|
I |
426
|
|
|
|
|
|
|
|
427
|
|
|
|
|
|
|
Path to tables for database. |
428
|
|
|
|
|
|
|
|
429
|
|
|
|
|
|
|
I |
430
|
|
|
|
|
|
|
|
431
|
|
|
|
|
|
|
File extension used on table files in the database. |
432
|
|
|
|
|
|
|
|
433
|
|
|
|
|
|
|
I |
434
|
|
|
|
|
|
|
|
435
|
|
|
|
|
|
|
Current database user. |
436
|
|
|
|
|
|
|
|
437
|
|
|
|
|
|
|
I |
438
|
|
|
|
|
|
|
|
439
|
|
|
|
|
|
|
Field delimiter string in use for the database. |
440
|
|
|
|
|
|
|
|
441
|
|
|
|
|
|
|
I |
442
|
|
|
|
|
|
|
|
443
|
|
|
|
|
|
|
Record delimiter string in use for the database. |
444
|
|
|
|
|
|
|
|
445
|
|
|
|
|
|
|
The following are environment variables specifically recognized by Sprite. |
446
|
|
|
|
|
|
|
|
447
|
|
|
|
|
|
|
I |
448
|
|
|
|
|
|
|
Environment variable specifying a path to search for Sprite |
449
|
|
|
|
|
|
|
databases (*.sdb) files. |
450
|
|
|
|
|
|
|
|
451
|
|
|
|
|
|
|
|
452
|
|
|
|
|
|
|
The following are Sprite-specific options which can be set when connecting. |
453
|
|
|
|
|
|
|
|
454
|
|
|
|
|
|
|
I => 0 | 1 |
455
|
|
|
|
|
|
|
|
456
|
|
|
|
|
|
|
By default, table names are case-insensitive (as they are in Oracle), |
457
|
|
|
|
|
|
|
to make table names case-sensitive (as in MySql), so that one could |
458
|
|
|
|
|
|
|
have two separate tables such as "test" and "TEST", set this option |
459
|
|
|
|
|
|
|
to 1. |
460
|
|
|
|
|
|
|
|
461
|
|
|
|
|
|
|
I => 0 | 1 |
462
|
|
|
|
|
|
|
|
463
|
|
|
|
|
|
|
By default, field names are case-insensitive (as they are in Oracle), |
464
|
|
|
|
|
|
|
to make field names case-sensitive, so that one could |
465
|
|
|
|
|
|
|
have two separate fields such as "test" and "TEST", set this option |
466
|
|
|
|
|
|
|
to 1. The default is 1 (case-sensitive) if XML. |
467
|
|
|
|
|
|
|
|
468
|
|
|
|
|
|
|
I => 0 | 1 |
469
|
|
|
|
|
|
|
|
470
|
|
|
|
|
|
|
CHAR fields are always right-padded with spaces to fill out |
471
|
|
|
|
|
|
|
the field. Old (pre 5.17) Sprite behaviour was to require the |
472
|
|
|
|
|
|
|
padding be included in literals used for testing equality in |
473
|
|
|
|
|
|
|
"where" clauses. I discovered that Oracle and some other databases |
474
|
|
|
|
|
|
|
do not require this when testing DBIx-Recordset, so Sprite will |
475
|
|
|
|
|
|
|
automatically right-pad literals when testing for equality. |
476
|
|
|
|
|
|
|
To disable this and force the old behavior, set this option to 1. |
477
|
|
|
|
|
|
|
|
478
|
|
|
|
|
|
|
I => [encrypt=|decrypt=][Crypt]::CBC;][[IDEA[_PP]|DES[_PP]|BLOWFISH[_PP];]keystring |
479
|
|
|
|
|
|
|
|
480
|
|
|
|
|
|
|
Optional encryption and/or decryption of data stored in tables. By |
481
|
|
|
|
|
|
|
omitting "encrypt=" and "decrypt=", data will be decrypted when read |
482
|
|
|
|
|
|
|
from the table and encrypted when written to the table using the |
483
|
|
|
|
|
|
|
"keystring" as the key. |
484
|
|
|
|
|
|
|
|
485
|
|
|
|
|
|
|
I => 0 | 1 |
486
|
|
|
|
|
|
|
|
487
|
|
|
|
|
|
|
This option forces the table file to first be deleted before being |
488
|
|
|
|
|
|
|
overwritten. Default is 0 (do not delete, just overwrite it). This |
489
|
|
|
|
|
|
|
was need by the author on certain network filesystems on one jobsite. |
490
|
|
|
|
|
|
|
|
491
|
|
|
|
|
|
|
I => xsl_stylesheet_url |
492
|
|
|
|
|
|
|
|
493
|
|
|
|
|
|
|
Optional xsl stylesheet url to be included in database tables in XML |
494
|
|
|
|
|
|
|
format. Otherwise, ignored. Default none. |
495
|
|
|
|
|
|
|
|
496
|
|
|
|
|
|
|
I => 0 | 1 |
497
|
|
|
|
|
|
|
|
498
|
|
|
|
|
|
|
By default, on error, Sprite prints the legacy |
499
|
|
|
|
|
|
|
"Oops! Sprite encountered the following error when processing your request..." |
500
|
|
|
|
|
|
|
multiline error message carried over from the original Sprite by |
501
|
|
|
|
|
|
|
Shishir Gurdavaram. Set to 1 to silense this, if it annoys you, or if you |
502
|
|
|
|
|
|
|
are using Sprite in a CGI script. |
503
|
|
|
|
|
|
|
|
504
|
|
|
|
|
|
|
The following attributes can be specified as a hash reference in "prepare" |
505
|
|
|
|
|
|
|
statements: |
506
|
|
|
|
|
|
|
|
507
|
|
|
|
|
|
|
I => # |
508
|
|
|
|
|
|
|
|
509
|
|
|
|
|
|
|
Limit processing the table to # records. This is NOT the same as a |
510
|
|
|
|
|
|
|
"LIMIT #" clause in selects. This limits the query to the first # |
511
|
|
|
|
|
|
|
records in the table UNSORTED - BEFORE any constraints or sorting are |
512
|
|
|
|
|
|
|
applied. This is useful for limiting queries to, say 1 record |
513
|
|
|
|
|
|
|
simply to populate the column metadata. |
514
|
|
|
|
|
|
|
|
515
|
|
|
|
|
|
|
I => # |
516
|
|
|
|
|
|
|
|
517
|
|
|
|
|
|
|
This is the same as adding a "LIMIT #" clause to a select statement |
518
|
|
|
|
|
|
|
when preparing it, as it will limit a query to returning # records |
519
|
|
|
|
|
|
|
AFTER applying any constraints and sorting. |
520
|
|
|
|
|
|
|
|
521
|
|
|
|
|
|
|
=head1 DRIVER PRIVATE METHODS |
522
|
|
|
|
|
|
|
|
523
|
|
|
|
|
|
|
B->B() |
524
|
|
|
|
|
|
|
|
525
|
|
|
|
|
|
|
The `data_sources' method returns a list of "databases" (.sdb files) |
526
|
|
|
|
|
|
|
found in the current directory and, if specified, the path in |
527
|
|
|
|
|
|
|
the SPRITE_HOME environment variable. |
528
|
|
|
|
|
|
|
|
529
|
|
|
|
|
|
|
$dbh->B() |
530
|
|
|
|
|
|
|
|
531
|
|
|
|
|
|
|
This method returns a list of table names specified in the current |
532
|
|
|
|
|
|
|
database. |
533
|
|
|
|
|
|
|
Example: |
534
|
|
|
|
|
|
|
|
535
|
|
|
|
|
|
|
my($dbh) = DBI->connect("DBI:Sprite:mydatabase",'me','mypswd'); |
536
|
|
|
|
|
|
|
my(@list) = $dbh->func('tables'); |
537
|
|
|
|
|
|
|
|
538
|
|
|
|
|
|
|
B('myfn', __PACKAGE__); |
539
|
|
|
|
|
|
|
|
540
|
|
|
|
|
|
|
This method takes the name of a user-defined data-conversion function |
541
|
|
|
|
|
|
|
for use in SQL commands. Your function can optionally take arguments, |
542
|
|
|
|
|
|
|
but should return a single number or string. Unless your function |
543
|
|
|
|
|
|
|
is defined in package "main", you must also specify the package name |
544
|
|
|
|
|
|
|
or "__PACKAGE__" for the current package. For an example, see the |
545
|
|
|
|
|
|
|
section "INSERTING, FETCHING AND MODIFYING DATA" above or (JSprite(3)). |
546
|
|
|
|
|
|
|
|
547
|
|
|
|
|
|
|
=head1 OTHER SUPPORTING UTILITIES |
548
|
|
|
|
|
|
|
|
549
|
|
|
|
|
|
|
B |
550
|
|
|
|
|
|
|
|
551
|
|
|
|
|
|
|
This utility lets you build new Sprite databases and later add |
552
|
|
|
|
|
|
|
additional user-spaces to them. Simply cd to the directory where |
553
|
|
|
|
|
|
|
you wish to create / modify a database, and run. It prompts as |
554
|
|
|
|
|
|
|
follows: |
555
|
|
|
|
|
|
|
|
556
|
|
|
|
|
|
|
Database name: Enter a 1-word name for your database. |
557
|
|
|
|
|
|
|
Database user: Enter a 1-word user-name. |
558
|
|
|
|
|
|
|
User password: Enter a 1-word password for this user. |
559
|
|
|
|
|
|
|
Database path: Enter a path (no trailing backslash) to store tables. |
560
|
|
|
|
|
|
|
Table file extension (default .stb): |
561
|
|
|
|
|
|
|
Record delimiter (default \n): |
562
|
|
|
|
|
|
|
Field delimiter (default ::): |
563
|
|
|
|
|
|
|
|
564
|
|
|
|
|
|
|
The last 6 prompts repeat until you do not enter another user-name |
565
|
|
|
|
|
|
|
allowing you to set up multiple users in a single database. Each |
566
|
|
|
|
|
|
|
"user" can have it's own separate tables by specifying different |
567
|
|
|
|
|
|
|
paths, file-extensions, password, and delimiters! You can invoke |
568
|
|
|
|
|
|
|
"makesdb.pl" on an existing database to add new users. You can |
569
|
|
|
|
|
|
|
edit it with vi to remove users, delete the 5 lines starting with |
570
|
|
|
|
|
|
|
the path for that user. The file is all text, except for the |
571
|
|
|
|
|
|
|
password, which is encrypted for your protection! |
572
|
|
|
|
|
|
|
|
573
|
|
|
|
|
|
|
=head1 RESTRICTIONS |
574
|
|
|
|
|
|
|
|
575
|
|
|
|
|
|
|
Although DBD::Sprite supports the following datatypes: |
576
|
|
|
|
|
|
|
NUMBER FLOAT DOUBLE INT INTEGER NUM CHAR VARCHAR VARCHAR2 |
577
|
|
|
|
|
|
|
DATE LONG BLOB and MEMO, there are really only 4 basic datatypes |
578
|
|
|
|
|
|
|
(NUMBER, CHAR, VARCHAR, and BLOB). This is because Perl treates |
579
|
|
|
|
|
|
|
everything as simple strings. The first 5 are all treated as "numbers" |
580
|
|
|
|
|
|
|
by Perl for sorting purposes and the rest as strings. This is seen |
581
|
|
|
|
|
|
|
when sorting, ie NUMERIC types sort as 1,5,10,40,200, whereas |
582
|
|
|
|
|
|
|
STRING types sort these as 1,10,200,40,5. CHAR fields are right- |
583
|
|
|
|
|
|
|
padded with spaces when stored. LONG-type fields are subject to |
584
|
|
|
|
|
|
|
truncation by the "LongReadLen" attribute value. |
585
|
|
|
|
|
|
|
|
586
|
|
|
|
|
|
|
DBD::Sprite works with the tieDBI module, if "Sprite => 1" lines are added |
587
|
|
|
|
|
|
|
to the "%CAN_BIND" and "%CAN_BINDSELECT" hashes. This should not be |
588
|
|
|
|
|
|
|
necessary, and I will investigate when I have time. |
589
|
|
|
|
|
|
|
|
590
|
|
|
|
|
|
|
=head1 KNOWN BUGS |
591
|
|
|
|
|
|
|
|
592
|
|
|
|
|
|
|
* The module is using flock() internally. However, this function is |
593
|
|
|
|
|
|
|
not available on platforms. Using flock() is disabled on MacOS |
594
|
|
|
|
|
|
|
and Windows 95: There's no locking at all (perhaps not so |
595
|
|
|
|
|
|
|
important on these operating systems, as they are for single |
596
|
|
|
|
|
|
|
users anyways). |
597
|
|
|
|
|
|
|
|
598
|
|
|
|
|
|
|
|
599
|
|
|
|
|
|
|
=head1 SEE ALSO |
600
|
|
|
|
|
|
|
|
601
|
|
|
|
|
|
|
B, B |
602
|
|
|
|
|
|
|
|
603
|
|
|
|
|
|
|
=cut |
604
|
|
|
|
|
|
|
|
605
|
|
|
|
|
|
|
package DBD::Sprite; |
606
|
|
|
|
|
|
|
|
607
|
|
|
|
|
|
|
#no warnings 'uninitialized'; |
608
|
|
|
|
|
|
|
|
609
|
1
|
|
|
1
|
|
2164
|
use strict; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
46
|
|
610
|
|
|
|
|
|
|
#use vars qw($VERSION @ISA @EXPORT @EXPORT_OK); |
611
|
1
|
|
|
1
|
|
7
|
use vars qw($VERSION $err $errstr $state $sqlstate $drh $i $j $dbcnt); |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
253
|
|
612
|
|
|
|
|
|
|
|
613
|
|
|
|
|
|
|
#require Exporter; |
614
|
|
|
|
|
|
|
|
615
|
|
|
|
|
|
|
#@ISA = qw(Exporter AutoLoader); |
616
|
|
|
|
|
|
|
# Items to export into callers namespace by default. Note: do not export |
617
|
|
|
|
|
|
|
# names by default without a very good reason. Use EXPORT_OK instead. |
618
|
|
|
|
|
|
|
# Do not simply export all your public functions/methods/constants. |
619
|
|
|
|
|
|
|
#@EXPORT = qw( |
620
|
|
|
|
|
|
|
|
621
|
|
|
|
|
|
|
#); |
622
|
|
|
|
|
|
|
$VERSION = '6.12'; |
623
|
|
|
|
|
|
|
|
624
|
|
|
|
|
|
|
# Preloaded methods go here. |
625
|
|
|
|
|
|
|
|
626
|
|
|
|
|
|
|
$err = 0; # holds error code for DBI::err |
627
|
|
|
|
|
|
|
$errstr = ''; # holds error string for DBI::errstr |
628
|
|
|
|
|
|
|
$sqlstate = ''; |
629
|
|
|
|
|
|
|
$drh = undef; # holds driver handle once initialised |
630
|
|
|
|
|
|
|
|
631
|
|
|
|
|
|
|
sub driver{ |
632
|
1
|
50
|
|
1
|
0
|
378614
|
return $drh if $drh; |
633
|
1
|
|
|
|
|
6
|
my($class, $attr) = @_; |
634
|
|
|
|
|
|
|
|
635
|
1
|
|
|
|
|
8
|
$class .= "::dr"; |
636
|
|
|
|
|
|
|
|
637
|
|
|
|
|
|
|
# not a 'my' since we use it above to prevent multiple drivers |
638
|
1
|
|
|
|
|
53
|
$drh = DBI::_new_drh($class, { 'Name' => 'Sprite', |
639
|
|
|
|
|
|
|
'Version' => $VERSION, |
640
|
|
|
|
|
|
|
'Err' => \$DBD::Sprite::err, |
641
|
|
|
|
|
|
|
'Errstr' => \$DBD::Sprite::errstr, |
642
|
|
|
|
|
|
|
'State' => \$DBD::Sprite::state, |
643
|
|
|
|
|
|
|
'Attribution' => 'DBD::Sprite by Shishir Gurdavaram & Jim Turner', |
644
|
|
|
|
|
|
|
}); |
645
|
1
|
|
|
|
|
87
|
$drh; |
646
|
|
|
|
|
|
|
} |
647
|
|
|
|
|
|
|
|
648
|
|
|
|
|
|
|
sub DESTROY #ADDED 20001108 |
649
|
|
|
|
0
|
|
|
{ |
650
|
|
|
|
|
|
|
} |
651
|
|
|
|
|
|
|
|
652
|
|
|
|
|
|
|
#sub AUTOLOAD { |
653
|
|
|
|
|
|
|
# print "***** AUTOLOAD CALLED! *****\n"; |
654
|
|
|
|
|
|
|
#} |
655
|
|
|
|
|
|
|
|
656
|
|
|
|
|
|
|
1; |
657
|
|
|
|
|
|
|
|
658
|
|
|
|
|
|
|
|
659
|
|
|
|
|
|
|
package DBD::Sprite::dr; # ====== DRIVER ====== |
660
|
1
|
|
|
1
|
|
7
|
use strict; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
38
|
|
661
|
1
|
|
|
1
|
|
6
|
use vars qw($imp_data_size); |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
1601
|
|
662
|
|
|
|
|
|
|
|
663
|
|
|
|
|
|
|
$DBD::Sprite::dr::imp_data_size = 0; |
664
|
|
|
|
|
|
|
|
665
|
|
|
|
|
|
|
sub connect { |
666
|
1
|
|
|
1
|
|
214
|
my($drh, $dbname, $dbuser, $dbpswd, $attr, $old_driver, $connect_meth) = @_; |
667
|
|
|
|
|
|
|
|
668
|
|
|
|
|
|
|
#DON'T PASS ATTRIBUTES IN AS A STRING, MUST BE A HASH-REF! |
669
|
|
|
|
|
|
|
|
670
|
1
|
|
|
|
|
2
|
my($port); |
671
|
1
|
|
|
|
|
7
|
my($cWarn, $i, $j); |
672
|
|
|
|
|
|
|
|
673
|
1
|
|
|
|
|
14
|
$_ = ''; #ONLY WAY I KNOW HOW TO RETURN ERRORS FROM HERE ($DBI::err WON'T WORK!) |
674
|
|
|
|
|
|
|
|
675
|
|
|
|
|
|
|
# Avoid warnings for undefined values |
676
|
1
|
|
50
|
|
|
5
|
$dbuser ||= ''; |
677
|
1
|
|
50
|
|
|
4
|
$dbpswd ||= ''; |
678
|
|
|
|
|
|
|
|
679
|
|
|
|
|
|
|
# create a 'blank' dbh |
680
|
1
|
|
|
|
|
27
|
my($privateattr) = { |
681
|
|
|
|
|
|
|
'Name' => $dbname, |
682
|
|
|
|
|
|
|
'user' => $dbuser, |
683
|
|
|
|
|
|
|
'dbpswd' => $dbpswd |
684
|
|
|
|
|
|
|
}; |
685
|
|
|
|
|
|
|
#if (!defined($this = DBI::_new_dbh($drh, { |
686
|
1
|
|
|
|
|
29
|
my $this = DBI::_new_dbh($drh, { |
687
|
|
|
|
|
|
|
'Name' => $dbname, |
688
|
|
|
|
|
|
|
'USER' => $dbuser, |
689
|
|
|
|
|
|
|
'CURRENT_USER' => $dbuser, |
690
|
|
|
|
|
|
|
}); |
691
|
|
|
|
|
|
|
|
692
|
|
|
|
|
|
|
# Call Sprite Connect function |
693
|
|
|
|
|
|
|
# and populate internal handle data. |
694
|
1
|
50
|
|
|
|
84
|
if ($this) #ADDED 20010226 TO FIX BAD ERROR MESSAGE HANDLING IF INVALID UN/PW ENTERED. |
695
|
|
|
|
|
|
|
{ |
696
|
1
|
|
|
|
|
4
|
my $dbfid = $dbname; |
697
|
1
|
50
|
|
|
|
15
|
$dbfid .= '.sdb' unless ($dbfid =~ /\.\w+$/); |
698
|
1
|
|
50
|
|
|
30
|
$ENV{SPRITE_HOME} ||= ''; |
699
|
1
|
50
|
|
|
|
6
|
if ($dbfid =~ m#^/#) |
700
|
|
|
|
|
|
|
{ |
701
|
0
|
0
|
|
|
|
0
|
unless (open(DBFILE, "<$dbfid")) |
702
|
|
|
|
|
|
|
{ |
703
|
|
|
|
|
|
|
#DBI::set_err($this, -1, "No such database ($dbname)!"); #REPLACED W/NEXT LINE 20021021! |
704
|
0
|
0
|
|
|
|
0
|
warn "No such database ($dbname)!" if ($attr->{PrintError}); |
705
|
0
|
|
|
|
|
0
|
$_ = "-1:No such database ($dbname)!"; |
706
|
0
|
|
|
|
|
0
|
return undef; |
707
|
|
|
|
|
|
|
} |
708
|
|
|
|
|
|
|
} |
709
|
|
|
|
|
|
|
else |
710
|
|
|
|
|
|
|
{ |
711
|
1
|
50
|
|
|
|
133
|
unless (open(DBFILE, "<$ENV{SPRITE_HOME}/$dbfid")) |
712
|
|
|
|
|
|
|
{ |
713
|
1
|
50
|
|
|
|
45
|
unless (open(DBFILE, "<$dbfid")) |
714
|
|
|
|
|
|
|
{ |
715
|
0
|
0
|
|
|
|
0
|
unless (open(DBFILE, "<$ENV{HOME}/$dbfid")) #NEXT 4 ADDED 20040909 |
716
|
|
|
|
|
|
|
{ |
717
|
0
|
|
|
|
|
0
|
my $pgmhome = $0; |
718
|
0
|
|
|
|
|
0
|
$pgmhome =~ s#[^/\\]*$##; #SET NAME TO SQL.PL FOR ORAPERL! |
719
|
0
|
|
0
|
|
|
0
|
$pgmhome ||= '.'; |
720
|
0
|
0
|
0
|
|
|
0
|
$pgmhome .= '/' unless ($pgmhome =~ m#\/$# || $dbfid =~ m#^\/#); |
721
|
0
|
0
|
|
|
|
0
|
unless (open(DBFILE, "<${pgmhome}$dbfid")) |
722
|
|
|
|
|
|
|
{ |
723
|
0
|
|
|
|
|
0
|
$_ = "-1:No such database ($dbname) ($!)!"; |
724
|
0
|
|
|
|
|
0
|
DBI::set_err($this, -1, $_); #REPLACED W/NEXT LINE 20021021! |
725
|
0
|
0
|
|
|
|
0
|
warn $DBI::errstr if ($attr->{PrintError}); |
726
|
0
|
|
|
|
|
0
|
return undef; |
727
|
|
|
|
|
|
|
} |
728
|
|
|
|
|
|
|
} |
729
|
|
|
|
|
|
|
} |
730
|
|
|
|
|
|
|
} |
731
|
|
|
|
|
|
|
} |
732
|
1
|
|
|
|
|
30
|
my (@dbinputs) = ; |
733
|
1
|
|
|
|
|
14
|
foreach $i (0..$#dbinputs) |
734
|
|
|
|
|
|
|
{ |
735
|
5
|
|
|
|
|
20
|
chomp ($dbinputs[$i]); |
736
|
|
|
|
|
|
|
} |
737
|
1
|
|
|
|
|
4
|
my ($inputcnt) = $#dbinputs; |
738
|
1
|
|
|
|
|
2
|
my ($dfltattrs, %dfltattr); |
739
|
1
|
|
|
|
|
5
|
for ($i=0;$i<=$inputcnt;$i+=5) #SHIFT OFF LINES UNTIL RIGHT USER FOUND. |
740
|
|
|
|
|
|
|
{ |
741
|
1
|
50
|
|
|
|
15
|
last if ($dbinputs[1] eq $dbuser); |
742
|
0
|
0
|
|
|
|
0
|
if ($dbinputs[1] =~ s/^$dbuser\:(.*)/$dbuser/) |
743
|
|
|
|
|
|
|
{ |
744
|
0
|
|
|
|
|
0
|
$dfltattrs = $1; |
745
|
0
|
|
|
|
|
0
|
eval "\%dfltattr = ($dfltattrs)"; |
746
|
0
|
|
|
|
|
0
|
foreach my $j (keys %dfltattr) |
747
|
|
|
|
|
|
|
{ |
748
|
|
|
|
|
|
|
#$attr->{$j} = $dfltattr{$j}; #CHGD. TO NEXT 20030207 |
749
|
0
|
0
|
|
|
|
0
|
$attr->{$j} = $dfltattr{$j} unless (defined $attr->{$j}); |
750
|
|
|
|
|
|
|
} |
751
|
0
|
|
|
|
|
0
|
last; |
752
|
|
|
|
|
|
|
} |
753
|
0
|
|
|
|
|
0
|
for ($j=0;$j<=4;$j++) |
754
|
|
|
|
|
|
|
{ |
755
|
0
|
|
|
|
|
0
|
shift (@dbinputs); |
756
|
|
|
|
|
|
|
} |
757
|
|
|
|
|
|
|
} |
758
|
|
|
|
|
|
|
#foreach my $x (keys %{$attr}) { print STDERR "-attr($x)=$attr->{$x}=\n"; }; |
759
|
1
|
50
|
|
|
|
5
|
if ($dbinputs[1] eq $dbuser) |
760
|
|
|
|
|
|
|
{ |
761
|
|
|
|
|
|
|
#if ($dbinputs[2] eq crypt($dbpswd, substr($dbuser,0,2))) |
762
|
1
|
|
|
|
|
3
|
my ($crypted); |
763
|
1
|
|
|
|
|
3
|
eval { $crypted = crypt($dbpswd, substr($dbuser,0,2)); }; |
|
1
|
|
|
|
|
550
|
|
764
|
1
|
50
|
33
|
|
|
8
|
if ($dbinputs[2] eq $crypted || $@ =~ /excessive paranoia/) |
765
|
|
|
|
|
|
|
{ |
766
|
1
|
|
|
|
|
3
|
++$DBD::Sprite::dbcnt; |
767
|
1
|
|
|
|
|
38
|
$this->STORE('sprite_dbname',$dbname); |
768
|
1
|
|
|
|
|
7
|
$this->STORE('sprite_dbuser',$dbuser); |
769
|
1
|
|
|
|
|
5
|
$this->STORE('sprite_dbpswd',$dbpswd); |
770
|
1
|
|
|
|
|
13
|
close (DBFILE); |
771
|
|
|
|
|
|
|
#$this->STORE('sprite_autocommit',0); #CHGD TO NEXT 20010912. |
772
|
1
|
|
50
|
|
|
19
|
$this->STORE('sprite_autocommit',($attr->{AutoCommit} || 0)); |
773
|
1
|
|
|
|
|
5
|
$this->STORE('sprite_SpritesOpen',{}); |
774
|
1
|
|
|
|
|
3
|
my ($t) = $dbinputs[0]; |
775
|
1
|
|
|
|
|
10
|
$t =~ s#(.*)/.*#$1#; |
776
|
1
|
50
|
|
|
|
7
|
if ($dbinputs[0] =~ /(.*)(\..*)/) |
777
|
|
|
|
|
|
|
{ |
778
|
1
|
|
|
|
|
6
|
$this->STORE('sprite_dbdir', $t); |
779
|
1
|
|
|
|
|
5
|
$this->STORE('sprite_dbext', $2); |
780
|
|
|
|
|
|
|
} |
781
|
|
|
|
|
|
|
else |
782
|
|
|
|
|
|
|
{ |
783
|
0
|
|
|
|
|
0
|
$this->STORE('sprite_dbdir', $dbinputs[0]); |
784
|
0
|
|
|
|
|
0
|
$this->STORE('sprite_dbext', '.stb'); |
785
|
|
|
|
|
|
|
} |
786
|
1
|
|
|
|
|
6
|
for (my $i=0;$i<=$#dbinputs;$i++) |
787
|
|
|
|
|
|
|
{ |
788
|
5
|
|
|
|
|
14
|
$dbinputs[$i] =~ /^(.*)$/; |
789
|
5
|
|
|
|
|
14
|
$dbinputs[$i] = $1; |
790
|
|
|
|
|
|
|
} |
791
|
1
|
|
50
|
|
|
82
|
$this->STORE('sprite_dbfdelim', $attr->{sprite_read} || $attr->{sprite_field} || eval("return(\"$dbinputs[3]\");") || '::'); |
792
|
1
|
|
50
|
|
|
54
|
$this->STORE('sprite_dbwdelim', $attr->{sprite_write} || $attr->{sprite_field} || eval("return(\"$dbinputs[3]\");") || '::'); |
793
|
1
|
|
50
|
|
|
221
|
$this->STORE('sprite_dbrdelim', $attr->{sprite_record} || eval("return(\"$dbinputs[4]\");") || "\n"); |
794
|
1
|
|
|
|
|
5
|
$this->STORE('sprite_attrhref', $attr); |
795
|
1
|
|
50
|
|
|
17
|
$this->STORE('AutoCommit', ($attr->{AutoCommit} || 0)); |
796
|
|
|
|
|
|
|
|
797
|
1
|
|
50
|
|
|
13
|
$this->STORE('sprite_autocommit',($attr->{AutoCommit} || 0)); |
798
|
|
|
|
|
|
|
|
799
|
|
|
|
|
|
|
#NOTE: "PrintError" and "AutoCommit" are ON by DEFAULT! |
800
|
|
|
|
|
|
|
#I KNOW OF NO WAY TO DETECT WHETHER AUTOCOMMIT IS SET BY |
801
|
|
|
|
|
|
|
#DEFAULT OR BY USER IN "AutoCommit => 1", THEREFORE I CAN'T |
802
|
|
|
|
|
|
|
#FORCE THE DEFAULT TO ZERO. JWT |
803
|
|
|
|
|
|
|
|
804
|
1
|
|
|
|
|
8
|
return $this; |
805
|
|
|
|
|
|
|
} |
806
|
|
|
|
|
|
|
} |
807
|
|
|
|
|
|
|
} |
808
|
0
|
|
|
|
|
0
|
close (DBFILE); |
809
|
|
|
|
|
|
|
#DBI::set_err($this, -1, "Invalid username/password!"); #REPLACED W/NEXT LINE 20021021! |
810
|
0
|
0
|
|
|
|
0
|
warn "Invalid username/password!" if ($attr->{PrintError}); |
811
|
0
|
|
|
|
|
0
|
$_ = "-1:Invalid username/password!"; |
812
|
0
|
|
|
|
|
0
|
return undef; |
813
|
|
|
|
|
|
|
} |
814
|
|
|
|
|
|
|
|
815
|
|
|
|
|
|
|
sub data_sources |
816
|
|
|
|
|
|
|
{ |
817
|
1
|
|
|
1
|
|
58
|
my ($self) = shift; |
818
|
|
|
|
|
|
|
|
819
|
1
|
|
|
|
|
8
|
my (@dsources) = (); |
820
|
1
|
|
|
|
|
4
|
my $path; |
821
|
1
|
50
|
|
|
|
7
|
if (defined $ENV{SPRITE_HOME}) |
822
|
|
|
|
|
|
|
{ |
823
|
0
|
|
|
|
|
0
|
$path = "$ENV{SPRITE_HOME}/*.sdb"; |
824
|
0
|
|
|
|
|
0
|
my $code = "while (my \$i = <$path>)\n"; |
825
|
0
|
|
|
|
|
0
|
$code .= <<'END_CODE'; |
826
|
|
|
|
|
|
|
{ |
827
|
|
|
|
|
|
|
chomp ($i); |
828
|
|
|
|
|
|
|
push (@dsources,"DBI:Sprite:$1") if ($i =~ m#([^\/\.]+)\.sdb$#); |
829
|
|
|
|
|
|
|
} |
830
|
|
|
|
|
|
|
END_CODE |
831
|
0
|
|
|
|
|
0
|
eval $code; |
832
|
0
|
|
|
|
|
0
|
$code =~ s/\.sdb([\>\$])/\.SDB$1/g; #HANDLE WINDOWSEY FILENAMES :( |
833
|
0
|
|
|
|
|
0
|
eval $code; |
834
|
|
|
|
|
|
|
} |
835
|
1
|
|
|
|
|
9
|
$path = '*.sdb'; |
836
|
1
|
|
|
|
|
6
|
my $code = "while (my \$i = <$path>)\n"; |
837
|
1
|
|
|
|
|
9
|
$code .= <<'END_CODE'; |
838
|
|
|
|
|
|
|
{ |
839
|
|
|
|
|
|
|
chomp ($i); |
840
|
|
|
|
|
|
|
push (@dsources,"DBI:Sprite:$1") if ($i =~ m#([^\/\.]+)\.sdb$#); |
841
|
|
|
|
|
|
|
} |
842
|
|
|
|
|
|
|
END_CODE |
843
|
1
|
|
|
|
|
290
|
eval $code; |
844
|
1
|
|
|
|
|
30
|
$code =~ s/\.sdb([\>\$])/\.SDB$1/g; #HANDLE WINDOWSEY FILENAMES :( |
845
|
1
|
|
|
|
|
142
|
eval $code; |
846
|
1
|
50
|
|
|
|
8
|
unless (@dsources) |
847
|
|
|
|
|
|
|
{ |
848
|
0
|
0
|
|
|
|
0
|
if (defined $ENV{HOME}) |
849
|
|
|
|
|
|
|
{ |
850
|
0
|
|
|
|
|
0
|
$path = "$ENV{HOME}/*.sdb"; |
851
|
0
|
|
|
|
|
0
|
my $code = "while (my \$i = <$path>)\n"; |
852
|
0
|
|
|
|
|
0
|
$code .= <<'END_CODE'; |
853
|
|
|
|
|
|
|
{ |
854
|
|
|
|
|
|
|
chomp ($i); |
855
|
|
|
|
|
|
|
push (@dsources,"DBI:Sprite:$1") if ($i =~ m#([^\/\.]+)\.sdb$#); |
856
|
|
|
|
|
|
|
} |
857
|
|
|
|
|
|
|
END_CODE |
858
|
0
|
|
|
|
|
0
|
eval $code; |
859
|
0
|
|
|
|
|
0
|
$code =~ s/\.sdb([\>\$])/\.SDB$1/g; #HANDLE WINDOWSEY FILENAMES :( |
860
|
0
|
|
|
|
|
0
|
eval $code; |
861
|
|
|
|
|
|
|
} |
862
|
|
|
|
|
|
|
} |
863
|
1
|
|
|
|
|
18
|
return (@dsources); |
864
|
|
|
|
|
|
|
} |
865
|
|
|
|
|
|
|
|
866
|
|
|
|
|
|
|
sub DESTROY |
867
|
|
|
|
|
|
|
{ |
868
|
0
|
|
|
0
|
|
0
|
my($drh) = shift; |
869
|
|
|
|
|
|
|
|
870
|
|
|
|
|
|
|
# if ($drh->FETCH('AutoCommit') == 1) #REMOVED 20020225 TO ELIMINATE -w WARNING. |
871
|
|
|
|
|
|
|
# { |
872
|
|
|
|
|
|
|
# $drh->STORE('AutoCommit',0); |
873
|
|
|
|
|
|
|
# $drh->rollback(); #COMMIT IT IF AUTOCOMMIT ON! |
874
|
|
|
|
|
|
|
# $drh->STORE('AutoCommit',1); |
875
|
|
|
|
|
|
|
# } |
876
|
0
|
|
|
|
|
0
|
$drh = undef; |
877
|
|
|
|
|
|
|
} |
878
|
|
|
|
|
|
|
|
879
|
|
|
|
|
|
|
sub disconnect_all |
880
|
|
|
|
1
|
|
|
{ |
881
|
|
|
|
|
|
|
} |
882
|
|
|
|
|
|
|
|
883
|
|
|
|
|
|
|
sub admin { #I HAVE NO IDEA WHAT THIS DOES! |
884
|
0
|
|
|
0
|
|
0
|
my($drh) = shift; |
885
|
0
|
|
|
|
|
0
|
my($command) = shift; |
886
|
|
|
|
|
|
|
|
887
|
0
|
0
|
0
|
|
|
0
|
my($dbname) = ($command eq 'createdb' || $command eq 'dropdb') ? |
888
|
|
|
|
|
|
|
shift : ''; |
889
|
0
|
|
0
|
|
|
0
|
my($host, $port) = DBD::Sprite->_OdbcParseHost(shift(@_) || ''); |
890
|
0
|
|
0
|
|
|
0
|
my($user) = shift || ''; |
891
|
0
|
|
0
|
|
|
0
|
my($password) = shift || ''; |
892
|
|
|
|
|
|
|
|
893
|
0
|
|
0
|
|
|
0
|
$drh->func(undef, $command, |
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
894
|
|
|
|
|
|
|
$dbname || '', |
895
|
|
|
|
|
|
|
$host || '', |
896
|
|
|
|
|
|
|
$port || '', |
897
|
|
|
|
|
|
|
$user, $password, '_admin_internal'); |
898
|
|
|
|
|
|
|
} |
899
|
|
|
|
|
|
|
|
900
|
|
|
|
|
|
|
1; |
901
|
|
|
|
|
|
|
|
902
|
|
|
|
|
|
|
|
903
|
|
|
|
|
|
|
package DBD::Sprite::db; # ====== DATABASE ====== |
904
|
1
|
|
|
1
|
|
10
|
use strict; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
26
|
|
905
|
1
|
|
|
1
|
|
942
|
use JSprite; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
49
|
|
906
|
|
|
|
|
|
|
|
907
|
|
|
|
|
|
|
$DBD::Sprite::db::imp_data_size = 0; |
908
|
1
|
|
|
1
|
|
9
|
use vars qw($imp_data_size); |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
4147
|
|
909
|
|
|
|
|
|
|
|
910
|
|
|
|
|
|
|
sub last_insert_id #MUST BE CALLED W/"$dbh->func"! ADDED 20040407 TO SUPPORT NEW DBI FUNCTION. |
911
|
|
|
|
|
|
|
{ |
912
|
0
|
|
|
0
|
|
0
|
my ($resptr, $cat, $schema, $tablename, $seqfield) = @_; |
913
|
0
|
0
|
0
|
|
|
0
|
return $resptr->{sprite_insertid} if (defined $resptr->{sprite_insertid} && $resptr->{sprite_insertid} =~ /\d$/); |
914
|
0
|
|
|
|
|
0
|
my $mycsr; |
915
|
0
|
0
|
|
|
|
0
|
if ($mycsr = $resptr->prepare("select ${seqfield}.CURRVAL from DUAL")) |
916
|
|
|
|
|
|
|
{ |
917
|
0
|
|
|
|
|
0
|
my $myexe; |
918
|
0
|
0
|
|
|
|
0
|
if ($myexe = $mycsr->execute()) |
919
|
|
|
|
|
|
|
{ |
920
|
0
|
|
|
|
|
0
|
my ($lastseq) = $mycsr->fetchrow_array(); |
921
|
0
|
|
|
|
|
0
|
$mycsr->finish(); |
922
|
|
|
|
|
|
|
###return $lastseq if ($lastseq =~ /\d$/); #CHGD. TO NEXT 20061006 TO HANDLE ERRORS, IE. WHEN SEQ IS AN AUTONUMBER, NOT A SEQ! |
923
|
0
|
0
|
0
|
|
|
0
|
return $lastseq if ($lastseq =~ /\d$/ && $lastseq > 0); |
924
|
|
|
|
|
|
|
} |
925
|
|
|
|
|
|
|
} |
926
|
0
|
0
|
|
|
|
0
|
if ($seqfield) #IF ALL ELSE FAILS, FETCH A DESCENDING LIST OF VALUES FOR THE FIELD THE SEQUENCE WAS INSERTED INTO (USER MUST SPECIFY THE FIELD!) |
927
|
|
|
|
|
|
|
{ |
928
|
0
|
|
|
|
|
0
|
my $sql = <
|
929
|
|
|
|
|
|
|
select $seqfield |
930
|
|
|
|
|
|
|
from $tablename |
931
|
|
|
|
|
|
|
order by $seqfield desc |
932
|
|
|
|
|
|
|
END_SQL |
933
|
0
|
0
|
|
|
|
0
|
if ($mycsr = $resptr->prepare($sql)) |
934
|
|
|
|
|
|
|
{ |
935
|
0
|
|
|
|
|
0
|
my $myexe; |
936
|
0
|
0
|
|
|
|
0
|
if ($myexe = $mycsr->execute()) |
937
|
|
|
|
|
|
|
{ |
938
|
0
|
|
|
|
|
0
|
my ($lastseq) = $mycsr->fetchrow_array(); |
939
|
0
|
|
|
|
|
0
|
$mycsr->finish(); |
940
|
0
|
|
|
|
|
0
|
return $lastseq; |
941
|
|
|
|
|
|
|
} |
942
|
|
|
|
|
|
|
else |
943
|
|
|
|
|
|
|
{ |
944
|
0
|
|
|
|
|
0
|
return undef; |
945
|
|
|
|
|
|
|
} |
946
|
|
|
|
|
|
|
} |
947
|
0
|
|
|
|
|
0
|
return undef; |
948
|
|
|
|
|
|
|
} |
949
|
0
|
|
|
|
|
0
|
return undef; |
950
|
|
|
|
|
|
|
} |
951
|
|
|
|
|
|
|
|
952
|
|
|
|
|
|
|
sub Statement #MUST BE CALLED W/"dbh->func([undef, undef, 'tablename', 'seq/field name',] 'last_insert_id')"! ADDED 20040407 TO SUPPORT NEW DBI FUNCTION. |
953
|
|
|
|
|
|
|
{ |
954
|
0
|
0
|
|
0
|
|
0
|
return undef unless ($_[0]); |
955
|
0
|
|
|
|
|
0
|
return $_[0]->FETCH('sprite_last_prepare_sql'); |
956
|
|
|
|
|
|
|
} |
957
|
|
|
|
|
|
|
|
958
|
|
|
|
|
|
|
sub prepare |
959
|
|
|
|
|
|
|
{ |
960
|
11
|
|
|
11
|
|
251
|
my ($resptr, $sqlstr, $attribs) = @_; |
961
|
11
|
|
|
|
|
21
|
my ($indx, @QS); |
962
|
11
|
|
|
|
|
19
|
local ($_); |
963
|
|
|
|
|
|
|
#$sqlstr =~ s/\n/ /g; #REMOVED 20011107. |
964
|
|
|
|
|
|
|
|
965
|
|
|
|
|
|
|
#DBI::set_err($resptr, 0, ''); #CHGD. TO NEXT 20041104. |
966
|
11
|
|
|
|
|
44
|
DBI::set_err($resptr, undef); |
967
|
|
|
|
|
|
|
|
968
|
11
|
50
|
|
|
|
113
|
my $limit = ($sqlstr =~ s/^(.+)\s*limit\s+(\d+)\s*$/$1/i) ? $2 : 0; #ADDED 20160111 TO SUPPORT "limit #" ON QUERIES. |
969
|
11
|
|
|
|
|
57
|
$sqlstr =~ s/^\s*listfields\s+(\w+)/select * from $1 where 1 = 0/i; #ADDED 20030901. |
970
|
11
|
|
|
|
|
89
|
my $csr = DBI::_new_sth($resptr, { |
971
|
|
|
|
|
|
|
'Statement' => $sqlstr, |
972
|
|
|
|
|
|
|
}); |
973
|
|
|
|
|
|
|
|
974
|
11
|
|
|
|
|
378
|
my ($spritefid); |
975
|
11
|
|
|
|
|
43
|
$resptr->STORE('sprite_last_prepare_sql', $sqlstr); |
976
|
11
|
|
|
|
|
75
|
$csr->STORE('sprite_fetchcnt', 0); |
977
|
11
|
|
|
|
|
29
|
$csr->STORE('sprite_reslinev',''); |
978
|
11
|
|
|
|
|
40
|
$sqlstr =~ s/\\\'|\'\'/\x02\^3jSpR1tE\x02/gso; #PROTECT "\'" IN QUOTES. |
979
|
11
|
|
|
|
|
25
|
$sqlstr =~ s/\\\"|\"\"/\x02\^4jSpR1tE\x02/gso; #PROTECT "\"" IN QUOTES. |
980
|
11
|
|
|
|
|
21
|
$indx = 0; |
981
|
11
|
|
|
|
|
45
|
$indx++ while ($sqlstr =~ s/([\'\"])([^\1]*?)\1/ |
982
|
6
|
|
|
|
|
23
|
$QS[$indx] = "$1$2"; "\$QS\[$indx]"/e); |
|
6
|
|
|
|
|
38
|
|
983
|
|
|
|
|
|
|
#$sqlstr =~ /(into|from|update|table) \s*(\w+)/gi; #CHANGED 20000831 TO NEXT LINE! |
984
|
|
|
|
|
|
|
#$sqlstr =~ /(into|from|update|table|sequence)\s+(\w+)/is; #CHGD. 20040305 TO NEXT. |
985
|
11
|
100
|
|
|
|
101
|
$spritefid = $2 if ($sqlstr =~ /(into|from|update|table|sequence)\s+(\w+)/ios); |
986
|
11
|
100
|
|
|
|
31
|
$spritefid = $1 if ($sqlstr =~ /primary_key_info\s+(\w+)/ios); |
987
|
11
|
50
|
|
|
|
23
|
unless ($spritefid) #ADDED 20061010 TO SUPPORT "select fn" (like MySQL, et al.) |
988
|
|
|
|
|
|
|
{ |
989
|
0
|
0
|
|
|
|
0
|
$spritefid = 'DUAL' if ($sqlstr =~ s/^(\s*select\s+\w+\s*)(\(.*\))?$/$1$2 from DUAL/is); |
990
|
|
|
|
|
|
|
} |
991
|
|
|
|
|
|
|
|
992
|
11
|
50
|
|
|
|
21
|
unless ($spritefid) #NEXT 5 ADDED 20000831! |
993
|
|
|
|
|
|
|
{ |
994
|
0
|
|
|
|
|
0
|
DBI::set_err($resptr, -1, "Prepare:(bad sql) Must specify a table name!"); |
995
|
0
|
|
|
|
|
0
|
return undef; |
996
|
|
|
|
|
|
|
} |
997
|
11
|
50
|
|
|
|
36
|
$spritefid =~ tr/A-Z/a-z/ unless ($resptr->{sprite_attrhref}->{sprite_CaseTableNames}); |
998
|
11
|
|
|
|
|
40
|
$csr->STORE('sprite_spritefid', $spritefid); |
999
|
|
|
|
|
|
|
|
1000
|
11
|
|
|
|
|
22
|
my $join = 0; |
1001
|
11
|
|
|
|
|
13
|
my $joininfo; |
1002
|
|
|
|
|
|
|
#$joininfo = $1 if ($sqlstr =~ /from\s+([\w\.\, ]+)\s*(?:where|order\s+by)/is); |
1003
|
|
|
|
|
|
|
#$joininfo = $1 if (!$joininfo && $sqlstr =~ /from\s+([\w\.\, ]+)/is); |
1004
|
|
|
|
|
|
|
#LAST 2 CHGD. TO NEXT 2 20040914. |
1005
|
11
|
100
|
|
|
|
50
|
$joininfo = $1 if ($sqlstr =~ /from\s+([\w\.\,\s]+)\s*(?:where|order\s+by)/iso); |
1006
|
11
|
100
|
100
|
|
|
96
|
$joininfo = $1 if (!$joininfo && $sqlstr =~ /from\s+([\w\.\,\s]+)/iso); |
1007
|
11
|
|
|
|
|
23
|
my @joinfids; |
1008
|
11
|
100
|
|
|
|
35
|
@joinfids = split(/\,\s*/o, $joininfo) if (defined $joininfo); |
1009
|
11
|
|
|
|
|
21
|
my (@joinfid, @joinalias); |
1010
|
11
|
50
|
|
|
|
26
|
if ($#joinfids >= 1) |
1011
|
|
|
|
|
|
|
{ |
1012
|
0
|
0
|
|
|
|
0
|
unless ($#joinfids == 1) |
1013
|
|
|
|
|
|
|
{ |
1014
|
0
|
|
|
|
|
0
|
DBI::set_err($resptr, -1, "Only 2-table joins currently supported!"); |
1015
|
0
|
|
|
|
|
0
|
return undef; |
1016
|
|
|
|
|
|
|
} |
1017
|
0
|
|
|
|
|
0
|
for (my $i=0;$i<=$#joinfids;$i++) |
1018
|
|
|
|
|
|
|
{ |
1019
|
0
|
|
|
|
|
0
|
($joinfid[$i], $joinalias[$i]) = split(/\s+/o, $joinfids[$i]); |
1020
|
0
|
|
0
|
|
|
0
|
$joinfid[$i] ||= $joinfids[$i]; |
1021
|
0
|
0
|
|
|
|
0
|
$joinfid[$i] =~ tr/A-Z/a-z/ unless ($resptr->{sprite_attrhref}->{sprite_CaseTableNames}); |
1022
|
|
|
|
|
|
|
} |
1023
|
0
|
|
|
|
|
0
|
$csr->STORE('sprite_joinfid', \@joinfid); |
1024
|
0
|
|
|
|
|
0
|
$csr->STORE('sprite_joinalias', \@joinalias); |
1025
|
0
|
|
|
|
|
0
|
$join = 1; |
1026
|
|
|
|
|
|
|
} |
1027
|
|
|
|
|
|
|
#CHECK TO SEE IF A PREVIOUSLY-CLOSED SPRITE OBJECT EXISTS FOR THIS TABLE. |
1028
|
|
|
|
|
|
|
#IF SET, THE "RECYCLE" OPTION TELLS SPRITE NOT TO RELOAD THE TABLE DATA. |
1029
|
|
|
|
|
|
|
#THIS IS USEFUL TO SAVE TIME AND MEMORY FOR APPS DOING MULTIPLE |
1030
|
|
|
|
|
|
|
#TRANSACTIONS ON SEVERAL LARGE TABLES. |
1031
|
|
|
|
|
|
|
#RELOADING IS NECESSARY, HOWEVER, IF ANOTHER USER CAN CHANGE THE |
1032
|
|
|
|
|
|
|
#DATA SINCE YOUR LAST COMMIT, SO RECYCLE IS OFF BY DEFAULT! |
1033
|
|
|
|
|
|
|
#THE SPRITE HANDLE AND ALL IT'S BASIC CONFIGURATION IS RECYCLED REGARDLESS. |
1034
|
11
|
|
|
|
|
100
|
my (@spritedbs) = (qw(sprite_spritedb sprite_joindb)); |
1035
|
11
|
|
|
|
|
17
|
my ($myspriteref); |
1036
|
11
|
|
|
|
|
15
|
my $i = 0; |
1037
|
11
|
|
|
|
|
19
|
$myspriteref = undef; |
1038
|
11
|
|
|
|
|
29
|
foreach my $fid ($spritefid, $joinfid[1]) |
1039
|
|
|
|
|
|
|
{ |
1040
|
22
|
100
|
|
|
|
47
|
last unless ($fid); |
1041
|
11
|
100
|
66
|
|
|
65
|
if (ref($resptr->{'sprite_SpritesOpen'}) && ref($resptr->{'sprite_SpritesOpen'}->{$fid})) |
1042
|
|
|
|
|
|
|
{ |
1043
|
8
|
|
|
|
|
12
|
$myspriteref = ${$resptr->{'sprite_SpritesOpen'}->{$fid}}; |
|
8
|
|
|
|
|
18
|
|
1044
|
8
|
|
|
|
|
17
|
$csr->STORE($spritedbs[$i], ${$resptr->{'sprite_SpritesOpen'}->{$fid}}); |
|
8
|
|
|
|
|
31
|
|
1045
|
8
|
|
|
|
|
33
|
$myspriteref->{TYPE} = undef; |
1046
|
8
|
|
|
|
|
21
|
$myspriteref->{NAME} = undef; |
1047
|
8
|
|
|
|
|
13
|
$myspriteref->{PRECISION} = undef; |
1048
|
8
|
|
|
|
|
17
|
$myspriteref->{SCALE} = undef; |
1049
|
|
|
|
|
|
|
} |
1050
|
|
|
|
|
|
|
else #CREATE A NEW SPRITE OBJECT. |
1051
|
|
|
|
|
|
|
{ |
1052
|
3
|
|
|
|
|
5
|
$myspriteref = new JSprite(%{$resptr->{sprite_attrhref}}); |
|
3
|
|
|
|
|
54
|
|
1053
|
3
|
50
|
|
|
|
12
|
unless ($myspriteref) |
1054
|
|
|
|
|
|
|
{ |
1055
|
0
|
|
|
|
|
0
|
DBI::set_err($resptr, -1, "Unable to create JSprite handle ($@)!"); |
1056
|
0
|
|
|
|
|
0
|
return undef; |
1057
|
|
|
|
|
|
|
} |
1058
|
3
|
|
|
|
|
19
|
$csr->STORE($spritedbs[$i], $myspriteref); |
1059
|
3
|
|
|
|
|
24
|
my ($openhash) = $resptr->FETCH('sprite_SpritesOpen'); |
1060
|
3
|
|
|
|
|
13
|
$openhash->{$fid} = \$myspriteref; |
1061
|
3
|
|
33
|
|
|
46
|
$myspriteref->set_delimiter("-read",($attribs->{sprite_read} || $attribs->{sprite_field} || $resptr->FETCH('sprite_dbfdelim'))); |
1062
|
3
|
|
33
|
|
|
41
|
$myspriteref->set_delimiter("-write",($attribs->{sprite_write} || $attribs->{sprite_field} || $resptr->FETCH('sprite_dbwdelim'))); |
1063
|
3
|
|
33
|
|
|
31
|
$myspriteref->set_delimiter("-record",($attribs->{sprite_record} || $attribs->{sprite_field} || $resptr->FETCH('sprite_dbrdelim'))); |
1064
|
3
|
|
|
|
|
24
|
$myspriteref->set_db_dir($resptr->FETCH('sprite_dbdir')); |
1065
|
3
|
|
|
|
|
23
|
$myspriteref->set_db_ext($resptr->FETCH('sprite_dbext')); |
1066
|
3
|
|
|
|
|
11
|
$myspriteref->{CaseTableNames} = $resptr->{sprite_attrhref}->{sprite_CaseTableNames}; |
1067
|
3
|
|
|
|
|
7
|
$myspriteref->{sprite_CaseFieldNames} = $resptr->{sprite_attrhref}->{sprite_CaseFieldNames}; |
1068
|
3
|
|
|
|
|
6
|
$myspriteref->{StrictCharComp} = $resptr->{sprite_attrhref}->{sprite_StrictCharComp}; |
1069
|
|
|
|
|
|
|
#DON'T NEED!#$myspriteref->{Crypt} = $resptr->{sprite_attrhref}->{sprite_Crypt}; #ADDED 20020109. |
1070
|
3
|
|
|
|
|
19
|
$myspriteref->{sprite_forcereplace} = $resptr->{sprite_attrhref}->{sprite_forcereplace}; #ADDED 20010912. |
1071
|
3
|
|
|
|
|
16
|
$myspriteref->{dbuser} = $resptr->FETCH('sprite_dbuser'); #ADDED 20011026. |
1072
|
3
|
|
|
|
|
11
|
$myspriteref->{dbname} = $resptr->FETCH('sprite_dbname'); #ADDED 20011026. |
1073
|
3
|
|
|
|
|
8
|
$myspriteref->{dbhandle} = $resptr; #ADDED 20020516 |
1074
|
|
|
|
|
|
|
} |
1075
|
11
|
|
|
|
|
47
|
$myspriteref->{LongTruncOk} = $resptr->FETCH('LongTruncOk'); |
1076
|
11
|
|
|
|
|
33
|
my ($silent) = $resptr->FETCH('PrintError'); |
1077
|
11
|
100
|
|
|
|
36
|
$myspriteref->{silent} = ($silent ? 0 : 1); #ADDED 20000103 TO SUPPRESS "OOPS" MSG ON WEBSITES! |
1078
|
11
|
50
|
|
|
|
32
|
$myspriteref->{sprite_reclimit} = (defined $attribs->{sprite_reclimit}) ? $attribs->{sprite_reclimit} : 0; #ADDED 20020123. |
1079
|
11
|
50
|
|
|
|
32
|
$myspriteref->{sprite_sizelimit} = (defined $attribs->{sprite_sizelimit}) ? $attribs->{sprite_sizelimit} : 0; #ADDED 20020530. |
1080
|
11
|
|
|
|
|
18
|
$myspriteref->{sprite_actlimit} = $limit; #ADDED 20160111 TO SUPPORT "limit #" ON QUERIES. |
1081
|
11
|
|
|
|
|
20
|
++$i; |
1082
|
|
|
|
|
|
|
} |
1083
|
|
|
|
|
|
|
|
1084
|
|
|
|
|
|
|
#PARSE OUT SQL IF JOIN. |
1085
|
|
|
|
|
|
|
|
1086
|
11
|
|
|
|
|
29
|
my $num_of_params; |
1087
|
|
|
|
|
|
|
my @bindindices; |
1088
|
11
|
|
|
|
|
0
|
my @joinsql; |
1089
|
11
|
50
|
|
|
|
20
|
if ($join) |
1090
|
|
|
|
|
|
|
{ |
1091
|
0
|
|
|
|
|
0
|
my ($whereclause, $joinfid); |
1092
|
0
|
|
|
|
|
0
|
my %addfields; #FIELDS IN UNION CRITERIA THAT MUST BE ADDED TO FETCH. |
1093
|
0
|
|
|
|
|
0
|
my @selectfields; #FIELD NAMES OF FIELDS TO BE FETCHED. |
1094
|
0
|
|
|
|
|
0
|
my $addthesefields; #COLLECT LIST OF FIELDS THAT ACTUALLY NEED ADDING. |
1095
|
0
|
|
|
|
|
0
|
my @union; #LIST OF FIELDS IN THE JOIN UNION(S). |
1096
|
0
|
|
|
|
|
0
|
my $listprefix; |
1097
|
|
|
|
|
|
|
|
1098
|
0
|
|
|
|
|
0
|
for (my $jj=0;$jj<=1;$jj++) |
1099
|
|
|
|
|
|
|
{ |
1100
|
0
|
|
|
|
|
0
|
$joinsql[$jj] = $sqlstr; |
1101
|
0
|
0
|
|
|
|
0
|
$joinfid = $joinalias[$jj] ? $joinalias[$jj] : $joinfid[$jj]; |
1102
|
0
|
|
|
|
|
0
|
%addfields = (); |
1103
|
|
|
|
|
|
|
|
1104
|
0
|
|
|
|
|
0
|
$joinsql[$jj] =~ s/^\s+//gso; #STRIP LEADING, TRAILING SPACES. |
1105
|
0
|
|
|
|
|
0
|
$joinsql[$jj] =~ s/\s+$//gso; |
1106
|
|
|
|
|
|
|
|
1107
|
|
|
|
|
|
|
#CONVERT ALL "jointable.fieldname" to "fieldname" & REMOVE ALL "othertables.fieldname". |
1108
|
|
|
|
|
|
|
|
1109
|
0
|
|
|
|
|
0
|
$joinsql[$jj] =~ s!^\s*select(?:\s*distinct)?\s+(.+)\s+from\s+! |
1110
|
0
|
|
|
|
|
0
|
my $one = $1; |
1111
|
0
|
|
|
|
|
0
|
$one =~ s/$joinfid\.//g; |
1112
|
0
|
|
|
|
|
0
|
$one =~ s/\w+\.\w+(?:\s*\,)?//go; |
1113
|
0
|
|
|
|
|
0
|
$one =~ s/\,\s*$//o; |
1114
|
0
|
|
|
|
|
0
|
"select $one from " |
1115
|
|
|
|
|
|
|
!eis; |
1116
|
|
|
|
|
|
|
|
1117
|
0
|
0
|
|
|
|
0
|
$whereclause = $1 if ($joinsql[$jj] =~ s/\s+where\s+(.+)$/ /iso); |
1118
|
|
|
|
|
|
|
# $csr->STORE("sprite_where0", $whereclause) unless ($jj); |
1119
|
0
|
0
|
|
|
|
0
|
unless ($jj) |
1120
|
|
|
|
|
|
|
{ |
1121
|
0
|
|
|
|
|
0
|
my $unprotectedWhere = $whereclause; |
1122
|
0
|
0
|
|
|
|
0
|
if ($whereclause =~ /\S/o) |
1123
|
|
|
|
|
|
|
{ |
1124
|
|
|
|
|
|
|
#RESTORE QUOTED STRINGS AND ESCAPED QUOTES WITHIN THEM. |
1125
|
0
|
|
|
|
|
0
|
1 while ($unprotectedWhere =~ s/\$QS\[(\d+)\]/ |
1126
|
0
|
|
|
|
|
0
|
my $one = $1; |
1127
|
0
|
|
|
|
|
0
|
my $quotechar = substr($QS[$one],0,1); |
1128
|
0
|
|
|
|
|
0
|
($quotechar.substr($QS[$one],1).$quotechar) |
1129
|
|
|
|
|
|
|
/es); |
1130
|
0
|
|
|
|
|
0
|
$unprotectedWhere =~ s/\x02\^4jSpR1tE\x02/\"\"/gso; #UNPROTECT QUOTES WITHIN QUOTES! |
1131
|
0
|
|
|
|
|
0
|
$unprotectedWhere =~ s/\x02\^3jSpR1tE\x02/\'\'/gso; |
1132
|
|
|
|
|
|
|
} |
1133
|
0
|
|
|
|
|
0
|
$csr->STORE("sprite_where0", $unprotectedWhere); |
1134
|
|
|
|
|
|
|
} |
1135
|
|
|
|
|
|
|
|
1136
|
|
|
|
|
|
|
|
1137
|
|
|
|
|
|
|
# $whereclause =~ s/([\'\"])([^\1]*?)\1//g; #STRIP OUT QUOTED STRINGS TO PREVENT INTERFEARANCE W/OTHER REGICES. |
1138
|
0
|
0
|
|
|
|
0
|
$_ = $1 if ($joinsql[$jj] =~ /select\s+(.+?)\s+from\s+/o); |
1139
|
0
|
|
|
|
|
0
|
s/\s+//go; |
1140
|
0
|
|
|
|
|
0
|
@selectfields = split(/\,/o, $_); |
1141
|
|
|
|
|
|
|
|
1142
|
|
|
|
|
|
|
#DEAL WITH THE ORDER-BY CLAUSE, IF ANY. |
1143
|
|
|
|
|
|
|
|
1144
|
0
|
0
|
0
|
|
|
0
|
if ($whereclause =~ s/\s+order\s+by\s*(.*)//iso || $joinsql[$jj] =~ s/\s+order\s+by\s*(.*)//iso) |
1145
|
|
|
|
|
|
|
{ |
1146
|
0
|
|
|
|
|
0
|
my $ordbyclause = $1; |
1147
|
0
|
0
|
|
|
|
0
|
if ($jj) |
1148
|
|
|
|
|
|
|
{ |
1149
|
0
|
|
|
|
|
0
|
$ordbyclause =~ s/(?:$joinalias[0]|$joinfid[0])\.\w+(?:\s+desc)?//gis; |
1150
|
|
|
|
|
|
|
} |
1151
|
|
|
|
|
|
|
else |
1152
|
|
|
|
|
|
|
{ |
1153
|
0
|
0
|
|
|
|
0
|
$csr->STORE('sprite_joinorder', ( |
1154
|
|
|
|
|
|
|
($ordbyclause =~ /^(?:$joinalias[1]|$joinfid[1])\./) |
1155
|
|
|
|
|
|
|
? 1 : 0)); |
1156
|
0
|
|
|
|
|
0
|
$ordbyclause =~ s/(?:$joinalias[1]|$joinfid[1])\.\w+(?:\s+desc)?\s*\,?//gis; |
1157
|
|
|
|
|
|
|
} |
1158
|
0
|
|
|
|
|
0
|
$ordbyclause =~ s/\w+\.(\w+)/$1/gs; |
1159
|
0
|
|
|
|
|
0
|
$ordbyclause =~ s/\,\s*$//so; |
1160
|
0
|
|
|
|
|
0
|
$ordbyclause =~ s/^\s*\,//so; |
1161
|
0
|
0
|
|
|
|
0
|
$joinsql[$jj] .= " order by $ordbyclause" if ($ordbyclause =~ /\S/o); |
1162
|
|
|
|
|
|
|
} |
1163
|
|
|
|
|
|
|
|
1164
|
|
|
|
|
|
|
#ADD ANY FIELDS IN WHERE-CLAUSE BUT NOT FETCHED (WE MUST FETCH THEM)! |
1165
|
0
|
|
|
|
|
0
|
@union = (); |
1166
|
0
|
|
|
|
|
0
|
while ($whereclause =~ s/$joinfid\.(\w+)//is) |
1167
|
|
|
|
|
|
|
{ |
1168
|
0
|
|
|
|
|
0
|
$addfields{$1} = 1; |
1169
|
0
|
|
|
|
|
0
|
push (@union, "$joinfid.$1"); |
1170
|
|
|
|
|
|
|
} |
1171
|
0
|
|
|
|
|
0
|
$csr->STORE("sprite_union$jj", [@union]); |
1172
|
0
|
|
|
|
|
0
|
$joinsql[$jj] =~ s/$joinfid\.(\w+)/$1/gs; |
1173
|
|
|
|
|
|
|
# unless ($whereclause) |
1174
|
|
|
|
|
|
|
# { |
1175
|
|
|
|
|
|
|
# DBI::set_err($resptr, -1, 'Join queries require "where"-clause!'); |
1176
|
|
|
|
|
|
|
# return undef; |
1177
|
|
|
|
|
|
|
# } |
1178
|
|
|
|
|
|
|
|
1179
|
|
|
|
|
|
|
#REMOVE THE OTHER TABLES FROM THE FROM CLAUSE. |
1180
|
|
|
|
|
|
|
|
1181
|
|
|
|
|
|
|
#$joinsql[$jj] =~ s!\s+from\s+(\w+.*?)(\s+where.*)?$!" from $joinfid[$jj] $2"!egs; |
1182
|
0
|
|
|
|
|
0
|
$joinsql[$jj] =~ s!\s+from\s+(\w+.*?)(\s+(?:where|order\s+by).*)?$!" from $joinfid[$jj] $2"!egs; |
|
0
|
|
|
|
|
0
|
|
1183
|
|
|
|
|
|
|
|
1184
|
|
|
|
|
|
|
#APPEND UNION FIELDS FROM JOINTABLE NOT IN SELECT LIST TO SELECT LIST. |
1185
|
|
|
|
|
|
|
|
1186
|
0
|
|
|
|
|
0
|
$addthesefields = ''; |
1187
|
0
|
|
|
|
|
0
|
$listprefix = ''; |
1188
|
0
|
0
|
|
|
|
0
|
unless ($selectfields[0] eq '*') |
1189
|
|
|
|
|
|
|
{ |
1190
|
0
|
|
|
|
|
0
|
outer: foreach my $j (keys %addfields) |
1191
|
|
|
|
|
|
|
{ |
1192
|
0
|
|
|
|
|
0
|
for (my $k=0;$k<=$#selectfields;$k++) |
1193
|
|
|
|
|
|
|
{ |
1194
|
0
|
0
|
|
|
|
0
|
next outer if ($selectfields[$k] eq $j); |
1195
|
|
|
|
|
|
|
# $listprefix = ','; #REMOVED 20040913 |
1196
|
|
|
|
|
|
|
} |
1197
|
|
|
|
|
|
|
#$addthesefields .= $listprefix . $j; #CHGD. TO NEXT 20040913 |
1198
|
0
|
|
|
|
|
0
|
$addthesefields .= $listprefix . $j . ','; |
1199
|
|
|
|
|
|
|
} |
1200
|
0
|
|
|
|
|
0
|
$addthesefields =~ s/\,$//o; |
1201
|
|
|
|
|
|
|
#$joinsql[$jj] =~ s/\s+from\s+/ $addthesefields from /; #CHGD. TO NEXT IF-STMT. 20040929. |
1202
|
0
|
0
|
|
|
|
0
|
if ($addthesefields) |
1203
|
|
|
|
|
|
|
{ |
1204
|
0
|
0
|
|
|
|
0
|
($joinsql[$jj] =~ s/^\s*select\s+from\s+$joinfid[$jj]/select $addthesefields from $joinfid[$jj]/is) |
1205
|
|
|
|
|
|
|
or |
1206
|
|
|
|
|
|
|
($joinsql[$jj] =~ s/\s+from\s+$joinfid[$jj]/,$addthesefields from $joinfid[$jj]/is); |
1207
|
|
|
|
|
|
|
} |
1208
|
|
|
|
|
|
|
} |
1209
|
|
|
|
|
|
|
#$csr->STORE("sprite_bi$jj", $bindindices[$jj]); |
1210
|
0
|
|
|
|
|
0
|
$csr->STORE("sprite_joinnops$jj", 0); |
1211
|
|
|
|
|
|
|
|
1212
|
|
|
|
|
|
|
#RESTORE QUOTED STRINGS AND ESCAPED QUOTES WITHIN THEM. |
1213
|
0
|
|
|
|
|
0
|
1 while ($joinsql[$jj] =~ s/\$QS\[(\d+)\]/ |
1214
|
0
|
|
|
|
|
0
|
my $one = $1; |
1215
|
0
|
|
|
|
|
0
|
my $quotechar = substr($QS[$one],0,1); |
1216
|
0
|
|
|
|
|
0
|
($quotechar.substr($QS[$one],1).$quotechar) |
1217
|
|
|
|
|
|
|
/es); |
1218
|
0
|
|
|
|
|
0
|
$joinsql[$jj] =~ s/\x02\^4jSpR1tE\x02/\"\"/gso; #UNPROTECT QUOTES WITHIN QUOTES! |
1219
|
0
|
|
|
|
|
0
|
$joinsql[$jj] =~ s/\x02\^3jSpR1tE\x02/\'\'/gso; |
1220
|
0
|
|
|
|
|
0
|
$csr->STORE("sprite_joinstmt$jj", $joinsql[$jj]); |
1221
|
|
|
|
|
|
|
} |
1222
|
0
|
|
|
|
|
0
|
$csr->STORE('sprite_joinparams', []); |
1223
|
|
|
|
|
|
|
} |
1224
|
|
|
|
|
|
|
else |
1225
|
|
|
|
|
|
|
{ |
1226
|
11
|
|
|
|
|
93
|
$sqlstr =~ s/select\s+(.*?)\s+from\s+(\w+)\s+(\w+)\s+(where\s+.+|order\s+.+)?$/ |
1227
|
0
|
|
|
|
|
0
|
my ($one, $two, $three, $four) = ($1, $2, $3, $4); |
1228
|
0
|
|
|
|
|
0
|
$one =~ s|\b$three\.(\w)|$1|g; |
1229
|
0
|
|
|
|
|
0
|
$four =~ s|\b$three\.(\w)|$1|g; |
1230
|
0
|
|
|
|
|
0
|
"select $one from $two $four" |
1231
|
|
|
|
|
|
|
/eis; |
1232
|
|
|
|
|
|
|
} |
1233
|
|
|
|
|
|
|
|
1234
|
|
|
|
|
|
|
#SET UP STMT. PARAMETERS. |
1235
|
|
|
|
|
|
|
|
1236
|
11
|
|
|
|
|
44
|
$csr->STORE('sprite_params', []); |
1237
|
11
|
|
|
|
|
23
|
$num_of_params = ($sqlstr =~ tr/\?//); |
1238
|
11
|
|
|
|
|
22
|
$sqlstr =~ s/\x02\^2jSpR1tE\x02/\?/gso; |
1239
|
11
|
|
|
|
|
30
|
$csr->STORE('NUM_OF_PARAMS', $num_of_params); |
1240
|
11
|
50
|
|
|
|
39
|
$sqlstr = $joinsql[0] if ($joinsql[0]); |
1241
|
|
|
|
|
|
|
|
1242
|
|
|
|
|
|
|
#RESTORE QUOTED STRINGS. |
1243
|
11
|
|
|
|
|
64
|
1 while ($sqlstr =~ s/\$QS\[(\d+)\]/ |
1244
|
6
|
|
|
|
|
16
|
my $one = $1; |
1245
|
6
|
|
|
|
|
14
|
my $quotechar = substr($QS[$one],0,1); |
1246
|
6
|
|
|
|
|
37
|
($quotechar.substr($QS[$one],1).$quotechar) |
1247
|
|
|
|
|
|
|
/es); |
1248
|
|
|
|
|
|
|
#$sqlstr =~ s/\x02\^3jSpR1tE\x02/\"\"/gs; #BUGFIX: CHGD NEXT 2 TO FOLLOWING 2 20050429. |
1249
|
|
|
|
|
|
|
#$sqlstr =~ s/\x02\^2jSpR1tE\x02/\'\'/gs; |
1250
|
11
|
|
|
|
|
22
|
$sqlstr =~ s/\x02\^4jSpR1tE\x02/\"\"/gso; #UNPROTECT QUOTES WITHIN QUOTES! |
1251
|
11
|
|
|
|
|
17
|
$sqlstr =~ s/\x02\^3jSpR1tE\x02/\'\'/gso; |
1252
|
11
|
|
|
|
|
34
|
$csr->STORE('sprite_statement', $sqlstr); |
1253
|
11
|
|
|
|
|
81
|
return ($csr); |
1254
|
|
|
|
|
|
|
} |
1255
|
|
|
|
|
|
|
|
1256
|
|
|
|
|
|
|
sub parseParins #RECURSIVELY ASSIGN ALL PARENTHAASZED EXPRESSIONS TO AN ARRAY TO PROTECT FROM OTHER REGICES. |
1257
|
|
|
|
|
|
|
{ |
1258
|
0
|
|
|
0
|
|
0
|
my ($T, $tindx, $s) = @_; |
1259
|
|
|
|
|
|
|
|
1260
|
0
|
|
|
|
|
0
|
$tindx++ while ($s =~ s/\(([^\(\)]+)\)/ |
1261
|
0
|
|
|
|
|
0
|
$T->[$tindx] = &parseParins($T, $tindx, $1); |
1262
|
0
|
|
|
|
|
0
|
"\$T\[$tindx]" |
1263
|
|
|
|
|
|
|
/e); |
1264
|
0
|
|
|
|
|
0
|
return $s; |
1265
|
|
|
|
|
|
|
} |
1266
|
|
|
|
|
|
|
|
1267
|
|
|
|
|
|
|
sub commit |
1268
|
|
|
|
|
|
|
{ |
1269
|
2
|
|
|
2
|
|
112
|
my ($dB) = shift; |
1270
|
|
|
|
|
|
|
|
1271
|
2
|
50
|
33
|
|
|
14
|
if ($dB->FETCH('AutoCommit') && $dB->FETCH('Warn')) |
1272
|
|
|
|
|
|
|
{ |
1273
|
0
|
|
|
|
|
0
|
warn ('Commit ineffective while AutoCommit is ON!'); |
1274
|
0
|
|
|
|
|
0
|
return 1; |
1275
|
|
|
|
|
|
|
} |
1276
|
2
|
|
|
|
|
7
|
my ($commitResult) = 1; #ADDED 20000103 |
1277
|
|
|
|
|
|
|
|
1278
|
2
|
|
|
|
|
3
|
foreach (keys %{$dB->{sprite_SpritesOpen}}) |
|
2
|
|
|
|
|
10
|
|
1279
|
|
|
|
|
|
|
{ |
1280
|
5
|
50
|
|
|
|
18
|
next unless (defined($dB->{'sprite_SpritesOpen'}->{$_})); |
1281
|
5
|
100
|
|
|
|
111
|
next if (/^(USER|ALL)_TABLES$/i); |
1282
|
3
|
50
|
|
|
|
6
|
next unless (defined(${$dB->{'sprite_SpritesOpen'}->{$_}})); |
|
3
|
|
|
|
|
12
|
|
1283
|
3
|
|
|
|
|
63
|
$commitResult = ${$dB->{'sprite_SpritesOpen'}->{$_}}->commit($_); |
|
3
|
|
|
|
|
15
|
|
1284
|
3
|
50
|
33
|
|
|
24
|
return undef if (!defined($commitResult) || $commitResult <= 0); |
1285
|
|
|
|
|
|
|
} |
1286
|
2
|
|
|
|
|
10
|
return 1; |
1287
|
|
|
|
|
|
|
} |
1288
|
|
|
|
|
|
|
|
1289
|
|
|
|
|
|
|
sub rollback |
1290
|
|
|
|
|
|
|
{ |
1291
|
0
|
|
|
0
|
|
0
|
my ($dB) = shift; |
1292
|
|
|
|
|
|
|
|
1293
|
0
|
0
|
0
|
|
|
0
|
if (!shift && $dB->FETCH('AutoCommit') && $dB->FETCH('Warn')) |
|
|
|
0
|
|
|
|
|
1294
|
|
|
|
|
|
|
{ |
1295
|
0
|
|
|
|
|
0
|
warn ('Rollback ineffective while AutoCommit is ON!'); |
1296
|
0
|
|
|
|
|
0
|
return 1; |
1297
|
|
|
|
|
|
|
} |
1298
|
|
|
|
|
|
|
|
1299
|
0
|
|
|
|
|
0
|
foreach my $s (keys %{$dB->{sprite_SpritesOpen}}) |
|
0
|
|
|
|
|
0
|
|
1300
|
|
|
|
|
|
|
{ |
1301
|
0
|
0
|
|
|
|
0
|
next unless (defined($dB->{'sprite_SpritesOpen'}->{$s})); |
1302
|
0
|
0
|
|
|
|
0
|
next if ($s =~ /^(USER|ALL)_TABLES$/i); |
1303
|
0
|
0
|
|
|
|
0
|
next unless (defined(${$dB->{'sprite_SpritesOpen'}->{$s}})); |
|
0
|
|
|
|
|
0
|
|
1304
|
0
|
|
|
|
|
0
|
${$dB->{'sprite_SpritesOpen'}->{$s}}->rollback($s); |
|
0
|
|
|
|
|
0
|
|
1305
|
|
|
|
|
|
|
} |
1306
|
0
|
|
|
|
|
0
|
return 1; |
1307
|
|
|
|
|
|
|
} |
1308
|
|
|
|
|
|
|
|
1309
|
|
|
|
|
|
|
sub STORE |
1310
|
|
|
|
|
|
|
{ |
1311
|
42
|
|
|
42
|
|
327
|
my($dbh, $attr, $val) = @_; |
1312
|
42
|
100
|
|
|
|
109
|
if ($attr eq 'AutoCommit') |
1313
|
|
|
|
|
|
|
{ |
1314
|
|
|
|
|
|
|
# AutoCommit is currently the only standard attribute we have |
1315
|
|
|
|
|
|
|
# to consider. |
1316
|
|
|
|
|
|
|
|
1317
|
2
|
50
|
33
|
|
|
7
|
$dbh->commit() if ($val == 1 && !$dbh->FETCH('AutoCommit')); |
1318
|
2
|
|
|
|
|
5
|
$dbh->{AutoCommit} = $val; |
1319
|
2
|
|
|
|
|
12
|
return 1; |
1320
|
|
|
|
|
|
|
} |
1321
|
40
|
100
|
|
|
|
136
|
if ($attr =~ /^sprite/o) |
1322
|
|
|
|
|
|
|
{ |
1323
|
|
|
|
|
|
|
# Handle only our private attributes here |
1324
|
|
|
|
|
|
|
# Note that we could trigger arbitrary actions. |
1325
|
|
|
|
|
|
|
# Ideally we should catch unknown attributes. |
1326
|
35
|
|
|
|
|
93
|
$dbh->{$attr} = $val; # Yes, we are allowed to do this, |
1327
|
35
|
|
|
|
|
80
|
return 1; # but only for our private attributes |
1328
|
|
|
|
|
|
|
} |
1329
|
|
|
|
|
|
|
# Else pass up to DBI to handle for us |
1330
|
5
|
|
|
|
|
54
|
$dbh->SUPER::STORE($attr, $val); |
1331
|
|
|
|
|
|
|
} |
1332
|
|
|
|
|
|
|
|
1333
|
|
|
|
|
|
|
sub FETCH |
1334
|
|
|
|
|
|
|
{ |
1335
|
28
|
|
|
28
|
|
67
|
my($dbh, $attr) = @_; |
1336
|
28
|
50
|
|
|
|
61
|
if ($attr eq 'AutoCommit') { return $dbh->{AutoCommit}; } |
|
0
|
|
|
|
|
0
|
|
1337
|
28
|
50
|
|
|
|
78
|
if ($attr =~ /^sprite_/o) |
1338
|
|
|
|
|
|
|
{ |
1339
|
|
|
|
|
|
|
# Handle only our private attributes here |
1340
|
|
|
|
|
|
|
# Note that we could trigger arbitrary actions. |
1341
|
0
|
|
|
|
|
0
|
return $dbh->{$attr}; # Yes, we are allowed to do this, |
1342
|
|
|
|
|
|
|
# but only for our private attributes |
1343
|
0
|
|
|
|
|
0
|
return $dbh->{$attr}; |
1344
|
|
|
|
|
|
|
} |
1345
|
|
|
|
|
|
|
# Else pass up to DBI to handle |
1346
|
28
|
|
|
|
|
141
|
$dbh->SUPER::FETCH($attr); |
1347
|
|
|
|
|
|
|
} |
1348
|
|
|
|
|
|
|
|
1349
|
|
|
|
|
|
|
sub disconnect |
1350
|
|
|
|
|
|
|
{ |
1351
|
1
|
|
|
1
|
|
60
|
my ($db) = shift; |
1352
|
|
|
|
|
|
|
|
1353
|
|
|
|
|
|
|
#DBI::set_err($db, 0, ''); #CHGD. TO NEXT 20041104. |
1354
|
1
|
|
|
|
|
5
|
DBI::set_err($db, undef); |
1355
|
1
|
|
|
|
|
4
|
return (1); #20000114: MAKE WORK LIKE DBI! |
1356
|
|
|
|
|
|
|
} |
1357
|
|
|
|
|
|
|
|
1358
|
|
|
|
|
|
|
sub do |
1359
|
|
|
|
|
|
|
{ |
1360
|
3
|
|
|
3
|
|
109
|
my ($dB, $sqlstr, $attr, @bind_values) = @_; |
1361
|
3
|
50
|
|
|
|
38
|
my ($csr) = $dB->prepare($sqlstr, $attr) or return undef; |
1362
|
|
|
|
|
|
|
|
1363
|
|
|
|
|
|
|
#DBI::set_err($dB, 0, ''); #CHGD. TO NEXT 20041104. |
1364
|
3
|
|
|
|
|
11
|
DBI::set_err($dB, undef); |
1365
|
|
|
|
|
|
|
|
1366
|
|
|
|
|
|
|
#my $retval = $csr->execute(@bind_values) || undef; |
1367
|
3
|
|
100
|
|
|
28
|
return ($csr->execute(@bind_values) || undef); |
1368
|
|
|
|
|
|
|
} |
1369
|
|
|
|
|
|
|
|
1370
|
|
|
|
|
|
|
sub table_info |
1371
|
|
|
|
|
|
|
{ |
1372
|
1
|
|
|
1
|
|
6
|
my($dbh) = @_; # XXX add qualification |
1373
|
1
|
50
|
|
|
|
6
|
my $sth = $dbh->prepare('select TABLE_NAME from USER_TABLES') |
1374
|
|
|
|
|
|
|
or return undef; |
1375
|
1
|
50
|
|
|
|
5
|
$sth->execute or return undef; |
1376
|
1
|
|
|
|
|
3
|
return $sth; |
1377
|
|
|
|
|
|
|
} |
1378
|
|
|
|
|
|
|
|
1379
|
|
|
|
|
|
|
sub primary_key_info #ADDED 20060613 TO SUPPORT DBI primary_key/primary_key_info FUNCTIONS! |
1380
|
|
|
|
|
|
|
{ |
1381
|
1
|
|
|
1
|
|
42
|
my ($dbh, $cat, $schema, $tablename) = @_; |
1382
|
1
|
50
|
|
|
|
8
|
my $sth = $dbh->prepare("PRIMARY_KEY_INFO $tablename") |
1383
|
|
|
|
|
|
|
or return undef; |
1384
|
1
|
50
|
|
|
|
5
|
$sth->execute() or return undef; |
1385
|
1
|
|
|
|
|
4
|
return $sth; |
1386
|
|
|
|
|
|
|
} |
1387
|
|
|
|
|
|
|
|
1388
|
|
|
|
|
|
|
sub type_info_all #ADDED 20010312, BORROWED FROM "Oracle.pm". |
1389
|
|
|
|
|
|
|
{ |
1390
|
0
|
|
|
0
|
|
0
|
my ($dbh) = @_; |
1391
|
0
|
|
|
|
|
0
|
my $names = |
1392
|
|
|
|
|
|
|
{ |
1393
|
|
|
|
|
|
|
TYPE_NAME => 0, |
1394
|
|
|
|
|
|
|
DATA_TYPE => 1, |
1395
|
|
|
|
|
|
|
COLUMN_SIZE => 2, |
1396
|
|
|
|
|
|
|
LITERAL_PREFIX => 3, |
1397
|
|
|
|
|
|
|
LITERAL_SUFFIX => 4, |
1398
|
|
|
|
|
|
|
CREATE_PARAMS => 5, |
1399
|
|
|
|
|
|
|
NULLABLE => 6, |
1400
|
|
|
|
|
|
|
CASE_SENSITIVE => 7, |
1401
|
|
|
|
|
|
|
SEARCHABLE => 8, |
1402
|
|
|
|
|
|
|
UNSIGNED_ATTRIBUTE => 9, |
1403
|
|
|
|
|
|
|
FIXED_PREC_SCALE =>10, |
1404
|
|
|
|
|
|
|
AUTO_UNIQUE_VALUE =>11, |
1405
|
|
|
|
|
|
|
LOCAL_TYPE_NAME =>12, |
1406
|
|
|
|
|
|
|
MINIMUM_SCALE =>13, |
1407
|
|
|
|
|
|
|
MAXIMUM_SCALE =>14, |
1408
|
|
|
|
|
|
|
} |
1409
|
|
|
|
|
|
|
; |
1410
|
|
|
|
|
|
|
# Based on the values from Oracle 8.0.4 ODBC driver |
1411
|
0
|
|
|
|
|
0
|
my $ti = [ |
1412
|
|
|
|
|
|
|
$names, |
1413
|
|
|
|
|
|
|
[ 'LONG RAW', -4, '2147483647', '\'', '\'', undef, 1, '0', '0', |
1414
|
|
|
|
|
|
|
undef, '0', undef, undef, undef, undef |
1415
|
|
|
|
|
|
|
], |
1416
|
|
|
|
|
|
|
[ 'RAW', -2, 255, '\'', '\'', 'max length', 1, '0', 3, |
1417
|
|
|
|
|
|
|
undef, '0', undef, undef, undef, undef |
1418
|
|
|
|
|
|
|
], |
1419
|
|
|
|
|
|
|
[ 'LONG', -1, '2147483647', '\'', '\'', undef, 1, 1, '0', |
1420
|
|
|
|
|
|
|
undef, '0', undef, undef, undef, undef |
1421
|
|
|
|
|
|
|
], |
1422
|
|
|
|
|
|
|
[ 'CHAR', 1, 255, '\'', '\'', 'max length', 1, 1, 3, |
1423
|
|
|
|
|
|
|
undef, '0', '0', undef, undef, undef |
1424
|
|
|
|
|
|
|
], |
1425
|
|
|
|
|
|
|
[ 'NUMBER', 3, 38, undef, undef, 'precision,scale', 1, '0', 3, |
1426
|
|
|
|
|
|
|
'0', '0', '0', undef, '0', 38 |
1427
|
|
|
|
|
|
|
], |
1428
|
|
|
|
|
|
|
[ 'AUTONUMBER', 4, 38, undef, undef, 'precision,scale', 1, '0', 3, |
1429
|
|
|
|
|
|
|
'0', '0', '0', undef, '0', 38 |
1430
|
|
|
|
|
|
|
], |
1431
|
|
|
|
|
|
|
[ 'DOUBLE', 8, 15, undef, undef, undef, 1, '0', 3, |
1432
|
|
|
|
|
|
|
'0', '0', '0', undef, undef, undef |
1433
|
|
|
|
|
|
|
], |
1434
|
|
|
|
|
|
|
[ 'DATE', 11, 19, '\'', '\'', undef, 1, '0', 3, |
1435
|
|
|
|
|
|
|
undef, '0', '0', undef, '0', '0' |
1436
|
|
|
|
|
|
|
], |
1437
|
|
|
|
|
|
|
[ 'VARCHAR2', 12, 2000, '\'', '\'', 'max length', 1, 1, 3, |
1438
|
|
|
|
|
|
|
undef, '0', '0', undef, undef, undef |
1439
|
|
|
|
|
|
|
] |
1440
|
|
|
|
|
|
|
]; |
1441
|
0
|
|
|
|
|
0
|
return $ti; |
1442
|
|
|
|
|
|
|
} |
1443
|
|
|
|
|
|
|
sub tables #CONVENIENCE METHOD FOR FETCHING LIST OF TABLES IN THE DATABASE. |
1444
|
|
|
|
|
|
|
{ |
1445
|
1
|
|
|
1
|
|
58
|
my($dbh) = @_; # XXX add qualification |
1446
|
|
|
|
|
|
|
|
1447
|
1
|
|
|
|
|
16
|
my $sth = $dbh->table_info(); |
1448
|
|
|
|
|
|
|
|
1449
|
1
|
50
|
|
|
|
4
|
return undef unless ($sth); |
1450
|
|
|
|
|
|
|
|
1451
|
1
|
|
|
|
|
3
|
my ($row, @tables); |
1452
|
|
|
|
|
|
|
|
1453
|
1
|
|
|
|
|
7
|
while ($row = $sth->fetchrow_arrayref()) |
1454
|
|
|
|
|
|
|
{ |
1455
|
1
|
|
|
|
|
5
|
push (@tables, $row->[0]); |
1456
|
|
|
|
|
|
|
} |
1457
|
1
|
|
|
|
|
34
|
$sth->finish(); |
1458
|
1
|
50
|
|
|
|
6
|
return undef unless ($#tables >= 0); |
1459
|
1
|
|
|
|
|
13
|
return (@tables); |
1460
|
|
|
|
|
|
|
} |
1461
|
|
|
|
|
|
|
|
1462
|
|
|
|
|
|
|
sub rows |
1463
|
|
|
|
|
|
|
{ |
1464
|
0
|
|
|
0
|
|
0
|
return $DBI::rows; |
1465
|
|
|
|
|
|
|
} |
1466
|
|
|
|
|
|
|
|
1467
|
|
|
|
|
|
|
sub DESTROY #ADDED 20001108 |
1468
|
|
|
|
|
|
|
{ |
1469
|
0
|
|
|
0
|
|
0
|
my($drh) = shift; |
1470
|
|
|
|
|
|
|
|
1471
|
0
|
0
|
|
|
|
0
|
if ($drh->FETCH('AutoCommit') == 1) |
1472
|
|
|
|
|
|
|
{ |
1473
|
0
|
|
|
|
|
0
|
$drh->STORE('AutoCommit',0); |
1474
|
0
|
|
|
|
|
0
|
$drh->rollback(); #COMMIT IT IF AUTOCOMMIT ON! |
1475
|
0
|
|
|
|
|
0
|
$drh->STORE('AutoCommit',1); |
1476
|
|
|
|
|
|
|
} |
1477
|
0
|
|
|
|
|
0
|
$drh = undef; |
1478
|
|
|
|
|
|
|
} |
1479
|
|
|
|
|
|
|
|
1480
|
|
|
|
|
|
|
1; |
1481
|
|
|
|
|
|
|
|
1482
|
|
|
|
|
|
|
|
1483
|
|
|
|
|
|
|
package DBD::Sprite::st; # ====== STATEMENT ====== |
1484
|
1
|
|
|
1
|
|
11
|
use strict; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
115
|
|
1485
|
|
|
|
|
|
|
|
1486
|
|
|
|
|
|
|
my (%typehash) = ( |
1487
|
|
|
|
|
|
|
'LONG RAW' => -4, |
1488
|
|
|
|
|
|
|
'RAW' => -3, |
1489
|
|
|
|
|
|
|
'LONG' => -1, |
1490
|
|
|
|
|
|
|
'CHAR' => 1, |
1491
|
|
|
|
|
|
|
'NUMBER' => 3, |
1492
|
|
|
|
|
|
|
'AUTONUMBER' => 4, |
1493
|
|
|
|
|
|
|
'DOUBLE' => 8, |
1494
|
|
|
|
|
|
|
'DATE' => 11, |
1495
|
|
|
|
|
|
|
'VARCHAR' => 12, |
1496
|
|
|
|
|
|
|
'VARCHAR2' => 12, |
1497
|
|
|
|
|
|
|
'BOOLEAN' => -7, #ADDED 20000308! |
1498
|
|
|
|
|
|
|
'BLOB' => 113, #ADDED 20020110! |
1499
|
|
|
|
|
|
|
'MEMO' => -1, #ADDED 20020110! |
1500
|
|
|
|
|
|
|
|
1501
|
|
|
|
|
|
|
'DATE' => 9, |
1502
|
|
|
|
|
|
|
'REAL' => 7, |
1503
|
|
|
|
|
|
|
'TINYINT' => -6, |
1504
|
|
|
|
|
|
|
'NCHAR' => -8, |
1505
|
|
|
|
|
|
|
'NVARCHAR' => -9, |
1506
|
|
|
|
|
|
|
'NTEXT' => -10, |
1507
|
|
|
|
|
|
|
'SMALLDATETIME' => 93, |
1508
|
|
|
|
|
|
|
'BIGINT' => -5, |
1509
|
|
|
|
|
|
|
'DECIMAL' => 3, |
1510
|
|
|
|
|
|
|
'INTEGER' => 4, |
1511
|
|
|
|
|
|
|
); |
1512
|
|
|
|
|
|
|
|
1513
|
|
|
|
|
|
|
$DBD::Sprite::st::imp_data_size = 0; |
1514
|
1
|
|
|
1
|
|
7
|
use vars qw($imp_data_size *fetch); |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
4445
|
|
1515
|
|
|
|
|
|
|
|
1516
|
|
|
|
|
|
|
sub bind_param |
1517
|
|
|
|
|
|
|
{ |
1518
|
0
|
|
|
0
|
|
0
|
my($sth, $pNum, $val, $attr) = @_; |
1519
|
0
|
0
|
|
|
|
0
|
my $type = (ref $attr) ? $attr->{TYPE} : $attr; |
1520
|
|
|
|
|
|
|
|
1521
|
0
|
0
|
|
|
|
0
|
if ($type) |
1522
|
|
|
|
|
|
|
{ |
1523
|
0
|
|
|
|
|
0
|
my $dbh = $sth->{Database}; |
1524
|
0
|
|
|
|
|
0
|
$val = $dbh->quote($val, $type); |
1525
|
0
|
|
|
|
|
0
|
$val =~ s/^\'//o; |
1526
|
0
|
|
|
|
|
0
|
$val =~ s/\'$//o; |
1527
|
|
|
|
|
|
|
} |
1528
|
0
|
|
|
|
|
0
|
my $params = $sth->FETCH('sprite_params'); |
1529
|
0
|
|
|
|
|
0
|
$params->[$pNum-1] = $val; |
1530
|
|
|
|
|
|
|
|
1531
|
|
|
|
|
|
|
#${$sth->{bindvars}}[($pNum-1)] = $val; #FOR SPRITE. #REMOVED 20010312 (LVALUE NOT FOUND ANYWHERE ELSE). |
1532
|
|
|
|
|
|
|
|
1533
|
0
|
|
|
|
|
0
|
$sth->STORE('sprite_params', $params); |
1534
|
0
|
|
|
|
|
0
|
return 1; |
1535
|
|
|
|
|
|
|
} |
1536
|
|
|
|
|
|
|
|
1537
|
|
|
|
|
|
|
sub execute |
1538
|
|
|
|
|
|
|
{ |
1539
|
13
|
|
|
13
|
|
483
|
my ($sth, @bind_values) = @_; |
1540
|
13
|
100
|
|
|
|
58
|
my $params = (@bind_values) ? \@bind_values : $sth->FETCH('sprite_params'); |
1541
|
13
|
|
|
|
|
34
|
my @ocolnames; |
1542
|
13
|
|
|
|
|
23
|
for (my $i=0;$i<=$#{$params};$i++) #ADDED 20000303 FIX QUOTE PROBLEM WITH BINDS. |
|
21
|
|
|
|
|
61
|
|
1543
|
|
|
|
|
|
|
{ |
1544
|
8
|
|
|
|
|
22
|
$params->[$i] =~ s/\'/\'\'/go; |
1545
|
|
|
|
|
|
|
} |
1546
|
13
|
|
|
|
|
44
|
my $numParam = $sth->FETCH('NUM_OF_PARAMS'); |
1547
|
|
|
|
|
|
|
|
1548
|
13
|
50
|
33
|
|
|
64
|
if ($params && scalar(@$params) != $numParam) #CHECK FOR RIGHT # PARAMS. |
1549
|
|
|
|
|
|
|
{ |
1550
|
0
|
|
|
|
|
0
|
DBI::set_err($sth, (scalar(@$params)-$numParam), |
1551
|
|
|
|
|
|
|
"..execute: Wrong number of bind variables (".(scalar(@$params)-$numParam) |
1552
|
|
|
|
|
|
|
." too many!)"); |
1553
|
0
|
|
|
|
|
0
|
return undef; |
1554
|
|
|
|
|
|
|
} |
1555
|
|
|
|
|
|
|
#my $sqlstr = $sth->{'Statement'}; #CHGD. TO NEXT 20040205 TO PERMIT JOINS. |
1556
|
13
|
|
|
|
|
43
|
my $sqlstr = $sth->FETCH('sprite_statement'); |
1557
|
|
|
|
|
|
|
#NEXT 8 LINES ADDED 20010911 TO FIX BUG WHEN QUOTED VALUES CONTAIN "?"s. |
1558
|
13
|
|
|
|
|
27
|
$sqlstr =~ s/\\\'/\x02\^3jSpR1tE\x02/gso; #PROTECT ESCAPED DOUBLE-QUOTES. |
1559
|
13
|
|
|
|
|
21
|
$sqlstr =~ s/\'\'/\x02\^4jSpR1tE\x02/gso; #PROTECT DOUBLED DOUBLE-QUOTES. |
1560
|
13
|
|
|
|
|
49
|
$sqlstr =~ s/\'([^\']*?)\'/ |
1561
|
5
|
|
|
|
|
16
|
my ($str) = $1; |
1562
|
5
|
|
|
|
|
10
|
$str =~ s|\?|\x02\^2jSpR1tE\x02|gs; #PROTECT QUESTION-MARKS WITHIN QUOTES. |
1563
|
5
|
|
|
|
|
17
|
"'$str'"/egs; |
1564
|
13
|
|
|
|
|
25
|
$sqlstr =~ s/\x02\^4jSpR1tE\x02/\'\'/gso; #UNPROTECT DOUBLED DOUBLE-QUOTES. |
1565
|
13
|
|
|
|
|
19
|
$sqlstr =~ s/\x02\^3jSpR1tE\x02/\\\'/gso; #UNPROTECT ESCAPED DOUBLE-QUOTES. |
1566
|
|
|
|
|
|
|
|
1567
|
|
|
|
|
|
|
#CONVERT REMAINING QUESTION-MARKS TO BOUND VALUES. |
1568
|
|
|
|
|
|
|
|
1569
|
|
|
|
|
|
|
# my $bindindices = $sth->FETCH('sprite_bi0') || [0..($numParam-1)]; |
1570
|
|
|
|
|
|
|
# foreach my $i (@$bindindices) |
1571
|
13
|
|
|
|
|
38
|
for (my $i = 0; $i < $numParam; $i++) |
1572
|
|
|
|
|
|
|
{ |
1573
|
8
|
|
|
|
|
17
|
$params->[$i] =~ s/\?/\x02\^2jSpR1tE\x02/gso; #ADDED 20001023 TO FIX BUG WHEN PARAMETER OTHER THAN LAST CONTAINS A "?"! |
1574
|
8
|
|
|
|
|
24
|
$sqlstr =~ s/\?/"'".$params->[$i]."'"/es; |
|
8
|
|
|
|
|
33
|
|
1575
|
|
|
|
|
|
|
} |
1576
|
13
|
|
|
|
|
23
|
$sqlstr =~ s/\x02\^2jSpR1tE\x02/\?/gso; #ADDED 20001023! - UNPROTECT PROTECTED "?"s. |
1577
|
13
|
|
|
|
|
45
|
my ($spriteref) = $sth->FETCH('sprite_spritedb'); |
1578
|
|
|
|
|
|
|
|
1579
|
|
|
|
|
|
|
#CALL JSPRITE TO DO THE SQL! |
1580
|
13
|
|
|
|
|
50
|
my (@resv) = $spriteref->sql($sqlstr); |
1581
|
|
|
|
|
|
|
#!!! HANDLE SPRITE ERRORS HERE (SEE SPRITE.PM)!!! |
1582
|
13
|
|
|
|
|
25
|
my ($retval) = undef; |
1583
|
13
|
100
|
|
|
|
39
|
if ($#resv < 0) #GENERAL ERROR! |
|
|
100
|
|
|
|
|
|
1584
|
|
|
|
|
|
|
{ |
1585
|
|
|
|
|
|
|
DBI::set_err($sth, ($spriteref->{lasterror} || -601), |
1586
|
1
|
|
50
|
|
|
13
|
($spriteref->{lastmsg} || 'Unknown Error!')); |
|
|
|
50
|
|
|
|
|
1587
|
1
|
|
|
|
|
23
|
return $retval; |
1588
|
|
|
|
|
|
|
} |
1589
|
|
|
|
|
|
|
elsif ($resv[0]) #NORMAL ACTION IF NON SELECT OR >0 ROWS SELECTED. |
1590
|
|
|
|
|
|
|
{ |
1591
|
11
|
|
|
|
|
18
|
$retval = $resv[0]; |
1592
|
11
|
|
|
|
|
22
|
my $dB = $sth->{Database}; |
1593
|
|
|
|
|
|
|
#if ($dB->FETCH('AutoCommit') == 1 && $sth->FETCH('Statement') !~ /^\s*select/i) #CHGD. TO NEXT 20040205 TO PERMIT JOINS. |
1594
|
11
|
100
|
|
|
|
105
|
if ($sth->FETCH('sprite_statement') !~ /^\s*(?:select|primary_key_info)/io) |
1595
|
|
|
|
|
|
|
{ |
1596
|
5
|
50
|
|
|
|
27
|
if ($dB->FETCH('AutoCommit') == 1) |
1597
|
|
|
|
|
|
|
{ |
1598
|
0
|
0
|
|
|
|
0
|
$retval = undef unless ($spriteref->commit()); #ADDED 20010911 TO MAKE AUTOCOMMIT WORK (OOPS :( ) |
1599
|
|
|
|
|
|
|
#$dB->STORE('AutoCommit',1); #COMMIT DONE HERE! |
1600
|
|
|
|
|
|
|
} |
1601
|
|
|
|
|
|
|
} |
1602
|
|
|
|
|
|
|
else |
1603
|
|
|
|
|
|
|
{ |
1604
|
|
|
|
|
|
|
#OCOL* = ORIGINAL SQL. |
1605
|
|
|
|
|
|
|
#ICOL* = BASE SQL. |
1606
|
|
|
|
|
|
|
#JCOL* = JOIN SQL. |
1607
|
6
|
|
|
|
|
29
|
$sqlstr = $sth->FETCH('sprite_joinstmt1'); |
1608
|
6
|
50
|
|
|
|
15
|
if ($sqlstr) |
1609
|
|
|
|
|
|
|
{ |
1610
|
0
|
|
|
|
|
0
|
$sqlstr =~ s/\\\'/\x02\^3jSpR1tE\x02/gso; #PROTECT ESCAPED DOUBLE-QUOTES. |
1611
|
0
|
|
|
|
|
0
|
$sqlstr =~ s/\'\'/\x02\^4jSpR1tE\x02/gso; #PROTECT DOUBLED DOUBLE-QUOTES. |
1612
|
0
|
|
|
|
|
0
|
$sqlstr =~ s/\'([^\']*?)\'/ |
1613
|
0
|
|
|
|
|
0
|
my ($str) = $1; |
1614
|
0
|
|
|
|
|
0
|
$str =~ s|\?|\x02\^2jSpR1tE\x02|gso; #PROTECT QUESTION-MARKS WITHIN QUOTES. |
1615
|
0
|
|
|
|
|
0
|
"'$str'"/egs; |
1616
|
0
|
|
|
|
|
0
|
$sqlstr =~ s/\x02\^4jSpR1tE\x02/\'\'/gso; #UNPROTECT DOUBLED DOUBLE-QUOTES. |
1617
|
0
|
|
|
|
|
0
|
$sqlstr =~ s/\x02\^3jSpR1tE\x02/\\\'/gso; #UNPROTECT ESCAPED DOUBLE-QUOTES. |
1618
|
|
|
|
|
|
|
|
1619
|
|
|
|
|
|
|
#CONVERT REMAINING QUESTION-MARKS TO BOUND VALUES. |
1620
|
|
|
|
|
|
|
|
1621
|
|
|
|
|
|
|
#!!! my $bindindices = $sth->FETCH('sprite_bi1'); |
1622
|
|
|
|
|
|
|
# foreach my $i (@$bindindices) |
1623
|
|
|
|
|
|
|
# { |
1624
|
|
|
|
|
|
|
# $params->[$i] =~ s/\?/\x02\^2jSpR1tE\x02/gs; #ADDED 20001023 TO FIX BUG WHEN PARAMETER OTHER THAN LAST CONTAINS A "?"! |
1625
|
|
|
|
|
|
|
# $sqlstr =~ s/\?/"'".$params->[$i]."'"/es; |
1626
|
|
|
|
|
|
|
# } |
1627
|
0
|
|
|
|
|
0
|
$sqlstr =~ s/\x02\^2jSpR1tE\x02/\?/gso; #ADDED 20001023! - UNPROTECT PROTECTED "?"s. |
1628
|
0
|
|
|
|
|
0
|
my @icolnames = split(/\,/o, $spriteref->{use_fields}); |
1629
|
0
|
|
|
|
|
0
|
my %icolHash; |
1630
|
0
|
|
|
|
|
0
|
for (my $i=0;$i<=$#icolnames;$i++) |
1631
|
|
|
|
|
|
|
{ |
1632
|
0
|
|
|
|
|
0
|
$icolHash{$icolnames[$i]} = $i; |
1633
|
|
|
|
|
|
|
} |
1634
|
0
|
|
|
|
|
0
|
my $origsql = $sth->FETCH('Statement'); |
1635
|
0
|
|
|
|
|
0
|
$origsql =~ s/select\s+(.+)?\s+from\s+.+$/$1/is; |
1636
|
0
|
|
|
|
|
0
|
$origsql =~ s/\s+//g; |
1637
|
0
|
|
|
|
|
0
|
my $joinfids = $sth->FETCH('sprite_joinfid'); |
1638
|
0
|
|
|
|
|
0
|
my $joinalii = $sth->FETCH('sprite_joinalias'); |
1639
|
|
|
|
|
|
|
# unless ($spriteref->{sprite_CaseFieldNames}) #CHGD. TO NEXT 20040929. |
1640
|
0
|
0
|
|
|
|
0
|
$origsql =~ tr/a-z/A-Z/ unless ($spriteref->{sprite_CaseFieldNames}); |
1641
|
0
|
0
|
|
|
|
0
|
unless ($spriteref->{sprite_CaseTableNames}) |
1642
|
|
|
|
|
|
|
{ |
1643
|
0
|
|
|
|
|
0
|
for (my $i=0;$i<=$#{$joinfids};$i++) |
|
0
|
|
|
|
|
0
|
|
1644
|
|
|
|
|
|
|
{ |
1645
|
0
|
|
|
|
|
0
|
$joinfids->[$i] =~ tr/a-z/A-Z/; |
1646
|
0
|
|
|
|
|
0
|
$joinalii->[$i] =~ tr/a-z/A-Z/; |
1647
|
|
|
|
|
|
|
} |
1648
|
|
|
|
|
|
|
|
1649
|
|
|
|
|
|
|
} |
1650
|
|
|
|
|
|
|
#CALL JSPRITE TO DO THE SQL! |
1651
|
|
|
|
|
|
|
|
1652
|
0
|
|
|
|
|
0
|
my $joinspriteref = $sth->FETCH('sprite_joindb'); |
1653
|
0
|
|
|
|
|
0
|
my (@joinresv) = $joinspriteref->sql($sqlstr); |
1654
|
0
|
|
|
|
|
0
|
my $joinunion0 = $sth->FETCH('sprite_union0'); |
1655
|
|
|
|
|
|
|
|
1656
|
|
|
|
|
|
|
#BUILD ARRAYS OF INDICES FOR UNION FIELDS TO BE COMPARED. |
1657
|
0
|
|
|
|
|
0
|
my @icolindx; |
1658
|
0
|
|
|
|
|
0
|
for (my $i=0;$i<=$#{$joinunion0};$i++) |
|
0
|
|
|
|
|
0
|
|
1659
|
|
|
|
|
|
|
{ |
1660
|
0
|
|
|
|
|
0
|
$joinunion0->[$i] =~ s/[^\.]*\.(.*)/$1/; |
1661
|
|
|
|
|
|
|
$joinunion0->[$i] =~ tr/a-z/A-Z/ |
1662
|
0
|
0
|
|
|
|
0
|
unless ($joinspriteref->{sprite_CaseFieldNames}); |
1663
|
0
|
|
|
|
|
0
|
for (my $j=0;$j<=$#icolnames;$j++) |
1664
|
|
|
|
|
|
|
{ |
1665
|
0
|
0
|
|
|
|
0
|
if ($joinunion0->[$i] eq $icolnames[$j]) |
1666
|
|
|
|
|
|
|
{ |
1667
|
0
|
|
|
|
|
0
|
push (@icolindx, $j); |
1668
|
0
|
|
|
|
|
0
|
last; |
1669
|
|
|
|
|
|
|
} |
1670
|
|
|
|
|
|
|
} |
1671
|
|
|
|
|
|
|
} |
1672
|
0
|
|
|
|
|
0
|
my $joinunion1 = $sth->FETCH('sprite_union1'); |
1673
|
0
|
|
|
|
|
0
|
my @jcolnames = split(/\,/o, $joinspriteref->{use_fields}); |
1674
|
0
|
|
|
|
|
0
|
my %jcolHash; |
1675
|
0
|
|
|
|
|
0
|
for (my $i=0;$i<=$#jcolnames;$i++) |
1676
|
|
|
|
|
|
|
{ |
1677
|
0
|
|
|
|
|
0
|
$jcolHash{$jcolnames[$i]} = $i; |
1678
|
|
|
|
|
|
|
} |
1679
|
0
|
|
|
|
|
0
|
my @jcolindx; |
1680
|
0
|
|
|
|
|
0
|
for (my $i=0;$i<=$#{$joinunion1};$i++) |
|
0
|
|
|
|
|
0
|
|
1681
|
|
|
|
|
|
|
{ |
1682
|
0
|
|
|
|
|
0
|
$joinunion1->[$i] =~ s/[^\.]*\.(.*)/$1/; |
1683
|
|
|
|
|
|
|
$joinunion1->[$i] =~ tr/a-z/A-Z/ |
1684
|
0
|
0
|
|
|
|
0
|
unless ($joinspriteref->{sprite_CaseFieldNames}); |
1685
|
0
|
|
|
|
|
0
|
for (my $j=0;$j<=$#jcolnames;$j++) |
1686
|
|
|
|
|
|
|
{ |
1687
|
0
|
0
|
|
|
|
0
|
if ($joinunion1->[$i] eq $jcolnames[$j]) |
1688
|
|
|
|
|
|
|
{ |
1689
|
0
|
|
|
|
|
0
|
push (@jcolindx, $j); |
1690
|
0
|
|
|
|
|
0
|
last; |
1691
|
|
|
|
|
|
|
} |
1692
|
|
|
|
|
|
|
} |
1693
|
|
|
|
|
|
|
} |
1694
|
0
|
|
|
|
|
0
|
@ocolnames = split(/\,/o, $origsql); |
1695
|
0
|
|
|
|
|
0
|
my ($tbl,$fld); |
1696
|
0
|
|
|
|
|
0
|
my (@ocolwhich, %newtypes, %newlens, %newscales); |
1697
|
|
|
|
|
|
|
|
1698
|
0
|
|
|
|
|
0
|
I1: for (my $i=0;$i<=$#ocolnames;$i++) |
1699
|
|
|
|
|
|
|
{ |
1700
|
0
|
|
|
|
|
0
|
($tbl,$fld) = split(/\./o, $ocolnames[$i]); |
1701
|
0
|
|
|
|
|
0
|
$ocolnames[$i] = $fld; |
1702
|
0
|
0
|
0
|
|
|
0
|
if ($tbl eq $joinfids->[1] || $tbl eq $joinalii->[1]) |
1703
|
|
|
|
|
|
|
{ |
1704
|
0
|
|
|
|
|
0
|
$ocolwhich[$i] = 1; |
1705
|
0
|
|
|
|
|
0
|
for (my $j=0;$j<=$#jcolindx;$j++) |
1706
|
|
|
|
|
|
|
{ |
1707
|
0
|
0
|
|
|
|
0
|
if ($fld eq $jcolnames[$j]) |
1708
|
|
|
|
|
|
|
{ |
1709
|
0
|
|
|
|
|
0
|
$newtypes{$fld} = ${$joinspriteref->{types}}{$fld}; |
|
0
|
|
|
|
|
0
|
|
1710
|
0
|
|
|
|
|
0
|
$newlens{$fld} = ${$joinspriteref->{lengths}}{$fld}; |
|
0
|
|
|
|
|
0
|
|
1711
|
0
|
|
|
|
|
0
|
$newscales{$fld} = ${$joinspriteref->{scales}}{$fld}; |
|
0
|
|
|
|
|
0
|
|
1712
|
0
|
|
|
|
|
0
|
next I1; |
1713
|
|
|
|
|
|
|
} |
1714
|
|
|
|
|
|
|
} |
1715
|
|
|
|
|
|
|
} |
1716
|
|
|
|
|
|
|
else |
1717
|
|
|
|
|
|
|
{ |
1718
|
0
|
|
|
|
|
0
|
$ocolwhich[$i] = 0; |
1719
|
0
|
|
|
|
|
0
|
for (my $j=0;$j<=$#icolindx;$j++) |
1720
|
|
|
|
|
|
|
{ |
1721
|
0
|
0
|
|
|
|
0
|
if ($fld eq $icolnames[$j]) |
1722
|
|
|
|
|
|
|
{ |
1723
|
0
|
|
|
|
|
0
|
$newtypes{$fld} = ${$spriteref->{types}}{$fld}; |
|
0
|
|
|
|
|
0
|
|
1724
|
0
|
|
|
|
|
0
|
$newlens{$fld} = ${$spriteref->{lengths}}{$fld}; |
|
0
|
|
|
|
|
0
|
|
1725
|
0
|
|
|
|
|
0
|
$newscales{$fld} = ${$spriteref->{scales}}{$fld}; |
|
0
|
|
|
|
|
0
|
|
1726
|
0
|
|
|
|
|
0
|
next I1; |
1727
|
|
|
|
|
|
|
} |
1728
|
|
|
|
|
|
|
} |
1729
|
|
|
|
|
|
|
} |
1730
|
|
|
|
|
|
|
} |
1731
|
0
|
|
|
|
|
0
|
%{$spriteref->{types}} = %newtypes; |
|
0
|
|
|
|
|
0
|
|
1732
|
0
|
|
|
|
|
0
|
%{$spriteref->{lengths}} = %newlens; |
|
0
|
|
|
|
|
0
|
|
1733
|
0
|
|
|
|
|
0
|
%{$spriteref->{scales}} = %newscales; |
|
0
|
|
|
|
|
0
|
|
1734
|
0
|
|
|
|
|
0
|
$spriteref->{TYPE} = undef; |
1735
|
0
|
|
|
|
|
0
|
my $jrow = shift(@joinresv); |
1736
|
0
|
|
|
|
|
0
|
my $row = shift(@resv); |
1737
|
0
|
|
|
|
|
0
|
my $orig_whereclause = $sth->FETCH('sprite_where0'); |
1738
|
0
|
|
|
|
|
0
|
$orig_whereclause =~ s/\s+order\s+by\s+[\w\,\.\s]+$//is; |
1739
|
0
|
|
0
|
|
|
0
|
my @tblname = (($joinalii->[0] || $joinfids->[0]), |
|
|
|
0
|
|
|
|
|
1740
|
|
|
|
|
|
|
($joinalii->[1] || $joinfids->[1])); |
1741
|
0
|
|
|
|
|
0
|
my $validColumnnames = "(?:$tblname[0].".$spriteref->{use_fields}; |
1742
|
0
|
|
|
|
|
0
|
$validColumnnames =~ s/\,/\|$tblname[0]\./g; |
1743
|
0
|
|
|
|
|
0
|
$validColumnnames .= "|$tblname[1].".$joinspriteref->{use_fields}.')'; |
1744
|
0
|
|
|
|
|
0
|
$validColumnnames =~ s/\,/\|$tblname[1]\./g; |
1745
|
|
|
|
|
|
|
#DE-ALIAS ALL TABLE-ALIASES IN THE WHERE-CLAUSE. |
1746
|
0
|
0
|
|
|
|
0
|
if ($spriteref->{sprite_CaseTableNames}) #CONDITION ADDED 20040929. |
1747
|
|
|
|
|
|
|
{ |
1748
|
0
|
|
|
|
|
0
|
for (my $i=0;$i<=1;$i++) |
1749
|
|
|
|
|
|
|
{ |
1750
|
0
|
|
|
|
|
0
|
$orig_whereclause =~ s/ $joinalii->[$i]\./ $joinfids->[$i]\./gs; |
1751
|
|
|
|
|
|
|
} |
1752
|
|
|
|
|
|
|
} |
1753
|
|
|
|
|
|
|
else |
1754
|
|
|
|
|
|
|
{ |
1755
|
0
|
|
|
|
|
0
|
for (my $i=0;$i<=1;$i++) |
1756
|
|
|
|
|
|
|
{ |
1757
|
0
|
|
|
|
|
0
|
$orig_whereclause =~ s/ $joinalii->[$i]\./ $joinfids->[$i]\./igs; |
1758
|
|
|
|
|
|
|
} |
1759
|
|
|
|
|
|
|
} |
1760
|
|
|
|
|
|
|
|
1761
|
|
|
|
|
|
|
#NOW, BIND ALL BIND VARIABLES HERE! |
1762
|
0
|
|
|
|
|
0
|
$orig_whereclause =~ s/\\\'/\x02\^3jSpR1tE\x02/gso; #PROTECT ESCAPED DOUBLE-QUOTES. |
1763
|
0
|
|
|
|
|
0
|
$orig_whereclause =~ s/\'\'/\x02\^4jSpR1tE\x02/gso; #PROTECT DOUBLED DOUBLE-QUOTES. |
1764
|
0
|
|
|
|
|
0
|
$orig_whereclause =~ s/\'([^\']*?)\'/ |
1765
|
0
|
|
|
|
|
0
|
my ($str) = $1; |
1766
|
0
|
|
|
|
|
0
|
$str =~ s|\?|\x02\^2jSpR1tE\x02|gso; #PROTECT QUESTION-MARKS WITHIN QUOTES. |
1767
|
0
|
|
|
|
|
0
|
"'$str'"/egs; |
1768
|
0
|
|
|
|
|
0
|
$orig_whereclause =~ s/\x02\^4jSpR1tE\x02/\'\'/gso; #UNPROTECT DOUBLED DOUBLE-QUOTES. |
1769
|
0
|
|
|
|
|
0
|
$orig_whereclause =~ s/\x02\^3jSpR1tE\x02/\\\'/gso; #UNPROTECT ESCAPED DOUBLE-QUOTES. |
1770
|
|
|
|
|
|
|
|
1771
|
|
|
|
|
|
|
#CONVERT REMAINING QUESTION-MARKS TO BOUND VALUES. |
1772
|
|
|
|
|
|
|
|
1773
|
0
|
|
|
|
|
0
|
for (my $i = 0; $i < $numParam; $i++) |
1774
|
|
|
|
|
|
|
{ |
1775
|
0
|
|
|
|
|
0
|
$params->[$i] =~ s/\?/\x02\^2jSpR1tE\x02/gso; #ADDED 20001023 TO FIX BUG WHEN PARAMETER OTHER THAN LAST CONTAINS A "?"! |
1776
|
0
|
|
|
|
|
0
|
$orig_whereclause =~ s/\?/"'".$params->[$i]."'"/es; |
|
0
|
|
|
|
|
0
|
|
1777
|
|
|
|
|
|
|
} |
1778
|
0
|
|
|
|
|
0
|
$orig_whereclause =~ s/\x02\^2jSpR1tE\x02/\?/gso; #ADDED 20001023! - UNPROTECT PROTECTED "?"s. |
1779
|
0
|
|
|
|
|
0
|
my $cond = $spriteref->parse_expression($orig_whereclause, $validColumnnames); |
1780
|
|
|
|
|
|
|
#$cond =~ s/\$\_\-\>\{\w+\.(\w+)\}/BASE($icolHash{$1})/g; |
1781
|
|
|
|
|
|
|
#$cond =~ s/\$\_\-\>\{\w+\.(\w+)\}/\$baseresv\-\>\[\$icolHash\{$1\}\]/g; |
1782
|
|
|
|
|
|
|
#$cond =~ s/\$\_\-\>\{\w+\.(\w+)\}/JOIN($jcolHash{$1})/g; |
1783
|
0
|
|
|
|
|
0
|
$cond =~ s/\$\_\-\>\{$tblname[0]\.(\w+)\}/\$baserow\-\>\[\$icolHash\{$1\}\]/g; |
1784
|
0
|
|
|
|
|
0
|
$cond =~ s/\$\_\-\>\{$tblname[1]\.(\w+)\}/\$joinrow\-\>\[\$jcolHash\{$1\}\]/g; |
1785
|
|
|
|
|
|
|
#DONT NEED?$cond =~ s/[\r\n\t]/ /gs; |
1786
|
|
|
|
|
|
|
|
1787
|
|
|
|
|
|
|
#NOW EVAL THE *ORIGINAL* WHERE-CLAUSE CONDITION TO WEED OUT UNDESIRED RECORDS. |
1788
|
|
|
|
|
|
|
|
1789
|
0
|
|
|
|
|
0
|
my ($j, $k, $baserow, $joinrow, @newresv, @newrow); |
1790
|
0
|
0
|
|
|
|
0
|
if ($sth->FETCH('sprite_joinorder')) |
1791
|
|
|
|
|
|
|
{ |
1792
|
0
|
|
|
|
|
0
|
while (@joinresv) |
1793
|
|
|
|
|
|
|
{ |
1794
|
0
|
|
|
|
|
0
|
$joinrow = shift(@joinresv); |
1795
|
0
|
|
|
|
|
0
|
J2A: for ($j=0;$j<$row;$j++) |
1796
|
|
|
|
|
|
|
{ |
1797
|
0
|
|
|
|
|
0
|
$baserow = $resv[$j]; |
1798
|
0
|
|
|
|
|
0
|
$@ = ''; |
1799
|
0
|
|
0
|
|
|
0
|
$_ = ($cond !~ /\S/o || eval $cond); |
1800
|
0
|
0
|
|
|
|
0
|
next J2A unless ($_); |
1801
|
0
|
|
|
|
|
0
|
for ($k=0;$k<=$#ocolnames;$k++) |
1802
|
|
|
|
|
|
|
{ |
1803
|
0
|
0
|
|
|
|
0
|
if ($ocolwhich[$k]) |
1804
|
|
|
|
|
|
|
{ |
1805
|
0
|
|
|
|
|
0
|
push (@newrow, $joinrow->[$jcolHash{$ocolnames[$k]}]); |
1806
|
|
|
|
|
|
|
} |
1807
|
|
|
|
|
|
|
else |
1808
|
|
|
|
|
|
|
{ |
1809
|
0
|
|
|
|
|
0
|
push (@newrow, $baserow->[$icolHash{$ocolnames[$k]}]); |
1810
|
|
|
|
|
|
|
} |
1811
|
|
|
|
|
|
|
} |
1812
|
0
|
|
|
|
|
0
|
push (@newresv, [@newrow]); |
1813
|
0
|
|
|
|
|
0
|
@newrow = (); |
1814
|
|
|
|
|
|
|
} |
1815
|
|
|
|
|
|
|
} |
1816
|
|
|
|
|
|
|
} |
1817
|
|
|
|
|
|
|
else |
1818
|
|
|
|
|
|
|
{ |
1819
|
0
|
|
|
|
|
0
|
while (@resv) |
1820
|
|
|
|
|
|
|
{ |
1821
|
0
|
|
|
|
|
0
|
$baserow = shift(@resv); |
1822
|
0
|
|
|
|
|
0
|
J2B: for ($j=0;$j<$jrow;$j++) |
1823
|
|
|
|
|
|
|
{ |
1824
|
0
|
|
|
|
|
0
|
$joinrow = $joinresv[$j]; |
1825
|
0
|
|
|
|
|
0
|
$@ = ''; |
1826
|
0
|
|
0
|
|
|
0
|
$_ = ($cond !~ /\S/o || eval $cond); |
1827
|
0
|
0
|
|
|
|
0
|
next J2B unless ($_); |
1828
|
0
|
|
|
|
|
0
|
for ($k=0;$k<=$#ocolnames;$k++) |
1829
|
|
|
|
|
|
|
{ |
1830
|
0
|
0
|
|
|
|
0
|
if ($ocolwhich[$k]) |
1831
|
|
|
|
|
|
|
{ |
1832
|
0
|
|
|
|
|
0
|
push (@newrow, $joinrow->[$jcolHash{$ocolnames[$k]}]); |
1833
|
|
|
|
|
|
|
} |
1834
|
|
|
|
|
|
|
else |
1835
|
|
|
|
|
|
|
{ |
1836
|
0
|
|
|
|
|
0
|
push (@newrow, $baserow->[$icolHash{$ocolnames[$k]}]); |
1837
|
|
|
|
|
|
|
} |
1838
|
|
|
|
|
|
|
} |
1839
|
0
|
|
|
|
|
0
|
push (@newresv, [@newrow]); |
1840
|
0
|
|
|
|
|
0
|
@newrow = (); |
1841
|
|
|
|
|
|
|
} |
1842
|
|
|
|
|
|
|
} |
1843
|
|
|
|
|
|
|
} |
1844
|
0
|
|
|
|
|
0
|
@resv = (scalar(@newresv), @newresv); |
1845
|
0
|
|
0
|
|
|
0
|
$retval = $resv[0] || '0E0'; |
1846
|
|
|
|
|
|
|
} |
1847
|
|
|
|
|
|
|
} |
1848
|
|
|
|
|
|
|
} |
1849
|
|
|
|
|
|
|
else #SELECT SELECTED ZERO RECORDS. |
1850
|
|
|
|
|
|
|
{ |
1851
|
1
|
50
|
|
|
|
6
|
if ($spriteref->{lasterror}) |
1852
|
|
|
|
|
|
|
{ |
1853
|
0
|
|
|
|
|
0
|
DBI::set_err($sth, $spriteref->{lasterror}, $spriteref->{lastmsg}); |
1854
|
0
|
|
|
|
|
0
|
$retval = undef; |
1855
|
|
|
|
|
|
|
} |
1856
|
1
|
|
|
|
|
8
|
$retval = '0E0'; |
1857
|
|
|
|
|
|
|
} |
1858
|
|
|
|
|
|
|
|
1859
|
|
|
|
|
|
|
#EVERYTHING WORKED, SO SAVE SPRITE RESULT (# ROWS) AND FETCH FIELD INFO. |
1860
|
|
|
|
|
|
|
|
1861
|
|
|
|
|
|
|
#if ($retval) #CHGD TO NEXT 20020606. |
1862
|
12
|
50
|
33
|
|
|
57
|
if (defined($retval) && $retval) |
1863
|
|
|
|
|
|
|
{ |
1864
|
12
|
|
|
|
|
55
|
$sth->{'driver_rows'} = $retval; # number of rows |
1865
|
12
|
|
|
|
|
25
|
$sth->{'sprite_rows'} = $retval; # number of rows |
1866
|
12
|
|
|
|
|
56
|
$sth->STORE('sprite_rows', $retval); |
1867
|
12
|
|
|
|
|
30
|
$sth->STORE('driver_rows', $retval); |
1868
|
|
|
|
|
|
|
} |
1869
|
|
|
|
|
|
|
else |
1870
|
|
|
|
|
|
|
{ |
1871
|
0
|
|
|
|
|
0
|
$sth->{'driver_rows'} = 0; # number of rows |
1872
|
0
|
|
|
|
|
0
|
$sth->{'sprite_rows'} = 0; # number of rows |
1873
|
0
|
|
|
|
|
0
|
$sth->STORE('sprite_rows', 0); |
1874
|
0
|
|
|
|
|
0
|
$sth->STORE('driver_rows', 0); |
1875
|
|
|
|
|
|
|
} |
1876
|
|
|
|
|
|
|
|
1877
|
|
|
|
|
|
|
#### NOTE #### IF THIS FAILS, IT PROBABLY NEEDS TO BE "sprite_rows"? |
1878
|
|
|
|
|
|
|
|
1879
|
12
|
|
|
|
|
33
|
shift @resv; #REMOVE 1ST COLUMN FROM DATA RETURNED (THE SPRITE RESULT). |
1880
|
12
|
50
|
|
|
|
56
|
my @l = ($#ocolnames >= 0) ? @ocolnames : split(/,/,$spriteref->{use_fields}); |
1881
|
12
|
|
|
|
|
45
|
$sth->STORE('NUM_OF_FIELDS',($#l+1)); |
1882
|
12
|
|
|
|
|
37
|
my (@keyfields) = split(',', $spriteref->{key_fields}); #ADDED 20030520 TO IMPROVE NULLABLE. |
1883
|
|
|
|
|
|
|
|
1884
|
12
|
100
|
|
|
|
31
|
unless ($spriteref->{TYPE}) |
1885
|
|
|
|
|
|
|
{ |
1886
|
10
|
|
|
|
|
15
|
@{$spriteref->{NAME}} = @l; |
|
10
|
|
|
|
|
31
|
|
1887
|
10
|
|
|
|
|
34
|
for my $i (0..$#l) |
1888
|
|
|
|
|
|
|
{ |
1889
|
22
|
100
|
|
|
|
33
|
if (defined ${$spriteref->{types}}{$l[$i]}) |
|
22
|
|
|
|
|
54
|
|
1890
|
|
|
|
|
|
|
{ |
1891
|
19
|
|
|
|
|
23
|
${$spriteref->{TYPE}}[$i] = $typehash{"\U${$spriteref->{types}}{$l[$i]}\E"}; |
|
19
|
|
|
|
|
31
|
|
|
19
|
|
|
|
|
46
|
|
1892
|
19
|
|
|
|
|
25
|
${$spriteref->{PRECISION}}[$i] = ${$spriteref->{lengths}}{$l[$i]}; |
|
19
|
|
|
|
|
40
|
|
|
19
|
|
|
|
|
34
|
|
1893
|
19
|
|
|
|
|
29
|
${$spriteref->{SCALE}}[$i] = ${$spriteref->{scales}}{$l[$i]}; |
|
19
|
|
|
|
|
32
|
|
|
19
|
|
|
|
|
30
|
|
1894
|
|
|
|
|
|
|
} |
1895
|
|
|
|
|
|
|
else |
1896
|
|
|
|
|
|
|
{ |
1897
|
3
|
|
|
|
|
6
|
${$spriteref->{TYPE}}[$i] = ''; |
|
3
|
|
|
|
|
6
|
|
1898
|
3
|
|
|
|
|
6
|
${$spriteref->{PRECISION}}[$i] = 0; |
|
3
|
|
|
|
|
6
|
|
1899
|
3
|
|
|
|
|
4
|
${$spriteref->{SCALE}}[$i] = 0; |
|
3
|
|
|
|
|
7
|
|
1900
|
|
|
|
|
|
|
} |
1901
|
22
|
|
|
|
|
30
|
${$spriteref->{NULLABLE}}[$i] = 1; |
|
22
|
|
|
|
|
62
|
|
1902
|
22
|
|
|
|
|
37
|
foreach my $j (@keyfields) #ADDED 20030520 TO IMPROVE NULLABLE. |
1903
|
|
|
|
|
|
|
{ |
1904
|
21
|
100
|
|
|
|
26
|
if (${$spriteref->{NAME}}[$i] eq $j) |
|
21
|
|
|
|
|
48
|
|
1905
|
|
|
|
|
|
|
{ |
1906
|
3
|
|
|
|
|
5
|
${$spriteref->{NULLABLE}}[$i] = 0; |
|
3
|
|
|
|
|
6
|
|
1907
|
3
|
|
|
|
|
7
|
last; |
1908
|
|
|
|
|
|
|
} |
1909
|
|
|
|
|
|
|
} |
1910
|
|
|
|
|
|
|
} |
1911
|
|
|
|
|
|
|
} |
1912
|
|
|
|
|
|
|
|
1913
|
|
|
|
|
|
|
#TRANSFER SPRITE'S FIELD DATA TO DBI. |
1914
|
|
|
|
|
|
|
|
1915
|
12
|
|
|
|
|
29
|
$sth->{'driver_data'} = \@resv; |
1916
|
12
|
|
|
|
|
48
|
$sth->STORE('sprite_data', \@resv); |
1917
|
|
|
|
|
|
|
#$sth->STORE('sprite_rows', ($#resv+1)); # number of rows |
1918
|
12
|
|
|
|
|
18
|
$sth->{'TYPE'} = \@{$spriteref->{TYPE}}; |
|
12
|
|
|
|
|
27
|
|
1919
|
12
|
|
|
|
|
18
|
$sth->{'NAME'} = \@{$spriteref->{NAME}}; |
|
12
|
|
|
|
|
18
|
|
1920
|
12
|
|
|
|
|
23
|
for (my $i=0;$i<=$#{$sth->{'NAME'}};$i++) |
|
40
|
|
|
|
|
74
|
|
1921
|
|
|
|
|
|
|
{ |
1922
|
|
|
|
|
|
|
$sth->{'NAME'}->[$i] = $spriteref->{ASNAMES}->{$sth->{'NAME'}->[$i]} |
1923
|
28
|
50
|
|
|
|
68
|
if ($spriteref->{ASNAMES}->{$sth->{'NAME'}->[$i]}); |
1924
|
|
|
|
|
|
|
} |
1925
|
12
|
|
|
|
|
14
|
$sth->{'PRECISION'} = \@{$spriteref->{PRECISION}}; |
|
12
|
|
|
|
|
25
|
|
1926
|
12
|
|
|
|
|
17
|
$sth->{'SCALE'} = \@{$spriteref->{SCALE}}; |
|
12
|
|
|
|
|
21
|
|
1927
|
12
|
|
|
|
|
14
|
$sth->{'NULLABLE'} = \@{$spriteref->{NULLABLE}}; |
|
12
|
|
|
|
|
24
|
|
1928
|
12
|
|
|
|
|
37
|
$sth->STORE('sprite_resv',\@resv); |
1929
|
|
|
|
|
|
|
#ADDED NEXT LINE 20020905 TO SUPPORT DBIx::GeneratedKey! |
1930
|
12
|
|
|
|
|
58
|
$sth->{Database}->STORE('sprite_insertid', $spriteref->{'sprite_lastsequence'}); |
1931
|
12
|
50
|
|
|
|
25
|
if (defined $retval) |
1932
|
|
|
|
|
|
|
{ |
1933
|
12
|
50
|
|
|
|
77
|
return $retval ? $retval : '0E0'; |
1934
|
|
|
|
|
|
|
} |
1935
|
0
|
|
|
|
|
0
|
return undef; |
1936
|
|
|
|
|
|
|
} |
1937
|
|
|
|
|
|
|
|
1938
|
|
|
|
|
|
|
sub fetchrow_arrayref |
1939
|
|
|
|
|
|
|
{ |
1940
|
8
|
|
|
8
|
|
412
|
my($sth) = @_; |
1941
|
8
|
|
|
|
|
30
|
my $data = $sth->FETCH('driver_data'); |
1942
|
8
|
|
|
|
|
15
|
my $row = shift @$data; |
1943
|
|
|
|
|
|
|
#return undef if (!$row || !scalar(@$row)); #CHGD. TO NEXT 20040913 TO AVOID _FBAV ERROR IF NO ROWS RETURNED! |
1944
|
8
|
100
|
66
|
|
|
52
|
return undef if (!$row || !scalar(@$row)); |
1945
|
|
|
|
|
|
|
#my ($longreadlen) = $sth->{Database}->FETCH('LongReadLen'); #CHGD. TO NEXT 20020606 AS WORKAROUND FOR DBI::PurePerl; |
1946
|
6
|
|
50
|
|
|
29
|
my ($longreadlen) = $sth->{Database}->FETCH('LongReadLen') || 0; |
1947
|
6
|
50
|
|
|
|
18
|
if ($longreadlen > 0) |
1948
|
|
|
|
|
|
|
{ |
1949
|
6
|
50
|
|
|
|
22
|
if ($sth->FETCH('ChopBlanks')) |
1950
|
|
|
|
|
|
|
{ |
1951
|
0
|
|
|
|
|
0
|
for (my $i=0;$i<=$#{$row};$i++) |
|
0
|
|
|
|
|
0
|
|
1952
|
|
|
|
|
|
|
{ |
1953
|
0
|
0
|
|
|
|
0
|
if (${$sth->{TYPE}}[$i] < 0) #LONG, LONG RAW, etc. |
|
0
|
|
|
|
|
0
|
|
1954
|
|
|
|
|
|
|
{ |
1955
|
0
|
|
|
|
|
0
|
my ($t) = substr($row->[$i],0,$longreadlen); |
1956
|
0
|
0
|
0
|
|
|
0
|
return undef unless (($row->[$i] eq $t) || $sth->{Database}->FETCH('LongTruncOk')); |
1957
|
0
|
|
|
|
|
0
|
$row->[$i] = $t; |
1958
|
|
|
|
|
|
|
} |
1959
|
|
|
|
|
|
|
} |
1960
|
0
|
|
|
|
|
0
|
map { $_ =~ s/\s+$//; } @$row; |
|
0
|
|
|
|
|
0
|
|
1961
|
|
|
|
|
|
|
} |
1962
|
|
|
|
|
|
|
} |
1963
|
|
|
|
|
|
|
else |
1964
|
|
|
|
|
|
|
{ |
1965
|
0
|
0
|
|
|
|
0
|
if ($sth->FETCH('ChopBlanks')) |
1966
|
|
|
|
|
|
|
{ |
1967
|
0
|
|
|
|
|
0
|
map { $_ =~ s/\s+$//; } @$row; |
|
0
|
|
|
|
|
0
|
|
1968
|
|
|
|
|
|
|
} |
1969
|
|
|
|
|
|
|
} |
1970
|
6
|
|
|
|
|
13
|
my $myres; |
1971
|
6
|
|
|
|
|
11
|
eval { $myres = $sth->_set_fbav($row); }; |
|
6
|
|
|
|
|
39
|
|
1972
|
|
|
|
|
|
|
# $myres = $sth->_set_fbav($row); |
1973
|
6
|
|
|
|
|
30
|
return $myres; |
1974
|
|
|
|
|
|
|
} |
1975
|
|
|
|
|
|
|
|
1976
|
|
|
|
|
|
|
*fetch = \&fetchrow_arrayref; # required alias for fetchrow_arrayref |
1977
|
|
|
|
|
|
|
sub rows |
1978
|
|
|
|
|
|
|
{ |
1979
|
0
|
|
|
0
|
|
0
|
my($sth) = @_; |
1980
|
0
|
0
|
0
|
|
|
0
|
return $sth->FETCH('driver_rows') or $sth->FETCH('sprite_rows') or $sth->{drv_rows}; |
1981
|
|
|
|
|
|
|
} |
1982
|
|
|
|
|
|
|
#### NOTE #### IF THIS FAILS, IT PROBABLY NEEDS TO BE "sprite_rows"? |
1983
|
|
|
|
|
|
|
|
1984
|
|
|
|
|
|
|
|
1985
|
|
|
|
|
|
|
sub STORE |
1986
|
|
|
|
|
|
|
{ |
1987
|
137
|
|
|
137
|
|
258
|
my($dbh, $attr, $val) = @_; |
1988
|
137
|
50
|
|
|
|
253
|
if ($attr eq 'AutoCommit') |
1989
|
|
|
|
|
|
|
{ |
1990
|
|
|
|
|
|
|
# AutoCommit is currently the only standard attribute we have |
1991
|
|
|
|
|
|
|
# to consider. |
1992
|
|
|
|
|
|
|
#if (!$val) { die "Can't disable AutoCommit"; } |
1993
|
|
|
|
|
|
|
|
1994
|
0
|
|
|
|
|
0
|
$dbh->{AutoCommit} = $val; |
1995
|
0
|
|
|
|
|
0
|
return 1; |
1996
|
|
|
|
|
|
|
} |
1997
|
137
|
100
|
|
|
|
333
|
if ($attr =~ /^sprite/o) |
1998
|
|
|
|
|
|
|
{ |
1999
|
|
|
|
|
|
|
# Handle only our private attributes here |
2000
|
|
|
|
|
|
|
# Note that we could trigger arbitrary actions. |
2001
|
|
|
|
|
|
|
# Ideally we should catch unknown attributes. |
2002
|
102
|
|
|
|
|
239
|
$dbh->{$attr} = $val; # Yes, we are allowed to do this, |
2003
|
102
|
|
|
|
|
206
|
return 1; # but only for our private attributes |
2004
|
|
|
|
|
|
|
} |
2005
|
|
|
|
|
|
|
# Else pass up to DBI to handle for us |
2006
|
35
|
|
|
|
|
65
|
eval {$dbh->SUPER::STORE($attr, $val);}; |
|
35
|
|
|
|
|
186
|
|
2007
|
|
|
|
|
|
|
} |
2008
|
|
|
|
|
|
|
|
2009
|
|
|
|
|
|
|
sub FETCH |
2010
|
|
|
|
|
|
|
{ |
2011
|
12
|
|
|
12
|
|
24
|
my($dbh, $attr) = @_; |
2012
|
12
|
50
|
|
|
|
37
|
if ($attr eq 'AutoCommit') { return $dbh->{AutoCommit}; } |
|
0
|
|
|
|
|
0
|
|
2013
|
12
|
100
|
|
|
|
44
|
if ($attr =~ /^sprite_/o) |
2014
|
|
|
|
|
|
|
{ |
2015
|
|
|
|
|
|
|
# Handle only our private attributes here |
2016
|
|
|
|
|
|
|
# Note that we could trigger arbitrary actions. |
2017
|
6
|
|
|
|
|
22
|
return $dbh->{$attr}; # Yes, we are allowed to do this, |
2018
|
|
|
|
|
|
|
# but only for our private attributes |
2019
|
0
|
|
|
|
|
0
|
return $dbh->{$attr}; |
2020
|
|
|
|
|
|
|
} |
2021
|
|
|
|
|
|
|
# Else pass up to DBI to handle |
2022
|
6
|
|
|
|
|
36
|
$dbh->SUPER::FETCH($attr); |
2023
|
|
|
|
|
|
|
} |
2024
|
|
|
|
|
|
|
|
2025
|
|
|
|
|
|
|
sub DESTROY #ADDED 20010221 |
2026
|
|
|
|
10
|
|
|
{ |
2027
|
|
|
|
|
|
|
} |
2028
|
|
|
|
|
|
|
|
2029
|
|
|
|
|
|
|
1; |
2030
|
|
|
|
|
|
|
|
2031
|
|
|
|
|
|
|
package DBD::Sprite; # ====== HAD TO HAVE TO PREVENT MAKE ERROR! ====== |
2032
|
|
|
|
|
|
|
|
2033
|
|
|
|
|
|
|
1; |
2034
|
|
|
|
|
|
|
|
2035
|
|
|
|
|
|
|
__END__ |