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

Commit5e0b8f3

Browse files
committed
ecpglib: call newlocale() once per process.
ecpglib has been calling it once per SQL query and once per EXEC SQL GETDESCRIPTOR. Instead, if newlocale() has not succeeded before, call itwhile establishing a connection. This mitigates three problems:- If newlocale() failed in EXEC SQL GET DESCRIPTOR, the command silently proceeded without the intended locale change.- On AIX, each newlocale()+freelocale() cycle leaked memory.- newlocale() CPU usage may have been nontrivial.Fail the connection attempt if newlocale() fails. Rearrangeecpg_do_prologue() to validate the connection before its uselocale().The sort of program that may regress is one running in an environmentwhere newlocale() fails. If that program establishes connectionswithout running SQL statements, it will stop working in response to thischange. I'm betting against the importance of such an ECPG use case.Most SQL execution (any using ECPGdo()) has long required newlocale()success, so there's little a connection could do without newlocale().Back-patch to v10 (all supported versions).Reviewed by Tom Lane. Reported by Guillaume Lelarge.Discussion:https://postgr.es/m/20220101074055.GA54621@rfd.leadboat.com
1 parentf7b69b1 commit5e0b8f3

File tree

4 files changed

+71
-29
lines changed

4 files changed

+71
-29
lines changed

‎src/interfaces/ecpg/ecpglib/connect.c

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@
1010
#include"ecpglib_extern.h"
1111
#include"sqlca.h"
1212

