Another LOCOTD.... just for me to remember those nice *cough cough* code lines that i come around from time to time.... i'm currently working as a trainee (until February), i'm currently implementing a custom featured content management system (CMS), i'm using php, mySQL, xhtml, css and a bit of JS for some slideshows... but this LOCOTD is about SQL ...
Store Procedures (SPs), as you may not know, are supported by mySQL for quite some time, however not quite perfectly as you might expect....
On SPs, you basically build a wrap box around one or more SQL statements, you can set variables, use the usual SQL stuff.... in my case i was using a SELECT, like i did for the rest of the dozens of SPs i did before, i was implementing a page like feature in the CMS, for that LIMIT clause is god send, but guess what.... in SPs you can't use non-constant integers in LIMIT parameters... yes.... you can use the arguments of the SP anywhere, except on the LIMIT clause...
So ... "How to solve it?" that would be the question... one way would be using a prepared statement, like this:
CREATE PROCEDURE `fooTable`.`sp_fooTableList` ( limit_arg int )
BEGIN
SET @sql = concat('SELECT * FROM `fooTable` LIMIT ', limit_arg);
PREPARE STMT FROM @sql;
EXECUTE stmt;
END
An obvious problem with this, is that it broken the extra security provided by SPs... but it is a valid workaround.... quite simple as well.... but because this prepared statement kinda defeat the purpose of having a nicely wrapped SQL statement, i found a way of doing it without recurring to it, i say found and not invented, credit goes to Gert Brigsted, it's easy to follow and understand how and why it works:
CREATE PROCEDURE `fooDB`.`sp_fooTableList` ( limit_start, limit_end )
BEGIN
SET @rownum:=0;
SELECT *
FROM (
SELECT
( @rownum:=@rownum+1) AS Rownumber,
`fooTable`.*
FROM `fooTable`
ORDER BY `fooTable`.`mooCol` DESC
) AS t
WHERE Rownumber > limit_start AND Rownumber <= limit_end;
END
It looks messy, but it works... sure, it has some impact on performance, but that's the price to pay for security... until LIMIT clause accepts variables as parameters.
Perhaps you are thinking, "That surely is, or will be, fixed in current iterations of mySQL" ... you are right it is, in versions 5.5.6 and 6.0.14, it is 'fixed' ... But not all servers allow you to change mySQL version installed... so, I guess you may run into this problem and have to use one of the above workarounds...
As a side note, this was submitted as bug #11918 by 13 July 2005 and 'solved' by 24 September 2010 .... more than 5 years to 'fix' this 'bug' ... i use quotes because wasn't exactly a bug but more like a non-feature...
Hope it helps someone out there bashing at "ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near: s_limit, e_limit;"
Showing posts with label LOCOTD. Show all posts
Showing posts with label LOCOTD. Show all posts
Tuesday, November 16, 2010
Thursday, June 18, 2009
Line of code of the day #4
Weee... another LOCOTD ... (no ... that doesn't mean Crazy Tower Defence) ... today i present here the following line of code:
solution[i] = solution[j] | (~0)&(1<<z)
The most familiarized with C and pointers will notice that if i is not related in bounds with j value (or vice-versa) something really bad will happen with memory access/write... the lovely usual segmentation fault or worse... the line should have look like this:
solution[j] = solution[j] | (~0)&(1<<z)
Or in a more compact form:
solution[j] |= (~0)&(1<<z)
I lost 3h to find where the error on my code was... you see, when instead of j the i was there I was writing in some area, that area was where a pointer inside a struct was, at first I though the error was in functions that manipulate variables of that struct... when I noticed something very strange when I switch some entries on struct... it looked like something impossible to happen, but after I've done it some stuff worked, so struct control looked fine... only answer would me that I was modifying struct data unknowing it... after a bunch of printf's (like... everywhere) I tracked the error down... cost me a lot of time... and now I 'only' have to finish some algorithmic stuff that is implemented, polish some of the code and optimize some memory accesses...
Well... good coding... i hope you have better luck than me...
solution[i] = solution[j] | (~0)&(1<<z)
The most familiarized with C and pointers will notice that if i is not related in bounds with j value (or vice-versa) something really bad will happen with memory access/write... the lovely usual segmentation fault or worse... the line should have look like this:
solution[j] = solution[j] | (~0)&(1<<z)
Or in a more compact form:
solution[j] |= (~0)&(1<<z)
I lost 3h to find where the error on my code was... you see, when instead of j the i was there I was writing in some area, that area was where a pointer inside a struct was, at first I though the error was in functions that manipulate variables of that struct... when I noticed something very strange when I switch some entries on struct... it looked like something impossible to happen, but after I've done it some stuff worked, so struct control looked fine... only answer would me that I was modifying struct data unknowing it... after a bunch of printf's (like... everywhere) I tracked the error down... cost me a lot of time... and now I 'only' have to finish some algorithmic stuff that is implemented, polish some of the code and optimize some memory accesses...
Well... good coding... i hope you have better luck than me...
Tuesday, June 9, 2009
Line of code of the day #3
So... remember that little problem i had to 'compact' selected bits? i think i solved it...
By using a very special look-up table i manage to do the trick using this 'easy' to read line:
(( f[(m & 0xF0) | (val & 0xF0) >> 4] >> 3) >> (f[(m & 0x0F)<< 4 | (val & 0x0f )] >> 3 ) & 0xF)
Oh, this code is just for 8bits, a simple expansion allows me to use it for 32bits (with look-up table taking up 2Mb)... and no... I won't explain what is in f table has... and yes... I might screw up with the parentesis... I didn't compile that piece of code, but tested it manually instead... it should work... efficiency wise it's better that scan all bits one by one...
You can now commit suicide.
PS: By reading this you agree that i'm not responsible for any harm occoured both physically or mentally when reading the text above... really...
(( f[(m & 0xF0) | (val & 0xF0) >> 4] >> 3) >> (f[(m & 0x0F)<< 4 | (val & 0x0f )] >> 3 ) & 0xF)
Oh, this code is just for 8bits, a simple expansion allows me to use it for 32bits (with look-up table taking up 2Mb)... and no... I won't explain what is in f table has... and yes... I might screw up with the parentesis... I didn't compile that piece of code, but tested it manually instead... it should work... efficiency wise it's better that scan all bits one by one...
You can now commit suicide.
PS: By reading this you agree that i'm not responsible for any harm occoured both physically or mentally when reading the text above... really...
Tuesday, June 2, 2009
Line of code of the day #2
Who would guess its another LOCOTD, this time we have some C code to show...
solution[batch] = solution[batch] | ~((polar_0[batch] ^ polar_1[batch])&polar_0[batch]) | ((polar_0[batch] ^ polar_1[batch])&polar_1[batch]);
In case you're wondering ... yes i could load the values of polar_0 and polar_1 on index batch, but since i don't know what kind of effect that will have on performance, i'll try both and see... compilers and assemblers do magic sometimes... :p
I leave the moment to show you some magic ... long live to SWAR Algorithms!
Jokes aside, using general CPU instructions to make some crazy highly efficient operations is always good, while it is wise to check such approaches also keep moderation in mind, you can end up with some brain damage...
Now... a little puzzle for anyone who is willing to take it:
I have an array of 32-bit masks, that in reality represents a very huge mask for a very huge matrix, now ... i want to grab those bits masked (the number of masked bits is known) and pack them all in another array, all of that must be done fast, since speed is what we want. I leave a little example for 8-bit masks, 4 length array:
mask 01111000 01001001 10101110 10111100
masked 01101011 10100101 11101110 11010010
result 00000000 00000001 10100111 11110100
I do not have a (eficient) solution for this problem (yet - i kinda have an idea), i hope to find one since this is kinda crucial to optimize the speed of the rest of the algorithm.
With that said, feel free to comment and give sugestions about it...
Good coding...
Labels:
C,
english,
informative,
links,
LOCOTD,
programming,
SWAR
Tuesday, April 28, 2009
Line of code of the day
Hmmm ... you know... sometimes you create pieces of code that look like crap but do wonderful things and very fast... so i'll paste a line of a VHDL architecture module... now imagine that 90% of the rest of the module is similar... yes... a nightmare to debug...
div_buffer <= (NUM_VARS-LOG2_NUM_VARS-1 downto 1 => '0')&((offset-(stack(top)(NUM_VARS+LOG2_NUM_VARS-2 downto NUM_VARS)&'0'))&'0');
But work! I might clean up the code later ... anyway, this calculates a divider for a bit vector calculation ... in software takes around 2*N clock cycles to calculate the bit vector, in hardware takes N*log(N) clock cycles... i would say my implementation is efficient .. XD
In other news, my pen tablet and gimp (or should i say GTK+?) are always punching eachother... i found a way of solving the issues ... reboot! ... This only happens in windows Vista... so... yeah ... Vista is not only sluggish, slow and bad... is even worse ... specially since my pen tablet says "Certified for windows Vista" ... go figure!
Labels:
english,
informative,
LOCOTD,
programming,
rant,
vhdl
Subscribe to:
Posts (Atom)