De TIME
waarden werden altijd opgeslagen op 3 bytes in MySQL. Maar de indeling is gewijzigd op versie 5.6 .4
. Ik vermoed dat dit niet de eerste keer was dat het veranderde. Maar de andere verandering, als die er was, is lang geleden gebeurd en er is geen openbaar bewijs van. De geschiedenis van de MySQL-broncode op GitHub begint met versie 5.5 (de oudste commit is van mei 2008) maar de verandering waarnaar ik op zoek ben, gebeurde ergens rond 2001-2002 (MySQL 4 werd gelanceerd in 2003)
Het huidige formaat, zoals beschreven in de documentatie, gebruikt 6 bits voor seconden (mogelijke waarden:0
tot 63
), 6 bits voor minuten, 10 bits voor uren (mogelijke waarden:0
tot 1023
), 1 bit voor teken (voeg de negatieve waarden van de reeds genoemde intervallen toe) en 1 bit is ongebruikt en heeft het label "gereserveerd voor toekomstige extensies".
Het is geoptimaliseerd voor het werken met tijdcomponenten (uren, minuten, seconden) en verspilt niet veel ruimte. Met dit formaat is het mogelijk om waarden op te slaan tussen -1023:59:59
en +1023:59:59
. MySQL beperkt het aantal uren echter tot 838
, waarschijnlijk voor achterwaartse compatibiliteit met applicaties die een tijdje geleden zijn geschreven, terwijl ik denk dat dit de limiet was.
Tot versie 5.6.4, de TIME
waarden werden ook opgeslagen op 3 bytes en de componenten werden verpakt als days * 24 * 3600 + hours * 3600 + minutes * 60 + seconds
. Dit formaat is geoptimaliseerd voor het werken met tijdstempels (omdat het in feite een tijdstempel was). Met dit formaat zou het mogelijk zijn om waarden op te slaan in het bereik van ongeveer -2330
tot +2330
uur. Hoewel dit grote bereik aan waarden beschikbaar was, beperkte MySQL de waarden nog steeds tot -838
tot +838
uur.
Er was bug #11655
op MySQL 4. Het was mogelijk om TIME
te retourneren waarden buiten de -838..+838
bereik met behulp van geneste SELECT
verklaringen. Het was geen functie maar een bug en het is opgelost.
De enige reden om de waarden te beperken tot dit bereik en om elk stukje code actief te wijzigen dat TIME
produceert waarden daarbuiten was achterwaartse compatibiliteit.
Ik vermoed dat MySQL 3 een ander formaat gebruikte dat, vanwege de manier waarop de gegevens waren verpakt, de geldige waarden beperkte tot het bereik -838..+838
uur.
Door te kijken naar de huidige broncode van MySQL Ik vond deze interessante formule:
#define TIME_MAX_VALUE (TIME_MAX_HOUR*10000 + TIME_MAX_MINUTE*100 + TIME_MAX_SECOND)
Laten we de MAX
. voorlopig negeren een deel van de hierboven gebruikte namen en laten we alleen die TIME_MAX_MINUTE
. onthouden en TIME_MAX_SECOND
zijn getallen tussen 00
en 59
. De formule voegt alleen de uren, minuten en seconden samen in één geheel getal. Bijvoorbeeld de waarde 170:29:45
wordt 1702945
.
Deze formule roept de volgende vraag op:aangezien de TIME
waarden worden opgeslagen op 3 bytes met teken, wat is de maximale positieve waarde die op deze manier kan worden weergegeven?
De waarde die we zoeken is 0x7FFFFF
dat in decimale notatie is 8388607
. Sinds de laatste vier cijfers (8607
) moet worden gelezen als minuten (86
) en seconden (07
) en hun maximale geldige waarden zijn 59
, de grootste waarde die kan worden opgeslagen op 3 bytes met teken met behulp van de bovenstaande formule is 8385959
. Wat, als TIME
is +838:59:59
. Ta-da!
Raad eens? Het fragment van C
bovenstaande code is hieruit geëxtraheerd:
/* 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)
Ik weet zeker dat dit is hoe MySQL 3 de TIME
. bijhield waarden intern. Dit formaat legde de beperking van het bereik op, en de eis van achterwaartse compatibiliteit voor de volgende versies verspreidde de beperking tot onze dagen.