What is the XQuery equivalent of the ESQL COALESCE function? - sql

I'm trying convert WMB 7 mapping nodes to IIB 9 nodes. The auto-convert process turns some ESQL functions to XQuery functions.
Specifically, it turns the ESQL function
COALESCE (var0, var1)
(which returns the first non-null value, as in if var0 = null then var1 else var0) into
XQUERY (var0,var1)
Is it a correct conversion?
If it is, can someone provide a link to API? I couldn't find this on XQuery syntax and operators manuals.

XQuery is not an API, but a standard, and the full syntax can be found online: XQuery 1.0 and XQuery 3.0 (there is no 2.0). You'll also find many manuals, tutorials etc.
XQuery relies on XPath, which is even wider used than XQuery and can be found in libraries for almost every general purpose language.
Your expression is correct XQuery, in that it considers everything a sequence, and the comma concatenates (and flattens) two sequences.
XPath does not know NULL, but it knows xsi:nil and (), the latter being the empty sequence. An empty sequence is removed from the result.
I am not sure what XQuery processor is used underneath, but the correct expression should be ($var0, $var1)[1]2, which works the same way as your COALESCE operation1. In XPath and XQuery, variables are referenced with the $ sign. The number of variables or expressions separated by the comma is unbounded. If all are the empty sequence (null), the result is the empty sequence.
Without [1], it will return all items that are non-null and discard the rest. You can use another index, like [3] to get the third non-null value. If no such value exists, it will return null (empty sequence).
1 which behaves not exactly the way you described it. I believe it behaves like if var0 == null then var1 else var0, it selects the first non-null value (I've updated the OP).
2 as Florent has explained in the comments, a warning with this expression is in place. If you have $var1 := (1, 2) and $var2 := (3, 4), the expression $var1, $var2)[1] will return 1, not (1, 2), because sequences cannot contain subsequences, and indexing a sequence with [x] will return the xth value of the flattened sequence. You can safe-guard your expression with (zero-or-one($var1), zero-or-one($var2))[1].

Related

Oracle INSTR replacement in SQLite

I'm currently porting part of an application from an Oracle to a SQLite backend (Java, using plain JDBC). One Oracle-specific feature often being used is the INSTR function with three arguments:
INSTR(<string>, <search-string>, <position>)
This function searches within a string for a search string starting from a certain position. The third parameter can either be positive or negative. If it's negative, the search works backwards starting at the end of the string.
This function isn't available in SQLite and the best I could come up with is an alternative by nesting some other functions:
If <position> is positive:
LENGTH(<string>) - LENGTH(SUBSTR(SUBSTR(<string>,
<position>), STRPOS(SUBSTR(<string>, <position>),
<search-string>) + 1))
If <position> is negative (in our case -1 is the only negative value being used):
LENGTH(<string>) - LENGTH(REPLACE(<string>,
RTRIM(<string>, REPLACE(<string>, <search-string>,
'')), ''))
This seems to be giving the desired result, but you can see why I'm not really in favor of this approach. Certainly because in the original syntax the INSTR is used a lot and is being nested as well. It becomes a disaster for maintenance afterwards.
Is there a more elegant approach or could I be missing some other native solution for what seems to be a rather trivial task?
SQL
CASE WHEN position = 0
THEN INSTR(string, substring)
WHEN position > 0
THEN INSTR(SUBSTR(string, position), substring) + position - 1
WHEN position < 0
THEN LENGTH(RTRIM(REPLACE(string,
substring,
REPLACE(HEX(ZEROBLOB(LENGTH(substring))),
'00',
'¬')),
string)) - LENGTH(substring) + 1
END
It assumes the ¬ character won't be part of the search string (but in the unlikely event this assumption is false could of course be changed to a different rarely used character).
SQLFiddle Demo
Some worked examples here: http://sqlfiddle.com/#!5/7e40f9/5
Credits
The positive position method was adapted from Tim Biegeleisen's answer. (But a zero value needs to be handled separately).
The negative position method used the method described in this question as a starting point.
The creation of a string consisting of a character repeated n times was taken from this simplified answer.
Actually, SQLite does support an INSTR function. But, it does not have a third parameter, which means, it always searches from the very beginning of the string.
But, we can workaround this by passing a substring to INSTR, and then offsetting the position found by adding the amount of the offset of the substring.
So, as an example, Oracle's call:
INSTR('catsondogsonhats', 'on', 7)
which would return 11, would become:
INSTR(SUBSTR('catsondogsonhats', 7), 'on') + 6

Difference between sequential and combined predicates

In Selenium I have written a xpath and both of them retrieves the same result.
//a[#role='tab'][text()=' Assets']
//a[#role='tab' and text()=' Assets']
Does both of them have the same meaning?
In most cases a[b][c] has exactly the same effect as a[b and c]. There are two exceptions to be aware of:
They are not equivalent if either predicate is numeric, or has a dependency on position() or last() (I call these positional predicates). For example a[#x][1] selects the first a element that has an #x attribute, while a[1][#x] selects the first a element provided it has an #x attribute (and selects nothing otherwise). By contrast a[1 and #x] converts the integer 1 to the boolean true(), so it just means a[#x].
There may be differences in behaviour if evaluation of b or c fails with a dynamic error. The precise rules here depend on which version of XPath you are using, and to be honest the rules leave implementations some leeway, but you need to exercise care if you want to be sure that in the event of b being false, c is not evaluated. (This hardly matters in XPath 1.0 because very few expressions throw dynamic errors.)
When you add Square Brackets ([]) to XPath you are adding a condition, so
first row adding 2 conditions
Which produce similar results as adding condition with and
Normally you don't use first row, because it less readable,
Mainly because this syntax represent in other languages a Matrix
// return a random m-by-n matrix with values between 0 and 1
public static double[][] random(int m, int n) {
See tutorial:
5 XPaths with predicates
A predicate is an expression that can be true or false
It is appended within [...] to a given location path and will refine results
More than one predicate can be appended to and within (!) a location path
The first one is a predicate, which means it checks if a[#role='tab'] is true then it proceeds to [text()=' Assets']
The second one is a just using an and operator so it validates both are true.

How to tell if an identifier is being assigned or referenced? (FLEX/BISON)

So, I'm writing a language using flex/bison and I'm having difficulty with implementing identifiers, specifically when it comes to knowing when you're looking at an assignment or a reference,
for example:
1) A = 1+2
2) B + C (where B and C have already been assigned values)
Example one I can work out by returning an ID token from flex to bison, and just following a grammar that recognizes that 1+2 is an integer expression, putting A into the symbol table, and setting its value.
examples two and three are more difficult for me because: after going through my lexer, what's being returned in ex.2 to bison is "ID PLUS ID" -> I have a grammar that recognizes arithmetic expressions for numerical values, like INT PLUS INT (which would produce an INT), or DOUBLE MINUS INT (which would produce a DOUBLE). if I have "ID PLUS ID", how do I know what type the return value is?
Here's the best idea that I've come up with so far: When tokenizing, every time an ID comes up, I search for its value and type in the symbol table and switch out the ID token with its respective information; for example: while tokenizing, I come across B, which has a regex that matches it as being an ID. I look in my symbol table and see that it has a value of 51.2 and is a DOUBLE. So instead of returning ID, with a value of B to bison, I'm returning DOUBLE with a value of 51.2
I have two different solutions that contradict each other. Here's why: if I want to assign a value to an ID, I would say to my compiler A = 5. In this situation, if I'm using my previously described solution, What I'm going to get after everything is tokenized might be, INT ASGN INT, or STRING ASGN INT, etc... So, in this case, I would use the former solution, as opposed to the latter.
My question would be: what kind of logical device do I use to help my compiler know which solution to use?
NOTE: I didn't think it necessary to post source code to describe my conundrum, but I will if anyone could use it effectively as a reference to help me understand their input on this topic.
Thank you.
The usual way is to have a yacc/bison rule like:
expr: ID { $$ = lookupId($1); }
where the the lookupId function looks up a symbol in the symbol table and returns its type and value (or type and storage location if you're writing a compiler rather than a strict interpreter). Then, your other expr rules don't need to care whether their operands come from constants or symbols or other expressions:
expr: expr '+' expr { $$ = DoAddition($1, $3); }
The function DoAddition takes the types and values (or locations) for its two operands and either adds them, producing a result, or produces code to do the addition at run time.
If possible redesign your language so that the situation is unambiguous. This is why even Javascript has var.
Otherwise you're going to need to disambiguate via semantic rules, for example that the first use of an identifier is its declaration. I don't see what the problem is with your case (2): just generate the appropriate code. If B and C haven't been used yet, a value-reading use like this should be illegal, but that involves you in control flow analysis if taken to the Nth degree of accuracy, so you might prefer to assume initial values of zero.
In any case you can see that it's fundamentally a language design problem rather than a coding problem.

How SQL/sqlite wildcars work? LIKE operator

How wildcards in sqlite work. Or how LIKE operator matches.
For examle lets say:
1: LIKE('s%s%', 's12s12')
2: LIKE('asdaska', '%sk%')
In 1st example what % matches after 1st s, and how it decides to continue matching % or s after %.
In 2nd example if s matches first then FALSE returned.
Both examples return TRUE. From my Programming knowledge I came up with that LIKE function is some like a recursive function that when 2 possibilities appear function calls itself with 2 different params and uses OR between them, then obviously if one call returns true, upper function directly returns true. If it is so, then LIKE operator is quiet slow to use on large DBs.
P.S. There is one more '_' wildcard which matches exactly one character
I couldnt find any detailed documentation of LIKE operator.
% matches zero or more characters, _ matches exactly one.
Your first pattern 's%s%' would match, 'ss', 's1s', 's1111s', 'ss1111', etc. etc.
However if you wrote 's_s_' it would match 's1s1', but none of the above.

ISNUMERIC('07213E71') = True?

SQL is detecting that the following string ISNUMERIC:
'07213E71'
I believe this is because the 'E' is being classed as a mathmatical symbol.
However, I need to ensure that only values which are whole integers are returned as True.
How can I do this?
07213E71 is a floating number 7213 with 71 zeros
You can use this ISNUMERIC(myValue + '.0e0') to test for whole integers. Slightly cryptic but works.
Another test is the double negative myValue NOT LIKE '%[^0-9]%' which allows only digits 0 to 9.
ISNUMERIC has other issues in that these all return 1: +, -,
To nitpick: This is a whole integer. It is equivalent to 7213 * 10 ^ 71.
In the documentation it says
ISNUMERIC returns 1 when the input expression evaluates to a valid integer, floating point number, money or decimal type; otherwise it returns 0. A return value of 1 guarantees that expression can be converted to one of these numeric types.
Your number is also float (with exponential notation), therefore the only way to have ISINTEGER is to define it yourself on SQL. Read the following link.
http://classicasp.aspfaq.com/general/what-is-wrong-with-isnumeric.html
Extras:
http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=59049
http://www.tek-tips.com/faqs.cfm?fid=6423
I have encountered the same problem. IsNumeric accepts "$, €, +, -, etc" as valid inputs and Convert function throws errors because of this.
Using "LIKE" SQL statement fixed my problem. I hope it'll help the others
SELECT UnitCode, UnitGUID, Convert(int, UnitCode) AS IntUnitCode
FROM [NG_Data].[NG].[T_GLB_Unit]
WHERE ISNULL(UnitType,'') <>'Department'
AND UnitCode NOT LIKE '%[^0-9]%'
ORDER BY IntUnitCode
PS: don't blame me for using "UnitCode" as nvarchar :) It is an old project :)
You have to ensure it out of the call to the database, whatever the language you work with, and then pass the value to the query. Probably the SQL is understanding that value as a string.