If inside If in Informix stored proc - informix

In Informix stored Procedure I have some condition which goes like this :-
If val1 > 0 // 1st If
Select count(*) of value from a table and stored it in a Variable say VALUE
If VALUE > 0 // 2nd If
perform UPDATE
ELSE // Intended ELSE for 2nd IF
Perform Insert
END IF
ELSE // Intended ELSE for 1st IF
perform Operation X
END IF
Some how I see my execution is always going in ELSE Intended for 1st IF and this is creating a problem for me . Can SomeOne let me know How can I correct this or where am i
Going Wrong.
Regards

The explicit keyword END IF means that the nesting of IF statements in SPL is unambiguous. Translating and indenting your code yields:
IF val1 > 0 THEN
SELECT COUNT(*) INTO value FROM SomeTable;
If VALUE > 0 THEN
Perform UPDATE
ELSE
Perform INSERT
END IF
ELSE
Perform Operation X
END IF
There is no way for there to be any ambiguity; there is no 'dangling else' problem because of the explicit END IF notation.
If the wrong code is being executed, then maybe you're being caught by 3-value logic and the behaviour of comparisons when one of the comparands is NULL. For example, if val1 is NULL, then the perform Operation X will always be executed because val1 > 0 is NULL > 0 which evaluates to NULL which is not TRUE so the ELSE clause is taken and Operation X is performed.
As noted by ceinmart, you can use SET DEBUG FILE and TRACE ON to debug what is happening as you execute the stored procedure.

Include the commands bellow before the if.
set debug file to '/tmp/trace.out';
trace on ;
....
trace "Value of val1 ="||val1;
trace "Value of VALUE = "||VALUE;
Run the procedure and check the output of the /tmp/trace.out file on SERVER where the database is.
To commands reference, use the online manual : TRACE , SET DEBUG FILE

Related

Infinite loop bug in Lua

I'm new to this platform and I'm still learning to
program in Lua, so, if any newbie errors appear, forgive me.
The following code is from one of the functions in my project that reads the insert
of the user and validates whether or not it is a data of type "Number". If,
the loop will be broken and the function will return the user input, otherwise, the
program will ask the user to enter the data again:
function bin.readnum(text)
local insertion
if text == nil then text = "Text: " end
while (insertion == nil) do
insertion = nil
print(text)
insertion = io.read("number")
if insertion ~= nil then break end
end
return insertion
end
But, if the user enters a wrong data (string) the function prints the text
madly instead of asking the user to re-enter the data.
When io.read fails to parse the data it got into a number, it doesn't discard it, but instead leaves it in the buffer for the next call to it. That means that in your code, instead of letting the user enter something else, it'll just keep trying to parse the same non-number forever. To fix it, in your if insertion ~= nil then block, do io.read() right before break, to read and discard the whole invalid line.
In addition to what Joseph Sible said:
io.read("number") is wrong: 5.1 docs demand "*n" and 5.4 docs demand just "n" for reading numbers. It probably works nevertheless due to Lua just searching for the chars in the string.
I recommend just replacing insertion = io.read("number") withinsertion = tonumber(assert(io.read(), "EOF")) - this will read a line and try to parse it as a number; the assert gracefully deals with nil being returned by io.read for EOF.
You don't need to set insertion to nil, the later assignment will do that already if what was read is not a valid number.
Style: Consider replacing your explicit nil checks with truthiness checks and removing the parentheses around the while-condition. You don't need a break, you can immediately return the read number; finally, you can even replace the entire loop with tail recursion.
All in all I'd rewrite it as follows:
function bin.readnum(text)
print(text or "Text: ")
local num = tonumber(assert(io.read(), "EOF"))
if num then return num end
return bin.readnum(text)
end
or alternatively using a repeat-until loop:
function bin.readnum(text)
local num
repeat
print(text or "Text: ")
num = tonumber(assert(io.read(), "EOF"))
until num
return num
end

In Delphi Rio (10.3.3) fdQuery does not correctly translate conditional function 'iif' when a macro is NULL

I have the following SQL command to run a query with a TFDQuery using PostgreSQL as the database:
fdqr.SQL.Text: =
'select * from (values (current_date-1), (current_date), (current_date + 1)) as t (datetest) ' +
'{iif (! Datevalue, where datetest =! Datevalue)}';
When I used the Clear method to clear the macro value, I expected the script to be interpreted so that the filter would be eliminated, but it wasn't.
fdqr.MacroByName('datevalue').Clear;
fdqr.Open;
Resulting database log:
select * from (values(current_date-1), (current_date), (current_date+1)) as t(datetest)
where datetest = NULL
However, if you include an assignment via AsRaw, it works as expected, even if the previous value was '' (empty string) and IsNull is True.
fdqr.MacroByName('datevalue').Clear;
{ at this point IsNull = True and AsRaw is '' }
fdqr.MacroByName('datevalue').AsRaw := '';
fdqr.Open;
Resulting database log:
select * from (values(current_date-1), (current_date), (current_date+1)) as t(datetest)
Is this a FireDAC bug or a feature that I don't understand correctly?
In order to apply substitution of {IIF(…)} or {IF}…{FI} based on a macro variable, the variable value must not be empty. That is what documentation for Conditional Substitution says. It literally means that the substitution is applied if the macro variable expands to a non-empty string. This fact can be verified by inspecting FireDAC source code, specifically method TFDPhysConnectionMetadata.TranslateEscapeSequence in unit FireDAC.Phys.Meta. In case for eskIF you can find:
s := Trim(ASeq.FArgs[0]);
…
else if s <> '' then
Result := 'True';
Let's see what happens when you Clear the macro variable. Its Value is set to Null and its DataType is set to mdUnknown. In this case the variable is expanded to NULL literal by the preprocessor, which is not an empty string. The value of AsRaw is irrelevant, because preprocessor uses SQL property for substitution.
There seems to be no other way to expand macro variable to an empty string than setting AsRaw := ''. In this case its DataType is set to mdRaw and the value SQL property is equal to AsRaw.
I'm not sure whether this behaviour is a bug or feature, but changing it could break exiting code bases, so I don't expect this to be ever fixed. I'd rather say that it eventually became a feature.
Apart from the above, you can avoid macros by using simple parameters:
select * from (values(current_date-1), (current_date), (current_date+1)) as t(datetest)
where :Datevalue is null or datetest = :Datevalue
This way you can clear or set the value of Datevalue parameter as you would expect:
{ to bind null value }
fdqr.ParamByName('Datevalue').Clear;
{ to bind some value }
fdqr.ParamByName('Datevalue').AsDate := Today;

