Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
P
Postgres FD Implementation
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Abuhujair Javed
Postgres FD Implementation
Commits
319902dc
Commit
319902dc
authored
Oct 28, 2004
by
Tom Lane
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fix to_number for the case of a trailing S.
Karel Zak
parent
5fef3c6e
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
139 additions
and
46 deletions
+139
-46
src/backend/utils/adt/formatting.c
src/backend/utils/adt/formatting.c
+137
-44
src/test/regress/expected/numeric.out
src/test/regress/expected/numeric.out
+1
-1
src/test/regress/sql/numeric.sql
src/test/regress/sql/numeric.sql
+1
-1
No files found.
src/backend/utils/adt/formatting.c
View file @
319902dc
/* -----------------------------------------------------------------------
* formatting.c
*
* $PostgreSQL: pgsql/src/backend/utils/adt/formatting.c,v 1.
79 2004/10/13 01:25:11 neilc
Exp $
* $PostgreSQL: pgsql/src/backend/utils/adt/formatting.c,v 1.
80 2004/10/28 18:55:06 tgl
Exp $
*
*
* Portions Copyright (c) 1999-2004, PostgreSQL Global Development Group
...
...
@@ -853,7 +853,8 @@ typedef struct NUMProc
num_pre
,
/* space before first number */
read_dec
,
/* to_number - was read dec. point */
read_post
;
/* to_number - number of dec. digit */
read_post
,
/* to_number - number of dec. digit */
read_pre
;
/* to_number - number non-dec. digit */
char
*
number
,
/* string with number */
*
number_p
,
/* pointer to current number position */
...
...
@@ -3623,15 +3624,18 @@ get_last_relevant_decnum(char *num)
static
void
NUM_numpart_from_char
(
NUMProc
*
Np
,
int
id
,
int
plen
)
{
bool
isread
=
FALSE
;
#ifdef DEBUG_TO_FROM_CHAR
elog
(
DEBUG_elog_output
,
" --- scan start --- "
);
elog
(
DEBUG_elog_output
,
" --- scan start --- id=%s"
,
(
id
==
NUM_0
||
id
==
NUM_9
)
?
"NUM_0/9"
:
id
==
NUM_DEC
?
"NUM_DEC"
:
"???"
);
#endif
if
(
*
Np
->
inout_p
==
' '
)
Np
->
inout_p
++
;
#define OVERLOAD_TEST (Np->inout_p >= Np->inout + plen)
#define AMOUNT_TEST(_s) (plen-(Np->inout_p-Np->inout) >= _s)
if
(
*
Np
->
inout_p
==
' '
)
Np
->
inout_p
++
;
...
...
@@ -3640,68 +3644,73 @@ NUM_numpart_from_char(NUMProc *Np, int id, int plen)
return
;
/*
* read sign
* read sign
before number
*/
if
(
*
Np
->
number
==
' '
&&
(
id
==
NUM_0
||
id
==
NUM_9
||
NUM_S
))
if
(
*
Np
->
number
==
' '
&&
(
id
==
NUM_0
||
id
==
NUM_9
)
&&
(
Np
->
read_pre
+
Np
->
read_post
)
==
0
)
{
#ifdef DEBUG_TO_FROM_CHAR
elog
(
DEBUG_elog_output
,
"Try read sign (%c)"
,
*
Np
->
inout_p
);
elog
(
DEBUG_elog_output
,
"Try read sign (%c), locale positive: %s, negative: %s"
,
*
Np
->
inout_p
,
Np
->
L_positive_sign
,
Np
->
L_negative_sign
);
#endif
/*
* locale sign
*/
if
(
IS_LSIGN
(
Np
->
Num
))
if
(
IS_LSIGN
(
Np
->
Num
)
&&
Np
->
Num
->
lsign
==
NUM_LSIGN_PRE
)
{
int
x
=
strlen
(
Np
->
L_negative_sign
);
int
x
=
0
;
#ifdef DEBUG_TO_FROM_CHAR
elog
(
DEBUG_elog_output
,
"Try read locale sign (%c)"
,
*
Np
->
inout_p
);
elog
(
DEBUG_elog_output
,
"Try read locale
pre-
sign (%c)"
,
*
Np
->
inout_p
);
#endif
if
(
!
strncmp
(
Np
->
inout_p
,
Np
->
L_negative_sign
,
x
))
if
((
x
=
strlen
(
Np
->
L_negative_sign
))
&&
AMOUNT_TEST
(
x
)
&&
strncmp
(
Np
->
inout_p
,
Np
->
L_negative_sign
,
x
)
==
0
)
{
Np
->
inout_p
+=
x
-
1
;
Np
->
inout_p
+=
x
;
*
Np
->
number
=
'-'
;
return
;
}
x
=
strlen
(
Np
->
L_positive_sign
);
if
(
!
strncmp
(
Np
->
inout_p
,
Np
->
L_positive_sign
,
x
)
)
else
if
((
x
=
strlen
(
Np
->
L_positive_sign
))
&&
AMOUNT_TEST
(
x
)
&&
strncmp
(
Np
->
inout_p
,
Np
->
L_positive_sign
,
x
)
==
0
)
{
Np
->
inout_p
+=
x
-
1
;
Np
->
inout_p
+=
x
;
*
Np
->
number
=
'+'
;
return
;
}
}
else
{
#ifdef DEBUG_TO_FROM_CHAR
elog
(
DEBUG_elog_output
,
"Try read simple sign (%c)"
,
*
Np
->
inout_p
);
elog
(
DEBUG_elog_output
,
"Try read simple sign (%c)"
,
*
Np
->
inout_p
);
#endif
/*
* simple + - < >
*/
if
(
*
Np
->
inout_p
==
'-'
||
(
IS_BRACKET
(
Np
->
Num
)
&&
*
Np
->
inout_p
==
'<'
))
{
/*
* simple + - < >
*/
if
(
*
Np
->
inout_p
==
'-'
||
(
IS_BRACKET
(
Np
->
Num
)
&&
*
Np
->
inout_p
==
'<'
))
{
*
Np
->
number
=
'-'
;
/* set - */
Np
->
inout_p
++
;
*
Np
->
number
=
'-'
;
/* set - */
Np
->
inout_p
++
;
}
else
if
(
*
Np
->
inout_p
==
'+'
)
{
}
else
if
(
*
Np
->
inout_p
==
'+'
)
{
*
Np
->
number
=
'+'
;
/* set + */
Np
->
inout_p
++
;
*
Np
->
number
=
'+'
;
/* set + */
Np
->
inout_p
++
;
}
}
}
if
(
OVERLOAD_TEST
)
return
;
#ifdef DEBUG_TO_FROM_CHAR
elog
(
DEBUG_elog_output
,
"Scan for numbers (%c), current number: '%s'"
,
*
Np
->
inout_p
,
Np
->
number
);
#endif
/*
* read digit
*/
...
...
@@ -3716,16 +3725,19 @@ NUM_numpart_from_char(NUMProc *Np, int id, int plen)
if
(
Np
->
read_dec
)
Np
->
read_post
++
;
else
Np
->
read_pre
++
;
isread
=
TRUE
;
#ifdef DEBUG_TO_FROM_CHAR
elog
(
DEBUG_elog_output
,
"Read digit (%c)"
,
*
Np
->
inout_p
);
#endif
/*
* read decimal point
*/
/*
* read decimal point
*/
}
else
if
(
IS_DECIMAL
(
Np
->
Num
))
else
if
(
IS_DECIMAL
(
Np
->
Num
)
&&
Np
->
read_dec
==
FALSE
)
{
#ifdef DEBUG_TO_FROM_CHAR
...
...
@@ -3737,7 +3749,7 @@ NUM_numpart_from_char(NUMProc *Np, int id, int plen)
*
Np
->
number_p
=
'.'
;
Np
->
number_p
++
;
Np
->
read_dec
=
TRUE
;
isread
=
TRUE
;
}
else
{
...
...
@@ -3747,15 +3759,90 @@ NUM_numpart_from_char(NUMProc *Np, int id, int plen)
elog
(
DEBUG_elog_output
,
"Try read locale point (%c)"
,
*
Np
->
inout_p
);
#endif
if
(
!
strncmp
(
Np
->
inout_p
,
Np
->
decimal
,
x
)
)
if
(
x
&&
AMOUNT_TEST
(
x
)
&&
strncmp
(
Np
->
inout_p
,
Np
->
decimal
,
x
)
==
0
)
{
Np
->
inout_p
+=
x
-
1
;
*
Np
->
number_p
=
'.'
;
Np
->
number_p
++
;
Np
->
read_dec
=
TRUE
;
isread
=
TRUE
;
}
}
}
if
(
OVERLOAD_TEST
)
return
;
/*
* Read sign behind "last" number
*
* We need sign detection because determine exact position of
* post-sign is difficult:
*
* FM9999.9999999S -> 123.001-
* 9.9S -> .5-
* FM9.999999MI -> 5.01-
*/
if
(
*
Np
->
number
==
' '
&&
Np
->
read_pre
+
Np
->
read_post
>
0
)
{
/*
* locale sign (NUM_S) is always anchored behind a last number, if:
* - locale sign expected
* - last read char was NUM_0/9 or NUM_DEC
* - and next char is not digit
*/
if
(
IS_LSIGN
(
Np
->
Num
)
&&
isread
&&
(
Np
->
inout_p
+
1
)
<=
Np
->
inout
+
plen
&&
isdigit
(
*
(
Np
->
inout_p
+
1
))
==
0
)
{
int
x
;
char
*
tmp
=
Np
->
inout_p
++
;
#ifdef DEBUG_TO_FROM_CHAR
elog
(
DEBUG_elog_output
,
"Try read locale post-sign (%c)"
,
*
Np
->
inout_p
);
#endif
if
((
x
=
strlen
(
Np
->
L_negative_sign
))
&&
AMOUNT_TEST
(
x
)
&&
strncmp
(
Np
->
inout_p
,
Np
->
L_negative_sign
,
x
)
==
0
)
{
Np
->
inout_p
+=
x
-
1
;
/* -1 .. NUM_processor() do inout_p++ */
*
Np
->
number
=
'-'
;
}
else
if
((
x
=
strlen
(
Np
->
L_positive_sign
))
&&
AMOUNT_TEST
(
x
)
&&
strncmp
(
Np
->
inout_p
,
Np
->
L_positive_sign
,
x
)
==
0
)
{
Np
->
inout_p
+=
x
-
1
;
/* -1 .. NUM_processor() do inout_p++ */
*
Np
->
number
=
'+'
;
}
if
(
*
Np
->
number
==
' '
)
/* no sign read */
Np
->
inout_p
=
tmp
;
}
/*
* try read non-locale sign, it's happen only if format is not exact
* and we cannot determine sign position of MI/PL/SG, an example:
*
* FM9.999999MI -> 5.01-
*
* if (.... && IS_LSIGN(Np->Num)==FALSE) prevents read wrong formats
* like to_number('1 -', '9S') where sign is not anchored to last number.
*/
else
if
(
isread
==
FALSE
&&
IS_LSIGN
(
Np
->
Num
)
==
FALSE
&&
(
IS_PLUS
(
Np
->
Num
)
||
IS_MINUS
(
Np
->
Num
)))
{
#ifdef DEBUG_TO_FROM_CHAR
elog
(
DEBUG_elog_output
,
"Try read simple post-sign (%c)"
,
*
Np
->
inout_p
);
#endif
/*
* simple + -
*/
if
(
*
Np
->
inout_p
==
'-'
||
*
Np
->
inout_p
==
'+'
)
/* NUM_processor() do inout_p++ */
*
Np
->
number
=
*
Np
->
inout_p
;
}
}
}
#define IS_PREDEC_SPACE(_n) \
...
...
@@ -3978,6 +4065,7 @@ NUM_processor(FormatNode *node, NUMDesc *Num, char *inout, char *number,
Np
->
inout
=
inout
;
Np
->
last_relevant
=
NULL
;
Np
->
read_post
=
0
;
Np
->
read_pre
=
0
;
Np
->
read_dec
=
FALSE
;
if
(
Np
->
Num
->
zero_start
)
...
...
@@ -4130,6 +4218,11 @@ NUM_processor(FormatNode *node, NUMDesc *Num, char *inout, char *number,
{
/*
* Create/reading digit/zero/blank/sing
*
* 'NUM_S' note:
* The locale sign is anchored to number and we read/write it
* when we work with first or last number (NUM_0/NUM_9). This
* is reason why NUM_S missing in follow switch().
*/
switch
(
n
->
key
->
id
)
{
...
...
src/test/regress/expected/numeric.out
View file @
319902dc
...
...
@@ -1191,7 +1191,7 @@ SELECT '' AS to_number_12, to_number('.01-', '99.99S');
| -0.01
(1 row)
SELECT '' AS to_number_13, to_number(' . 0 1
-', ' 9 9 . 9 9 S');
SELECT '' AS to_number_13, to_number(' . 0 1-', ' 9 9 . 9 9 S');
to_number_13 | to_number
--------------+-----------
| -0.01
...
...
src/test/regress/sql/numeric.sql
View file @
319902dc
...
...
@@ -760,7 +760,7 @@ SELECT '' AS to_number_9, to_number('.0', '99999999.99999999');
SELECT
''
AS
to_number_10
,
to_number
(
'0'
,
'99.99'
);
SELECT
''
AS
to_number_11
,
to_number
(
'.-01'
,
'S99.99'
);
SELECT
''
AS
to_number_12
,
to_number
(
'.01-'
,
'99.99S'
);
SELECT
''
AS
to_number_13
,
to_number
(
' . 0 1
-'
,
' 9 9 . 9 9 S'
);
SELECT
''
AS
to_number_13
,
to_number
(
' . 0 1-'
,
' 9 9 . 9 9 S'
);
--
-- Input syntax
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment