LCOV - code coverage report
Current view: top level - sql/server - sql_datetime.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 156 210 74.3 %
Date: 2021-10-13 02:24:04 Functions: 8 9 88.9 %

          Line data    Source code
       1             : /*
       2             :  * This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0.  If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       5             :  *
       6             :  * Copyright 1997 - July 2008 CWI, August 2008 - 2021 MonetDB B.V.
       7             :  */
       8             : 
       9             : #include "monetdb_config.h"
      10             : #include "sql_datetime.h"
      11             : #include "sql_string.h"
      12             : 
      13             : int
      14        7592 : parse_interval_qualifier(mvc *sql, struct dlist *pers, int *sk, int *ek, int *sp, int *ep)
      15             : {
      16        7592 :         *sk = iyear;
      17        7592 :         *ek = isec;
      18             : 
      19        7592 :         if (pers) {
      20        7592 :                 dlist *s = pers->h->data.lval;
      21             : 
      22        7592 :                 assert(s->h->type == type_int);
      23        7592 :                 *ek = *sk = s->h->data.i_val;
      24        7592 :                 *ep = *sp = s->h->next->data.i_val;
      25             : 
      26        7592 :                 if (dlist_length(pers) == 2) {
      27         137 :                         dlist *e = pers->h->next->data.lval;
      28             : 
      29         137 :                         assert(e->h->type == type_int);
      30         137 :                         *ek = e->h->data.i_val;
      31         137 :                         *ep = e->h->next->data.i_val;
      32             :                 }
      33             :         }
      34        7592 :         if (*sk > *ek) {
      35           0 :                 snprintf(sql->errstr, ERRSIZE, _("End interval field is larger than the start field\n"));
      36           0 :                 return -1;
      37             :         }
      38        7592 :         if ((*sk == iyear || *sk == imonth) && *ek > imonth) {
      39           0 :                 snprintf(sql->errstr, ERRSIZE, _("Correct interval ranges are year-month or day-seconds\n"));
      40           0 :                 return -1;
      41             :         }
      42        7592 :         if (*sk == iyear || *sk == imonth)
      43        2342 :                 return 0;
      44             :         return 1;
      45             : }
      46             : 
      47             : lng
      48           0 : qualifier2multiplier( int sk )
      49             : {
      50             :         lng mul = 1;
      51             : 
      52           0 :         switch (sk) {
      53           0 :         case iyear:
      54             :                 mul *= 12;
      55             :                 /* fall through */
      56             :         case imonth:
      57             :                 break;
      58           0 :         case iday:
      59             :                 mul *= 24;
      60             :                 /* fall through */
      61           0 :         case ihour:
      62           0 :                 mul *= 60;
      63             :                 /* fall through */
      64           0 :         case imin:
      65           0 :                 mul *= 60000;
      66             :                 /* fall through */
      67             :         case isec:
      68             :                 break;
      69             :         default:
      70             :                 return -1;
      71             :         }
      72             :         return mul;
      73             : }
      74             : 
      75             : static int
      76          80 : parse_interval_(mvc *sql, lng sign, char *str, int sk, int ek, int sp, int ep, lng *i)
      77             : {
      78          80 :         char *n = NULL, sep = ':';
      79             :         lng val = 0, mul;
      80             :         int type;
      81             : 
      82          80 :         if (*str == '-') {
      83           0 :                 sign *= -1;
      84           0 :                 str++;
      85             :         }
      86             :         mul = sign;
      87             : 
      88          80 :         switch (sk) {
      89           0 :         case iyear:
      90           0 :                 mul *= 12;
      91             :                 /* fall through */
      92             :         case imonth:
      93             :                 sep = '-';
      94             :                 type = 0;
      95             :                 break;
      96           0 :         case iday:
      97           0 :                 mul *= 24;
      98             :                 sep = ' ';
      99             :                 /* fall through */
     100          12 :         case ihour:
     101          12 :                 mul *= 60;
     102             :                 /* fall through */
     103          49 :         case imin:
     104          49 :                 mul *= 60000;
     105             :                 /* fall through */
     106             :         case isec:
     107             :                 type = 1;
     108             :                 break;
     109           0 :         default:
     110           0 :                 if (sql)
     111           0 :                         snprintf(sql->errstr, ERRSIZE, _("Internal error: parse_interval: bad value for sk (%d)\n"), sk);
     112             :                 return -1;
     113             :         }
     114             : 
     115          80 :         val = strtoll(str, &n, 10);
     116          80 :         if (!n)
     117             :                 return -1;
     118          80 :         if (sk == isec) {
     119             :                 lng msec = 0;
     120           8 :                 val *= 1000;
     121           8 :                 if (n && n[0] == '.') {
     122             :                         char *nn;
     123           0 :                         msec = strtol(n+1, &nn, 10);
     124           0 :                         if (msec && nn) {
     125           0 :                                 ptrdiff_t d = nn-(n+1);
     126           0 :                                 for( ;d<3; d++)
     127           0 :                                         msec *= 10;
     128           0 :                                 for( ;d>3; d--)
     129           0 :                                         msec /= 10;
     130           0 :                                 n = nn;
     131             :                         }
     132             :                 }
     133           8 :                 val += msec;
     134             :         }
     135          80 :         switch (sk) {
     136          23 :         case imonth:
     137          23 :                 if (val >= 12) {
     138           0 :                         snprintf(sql->errstr, ERRSIZE, _("Overflow detected in months (" LLFMT ")\n"), val);
     139           0 :                         return -1;
     140             :                 }
     141             :                 break;
     142          12 :         case ihour:
     143          12 :                 if (val >= 24) {
     144           0 :                         snprintf(sql->errstr, ERRSIZE, _("Overflow detected in hours (" LLFMT ")\n"), val);
     145           0 :                         return -1;
     146             :                 }
     147             :                 break;
     148          37 :         case imin:
     149          37 :                 if (val >= 60) {
     150           1 :                         snprintf(sql->errstr, ERRSIZE, _("Overflow detected in minutes (" LLFMT ")\n"), val);
     151           1 :                         return -1;
     152             :                 }
     153             :                 break;
     154           8 :         case isec:
     155           8 :                 if (val >= 60000) {
     156           0 :                         snprintf(sql->errstr, ERRSIZE, _("Overflow detected in seconds (" LLFMT ")\n"), val);
     157           0 :                         return -1;
     158             :                 }
     159             :                 break;
     160             :         }
     161          79 :         val *= mul;
     162          79 :         *i += val;
     163          79 :         if (ek != sk) {
     164          11 :                 if (*n != sep) {
     165           0 :                         if (sql)
     166           0 :                                 snprintf(sql->errstr, ERRSIZE, _("Interval field seperator \'%c\' missing\n"), sep);
     167           0 :                         return -1;
     168             :                 }
     169          11 :                 return parse_interval_(sql, sign, n + 1, sk + 1, ek, sp, ep, i);
     170             :         } else {
     171             :                 return type;
     172             :         }
     173             : }
     174             : 
     175             : #define MABS(a) (((a) < 0) ? -(a) : (a))
     176             : 
     177             : int
     178        1064 : parse_interval(mvc *sql, lng sign, char *str, int sk, int ek, int sp, int ep, lng *i)
     179             : {
     180        1064 :         char *n = NULL, sep = ':';
     181             :         lng val = 0, mul, msec = 0;
     182             :         int type;
     183             : 
     184        1064 :         if (*str == '-') {
     185         205 :                 sign *= -1;
     186         205 :                 str++;
     187             :         }
     188             :         mul = sign;
     189             : 
     190        1064 :         switch (sk) {
     191          42 :         case iyear:
     192          42 :                 mul *= 12;
     193             :                 /* fall through */
     194             :         case imonth:
     195             :                 sep = '-';
     196             :                 type = 0;
     197             :                 break;
     198         139 :         case iday:
     199         139 :                 mul *= 24;
     200             :                 sep = ' ';
     201             :                 /* fall through */
     202         225 :         case ihour:
     203         225 :                 mul *= 60;
     204             :                 /* fall through */
     205         250 :         case imin:
     206         250 :                 mul *= 60000;
     207             :                 /* fall through */
     208             :         case isec:
     209             :                 type = 1;
     210             :                 break;
     211           0 :         default:
     212           0 :                 if (sql)
     213           0 :                         snprintf(sql->errstr, ERRSIZE, _("Internal error: parse_interval: bad value for sk (%d)\n"), sk);
     214             :                 return -1;
     215             :         }
     216             : 
     217        1064 :         val = strtoll(str, &n, 10);
     218        1064 :         if (!n)
     219             :                 return -1;
     220        1064 :         if (sk == isec) {
     221         432 :                 if (n && n[0] == '.') {
     222             :                         char *nn;
     223           5 :                         msec = strtol(n+1, &nn, 10);
     224           5 :                         if (msec && nn) {
     225           5 :                                 ptrdiff_t d = nn-(n+1);
     226           7 :                                 for( ;d<3; d++)
     227           2 :                                         msec *= 10;
     228           6 :                                 for( ;d>3; d--)
     229           1 :                                         msec /= 10;
     230           5 :                                 n = nn;
     231             :                         }
     232             :                 }
     233             :         }
     234        1064 :         switch (sk) {
     235         382 :         case iyear:
     236             :         case imonth:
     237         382 :                 if (val > (lng) GDK_int_max / MABS(mul)) {
     238           3 :                         if (sql)
     239           0 :                                 snprintf(sql->errstr, ERRSIZE, _("Overflow\n"));
     240           3 :                         return -1;
     241             :                 }
     242             :                 break;
     243         250 :         case iday:
     244             :         case ihour:
     245             :         case imin:
     246         250 :                 if (val > GDK_lng_max / MABS(mul)) {
     247           0 :                         if (sql)
     248           0 :                                 snprintf(sql->errstr, ERRSIZE, _("Overflow\n"));
     249           0 :                         return -1;
     250             :                 }
     251             :                 break;
     252         432 :         case isec:
     253         432 :                 if (val > GDK_lng_max / 1000 / MABS(mul) || (val == GDK_lng_max / 1000 / MABS(mul) && msec > GDK_lng_max % 1000)) {
     254           6 :                         if (sql)
     255           0 :                                 snprintf(sql->errstr, ERRSIZE, _("Overflow\n"));
     256           6 :                         return -1;
     257             :                 }
     258         426 :                 val *= 1000;
     259         426 :                 val += msec;
     260         426 :                 break;
     261             :         default:
     262           0 :                 assert(0);
     263             :         }
     264        1055 :         val *= mul;
     265        1055 :         *i += val;
     266        1055 :         if (ek != sk) {
     267          73 :                 if (*n != sep) {
     268           4 :                         if (sql)
     269           0 :                                 snprintf(sql->errstr, ERRSIZE, _("Interval field seperator \'%c\' missing\n"), sep);
     270           4 :                         return -1;
     271             :                 }
     272          69 :                 return parse_interval_(sql, sign, n + 1, sk + 1, ek, sp, ep, i);
     273             :         } else {
     274         982 :                 if (!n || *n) {
     275          80 :                         if (sql)
     276           0 :                                 snprintf(sql->errstr, ERRSIZE, _("Interval type miss match '%s'\n"), (!n)?"":n);
     277          80 :                         return -1;
     278             :                 }
     279             :                 return type;
     280             :         }
     281             : }
     282             : 
     283         134 : int interval_from_str(char *str, int d, int p, lng *val)
     284             : {
     285         134 :         int sk = digits2sk(d);
     286         134 :         int ek = digits2ek(d);
     287         134 :         *val = 0;
     288         134 :         return parse_interval(NULL, 1, str, sk, ek, p, p, val);
     289             : }
     290             : 
     291             : char *
     292         267 : datetime_field(itype f)
     293             : {
     294         267 :         switch (f) {
     295             :         default:
     296             :         case icentury:
     297             :                 return "century";
     298           7 :         case idecade:
     299           7 :                 return "decade";
     300          94 :         case iyear:
     301          94 :                 return "year";
     302          65 :         case imonth:
     303          65 :                 return "month";
     304          18 :         case iday:
     305          18 :                 return "day";
     306          18 :         case ihour:
     307          18 :                 return "hour";
     308          14 :         case imin:
     309          14 :                 return "minute";
     310          15 :         case isec:
     311          15 :                 return "second";
     312           6 :         case iquarter:
     313           6 :                 return "quarter";
     314           8 :         case iweek:
     315           8 :                 return "week";
     316           0 :         case idow:
     317           0 :                 return "dayofweek";
     318           0 :         case idoy:
     319           0 :                 return "dayofyear";
     320           7 :         case iepoch:
     321           7 :                 return "epoch_ms";
     322             :         }
     323             : }
     324             : 
     325       13175 : int inttype2digits( int sk, int ek )
     326             : {
     327       13175 :         switch(sk) {
     328          65 :         case iyear:
     329          65 :                 if(ek == iyear)
     330          31 :                         return 1;
     331             :                 return 2;
     332             :         case imonth:
     333             :                 return 3;
     334        2416 :         case iday:
     335        2416 :                 switch(ek) {
     336             :                 case iday:
     337             :                         return 4;
     338             :                 case ihour:
     339             :                         return 5;
     340             :                 case imin:
     341             :                         return 6;
     342             :                 default:
     343             :                         return 7;
     344             :                 }
     345        5697 :         case ihour:
     346        5697 :                 switch(ek) {
     347             :                 case ihour:
     348             :                         return 8;
     349          38 :                 case imin:
     350          38 :                         return 9;
     351        5599 :                 default:
     352        5599 :                         return 10;
     353             :                 }
     354          43 :         case imin:
     355          43 :                 if(ek == imin)
     356          33 :                         return 11;
     357             :                 return 12;
     358        2677 :         case isec:
     359        2677 :                 return 13;
     360             :         }
     361           0 :         return 1;
     362             : }
     363             : 
     364         134 : int digits2sk( int digits)
     365             : {
     366             :         int sk = iyear;
     367             : 
     368         134 :         if (digits > 2)
     369             :                 sk = imonth;
     370         134 :         if (digits > 3)
     371             :                 sk = iday;
     372         134 :         if (digits > 7)
     373             :                 sk = ihour;
     374         134 :         if (digits > 10)
     375             :                 sk = imin;
     376         134 :         if (digits > 12)
     377             :                 sk = isec;
     378         134 :         return sk;
     379             : }
     380             : 
     381         135 : int digits2ek( int digits)
     382             : {
     383             :         int ek = iyear;
     384             : 
     385         135 :         if (digits == 2 || digits == 3)
     386             :                 ek = imonth;
     387         135 :         if (digits == 4)
     388             :                 ek = iday;
     389         135 :         if (digits == 5 || digits == 8)
     390             :                 ek = ihour;
     391         135 :         if (digits == 6 || digits == 9 || digits == 11)
     392             :                 ek = imin;
     393         135 :         if (digits == 7 || digits == 10 || digits == 12 || digits == 13)
     394             :                 ek = isec;
     395         135 :         return ek;
     396             : }
     397             : 

Generated by: LCOV version 1.14