Close Menu
    DevStackTipsDevStackTips
    • Home
    • News & Updates
      1. Tech & Work
      2. View All

      Error’d: You Talkin’ to Me?

      September 20, 2025

      The Psychology Of Trust In AI: A Guide To Measuring And Designing For User Confidence

      September 20, 2025

      This week in AI updates: OpenAI Codex updates, Claude integration in Xcode 26, and more (September 19, 2025)

      September 20, 2025

      Report: The major factors driving employee disengagement in 2025

      September 20, 2025

      DistroWatch Weekly, Issue 1140

      September 21, 2025

      Distribution Release: DietPi 9.17

      September 21, 2025

      Development Release: Zorin OS 18 Beta

      September 19, 2025

      Distribution Release: IPFire 2.29 Core 197

      September 19, 2025
    • Development
      1. Algorithms & Data Structures
      2. Artificial Intelligence
      3. Back-End Development
      4. Databases
      5. Front-End Development
      6. Libraries & Frameworks
      7. Machine Learning
      8. Security
      9. Software Engineering
      10. Tools & IDEs
      11. Web Design
      12. Web Development
      13. Web Security
      14. Programming Languages
        • PHP
        • JavaScript
      Featured

      @ts-ignore is almost always the worst option

      September 22, 2025
      Recent

      @ts-ignore is almost always the worst option

      September 22, 2025

      MutativeJS v1.3.0 is out with massive performance gains

      September 22, 2025

      Student Performance Prediction System using Python Machine Learning (ML)

      September 21, 2025
    • Operating Systems
      1. Windows
      2. Linux
      3. macOS
      Featured

      DistroWatch Weekly, Issue 1140

      September 21, 2025
      Recent

      DistroWatch Weekly, Issue 1140

      September 21, 2025

      Distribution Release: DietPi 9.17

      September 21, 2025

      Hyprland Made Easy: Preconfigured Beautiful Distros

      September 20, 2025
    • Learning Resources
      • Books
      • Cheatsheets
      • Tutorials & Guides
    Home»News & Updates»Divine Comedy

    Divine Comedy

    August 7, 2025

    “Code should be clear and explain what it does, comments should explain why it does that.” This aphorism is a decent enough guideline, though like any guidance short enough to fit on a bumper sticker, it can easily be overapplied or misapplied.

    Today, we’re going to look at a comment Salagir wrote. This comment does explain what the code does, can’t hope to explain why, and instead serves as a cautionary tale. We’re going to take the comment in sections, because it’s that long.

    This is about a stored procedure in MariaDB. Think of Salagir as our Virgil, a guide showing us around the circles of hell. The first circle? A warning that the dead code will remain in the code base:

    	/************************** Dead code, but don't delete!
    
    	  What follows if the history of a terrible, terrible code.
    	  I keep it for future generations.
    	  Read it in a cold evening in front of the fireplace.
    

    My default stance is “just delete bad, dead code”. But it does mean we get this story out of it, so for now I’ll allow it.

    	  **** XXX ****   This is the story of the stored procedure for getext_fields.   **** XXX ****
    
    	Gets the english and asked language for the field, returns what it finds: it's the translation you want.
    		   Called like this:
    		   " SELECT getext('$table.$field', $key, '$lang') as $label "
    		   The function is only *in the database you work on right now*.
    

    Okay, this seems like a pretty simple function. But why does this say “the function is only in the database you work on right now”? That’s concerning.

    		***** About syntax!!
    			The code below can NOT be used by copy and paste in SQL admin (like phpmyadmin), due to the multiple-query that needs DELIMITER set.
    			The code that works in phpmyadmin is this:
    DELIMITER $$
    DROP FUNCTION IF EXISTS getext$$
    CREATE FUNCTION (...same...)
    		LIMIT 1;
    	RETURN `txt_out`;
    END$$
    			However, DELIMITER breaks the code when executed from PHP.
    

    Am I drowning in the river Styx? Why would I be copy/pasting SQL code into PhpMyAdmin from my PHP code? Is… is this a thing people were doing? Or was it going the opposite way, and people were writing delimited statements and hoping to execute them as a single query? I’m not surprised that didn’t work.

    		***** About configuration!!!
    			IMPORTANT: If you have two MySQL servers bind in Replication mode in order to be able to execute this code, you (or your admin) should set:
    			SET GLOBAL log_bin_trust_function_creators = 1;
    			Without that, adding of this function will fail (without any error).
    

    I don’t know the depths of MariaDB, so I can’t comment on if this is a WTF. What leaps out to me though, is that this likely needs to be in a higher-level form of documentation, since this is a high-level configuration flag. Having it live here is a bit buried. But, this is dead code, so it’s fine, I suppose.

    		***** About indexes!!!!
    			The primary key was not used as index in the first version of this function. No key was used.
    			Because the code you see here is modified for it's execution. And
    				`field`=my_field
    			becomes
    				`field`= NAME_CONST('my_field',_ascii'[value]' COLLATE 'ascii_bin')
    			And if the type of my_field in the function parameter wasn't the exact same as the type of `text`, no index is used!
    			At first, I didn't specify the charset, and it became
    				`field`= NAME_CONST('my_field',_utf8'[value]' COLLATE 'utf8_unicode_ci')
    			Because utf8 is my default, and no index was used, the table `getext_fields` was read entirely each time!
    			Be careful of your types and charsets... Also...
    

    Because the code you see here is modified for its execution. What? NAME_CONST is meant to create synthetic columns not pulled from tables, e.g. SELECT NAME_CONST("foo", "bar") would create a result set with one column (“foo”), with one row (“bar”). I guess this is fine as part of a join- but the idea that the code written in the function gets modified before execution is a skin-peelingly bad idea. And if the query is rewritten before being sent to the database, I bet that makes debugging hard.

    		***** About trying to debug!!!!!
    			To see what the query becomes, there is *no simple way*.
    			I literally looped on a SHOW PROCESSLIST to see it!
    			Bonus: if you created the function with mysql user "root" and use it with user "SomeName", it works.
    			But if you do the show processlist with "SomeName", you won't see it!!
    

    Ah, yes, of course. I love running queries against the database without knowing what they are, and having to use diagnostic tools in the database to hope to understand what I’m doing.

    		***** The final straw!!!!!!
    			When we migrated to MariaDB, when calling this a lot, we had sometimes the procedure call stucked, and UNKILLABLE even on reboot.
    			To fix it, we had to ENTIRELY DESTROY THE DATABASE AND CREATE IT BACK FROM THE SLAVE.
    			Several times in the same month!!!
    

    This is the 9th circle of hell, reserved for traitors and people who mix tabs and spaces in the same file. Unkillable even on reboot? How do you even do that? I have a hunch about the database trying to retain consistency even after failures, but what the hell are they doing inside this function creation statement that can break the database that hard? The good news(?) is the comment(!) contains some of the code that was used:

    		**** XXX ****    The creation actual code, was:   **** XXX ****
    
    		// What DB are we in?
    		$PGf = $Phoenix['Getext']['fields'];
    		$db = $PGf['sql_database']? : (
    				$PGf['sql_connection'][3]? : (
    						$sql->query2cell("SELECT DATABASE()")
    					)
    				);
    
    		$func = $sql->query2assoc("SHOW FUNCTION STATUS WHERE `name`='getext' AND `db`='".$sql->e($db)."'");
    
    		if ( !count($func) ) {
    			$sql->query(<<<MYSQL
    				CREATE FUNCTION {$sql->gt_db}getext(my_field VARCHAR(255) charset {$ascii}, my_id INT(10) UNSIGNED, my_lang VARCHAR(6) charset {$ascii})
    				RETURNS TEXT DETERMINISTIC
    				BEGIN
    					DECLARE `txt_out` TEXT;
    					SELECT `text` INTO `txt_out`
    						FROM {$sql->gt_db}`getext_fields`
    						WHERE `field`=my_field AND `id`=my_id AND `lang` IN ('en',my_lang) AND `text`!=''
    						ORDER BY IF(`lang`=my_lang, 0, 1)
    						LIMIT 1;
    					RETURN `txt_out`;
    				END;
    MYSQL
    			);
    			...
    		}
    

    I hate doing string munging to generate SQL statements, but I especially hate it when the very name of the object created is dynamic. The actual query doesn’t look too unreasonable, but everything about how we got here is terrifying.

    		**** XXX ****    Today, this is not used anymore, because...   **** XXX ****
    
    		Because a simple sub-query perfectly works! And no maria-db bug.
    
    		Thus, in the function selects()
    		The code:
    			//example: getext('character.name', `character_id`, 'fr') as name
    			$sels[] = $this->sql_fields->gt_db."getext('$table.$field', $key, '$lang') as `$label`";
    
    		Is now:
    			$sels[] = "(SELECT `text` FROM {$this->sql_fields->gt_db}`getext_fields`
    				WHERE `field`='$table.$field' AND `lang` IN ('en', '$lang') AND `id`=$key AND `text`!=''
    				ORDER BY IF(`lang`='$lang', 0, 1) LIMIT 1) as `$label`";
    
    		Less nice to look at, but no procedure, all the previous problems GONE!
    
    
    		**** XXX   The end.
    */
    

    Of course a simple subquery (or heck, probably a join!) could handle this. Linking data across two tables is what databases are extremely good at. I agree that, at the call site, this is less readable, but there are plenty of ways one could clean this up to make it more readable. Heck, with this, it looks a heck of a lot like you could have written a much simpler function.

    Salagir did not provide the entirety of the code, just this comment. The comment remains in the code, as a warning sign. That said, it’s a bit verbose. I think a simple “Abandon all hope, ye who enter here,” would have covered it.

    [Advertisement]
    BuildMaster allows you to create a self-service release management platform that allows different teams to manage their applications. Explore how!

    Source: Read More 

    Facebook Twitter Reddit Email Copy Link
    Previous Articlerewindtty – terminal session recorder and replayer
    Next Article Smart Ways to Pass AI Detection When Writing With AI Help

    Related Posts

    News & Updates

    DistroWatch Weekly, Issue 1140

    September 21, 2025
    News & Updates

    Distribution Release: DietPi 9.17

    September 21, 2025
    Leave A Reply Cancel Reply

    For security, use of Google's reCAPTCHA service is required which is subject to the Google Privacy Policy and Terms of Use.

    Continue Reading

    A Step-by-Step Coding Guide to Defining Custom Model Context Protocol (MCP) Server and Client Tools with FastMCP and Integrating Them into Google Gemini 2.0’s Function‑Calling Workflow

    Machine Learning

    CVE-2025-2168 – Elementor Store Kit CSRF

    Common Vulnerabilities and Exposures (CVEs)

    CVE-2025-7164 – PHPGurukul/Campcodes Cyber Cafe Management System SQL Injection Vulnerability

    Common Vulnerabilities and Exposures (CVEs)

    Slow Fire TV? This 30-second fix made my system run like new again

    News & Updates

    Highlights

    CVE-2025-1418 – Konsola Proget Profile Information Disclosure Vulnerability

    May 21, 2025

    CVE ID : CVE-2025-1418

    Published : May 21, 2025, 1:16 p.m. | 1 hour, 34 minutes ago

    Description : A low-privileged user can access information about profiles created in Proget MDM (Mobile Device Management), which contain details about allowed/prohibited functions. The profiles do not reveal any sensitive information (including their usage in connected devices).   

    This issue has been fixed in 2.17.5 version of Konsola Proget (server part of the MDM suite).

    Severity: 0.0 | NA

    Visit the link for more details, such as CVSS details, affected products, timeline, and more…

    How I Turned My Old Hi-Fi Speakers into Bluetooth Ones with Raspberry Pi

    May 10, 2025

    Nightdive and id Software are a match made in gaming heaven — As I play Heretic + Hexen, I’m hopeful for more remasters across Activision and Bethesda

    August 18, 2025

    CVE-2025-7763 – Open Redirect Vulnerability in thinkgem JeeSite Site Controller/SSO

    July 17, 2025
    © DevStackTips 2025. All rights reserved.
    • Contact
    • Privacy Policy

    Type above and press Enter to search. Press Esc to cancel.