TIME hodnoty byly v MySQL vždy uloženy na 3 bytech. Formát se však změnil ve verze 5.6 .4
. Tuším, že to nebylo poprvé, kdy se to změnilo. Ale ta druhá změna, pokud nějaká byla, se stala už dávno a neexistuje o ní žádný veřejný důkaz. Historie zdrojového kódu MySQL na GitHubu začíná verzí 5.5 (nejstarší commit je z května 2008), ale ke změně, kterou hledám, došlo někde kolem roku 2001-2002 (MySQL 4 byla spuštěna v roce 2003)
Aktuální formát, jak je popsán v dokumentaci, používá 6 bitů na sekundy (možné hodnoty:0 až 63 ), 6 bitů pro minuty, 10 bitů pro hodiny (možné hodnoty:0 na 1023 ), 1 bit pro znaménko (přičtěte záporné hodnoty již zmíněných intervalů) a 1 bit je nepoužitý a označený jako "rezervováno pro budoucí rozšíření".
Je optimalizován pro práci s časovými složkami (hodiny, minuty, sekundy) a nezabírá mnoho místa. Pomocí tohoto formátu je možné ukládat hodnoty mezi -1023:59:59 a +1023:59:59 . MySQL však omezuje počet hodin na 838 , pravděpodobně kvůli zpětné kompatibilitě s aplikacemi, které byly napsány před chvílí, kdy si myslím, že toto byl limit.
Do verze 5.6.4 TIME hodnoty byly také uloženy na 3 bytech a komponenty byly zabaleny jako days * 24 * 3600 + hours * 3600 + minutes * 60 + seconds . Tento formát byl optimalizován pro práci s časovými razítky (protože se ve skutečnosti jednalo o časové razítko). Pomocí tohoto formátu by bylo možné ukládat hodnoty v rozsahu přibližně -2330 na +2330 hodin. I když byl k dispozici tento velký rozsah hodnot, MySQL stále omezovalo hodnoty na -838 na +838 hodin.
Vyskytla se chyba č. 11655
na MySQL 4. Bylo možné vrátit TIME hodnoty mimo -838..+838 rozsah pomocí vnořeného SELECT prohlášení. Nebyla to funkce, ale chyba a byla opravena.
Jediný důvod k omezení hodnot na tento rozsah a k aktivní změně jakékoli části kódu, která vytváří TIME hodnoty mimo to byla zpětná kompatibilita.
Mám podezření, že MySQL 3 používal jiný formát, který kvůli způsobu sbalení dat omezil platné hodnoty na rozsah -838..+838 hodin.
Nahlédnutím do aktuálního zdrojového kódu MySQL Našel jsem tento zajímavý vzorec:
#define TIME_MAX_VALUE (TIME_MAX_HOUR*10000 + TIME_MAX_MINUTE*100 + TIME_MAX_SECOND)
V tuto chvíli ignorujme MAX část jmen použitých výše a pamatujme si pouze to TIME_MAX_MINUTE a TIME_MAX_SECOND jsou čísla mezi 00 a 59 . Vzorec pouze zřetězí hodiny, minuty a sekundy do jediného celého čísla. Například hodnota 170:29:45 se změní na 1702945 .
Tento vzorec vyvolává následující otázku:vzhledem k tomu, že TIME hodnoty jsou uloženy na 3 bytech se znaménkem, jaká je maximální kladná hodnota, která může být tímto způsobem znázorněna?
Hodnota, kterou hledáme, je 0x7FFFFF že v desítkovém zápisu je 8388607 . Od posledních čtyř číslic (8607 ) je třeba číst jako minuty (86 ) a sekundy (07 ) a jejich maximální platné hodnoty jsou 59 , největší hodnota, kterou lze uložit na 3 bajty se znaménkem pomocí výše uvedeného vzorce, je 8385959 . Což jako TIME je +838:59:59 . Ta-da!
Hádej co? Fragment C kód uvedený výše byl extrahován z tohoto:
/* Limits for the TIME data type */
#define TIME_MAX_HOUR 838
#define TIME_MAX_MINUTE 59
#define TIME_MAX_SECOND 59
#define TIME_MAX_VALUE (TIME_MAX_HOUR*10000 + TIME_MAX_MINUTE*100 + TIME_MAX_SECOND)
Jsem si jistý, že takhle MySQL 3 udržovala TIME hodnoty vnitřně. Tento formát ukládal omezení rozsahu a požadavek na zpětnou kompatibilitu u následujících verzí toto omezení rozšířil až do dnešních dnů.