@@ -984,96 +984,129 @@ int MADB_CharToSQLNumeric(char *buffer, MADB_Desc *Ard, MADB_DescRecord *ArdReco
984984  int  ret =  0 ;
985985
986986  if  (!buffer  ||  !number )
987+   {
987988    return  ret ;
989+   }
988990
989991  p =  trim (buffer );
990992  MADB_NumericInit (number , ArdRecord );
991993
992-   if  (!(number -> sign =  (* p == '-' ) ? 0  : 1 ))
994+   /* Determining the sign of the number. From now on we dean with unsigned number */ 
995+   if  (!(number -> sign  =  (* p  ==  '-' ) ? 0  : 1 ))
996+   {
993997    p ++ ;
998+   }
999+   /* Empty string - nothing to do*/ 
9941000  if  (!* p )
995-     return  FALSE;
1001+   {
1002+     return  ret ;
1003+   }
9961004
9971005  if  (number -> precision  ==  0 )
9981006  {
9991007    number -> precision =  MADB_DEFAULT_PRECISION ;
10001008  }
10011009
1002-   while  (* p == '0' )
1010+   /* Skipping leading zeroes */ 
1011+   while  (* p  ==  '0' )
10031012  {
1004-     p ++ ;
1013+     ++ p ;
10051014  }
10061015  if  (* p )
10071016  {
10081017    int  i ;
1009-     int  bit , hval , tv , dig , sta , olen ;
1010-     int  tmp_digit =  0 ;
1018+     unsigned int   bit , hval , tv , dig , sta , olen ;
10111019    int  leading_zeros =  0 ;
10121020    char  * dot =  strchr (p , '.' );
10131021    char  digits [100 ];
1014-     short  digits_count =  0 ;
1022+     unsigned short  digits_count =  0 ; /* integer part digits count*/ 
1023+ 
1024+     if  (dot  ==  NULL )
1025+     {
1026+       char *  end =  p ;
1027+       while  (* end  &&  isdigit (0x000000ff  &  * end ))
1028+         ++ end ;
10151029
1016-     /* Overflow check */ 
1017-     if  (number -> precision  >  0  &&  (dot  -  p ) >  number -> precision )
1030+       digits_count =  (unsigned short )(end  -  p );
1031+     }
1032+     else 
1033+     {
1034+       digits_count =  (unsigned short )(dot  -  p );
1035+     }
1036+     /* Overflow checks */ 
1037+     if  (digits_count  >  MADB_DEFAULT_PRECISION  +  1  ) /* 16 bytes of FF make up 39 digits number */ 
1038+     {
10181039      return  MADB_ERR_22003 ;
1019-     
1040+     }
1041+     if  (number -> precision  >  0  &&   digits_count  >  number -> precision )
1042+     {
1043+       /* if scale is negative, and we have just enough zeroes at the end - we are fine, there is no overflow */ 
1044+       if  (number -> scale  <  0  &&  (number -> precision  -  number -> scale ) >= digits_count )
1045+       {
1046+         /* Checking that all digits past presision are '0'. Otherwise - overflow */ 
1047+         for  (i  =  digits_count  -  number -> precision ; i  >  0 ; -- i )
1048+         {
1049+           if  (* (p  +  digits_count  -  i ) !=  '0' )
1050+           {
1051+             return  MADB_ERR_22003 ;
1052+           }
1053+         }
1054+       }
1055+       else 
1056+       {
1057+         return  MADB_ERR_22003 ;
1058+       }
1059+     }
1060+ 
1061+     memcpy (digits , p , digits_count );
1062+ 
10201063    if  (dot  &&  number -> scale  >  0 )
10211064    {
1022-       short  digits_total =  0 , 
1023-             digits_significant =  0 ;
1024-       digits_count =  (short )(dot  -  p );
1025-       memcpy (digits , p , digits_count );
1065+       short  digits_total =  0 ,       /* fractional part total digits */ 
1066+             digits_significant =  0 ; /* fractional part significant digits(not counting 0 at the end) */ 
1067+ 
10261068      p =  dot  +  1 ;
10271069      while  (* p )
10281070      {
10291071        /* ignore non numbers */ 
10301072        if  (!isdigit (0x000000ff  &  * p ))
10311073          break ;
1032-         digits_total ++ ;
1074+         ++ digits_total ;
10331075        /* ignore trailing zeros */ 
10341076        if  (* p  !=  '0' )
10351077        {
10361078          digits_significant =  digits_total ;
10371079        }
1038-         p ++ ;
1080+         ++ p ;
10391081      }
10401082
1041-       if  (digits_count  +  number -> scale  >  number -> precision )
1083+       /* Kinda tricky. let's say precision is 5.2. 1234.5 is fine, 1234.56 is overflow, 123.456 fractional overflow with rounding and warning */ 
1084+       if  (digits_count  +  digits_significant  >  number -> precision  &&  digits_significant  <= number -> scale )
10421085      {
1043-         int   i ;
1086+         return   MADB_ERR_22003 ;
10441087        /* if digits are zero there is no overflow */ 
1045-         for  (i = 1 ; i  <= digits_significant ; i ++ )
1088+         /* for (p= dot +  1; p  <= dot +  digits_significant; ++p )
10461089        { 
1047-           p =  dot  +  i ;
10481090          if (*p != '0') 
1049-             return   MADB_ERR_22003 ; 
1050-         }
1091+              
1092+         }*/  
10511093      }
10521094
1053-       memcpy (digits  +  digits_count , dot  +  1 , digits_significant );
1054-       if  (number -> scale  >  digits_significant )
1095+       if  (digits_significant  >  number -> scale )
1096+       {
1097+         ret =  MADB_ERR_01S07 ;
1098+         memcpy (digits  +  digits_count , dot  +  1 , number -> scale );
1099+       }
1100+       else 
10551101      {
1056-         for  (i =  digits_count  +  digits_significant ; i  <  number -> precision  &&  i  <  digits_count  + number -> scale ; ++ i )
1102+         memcpy (digits  +  digits_count , dot  +  1 , digits_significant );
1103+       
1104+         for  (i =  digits_count  +  digits_significant ; i  <  digits_count  +  number -> scale ; ++ i )
10571105        {
10581106          digits [i ]=  '0' ;
10591107        }
1060-         digits_significant =  number -> scale ;
1061-       }
1062-       digits_count +=  digits_significant ;
1063-     }
1064-     else  
1065-     {
1066-       char  * start =  p ;
1067-       while  (* p  &&  isdigit (0x000000ff  &  * p ))
1068-         p ++ ;
1069-       /* check overflow */ 
1070-       if  (p  -  start  >  number -> precision )
1071-       {
1072-         return  MADB_ERR_22003 ;
10731108      }
1074-       digits_count =  (short )(p  -  start );
1075-       memcpy (digits , start , digits_count );
1076-       number -> scale =  ArdRecord -> Scale  ? ArdRecord -> Scale  : 0 ;
1109+       digits_count +=  number -> scale ;
10771110    }
10781111
10791112    /* Rounding */ 
@@ -1082,20 +1115,25 @@ int MADB_CharToSQLNumeric(char *buffer, MADB_Desc *Ard, MADB_DescRecord *ArdReco
10821115      int64_t  OldVal , Val ;
10831116      int64_t  RoundNumber =  (int64_t )pow (10.0 , - number -> scale );
10841117
1085-       digits [number -> precision ]=  0 ;
1118+       //if (digits_count <= number->precision) 
1119+       {
1120+         digits [digits_count /*number->precision*/ ]=  0 ;
1121+       }
10861122      Val =  _atoi64 (digits );
10871123
10881124      OldVal =  Val ;
10891125      Val =  (Val  +  RoundNumber  / 2 ) / RoundNumber  *  RoundNumber ;
10901126      if  (OldVal  !=  Val )
1127+       {
10911128        return  MADB_ERR_22003 ;
1092-       _snprintf (digits , sizeof (digits ), "%lld" , Val );
1129+       }
1130+       _snprintf (digits , sizeof (digits ), "%lld" , Val /RoundNumber );
10931131      digits_count =  (short )strlen (digits );
10941132      if  (digits_count  >  number -> precision )
10951133        return  MADB_ERR_22003 ;
10961134    }
10971135
1098-     digits_count =  MIN (digits_count , MADB_DEFAULT_PRECISION );
1136+     digits_count =  MIN (digits_count , MADB_DEFAULT_PRECISION   +   1 );
10991137    for  (hval  =  0 , bit  =  1L , sta  =  0 , olen  =  0 ; sta  <  digits_count ;)
11001138    {
11011139      for  (dig  =  0 , i  =  sta ; i  <  digits_count ; i ++ )
@@ -1111,20 +1149,28 @@ int MADB_CharToSQLNumeric(char *buffer, MADB_Desc *Ard, MADB_DescRecord *ArdReco
11111149      bit  <<= 1 ;
11121150      if  (bit  >= (1L  << 8 ))
11131151      {
1114-         number -> val [olen ++ ] =  hval ;
1115-         hval  =  0 ;
1116-         bit  =  1L ;
1117-         if  (olen  >= SQL_MAX_NUMERIC_LEN  -  1 )
1152+         if  (olen  >= SQL_MAX_NUMERIC_LEN )
11181153        {
11191154          //number->scale = sta - number->precision; 
1120-           // ret= MADB_ERR_22003;
1155+           ret =  MADB_ERR_22003 ;
11211156          break ;
11221157        }
1158+         number -> val [olen ++ ] =  hval ;
1159+         hval  =  0 ;
1160+         bit  =  1L ;
1161+ 
11231162      } 
11241163    }
1125-     if  (hval  &&   olen   <   SQL_MAX_NUMERIC_LEN   -   1 )
1164+     if  (hval  !=   0 )
11261165    {
1127-       number -> val [olen ++ ] =  hval ;
1166+       if  (olen  <  SQL_MAX_NUMERIC_LEN )
1167+       {
1168+         number -> val [olen ++ ] =  hval ;
1169+       }
1170+       else 
1171+       {
1172+         ret =  MADB_ERR_22003 ;
1173+       }
11281174    }
11291175  } 
11301176  return  ret ;
0 commit comments