Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
Greenplum
Gpdb
提交
319902dc
G
Gpdb
项目概览
Greenplum
/
Gpdb
通知
7
Star
1
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
G
Gpdb
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
319902dc
编写于
10月 28, 2004
作者:
T
Tom Lane
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Fix to_number for the case of a trailing S.
Karel Zak
上级
5fef3c6e
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
139 addition
and
46 deletion
+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
未找到文件。
src/backend/utils/adt/formatting.c
浏览文件 @
319902dc
/* -----------------------------------------------------------------------
/* -----------------------------------------------------------------------
* formatting.c
* 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
* Portions Copyright (c) 1999-2004, PostgreSQL Global Development Group
...
@@ -853,7 +853,8 @@ typedef struct NUMProc
...
@@ -853,7 +853,8 @@ typedef struct NUMProc
num_pre
,
/* space before first number */
num_pre
,
/* space before first number */
read_dec
,
/* to_number - was read dec. point */
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 */
char
*
number
,
/* string with number */
*
number_p
,
/* pointer to current number position */
*
number_p
,
/* pointer to current number position */
...
@@ -3623,15 +3624,18 @@ get_last_relevant_decnum(char *num)
...
@@ -3623,15 +3624,18 @@ get_last_relevant_decnum(char *num)
static
void
static
void
NUM_numpart_from_char
(
NUMProc
*
Np
,
int
id
,
int
plen
)
NUM_numpart_from_char
(
NUMProc
*
Np
,
int
id
,
int
plen
)
{
{
bool
isread
=
FALSE
;
#ifdef DEBUG_TO_FROM_CHAR
#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
#endif
if
(
*
Np
->
inout_p
==
' '
)
if
(
*
Np
->
inout_p
==
' '
)
Np
->
inout_p
++
;
Np
->
inout_p
++
;
#define OVERLOAD_TEST (Np->inout_p >= Np->inout + plen)
#define OVERLOAD_TEST (Np->inout_p >= Np->inout + plen)
#define AMOUNT_TEST(_s) (plen-(Np->inout_p-Np->inout) >= _s)
if
(
*
Np
->
inout_p
==
' '
)
if
(
*
Np
->
inout_p
==
' '
)
Np
->
inout_p
++
;
Np
->
inout_p
++
;
...
@@ -3640,68 +3644,73 @@ NUM_numpart_from_char(NUMProc *Np, int id, int plen)
...
@@ -3640,68 +3644,73 @@ NUM_numpart_from_char(NUMProc *Np, int id, int plen)
return
;
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
#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
#endif
/*
/*
* locale sign
* locale sign
*/
*/
if
(
IS_LSIGN
(
Np
->
Num
))
if
(
IS_LSIGN
(
Np
->
Num
)
&&
Np
->
Num
->
lsign
==
NUM_LSIGN_PRE
)
{
{
int
x
=
0
;
int
x
=
strlen
(
Np
->
L_negative_sign
);
#ifdef DEBUG_TO_FROM_CHAR
#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
#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
=
'-'
;
*
Np
->
number
=
'-'
;
return
;
}
}
else
if
((
x
=
strlen
(
Np
->
L_positive_sign
))
&&
x
=
strlen
(
Np
->
L_positive_sign
);
AMOUNT_TEST
(
x
)
&&
if
(
!
strncmp
(
Np
->
inout_p
,
Np
->
L_positive_sign
,
x
)
)
strncmp
(
Np
->
inout_p
,
Np
->
L_positive_sign
,
x
)
==
0
)
{
{
Np
->
inout_p
+=
x
-
1
;
Np
->
inout_p
+=
x
;
*
Np
->
number
=
'+'
;
*
Np
->
number
=
'+'
;
return
;
}
}
}
}
else
{
#ifdef DEBUG_TO_FROM_CHAR
#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
#endif
/*
* simple + - < >
*/
if
(
*
Np
->
inout_p
==
'-'
||
(
IS_BRACKET
(
Np
->
Num
)
&&
*
Np
->
inout_p
==
'<'
))
{
/*
*
Np
->
number
=
'-'
;
/* set - */
* simple + - < >
Np
->
inout_p
++
;
*/
if
(
*
Np
->
inout_p
==
'-'
||
(
IS_BRACKET
(
Np
->
Num
)
&&
*
Np
->
inout_p
==
'<'
))
{
*
Np
->
number
=
'-'
;
/* set - */
Np
->
inout_p
++
;
}
}
else
if
(
*
Np
->
inout_p
==
'+'
)
else
if
(
*
Np
->
inout_p
==
'+'
)
{
{
*
Np
->
number
=
'+'
;
/* set + */
*
Np
->
number
=
'+'
;
/* set + */
Np
->
inout_p
++
;
Np
->
inout_p
++
;
}
}
}
}
}
if
(
OVERLOAD_TEST
)
if
(
OVERLOAD_TEST
)
return
;
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
* read digit
*/
*/
...
@@ -3716,16 +3725,19 @@ NUM_numpart_from_char(NUMProc *Np, int id, int plen)
...
@@ -3716,16 +3725,19 @@ NUM_numpart_from_char(NUMProc *Np, int id, int plen)
if
(
Np
->
read_dec
)
if
(
Np
->
read_dec
)
Np
->
read_post
++
;
Np
->
read_post
++
;
else
Np
->
read_pre
++
;
isread
=
TRUE
;
#ifdef DEBUG_TO_FROM_CHAR
#ifdef DEBUG_TO_FROM_CHAR
elog
(
DEBUG_elog_output
,
"Read digit (%c)"
,
*
Np
->
inout_p
);
elog
(
DEBUG_elog_output
,
"Read digit (%c)"
,
*
Np
->
inout_p
);
#endif
#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
#ifdef DEBUG_TO_FROM_CHAR
...
@@ -3737,7 +3749,7 @@ NUM_numpart_from_char(NUMProc *Np, int id, int plen)
...
@@ -3737,7 +3749,7 @@ NUM_numpart_from_char(NUMProc *Np, int id, int plen)
*
Np
->
number_p
=
'.'
;
*
Np
->
number_p
=
'.'
;
Np
->
number_p
++
;
Np
->
number_p
++
;
Np
->
read_dec
=
TRUE
;
Np
->
read_dec
=
TRUE
;
isread
=
TRUE
;
}
}
else
else
{
{
...
@@ -3747,15 +3759,90 @@ NUM_numpart_from_char(NUMProc *Np, int id, int plen)
...
@@ -3747,15 +3759,90 @@ NUM_numpart_from_char(NUMProc *Np, int id, int plen)
elog
(
DEBUG_elog_output
,
"Try read locale point (%c)"
,
elog
(
DEBUG_elog_output
,
"Try read locale point (%c)"
,
*
Np
->
inout_p
);
*
Np
->
inout_p
);
#endif
#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
->
inout_p
+=
x
-
1
;
*
Np
->
number_p
=
'.'
;
*
Np
->
number_p
=
'.'
;
Np
->
number_p
++
;
Np
->
number_p
++
;
Np
->
read_dec
=
TRUE
;
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) \
#define IS_PREDEC_SPACE(_n) \
...
@@ -3978,6 +4065,7 @@ NUM_processor(FormatNode *node, NUMDesc *Num, char *inout, char *number,
...
@@ -3978,6 +4065,7 @@ NUM_processor(FormatNode *node, NUMDesc *Num, char *inout, char *number,
Np
->
inout
=
inout
;
Np
->
inout
=
inout
;
Np
->
last_relevant
=
NULL
;
Np
->
last_relevant
=
NULL
;
Np
->
read_post
=
0
;
Np
->
read_post
=
0
;
Np
->
read_pre
=
0
;
Np
->
read_dec
=
FALSE
;
Np
->
read_dec
=
FALSE
;
if
(
Np
->
Num
->
zero_start
)
if
(
Np
->
Num
->
zero_start
)
...
@@ -4130,6 +4218,11 @@ NUM_processor(FormatNode *node, NUMDesc *Num, char *inout, char *number,
...
@@ -4130,6 +4218,11 @@ NUM_processor(FormatNode *node, NUMDesc *Num, char *inout, char *number,
{
{
/*
/*
* Create/reading digit/zero/blank/sing
* 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
)
switch
(
n
->
key
->
id
)
{
{
...
...
src/test/regress/expected/numeric.out
浏览文件 @
319902dc
...
@@ -1191,7 +1191,7 @@ SELECT '' AS to_number_12, to_number('.01-', '99.99S');
...
@@ -1191,7 +1191,7 @@ SELECT '' AS to_number_12, to_number('.01-', '99.99S');
| -0.01
| -0.01
(1 row)
(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
to_number_13 | to_number
--------------+-----------
--------------+-----------
| -0.01
| -0.01
...
...
src/test/regress/sql/numeric.sql
浏览文件 @
319902dc
...
@@ -760,7 +760,7 @@ SELECT '' AS to_number_9, to_number('.0', '99999999.99999999');
...
@@ -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_10
,
to_number
(
'0'
,
'99.99'
);
SELECT
''
AS
to_number_11
,
to_number
(
'.-01'
,
'S99.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_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
-- Input syntax
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录