powershell testing a variable that hasnt being assign yet - variables

I want to test to see if a variable has been assigned a variable and if not perform action. How can this be achieve?
I've attempted it with the following code but receive the error: The right operand of '-is' must be a type.
$ProgramName is not assigned at this point.
If ($ProgramName -isnot $null) {
$ProgramName = $ProgramName + ', ' + $cncPrograms
}
Else {
If ($cncPrograms -isnot $null) {
$ProgramName = $cncPrograms
}
}

Any unassigned variable will have a value of null, not a data type of null. So, just do this:
If ($ProgramName -ne $null)
...that will return TRUE if it's been assigned to a non-null value.
An even easier check to make is
IF($ProgramName)
Which will check if that is $null or not, though the logic is reversed, so you could use
IF(!$ProgramName)
Edit:
Ruffin raises a good point about strictmode in comments. This method will work as well:
Test-Path variable:ProgramName or Test-Path variable:global:ProgramName if it's explicitly global scoped, for instance. This will return $true or $false depending on if the variable exists.

Test-Path variable:\var should do what you want, I guess.

Contrary to answers above
Test-Path variable:ProgramName
Might not be what you are looking for because it only tests for the existence of the variable. If the Variable is set to $null it will still return $true.
Therefore in strictmode you may have to test for it's existence existence and whether it is non-empty.
Set-StrictMode -version Latest
#TODO Add a scope parameter
Function IsEmpty([string]$varname){
if (Test-path "variable:$varname"){
$val=(gi "variable:$varname").value
if ($val -is [bool]) {$false}
else {$val -eq '' -or $val -eq $null} }
else{ $true }
}
#TEST:
if (test-path variable:foobar){remove-variable foobar} ; IsEmpty foobar
$foobar=$null; IsEmpty foobar
$foobar=''; IsEmpty foobar;
$foobar=$false; IsEmpty foobar
#Results:
True
True
True
False
Strict mode kind of takes some of the fun out of scripting...

To build on the (correct) answers from JNK and David, check out this great blog post from Jeffrey Snover that walks you through all the use cases of Boolean expressions in PoweShell. It concludes with how to test for the existence of a variable.
https://devblogs.microsoft.com/powershell/boolean-values-and-operators/

Aside from the fact that -isnot is for types, in powershell 7 there's a new operator for this purpose. The assignment will only happen if the left side is $null.
$programname ??= 'foo'

Related

Perl user input into SQL Like statement

