ClearQuest Perl : how to clear a list of values? SetFieldValue doesn't work on lists - perl

New to Perl and new to ClearQuest Perl API both. I am trying to clear some values from a CQ form. I am able to clear values by simply setting the value to "" but it doesn't work on lists. Any idea how this can be done?
# following doesn't work on lists. What to do?
$entity->SetFieldValue("Foo_List", "");
# following works just fine
$entity->SetFieldValue("barstatus", "");
Here is CQ API reference:
http://publib.boulder.ibm.com/infocenter/cqhelp/v7r0m1/index.jsp?topic=/com.ibm.rational.clearquest.apiref.doc/r_examples_mangngrecrds.htm

As I understand your API, the undef is unlikely to work. setFieldValue can not be called on a list to begin with. I don't know much Perl either. But try creating a loop to read all values, and delete each value using DeleteFieldValue method of entity object.
All methods of entity objects are listed here: http://publib.boulder.ibm.com/infocenter/cqhelp/v7r0m1/index.jsp?topic=/com.ibm.rational.clearquest.apiref.doc/c_entity_mthds.htm
I don't know Perl syntax well. But someone here may be able to help.
hth.

Related

UniData List all avaiable subroutines / All parameters

I am trying to wrap some UniData Subroutines to SOAP Web Service. I'm planning to use C# and UODOTNET library (IBM U2 Data Management Interface for .NET). Also I'm looking to create an engine to read all the available Subroutines from data server and also reads all the required parameters and dynamically generate required codes for Web Service.
My code would be something like this:
var session = UniObjects.OpenSession(
"192.168.0.1",
"user",
"password",
"account"
);
var cmd = session.CreateUniCommand();
cmd.Command = "LIST SUBURB.INDEX"; // ?????
cmd.Execute();
var res = cmd.Response;
Question 1: Is there any command that I can use to retrieve the list of all available subroutines?
Question 2: Is there any command that I can use to retrieve list of all parameters for specific subroutine?
Cheers
The short answer is no.
The longer answer is yes, but with a lot of work.
Since you are asking this question, I'm going to assume you are missing a lot of generally knowledge about the platform. Hence to be able to do this you'll need to:
Learn about how VOC works, specifically how executable code can be catalogued here.
Learn about the CATALOG and how cataloguing programs globally, locally and direct differ.
Understand how your system in particular is designed. Some places have everything directly catalogued in the VOC, others are a mix. If the former, it'll be easier for your question.
Once you understand the above, you'll know how to get a list of all executable programs from VOC, local catalog and global catalog. For example, a simplified example for the VOC is the UniQuery command LIST VOC WITH F1="C".
The hard part is getting the parameter list, of which there isn't any system command. To do this you have 2 options.
Reverse engineer the byte code of every subroutine and tease out the number of parameters
If you have access to the related source code, parse it to generate the list.
Just wanted to add a comment on this one, in UniData there is a MAKE.MAP.FILE command that will identify Programs and Subroutines ( and the number of parameters) which puts the information in the '_MAP_' file. This does not tell you what the parameters are used for, but it helps.

Checking for existence of hash key creates key

