Category Archives: varia programistyczna

Eh ta rekurencja…

Zagadnienie było z pozoru proste. Potrzebowałem za pomocą SQL-a wyciągać z bazy wszystkie podkategorie dla danej kategorii w sklepie. Typowe drzewo. Od razu przychodzi na myśl rozwiązanie: funkcja/procedura rekurencyjna… niestety w MySQL-u nie jest to takie proste…Nie pozwala nam on na ich Tworzenie. Po dłuższym czasie wpadłem na rozwiązanie, które zamieszczam poniżej. Nie jest ono zbytnio eleganckie. Oto ono:

DROP PROCEDURE IF EXISTS getTreeElements;
DELIMITER //
CREATE PROCEDURE getTreeElements(root INT(8))
BEGIN
DROP TABLE IF EXISTS TreeElementsTemporaryTable;
CREATE TABLE TreeElementsTemporaryTable (id BIGINT NOT NULL, depth INT NOT NULL, UNIQUE (id));

SET @parent = root, @depth = 0;
INSERT INTO TreeElementsTemporaryTable VALUES (root, @depth);
mlp: LOOP
set @depth = @depth + 1;
SELECT COUNT(*) FROM TreeElementsTemporaryTable INTO @pre;

INSERT INTO TreeElementsTemporaryTable
SELECT node.id, @depth FROM TreeElementsStorageTable AS node, TreeElementsTemporaryTable AS nn
WHERE node.parent_id = nn.id
ON DUPLICATE KEY UPDATE TreeElementsTemporaryTable.id = node.id;

SELECT COUNT(*) FROM TreeElementsTemporaryTable INTO @post;

IF @post = @pre THEN LEAVE mlp; END IF;
END LOOP;

SELECT id FROM TreeElementsTemporaryTable; #tutaj wstaw Twoją kwerende

DROP TABLE TreeElementsTemporaryTable;
END//
DELIMITER ;

Małe wyjaśnienie:
TreeElementsTemporaryTable – nazwa tabeli przechowującej tymczasowe wyniki. Niestety tabela ta nie może być tabelą tymczasową (temporary table), gdyż do takich tabel możemy tworzyć jedynie jedno połączenie w zapytaniu, a jak widać powyżej potrzebowałem ich więcej.
TreeElementsStorageTable – tabela z danymi drzewa. W moim wypadku była to tabela o takiej strukturze:

CREATE TABLE IF NOT EXISTS `TreeElementsStorageTable` (
`id` bigint(20) NOT NULL auto_increment,
`parent_id` bigint(20) NOT NULL default ‘0′,
`name` varchar(255) NOT NULL,
PRIMARY KEY (`id`),
KEY `parent_id` (`parent_id`)
);

Rozwiązanie niezbyt eleganckie, które stwarza dużo nadmiarowego ruchu, ale po kolei. Na początku do tabeli tymczasowej dodaje id głównego elementu, a następnie w każdym obiegu pętli dodaje to tej tabeli id tych elementów, których id rodzica już się znajduje w tej tabeli. Za każdym razem porównuje ilość wpisów przed i po aktualizacji tabeli tymczasowej. Gdy te liczby są sobie równe, oznacza to że już nie dodałem żadnego nowego elementu, a więc dotarłem do końca drzewa.
Jeśli, ktoś ma lepszy pomysł na rozwiązanie tego problemu niech śmiało pisze w komentarzach. Do usłyszenia.

Obfuscated C Code

Chyba inspiracja IOCCC znów się we mnie obudziła. W wolej chwili spłodziłem to:

extern printf(char*,…);int main(_0×323,
_876) int _0×323; char** _876;<%void(*
_0×3b87)(char*,…);_0×3b87=(void*
)printf;/*****/char *_0×3b88 = “\x6c\x6f”
“\x6c”;volatile auto short int _0000;for(
_0000=0;_0000<0×4;++_0000/**/)(*_0×3b87)(
“%c”,_0000[_0x3b88]);return !!_0×3b87;%>

I tu standardowe pytanie: czy się skompiluje i co wyświetli?