Im trying to get user input and send it through to the SQL Like statement. But Im getting error: Can't call method "bind_param" on an undefined.
My Original code :
#!/usr/bin/perl
use DBI;
#use DBD::Oracle;
use strict;
use warnings;
use CGI;
print "Enter INCD number : ";
my $input = <>;
chomp $input;
my $DSN = 'driver={SQL Server};Server=ddsfs1; database=sdfds;TrustedConnection=Yes';
my $dbh = DBI->connect("dbi:ODBC:$DSN")
#print "connected.."
or die "$DBI::errstr\n";
my $query = $dbh->prepare("SELECT TOP 20 Id
,Created
,Updated
,Message
FROM FrameworkDEV3.Log.Entry
where Message like ?
and Created >= DATEADD(day, -10, GETDATE())
order by Created desc");
$sth->bind_param(1, '%$input%');
print $sth;
$sth->execute;
#DBI::dump_results($sth);
while( my #data = $query->fetchrow_array())
{
foreach(#data) {
print "[$_]";
}
print "\n\n";
}
$sth->finish;
$dbh->disconnect;
#print "Connected..";
print "\n";
Following code is fixed as per comments from Dave and Jim :
my $sth = $dbh->prepare("SELECT TOP 20 Id
,Created
,Updated
,Message
FROM FrDEVsd.Log.Entry
where Message like ?
and Created >= DATEADD(day, -10, GETDATE())
order by Created desc");
$sth->bind_param(1, "%$input%");
print $sth;
$sth->execute;
#DBI::dump_results($sth);
while( my #data = $sth->fetchrow_array())
{
foreach(#data) {
print "[$_]";
}
print "\n\n";
}
$sth->finish;
$dbh->disconnect;
print "\n";
The error im getting now is
DBI::st=HASH(0x2a9a480)
In your code:
my $query = $dbh->prepare("SELECT TOP 20 Id
,Created
,Updated
,Message
FROM sdada.ada.asd
where Message like ?
and Created >= DATEADD(day, -10, GETDATE())
order by Created desc");
my $sth->bind_param(1, "%$input%");
Notice the prepared statement is stored in a variable named $query, but you attempt to bind using $sth which was never set and is undefined. That is what the error message was telling you.
Use the same variable name both places (and later when you execute the statement) to fix the problem.
You've already been given a fish. Perhaps we can show you how to catch your own in the future.
This is your error:
Can't call method "bind_param" on an undefined
You call bind_param() on this line:
my $sth->bind_param(1, "%$input%");
So you're defining a variable (called $sth) and immediately expecting that variable to be an object that you can call a method on. When you define a variable with my the variable is initialised to undef unless you assign something to it like this:
my $var = 'something';
Your code is the equivalent of this.
my $sth = undef;
$sth->my $sth->bind_param(1, "%$input%");
Do you see the problem now?
In DBI code you'll often see the the variable $sth used to store the statement handle that we use to execute a statement. I suspect you've copied this from some example DBI code and taken the variable name from there. If $sth was a statement handle then you could certainly call the bind_param() method on it.
So $sth needs to be a statement handle. And we create one of those by calling the prepare() method on a database handle.
my $sth = $dbh->prepare($some_sql);
Oh, but wait.... you already have a line that looks a lot like that:
my $query = $dbh->prepare("SELECT ...");
So it looks to me like you started writing your own code, using $query as the variable to hold the statement handle. You then copied the bind_param() line from some sample code. That didn't compile, because it used $sth, which you hadn't declared, so you just stuck a my in front of it to get around that problem? Does that sound at all accurate?
What you really wanted was to call bind_param() on the statement handle that you had already created.
$query->bind_param(1, "%$input%");
But, to be honest, I think it's a good idea to stick with the "standard" names for DBi-related variables. It's what your maintenance programmer (which might well be you in six months time!) will expect to see.
So I'd change the prepare() line to:
my $sth = $dbh->prepare("SELECT ...");
And leave the bind_param() call as it is. You'll need to change the fetchrow_array() to be called on $sth as well.

bindValue and bindParam in mysqli and PDO ignore variable type

I'm having problems in understanding a part of the meaning of binding certain variable types in PDO and mysqli if the type given, in my case, seems to be meaningless. In the following code, the type bound (like i or s) gets ignored. The table row "wert_sortierung" in the database is INT(11). Regardingless if $val_int is really integer or not and if I bind it via i,s / PDO::PARAM_INT or _STR, the query always works, no break, no error or warning, that the types in the binding and database or variable itself don't fit.
<?
class PDOTest {
protected $pdo;
function __construct(){
$usr="usr";
$pwd="pwd";
$host="localhost";
$db="db";
$val_int="I'm a string";
$val_str="OP";
$querystring="SELECT wert_langtext FROM TB_wert WHERE wert_sortierung = ? AND wert_CD = ?";
try {
$db_info = "mysql:host=$host;dbname=$db"; // usually provided via require_once and during construction
$this->pdo = new PDO($db_info, $usr, $pwd);
$this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$this->pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$stmt = $this->pdo->prepare($querystring);
$stmt->bindValue(1,$val_int,PDO::PARAM_INT);
$stmt->bindValue(2,$val_str,PDO::PARAM_STR);
$stmt->execute();
$row_return = $stmt->fetchAll(PDO::FETCH_ASSOC);
$this->varprint($row_return);
$this->pdo = NULL;
}
catch (PDOException $ex) {
printf ('Es spricht:');
$this->printerror("Fehla! (" . $ex->getMessage() . ")");
$this->pdo = NULL;
exit();
}
printf("<br />-------<br />");
//Added for comparison
$mysqli = new mysqli($host, $usr, $pwd, $db);
$m_stmt = $mysqli->prepare($querystring);
$m_stmt->bind_param('is',$val_int, $val_str);
$m_stmt->execute();
$m_stmt->bind_result($row_return);
$m_stmt->fetch();
$this->varprint($row_return);
$m_stmt->close();
$mysqli->close();
}
private function printerror($txt) {
printf("<p><font color=\"#ff0000\">%s</font></p>\n",
htmlentities($txt));
}
private function varprint($var) {
echo "<br />";
echo "<pre>";
echo var_dump($var);
echo "</pre>";
}
}
new PDOTest();
?>
Please can anyone point out my error in reasoning.
It is actually Mysql's loose-typing that that deceived you.
As a matter of fact, regular Mysql queries can accept strings for the numberic values all right:
SELECT wert_langtext FROM TB_wert WHERE wert_sortierung = '1' AND wert_CD = '1';
while prepared statement just following this behavior.
However, a contrary situation is not that harmless. Addressing a string value with a number
SELECT wert_langtext FROM TB_wert WHERE wert_sortierung = 1;
will cause infinite number of warnings in case of wert_sortierung being of string type and some unexpected behavior, like matching for ALL the rows.
So, as a general advise I would suggest to always use 's' by default. The only drawback is PDO's emulated prepares and it can be easily worked around.
So, to answer your question explicitly - prepared statements just allow the same behavior as regular queries, adding nothing to it. Everything that possible with a regular query, is possible with prepared statement as well. And no, binding do not validate your data (however it should. Imn my class I test integer placeholders and throw an exception if no numeric value given)

PHP - variable scope inside if statement and while loop

I know that if statement gives a result as a Boolean.
<?php
if (isset($_GET['subj'])) {
$sel_subj = $_GET['subj'];
$sel_page = "";
?>
Can i use $sel_subj or $sel_page outside if statement ? The second question in the case of while loop ? Can i use a variable outside it or its considered as in the local scope ?
while ($page = mysql_fetch_array($page_set)) {
echo "<li";
if ($page["id"] == $sel_page) { echo " class=\"selected\""; }
echo "><a href=\"content.php?page=" . urlencode($page["id"]) .
"\">{$page["menu_name"]}</a></li>";
}
Basically yes, any variables defined inside an if or while will be available in the scope that the if or while exists in (as they are defined in a conditional though they might not have been set so you would receive an undefined warning)
so
function foo(){
$i=0
while($i==0){
$i=1;
$a=1;
}
echo $a;
//$a is available here although it might be undefined as the condition may not have been met
}
echo $a //$a is not available here
You should ideally declare the variable first.

Writing a PHP if Blank statement

I'm new to PHP so this will sound basic to most people but I need to write the code for when a variable returns nothing (blank).
My variable is $winner, but sometimes there is no winner, in this case it just leaves the page blank, I would like it so if there is no winner then it will display "no winner".
This is my attempt:
if empty($winner) {
echo "no winner";
}
You can make a function to check the variable's valaue with null or empty...
function IsEmptyString($Season){
return (!isset($Season) || trim($Season)==='');
}
This function can be used to check the same.
Just use:
if (!$winner) { // will catch "", null
echo "no winner"
}

Powershell and SQL parameters. If empty string, pass DBNull

I got this parameter:
$objDbCmd.Parameters.Add("#telephone", [System.Data.SqlDbType]::VarChar, 18) | Out-Null;
$objDbCmd.Parameters["#telephone"].Value = $objUser.Telephone;
Where the string $objUser.Telephone can be empty. If it's empty, how can I convert it to [DBNull]::Value?
I tried:
if ([string]:IsNullOrEmpty($objUser.Telephone)) { $objUser.Telephone = [DBNull]::Value };
But that gives me the error:
Exception calling "ExecuteNonQuery" with "0" argument(s): "Failed to convert parameter value from a ResultPropertyValueCollection to a String."
And if I convert it to a string, it inserts an empty string "", and not DBNull.
How can this be accomplished?
Thanks.
In PowerShell, you can treat null/empty strings as a boolean.
$x = $null
if ($x) { 'this wont print' }
$x = ""
if ($x) { 'this wont print' }
$x = "blah"
if ($x) { 'this will' }
So.... having said that you can do:
$Parameter.Value = $(if ($x) { $x } else { [DBNull]::Value })
But I'd much rather wrap this up in a function like:
function CatchNull([String]$x) {
if ($x) { $x } else { [DBNull]::Value }
}
I don't know about powershell, but in C# I would do something like this:
if ([string]::IsNullOrEmpty($objUser.Telephone))
{
$objDbCmd.Parameters["#telephone"].Value = [DBNull]::Value;
}
else
{
$objDbCmd.Parameters["#telephone"].Value = $objUser.Telephone;
}
Always append +"" at the end of db values...
$command.Parameters["#EmployeeType"].Value= $ADResult.EmployeeType + ""
Many years later, let me clarify:
Josh's answer shows a helpful simplification for testing strings for emptiness (relying on PowerShell's implicit to-Boolean conversion[1]), but it is unrelated to Tommy's (the OP's) problem.
Instead, the error message
"Failed to convert parameter value from a ResultPropertyValueCollection to a String."
implies that it is the non-null case that caused the problem, because $objDbCmd.Parameters["#telephone"].Value expects either a string value or [DBNull]::Value, whereas $objUser.Telephone is of type [ResultPropertyValueCollection], i.e. a collection of values.
Thus, in the non-null case, a string value must be assigned, which must be derived from the collection; one option is to take the first collection element's value, another would be to join all values with a separator to form a single string, using, e.g., [string]::Join(';', $objUser.Telephone) or, if joining the elements with spaces is acceptable (not a good idea with multiple phone numbers), simply with "$($objUser.Telephone)".[2]
Detecting an empty collection via [string]:IsNullOrEmpty() actually worked, despite the type mismatch, due to how PowerShell implicitly stringifies collections when passing a value to a [string] typed method parameter.[2]
Similarly, using implicit to-Boolean conversion works as expected with collections too: an empty collection evaluates to $false, a non-empty one to $true (as long as there are either at least two elements or the only element by itself would be considered $true[1])
Therefore, one solution is to use the first telephone number entry:
$objDbCmd.Parameters["#telephone"].Value = if ($objUser.Telephone) {
$objUser.Telephone[0].ToString() # use first entry
} else {
[DBNull]::Value
}
Note: If $objUser.Telephone[0] directly returns a [string], you can omit the .ToString() call.
In PowerShell v7+ you can alternatively shorten the statement via a ternary conditional:
$objDbCmd.Parameters["#telephone"].Value =
$objUser.Telephone ? $objUser.Telephone[0].ToString() : [DBNull]::Value
[1] For a comprehensive summary of PowerShell's automatic to-Boolean conversions, see the bottom section of this answer.
[2] When implicitly converting a collection to a string, PowerShell joins the stringified elements of a collection with a single space as the separator by default; you can override the separator with the automatic $OFS variable, but that is rarely done in practice; e.g., array 'foo', 'bar' is converted to 'foo bar'; note that this conversion does not apply when you call the collection's .ToString() method explicitly, but it does apply inside expandable (interpolating) strings, e.g., "$array".