Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit319902d

Browse files
committed
Fix to_number for the case of a trailing S.
Karel Zak
1 parent5fef3c6 commit319902d

File tree

3 files changed

+139
-46
lines changed

3 files changed

+139
-46
lines changed

‎src/backend/utils/adt/formatting.c

Lines changed: 137 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/* -----------------------------------------------------------------------
22
* formatting.c
33
*
4-
* $PostgreSQL: pgsql/src/backend/utils/adt/formatting.c,v 1.79 2004/10/13 01:25:11 neilc Exp $
4+
* $PostgreSQL: pgsql/src/backend/utils/adt/formatting.c,v 1.80 2004/10/28 18:55:06 tgl Exp $
55
*
66
*
77
* Portions Copyright (c) 1999-2004, PostgreSQL Global Development Group
@@ -853,7 +853,8 @@ typedef struct NUMProc
853853
num_pre,/* space before first number*/
854854

855855
read_dec,/* to_number - was read dec. point*/
856-
read_post;/* to_number - number of dec. digit */
856+
read_post,/* to_number - number of dec. digit */
857+
read_pre;/* to_number - number non-dec. digit */
857858

858859
char*number,/* string with number*/
859860
*number_p,/* pointer to current number position */
@@ -3623,15 +3624,18 @@ get_last_relevant_decnum(char *num)
36233624
staticvoid
36243625
NUM_numpart_from_char(NUMProc*Np,intid,intplen)
36253626
{
3626-
3627+
boolisread= FALSE;
3628+
36273629
#ifdefDEBUG_TO_FROM_CHAR
3628-
elog(DEBUG_elog_output," --- scan start --- ");
3630+
elog(DEBUG_elog_output," --- scan start --- id=%s",
3631+
(id==NUM_0||id==NUM_9) ?"NUM_0/9" :id==NUM_DEC ?"NUM_DEC" :"???");
36293632
#endif
36303633

36313634
if (*Np->inout_p==' ')
36323635
Np->inout_p++;
36333636

36343637
#defineOVERLOAD_TEST(Np->inout_p >= Np->inout + plen)
3638+
#defineAMOUNT_TEST(_s)(plen-(Np->inout_p-Np->inout) >= _s)
36353639

36363640
if (*Np->inout_p==' ')
36373641
Np->inout_p++;
@@ -3640,68 +3644,73 @@ NUM_numpart_from_char(NUMProc *Np, int id, int plen)
36403644
return;
36413645

36423646
/*
3643-
* read sign
3647+
* read sign before number
36443648
*/
3645-
if (*Np->number==' '&& (id==NUM_0||id==NUM_9||NUM_S))
3649+
if (*Np->number==' '&& (id==NUM_0||id==NUM_9 )&&
3650+
(Np->read_pre+Np->read_post)==0)
36463651
{
36473652

36483653
#ifdefDEBUG_TO_FROM_CHAR
3649-
elog(DEBUG_elog_output,"Try read sign (%c)",*Np->inout_p);
3654+
elog(DEBUG_elog_output,"Try read sign (%c), locale positive: %s, negative: %s",
3655+
*Np->inout_p,Np->L_positive_sign,Np->L_negative_sign);
36503656
#endif
36513657

36523658
/*
36533659
* locale sign
36543660
*/
3655-
if (IS_LSIGN(Np->Num))
3661+
if (IS_LSIGN(Np->Num)&&Np->Num->lsign==NUM_LSIGN_PRE)
36563662
{
3657-
3658-
intx=strlen(Np->L_negative_sign);
3659-
3663+
intx=0;
36603664
#ifdefDEBUG_TO_FROM_CHAR
3661-
elog(DEBUG_elog_output,"Try read locale sign (%c)",*Np->inout_p);
3665+
elog(DEBUG_elog_output,"Try read localepre-sign (%c)",*Np->inout_p);
36623666
#endif
3663-
if (!strncmp(Np->inout_p,Np->L_negative_sign,x))
3667+
if ((x=strlen(Np->L_negative_sign))&&
3668+
AMOUNT_TEST(x)&&
3669+
strncmp(Np->inout_p,Np->L_negative_sign,x)==0)
36643670
{
3665-
Np->inout_p+=x-1;
3671+
Np->inout_p+=x;
36663672
*Np->number='-';
3667-
return;
36683673
}
3669-
3670-
x=strlen(Np->L_positive_sign);
3671-
if (!strncmp(Np->inout_p,Np->L_positive_sign,x))
3674+
elseif ((x=strlen(Np->L_positive_sign))&&
3675+
AMOUNT_TEST(x)&&
3676+
strncmp(Np->inout_p,Np->L_positive_sign,x)==0)
36723677
{
3673-
Np->inout_p+=x-1;
3678+
Np->inout_p+=x;
36743679
*Np->number='+';
3675-
return;
36763680
}
36773681
}
3678-
3682+
else
3683+
{
36793684
#ifdefDEBUG_TO_FROM_CHAR
3680-
elog(DEBUG_elog_output,"Try read simple sign (%c)",*Np->inout_p);
3685+
elog(DEBUG_elog_output,"Try read simple sign (%c)",*Np->inout_p);
36813686
#endif
3687+
/*
3688+
* simple + - < >
3689+
*/
3690+
if (*Np->inout_p=='-'|| (IS_BRACKET(Np->Num)&&
3691+
*Np->inout_p=='<'))
3692+
{
36823693

3683-
/*
3684-
* simple + - < >
3685-
*/
3686-
if (*Np->inout_p=='-'|| (IS_BRACKET(Np->Num)&&
3687-
*Np->inout_p=='<'))
3688-
{
3689-
3690-
*Np->number='-';/* set - */
3691-
Np->inout_p++;
3694+
*Np->number='-';/* set - */
3695+
Np->inout_p++;
36923696

3693-
}
3694-
elseif (*Np->inout_p=='+')
3695-
{
3697+
}
3698+
elseif (*Np->inout_p=='+')
3699+
{
36963700

3697-
*Np->number='+';/* set + */
3698-
Np->inout_p++;
3701+
*Np->number='+';/* set + */
3702+
Np->inout_p++;
3703+
}
36993704
}
37003705
}
37013706

37023707
if (OVERLOAD_TEST)
37033708
return;
3704-
3709+
3710+
#ifdefDEBUG_TO_FROM_CHAR
3711+
elog(DEBUG_elog_output,"Scan for numbers (%c), current number: '%s'",*Np->inout_p,Np->number);
3712+
#endif
3713+
37053714
/*
37063715
* read digit
37073716
*/
@@ -3716,16 +3725,19 @@ NUM_numpart_from_char(NUMProc *Np, int id, int plen)
37163725

37173726
if (Np->read_dec)
37183727
Np->read_post++;
3728+
else
3729+
Np->read_pre++;
37193730

3731+
isread= TRUE;
3732+
37203733
#ifdefDEBUG_TO_FROM_CHAR
37213734
elog(DEBUG_elog_output,"Read digit (%c)",*Np->inout_p);
37223735
#endif
3723-
3724-
/*
3725-
* read decimal point
3726-
*/
3736+
/*
3737+
* read decimal point
3738+
*/
37273739
}
3728-
elseif (IS_DECIMAL(Np->Num))
3740+
elseif (IS_DECIMAL(Np->Num)&&Np->read_dec== FALSE)
37293741
{
37303742

37313743
#ifdefDEBUG_TO_FROM_CHAR
@@ -3737,7 +3749,7 @@ NUM_numpart_from_char(NUMProc *Np, int id, int plen)
37373749
*Np->number_p='.';
37383750
Np->number_p++;
37393751
Np->read_dec= TRUE;
3740-
3752+
isread= TRUE;
37413753
}
37423754
else
37433755
{
@@ -3747,15 +3759,90 @@ NUM_numpart_from_char(NUMProc *Np, int id, int plen)
37473759
elog(DEBUG_elog_output,"Try read locale point (%c)",
37483760
*Np->inout_p);
37493761
#endif
3750-
if (!strncmp(Np->inout_p,Np->decimal,x))
3762+
if (x&&AMOUNT_TEST(x)&&strncmp(Np->inout_p,Np->decimal,x)==0)
37513763
{
37523764
Np->inout_p+=x-1;
37533765
*Np->number_p='.';
37543766
Np->number_p++;
37553767
Np->read_dec= TRUE;
3768+
isread= TRUE;
37563769
}
37573770
}
37583771
}
3772+
3773+
if (OVERLOAD_TEST)
3774+
return;
3775+
3776+
/*
3777+
* Read sign behind "last" number
3778+
*
3779+
* We need sign detection because determine exact position of
3780+
* post-sign is difficult:
3781+
*
3782+
* FM9999.9999999S -> 123.001-
3783+
* 9.9S-> .5-
3784+
* FM9.999999MI-> 5.01-
3785+
*/
3786+
if (*Np->number==' '&&Np->read_pre+Np->read_post>0)
3787+
{
3788+
/*
3789+
* locale sign (NUM_S) is always anchored behind a last number, if:
3790+
*- locale sign expected
3791+
*- last read char was NUM_0/9 or NUM_DEC
3792+
*- and next char is not digit
3793+
*/
3794+
if (IS_LSIGN(Np->Num)&&isread&&
3795+
(Np->inout_p+1) <=Np->inout+plen&&
3796+
isdigit(*(Np->inout_p+1))==0)
3797+
{
3798+
intx;
3799+
char*tmp=Np->inout_p++;
3800+
3801+
#ifdefDEBUG_TO_FROM_CHAR
3802+
elog(DEBUG_elog_output,"Try read locale post-sign (%c)",*Np->inout_p);
3803+
#endif
3804+
if ((x=strlen(Np->L_negative_sign))&&
3805+
AMOUNT_TEST(x)&&
3806+
strncmp(Np->inout_p,Np->L_negative_sign,x)==0)
3807+
{
3808+
Np->inout_p+=x-1;/* -1 .. NUM_processor() do inout_p++ */
3809+
*Np->number='-';
3810+
}
3811+
elseif ((x=strlen(Np->L_positive_sign))&&
3812+
AMOUNT_TEST(x)&&
3813+
strncmp(Np->inout_p,Np->L_positive_sign,x)==0)
3814+
{
3815+
Np->inout_p+=x-1;/* -1 .. NUM_processor() do inout_p++ */
3816+
*Np->number='+';
3817+
}
3818+
if (*Np->number==' ')
3819+
/* no sign read */
3820+
Np->inout_p=tmp;
3821+
}
3822+
3823+
/*
3824+
* try read non-locale sign, it's happen only if format is not exact
3825+
* and we cannot determine sign position of MI/PL/SG, an example:
3826+
*
3827+
* FM9.999999MI -> 5.01-
3828+
*
3829+
* if (.... && IS_LSIGN(Np->Num)==FALSE) prevents read wrong formats
3830+
* like to_number('1 -', '9S') where sign is not anchored to last number.
3831+
*/
3832+
elseif (isread==FALSE&&IS_LSIGN(Np->Num)==FALSE&&
3833+
(IS_PLUS(Np->Num)||IS_MINUS(Np->Num)))
3834+
{
3835+
#ifdefDEBUG_TO_FROM_CHAR
3836+
elog(DEBUG_elog_output,"Try read simple post-sign (%c)",*Np->inout_p);
3837+
#endif
3838+
/*
3839+
* simple + -
3840+
*/
3841+
if (*Np->inout_p=='-'||*Np->inout_p=='+')
3842+
/* NUM_processor() do inout_p++ */
3843+
*Np->number=*Np->inout_p;
3844+
}
3845+
}
37593846
}
37603847

