- Feature Articles
- CodeSOD
- Error'd
- Forums
-
Other Articles
- Random Article
- Other Series
- Alex's Soapbox
- Announcements
- Best of…
- Best of Email
- Best of the Sidebar
- Bring Your Own Code
- Coded Smorgasbord
- Mandatory Fun Day
- Off Topic
- Representative Line
- News Roundup
- Editor's Soapbox
- Software on the Rocks
- Souvenir Potpourri
- Sponsor Post
- Tales from the Interview
- The Daily WTF: Live
- Virtudyne
Admin
Don't I wish this was what we were doing.
The ERP solution our pointy-headed managers chose had such a brain dead UI (that was intentional - you see that allowed them to charge for 'training')...that it was simpler for our users to use the system as it was supposed to be used (with respect to business logic) if we wrapped a simple set of web forms around their business logic.
Admin
At what point did reading comments under YouTube videos become a good idea?
Admin
Not sure, but how otherwise would I learn that suddenly everybody rips on Bowie?
Admin
If they're my videos, you can see a lot of really annoyed people telling me I shouldn't try playing a video game without taking a 3-year-long study course on how to play it.
Silly me. Thinking games should be fun to play right away.
Admin
It isn't strictly Oracle that has tri-state booleans, it's part of standard SQL.
What isn't part of standard SQL is that in Oracle,
'' IS NULL
is true. As far as I'm concerned, that's the biggest :wtf: ever. I wonder how this system handles that.Admin
But
UNKNOWN OR TRUE
is true, andUNKNOWN AND FALSE
is false (and hence,NOT (UNKNOWN AND FALSE)
is true).Admin
SQL tri-state logic: fucking with people's minds since
NULL
Admin
Which makes sense when you realize UNKNOWN is not some random third value, but a literally unknown boolean value.
Which means that statements where the value depends on UNKNOWN will be UNKNOWN themselves, but those where it doesn't (i.e. the result is the same if you substitute TRUE or FALSE under the UNKNOWN) will have a known value.
Oracle docs seem to have belgiumed that up, though...
Admin
The logic working with such things is not standard boolean, but rather a kind of modal logic. Knowing that something is
UNKNOWN OR FALSE
means that it is known to be not definitelyTRUE
. Things get more complicated from thereon in.I'm really happy I don't work with that sort of thing any more. ;)
Admin
No, this is boolean logic:
(TRUE || TRUE) == (FALSE || TRUE),
so(??? || TRUE)
simplifies toTRUE
.(TRUE||FALSE) != (FALSE||FALSE)
, so(???||FALSE)
simplifies to???
.Admin
Different interpretation of
OR
. ;)Admin
I do, constantly. (Well, when I have a job, anyway.) One of the "favorite" parts of the job is figuring out why some logic went unknown. Especially when it went unknown because, say, the carry bit of the embedded CPU went unknown because the data in some CPU register went unknown 100 instructions earlier, and the CPU just tried to do some operation with that data. At least those sorts of test failures are obvious, if far removed from the actual cause.
Admin
Hey guys slow down you've lost me.
The problem is that WTF developer wants to know if the value changed, and with ANSI NULLS, NULL != NULL. OK so far. First code:
The problem with that code is not that the intent is not clear, it's that if oldValue is NULL then the code does not execute regardless of whether newValue is different from oldValue.
Replacement code:
If you plug in two NULLs, you return NULL!=NULL, thus TRUE, thus you get "changed" even though it didn't change. Maybe other developers do this differently because different ways work...
Either I've accidentally boolean logic, or TRWTF is the article itself!
Admin
If things are too complicated, stop trying to use a single expression. Instead, use several with an outer conditional based on (say) whether the old value is NULL.
Whether this is the most efficient way is beside the point; you can look at the code and see that it is definitely right. (As a bonus, any optimiser worth the name will emit the same back-end code as you'd get in a single nasty-but-correct expression.)
Admin
NULL == NULL does not return TRUE NULL != NULL does not return TRUE
In SQL, if a condition does not return true, then, for all practical purposes, it will handle the case as if FALSE was returned
So the code will work as intended
Admin
In SQL, they're UNKNOWN. Three valued logic, rememeber?
UNKNOWN is kind of like FALSE because records only are returned when the WHERE clause evaluates to TRUE; however, NOT UNKNOWN is still UNKNOWN. It's considered very poor practice to allow your whole WHERE clause to evaluate to UNKNOWN. You should always explicitly handle your null values. Its the only way to really be sure that your queries will return the results you want.
There is an operator that allows this type of comparison in the SQL standard, but neither SQL Server nor Oracle implement it, although PostgreSQL does. This is the
IS DISTINCT FROM
operator.A IS DISTINCT FROM B
is equivalent toA <> B OR (A IS NULL AND B IS NOT NULL) OR (A IS NOT NULL AND B IS NULL)
. SimilarlyA IS NOT DISTINCT FROM B
is equivalent toA = B OR (A IS NULL AND B IS NULL)
.TRWTF, for those wondering, is using a function. A function here is not sargable, so your indexes on the compared fields will be useless. Additionally, the query engine will need to execute this function for every single row, which is a hell of a lot slower than just loading all the data into memory (which it has to do anyways) and doing a straight comparison. The author should just write the damn expression out. It's not hard to do, and the function just adds complexity.
Admin
That depends on how the query optimiser handles the function; it's not required to treat it as a black box.
Admin
Specifically, from the world of sqlserver.
I had to look it up, having worked with databases for 19 years and counting.
Admin
I've not seen any query optimizer unroll a scalar function to allow it to use an index. Have you got an example where it does that?
Admin
No, but I'm writing a compiler for fun and modern compilers most definitely can do this sort of thing quite extensively. A query optimiser is just a specialist kind of compiler with a slightly unusual target language.
Admin
I know that English allows verbing of most words, but what is the action related to a sarge?
Anyway, it's just a bit of fun that has to be one. The least significant one too, to be precise.
Admin
There was a link up-thread:
Admin
I assume it involves a lot of shouting and gratuitous insults.
Admin
https://www.youtube.com/watch?v=GTQAXX08A-s
Admin
Mmm... kind of. It's more of a JIT compiler, except query plans are focused on what's deterministic and what isn't, because they're designed to enforce the relational model first. There's not really a good equivalent for gcc's
--funroll-loops
, for example. That's why cursors often perform so poorly. It's also one reason why functions are usually recommended to be avoided: you sacrifice performance for what's often a minor ease of query writing. The second reason, parameter sniffing, means your query engine might choose to use a poor cached query plan for the function (or sproc) because that was the best one available the first time it ran.SQL Server will treat a very narrow range of functions as unrollable. So-called "Inline Table-Valued Functions" (ITVFs) will be broken up into their components by the query planner, but Multi-Statement Table-Valued Functions and all Scalar Functions will not (with some exceptions for system functions that the SQL Server devs know how to optimize for). You have to write ITVFs in very specific ways, and they really only work well for a fairly narrow set of circumstances, since both a table and a view are the most preferred type of "function" in SQL and perform even better. And this is with SQL Server, which has one of the better query planners out there.
This blog gives a really good overview of what's going on internally.
In TFA, of course, there should be no function or sproc at all. People should just write the damned Boolean expression and learn to handle NULLs in their WHERE clauses.
Admin
The point is they could go a lot further. Yes, the relational model needs to be enforced, but that's just a bunch of semantic constraints on what the legal transformations are, and once you've established the semantics according to the constraints, any operation that preserves the semantics is actually legal within the query engine. This is how C++ and C compilers work, and how the JIT engines for Java, C# and Javascript work; the result of compilation isn't required to be in a language that guarantees that the program is correct, but rather just that the program itself actually is correct.
Function inlining is one of the more trivial transformations (with appropriate semantics set up elsewhere).