13+
#ifdefHAVE_USELOCALE
14+
locale_tecpg_clocale;
15+
#endif
16+
1317
#ifdefENABLE_THREAD_SAFETY
1418
staticpthread_mutex_tconnections_mutex=PTHREAD_MUTEX_INITIALIZER;
1519
staticpthread_key_tactual_connection_key;
@@ -531,6 +535,42 @@ ECPGconnect(int lineno, int c, const char *name, const char *user, const char *p
531535
#ifdefENABLE_THREAD_SAFETY
532536
pthread_mutex_lock(&connections_mutex);
533537
#endif
538+
539+
/*
540+
* ... but first, make certain we have created ecpg_clocale. Rely on
541+
* holding connections_mutex to ensure this is done by only one thread.
542+
*/
543+
#ifdefHAVE_USELOCALE
544+
if (!ecpg_clocale)
545+
{
546+
ecpg_clocale=newlocale(LC_NUMERIC_MASK,"C", (locale_t)0);
547+
if (!ecpg_clocale)
548+
{
549+
#ifdefENABLE_THREAD_SAFETY
550+
pthread_mutex_unlock(&connections_mutex);
551+
#endif
552+
ecpg_raise(lineno,ECPG_OUT_OF_MEMORY,
553+
ECPG_SQLSTATE_ECPG_OUT_OF_MEMORY,NULL);
554+
if (host)
555+
ecpg_free(host);
556+
if (port)
557+
ecpg_free(port);
558+
if (options)
559+
ecpg_free(options);
560+
if (realname)
561+
ecpg_free(realname);
562+
if (dbname)
563+
ecpg_free(dbname);
564+
if (conn_keywords)
565+
ecpg_free(conn_keywords);
566+
if (conn_values)
567+
ecpg_free(conn_values);
568+
free(this);
569+
return false;
570+
}
571+
}
572+
#endif
573+
534574
if (connection_name!=NULL)
535575
this->name=ecpg_strdup(connection_name,lineno);
536576
else

‎src/interfaces/ecpg/ecpglib/descriptor.c

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -491,9 +491,16 @@ ECPGget_desc(int lineno, const char *desc_name, int index,...)
491491
/* since the database gives the standard decimal point */
492492
/* (see comments in execute.c) */
493493
#ifdefHAVE_USELOCALE
494-
stmt.clocale=newlocale(LC_NUMERIC_MASK,"C", (locale_t)0);
495-
if (stmt.clocale!= (locale_t)0)
496-
stmt.oldlocale=uselocale(stmt.clocale);
494+
495+
/*
496+
* To get here, the above PQnfields() test must have found nonzero
497+
* fields. One needs a connection to create such a descriptor. (EXEC
498+
* SQL SET DESCRIPTOR can populate the descriptor's "items", but it
499+
* can't change the descriptor's PQnfields().) Any successful
500+
* connection initializes ecpg_clocale.
501+
*/
502+
Assert(ecpg_clocale);
503+
stmt.oldlocale=uselocale(ecpg_clocale);
497504
#else
498505
#ifdefHAVE__CONFIGTHREADLOCALE
499506
stmt.oldthreadlocale=_configthreadlocale(_ENABLE_PER_THREAD_LOCALE);
@@ -509,8 +516,6 @@ ECPGget_desc(int lineno, const char *desc_name, int index,...)
509516
#ifdefHAVE_USELOCALE
510517
if (stmt.oldlocale!= (locale_t)0)
511518
uselocale(stmt.oldlocale);
512-
if (stmt.clocale)
513-
freelocale(stmt.clocale);
514519
#else
515520
if (stmt.oldlocale)
516521
{

‎src/interfaces/ecpg/ecpglib/ecpglib_extern.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,10 @@ struct ECPGtype_information_cache
5959
enumARRAY_TYPEisarray;
6060
};
6161

62+
#ifdefHAVE_USELOCALE
63+
externlocale_tecpg_clocale;/* LC_NUMERIC=C */
64+
#endif
65+
6266
/* structure to store one statement */
6367
structstatement
6468
{
@@ -73,7 +77,6 @@ struct statement
7377
structvariable*inlist;
7478
structvariable*outlist;
7579
#ifdefHAVE_USELOCALE
76-
locale_tclocale;
7780
locale_toldlocale;
7881
#else
7982
char*oldlocale;

‎src/interfaces/ecpg/ecpglib/execute.c

Lines changed: 17 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -102,10 +102,7 @@ free_statement(struct statement *stmt)
102102
free_variable(stmt->outlist);
103103
ecpg_free(stmt->command);
104104
ecpg_free(stmt->name);
105-
#ifdefHAVE_USELOCALE
106-
if (stmt->clocale)
107-
freelocale(stmt->clocale);
108-
#else
105+
#ifndefHAVE_USELOCALE
109106
ecpg_free(stmt->oldlocale);
110107
#endif
111108
ecpg_free(stmt);
@@ -1969,6 +1966,15 @@ ecpg_do_prologue(int lineno, const int compat, const int force_indicator,
19691966
return false;
19701967
}
19711968

1969+
#ifdefENABLE_THREAD_SAFETY
1970+
ecpg_pthreads_init();
1971+
#endif
1972+
1973+
con=ecpg_get_connection(connection_name);
1974+
1975+
if (!ecpg_init(con,connection_name,lineno))
1976+
return false;
1977+
19721978
stmt= (structstatement*)ecpg_alloc(sizeof(structstatement),lineno);
19731979

19741980
if (stmt==NULL)
@@ -1983,13 +1989,13 @@ ecpg_do_prologue(int lineno, const int compat, const int force_indicator,
19831989
* treat that situation as if the function doesn't exist.
19841990
*/
19851991
#ifdefHAVE_USELOCALE
1986-
stmt->clocale=newlocale(LC_NUMERIC_MASK,"C", (locale_t)0);
1987-
if (stmt->clocale== (locale_t)0)
1988-
{
1989-
ecpg_do_epilogue(stmt);
1990-
return false;
1991-
}
1992-
stmt->oldlocale=uselocale(stmt->clocale);
1992+
1993+
/*
1994+
* Since ecpg_init() succeeded, we have a connection. Any successful
1995+
* connection initializes ecpg_clocale.
1996+
*/
1997+
Assert(ecpg_clocale);
1998+
stmt->oldlocale=uselocale(ecpg_clocale);
19931999
if (stmt->oldlocale== (locale_t)0)
19942000
{
19952001
ecpg_do_epilogue(stmt);
@@ -2008,18 +2014,6 @@ ecpg_do_prologue(int lineno, const int compat, const int force_indicator,
20082014
setlocale(LC_NUMERIC,"C");
20092015
#endif
20102016

2011-
#ifdefENABLE_THREAD_SAFETY
2012-
ecpg_pthreads_init();
2013-
#endif
2014-
2015-
con=ecpg_get_connection(connection_name);
2016-
2017-
if (!ecpg_init(con,connection_name,lineno))
2018-
{
2019-
ecpg_do_epilogue(stmt);
2020-
return false;
2021-
}
2022-
20232017
/*
20242018
* If statement type is ECPGst_prepnormal we are supposed to prepare the
20252019
* statement before executing them

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp