Reputation: 65
I have a simple perl script which queries the dml (ignore the db->query bit if it looks strange - I am not using the DBI library) for a database view, then stores this in a global variable
my $dmlRef = $db->query($sql) || die "cannot query the db $! \n for sql: $sql";
our $dml = $dmlRef->[0]->{'DML'};
when I print this dml in a sub (print "$main::dml\n") , it looks like this:
"... from schema.MY_CALL_LOG ..."
the dml is a series of common table expressions so there are lots of schemas mentioned in it in the same style as above.
so I then have a sub, where I try and find if my list of schemas are in this, using the global variable I saved the dml to:
sub is_in_view_dll {
my $schema = shift || die "no schema passed in";
if ($main::dml =~ m/FROM\s+$schema\.MY_CALL_LOG/ig){ ##use global variable $dml here
print "found $schema in dml!\n";
}else{
print "couldn't find $schema in dml \n";
}
when I use this, I find that the perl fails to regex match some of the schema names in my list, despite me checking that a) they are in the dml b) the case matches up in my schema list (which has no spaces in the names of schemas)
When I instead make a local copy of the global $dml variable, I find that perl regex works as expected
sub is_in_view_dll {
my $schema = shift || die "no schema passed in";
my $localdml = "$main::dml";
if ($localdml =~ m/FROM\s+$schema\.MY_CALL_LOG/ig){ ##search through local copy of global var
print "found $schema in dml!\n"; ##works correctly
}else{
print "couldn't find $schema in dml \n";
}
I can't understand why using the global variable directly "$main::dml" didn't work for all the attempts to match, while using the local copy of it in the regex in the sub did work
I have created a stripped back example where I can replicate this issue (and you hopefully can too) with the data/input that is being generated included as a string stored in the our $dml variable:
#!/usr/bin/perl -I/usr/local/lib/perl
use strict;
use Data::Dumper;
our $dml = <<EOM
CREATE OR REPLACE FORCE EDITIONABLE VIEW "GWMONITORING"."MY_CALL_LOG" ("OWNER", "DAY", "HOUR", "USERNAME", "CALL_ID") AS
SELECT
'DEMOGW' AS OWNER,
TRUNC (TIME_START) DAY,
TO_NUMBER (TO_CHAR (TIME_START, 'HH24')) HOUR,
USERNAME,
CALL_ID
FROM
DEMOGW.MY_CALL_LOG
UNION ALL
SELECT
'ARMYS' AS OWNER,
TRUNC (TIME_START) DAY,
TO_NUMBER (TO_CHAR (TIME_START, 'HH24')) HOUR,
USERNAME,
CALL_ID
FROM
ARMYS.MY_CALL_LOG
UNION ALL
SELECT
'GFW' AS OWNER,
TRUNC (TIME_START) DAY,
TO_NUMBER (TO_CHAR (TIME_START, 'HH24')) HOUR,
USERNAME,
CALL_ID
FROM
GFW.MY_CALL_LOG
UNION ALL
SELECT
'GLOBE' AS OWNER,
TRUNC (TIME_START) DAY,
TO_NUMBER (TO_CHAR (TIME_START, 'HH24')) HOUR,
USERNAME,
CALL_ID
FROM
GLOBE.MY_CALL_LOG
UNION ALL
SELECT
'VARS' AS OWNER,
TRUNC (TIME_START) DAY,
TO_NUMBER (TO_CHAR (TIME_START, 'HH24')) HOUR,
USERNAME,
CALL_ID
FROM
VARS.MY_CALL_LOG
UNION ALL
SELECT
'ALLHH' AS OWNER,
TRUNC (TIME_START) DAY,
TO_NUMBER (TO_CHAR (TIME_START, 'HH24')) HOUR,
USERNAME,
CALL_ID
FROM
ALLHH.MY_CALL_LOG
UNION ALL
SELECT
'GW' AS OWNER,
TRUNC (TIME_START) DAY,
TO_NUMBER (TO_CHAR (TIME_START, 'HH24')) HOUR,
USERNAME,
CALL_ID
FROM
GW.MY_CALL_LOG
UNION ALL
SELECT
'QUEEN' AS OWNER,
TRUNC (TIME_START) DAY,
TO_NUMBER (TO_CHAR (TIME_START, 'HH24')) HOUR,
USERNAME,
CALL_ID
FROM
QUEEN.MY_CALL_LOG
UNION ALL
SELECT
'GEORGEY' AS OWNER,
TRUNC (TIME_START) DAY,
TO_NUMBER (TO_CHAR (TIME_START, 'HH24')) HOUR,
USERNAME,
CALL_ID
FROM
GEORGEY.MY_CALL_LOG
UNION ALL
SELECT
'MONKEYS' AS OWNER,
TRUNC (TIME_START) DAY,
TO_NUMBER (TO_CHAR (TIME_START, 'HH24')) HOUR,
USERNAME,
CALL_ID
FROM
MONKEYS.MY_CALL_LOG
UNION ALL
SELECT
'MYPAQS' AS OWNER,
TRUNC (TIME_START) DAY,
TO_NUMBER (TO_CHAR (TIME_START, 'HH24')) HOUR,
USERNAME,
CALL_ID
FROM
MYPAQS.MY_CALL_LOG
UNION ALL
SELECT
'GWINV' AS OWNER,
TRUNC (TIME_START) DAY,
TO_NUMBER (TO_CHAR (TIME_START, 'HH24')) HOUR,
USERNAME,
CALL_ID
FROM
GWINV.MY_CALL_LOG
UNION ALL
SELECT
'PRIMER' AS OWNER,
TRUNC (TIME_START) DAY,
TO_NUMBER (TO_CHAR (TIME_START, 'HH24')) HOUR,
USERNAME,
CALL_ID
FROM
PRIMER.MY_CALL_LOG
UNION ALL
SELECT
'GWSTIM' AS OWNER,
TRUNC (TIME_START) DAY,
TO_NUMBER (TO_CHAR (TIME_START, 'HH24')) HOUR,
USERNAME,
CALL_ID
FROM
GWSTIM.MY_CALL_LOG
UNION ALL
SELECT
'GFW2' AS OWNER,
TRUNC (TIME_START) DAY,
TO_NUMBER (TO_CHAR (TIME_START, 'HH24')) HOUR,
USERNAME,
CALL_ID
FROM
GFW2.MY_CALL_LOG
UNION ALL
SELECT
'GPETW' AS OWNER,
TRUNC (TIME_START) DAY,
TO_NUMBER (TO_CHAR (TIME_START, 'HH24')) HOUR,
USERNAME,
CALL_ID
FROM
GPETW.MY_CALL_LOG
UNION ALL
SELECT
'GWAHG' AS OWNER,
TRUNC (TIME_START) DAY,
TO_NUMBER (TO_CHAR (TIME_START, 'HH24')) HOUR,
USERNAME,
CALL_ID
FROM
GWAHG.MY_CALL_LOG
EOM
;
my @schemas = qw(GW GWAHG GPETW GFW2 GFW GWSTIM DEMOGW GWINV GLOBE PRIMER ARMYS MONKEYS QUEEN VARS ALLHH MYPAQS GEORGEY );
foreach(@schemas){
is_in_view($_);
}
sub is_in_view {
my $owner = shift || die "no owner passed in";
my $localdml = "$main::dml";
if ($localdml !~ m/FROM\s+$owner\.MY_CALL_LOG/ig){ ##when you use this line, should find no matches fail to be found
#if ($main::dml !~ m/FROM\s+$owner\.MY_CALL_LOG/ig){ ##when you use this line, should find that some matches fail to be found. For me this was GPETW, GFW DEMOGW GLOBE ARMYS QUEEN GEORGEY
print "$owner is not in the dml for GWMONITORING\.MY_CALL_LOG\n";
}
}
Upvotes: 1
Views: 107
Reputation: 3262
This is the regex engine storing the last position and starting at that position for the next match (under /g):
#!/bin/env perl
use strict;
use warnings;
my $string = 'bar foo bar baz';
for my $pat (qw/bar foo bar foo/){
if ($string =~ /$pat/g){
print "\nmatch for $pat\n"
}
else{
print "\nno match for $pat\n"
}
print pos $string;
}
prints:
match for bar
3
match for foo
7
match for bar
11
no match for foo
Use of uninitialized value in print at command.pl line 13.
The last match will fail, because there is no 'foo' after pos 11 in the string.
If you add a debug print for pos $main::dml
to your function or reset pos each time pos($main::dml) = 0;
you will see the effect.
Note that pos gets reset after a failing match.
See perlrequick for reference.
Upvotes: 2