Lua - For loops: saving the value of the control variable

I'm having a hard time understanding the example from the doc(https://www.lua.org/pil/4.3.4.html) and need some clarification.
If you need the value of the control variable after the loop (usually when you break the loop), you must save this value into another variable:
-- find a value in a list
local found = nil
for i=1,a.n do
if a[i] == value then
found = i -- save value of `i'
break
end
end
print(found)
I don't understand the a.n and if a[i] == value then parts. Are they creating a table a={n=5,...} and calling a single value like a.n=5?
I think I need a written explanation of what's occurring in the example, and what is missing, or a complete example. I'm guessing its missing the declaration of table/variables...?
Cause a[i] is calling entries of a={} and I don't understand what 'value' is...? A variable I have to declare first and then set to a specific value...? What value though?
Why am I calling other entries in a table (i.e. a[i]) when I'm defining a.n as the entry I want to be dealing with?
And in this case do I have to define the entry I want the control variable to break on by predefining the number and that's what value is set to...?
That would defeat the point of calling the value of the control variable if I already define what its going to be. I'm very confused. Like I understand if the example was:
local found = nil
local a=7
for i=1,a do
print(i)
found=a
break
end
However print(found) is equal to 7 rather than the last iteration of the incomplete for loop (2 or 1?).
What I was looking for was a way to save whatever number the control variable was on when the loop was interrupted.
So if it was for i=1,5 do... and the last printed iteration was 4, how would I call this value? I'm unsure if the doc is providing that in its example or not.
The complete working example may be the following:
local function find_value_in_list(value, a)
-- find a value in a list and print its index
local found = nil
for i=1, a.n do
if a[i] == value then
found = i -- save value of `i'
break
end
end
print(found)
end
find_value_in_list(33, {n=4, 11, 22, 33, 44}) --> 3
find_value_in_list(42, {n=4, 11, 22, 33, 44}) --> nil

Dafny verification - refer to original var in post condition

I am trying to verify my code in Dafny and I encountered a problem:
I have a method that is iterating over a sequence and changes it. The method changes the sequence according to the elements in the sequence. I would like to add a post condition like this: "if the elements in the sequence are X then something should happen". The problem is that the method changes the set (adds element etc.) and I want to check the condition of the original sequence. Is there an elegant way of doing that in Dafny? (The only way I could think of right now is keeping global var of the original condition of the sequence, but I am looking for the right way of doing that).
Code example:
method changeSeq(p: class1, s: seq<class1>)
ensures |s| == 10 ==> p in s
{
if (|s| == 10){
s := s + [p];
}
}
In the code, I want the post condition to check original s stat, and not its stat after we changed it.
you can use old for old value of a variable like s == old(s).
Here is one example: http://rise4fun.com/Dafny/fhQgD
From Dafny Documentation 22.18. Old Expressions
OldExpression_ = "old" "(" Expression(allowLemma: true, allowLambda: true) ")"
An old expression is used in postconditions. old(e) evaluates to the value expression e had on entry to the current method. Note that old only affects heap dereferences, like o.f and a[i]. In particular, old has no effect on the value returned for local variables or out-parameters.

Expression illegal in evaluator

I'm trying to code something but there is happening something I don't understand.
I get some values from a database and loop over them and change some of them if needed.
This is what I'm trying to do:
if qryGeneral.fieldbyname('B_PRIJS').IsNull or
qryGeneral.fieldbyname('B_PRIJS').Value = 0 then
begin
if (qryGeneral.fieldbyname('V_PRIJS').Value <> 0) or
(qryGeneral.fieldbyname('V_PRIJSEXCL').Value <> 0) then
//make some calculations and save data
end;
B_PRIJS is a float, null type in a SQL Server DB. When I set a breakpoint and I hover .Value it shows 0,11. When I hover IsNull it shows False, so far so good.
Now I would expect it would NOT enter the if-structure, because it is not null and not equal to 0, but it does enter the if-structure.
I don't understand why, I always coded like this.
When I select qryGeneral.fieldbyname('B_PRIJS').Value = 0 while still being in debug mode, I get a message "Expression illegal in evaluator".
I tried replacing Value into AsFloat or changing 0 into 0.0 but it doesn't work.
What am I doing wrong or not understanding here?
Delphi's operator precedence rules mean that your expression is evaluated like this:
if (qryGeneral.fieldbyname('B_PRIJS').IsNull or qryGeneral.fieldbyname('B_PRIJS').Value)
= 0 then
Put parentheses around your = expression just like you have around you <> expressions, and you should get closer to the results you expect. However, the Value property is a Variant. When comparing a Variant to an Integer, the = operator will cause the Variant to be converted to an Integer. Delphi's variant-type-conversion rules show that a Variant holding a real value will be rounded to the nearest integer when the target type is an integer, so your 0.11 value will be rounded to zero. Consider comparing to 0.0 instead.

Resources