Given the following code
#!/usr/bin/perl
use Data::Dumper;
my %hash;
my #colos = qw(ac4 ch1 ir2 ird kr3);
foreach my $colo (#colos) {
if(exists $hash{output}{$colo}) {
print "$colo is in the hash\n";
}
}
print Dumper(\%hash);
I have an empty hash that is created. I have an array with a few abbreviations in it. If I cycle through the array to see if these guys are in the hash, nothing is displayed to STDOUT which is expected but the $hash{output} is created for some reason. This does not make sense. All I am doing is an if exists. Where did I go wrong?
exists looks for a hash element in a given hash. Your code is autogenerating the hash
%{ $hash{output} } and checking if a hash element with key $colo is existing in that hash.
Try the following:
if(exists $hash{output}{$colo}) {
changed to
if(exists $hash{output} and exists $hash{output}{$colo}) {
You can, of course, write a sub that is hiding that complexity from your code.
Perl creates it because exists tests the last key specified, it doesn't test recursively. It should not get created if you instead do:
if( exists $hash{output} && exists $hash{output}{$colo} ) {
However why do you need the additional key at all? Why not just $hash{$colo}? Also if you If you use strict you'd get a warning about an uninitialized value in $hash.
You've already got a couple good answers, but, if you want to read more about this behavior, it's normally called "autovivification" and there is a CPAN module available to disable it if you would prefer that it doesn't happen.
The actual code/hash is more complexed. The hash is: $rotation_hash{output}{oor}{$colo}{$type}{$hostname}{file}{$filename} = <html_status_code>
As others have stated, when you ask about the existence of $foo{bar}{fubar}, Perl automatically creates $foo{bar} in order to test whether $foo{bar}{fubar} exists. If you want to prevent this, you have to test to see if $foo{bar} exists, and if it does, then test if $foo{bar}{fubar} exists.
However, what caught my eye was your seven layer hash. When your data structures start to get that complex, you should really be using Perl Object Oriented coding. I know a lot of people are scared off by Perl objected oriented programming, but Perl is probably one of the easiest languages for people in picking up OOP.
If for nothing else, you use OOP for the same reason you use use strict;. When I use strict;, Perl will easily pickup where I used $foobar as a variable in one place, but then refer to it as $fubar in another place. You lose that protection with complex data structures. For example, you might put $rotation_hash{output}{oor} in one place, but $rotation_hash{oor}{output} in another place, and use strict won't catch that. But, if you declare objects via package, and use subroutines as methods and constructors, you gain that back.
Object oriented design will also help you eliminate the need to track your data structure. The objects handle these for you, and you can concentrate on your coding. And, you don't have to create multiple files. You can simply attach the object definitions on the bottom of your file.
There are some excellent tutorials included in the Perl documentation. If you're not familiar with OOP Perl, you should go through the tutorials and give it a try.

Is there an implementation of the Penn Treebank Tokenizer in Perl?

I'm looking for a Perl module that is a port of this where I can basically create an object, call a tokenize() subroutine, pass in a pile of text and get back a list of tokens. Something to that effect. If it doesn't exist I'll do it, but no sense in reinventing the wheel, right? :) TIA.
I couldn't find an exact match, but could one of Lingua::EN::Tagger, Lingua::Treebank, Text::StemTagPOS, Lingua::Stem::Snowball or Treex::EN handle the problem?

Perl: Determining where a function is defined [duplicate]

This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
In Perl, how can I check from which module a given function was imported?
Hi guys!
I am using my weekend time to comb through our web app to get a better understanding of it. It uses numerous modules whose functions get pulled into it and my question is this.. how can I determine the module where a function originates?
Reason I ask is because I am using print STDERR lines sprinkled here and there to understand the way data moves around (it has demystified things greatly).. here's an example....
($file_data,$count) = lookup_files($customer,$site,'','0',$d);
What I'm not sure of is where lookup_files() is originating from. What I'd like to see is this....
($file_data,$count) = lookup_files($customer,$site,'','0',$d);
print STDERR "lookup_files originates here " . <CODE TO SHOW ME WHERE lookup_files IS DEFINED>;
Any advice on where to begin would be greatly appreciated. The webapp uses tons of use modules and instead of selectively importing only what's needed, each use seems to bring all functions in.
I know my terminology might be incorrect when referring to "method", "parent" and so on in regards to Perl. If anyone would like to correct me on it that would be appreciated too. I am at best a beginner with this stuff. Janie
Take a look at the core module Devel::Peek
http://perldoc.perl.org/Devel/Peek.html#A-reference-to-a-subroutine
The output of that module's functions will tell you where a subroutine comes from
One fairly easy way is to load Carp::Always. If it’s a web app, you’ll need to put it in the code. For a command line you can just perl -MCarp::Always ...

Perl: variable scope issue with CGI & DBI modules

I've run into what appears to be a variable scope issue I haven't encountered before. I'm using Perl's CGI module and a call to DBI's do() method. Here's the code structure, simplified a bit:
use DBI;
use CGI qw(:cgi-lib);
&ReadParse;
my $dbh = DBI->connect(...............);
my $test = $in{test};
$dbh->do(qq{INSERT INTO events VALUES (?,?,?)},undef,$in{test},"$in{test}",$test);
The #1 placeholder variable evaluates as if it is uninitialized. The other two placeholder variables work.
The question: Why is the %in hash not available within the context of do(), unless I wrap it in double quotes (#2 placeholder) or reassign the value to a new variable (#3 placeholder)?
I think it's something to do with how the CGI module's ReadParse() function assigns scope to the %in hash, but I don't know Perl scoping well enough to understand why %in is available at the top level but not from within my do() statement.
If someone does understand the scoping issue, is there a better way to handle it? Wrapping all the %in references in double quotes seems a little messy. Creating new variables for each query parameter isn't realistic.
Just to be clear, my question is about the variable scoping issue. I realize that ReadParse() isn't the recommended method to grab query params with CGI.
I'm using Perl 5.8.8, CGI 3.20, and DBI 1.52. Thank you in advance to anyone reading this.
#Pi & #Bob, thanks for the suggestions. Pre-declaring the scope for %in has no effect (and I always use strict). The result is the same as before: in the db, col1 is null while cols 2 & 3 are set to the expected value.
For reference, here's the ReadParse function (see below). It's a standard function that's part of CGI.pm. The way I understand it, I'm not meant to initialize the %in hash (other than satisfying strict) for purposes of setting scope, since the function appears to me to handle that:
sub ReadParse {
local(*in);
if (#_) {
*in = $_[0];
} else {
my $pkg = caller();
*in=*{"${pkg}::in"};
}
tie(%in,CGI);
return scalar(keys %in);
}
I guess my question is what is the best way to get the %in hash within the context of do()? Thanks again! I hope this is the right way to provide additional info to my original question.
#Dan: I hear ya regarding the &ReadParse syntax. I'd normally use CGI::ReadParse() but in this case I thought it was best to stick to how the CGI.pm documentation has it exactly.
It doesn't actually look like you're using it as described in the docs:
https://metacpan.org/pod/CGI#COMPATIBILITY-WITH-CGI-LIB.PL
If you must use it, then CGI::ReadParse(); seems more sensible and less crufty syntax. Although I can't see it making much difference in this situation, but then it is a tied variable, so who the hell knows what it's doing ;)
Is there a particular reason you can't use the more-common $cgi->param('foo') syntax? It's a little bit cleaner, and filths up your namespace in a considerably more predictable manner..
use strict;. Always.
Try declaring
our %in;
and seeing if that helps. Failing that, strict may produce a more useful error.
I don't know what's wrong, but I can tell you some things that aren't:
It's not a scoping issue. If it were then none of the instances of $in{test} would work.
It's not the archaic & calling syntax. (It's not "right" but it's harmless in this case.)
ReadParse is a nasty bit of code. It munges the symbol table to create the global variable %in in the calling package. What's worse is that it's a tied variable, so accessing it could (theoretically) do anything. Looking at the source code for CGI.pm, the FETCH method just invokes the params() method to get the data. I have no idea why the fetch in the $dbh->do() isn't working.
Firstly, that is not in the context/scope of do. It is still in the context of main or global. You dont leave context until you enter {} in some way relating to subroutines or different 'classes' in perl. Within () parens you are not leaving scope.
The sample you gave us is of an uninitialized hash and as Pi has suggested, using strict will certainly keep those from occuring.
Can you give us a more representative example of your code? Where are you setting %IN and how?
Something's very broken there. Perl's scoping is relatively simple, and you're unlikely to stumble upon anything odd like that unless you're doing something daft. As has been suggested, switch on the strict pragma (and warnings, too. In fact you should be using both anyway).
It's pretty hard to tell what's going on without being able to see how %in is defined (is it something to do with that nasty-looking ReadParse call? why are you calling it with the leading &, btw? that syntax has been considered dead and gone for a long time). I suggest posting a bit more code, so we can see what's going on..
What version of DBI are you using? From looking at the DBI changelog it appears that versions prior to 1.00 didn't support the attribute argument. I suspect that the "uninitialized" $in{test} is actually the undef that you're passing to $dbh->do().
From the example you gave, this is not a scoping issue, or none of the parameters would work.
Looks like DBI (or a DBD, not sure where bind parameters are used) isn't honoring tie magic.
The workaround would be to stringize or copy what you pass to it, like your second and third parameters do.
A simple test using SQLite and DBI 1.53 shows it working ok:
$ perl -MDBI -we'sub TIEHASH { bless {} } sub FETCH { "42" } tie %x, "main" or die; my $dbh = DBI->connect("dbi:SQLite:dbname=dbfile","",""); $dbh->do("create table foo (bar char(80))"); $dbh->do("insert into foo values (?)", undef, $x{foo}); print "got: " . $dbh->selectrow_array("select bar from foo") . "\n"; $dbh->do("drop table foo")'
got: 42
Care to share what database you are using?
Per the DBI documentation: Binding a tied variable doesn't work, currently.
DBI is pretty complicated under the hood, and unfortunately goes through some gyrations to be efficient that are causing your problem. I agree with everyone else who says to get rid of the ugly old cgi-lib style code. It's unpleasant enough to do CGI without a nice framework (go Catalyst), let alone something that's been obsolete for a decade.
Okay, try this:
use CGI;
my %in;
CGI::ReadParse(\%in);
That might help as it's actually using a variable that you've declared, and therefore can control the scope of (plus it'll let you use strict without other nastiness that could be muddying the waters)
As this is starting to look like a tie() problem, try the following experiment. Save this as a foo.pl and run it as perl foo.pl "x=1"
use CGI;
CGI::ReadParse();
p($in{x}, "$in{x}");
sub p { my #a = #_; print "#a\n" }
It should print 1 1. If it doesn't, we've found the culprit.
I just tried your test codce from http://www.carcomplaints.com/test/test.pl.txt, and it works right away on my computer, no problems. I get three values as expected. I didn't run it as CGI, but using:
...
use CGI qw/-debug/;
...
I write a variable on the console (test=test) and your scripts inserts without a problem.
If however your leave this out, tt will insert an empty string and two NULLs. This is a because you interpolate a value into a string. This will makes a string with value of $in{test} which is undef at the moment. undef stringifies to an empty string, which is what is inserted into database.
Try this
%in = ReadParse();
but i doubt that. Are you trying to get query parameters or something?