37613848
#defineIS_PREDEC_SPACE(_n) \
@@ -3978,6 +4065,7 @@ NUM_processor(FormatNode *node, NUMDesc *Num, char *inout, char *number,
39784065
Np->inout=inout;
39794066
Np->last_relevant=NULL;
39804067
Np->read_post=0;
4068+
Np->read_pre=0;
39814069
Np->read_dec= FALSE;
39824070

39834071
if (Np->Num->zero_start)
@@ -4130,6 +4218,11 @@ NUM_processor(FormatNode *node, NUMDesc *Num, char *inout, char *number,
41304218
{
41314219
/*
41324220
* Create/reading digit/zero/blank/sing
4221+
*
4222+
* 'NUM_S' note:
4223+
* The locale sign is anchored to number and we read/write it
4224+
* when we work with first or last number (NUM_0/NUM_9). This
4225+
* is reason why NUM_S missing in follow switch().
41334226
*/
41344227
switch (n->key->id)
41354228
{

‎src/test/regress/expected/numeric.out

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1191,7 +1191,7 @@ SELECT '' AS to_number_12, to_number('.01-', '99.99S');
11911191
| -0.01
11921192
(1 row)
11931193

1194-
SELECT '' AS to_number_13, to_number(' . 0 1-', ' 9 9 . 9 9 S');
1194+
SELECT '' AS to_number_13, to_number(' . 0 1-', ' 9 9 . 9 9 S');
11951195
to_number_13 | to_number
11961196
--------------+-----------
11971197
| -0.01

‎src/test/regress/sql/numeric.sql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -760,7 +760,7 @@ SELECT '' AS to_number_9, to_number('.0', '99999999.99999999');
760760
SELECT''AS to_number_10, to_number('0','99.99');
761761
SELECT''AS to_number_11, to_number('.-01','S99.99');
762762
SELECT''AS to_number_12, to_number('.01-','99.99S');
763-
SELECT''AS to_number_13, to_number(' . 0 1-',' 9 9 . 9 9 S');
763+
SELECT''AS to_number_13, to_number(' . 0 1-',' 9 9 . 9 9 S');
764764

765765
--
766766
-- Input syntax

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp