- 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
Nah, you can do this neatly as well: First construct a single-digit BCD adder with carry. Then chain two of these together. If the MSD adder carries, set both digits to zero. Trivial.
Admin
Not knowing the application or the database, I can't say what is invalid input. Perhaps (by design) values other than two digits have special meaning and must be preserved. If we assume we should preserve current behavior, suggested replacement code should be tested with strings like '2', '-6', '3D', 'NA', etc. to ensure that the original value is preserved.
Admin
Everyone knows that the costliest part of this is the conditionals, and I only have one!
Admin
Way to handle boolean function results! Only, the second test should be:
# I only trust the = operator
if (($sn < 0) = 1 or ($sn >= 99) = 1)
And maybe the first should be...
if (((isnumeric(@sequenceNumber) = 1) > 0) = 1)
Looks kinda cheery. (And (Ever (So (Lispy (.))))) But hey, we can always blame the T-SQL "programming" "language" for things like this ;-)
Disclaimer: I don't know (how a Boolean is represented in) T-SQL
Admin
Damn, if I didn't laugh out loud reading that. My brain managed to "censor" the "second special case."
Admin
Either
CAST(1 AS BIT) -- true
CAST(0 AS BIT) -- false
or
DECLARE @True bit, @False bit
SELECT @True = 1, @False = 0
Admin
You do filter your input before you use it don't you?
Admin
How did this get in here?
Admin
That is exactly what I was thinking.
Admin
Considering how many "improvements" fail to leave '00' and non-numeric inputs alone, I'd be tempted to not fix the WTF if I ran across the code. An elegant yet erroneous change does not count as "fixing" the WTF.
Admin
Ok let me try:
set @sequenceCode = case when (CAST(@sequenceCode as int) > 0) then right( cast 101 + cast( @sequenceCode as int) as char(3)) , 2) else @sequenceCode end
Admin
The cast will fail on non-numeric input.
DECLARE @sequenceCode VARCHAR(2) SET @sequenceCode = '99'
-- Do your input validation somewhere here...
SET @sequenceCode = CASE WHEN ISNUMERIC(@sequenceCode) = 0 THEN @sequenceCode WHEN @sequenceCode = '00' THEN '00' ELSE RIGHT('0'+CONVERT(VARCHAR,@sequenceCode+1),2) END
SELECT @sequenceCode
Admin
(Stupid forum editor)
The cast will fail on non-numeric input.
DECLARE @sequenceCode VARCHAR(2)
SET @sequenceCode = '99'
-- Do your input validation somewhere here...
SET @sequenceCode =
CASE WHEN ISNUMERIC(@sequenceCode) = 0 THEN @sequenceCode
WHEN @sequenceCode = '00' THEN '00'
ELSE RIGHT('0'+CONVERT(VARCHAR,@sequenceCode+1),2)
END
SELECT @sequenceCode
Admin
Dude, as WTFGenerators go, this is a great one. The fact that you're incrementing x while looping over i is fairly obvious, but may lead to some severe crashes before someone finds out. All that's fairly trivial... But I especially love the "i != 100" (as opposed to the "i < 100") which is always garanteed to have the next person maintaining your code searching for at least a day before he finds the conditional "i += 10".
Brillant!
Fabian
Admin
Has anyone here ever remarked on the quality of the forum software?
Jus' kiddin'...
What was I was trying to say was:
"(as opposed to the "i < 100") which is guaranteed to have 'the next guy' searching for at least a day before he finds the conditional "i += 10".
(...praying this works...)
Admin
In Ada:
inc num and watch out for that num > 99, ok?
Admin
If it had been MySQL, I would have set the column type to TINYINT(2) UNSIGNED ZEROFILL and used modulus (MOD 100) when incrementing it.
Admin
Couldn't you just do a Case statement and if case is equal to 99 set it to 0 otherwise add 1?
Codename: Mushoo
Admin
Yeah, but using Sybase is a WTF in itself. It's like running a real old version of SQL Server.
Sybase almost makes baby Jesus cry, although not as much as Oracle.
Admin
It's a trick question, right? The WTF isn't (only) in this code. If a record might need to be incremented, then it shouldn't have been a decimal string in the first place. And if this string really does need to be incremented, then I'm not writing a line of code until I've gathered requirements and you've signed off on a definition of "increment" for char(2)s. Then I'll write the unit tests (I don't know how wide chars are here, if they're small enough these could be exhasutive), and your nominated technical reviewer can sign off on those. Then I'll write the code. But only if you're sure you don't need a design document.
Admin
i wouldn't hand type all those conversions - i would write a perl script to generate the code for me, then copy and paste the result!!
Admin
What people doesn't seem to get is that he kept the numbers on the interval [00..99] because he wasn't going to cover the range [00..4294967295].
Imagine if the column where this is inserted was an integer 64 bits!
Admin
i have a sneaking suspicion that this was a y2k fix, and that it eliminated mod100 year problems by storing the 2 digits as a string...
Admin
set @sequenceCode = right(cast(cast( @sequenceCode as int) + 101 as varchar(3)), 2)
or possibly even
set @sequenceCode = cast(cast( @sequenceCode as int) + 101 as varchar(2))
Admin
All right. I have come to a conclusion that, some of you guys are having some problem understanding the problem of this topic.
To ease the pain of reading If statements, i have come up with even more readable solution
SET @sequenceCode = (
CASE
WHEN @sequenceCode = '01' THEN '02'
WHEN @sequenceCode = '02' THEN '03'
WHEN @sequenceCode = '03' THEN '04'
WHEN @sequenceCode = '04' THEN '05'
WHEN @sequenceCode = '05' THEN '06'
WHEN @sequenceCode = '06' THEN '07'
-- snip --
WHEN @sequenceCode = '94' THEN '95'
WHEN @sequenceCode = '95' THEN '96'
WHEN @sequenceCode = '96' THEN '97'
WHEN @sequenceCode = '97' THEN '98'
WHEN @sequenceCode = '98' THEN '99'
WHEN @sequenceCode = '99' THEN '00'
END
)
Admin
Senior programmer? Looks more like a senile programmer shiver
Admin
Hey Bill,
Write me a stored proc that does this ..
Now was that fast or what - 15 secs. :)
Admin
All of you are trying to actually change the algorithm, and use casting to an integer or something. Assume that casting is not available, or is very expensive (otherwise he would have used it, right?)
Besides, the goal is to "Fix the WTF", so it must still remain a WTF (albeit fixed) when done.
So, here's my solution. (I don't know the syntax for T-SQL arrays, so fix it further yourself.)
Array[100] = {'00','01','02','03', ... , '99'}
for(i=0;i<100;++i)
IF (@sequenceCode = Array[i])
{
SET @sequenceCode = Array[(i+1)%100];
break;
}
How's that?
Admin
-- Best to use a temporary table for this job. Much quicker.
Declare @i int
Declare @c char(2)
Declare @t table (GoFrom char(2), Go_To char(2))
Set @i = 0
While (@i < 100)
Begin
If @i = 0
Set @c = '00'
Else
Set @c = right('0' + cast(@i+1 as varchar(3)),2)
Insert Into @t (GoFrom, Go_To) values (right('0' + cast(@i as varchar(3)),2), @c)
Set @i=@i+1
End
Select @SequenceCode = isnull(Go_To,@SequenceCode) From @t Where GoFrom = @SequenceCode
Admin
You Forgot to Build INDEX!!
Admin
That would be:
SET @sequenceCode = (
CASE @sequenceCode
WHEN '01' THEN '02'
WHEN '02' THEN '03'
WHEN '03' THEN '04'
WHEN '04' THEN '05'
WHEN '05' THEN '06'
WHEN '06' THEN '07'
-- snip --
WHEN '94' THEN '95'
WHEN '95' THEN '96'
WHEN '96' THEN '97'
WHEN '97' THEN '98'
WHEN '98' THEN '99'
WHEN '99' THEN '00'
END
)
:)
Admin
This is surely the correct answer (as md2perpe also pointed out). The WTF is using a
CHAR for a counter in the first place.
So given this piece of arse-wipingly bad database design, what should one do?
a) refactor the database
b) do what the wtf guy did and write 100 conditionals
or
c) use some moderately intelligent programming with casting or a map to do it in
fewer lines.
In real life I might well have ended up doing (b).
Admin
The WTFGenerator class given by Volmarias does not compile:
dmitriy@si[202]$ javac WTFGenerator.java
WTFGenerator.java:3: illegal start of expression
for(int i = 1; i!=100; ;) {
^
WTFGenerator.java:3: illegal start of expression
for(int i = 1; i!=100; ;) {
^
WTFGenerator.java:7: ';' expected
}
^
3 errors
Once I remove the errors in the code (those above and others), it prints out lines to set the value to 2 if it is 1, to 3 if it is 2, and so on. Similarly to some of the other submissions, it increments 99 to 100.
Admin
Admin
The 1st one would be the solution I would have come up with. For fixed-length-char numeric sequences. Easily extendable for larger lengths:
3 digits:
set @sequenceCode = right(cast(cast( @sequenceCode as int) + 1001 as varchar(3)), 3)
4 digits:
set @sequenceCode = right(cast(cast( @sequenceCode as int) + 10001 as varchar(3)), 4)
Admin
WTF, should be
set @sequenceCode = right(cast(cast( @sequenceCode as int) + 1001 as varchar(4)), 3)
set @sequenceCode = right(cast(cast( @sequenceCode as int) + 10001 as varchar(5)), 4)
Admin
Everyone knows that you should be using lookup tables and select statements in SQL. And why on earth would we want to waste disk space by storing the lookup table in the database when we can generate it on the fly?
Admin
I've had enough of these things that are supposed to be simple being difficult. I'm going to invent something to make it easier to make simple changes to numbers according to a basic rule.
I shall call it 'maths'.
Admin
Now *that* is what I call brillant!
Admin
Here is a Python (but not pythonic at all) version that does handle 99>00 increment, and does in fact generate any random length incrementing suite behaving as today's WTF does: increment by 1, replace maximum value by "00", pad to 2, anything out of the (]0, upper[) intact.
Admin
And a version a slight bit more pythonic (but much more moronic):
Admin
I think we have a winner.
Admin
And that's a good thing, Mr. Spolsky.
Admin
in Oracle, a brillant solution would look like that:
select ltrim(to_char(nvl(min(num),0),'00'))
into sequenceCode
from (select rownum as num from all_objects where rownum<100)
where num>sequenceCode;
The sad part of the story: I've seen programs that really did similar select statements...
Admin
Remarked on what?
Admin
As people continued to complain that the preview didn't always look like the final result, the author of the forum software just dropped the preview button entirely (at least for unregistered users). What a brillant solution!
Frankly, by now I'm surprised that the URL in my browser's location bar does not contain snippets of SQL.
Admin
I can confirm that it is also gone for registered users. "If you can't fix it, kill it".
Admin
And if the intern had an ounce of sense he'd at least write a code generator in [perl|python|VB|whatever] to write out all the cases for him!
Admin
hahahha...
Sometimes my boss and I have conversations like this...
me: It's a complicated program, there is a lot of business logic
him: A lot of if/else's, hunh?
me: yes
this (and similiar wtf's) make me wonder how many programmers such as this one he is come into contact with over the years. A little scary.[:^)]
Admin
The problem is, their thought process goes like this:
// Do I have too many cases?
switch (numberOfCases) {
case 1:
// not too many
case 2:
// not too many
case 3:
// not too many
...