Create a Postgres boolean function that handles nulls - postgresql-11

I'm trying to create a function that will cast boolean values to 't' or 'f', or '' if NULL.
CREATE OR REPLACE FUNCTION bool(b BOOLEAN) RETURNS VARCHAR
AS $$
BEGIN
IF b IS NULL THEN
RETURN '';
END IF;
IF b THEN
RETURN 't';
ELSE
RETURN 'f';
END IF;
END;
$$ LANGUAGE PLPGSQL CALLED ON NULL INPUT;
However, the following always returns NULL. What gives?
SELECT bool(NULL)

bool is also a built-in function and type cast (because there is a data type with that name).
You need to either explicitly reference your function by prefixing it with the schema:
select public.bool(null);
or give your function a different name.
Unrelated, but: your function can be simplified to:
CREATE OR REPLACE FUNCTION bool(b BOOLEAN)
RETURNS VARCHAR
AS $$
select coalesce(case when b then 't' else 'f' end, '');
$$
language sql
called on null input;

Related

Binding a variable to one of two values with IF?

In the following SPARQL query, I'm not sure how to use if to bind one of two strings to the variable ?result. I heard that there are concepts of “in scope” and “out of scope,” but I don't really see the difference. I've also tried putting the if clause in the select line, but it didn't work either. How can I fix this query to bind ?result to one of the two strings based on the condition?
SELECT ?result
WHERE{
?chain rdf:type rdfs:Property .
?chain rdfs:domain <http://www.vs.cs.hs-rm.de/ontostor/SVC#MDiskGroup> .
?chain rdfs:range <http://www.vs.cs.hs-rm.de/ontostor/SVC#IOgroup> .
?this ?chain ?arg .
?arg io:id ?var .
IF(?var = "0"^^xsd:integer,
BIND(" *"^^xsd:string AS ?result),
BIND(""^^xsd:string AS ?result)) .
}
The if operator in SPARQL isn't a statement as it sometimes is in a programming language, but rather is an "function form" for creating an expression (with special evaluation semantics). The value of if(test,a,b) is a if test is true, and b if test is false. As the documentation says:
17.4.1.2 IF
rdfTerm IF (expression1, expression2, expression3)
The IF function form evaluates the first argument, interprets it as a
effective boolean value, then returns the value of expression2 if the
EBV is true, otherwise it returns the value of expression3. Only one
of expression2 and expression3 is evaluated. If evaluating the first
argument raises an error, then an error is raised for the evaluation
of the IF expression.
Examples: Suppose ?x = 2, ?z = 0 and ?y is not bound in some query
solution:
IF(?x = 2, "yes", "no") returns "yes"
IF(bound(?y), "yes", "no") returns "no"
IF(?x=2, "yes", 1/?z) returns "yes", the expression 1/?z is not evaluated
IF(?x=1, "yes", 1/?z) raises an error
IF("2" > 1, "yes", "no") raises an error
So, if isn't a statement like it might be in a programming language, but it's simply a function (though lazily evaluated) that takes three arguments and returns a value. SPARQL is a query language, and doesn't have statements that get executed; it's a query language for matching patterns in a graph and binding variables to values. So if is a function, and it just so happens that if the first argument is true, then it returns the second argument, otherwise it returns the third. In general, you'd bind the value of a function to a variable with
bind( function(args...) as ?variable )
and this case is no different. You'd call the if function and bind its result to a variable with
bind( if(condition,then,else) as ?result )
In your case, this means that you would use the following query. I've added some newlines to help the readability, but they're not necessary. Integers in a SPARQL query are shorthand for a literal with type xsd:integer, so I've also used (thanks to RobV's comment) 0 instead of "0"^^xsd:integer. (See 2.3.2 Matching Literals with Numeric Types.)
bind(if(?var = 0,
" *"^^xsd:string,
""^^xsd:string )
as ?result)
If we actually want to shorten this even more, then we can use xsd:string as a constructor, and do (see 17.5 XPath Constructor Functions):
bind(xsd:string(if(?var = 0," *", "")) as ?result)
This might seem a little bit odd at first if you're used to doing things like
String result;
if ( var == 0 ) {
result = "case 1";
}
else {
result = "case 2";
}
but many language actually provide a ternary operator that lets you do the much shorter
String result = (var == 0) ? "case 1" : "case 2";
instead. This is the functionality you're getting with SPARQL.

no match for 'operator!=' in checking while loop

