Changeset: c497a8bb067e for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/c497a8bb067e
Modified Files:
        gdk/gdk_atoms.c
        sql/server/sql_decimal.c
        sql/server/sql_parser.y
Branch: Mar2025
Log Message:

Remove arbitrary limit of 50 characters in a number.


diffs (164 lines):

diff --git a/gdk/gdk_atoms.c b/gdk/gdk_atoms.c
--- a/gdk/gdk_atoms.c
+++ b/gdk/gdk_atoms.c
@@ -649,11 +649,12 @@ numFromStr(const char *src, size_t *len,
        int sign = 1;
 
        /* a valid number has the following syntax:
-        * [-+]?[0-9]+([eE][0-9]+)?(LL)? -- PCRE syntax, or in other words
+        * [-+]?[0-9]+(_[0-9]+)*([eE][0-9]+(_[0-9]+)*)?(LL)? -- PCRE syntax, or 
in other words
         * optional sign, one or more digits, optional exponent, optional LL
         * the exponent has the following syntax:
         * lower or upper case letter E, one or more digits
-        * embedded spaces are not allowed
+        * embedded spaces are not allowed but embedded underscores are
+        * (but not more than one consecutively)
         * the optional LL at the end are only allowed for lng and hge
         * values */
        atommem(sz);
@@ -699,6 +700,8 @@ numFromStr(const char *src, size_t *len,
                }
                base = 10 * base + dig;
                p++;
+               if (*p == '_' && GDKisdigit(p[1]))
+                       p++;
        } while (GDKisdigit(*p));
        if ((*p == 'e' || *p == 'E') && GDKisdigit(p[1])) {
                p++;
@@ -717,6 +720,8 @@ numFromStr(const char *src, size_t *len,
                                        goto overflow;
                                }
                                p++;
+                               if (*p == '_' && GDKisdigit(p[1]))
+                                       p++;
                        } while (GDKisdigit(*p));
                        if (base > maxdiv[exp].maxval) {
                                /* overflow */
diff --git a/sql/server/sql_decimal.c b/sql/server/sql_decimal.c
--- a/sql/server/sql_decimal.c
+++ b/sql/server/sql_decimal.c
@@ -60,7 +60,7 @@ fractional_sep_first_opp:
                *has_errors = 1;
                goto end_state;
        }
-       while (*dec == '0'){
+       while (*dec == '0' || *dec == '_'){
                // skip leading zeros in preceding digits, e.g. '0004563.1234' 
=> '4563.1234'
                dec++;
                if (*dec == '.') {
@@ -68,7 +68,9 @@ fractional_sep_first_opp:
                        goto fractional_sep_first_opp;
                }
        }
-       for (; *dec && (isdigit((unsigned char) *dec)); dec++) {
+       for (; *dec && (*dec == '_' || isdigit((unsigned char) *dec)); dec++) {
+               if (*dec == '_')
+                       continue;
                if (res > max0 || (res == max0 && *dec - '0' > max1)) {
                        *has_errors = 1;
                        return 0;
@@ -87,7 +89,9 @@ fractional_sep_first_opp:
 trailing_digits:
        if (!isdigit((unsigned char) *dec))
                goto trailing_whitespace;
-       for (; *dec && (isdigit((unsigned char) *dec)); dec++) {
+       for (; *dec && (*dec == '_' || isdigit((unsigned char) *dec)); dec++) {
+               if (*dec == '_')
+                       continue;
                if (res > max0 || (res == max0 && *dec - '0' > max1)) {
                        *has_errors = 1;
                        return 0;
diff --git a/sql/server/sql_parser.y b/sql/server/sql_parser.y
--- a/sql/server/sql_parser.y
+++ b/sql/server/sql_parser.y
@@ -5480,18 +5480,7 @@ literal:
                }
  |  sqlINT
                { 
-                       char filtered[50] = {0};
-                       int j = 0;
-                       for (int i = 0; i < 50; i++) {
-                               char d = $1[i];
-                               if (!d)
-                                       break;
-                               else if (d == '_')
-                                       continue;
-                               filtered[j] = d;
-                               ++j;
-                       }
-                       int err = 0;
+                 int err = 0;
 #ifdef HAVE_HGE
                  hge value, *p = &value;
                  size_t len = sizeof(hge);
@@ -5502,10 +5491,10 @@ literal:
                  sql_subtype t;
 
 #ifdef HAVE_HGE
-                 if (hgeFromStr(filtered, &len, &p, false) < 0 || 
is_hge_nil(value))
+                 if (hgeFromStr($1, &len, &p, false) < 0 || is_hge_nil(value))
                        err = 2;
 #else
-                 if (lngFromStr(filtered, &len, &p, false) < 0 || 
is_lng_nil(value))
+                 if (lngFromStr($1, &len, &p, false) < 0 || is_lng_nil(value))
                        err = 2;
 #endif
 
@@ -5539,19 +5528,7 @@ literal:
                }
  |  INTNUM
                {
-                       char filtered[51] = {0};
-                       int j = 0;
-                       for (int i = 0; i < 50; i++) {
-                               char d = $1[i];
-                               if (!d)
-                                       break;
-                               else if (d == '_')
-                                       continue;
-                               filtered[j] = d;
-                               ++j;
-                       }
-                       filtered[j] = 0;
-                       char *s = filtered;
+                       char *s = $1;
 
                        int digits;
                        int scale;
@@ -5587,23 +5564,27 @@ literal:
                }
  |  APPROXNUM
                {
-                 char filtered[50] = {0};
+                 char *filtered = strdup($1);
+                 if (filtered == NULL) {
+                         sqlformaterror(m, SQLSTATE(HY013) "Malloc failed");
+                         $$ = NULL;
+                         YYABORT;
+                 }
                  int j = 0;
-                 for (int i = 0; i < 50; i++) {
-                               char d = $1[i];
-                               if (!d)
-                                       break;
-                               else if (d == '_')
-                       continue;
-                       filtered[j] = d;
-                       ++j;
+                 for (int i = 0; $1[i]; i++) {
+                         char d = $1[i];
+                         if (d == '_')
+                                 continue;
+                         filtered[j++] = d;
                  }
+                 filtered[j] = 0;
                  sql_subtype t;
                  char *p = filtered;
                  double val;
 
                  errno = 0;
                  val = strtod(filtered,&p);
+                 free(filtered);
                  if (p == filtered || is_dbl_nil(val) || (errno == ERANGE && 
(val < -1 || val > 1))) {
                        sqlformaterror(m, SQLSTATE(22003) "Double value too 
large or not a number (%s)", $1);
                        $$ = NULL;
_______________________________________________
checkin-list mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to