Hide Show 433 lines of Pod
no
warnings
'uninitialized'
;
require
5.002;
our
(
$XMLavailable
,
$results
);
eval
'use XML::Simple; $XMLavailable = 1; 1'
;
eval
{
require
'OraSpriteFns.pl'
;};
use
vars
qw ($VERSION
$LOCK_SH
$LOCK_EX
);
$JSprite::VERSION
=
'6.12'
;
$JSprite::LOCK_SH
= 1;
$JSprite::LOCK_EX
= 2;
my
$NUMERICTYPES
=
'^(NUMBER|FLOAT|DOUBLE|INT|INTEGER|NUM|AUTONUMBER|AUTO|AUTO_INCREMENT|DECIMAL|TINYINT|BIGINT|DOUBLE)$'
;
my
$STRINGTYPES
=
'^(VARCHAR2|CHAR|VARCHAR|DATE|LONG|BLOB|MEMO|RAW|TEXT)$'
;
my
$BLOBTYPES
=
'^(LONG.*|.*?LOB|MEMO|.FILE)$'
;
my
$REFTYPES
=
'^(LONG.*|.FILE)$'
;
my
@perlconds
= ();
my
@perlmatches
= ();
my
$sprite_user
=
''
;
our
(
$errdetails
);
sub
new
{
my
$class
=
shift
;
my
$self
;
$self
= {
commands
=>
'select|update|delete|alter|insert|create|drop|truncate|primary_key_info'
,
column
=>
'[A-Za-z0-9][\w\x80-\xFF]*'
,
_select
=>
'[\w\x80-\xFF\*,\s\~]+'
,
path
=>
'[\w\x80-\xFF\-\/\.\:\~\\\\]+'
,
table
=>
''
,
file
=>
''
,
table
=>
''
,
ext
=>
''
,
directory
=>
''
,
timestamp
=> 0,
_read
=>
','
,
_write
=>
','
,
_record
=>
"\n"
,
fields
=> {},
fieldregex
=>
''
,
use_fields
=>
''
,
key_fields
=>
''
,
order
=> [],
types
=> {},
lengths
=> {},
scales
=> {},
defaults
=> {},
records
=> [],
platform
=>
'Unix'
,
fake_lock
=> 0,
default_lock
=>
'Sprite.lck'
,
sprite_lock_file
=>
''
,
lock_handle
=>
''
,
default_try
=> 10,
sprite_lock_try
=>
''
,
lock_sleep
=> 1,
errors
=> {},
lasterror
=> 0,
lastmsg
=>
''
,
CaseTableNames
=> 0,
LongTruncOk
=> 0,
LongReadLen
=> 0,
RaiseError
=> 0,
silent
=> 0,
dirty
=> 0,
StrictCharComp
=> 0,
sprite_forcereplace
=> 0,
sprite_Crypt
=> 0,
sprite_reclimit
=> 0,
sprite_sizelimit
=> 0,
sprite_actlimit
=> 0,
dbuser
=>
''
,
dbname
=>
''
,
CBC
=> 0,
sprite_xsl
=>
''
,
sprite_CaseFieldNames
=> 0,
sprite_lastsequence
=>
''
,
sprite_nocase
=> 0,
ASNAMES
=> {},
};
$self
->{separator} = {
Unix
=>
'/'
,
Mac
=>
':'
,
PC
=>
'\\\\'
,
VMS
=>
'/'
};
$self
->{maxsizes} = {
'LONG RAW'
=> 2147483647,
'RAW'
=> 255,
'LONG'
=> 2147483647,
'CHAR'
=> 255,
'NUMBER'
=> 38,
'AUTONUMBER'
=> 38,
'DOUBLE'
=> 15,
'DATE'
=> 19,
'VARCHAR'
=> 2000,
'VARCHAR2'
=> 2000,
'BOOLEAN'
=> 1,
'BLOB'
=> 2147483647,
'MEMO'
=> 2147483647,
};
bless
$self
,
$class
;
for
(
my
$i
=0;
$i
<
scalar
(
@_
);
$i
+=2)
{
$self
->{
$_
[
$i
]} =
$_
[
$i
+1];
}
$self
->initialize;
return
$self
;
}
sub
initialize
{
my
$self
=
shift
;
$sprite_user
=
$self
->{
'dbuser'
};
$self
->define_errors;
$self
->set_os ($^O)
if
(
defined
$^O);
if
(
$self
->{sprite_Crypt})
{
my
(
@cryptinfo
) =
split
(/\;/,
$self
->{sprite_Crypt});
unshift
(
@cryptinfo
,
'IDEA'
)
if
(
$#cryptinfo
< 1);
unshift
(
@cryptinfo
,
'Crypt::CBC'
)
if
(
$#cryptinfo
< 2);
$self
->{sprite_Crypt} = 1;
$self
->{sprite_Crypt} = 2
if
(
$cryptinfo
[0] =~ s/^encrypt\=//i);
$self
->{sprite_Crypt} = 3
if
(
$cryptinfo
[0] =~ s/^decrypt\=//i);
$cryptinfo
[0] =
'Crypt::'
.
$cryptinfo
[0]
unless
(
$cryptinfo
[0] =~ /\:\:/);
eval
"require $cryptinfo[0]"
;
if
($@)
{
$errdetails
= $@;
$self
->display_error (-526);
}
else
{
eval
{
$self
->{CBC} = Crypt::CBC->new(
$cryptinfo
[2],
$cryptinfo
[1]); };
if
($@)
{
$errdetails
=
"Can't find/use module \"$cryptinfo[1].pm\"? ($@)!"
;
$self
->display_error (-526);
}
}
}
return
$self
;
}
sub
set_delimiter
{
my
(
$self
,
$type
,
$delimiter
) =
@_
;
$type
||=
'other'
;
$delimiter
||=
$self
->{_read} ||
$self
->{_write};
$type
=~ s/^-//;
$type
=~
tr
/A-Z/a-z/;
if
(
$type
eq
'read'
) {
$self
->{_read} =
$delimiter
;
}
elsif
(
$type
eq
'write'
) {
$self
->{_write} =
$delimiter
;
}
elsif
(
$type
eq
'record'
) {
$self
->{_record} =
$delimiter
;
}
else
{
$self
->{_read} =
$self
->{_write} =
$delimiter
;
}
return
(1);
}
sub
set_os
{
my
(
$self
,
$platform
) =
@_
;
return
$self
->{platform}
unless
(
$platform
);
$platform
=~ s/\s//g;
if
(
$platform
=~ /(?:darwin|bsdos)/i)
{
$self
->{platform} =
'Unix'
;
}
elsif
(
$platform
=~ /(OS2|Win|DOS)/i)
{
$self
->{platform} =
'PC'
;
}
elsif
(
$platform
=~ /^Mac(?:OS|intosh)?$/i)
{
$self
->{platform} =
'Mac'
;
}
elsif
(
$platform
=~ /^VMS$/i)
{
$self
->{platform} =
'VMS'
;
}
else
{
$self
->{platform} =
'Unix'
;
}
return
(1);
}
sub
set_db_dir
{
my
(
$self
,
$directory
) =
@_
;
return
(0)
unless
(
$directory
);
stat
(
$directory
);
if
( (-d _) && (-e _) && (-r _) ) {
$self
->{directory} =
$directory
;
return
(1);
}
else
{
return
(0);
}
}
sub
set_db_ext
{
my
(
$self
,
$ext
) =
@_
;
return
(0)
unless
(
$ext
);
stat
(
$ext
);
$self
->{ext} =
$ext
;
return
(1);
}
sub
get_path_info
{
my
(
$self
,
$file
) =
@_
;
my
(
$separator
,
$path
,
$name
,
$full
);
$separator
=
$self
->{separator}->{
$self
->{platform} };
(
$path
,
$name
) =
$file
=~ m|(.*?)([^
$separator
]+)$|o;
$name
=~
tr
/A-Z/a-z/
unless
(
$self
->{CaseTableNames});
if
(
$path
) {
$full
=
$file
;
}
else
{
$path
=
$self
->{directory};
$path
.=
$separator
;
$full
=
$path
.
$name
;
}
return
wantarray
? (
$path
,
$name
) :
$full
;
}
sub
set_lock_file
{
my
(
$self
,
$file
,
$lock_try
) =
@_
;
if
(!
$file
|| !
$lock_try
) {
return
(0);
}
else
{
$self
->{sprite_lock_file} =
$file
;
$self
->{sprite_lock_try} =
$lock_try
;
return
(1);
}
}
sub
lock
{
my
$self
=
shift
;
my
$count
;
$self
->{sprite_lock_file} ||=
$self
->{default_lock};
$self
->{sprite_lock_file} =
$self
->get_path_info (
$self
->{sprite_lock_file});
$self
->{sprite_lock_try} ||=
$self
->{default_try};
local
*FILE
;
$count
= 0;
while
(++
$count
<=
$self
->{sprite_lock_try}) {
if
(
sysopen
(FILE,
$self
->{sprite_lock_file},
O_WRONLY|O_EXCL|O_CREAT, 0644)) {
$self
->{fake_lock} = 1;
$self
->{lock_handle} =
*FILE
;
last
;
}
else
{
select
(
undef
,
undef
,
undef
,
$self
->{lock_sleep});
}
}
return
$self
->{fake_lock};
}
sub
unlock
{
my
$self
=
shift
;
if
(
$self
->{fake_lock}) {
close
(
$self
->{lock_handle}) ||
return
(0);
unlink
(
$self
->{sprite_lock_file}) ||
return
(0);
$self
->{fake_lock} = 0;
$self
->{lock_handle} =
''
;
}
return
(1);
}
sub
sql
{
my
(
$self
,
$query
) =
@_
;
my
(
$command
,
$status
);
return
wantarray
? () : -514
unless
(
$query
);
$sprite_user
=
$self
->{
'dbuser'
};
$self
->{lasterror} = 0;
$self
->{lastmsg} =
''
;
$query
=~ s/^\s*(.*?)\s*$/$1/s;
$command
=
''
;
if
(
$query
=~ /^(
$self
->{commands})/io)
{
$command
= $1;
$command
=~
tr
/A-Z/a-z/;
$status
=
$self
->
$command
(
$query
);
if
(
ref
(
$status
) eq
'ARRAY'
)
{
return
wantarray
?
@$status
:
$status
;
}
else
{
if
(
$status
< 0)
{
$self
->display_error (
$status
);
return
wantarray
? () :
$status
;
}
else
{
return
wantarray
? (
$status
) :
$status
;
}
}
}
else
{
return
wantarray
? () : -514;
}
}
sub
display_error
{
my
(
$self
,
$error
) =
@_
;
my
$other
= $@ || $! ||
'None'
;
print
STDERR
<<Error_Message unless ($self->{silent});
Oops! Sprite encountered the following error when processing your request:
($error) $self->{errors}->{$error} ($errdetails)
Here's some more information to help you:
file: $self->{file}
$other
Error_Message
$self
->{lasterror} =
$error
;
$self
->{lastmsg} =
"$error:"
.
$self
->{errors}->{
$error
};
$self
->{lastmsg} .=
'('
.
$errdetails
.
')'
if
(
$errdetails
);
$errdetails
=
''
;
die
$self
->{lastmsg}
if
(
$self
->{RaiseError});
return
(1);
}
sub
commit
{
my
(
$self
,
$file
) =
@_
;
my
(
$status
,
$full_path
);
$status
= 1;
return
$status
unless
(
$self
->{dirty});
if
(
$file
)
{
$full_path
=
$self
->get_path_info (
$file
);
$full_path
.=
$self
->{ext}
if
(
$self
->{ext});
}
else
{
$full_path
=
$self
->{file};
}
$status
=
$self
->write_file (
$full_path
);
$self
->display_error (
$status
)
if
(
$status
<= 0);
return
undef
if
(
$status
<= 0);
my
$blobglob
=
$full_path
;
$blobglob
=~ s/
$self
->{ext}$/\_\*\_$$\.tmp/;
my
@tempblobs
;
eval
qq|\@tempblobs = <$blobglob>|
;
my
(
$blobfile
,
$tempfile
);
my
$bloberror
= 0;
while
(
@tempblobs
)
{
$tempfile
=
shift
(
@tempblobs
);
$blobfile
=
$tempfile
;
$blobfile
=~ s/\_$$\.tmp/\.ldt/;
unlink
$blobfile
if
(
$self
->{sprite_forcereplace} && -w
$blobfile
&& -e
$tempfile
);
$bloberror
= $?.
':'
.$@
if
($?);
rename
(
$tempfile
,
$blobfile
) or (
$bloberror
=
"Could not rename $tempfile to $blobfile ("
.$!.
')'
);
last
if
(
$bloberror
);
}
if
(
$bloberror
)
{
$errdetails
=
$bloberror
;
$self
->display_error (-528);
return
undef
;
}
else
{
$blobglob
=
$self
->{directory}.
$self
->{separator}->{
$self
->{platform} }
.
$self
->{table}.
"_*_$$.del"
;
@tempblobs
= ();
eval
qq|\@tempblobs = <$blobglob>|
;
while
(
@tempblobs
)
{
$tempfile
=
shift
(
@tempblobs
);
unlink
$tempfile
;
}
$self
->{dirty} = 0;
}
return
$status
;
}
sub
xclose
{
my
(
$self
,
$file
) =
@_
;
my
$status
=
$self
->commit(
$file
);
undef
$self
;
return
$status
;
}
sub
define_errors
{
my
$self
=
shift
;
my
$errors
;
$errors
= {};
$errors
->{
'-501'
} =
'Could not open specified database.'
;
$errors
->{
'-502'
} =
'Specified column(s) not found.'
;
$errors
->{
'-503'
} =
'Incorrect format in [select] statement.'
;
$errors
->{
'-504'
} =
'Incorrect format in [update] statement.'
;
$errors
->{
'-505'
} =
'Incorrect format in [delete] statement.'
;
$errors
->{
'-506'
} =
'Incorrect format in [add/drop column] statement.'
;
$errors
->{
'-507'
} =
'Incorrect format in [alter table] statement.'
;
$errors
->{
'-508'
} =
'Incorrect format in [insert] command.'
;
$errors
->{
'-509'
} =
'The no. of columns does not match no. of values.'
;
$errors
->{
'-510'
} =
'A severe error! Check your query carefully.'
;
$errors
->{
'-511'
} =
'Cannot write the database to output file.'
;
$errors
->{
'-512'
} =
'Unmatched quote in expression.'
;
$errors
->{
'-513'
} =
'Need to open the database first!'
;
$errors
->{
'-514'
} =
'Please specify a valid query.'
;
$errors
->{
'-515'
} =
'Cannot get lock on database file.'
;
$errors
->{
'-516'
} =
'Cannot delete temp. lock file.'
;
$errors
->{
'-517'
} =
"Built-in function failed ($@)."
;
$errors
->{
'-518'
} =
"Unique Key Constraint violated."
;
$errors
->{
'-519'
} =
"Field would have to be truncated."
;
$errors
->{
'-520'
} =
"Can not create existing table (drop first!)."
;
$errors
->{
'-521'
} =
"Can not change datatype on non-empty table."
;
$errors
->{
'-522'
} =
"Can not decrease field-size on non-empty table."
;
$errors
->{
'-523'
} =
"Special table \"DUAL\" is READONLY!"
;
$errors
->{
'-524'
} =
"Can't store non-NULL value into AUTOSEQUENCE!"
;
$errors
->{
'-525'
} =
"Can't update AUTOSEQUENCE field!"
;
$errors
->{
'-526'
} =
"Can't find encryption modules"
;
$errors
->{
'-527'
} =
"Database illedgable - wrong encryption key/method?"
;
$errors
->{
'-528'
} =
"Could not read/write BLOB file!"
;
$errors
->{
'-529'
} =
"Conversion between BLOB and nonBLOB types not (yet) supported!"
;
$errors
->{
'-530'
} =
'Incorrect format in [create] command.'
;
$errors
->{
'-531'
} =
'Encryption of XML databases not supported.'
;
$errors
->{
'-532'
} =
'XML requested, but XML::Simple module not available!'
;
$errors
->{
'-533'
} =
'Incorrect format in [truncate] statement.'
;
$self
->{errors} =
$errors
;
return
(1);
}
sub
parse_expression
{
my
(
$self
,
$query
,
$colmlist
) =
@_
;
return
unless
(
$query
);
my
(
$column
,
@strings
,
%numopmap
,
%stropmap
,
$numops
,
$strops
,
$special
);
$colmlist
||=
join
(
'|'
,@{
$self
->{order}});
my
(
$psuedocols
) =
"CURRVAL|NEXTVAL"
;
unless
(
$colmlist
=~ /\S/o)
{
$self
->{file} =~
tr
/A-Z/a-z/
unless
(
$self
->{CaseTableNames});
$colmlist
=
&load_columninfo
(
$self
,
'|'
);
return
$colmlist
if
(
$colmlist
=~ /^\-?\d+$/o);
}
$column
=
$self
->{column};
@strings
= ();
%numopmap
= (
'='
=>
'eq'
,
'=='
=>
'eq'
,
'>='
=>
'ge'
,
'<='
=>
'le'
,
'>'
=>
'gt'
,
'<'
=>
'lt'
,
'!='
=>
'ne'
,
'<>'
=>
'ne'
);
%stropmap
= (
'eq'
=>
'=='
,
'ge'
=>
'>='
,
'le'
=>
'<='
,
'gt'
=>
'>'
,
'lt'
=>
'<'
,
'ne'
=>
'!='
,
'='
=>
'=='
);
$numops
=
join
'|'
,
keys
%numopmap
;
$strops
=
join
'|'
,
keys
%stropmap
;
$special
=
"$strops|and|or"
;
$query
=~ s/\\\\/\x02\^2jSpR1tE\x02/gso;
$query
=~ s/\\\
'|\'\'/\^3jSpR1tE/gso; #20000201 #PROTECT "", \", '
', AND \'.
my
(
$i
,
$j
,
$j2
,
$k
);
my
$caseopt
= (
$self
->{sprite_nocase} ?
'i'
:
''
);
while
(1)
{
$i
= 0;
$i
= (
$query
=~ s|\b(
$colmlist
)\s+not\s+like\s+|$1 !^ |is);
$i
= (
$query
=~ s|\b(
$colmlist
)\s+like\s+|$1 =^ |is)
unless
(
$i
);
if
(
$i
)
{
if
(
$query
=~ s/([\=\!]\^\s*)(["'])(.*?)\2/$1$2$3$2
$caseopt
/s)
{
$j
=
"$1$2"
;
$i
= $3;
my
$iquoted
=
$i
;
$iquoted
=~ s/([\\\|\(\)\[\{\^\$\*\+\?\.])/\\$1/gs;
my
(
$k
) =
"\^$iquoted\$"
;
$k
=~ s/^\^%//so;
$k
=~ s/%\$$//s;
$j2
=
$j
;
$j2
=~ s/^(.)\^/$1~/s;
$k
=~ s/_/./gso;
$query
=~ s/\Q
$j
$i
\E/
$j2
$k
/s;
}
}
else
{
last
;
}
}
1
while
(
$query
=~ s|([!=][~\^])\s*([a-zA-Z_]+)(.*)$|
my
(
$one
,
$two
,
$three
) = ($1, $2, $3);
my
(
$parincnt
) = 0;
my
(
@lx
) =
split
(
''
,
$three
);
my
(
$i
);
for
(
$i
=0;
$i
<=
length
(
$three
);
$i
++)
{
++
$parincnt
if
(
$lx
[
$i
] eq
'('
);
last
unless
(
$parincnt
);
--
$parincnt
if
(
$lx
[
$i
] eq
')'
);
}
"$one "
.
'&'
.
"$two"
.
substr
(
$three
,0,
$i
).
'&'
.
substr
(
$three
,
$i
);
|es);
@perlconds
= ();
$query
=~ s%\b(
$colmlist
)\s*([!=][~\^])\s*(m)?(.)([^\4]*?)\4(i)?%
my
(
$m
,
$i
,
$delim
,
$four
,
$one
,
$fldname
) = ($3, $6, $4, $5, $2, $1);
my
(
$catchmatch
) = 0;
$m
||=
''
;
$i
||=
''
;
$m
=
'm'
unless
(
$delim
eq
'/'
);
my
(
$three
) =
$delim
;
$four
=~ s/\\\(/\x02\^5jSpR1tE\x02/gso;
$four
=~ s/\\\)/\x02\^6jSpR1tE\x02/gso;
if
(
$four
=~ /\(.*\)/)
{
$catchmatch
= 1;
}
$four
=~ s/\x02\^5jSpR1tE\x02/\(/gso;
$four
=~ s/\x02\^6jSpR1tE\x02/\)/gso;
push
(
@strings
,
"$m$delim$four$three$i"
);
push
(
@perlconds
,
"\$_->{$fldname} $one *$#strings; push (\@perlmatches, \$1) if (defined \$1); push (\@perlmatches, \$2) if (defined \$2);"
)
if
(
$catchmatch
);
"$fldname $one *$#strings"
;
%geis
;
$query
=~ s|(["'])(.*?)\1|
push
(
@strings
,
"$1$2$1"
);
"*$#strings"
;
|ges;
$query
=~ s/\x02\^3jSpR1tE\x02/\'/gso;
$query
=~ s/\^3jSpR1tE/\'/gso;
$query
=~ s/\x02\^2jSpR1tE\x02/\\\\/gso;
for
$i
(0..
$#strings
)
{
if
(
$strings
[
$i
] =~ /^m\
'/o) #TEST MODIFIED 20050429 TO FIX BUG - IF STRING IS LIKE, THEN CHANGE m'
str
' to m`str` and restore '
UNESCAPED!
{
$strings
[
$i
] =~ s/\^3jSpR1tE/\'/gso;
if
(
$string
!~ /\`/o)
{
$strings
[
$i
] =~ s/^m\'/m\`/o;
$strings
[
$i
] =~ s/\'${caseopt}$/\`
$caseopt
/;
}
else
{
$strings
[
$i
] =~ s/^m\'/m\^/o;
$strings
[
$i
] =~ s/\'${caseopt}$/\^
$caseopt
/;
}
}
else
{
$strings
[
$i
] =~ s/\^3jSpR1tE/\\\'/gso;
}
$strings
[
$i
] =~ s/\x02\^2jSpR1tE\x02/\\\\/gso;
}
if
(
$query
=~ /^(
$column
)$/)
{
$i
= $1;
$query
=
'&'
.
$i
unless
(
$i
=~ m/(
$colmlist
)/i);
}
$query
=~ s
$query
=~ s
$query
=~ s
$query
=~ s%\b(
$column
\s*(?:\(.*?\))?)\s+is\s+null%$1 eq
''
%igs
;
$query
=~ s%\b(
$column
\s*(?:\(.*?\))?)\s+is\s+not\s+null%$1 ne
''
%igs
;
$query
=~ s%(
$column
)\s*(
$numops
)\s*(
$column
\.(?:
$psuedocols
))%
"$1 $2 "
.
&pscolfn
(
$self
,$3)
%egs
;
$query
=~ s%\b(
$column
\s*(?:\(.*?\))?)\s*(
$numops
)\s*((?:[\+\-]?[0..9+-\.Ee]+|
$column
)\s*(?:\(.*?\))?)%
my
(
$one
,
$two
,
$three
) = ($1,$2,$3);
$one
=~ s/\s+$//;
my
$ONE
=
$one
;
$ONE
=~
tr
/a-z/A-Z/
unless
(
$self
->{sprite_CaseFieldNames});
if
(
$one
=~ /NUM\s*\(/ || ${
$self
->{types}}{
$ONE
} =~ /
$NUMERICTYPES
/io)
{
$two
=~ s/^(
$strops
)$/
$stropmap
{
$two
}/s;
"$one $two $three"
;
}
else
{
"$one $numopmap{$two} $three"
;
}
%egs
;
$query
=~ s|\b(
$colmlist
)\s*(
$strops
)\s*(\d+)|$1
$stropmap
{$2} $3|gis;
my
$ineqop
=
'!='
;
$query
=~ s!\b(
$colmlist
)\s*(
$strops
)\s*(\*\d+)!
my
(
$one
,
$two
,
$three
) = ($1,$2,$3);
$one
=~ s/\s+$//;
my
$ONE
=
$one
;
$ONE
=~
tr
/a-z/A-Z/
unless
(
$self
->{sprite_CaseFieldNames});
my
$res
;
if
(
$one
=~ /NUM\s*\(/ || ${
$self
->{types}}{
$ONE
} =~ /
$NUMERICTYPES
/ios)
{
my
(
$opno
) =
undef
;
if
(
$three
=~ /^\*\d+/s)
{
$opno
=
substr
(
$three
,1);
$opno
=
$strings
[
$opno
];
$opno
=~ s/^\'//s;
$opno
=~ s/\'$//s;
}
else
{
$opno
=
$three
;
}
unless
(
$opno
=~ /^[\+\-\d\.][\d\.Ex\+\-\_]*$/s)
{
$res
=
"$one $two '0'"
;
}
else
{
$two
=~ s/^(
$strops
)$/
$stropmap
{
$two
}/s
unless
(
$opno
eq
"0"
);
$res
=
"$one $two $three"
;
}
}
elsif
(
$self
->{StrictCharComp} == 0 && ${
$self
->{types}}{
$ONE
} eq
'CHAR'
)
{
my
(
$opno
) =
undef
;
if
(
$three
=~ /^\*\d+/)
{
$opno
=
substr
(
$three
,1);
my
$opstr
=
$strings
[
$opno
];
$opstr
=~ s/^\'//s;
$opstr
=~ s/\'$//s;
$strings
[
$opno
] =
"'"
.
sprintf
(
'%-'
.${
$self
->{lengths}}{
$ONE
}.
's'
,
$opstr
) .
"'"
;
}
$res
=
"$one $two $three"
;
}
else
{
$res
=
"$one $two $three"
;
}
$res
;
!egis;
$query
=~ s!\b((
$colmlist
))\b!
my
$match
= $1;
$match
=~
tr
/a-z/A-Z/
unless
(
$self
->{sprite_CaseFieldNames});
(
$match
=~ /\b(?:
$special
)\b/ios) ?
"\L$match\E"
:
"\$_->{$match}"
!geis;
$query
=~ s/ (and|or|not) / \L$1\E /igs;
$query
=~ s|[;`]||gso;
$query
=~ s
$query
=~ s
$query
=~ s|(\d+)\s*(
$strops
)\s*(\d+)|$1
$stropmap
{$2} $3|gios;
$query
=~ s|\*(\d+)|
$strings
[$1]|gs;
for
(
my
$i
=0;
$i
<=
$#perlconds
;
$i
++)
{
$perlconds
[
$i
] =~ s|\*(\d+)|
$strings
[$1]|gs;
}
$query
=~ s@([!=][~\^])\s
*m
\&([a-zA-Z_]+[^&]*)\&@
my
(
$one
,
$two
) = ($1, $2);
my
(
$res
) =
eval
(
$two
);
$res
=~ s/^\%//so;
$res
=~ s/\%$//so;
my
(
$rtn
,
$isalike
);
foreach
my
$i
(
'/'
,
"'"
,'"
','
|')
{
unless
(
$res
=~ m
%$i
%)
{
$isalike
= 1
if
(
$one
=~ s/\^/\~/so);
$rtn
=
"$one m"
.
$i
.
$res
.
$i
;
$rtn
.=
'i'
if
(
$self
->{sprite_nocase} &&
$isalike
);
last
;
}
}
$rtn
;
@egs
;
return
$query
;
}
sub
check_columns
{
my
(
$self
,
$column_string
) =
@_
;
my
(
$status
,
@columns
,
$column
);
$status
= 1;
unless
(
$self
->{sprite_CaseFieldNames})
{
$column
=~
tr
/a-z/A-Z/
if
(
defined
$column
);
$column_string
=~
tr
/a-z/A-Z/;
}
$self
->{use_fields} =
$column_string
;
@columns
=
split
(/\,/o,
$column_string
);
foreach
$column
(
@columns
) {
unless
(
$self
->{fields}->{
$column
})
{
$errdetails
=
$column
;
$status
= 0;
}
}
return
$status
;
}
sub
parse_columns
{
my
(
$self
,
$command
,
$column_string
,
$condition
,
$values
,
$ordercols
,
$descorder
,
$fields
,
$distinct
) =
@_
;
my
(
$i
,
$j
,
$k
,
$rowcnt
,
$status
,
@columns
,
$single
,
$loop
,
$code
,
$column
);
my
(
%colorder
,
$rawvalue
);
my
(
@result_index
);
my
(
$psuedocols
) =
"CURRVAL|NEXTVAL"
;
local
$results
=
undef
;
my
(
@keyfields
) =
split
(
','
,
$self
->{key_fields});
my
(
%valuenames
);
foreach
$i
(
keys
%$values
)
{
$values
->{
$i
} =~ s/^\'(.*)\'$/
my
(
$stuff
) = $1;
$stuff
=~ s|\'|\\\'|gso;
$stuff
=~ s|\\\'\\\'|\\\'|gso;
"'"
.
$stuff
.
"'"
/es;
$values
->{
$i
} =~ s/^\'$//so;
$values
->{
$i
} =
"''"
unless
(
$values
->{
$i
} =~ /\S/o);
$valuenames
{
$i
} =
$values
->{
$i
};
}
local
$SIG
{
'__WARN__'
} =
sub
{
$status
= -510;
$errdetails
=
"$_[0] at "
.__LINE__ };
local
$^W = 0;
local
(
$_
);
$status
= 1;
$results
= [];
@columns
=
split
(/,/o,
$column_string
);
if
(
$command
eq
'update'
)
{
foreach
my
$i
(
@columns
)
{
if
(${
$self
->{types}}{
$i
} =~ /AUTO/o)
{
$errdetails
=
$i
;
return
(-525);
}
}
}
$single
= (
$#columns
) ?
$columns
[
$#columns
] :
$column_string
;
$rowcnt
= 0;
my
(
@these_results
);
my
(
$skipreformat
) = 0;
my
(
$colskipreformat
) = 0;
my
(
@types
);
my
(
@coltypes
);
@coltypes
= ();
for
(
my
$i
=0;
$i
<=
$#columns
;
$i
++)
{
push
(
@coltypes
, (${
$self
->{types}}{
$columns
[
$i
]} =~ /
$REFTYPES
/o));
}
if
(
$fields
)
{
@types
= ();
for
(
my
$i
=0;
$i
<=$
{
push
(
@types
, ((${
$self
->{types}}{
$columns
[
$i
]} =~ /
$REFTYPES
/o)||0));
}
}
else
{
push
(
@$results
, [
@$_
{
@columns
} ]);
for
(
my
$i
=0;
$i
<=@{
$_
{
@columns
}};
$i
++)
{
push
(
@types
, ((${
$self
->{types}}{
$i
} =~ /
$REFTYPES
/o)||0));
}
}
my
$blobfid
;
my
$jj
;
$self
->{sprite_reclimit} ||=
$self
->{sprite_sizelimit};
for
(
$loop
=0;
$loop
<
scalar
@{
$self
->{records} };
$loop
++)
{
next
unless
(
defined
$self
->{records}->[
$loop
]);
$_
=
$self
->{records}->[
$loop
];
$@ =
''
;
if
( !
$condition
|| (
eval
$condition
) )
{
if
(
$command
eq
'select'
)
{
last
if
(
$self
->{sprite_reclimit} &&
$loop
>=
$self
->{sprite_reclimit});
if
(
$fields
)
{
@these_results
= ();
for
(
my
$i
=0;
$i
<=$
{
$fields
->[
$i
] =~ s/(
$self
->{column}\.(?:
$psuedocols
))\b/
&pscolfn
(
$self
,$1)/eg;
$rawvalue
=
eval
$fields
->[
$i
];
if
(
$types
[
$i
] &&
$rawvalue
=~ /^\d+$/o)
{
$blobfid
=
$self
->{directory}
.
$self
->{separator}->{
$self
->{platform} }
.
$self
->{table}.
"_${rawvalue}_$$.tmp"
;
if
(
open
(FILE,
"<$blobfid"
))
{
binmode
FILE;
$rawvalue
=
''
;
my
$rawline
;
while
(
$rawline
= <FILE>)
{
$rawvalue
.=
$rawline
;
}
close
FILE;
}
else
{
$blobfid
=
$self
->{directory}
.
$self
->{separator}->{
$self
->{platform} }
.
$self
->{table}.
"_${rawvalue}.ldt"
;
if
(
open
(FILE,
"<$blobfid"
))
{
binmode
FILE;
$rawvalue
=
''
;
my
$rawline
;
while
(
$rawline
= <FILE>)
{
$rawvalue
.=
$rawline
;
}
close
FILE;
}
else
{
$errdetails
=
"$blobfid ($?)"
;
return
(-528);
}
}
}
push
(
@these_results
,
$rawvalue
);
}
push
(
@$results
, [
@these_results
]);
push
(
@result_index
,
$loop
);
}
else
{
push
(
@$results
, [
@$_
{
@columns
} ]);
}
}
elsif
(
$command
eq
'update'
)
{
@perlmatches
= ();
for
(
my
$i
=0;
$i
<=
$#perlconds
;
$i
++)
{
eval
$perlconds
[
$i
];
}
$code
=
''
;
my
(
$matchcnt
) = 0;
my
(
@valuelist
) =
keys
(
%$values
);
my
(
$dontchkcols
) =
'('
.
join
(
'|'
,
@valuelist
);
for
(
my
$i
=0;
$i
<=
$#columns
;
$i
++)
{
$dontchkcols
.=
'|'
.
$columns
[
$i
]
if
(
$coltypes
[
$i
]);
}
$dontchkcols
.=
')'
;
foreach
$i
(
@valuelist
)
{
for
(
$j
=0;
$j
<=
$#keyfields
;
$j
++)
{
if
(
$i
eq
$keyfields
[
$j
])
{
K:
for
(
$k
=0;
$k
<
scalar
@{
$self
->{records} };
$k
++)
{
$rawvalue
=
$values
->{
$i
};
$rawvalue
=~ s/^\'(.*)\'\s*$/$1/s;
if
(
$self
->{records}->[
$k
]->{
$i
} eq
$rawvalue
)
{
foreach
$jj
(
@keyfields
)
{
unless
(
$jj
=~ /
$dontchkcols
/)
{
next
K
unless
(
$self
->{records}->[
$k
]->{
$jj
}
eq
$_
->{
$jj
});
}
}
goto
MATCHED1;
}
}
goto
NOMATCHED1;
MATCHED1: ++
$matchcnt
;
}
}
}
return
(-518)
if
(
$matchcnt
&&
$matchcnt
>
$#valuelist
); #ALL KEY FIELDS WERE DUPLICATES!
NOMATCHED1:
$self
->{dirty} = 1;
foreach
$jj
(
@columns
)
{
$colskipreformat
=
$skipreformat
;
$rawvalue
=
$valuenames
{
$jj
};
$colskipreformat
= 0
if
(
$rawvalue
=~ s/\$(\d)/
$perlmatches
[$1-1]/g);
if
(
$valuenames
{
$jj
} =~ /^[_a-zA-Z]/o)
{
if
(
$self
->{sprite_CaseFieldNames})
{
unless
(
$self
->{fields}->{
"$valuenames{$jj}"
})
{
$rawvalue
=
&chkcolumnparms
(
$self
,
$rawvalue
);
$rawvalue
=
eval
$rawvalue
;
return
(-517)
if
($@);
}
else
{
$rawvalue
=
$_
->{
$valuenames
{
$jj
}};
}
}
else
{
unless
(
$self
->{fields}->{
"\U$valuenames{$jj}\E"
})
{
$rawvalue
=
&chkcolumnparms
(
$self
,
$rawvalue
);
$rawvalue
=
eval
$rawvalue
;
return
(-517)
if
($@);
}
else
{
$rawvalue
=
$_
->{
$valuenames
{
$jj
}};
}
}
$colskipreformat
= 0;
}
else
{
$rawvalue
=~ s/^\'(.*)\'\s*$/$1/s
if
(
$valuenames
{
$jj
} =~ /^\'/o);
}
unless
(
$colskipreformat
)
{
if
(
length
(
$rawvalue
) > 0 && ${
$self
->{types}}{
$jj
} =~ /
$NUMERICTYPES
/)
{
$k
=
sprintf
((
'%.'
.${
$self
->{scales}}{
$jj
}.
'f'
),
$rawvalue
);
}
else
{
$k
=
$rawvalue
;
}
$rawvalue
= (${
$self
->{types}}{
$jj
} =~ /
$BLOBTYPES
/) ?
$k
:
substr
(
$k
,0,${
$self
->{lengths}}{
$jj
});
unless
(
$self
->{LongTruncOk} ||
$rawvalue
eq
$k
||
(${
$self
->{types}}{
$jj
} eq
'FLOAT'
))
{
$errdetails
=
"$jj to ${$self->{lengths}}{$jj} chars"
;
return
(-519);
}
if
((${
$self
->{types}}{
$jj
} eq
'FLOAT'
)
&& (
int
(
$rawvalue
) !=
int
(
$k
)))
{
$errdetails
=
"$jj to ${$self->{lengths}}{$jj} chars"
;
return
(-519);
}
if
(${
$self
->{types}}{
$jj
} eq
'CHAR'
&&
length
(
$rawvalue
) > 0)
{
$values
->{
$jj
} =
"'"
.
sprintf
(
'%-'
.${
$self
->{lengths}}{
$jj
}.
's'
,
$rawvalue
) .
"'"
;
}
else
{
$values
->{
$jj
} =
"'"
.
$rawvalue
.
"'"
;
}
}
}
for
(
my
$i
=0;
$i
<=
$#columns
;
$i
++)
{
if
(
$coltypes
[
$i
])
{
$code
=
qq|\$rawvalue = $values->{$columns[$i]};|
;
eval
$code
;
$blobfid
=
$self
->{directory}.
$self
->{separator}->{
$self
->{platform} }
.
$self
->{table}.
'_'
.
$_
->{
$columns
[
$i
]}.
"_$$.tmp"
;
if
(
open
(FILE,
">$blobfid"
))
{
binmode
FILE;
if
(
$self
->{CBC} &&
$self
->{sprite_Crypt} <= 2)
{
print
FILE
$self
->{CBC}->encrypt(
$rawvalue
);
}
else
{
print
FILE
$rawvalue
;
}
close
FILE;
}
else
{
$errdetails
=
"$blobfid: ($?)"
;
return
(-528);
}
}
else
{
$code
=
qq|\$_->{'$columns[$i]'} = $values->{$columns[$i]};|
;
eval
$code
;
}
}
return
(-517)
if
($@);
}
elsif
(
$command
eq
'add'
)
{
$_
->{
$single
} =
''
;
}
elsif
(
$command
eq
'drop'
)
{
delete
$_
->{
$single
};
}
++
$rowcnt
;
$skipreformat
= 1;
}
elsif
($@)
{
$errdetails
=
"Condition failed ($@) in condition=$condition!"
;
return
-503
if
(
$command
eq
'select'
);
return
-505
if
(
$command
eq
'delete'
);
return
-504;
}
}
if
(
$status
<= 0)
{
return
$status
;
}
elsif
(
$command
ne
'select'
)
{
return
$rowcnt
;
}
else
{
my
$theresanull
= 0;
my
$rowcntdigits
=
length
(
scalar
(
@$results
));
my
(
$ii
,
$t
);
if
(
$distinct
)
{
my
(
%disthash
);
for
(
my
$i
=0;
$i
<=
$#$results
;
$i
++)
{
++
$disthash
{
join
(
"\x02\^2jSpR1tE\x02"
,@{
$results
->[
$i
]})};
}
@$results
= ();
foreach
my
$i
(
keys
(
%disthash
))
{
if
(
$i
eq
''
)
{
$theresanull
= 1;
next
;
}
push
(
@$results
, [
split
(/\x02\^2jSpR1tE\x02/o,
$i
, -1)]);
}
}
if
(
@$ordercols
)
{
@$ordercols
=
reverse
(
@$ordercols
);
@$descorder
=
reverse
(
@$descorder
);
$rowcnt
= 0;
my
@mysep
= (
"\x00"
,
"\xff"
);
my
@SA
= ();
my
@SSA
= ();
my
@SI
= ();
my
@l
;
for
(0..
$#columns
)
{
$colorder
{
$columns
[
$_
]} =
$_
;
}
for
(
my
$i
=0;
$i
<=
$#$results
;
$i
++)
{
$t
=
sprintf
(
'%'
.
$rowcntdigits
.
'.'
.
$rowcntdigits
.
'd'
,
$i
);
push
(
@SI
,
$t
);
push
(
@SSA
,
$t
);
}
my
$jcnt
= 0;
my
$do
= (
$descorder
->[0] =~ /de/io) ? 1 : 0;
my
$fieldval
;
foreach
my
$j
(
@$ordercols
)
{
$j
=~
tr
/a-z/A-Z/
unless
(
$self
->{sprite_CaseFieldNames});
$k
=
defined
(
$colorder
{
$j
}) ?
$colorder
{
$j
} : -1;
for
(
my
$i
=0;
$i
<=
$#$results
;
$i
++)
{
$fieldval
= (
$k
>= 0) ?
${
$results
}[
$SI
[
$i
]]->[
$k
]
:
$self
->{records}->[
$result_index
[
$SI
[
$i
]]]->{
$j
};
if
(${
$self
->{types}}{
$j
} eq
'FLOAT'
|| ${
$self
->{types}}{
$j
} eq
'DOUBLE'
)
{
push
(
@SA
, (
sprintf
(
'%'
.${
$self
->{lengths}}{
$j
}.${
$self
->{scales}}{
$j
}.
'e'
,
$fieldval
) .
$mysep
[
$do
] .
$SSA
[
$i
]));
}
elsif
(
length
(
$fieldval
) > 0 && ${
$self
->{types}}{
$j
} =~ /
$NUMERICTYPES
/)
{
push
(
@SA
, (
sprintf
(
'%'
.${
$self
->{lengths}}{
$j
}.${
$self
->{scales}}{
$j
}.
'f'
,
$fieldval
) .
$mysep
[
$do
] .
$SSA
[
$i
]));
}
else
{
push
(
@SA
, (
$fieldval
.
$mysep
[
$do
] .
$SSA
[
$i
]));
}
}
@SI
= ();
@SSA
= ();
@SI
=
sort
{
$a
cmp
$b
}
@SA
;
@SI
=
reverse
(
@SI
)
if
(
$do
);
@SA
= ();
my
$ii
=
$#SI
;
$l
=
length
(
$ii
);
if
(
$jcnt
<
$#$ordercols
)
{
$do
= (
$descorder
->[++
$jcnt
] =~ /de/io) ? 1 : 0;
for
(
my
$i
=0;
$i
<=
$#SI
;
$i
++)
{
$SI
[
$i
] = $1
if
(
$SI
[
$i
] =~ /(\d+)$/o);
push
(
@SSA
,
sprintf
(
"%${l}d"
,(
$do
?
$ii
-- :
$i
)) .
$mysep
[
$do
] .
sprintf
(
'%'
.
$rowcntdigits
.
'.'
.
$rowcntdigits
.
'd'
,
$SI
[
$i
]));
}
}
}
@SA
=
@$results
;
@$results
= ();
for
(
my
$i
=0;
$i
<=
$#SI
;
$i
++)
{
$SI
[
$i
] = $1
if
(
$SI
[
$i
] =~ /(\d+)$/o);
push
(
@$results
,
$SA
[
$SI
[
$i
]]);
}
}
if
(
$theresanull
)
{
unshift
(
@$results
, [
''
]);
}
$
if
(
$self
->{sprite_actlimit} > 0 && $
$rowcnt
=
scalar
(@{
$results
});
}
unshift
(
@$results
,
$rowcnt
);
return
$results
;
}
sub
check_for_reload
{
my
(
$self
,
$file
) =
@_
;
my
(
$table
,
$path
,
$status
);
return
unless
(
$file
);
if
(
$file
=~ /^DUAL$/io)
{
undef
%{
$self
->{types} };
undef
%{
$self
->{lengths} };
$self
->{use_fields} =
'DUMMY'
;
$self
->{key_fields} =
'DUMMY'
;
${
$self
->{types}}{DUMMY} =
'VARCHAR2'
;
${
$self
->{lengths}}{DUMMY} = 1;
${
$self
->{scales}}{DUMMY} = 1;
$self
->{order} = [
'DUMMY'
];
$self
->{fields}->{DUMMY} = 1;
undef
@{
$self
->{records} };
$self
->{records}->[0] = {
'DUMMY'
=>
'X'
};
$self
->{table} =
'DUAL'
;
return
(1);
}
(
$path
,
$table
) =
$self
->get_path_info (
$file
);
$file
=
$path
.
$table
;
$file
.=
$self
->{ext}
if
(
$self
->{ext});
$self
->{table} =
$table
;
$status
= 1;
my
(
@stats
) =
stat
(
$file
);
if
( (
$self
->{table} ne
$table
) || (
$self
->{file} ne
$file
||
$self
->{timestamp} !=
$stats
[9]) )
{
if
( (-e _) && (-s _) && (-r _) )
{
$self
->{table} =
$table
;
$self
->{file} =
$file
;
$status
=
$self
->load_database (
$file
);
$self
->{timestamp} =
$stats
[9];
}
else
{
$errdetails
=
$file
;
$status
= 0;
}
}
$errdetails
=
$file
if
(
$status
== 0);
return
$status
;
}
sub
rollback
{
my
(
$self
) =
@_
;
my
(
$table
,
$path
,
$status
);
my
(
@stats
) =
stat
(
$self
->{file});
if
( (-e _) && (-T _) && (-s _) && (-r _) )
{
$status
=
$self
->load_database (
$self
->{file});
$self
->{timestamp} =
$stats
[9];
}
else
{
$status
= 0;
}
my
$blobglob
=
$self
->{file};
$blobglob
=~ s/
$self
->{ext}$/\_\*\_$$\.tmp/;
my
$bloberror
= 0;
unlink
$blobglob
;
$bloberror
= $?.
':'
.$@
if
($?);
if
(
$blobglob
&&
$bloberror
)
{
$errdetails
=
$bloberror
;
$self
->display_error (-528);
return
undef
;
}
else
{
$blobglob
=
$self
->{directory}.
$self
->{separator}->{
$self
->{platform} }
.
$self
->{table}.
"_*_$$.del"
;
my
@tempblobs
= ();
eval
qq|\@tempblobs = <$blobglob>|
;
my
(
$blobfile
,
$tempfile
);
while
(
@tempblobs
)
{
$tempfile
=
shift
(
@tempblobs
);
$blobfile
=
$tempfile
;
$blobfile
=~ s/\_$$\.del/\.ldt/;
rename
(
$tempfile
,
$blobfile
);
}
$self
->{dirty} = 0;
}
return
$status
;
}
sub
select
{
my
(
$self
,
$query
) =
@_
;
my
(
$i
,
@l
,
$regex
,
$path
,
$columns
,
$table
,
$extra
,
$condition
,
$values_or_error
,
$descorder
,
@descorder
);
my
(
@ordercols
) = ();
$regex
=
$self
->{_select};
$path
=
$self
->{path};
my
(
$psuedocols
) =
"CURRVAL|NEXTVAL"
;
my
$distinct
;
$distinct
= 1
if
(
$query
=~ /^
select
\s+distinct/o);
$query
=~ s/^
select
\s+distinct(\s+\w|\s*\(|\s+\*)/
select
$1/is;
if
(
$query
=~ /^
select
\s+
(.+)\s+
from\s+
(\w+)(.*)$/ioxs)
{
my
(
$column_stuff
,
$table
,
$extra
) = ($1, $2, $3);
my
(
@fields
) = ();
my
(
$fnname
,
$found_parin
,
$parincnt
,
$t
);
my
@column_stuff
;
if
(
$column_stuff
=~ /^table_name\s*$/io &&
$table
=~ /^(user|all)_tables$/io)
{
my
$full_path
=
$self
->{directory};
$full_path
.=
$self
->{separator}->{
$self
->{platform} }
unless
(
$full_path
!~ /\S/o
||
$full_path
=~ m
my
(
$cmd
);
$cmd
=
$full_path
.
'*'
.
$self
->{ext};
my
(
$code
);
if
($^O =~ /Win/i)
{
@l
=
glob
$cmd
;
}
else
{
@l
= ();
$code
=
"while (my \$i = <$cmd>)\n"
;
$code
.=
<<'END_CODE';
{
chomp ($i);
push (@l, $i);
}
END_CODE
eval
$code
;
}
$self
->{use_fields} =
'TABLE_NAME'
;
$values_or_error
= [];
for
(
$i
=0;
$i
<=
$#l
;
$i
++) {
if
($^O =~ /Win/i)
{
$l
[
$i
] =~ s/${full_path}(.*?)
$self
->{ext}/$1/i;
$l
[
$i
] =~ s/
$self
->{ext}$//i;
}
else
{
$l
[
$i
] =~ s/${full_path}(.*?)
$self
->{ext}/$1/;
$l
[
$i
] =~ s/
$self
->{ext}$//;
}
push
(
@$values_or_error
,[
$l
[
$i
]]);
}
unshift
(
@$values_or_error
, (
$#l
+1));
return
$values_or_error
;
}
$self
->{ASNAMES} = {};
while
(
$column_stuff
=~ s/(
$self
->{column})\s+(?:AS|as)\s+(
$self
->{column})/$1/)
{
$self
->{ASNAMES}->{$1} = $2;
};
$column_stuff
=~ s/\s+$//o;
while
(1)
{
$found_parin
= 0;
$column_stuff
=~ s/^\s+//o;
$fnname
=
''
;
$fnname
= $1
if
(
$column_stuff
=~ s/^(
$self
->{column}(?:\.(?:
$psuedocols
))?)//);
$column_stuff
=~ s/^ +//o;
last
unless
(
$fnname
);
@column_stuff
=
split
(//o,
$column_stuff
);
if
(
$#column_stuff
<= 0 ||
$column_stuff
[0] eq
','
)
{
push
(
@fields
,
$fnname
);
$column_stuff
=~ s/^\,//o;
next
;
}
for
(
$i
=0;
$i
<=
length
(
$column_stuff
);
$i
++)
{
if
(
$column_stuff
[
$i
] eq
'('
)
{
++
$parincnt
;
$found_parin
= 1;
}
last
if
(!
$parincnt
&&
$found_parin
);
--
$parincnt
if
(
$column_stuff
[
$i
] eq
')'
);
}
push
(
@fields
, (
$fnname
.
substr
(
$column_stuff
,0,
$i
)));
$t
=
substr
(
$column_stuff
,
$i
);
$t
=~ s/^\s*\,//o;
last
unless
(
$t
);
$column_stuff
=
$t
;
}
my
$cfr
=
$self
->check_for_reload(
$table
) || -501;
return
$cfr
if
(
$cfr
< 0);
$columns
=
''
;
my
(
@strings
);
my
(
$column_list
) =
'('
.
join
(
'|'
, @{
$self
->{order} }).
')'
;
for
(
my
$i
=0;
$i
<=
$#fields
;
$i
++)
{
@strings
= ();
$fields
[
$i
] =~ s|(\'[^\']+\')|
push
(
@strings
, $1);
"\x02\^2jSpR1tE\x02$#strings\x02\^2jSpR1tE\x02"
|eg;
if
(
$self
->{sprite_CaseFieldNames})
{
$fields
[
$i
] =~ s/\b(
$column_list
)\b/
my
(
$column_name
) = $1;
$columns
.=
$column_name
.
','
;
"\$\$\_\{$column_name\}"
/ieg;
}
else
{
$fields
[
$i
] =~ s/\b(
$column_list
)\b/
my
(
$column_name
) = $1;
$columns
.=
$column_name
.
','
;
"\$\$\_\{\U$column_name\E\}"
/ieg;
}
$fields
[
$i
] =~ s/\x02\^2jSpR1tE\x02(\d+)\x02\^2jSpR1tE\x02/
$strings
[$1]/g;
}
chop
(
$columns
);
if
(
$extra
=~ s/([\s|\)]+)order\s+by\s*(.*)/$1/is)
{
my
$orderclause
= $2;
@ordercols
=
split
(/,/o,
$orderclause
);
for
(
my
$i
=0;
$i
<=
$#ordercols
;
$i
++)
{
$descorder
=
'asc'
;
$descorder
= $2
if
(
$ordercols
[
$i
] =~ s/(\w+)\W+(asc|desc|ascending|descending)$/$1/is);
push
(
@descorder
,
$descorder
);
}
for
$i
(0..
$#ordercols
)
{
$ordercols
[
$i
] =~ s/\s//go;
$ordercols
[
$i
] =~ s/[\(\)]+//go;
}
}
if
(
$extra
=~ /^\s+where\s*(.+)$/iso)
{
$condition
=
$self
->parse_expression ($1);
}
if
(
$column_stuff
=~ /\*/o)
{
@fields
= @{
$self
->{order} };
$columns
=
join
(
','
,
@fields
);
if
(
$self
->{sprite_CaseFieldNames})
{
for
(
my
$i
=0;
$i
<=
$#fields
;
$i
++)
{
$fields
[
$i
] =~ s/([^\,]+)/\$\$\_\{$1\}/g;
}
}
else
{
for
(
my
$i
=0;
$i
<=
$#fields
;
$i
++)
{
$fields
[
$i
] =~ s/([^\,]+)/\$\$\_\{$1\}/g;
$fields
[
$i
] =~
tr
/a-z/A-Z/;
}
}
}
$columns
=~
tr
/a-z/A-Z/
unless
(
$self
->{sprite_CaseFieldNames});
$self
->check_columns (
$columns
) ||
return
(-502);
if
(
$#fields
>= 0)
{
my
(
@fieldnames
) =
@fields
;
for
(
my
$i
=0;
$i
<=
$#fields
;
$i
++)
{
$fieldnames
[
$i
] =~ s/\(.*$//o;
$fieldnames
[
$i
] =~ s/\$\_//o;
$fieldnames
[
$i
] =~ s/[^\w\,]//go;
}
$self
->{use_fields} =
join
(
','
,
@fieldnames
);
}
$values_or_error
=
$self
->parse_columns (
'select'
,
$columns
,
$condition
,
''
, \
@ordercols
, \
@descorder
, \
@fields
,
$distinct
);
return
$values_or_error
;
}
else
{
$errdetails
=
$query
;
return
(-503);
}
}
sub
update
{
my
(
$self
,
$query
) =
@_
;
my
(
$i
,
$path
,
$regex
,
$table
,
$extra
,
$condition
,
$all_columns
,
$columns
,
$status
);
my
(
$psuedocols
) =
"CURRVAL|NEXTVAL"
;
$query
=~ s/\\([()])/
sprintf
(
"%%\0%d: "
,
ord
($1))/ges;
$path
=
$self
->{path};
$regex
=
$self
->{column};
if
(
$query
=~ /^update\s+(
$path
)\s+set\s+(.+)$/ios) {
(
$table
,
$extra
) = ($1, $2);
return
(-523)
if
(
$table
=~ /^DUAL$/io);
if
(
$extra
=~ /^\(.+\)\s
*where
/so)
{
$errdetails
=
'parenthesis around SET clause?'
;
return
(-504);
}
my
$cfr
=
$self
->check_for_reload(
$table
) || -501;
return
$cfr
if
(
$cfr
< 0);
return
(-511)
unless
(-w
$self
->{file});
$all_columns
= {};
$columns
=
''
;
$extra
=~ s/\\\\/\x02\^2jSpR1tE\x02/gso;
$extra
=~ s/\
'\'/\x02\^8jSpR1tE\x02/gso; #PROTECT '
'.
$extra
=~ s/\\\'/\x02\^3jSpR1tE\x02/gso;
$extra
=~ s/^\s+//so;
$extra
=~ s/\s+$//so;
my
$column
=
$self
->{column};
$extra
=~ s/(
$column
\s*\=\s*)\'(.*?)\'(,|$)/
my
(
$one
,
$two
,
$three
) = ($1,$2,$3);
$two
=~ s|\,|\x02\^5jSpR1tE\x02|go;
$two
=~ s|\(|\x02\^6jSpR1tE\x02|go;
$two
=~ s|\)|\x02\^7jSpR1tE\x02|go;
$one
.
"'"
.
$two
.
"'"
.
$three
;
/egs;
1
while
(
$extra
=~ s/\(([^\(\)]*)\)/
my
(
$args
) = $1;
$args
=~ s|\,|\x02\^5jSpR1tE\x02|go;
"\x02\^6jSpR1tE\x02$args\x02\^7jSpR1tE\x02"
;
/egs);
my
@expns
=
split
(
','
,
$extra
);
for
(
$i
=0;
$i
<=
$#expns
;
$i
++) #PROTECT
"WHERE"
IN QUOTED VALUES.
{
$expns
[
$i
] =~ s/\x02\^5jSpR1tE\x02/,/gso;
$expns
[
$i
] =~ s/\x02\^6jSpR1tE\x02/\(/gso;
$expns
[
$i
] =~ s/\x02\^7jSpR1tE\x02/\)/gso;
$expns
[
$i
] =~ s/\=\s*
'([^'
]*?)where([^
']*?)'
/\=
'$1\x02\^5jSpR1tE\x02$2'
/gis;
$expns
[
$i
] =~ s/\'(.*?)\'/
my
(
$j
)=$1;
$j
=~s|where|\x02\^5jSpR1tE\x02|go;
"'$j'"
/egs;
}
$extra
=
$expns
[
$#expns
]; #EXTRACT WHERE-CLAUSE, IF ANY.
$extra
=~ s/\x02\^8jSpR1tE\x02/\'\'/gso;
$condition
= (
$extra
=~ s/(.*)where(.+)$/where$1/is) ? $2 :
''
;
$condition
=~ s/\s+//so;
$expns
[
$#expns
] =~ s/\s
*where
(.+)$//iso; #20000108 REP. PREV. LINE 2FIX BUG IF LAST COLUMN CONTAINS SINGLE QUOTES.
$column
=
$self
->{column};
$condition
=
$self
->parse_expression (
$condition
);
$columns
=
''
;
for
(
$i
=0;
$i
<=
$#expns
;
$i
++) #EXTRACT FIELD NAMES AND
{
$expns
[
$i
] =~ s!\s*(
$column
)\s*=\s*(.+)$!
my
(
$var
) = $1;
my
(
$val
) = $2;
$var
=~
tr
/a-z/A-Z/
unless
(
$self
->{sprite_CaseFieldNames});
$columns
.=
$var
.
','
;
$val
=~ s|%\0(\d+): |
pack
(
"C"
,$1)|ge;
$all_columns
->{
$var
} =
$val
;
$all_columns
->{
$var
} =~ s/\x02\^2jSpR1tE\x02/\\\\/g;
$all_columns
->{
$var
} =~ s/\x02\^8jSpR1tE\x02/\'\'/g;
$all_columns
->{
$var
} =~ s/\x02\^3jSpR1tE\x02/\
'/g; #20000108 REPL. PREV. LINE - NO NEED TO DOUBLE QUOTES (WE ESCAPE THEM) - THIS AIN'
T ORACLE.
!es;
}
chop
(
$columns
);
$self
->check_columns (
$columns
) ||
return
(-502);
$status
=
$self
->parse_columns (
'update'
,
$columns
,
$condition
,
$all_columns
);
return
(
$status
);
}
else
{
$errdetails
=
$query
;
return
(-504);
}
}
sub
delete
{
my
(
$self
,
$query
) =
@_
;
my
(
$path
,
$table
,
$condition
,
$status
,
$wherepart
);
$path
=
$self
->{path};
if
(
$query
=~ /^
delete
\s+from\s+(
$path
)(?:\s+where\s+(.+))?$/ios) {
$table
= $1;
$wherepart
= $2;
my
$cfr
=
$self
->check_for_reload(
$table
) || -501;
return
$cfr
if
(
$cfr
< 0);
return
(-511)
unless
(-w
$self
->{file});
if
(
$wherepart
=~ /\S/o)
{
$condition
=
$self
->parse_expression (
$wherepart
);
}
else
{
$condition
= 1;
}
$status
=
$self
->delete_rows (
$condition
);
return
$status
;
}
else
{
$errdetails
=
$query
;
return
(-505);
}
}
sub
drop
{
my
(
$self
,
$query
) =
@_
;
my
(
$path
,
$table
,
$condition
,
$status
,
$wherepart
);
$path
=
$self
->{path};
$_
=
undef
;
if
(
$query
=~ /^drop\s+table\s+(
$path
)\s*$/ios)
{
$table
= $1;
my
$cfr
=
$self
->check_for_reload(
$table
) || -501;
return
$cfr
if
(
$cfr
< 0);
@{
$self
->{records}} = ();
@{
$self
->{order}} = ();
%{
$self
->{types}} = ();
%{
$self
->{lengths}} = ();
%{
$self
->{scales}} = ();
%{
$self
->{defaults}} = ();
$self
->{key_fields} =
''
;
return
(
unlink
$self
->{file}) ?
'0E0'
: -501;
}
$errdetails
=
$query
;
return
(-501);
}
sub
truncate
{
my
(
$self
,
$query
) =
@_
;
return
$self
->
delete
(
$query
)
if
(
$query
=~ s/^\s
*truncate
\s+table\s+/
delete
from /ios);
$errdetails
=
$query
;
return
(-533);
}
sub
primary_key_info
{
my
(
$self
,
$query
) =
@_
;
my
$table
=
$query
;
$table
=~ s/^.*\s+(\w+)$/$1/;
my
$cfr
=
$self
->check_for_reload(
$table
) || -501;
return
$cfr
if
(
$cfr
< 0);
undef
%{
$self
->{types} };
undef
%{
$self
->{lengths} };
$self
->{use_fields} =
'CAT,SCHEMA,TABLE_NAME,PRIMARY_KEY'
;
$self
->{order} = [
'CAT'
,
'SCHEMA'
,
'TABLE_NAME'
,
'PRIMARY_KEY'
];
$self
->{fields}->{CAT} = 1;
$self
->{fields}->{SCHEMA} = 1;
$self
->{fields}->{TABLE_NAME} = 1;
$self
->{fields}->{PRIMARY_KEY} = 1;
undef
@{
$self
->{records} };
my
(
@keyfields
) =
split
(
','
,
$self
->{key_fields});
${
$self
->{types}}{CAT} =
'VARCHAR2'
;
${
$self
->{types}}{SCHEMA} =
'VARCHAR2'
;
${
$self
->{types}}{TABLE_NAME} =
'VARCHAR2'
;
${
$self
->{types}}{PRIMARY_KEY} =
'VARCHAR2'
;
${
$self
->{lengths}}{CAT} = 50;
${
$self
->{lengths}}{SCHEMA} = 50;
${
$self
->{lengths}}{TABLE_NAME} = 50;
${
$self
->{lengths}}{PRIMARY_KEY} = 50;
${
$self
->{defaults}}{CAT} =
undef
;
${
$self
->{defaults}}{SCHEMA} =
undef
;
${
$self
->{defaults}}{TABLE_NAME} =
undef
;
${
$self
->{defaults}}{PRIMARY_KEY} =
undef
;
${
$self
->{scales}}{PRIMARY_KEY} = 50;
${
$self
->{scales}}{PRIMARY_KEY} = 50;
${
$self
->{scales}}{PRIMARY_KEY} = 50;
${
$self
->{scales}}{PRIMARY_KEY} = 50;
my
$results
;
my
$keycnt
=
scalar
(
@keyfields
);
while
(
@keyfields
)
{
push
(@{
$results
}, [0, 0,
$table
,
shift
(
@keyfields
)]);
}
unshift
(
@$results
,
$keycnt
);
return
$results
;
}
sub
delete_rows
{
my
(
$self
,
$condition
) =
@_
;
my
(
$status
,
$loop
);
local
$SIG
{
'__WARN__'
} =
sub
{
$status
= -510;
$errdetails
=
"$_[0] at "
.__LINE__ };
local
$^W = 0;
$status
= 0;
my
@blobcols
;
foreach
my
$i
(
keys
%{
$self
->{types}})
{
push
(
@blobcols
,
$i
)
if
(${
$self
->{types}}{
$i
} =~ /
$REFTYPES
/o)
}
my
(
$blobfid
,
$delfid
,
$rawvalue
);
$loop
= 0;
while
(1)
{
last
if
(!
scalar
(@{
$self
->{records}}) ||
$loop
>=
scalar
@{
$self
->{records} });
$_
=
$self
->{records}->[
$loop
];
if
(
eval
$condition
)
{
foreach
my
$i
(
@blobcols
)
{
$rawvalue
=
$self
->{records}->[
$loop
]->{
$i
};
$blobfid
=
$self
->{directory}
.
$self
->{separator}->{
$self
->{platform} }
.
$self
->{table}.
"_${rawvalue}.ldt"
;
$delfid
=
$self
->{directory}
.
$self
->{separator}->{
$self
->{platform} }
.
$self
->{table}.
"_${rawvalue}_$$.del"
;
rename
(
$blobfid
,
$delfid
);
}
splice
(@{
$self
->{records} },
$loop
, 1);
++
$status
;
}
else
{
++
$loop
;
}
}
$self
->{dirty} = 1
if
(
$status
> 0);
return
$status
;
}
sub
create
{
my
(
$self
,
$query
) =
@_
;
my
(
$i
,
@keyfields
,
@values
);
local
(
*FILE
, $^W);
local
($/) =
$self
->{_record};
$^W = 0;
if
(
$query
=~ /^create\s+table\s+(
$self
->{path})\s*\((.+)\)\s*$/is)
{
my
(
$table
,
$extra
) = ($1, $2);
$query
=~
tr
/a-z/A-Z/s
unless
(
$self
->{sprite_CaseFieldNames});
$extra
=~ s/^\s*//so;
$extra
=~ s/\s*$//so;
$extra
=~ s/\((.*?)\)/
my
(
$precision
) = $1;
$precision
=~ s|\,|\x02\^2jSpR1tE\x02|g;
"($precision)"
/egs;
$extra
=~ s/([\'\"])([^\1]*?)\1/
my
(
$quote
) = $1;
my
(
$str
) = $2;
$str
=~ s|\,|\x02\^2jSpR1tE\x02|g;
"$quote$str$quote"
/egs;
my
(
@fieldlist
) =
split
(/,/o ,
$extra
);
my
$fieldname
;
for
(
$i
=0;
$i
<=
$#fieldlist
;
$i
++)
{
$fieldlist
[
$i
] =~ s/^\s+//gso;
$fieldlist
[
$i
] =~ s/\s+$//gso;
if
(
$fieldlist
[
$i
] =~ s/^PRIMARY\s+KEY\s*\(([^\)]+)\)$//i)
{
my
$keyfields
= $1;
$keyfields
=~ s/\s+//go;
$keyfields
=~
tr
/a-z/A-Z/
unless
(
$self
->{sprite_CaseFieldNames});
@keyfields
=
split
(/\x02\^2jSpR1tE\x02/o ,
$keyfields
);
}
}
@{
$self
->{order}} = ();
%{
$self
->{types}} = ();
%{
$self
->{lengths}} = ();
%{
$self
->{scales}} = ();
%{
$self
->{defaults}} = ();
while
(
@fieldlist
)
{
$i
=
shift
(
@fieldlist
);
last
unless
(
$i
=~ /\S/o);
$i
=~ s/\s+DEFAULT\s+(?:([\'\"])([^\1]*?)\1|([\+\-]?[\d\.]+)|(NULL))$/
my
(
$value
) = $4 || $3 || $2 || $1;
$value
=
''
if
($4);
push
(
@values
,
$value
);
"=<3>"
/ieg;
$i
=~ s/\s+/=/o;
$i
=~
tr
/a-z/A-Z/
unless
(
$self
->{sprite_CaseFieldNames});
$fieldname
=
$i
;
$fieldname
=~ s/=.*//o;
push
(
@keyfields
,
$fieldname
)
if
(
$i
=~ s/\s
*PRIMARY
\s+KEY\s*//i);
my
(
$tp
,
$len
,
$scale
);
$i
=~ s/\w+\=//o;
$i
=~ s/\s+//go;
if
(
$i
=~ /(\w+)(?:\((\d+))?(?:\x02\^2jSpR1tE\x02(\d+))?/o)
{
$tp
= $1;
$len
= $2;
$scale
= $3;
}
else
{
$tp
=
'VARCHAR2'
;
}
unless
(
$len
)
{
$len
= 40;
$len
= 10
if
(
$tp
=~ /NUM|INT|FLOAT|DOUBLE/o);
$len
=
$self
->{LongReadLen} || 0
if
(
$tp
=~ /
$BLOBTYPES
/);
}
unless
(
$scale
)
{
$scale
=
$len
;
if
(
$tp
eq
'FLOAT'
)
{
$scale
-= 3;
}
elsif
(
$tp
=~ /
$NUMERICTYPES
/)
{
$scale
= 0;
}
}
my
(
$value
) =
''
;
if
(
$i
=~ /\<3\>/)
{
$value
=
shift
(
@values
);
my
(
$rawvalue
);
if
(
length
(
$value
) > 0 &&
$tp
=~ /
$NUMERICTYPES
/)
{
$rawvalue
=
sprintf
((
'%.'
.
$scale
.
'f'
),
$value
);
}
else
{
$rawvalue
=
$value
;
}
$value
= (
$tp
=~ /
$BLOBTYPES
/) ?
$rawvalue
:
substr
(
$rawvalue
,0,
$len
);
unless
(
$self
->{LongTruncOk} ||
$value
eq
$rawvalue
||
(
$tp
eq
'FLOAT'
))
{
$errdetails
=
"$fieldname to $len chars"
;
return
(-519);
}
if
((
$tp
eq
'FLOAT'
)
&& (
int
(
$value
) !=
int
(
$rawvalue
)))
{
$errdetails
=
"$fieldname to $len chars"
;
return
(-519);
}
if
(
$tp
eq
'CHAR'
&&
length
(
$rawvalue
) > 0)
{
$rawvalue
=
sprintf
(
'%-'
.
$len
.
's'
,
$value
);
}
else
{
$rawvalue
=
$value
;
}
}
push
(@{
$self
->{order}},
$fieldname
);
${
$self
->{types}}{
$fieldname
} =
$tp
;
${
$self
->{lengths}}{
$fieldname
} =
$len
;
${
$self
->{scales}}{
$fieldname
} =
$scale
;
${
$self
->{defaults}}{
$fieldname
} =
$value
;
}
$self
->{key_fields} =
join
(
','
,
@keyfields
);
$self
->{dirty} = 1;
@{
$self
->{records}} = ();
$self
->commit(
$table
);
my
$cfr
=
$self
->check_for_reload(
$table
) || -501;
return
$cfr
if
(
$cfr
< 0);
}
elsif
(
$query
=~ /^create\s+sequence\s+(
$self
->{path})(?:\s+inc(?:rement)?\s+by\s+(\d+))?(?:\s+start\s+
with
\s+(\d+))?/is)
{
my
(
$seqfid
,
$incval
,
$startval
) = ($1, $2, $3);
$incval
= 1
unless
(
$incval
);
$startval
= 0
unless
(
$startval
);
my
(
$new_file
) =
$self
->get_path_info(
$seqfid
) .
'.seq'
;
unlink
(
$new_file
)
if
(
$self
->{sprite_forcereplace} && -e
$new_file
);
if
(
open
(FILE,
">$new_file"
))
{
print
FILE
"$startval,$incval\n"
;
close
(FILE);
}
else
{
$errdetails
=
"$@/$? (file:$new_file)"
;
return
-511;
}
}
else
{
$errdetails
=
$query
;
return
-530;
}
}
sub
alter
{
my
(
$self
,
$query
) =
@_
;
my
(
$i
,
$path
,
$regex
,
$table
,
$extra
,
$type
,
$column
,
$count
,
$status
,
$fd
);
my
(
$posn
);
my
(
@keyfields
) =
split
(
','
,
$self
->{key_fields});
$path
=
$self
->{path};
$regex
=
$self
->{column};
if
(
$query
=~ /^alter\s+table\s+(
$path
)\s+(.+)$/ios)
{
(
$table
,
$extra
) = ($1, $2);
if
(
$extra
=~ /^(add|modify|drop)\s*(.+)$/ios)
{
my
(
$type
,
$columnstuff
) = ($1, $2);
$columnstuff
=~ s/^\s*\(//s;
$columnstuff
=~ s/\)\s*$//s;
$columnstuff
=~ s/\((.*?)\)/
my
(
$precision
) = $1;
$precision
=~ s|\,|\x02\^2jSpR1tE\x02|g;
"($precision)"
/egs;
$columnstuff
=~ s/([\'\"])([^\1]*?)\1/
my
(
$quote
) = $1;
my
(
$str
) = $2;
$str
=~ s|\,|\x02\^2jSpR1tE\x02|gs;
"$quote$str$quote"
/egs;
my
$cfr
=
$self
->check_for_reload(
$table
) || -501;
return
$cfr
if
(
$cfr
< 0);
my
(
@values
) = ();
my
(
@fieldlist
) =
split
(/,/,
$columnstuff
);
my
(
$olddf
,
$oldln
,
$tp
,
$x
);
while
(
@fieldlist
)
{
$i
=
shift
(
@fieldlist
);
$i
=~ s/^\s+//go;
$i
=~ s/\s+$//go;
last
unless
(
$i
=~ /\S/o);
$i
=~ s/\x02\^2jSpR1tE\x02/\,/go;
$i
=~ s/\s+DEFAULT\s+(?:([\'\"])([^\1]*?)\1|([\+\-]?[\d\.]+)|(NULL))$/
my
(
$value
) = $4 || $3 || $2 || $1;
$value
=
"\x02\^4jSpR1tE\x02"
if
($4);
push
(
@values
,
$value
);
"=\x02\^3jSpR1tE\x02"
/ieg;
$posn
=
undef
;
$posn
= $1
if
(
$i
=~ s/^(\d+)\s*//o);
$i
=~ s/\s+/=/o;
$fd
=
$i
;
$fd
=~ s/=.*//o;
$fd
=~
tr
/a-z/A-Z/
unless
(
$self
->{sprite_CaseFieldNames});
for
(
my
$j
=0;
$j
<=
$#keyfields
;
$j
++)
{
$i
=~ s/=/=*/o
if
(
$fd
eq
$keyfields
[
$j
]);
}
$x
=
undef
;
$tp
=
undef
;
$i
=~ /\w+\=[\*]?(\w*)\s*(.*)/o;
(
$tp
,
$x
) = ($1, $2);
$oldln
= 0;
$tp
=~
tr
/a-z/A-Z/;
if
(
$type
=~ /modify/io)
{
unless
(
$tp
=~ /[a-zA-Z]/)
{
$tp
=
$self
->{types}->{
$fd
};
}
unless
(
$tp
eq
$self
->{types}->{
$fd
})
{
if
($
{
$errdetails
= ($
return
-521;
}
}
$olddf
=
undef
;
$olddf
=
$self
->{defaults}->{
$fd
}
if
(
defined
$self
->{defaults}->{
$fd
});
unless
(
$tp
eq
$self
->{types}->{
$fd
})
{
$self
->{lengths}->{
$fd
} = 0;
$self
->{scales}->{
$fd
} = 0;
}
$oldln
=
$self
->{lengths}->{
$fd
};
}
$self
->{defaults}->{
$fd
} =
undef
;
$self
->{lengths}->{
$fd
} = $1
if
(
$x
=~ s/(\d+)//o);
unless
(
$self
->{lengths}->{
$fd
})
{
$self
->{lengths}->{
$fd
} = 40;
$self
->{lengths}->{
$fd
} = 10
if
(
$tp
=~ /NUM|INT|FLOAT|DOUBLE/o);
$self
->{lengths}->{
$fd
} =
$self
->{LongReadLen} || 0
if
(
$tp
=~ /
$BLOBTYPES
/);
}
if
(
$self
->{lengths}->{
$fd
} <
$oldln
&&
$tp
!~ /
$BLOBTYPES
/)
{
$errdetails
=
$fd
;
return
-522;
}
$x
=~ s/\x02\^3jSpR1tE\x02/
$self
->{defaults}->{
$fd
} =
shift
(
@values
);
$self
->{defaults}->{
$fd
}/eg;
$self
->{fields}->{
$fd
} = 1;
if
(
$self
->{types}->{
$fd
} =~ /
$REFTYPES
/o ||
$tp
=~ /
$REFTYPES
/o)
{
$errdetails
=
"$fd: "
.
$self
->{types}->{
$fd
}.
" <=> $tp"
;
return
-529;
}
$self
->{types}->{
$fd
} =
$tp
;
$self
->{defaults}->{
$fd
} =
$olddf
if
((
defined
$olddf
) && !(
defined
$self
->{defaults}->{
$fd
}));
$self
->{defaults}->{
$fd
} =
undef
if
(
$self
->{defaults}->{
$fd
} eq
"\x02\^4jSpR1tE\x02"
);
if
(
$x
=~ s/\,\s*(\d+)//o)
{
$self
->{scales}->{
$fd
} = $1;
}
elsif
(
$self
->{types}->{
$fd
} eq
'FLOAT'
)
{
$self
->{scales}->{
$fd
} =
$self
->{lengths}->{
$fd
} - 3;
}
if
(
defined
$self
->{defaults}->{
$fd
})
{
my
(
$val
);
if
(
length
(
$self
->{defaults}->{
$fd
}) > 0 && ${
$self
->{types}}{
$fd
} =~ /
$NUMERICTYPES
/)
{
$val
=
sprintf
((
'%.'
.${
$self
->{scales}}{
$fd
}.
'f'
),
$self
->{defaults}->{
$fd
});
}
else
{
$val
=
$self
->{defaults}->{
$fd
};
}
$self
->{defaults}->{
$fd
} = (${
$self
->{types}}{
$fd
} =~ /
$BLOBTYPES
/) ?
$val
:
substr
(
$val
,0,${
$self
->{lengths}}{
$fd
});
unless
(
$self
->{LongTruncOk} || ${
$self
->{types}}{
$fd
} =~ /
$BLOBTYPES
/
||
$self
->{defaults}->{
$fd
} eq
$val
|| ${
$self
->{types}}{
$fd
} eq
'FLOAT'
)
{
$errdetails
=
"$fd to ${$self->{lengths}}{$fd} chars"
;
return
(-519);
}
if
(${
$self
->{types}}{
$fd
} eq
'FLOAT'
&&
int
(
$self
->{defaults}->{
$fd
}) !=
int
(
$val
))
{
$errdetails
=
"$fd to ${$self->{lengths}}{$fd} chars"
;
return
(-519);
}
if
(${
$self
->{types}}{
$fd
} eq
'CHAR'
&&
length
(
$self
->{defaults}->{
$fd
}) > 0)
{
$val
=
sprintf
(
'%-'
.${
$self
->{lengths}}{
$fd
}.
's'
,
$self
->{defaults}->{
$fd
});
$self
->{defaults}->{
$fd
} =
$val
;
}
}
if
(
$type
=~ /add/io)
{
if
(
defined
$posn
)
{
my
(
@myorder
) = (@{
$self
->{order} }[0..(
$posn
-1)],
$fd
,
@{
$self
->{order} }[
$posn
..$
@{
$self
->{order} } =
@myorder
;
}
else
{
push
(@{
$self
->{order} },
$fd
);
}
}
elsif
(
$type
=~ /modify/io)
{
if
(
defined
$posn
)
{
for
(
my
$j
=0;
$j
<=$
{
if
(${
$self
->{order} }[
$j
] eq
$fd
)
{
splice
(@{
$self
->{order} },
$j
, 1);
my
(
@myorder
) = (@{
$self
->{order} }[0..(
$posn
-1)],
$fd
,
@{
$self
->{order} }[
$posn
..$
@{
$self
->{order} } =
@myorder
;
last
;
}
}
}
}
elsif
(
$type
=~ /drop/io)
{
$self
->check_columns (
$fd
) ||
return
(-502);
$count
= -1;
foreach
(@{
$self
->{order} })
{
++
$count
;
last
if
(
$_
eq
$fd
);
}
splice
(@{
$self
->{order} },
$count
, 1);
delete
$self
->{fields}->{
$fd
};
delete
$self
->{types}->{
$fd
};
delete
$self
->{lengths}->{
$fd
};
delete
$self
->{scales}->{
$fd
};
}
}
$status
=
$self
->parse_columns (
"\L$type\E"
,
$column
);
$self
->{dirty} = 1;
$self
->commit(
$table
);
return
$status
;
}
else
{
$errdetails
=
$extra
;
return
(-506);
}
}
else
{
$errdetails
=
$query
;
return
(-507);
}
}
sub
insert
{
my
(
$self
,
$query
) =
@_
;
my
(
$i
,
$path
,
$table
,
$columns
,
$values
,
$status
);
$path
=
$self
->{path};
if
(
$query
=~ /^insert\s+into\s+
(
$path
)\s*
(?:\((.+?)\)\s*)?
values
\s*
\((.+)\)$/ixos)
{
(
$table
,
$columns
,
$values
) = ($1, $2, $3);
return
(-523)
if
(
$table
=~ /^DUAL$/io);
my
$cfr
=
$self
->check_for_reload(
$table
) || -501;
return
$cfr
if
(
$cfr
< 0);
$columns
||=
''
;
$columns
=~ s/\s//gso;
$columns
=
join
(
','
, @{
$self
->{order} })
unless
(
$columns
=~ /\S/o);
return
(-511)
unless
(-w
$self
->{file});
unless
(
$columns
=~ /\S/o)
{
$columns
=
&load_columninfo
(
$self
,
','
);
return
$columns
if
(
$columns
=~ /^\-?\d+$/o);
}
$values
=~ s/\\\\/\x02\^2jSpR1tE\x02/gso;
$values
=~ s/\\\'/\x02\^3jSpR1tE\x02/gso;
$values
=~ s/\\\"/\x02\^5jSpR1tE\x02/gso;
1
while
(
$values
=~ s/\(([^\)]*?)\)/
my
(
$j
)=$1;
$j
=~s|\,|\x02\^4jSpR1tE\x02|gso;
"($j\x02\^6jSpR1tE\x02"
/egs);
$values
=~ s/([\'\"])([^\1]*?)\1/
my
(
$j
)=$2;
$j
=~s|\,|\x02\^4jSpR1tE\x02|gso;
"'$j'"
/egs;
$values
=~ s/\x02\^6jSpR1tE\x02/\)/gso;
my
$x
;
my
@values
=
split
(/\,\s*/o ,
$values
);
$values
=
''
;
for
$i
(0..
$#values
)
{
$values
[
$i
] =~ s/^\s+//so;
$values
[
$i
] =~ s/\s+$//so;
$values
[
$i
] =~ s/\x02\^5jSpR1tE\x02/\\\"/gso;
$values
[
$i
] =~ s/\x02\^3jSpR1tE\x02/\\\'/gso;
$values
[
$i
] =~ s/\x02\^2jSpR1tE\x02/\\\\/gso;
$values
[
$i
] =~ s/\x02\^4jSpR1tE\x02/\,/gos;
if
(
$values
[
$i
] =~ /^[_a-zA-Z]/so)
{
if
(
$values
[
$i
] =~ /\s*(\w+).NEXTVAL\s*$/o
||
$values
[
$i
] =~ /\s*(\w+).CURRVAL\s*$/o)
{
my
(
$seq_file
) =
$self
->get_path_info($1) .
'.seq'
;
unless
(
open
(FILE,
"<$seq_file"
))
{
$errdetails
=
"$@/$? (file:$seq_file)"
;
return
(-511);
}
$x
= <FILE>;
$x
=~ s/\s+$//;
my
(
$incval
,
$startval
) =
split
(/,/o ,
$x
);
close
(FILE);
$_
=
$values
[
$i
];
if
(/\s*(\w+).NEXTVAL\s*$/o)
{
unlink
(
$seq_file
)
if
(
$self
->{sprite_forcereplace} && -e
$seq_file
);
unless
(
open
(FILE,
">$seq_file"
))
{
$errdetails
=
"$@/$? (file:$seq_file)"
;
return
(-511);
}
$incval
+= (
$startval
|| 1);
print
FILE
"$incval,$startval\n"
;
close
(FILE);
}
$values
[
$i
] =
$incval
;
$self
->{sprite_lastsequence} =
$incval
;
}
else
{
$values
[
$i
] =
eval
&chkcolumnparms
(
$self
,
$values
[
$i
]);
return
(-517)
if
($@);
}
}
};
chop
(
$values
);
$self
->check_columns (
$columns
) ||
return
(-502);
$status
=
$self
->insert_data (
$columns
,
@values
);
return
$status
;
}
else
{
$errdetails
=
$query
;
return
(-508);
}
}
sub
insert_data
{
my
(
$self
,
$column_string
,
@values
) =
@_
;
my
(
@columns
,
$hash
,
$loop
,
$column
,
$j
,
$k
,
$autoColumnIncluded
);
$column_string
=~
tr
/a-z/A-Z/
unless
(
$self
->{sprite_CaseFieldNames});
@columns
=
split
(/,/,
$column_string
);
foreach
my
$i
(@{
$self
->{order} })
{
if
(${
$self
->{types}}{
$i
} =~ /AUTO/io)
{
$autoColumnIncluded
= 0;
foreach
my
$j
(
@columns
)
{
if
(
$j
eq
$i
)
{
$autoColumnIncluded
= 1;
last
;
}
}
unless
(
$autoColumnIncluded
)
{
push
(
@columns
,
$i
);
push
(
@values
,
''
);
}
}
}
$column_string
=
join
(
','
,
@columns
);
if
(
$#columns
==
$#values
) {
my
(
@keyfields
) =
split
(
','
,
$self
->{key_fields});
my
(
$matchcnt
) = 0;
$hash
= {};
foreach
$column
(@{
$self
->{order} })
{
$column
=~
tr
/a-z/A-Z/
unless
(
$self
->{sprite_CaseFieldNames});
$hash
->{
$column
} =
$self
->{defaults}->{
$column
}
if
(
defined
(
$self
->{defaults}->{
$column
}) &&
length
(
$self
->{defaults}->{
$column
}));
}
for
(
$loop
=0;
$loop
<=
$#columns
;
$loop
++)
{
$column
=
$columns
[
$loop
];
$column
=~
tr
/a-z/A-Z/
unless
(
$self
->{sprite_CaseFieldNames});
my
(
$v
);
if
(
$self
->{fields}->{
$column
})
{
$values
[
$loop
] =~ s/^\'(.*)\'$/
my
(
$stuff
) = $1;
$stuff
=~ s|\'\'|\'|gso;
$stuff
/es;
$values
[
$loop
] =~ s|^\'$||so;
if
(${
$self
->{types}}{
$column
} =~ /AUTO/o)
{
if
(
length
(
$values
[
$loop
]))
{
$errdetails
=
"value($values[$loop]) into column($column)"
;
return
(-524);
}
else
{
$v
= ++
$self
->{defaults}->{
$column
};
$self
->{sprite_lastsequence} =
$v
;
}
}
elsif
(
length
(
$values
[
$loop
]) || !
length
(
$self
->{defaults}->{
$column
}))
{
$v
=
$values
[
$loop
];
}
else
{
$v
=
$self
->{defaults}->{
$column
};
}
if
(
length
(
$v
) > 0 && ${
$self
->{types}}{
$column
} =~ /
$NUMERICTYPES
/)
{
$hash
->{
$column
} =
sprintf
((
'%.'
.${
$self
->{scales}}{
$column
}.
'f'
),
$v
);
}
elsif
(${
$self
->{types}}{
$column
} =~ /
$REFTYPES
/o)
{
my
$randblobid
=
int
(
rand
(99999));
my
$randblobfid
;
do
{
$randblobid
=
int
(
rand
(99999));
$randblobfid
=
$self
->{directory}
.
$self
->{separator}->{
$self
->{platform} }
.
$self
->{table}.
"_${randblobid}_$$.tmp"
;
}
while
(-e
$randblobfid
);
if
(
open
(FILE,
">$randblobfid"
))
{
binmode
FILE;
if
(
$self
->{CBC} &&
$self
->{sprite_Crypt} <= 2)
{
print
FILE
$self
->{CBC}->encrypt(
$v
);
}
else
{
print
FILE
$v
;
}
close
FILE;
$hash
->{
$column
} =
$randblobid
;
}
else
{
$errdetails
=
"$randblobfid: ($?)"
;
return
(-528);
}
}
else
{
$hash
->{
$column
} =
$v
;
}
$v
= (${
$self
->{types}}{
$column
} =~ /
$BLOBTYPES
/) ?
$hash
->{
$column
} :
substr
(
$hash
->{
$column
},0,${
$self
->{lengths}}{
$column
});
unless
(
$self
->{LongTruncOk} ||
$v
eq
$hash
->{
$column
} ||
(${
$self
->{types}}{
$column
} eq
'FLOAT'
))
{
$errdetails
=
"$column to ${$self->{lengths}}{$column} chars"
;
return
(-519);
}
if
((${
$self
->{types}}{
$column
} eq
'FLOAT'
)
&& (
int
(
$v
) !=
int
(
$hash
->{
$column
})))
{
$errdetails
=
"$column to ${$self->{lengths}}{$column} chars"
;
return
(-519);
}
elsif
(${
$self
->{types}}{
$column
} eq
'CHAR'
&&
length
(
$v
) > 0)
{
$hash
->{
$column
} =
sprintf
(
'%-'
.${
$self
->{lengths}}{
$column
}.
's'
,
$v
);
}
else
{
$hash
->{
$column
} =
$v
;
}
}
}
recloop:
for
(
$k
=0;
$k
<
scalar
@{
$self
->{records} };
$k
++)
{
$matchcnt
= 0;
valueloop:
foreach
$column
(
keys
%$hash
)
{
keyloop:
for
(
$j
=0;
$j
<=
$#keyfields
;
$j
++)
{
if
(
$column
eq
$keyfields
[
$j
])
{
if
(
$self
->{records}->[
$k
]->{
$column
} eq
$hash
->{
$column
})
{
++
$matchcnt
;
return
(-518)
if
(
$matchcnt
&&
$matchcnt
>
$#keyfields
); #ALL KEY FIELDS WERE DUPLICATES!
}
}
}
}
}
push
@{
$self
->{records} },
$hash
;
$self
->{dirty} = 1;
return
(1);
}
else
{
$errdetails
=
"$#columns != $#values"
; #20000114
return
(-509);
}
}
sub
write_file
{
my
(
$self
,
$new_file
) =
@_
;
my
(
$i
,
$j
,
$status
,
$loop
,
$record
,
$column
,
$value
,
$fields
,
$record_string
);
my
(
@keyfields
) =
split
(
','
,
$self
->{key_fields});
return
(
$self
->display_error (-531) * -531)
if
((
$self
->{_write} =~ /^xml/io) &&
$self
->{CBC} &&
$self
->{sprite_Crypt} <= 2);
local
(
*FILE
, $^W);
local
($/);
if
(
$self
->{CBC} &&
$self
->{sprite_Crypt} <= 2)
{
$/ =
"\x03^0jSp"
.
$self
->{_record};
}
elsif
(
$self
->{_write} !~ /^xml/io)
{
$/ =
$self
->{_record};
}
$^W = 0;
$status
= 1;
return
1
if
$
unlink
(
$new_file
)
if
(
$status
>= 1 &&
$self
->{sprite_forcereplace} && -e
$new_file
);
if
( (
$status
>= 1) && (
open
(FILE,
">$new_file"
)) ) {
binmode
FILE;
if
(
$self
->{platform} eq
'PC'
)
{
$self
->
lock
||
$self
->display_error (-515);
}
else
{
eval
{
flock
(FILE,
$JSprite::LOCK_EX
) ||
die
};
if
($@)
{
$self
->
lock
||
$self
->display_error (-515)
if
($@);
}
}
$fields
=
''
;
my
$reccnt
=
scalar
@{
$self
->{records} };
if
(
$self
->{_write} =~ /^xml/io)
{
$fields
=
<<END_XML;
<?xml version="1.0" encoding="UTF-8"?>
END_XML
$fields
.=
<<END_XML if ($self->{sprite_xsl});
<?xml-stylesheet type="text/xsl" href="$self->{sprite_xsl}"?>
END_XML
$fields
.=
<<END_XML;
<database name="$self->{dbname}" user="$self->{dbuser}">
<select query="select * from $self->{table}" rows="$reccnt">
END_XML
$fields
.=
' <columns order="'
.
join
(
','
,@{
$self
->{order} }).
'">'
.
"\n"
;
my
(
$iskey
,
$haveadefault
,
$havemaxsize
,
$typeinfo
);
for
$i
(0..$
{
$iskey
=
'NO'
;
for
(
$j
=0;
$j
<=
$#keyfields
;
$j
++) #JWT: MARK KEY FIELDS.
{
if
(${
$self
->{order}}[
$i
] eq
$keyfields
[
$j
])
{
$iskey
=
'PRIMARY'
;
last
;
}
}
$haveadefault
= ${
$self
->{defaults}}{${
$self
->{order}}[
$i
]};
$havemaxsize
= (${
$self
->{types}}{${
$self
->{order}}[
$i
]} =~ /
$BLOBTYPES
/)
? (
$self
->{LongReadLen} ||
'0'
)
: (
$self
->{maxsizes}->{${
$self
->{types}}{${
$self
->{order}}[
$i
]}}
|| ${
$self
->{lengths}}{${
$self
->{order}}[
$i
]} ||
'0'
);
$fields
.=
<<END_XML
<column>
<name>${$self->{order}}[$i]</name>
<type>${$self->{types}}{${$self->{order}}[$i]}</type>
<size>$havemaxsize</size>
<precision>${$self->{lengths}}{${$self->{order}}[$i]}</precision>
<scale>${$self->{scales}}{${$self->{order}}[$i]}</scale>
<nullable>NULL</nullable>
<key>$iskey</key>
<default>$haveadefault</default>
</column>
END_XML
}
$fields
.=
" </columns>\n"
;
}
else
{
for
$i
(0..$
{
$fields
.= ${
$self
->{order}}[
$i
] .
'='
;
for
(
$j
=0;
$j
<=
$#keyfields
;
$j
++) #JWT: MARK KEY FIELDS.
{
$fields
.=
'*'
if
(${
$self
->{order}}[
$i
] eq
$keyfields
[
$j
])
}
$fields
.= ${
$self
->{types}}{${
$self
->{order}}[
$i
]};
unless
(${
$self
->{types}}{${
$self
->{order}}[
$i
]} =~ /
$BLOBTYPES
/)
{
$fields
.=
'('
. ${
$self
->{lengths}}{${
$self
->{order}}[
$i
]};
if
(${
$self
->{scales}}{${
$self
->{order}}[
$i
]}
&& ${
$self
->{types}}{${
$self
->{order}}[
$i
]} =~ /
$NUMERICTYPES
/)
{
$fields
.=
','
. ${
$self
->{scales}}{${
$self
->{order}}[
$i
]}
}
$fields
.=
')'
;
}
$fields
.=
'='
. ${
$self
->{defaults}}{${
$self
->{order}}[
$i
]}
if
(
length
(${
$self
->{defaults}}{${
$self
->{order}}[
$i
]}));
$fields
.=
$self
->{_write};
}
$fields
=~ s/
$self
->{_write}$//;
}
if
(
$self
->{CBC} &&
$self
->{sprite_Crypt} <= 2)
{
print
FILE
$self
->{CBC}->encrypt(
$fields
).$/;
}
else
{
print
FILE
"$fields$/"
;
}
my
$rsinit
= (
$self
->{_write} =~ /^xml/io) ?
" <row>\n"
:
''
;
my
$rsend
=
$rsinit
?
" </row>\n"
:
''
;
for
(
$loop
=0;
$loop
<
$reccnt
;
$loop
++) {
$record
=
$self
->{records}->[
$loop
];
next
unless
(
defined
$record
);
$record_string
=
$rsinit
;
foreach
$column
(@{
$self
->{order} })
{
if
(${
$self
->{types}}{
$column
} eq
'CHAR'
&&
length
(
$record
->{
$column
}) > 0)
{
$value
=
sprintf
(
'%-'
.${
$self
->{lengths}}{
$column
}.
's'
,
$record
->{
$column
});
}
else
{
$value
=
$record
->{
$column
};
}
$value
=~ s/
$self
->{_record}/\x02\^0jSpR1tE\x02/gso;
$value
=~ s/
$self
->{_write}/\x02\^1jSpR1tE\x02/gso;
$record_string
.=
$rsinit
? (
&xmlescape
(
$column
,
$value
).
"\n"
)
:
"$self->{_write}$value"
;
}
$record_string
=~ s/^
$self
->{_write}//s;
$record_string
.=
$rsend
;
if
(
$self
->{CBC} &&
$self
->{sprite_Crypt} <= 2)
{
print
FILE
$self
->{CBC}->encrypt(
$record_string
).$/;
}
else
{
print
FILE
"$record_string$/"
;
}
}
if
(
$rsend
)
{
$rsend
=
" </select>\n</database>\n"
;
if
(
$self
->{CBC} &&
$self
->{sprite_Crypt} <= 2)
{
print
FILE
$self
->{CBC}->encrypt(
$rsend
).$/;
}
else
{
print
FILE
"$rsend$/"
;
}
}
close
(FILE);
my
(
@stats
) =
stat
(
$new_file
);
$self
->{timestamp} =
$stats
[9];
$self
->unlock ||
$self
->display_error (-516);
}
else
{
$status
= (
$status
< 1) ?
$status
: -511;
}
return
$status
;
}
{
my
%xmleschash
= (
'<'
=>
'<'
,
'>'
=>
'>'
,
'"'
=>
'"'
,
'--'
=>
'--'
,
);
sub
xmlescape
{
my
$res
;
$_
[1] =~ s/\&/\
&
;/gs;
eval
"\$_[1] =~ s/("
.
join
(
'|'
,
keys
(
%xmleschash
)).
")/\$xmleschash{\$1}/gs;"
;
if
(
$_
[1] =~ /[\x00-\x08\x0A-\x0C\x0E-\x19\x7f-\xff]/o)
{
return
" <$_[0] xml:encoding=\"base64\">"
. MIME::Base64::encode_base64(
$_
[1]) .
"</$_[0]>"
;
}
else
{
return
" <$_[0]>$_[1]</$_[0]>"
;
}
}
}
sub
load_database
{
my
(
$self
,
$file
) =
@_
;
return
-531
if
((
$self
->{_read} =~ /^xml/io) &&
$self
->{CBC} &&
$self
->{sprite_Crypt} <= 2);
my
(
$i
,
$header
,
@fields
,
$no_fields
,
@record
,
$hash
,
$loop
,
$tp
,
$dflt
);
local
(
*FILE
);
local
($/);
if
(
$self
->{CBC} &&
$self
->{sprite_Crypt} != 2)
{
$/ =
"\x03^0jSp"
.
$self
->{_record};
}
else
{
$/ =
$self
->{_record};
}
undef
@{
$self
->{records} }
if
(
scalar
@{
$self
->{records} });
$self
->{use_fields} =
''
;
$self
->{key_fields} =
''
;
if
(
$self
->{_read} =~ /^xml/io)
{
return
-532
unless
(
$XMLavailable
);
my
$xs1
= XML::Simple->new();
my
$xmldoc
;
eval
{
$xmldoc
=
$xs1
->XMLin(
$file
,
suppressempty
=>
undef
); };
$errdetails
= $@;
return
-501
unless
(
$xmldoc
);
@fields
= (
$xmldoc
->{
select
}->{columns}->{order})
?
split
(/\,/,
$xmldoc
->{
select
}->{columns}->{order})
:
keys
(%{
$xmldoc
->{
select
}->{columns}->{column}});
foreach
my
$i
(0..
$#fields
)
{
$self
->{key_fields} .= (
$fields
[
$i
] .
','
)
if
(
$xmldoc
->{
select
}->{columns}->{column}->{
$fields
[
$i
]}->{key}
eq
'PRIMARY'
);
${
$self
->{types}}{
$fields
[
$i
]} =
$xmldoc
->{
select
}->{columns}->{column}->{
$fields
[
$i
]}->{type};
${
$self
->{lengths}}{
$fields
[
$i
]} =
$xmldoc
->{
select
}->{columns}->{column}->{
$fields
[
$i
]}->{precision};
${
$self
->{scales}}{
$fields
[
$i
]} =
$xmldoc
->{
select
}->{columns}->{column}->{
$fields
[
$i
]}->{scale};
${
$self
->{defaults}}{
$fields
[
$i
]} =
undef
;
if
(
length
(
$xmldoc
->{
select
}->{columns}->{column}->{
$fields
[
$i
]}->{
default
}) > 0)
{
${
$self
->{defaults}}{
$fields
[
$i
]} =
$xmldoc
->{
select
}->{columns}->{column}->{
$fields
[
$i
]}->{
default
};
}
$self
->{use_fields} .=
$fields
[
$i
] .
','
;
}
if
(
ref
(
$xmldoc
->{
select
}->{row}) eq
'ARRAY'
)
{
$self
->{records} =
$xmldoc
->{
select
}->{row};
}
elsif
(
ref
(
$xmldoc
->{
select
}->{row}) eq
'HASH'
)
{
$self
->{records}->[0] =
$xmldoc
->{
select
}->{row};
}
else
{
$self
->{records} =
undef
;
}
$xmldoc
=
undef
;
if
(
ref
(
$self
->{records}) eq
'ARRAY'
)
{
for
(
my
$i
=0;
$i
<=$
{
foreach
my
$j
(
@fields
)
{
if
(
$self
->{records}->[
$i
]->{
$j
}->{
'xml:encoding'
})
{
$self
->{records}->[
$i
]->{
$j
} = MIME::Base64::decode_base64(
$self
->{records}->[
$i
]->{
$j
}->{content});
}
$self
->{records}->[
$i
]->{
$j
} =
''
if
(
ref
(
$self
->{records}->[
$i
]->{
$j
}));
$self
->{records}->[
$i
]->{
$j
} =~ s/\
<
;/\</gso;
$self
->{records}->[
$i
]->{
$j
} =~ s/\
>
;/\>/gso;
$self
->{records}->[
$i
]->{
$j
} =~ s/\
"
;/\"/gso;
$self
->{records}->[
$i
]->{
$j
} =~ s/\&\
$self
->{records}->[
$i
]->{
$j
} =~ s/\
&
;/\&/gso;
}
}
}
}
else
{
open
(FILE,
$file
) ||
return
(-501);
binmode
FILE;
if
(
$self
->{platform} eq
'PC'
)
{
$self
->
lock
||
$self
->display_error (-515);
}
else
{
eval
{
flock
(FILE,
$JSprite::LOCK_EX
) ||
die
};
if
($@)
{
$self
->
lock
||
$self
->display_error (-515)
if
($@);
}
}
$_
= <FILE>;
chomp
;
my
$t
=
$_
;
$_
=
$self
->{CBC}->decrypt(
$t
)
if
(
$self
->{CBC} &&
$self
->{sprite_Crypt} != 2);
return
-527
unless
(/^\w+\=/o);
(
$header
) = /^ *(.*?) *$/o;
@fields
=
split
(/\Q
$self
->{_read}\E/,
$header
);
$no_fields
=
$#fields
;
undef
%{
$self
->{types} };
undef
%{
$self
->{lengths} };
undef
%{
$self
->{scales} };
my
$ln
;
foreach
$i
(0..
$#fields
)
{
$dflt
=
undef
;
(
$fields
[
$i
],
$tp
,
$dflt
) =
split
(/\=/o ,
$fields
[
$i
]);
$fields
[
$i
] =~
tr
/a-z/A-Z/
unless
(
$self
->{sprite_CaseFieldNames});
$tp
=
'VARCHAR(40)'
unless
(
$tp
);
$tp
=~
tr
/a-z/A-Z/;
$self
->{key_fields} .=
$fields
[
$i
] .
','
if
(
$tp
=~ s/^\*//o);
$ln
= 40;
$ln
= 10
if
(
$tp
=~ /NUM|INT|FLOAT|DOUBLE/);
$ln
=
$self
->{LongReadLen} || 0
if
(
$tp
=~ /
$BLOBTYPES
/);
$ln
= $2
if
(
$tp
=~ s/(.*)\((.*)\)/$1/);
${
$self
->{types}}{
$fields
[
$i
]} =
$tp
;
${
$self
->{lengths}}{
$fields
[
$i
]} =
$ln
;
${
$self
->{defaults}}{
$fields
[
$i
]} =
undef
;
${
$self
->{defaults}}{
$fields
[
$i
]} =
$dflt
if
(
defined
$dflt
);
if
(${
$self
->{lengths}}{
$fields
[
$i
]} =~ s/\,(\d+)//)
{
${
$self
->{scales}}{
$fields
[
$i
]} = $1;
}
elsif
(${
$self
->{types}}{
$fields
[
$i
]} eq
'FLOAT'
)
{
${
$self
->{scales}}{
$fields
[
$i
]} = ${
$self
->{lengths}}{
$fields
[
$i
]} - 3;
}
${
$self
->{scales}}{
$fields
[
$i
]} =
'0'
unless
(${
$self
->{scales}}{
$fields
[
$i
]});
$self
->{use_fields} .=
$fields
[
$i
] .
','
;
}
while
(<FILE>)
{
chomp
;
$t
=
$_
;
$_
=
$self
->{CBC}->decrypt(
$t
)
if
(
$self
->{CBC} &&
$self
->{sprite_Crypt} != 2);
next
unless
(
$_
);
@record
=
split
(/\Q
$self
->{_read}\E/s,
$_
);
$hash
= {};
for
(
$loop
=0;
$loop
<=
$no_fields
;
$loop
++)
{
$record
[
$loop
] =~ s/\x02\^0jSpR1tE\x02/
$self
->{_record}/gs;
$record
[
$loop
] =~ s/\x02\^1jSpR1tE\x02/
$self
->{_read}/gs;
$hash
->{
$fields
[
$loop
] } =
$record
[
$loop
];
}
push
@{
$self
->{records} },
$hash
;
}
close
(FILE);
$self
->unlock ||
$self
->display_error (-516);
}
chop
(
$self
->{use_fields})
if
(
$self
->{use_fields});
chop
(
$self
->{key_fields})
if
(
$self
->{key_fields});
undef
%{
$self
->{fields} };
undef
@{
$self
->{order} };
$self
->{order} = [
@fields
];
$self
->{fieldregex} =
$self
->{use_fields};
$self
->{fieldregex} =~ s/,/\|/go;
map
{
$self
->{fields}->{
$_
} = 1 }
@fields
;
return
(1);
}
sub
load_columninfo
{
my
(
$self
) =
shift
;
my
(
$sep
) =
shift
;
my
$colmlist
;
if
($
{
$colmlist
=
join
(
$sep
, @{
$self
->{order}});
}
else
{
local
(
*FILE
);
local
(
$_
);
local
($/) =
$self
->{_record};
open
(FILE,
$self
->{file}) ||
return
-501;
binmode
FILE;
if
(
$self
->{_read} =~ /^xml/io)
{
return
-531
if
(
$self
->{CBC} &&
$self
->{sprite_Crypt} <= 2);
return
-532
unless
(
$XMLavailable
);
my
$xs1
= XML::Simple->new();
my
$xmltext
=
''
;
my
$xmldoc
;
while
(<FILE>)
{
last
if
(/^\s*\<row.*\>\s*$/o);
$xmltext
.=
$_
;
}
$xmltext
.=
<<END_XML; #MAKE IT WELL-FORMED!
</row>
</select>
</database>
END_XML
eval
{
$xmldoc
=
$xs1
->XMLin(
$xmltext
,
suppressempty
=>
undef
); };
$errdetails
= $@;
return
-501
unless
(
$xmldoc
);
$colmlist
=
$xmldoc
->{
select
}->{columns}->{order};
if
(
$colmlist
)
{
@{
$self
->{order}} =
split
(/
$sep
/,
$colmlist
);
}
else
{
@{
$self
->{order}} =
keys
(%{
$xmldoc
->{
select
}->{columns}->{column}});
$colmlist
=
join
(
$sep
, @{
$self
->{order}});
}
}
else
{
my
$colmlist
= <FILE>;
chomp
(
$colmlist
);
$colmlist
=~ s/\Q
$self
->{_read}\E/
$sep
/g;
@{
$self
->{order}} =
split
(/
$sep
/,
$colmlist
);
}
close
FILE;
}
return
$colmlist
;
}
sub
pscolfn
{
my
(
$self
,
$id
) =
@_
;
return
$id
unless
(
$id
=~ /CURRVAL|NEXTVAL/);
my
(
$value
) =
''
;
my
(
$seq_file
,
$col
) =
split
(/\./,
$id
);
$seq_file
=
$self
->get_path_info(
$seq_file
) .
'.seq'
;
unless
(
open
(FILE,
"<$seq_file"
))
{
$errdetails
=
"$@/$? (file:$seq_file)"
;
return
(-511);
}
my
$x
= <FILE>;
$x
=~ s/\s+$//o;
my
(
$incval
,
$startval
) =
split
(/\,/o ,
$x
);
close
(FILE);
if
(
$id
=~ /NEXTVAL/o)
{
unlink
(
$seq_file
)
if
(
$self
->{sprite_forcereplace} && -e
$seq_file
);
unless
(
open
(FILE,
">$seq_file"
))
{
$errdetails
=
"$@/$? (file:$seq_file)"
;
return
(-511);
}
$incval
+= (
$startval
|| 1);
print
FILE
"$incval,$startval\n"
;
close
(FILE);
}
$value
=
$incval
;
$self
->{sprite_lastsequence} =
$incval
;
return
$value
;
}
sub
quotewords {
my
(
$self
,
$delim
,
$keep
,
@lines
) =
@_
;
my
(
@words
,
$snippet
,
$field
,
$q
,
@quotes
);
$_
=
join
(
''
,
@lines
);
while
(
$_
) {
$field
=
''
;
for
(;;) {
$snippet
=
''
;
@quotes
= (
'\''
,
'"'
);
if
(s/^(["'`])(.+?)\1//) {
$snippet
= $2;
$snippet
=
"$1$snippet$1"
if
(
$keep
);
$field
.=
$snippet
;
last
;
}
elsif
(/^["']/o) {
$self
->display_error(-512);
return
();
}
elsif
(s/^\\(.)//o) {
$snippet
= $1;
$snippet
=
"\\$snippet"
if
(
$keep
);
}
elsif
(!
$_
|| s/^
$delim
//) {
last
;
}
else
{
while
(
$_
&& !(/^
$delim
/)) {
last
if
(/^['"]/ && (
$snippet
!~ /\\$/o));
$snippet
.=
substr
(
$_
, 0, 1);
substr
(
$_
, 0, 1) =
''
;
}
}
$field
.=
$snippet
;
}
push
(
@words
,
$field
);
}
@words
;
}
sub
chkcolumnparms
{
my
(
$self
) =
shift
;
my
(
$evalstr
) =
shift
;
$evalstr
=~ s/\\\'/\x02\^2jSpR1tE\x02/gso;
$evalstr
=~ s/\\\"/\x02\^3jSpR1tE\x02/gso;
my
$i
= -1;
my
(
@strings
);
$evalstr
=~ s/([\'\"])([^\1]*?)\1/
my
(
$one
,
$two
) = ($1, $2);
++
$i
;
$two
=~ s|([\'\"])|$1$1|g;
$strings
[
$i
] =
"$one$two$one"
;
"\x02\^4jSpR1tE\x02$i"
;
/egs;
$evalstr
=~ s/(
$self
->{fieldregex})/
my
(
$one
) = $1;
$one
=~
tr
!a-z!A-Z!;
my
$res
= (
defined
$_
->{
$one
}) ?
$_
->{
$one
} :
$one
;
$res
=
'"'
.
$res
.
'"'
unless
(${
$self
->{types}}{
$one
} =~ m
$res
;
/eigs;
$evalstr
=~ s/\x02\^4jSpR1tE\x02(\d+)/
$strings
[$1]/g;
$evalstr
=~ s/\x02\^3jSpR1tE\x02/\\\'/go;
$evalstr
=~ s/\x02\^2jSpR1tE\x02/\\\"/go;
return
$evalstr
;
}
sub
SYSTIME
{
return
time
;
}
sub
SYSDATE
{
return
time
;
}
sub
NUM
{
return
shift
;
}
sub
NULL
{
return
''
;
}
sub
ROWNUM
{
return
(
scalar
(
@$results
) + 1);
}
sub
USER
{
return
$sprite_user
;
}
sub
fn_register
{
shift
if
(
ref
(
$_
[0]) eq
'HASH'
);
my
(
$fnname
,
$packagename
) =
@_
;
$packagename
=
'main'
unless
(
$packagename
);
eval
<<END_EVAL;
sub $fnname
{
return &${packagename}::$fnname;
}
END_EVAL
}
1;