Pokud jste si už někdy hráli s MaNGOSem a nebo jiným emulátorem, mohli jste se v databázi u postav nebo itemů setkat s položkou data, která obsahuje řadu čísel oddělených mezerou. Tato čisla reprezentují různé atributy postavy/itemu. Proč jsou ale uložena takovým způsobem jakým jsou? Jedná se o z části o historickou záležitost z části lenost a z části neznalost. V dobách začáku vývoje emulátoru se u některých položek nevědělo k čemu přesně slouží a tak místo toho aby v databázi vznikaly sloupečku unk1, unk2, ... unkN se vývojáři raději rozhodli, že veškerá data uloží jako jednu velkou nudli.
To však malinkato komplikuje práci lidem, kteří potřebují prostřednictvím dotazovacího jazyka SQL s těmito daty pracovat. Pokud se podíváte na některé konverzní SQL scripty mezi jednotlivými verzemi herního clienta uvidíte, že se používají na první pohled velice komplikované "čachry" s přikazy pro práci s řetězci. Na ukázku:
UPDATE characters SET
arenaPoints = arena_pending_points +
SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 1278))+2,
length(SUBSTRING_INDEX(data, ' ', 1278+1))-
length(SUBSTRING_INDEX(data, ' ', 1278)) - 1);
Nyní zde předvedu jednoduchou metodu jak tento, na první pohled příšerný, zápis zjednodušit do tvaru:
UPDATE characters SET
arenaPoints = arena_pending_points + data2[1279];
Mnohem přijemnější, že? Takže jak na to?
Trik spočívá v tom, že vytvoříme novou tabulku následujícím způsobem.
CREATE TABLE tmp (
guid bigint NOT NULL,
data bigint[] NOT NULL,
PRIMARY KEY(guid)
);
Teď musíme tuto tabulku naplnit daty. Nejprve se zamyslíme nad tím, jak co nejjednodušeji zkonvertovat čísla oddělená mezerou na datový typ pole. V PostgreSQL je sytaxe pro vložení pole následující:
INSERT INTO tmp(guid, data) VALUES (1, {1,2,3,4});
Jak upravit data do tohoto tvaru? Jednoduše, nejprve z dat odstaníme možné počáteční a koncové přebytečné mezery, nahradíme každou mezeru za čárku, na začátek a konec přidáme složené závorky a donutíme databázový engine aby si myslel, že tento řetězer reprezentuje pole.
-- osekame mezery
UPDATE characters SET data = trim(' ' FROM data);
-- naplnime nasi novou tabulku
INSERT INTO tmp(guid, data)
SELECT guid, CAST('{' || REPLACE(data, ' ', ',') || '}' AS BIGINT[])
FROM characters;
Jak je vidět, celý trik spočívá v této části
CAST('{' || REPLACE(data, ' ', ',') || '}' AS BIGINT[]). Tento dotaz dělá přesně to, že nahradí všechny mezery čárkami, na začátek a konec přidá složené závorky a toto celé přetypuje na typ bigint[].
Na tomto místě bych poznamenal, že pole v PostgreSQL začínají na indexu 1. Proto tedy v příkladu z úvodu indexujeme číslem 1279 místo 1278.
Významy jednotlivých prvků pole pak můžete nalézt v přiloženém souboru UpdateFields.h (verze 3.3.2).
ffffff
This post is exactly what I
Myslím, že moje rady budou