struct dic
{
string key;
int code;
};
dic H[71];
Now using key in the condition of the while-statement gives me an error.
while ((H[h].key)!= NULL)
{
}
The error I am getting is:
error: no match for 'operator!=' in 'H[h].dic::key != 0'
the type of dic::key is string, and you are trying to compare it to an integer (NULL == 0), which is not implemented. You need to check if the string is empty:
while (!H[h].key.empty()) {
...
}
The key of the element is a string. You can not compare a string to NULL as it is an object not a pointer. The macro NULL will most probably either defined as a pointer or an int value and neither of those is comparable to string.
The macro NULL is often defined to either 0 or (void *) 0, none of those values can be used when comparing to a std::string (unless, of course, you implement your own custom comparison operator, which you shouldn't).
If you want to check if a string is empty, use std::string::empty.
Maybe you wanted to say:
if (H[h].key.empty()) { ... }

Perl regex search and replace with $variable->function("args")

Basically I'm trying to replace with whatever is returned from a function call from an object. But I need a return value from the regex search as the argument. It's a little tricky but the code should speak for itself:
while ( $token =~ s/\$P\(([a-z0-9A-Z_]+)\)/$db->getValue("params", qw($1))/e ) { }
The error I'm getting is that $1 is not getting evaluated to anything (the argument literally becomes "$1") so it screws up my getValue() method.
Cheers
The qw() functions quotes "words". I.e. it splits a string at all whitespace characters and returns that list. It does not interpolate.
You can just use the variable "as is":
s/\$P\(([a-z0-9A-Z_]+)\)/$db->getValue("params", $1)/e
The qw() function is very different from
q(abc) (<=> 'abc'),
qq(abc) (<=> "abc"), and
qx(abc) (<=> `abc`) or
qr(abc) (<=> m/abc/):
qw(a b c) <=> ('a', 'b', 'c')

SAS: Expressions in IF statement

does Sas provide mechanism of chain-expressions?
does Sas provide mechanism of In-clause?
Simple examples:
a = '09MAY2010'd;
b = '17MAY2010'd;
if (a<=c<=b) then do; /*code*/ end;
if (c in (a:b)) then do; /*code*/ end;
maybe any good techniques of if/where statements?
your suggestions and advises, please.
Thanks!
Your example, changed a bit:
data _null_;
a = '09MAY2010'd;
b = '17MAY2010'd;
c = '17MAY2010'd;
if (a<=c<=b) then do;
putlog "a<=c<=b";
end;
select (c);
when (a, b) putlog "in a, b";
when ('17MAY2010'd) putlog "'17MAY2010'd";/* not used, only first match is executed */
otherwise;
end;
run;
IN operator used with IF or in WHERE clause requires constants in the list.
Apart from the IN operator, which only accepts constant values inside the paranthesis, there is also an (undocumented) IN function, which can be used with variables, so instead of if c in(a,b) you can use if in(c,a,b) which will work also when a and b are variables.
Another possibility is to use WHICHN or WHICHC functions, which has the same syntax, and which return 0 (FALSE) when a match is not found, and otherwise the number of the (first) match.

Testing conditions using Character pointers

int main()
{
char *p,c;
for(p="Hello World";c=*p;++p)
{
printf("%c",c);
}
}
In the above code,i know that ++p will make pointer 'p' point to next character in the "Hello World".And i also know that there is no boundary checking performed on arrays in C or C++.The output of the program is 'Hello World'. How am i able to test conditions using
c=*p;
What does 'c=*p' return.As far as my understanding goes, when '++p' reaches the end of the 'hello world', pointer 'p' should point to some garbage value and the loop should print some garbage values.
c=*p; doesn't return anything, it's an expression. The for loop evaluates the value of c after the assignment.
when '++p' reaches the end of the 'hello world', pointer 'p' should point to some garbage value
Not really. Before reaching the end, it reaches the null terminating character - '\0'. Which is 0. Which is assigned to c and evaluates the break condition to false. So the loop finishes before it goes out of bounds.
C strings are by definition terminated by a NULL character '\0', if it is a string then it has to end it in a NULL. therefore c = *p will point to a NULL character when the string ends, which is in your case the immediately next character of 'd'. And the NULL character in the ASCII table has an integer value 0, which evaluates to false and gets out of the for loop.
Note that if a C string does not end in a NULL character (then at first it is not a C string), then basically there is no way of detecting that it is a string, as it will be stores as a sequence of bytes. In that case it will be simply a byte array or a string, will depend on how we interpret.
Also not that c = *p does not return anything, it is an expression and it is evaluated. e = *p transfers the value pointed by the current value of p into the var c, the value of which is the final evaluation of the expression.
Strings are terminated by a null character (aka with \0), so then at the end p should point to the null character that terminates the string, thus c would be \0 which is considered a false condition.