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

Commit5633836

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 parent4347071 commit5633836

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"ecpgtype.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;
@@ -504,6 +508,42 @@ ECPGconnect(int lineno, int c, const char *name, const char *user, const char *p
504508
#ifdefENABLE_THREAD_SAFETY
505509
pthread_mutex_lock(&connections_mutex);
506510
#endif
511+
512+
/*
513+
* ... but first, make certain we have created ecpg_clocale. Rely on
514+
* holding connections_mutex to ensure this is done by only one thread.
515+
*/
516+
#ifdefHAVE_USELOCALE
517+
if (!ecpg_clocale)
518+
{
519+
ecpg_clocale=newlocale(LC_NUMERIC_MASK,"C", (locale_t)0);
520+
if (!ecpg_clocale)
521+
{
522+
#ifdefENABLE_THREAD_SAFETY
523+
pthread_mutex_unlock(&connections_mutex);
524+
#endif
525+
ecpg_raise(lineno,ECPG_OUT_OF_MEMORY,
526+
ECPG_SQLSTATE_ECPG_OUT_OF_MEMORY,NULL);
527+
if (host)
528+
ecpg_free(host);
529+
if (port)
530+
ecpg_free(port);
531+
if (options)
532+
ecpg_free(options);
533+
if (realname)
534+
ecpg_free(realname);
535+
if (dbname)
536+
ecpg_free(dbname);
537+
if (conn_keywords)
538+
ecpg_free(conn_keywords);
539+
if (conn_values)
540+
ecpg_free(conn_values);
541+
free(this);
542+
return false;
543+
}
544+
}
545+
#endif
546+
507547
if (connection_name!=NULL)
508548
this->name=ecpg_strdup(connection_name,lineno);
509549
else

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

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -486,9 +486,16 @@ ECPGget_desc(int lineno, const char *desc_name, int index,...)
486486
/* since the database gives the standard decimal point */
487487
/* (see comments in execute.c) */
488488
#ifdefHAVE_USELOCALE
489-
stmt.clocale=newlocale(LC_NUMERIC_MASK,"C", (locale_t)0);
490-
if (stmt.clocale!= (locale_t)0)
491-
stmt.oldlocale=uselocale(stmt.clocale);
489+
490+
/*
491+
* To get here, the above PQnfields() test must have found nonzero
492+
* fields. One needs a connection to create such a descriptor. (EXEC
493+
* SQL SET DESCRIPTOR can populate the descriptor's "items", but it
494+
* can't change the descriptor's PQnfields().) Any successful
495+
* connection initializes ecpg_clocale.
496+
*/
497+
Assert(ecpg_clocale);
498+
stmt.oldlocale=uselocale(ecpg_clocale);
492499
#else
493500
#ifdefHAVE__CONFIGTHREADLOCALE
494501
stmt.oldthreadlocale=_configthreadlocale(_ENABLE_PER_THREAD_LOCALE);
@@ -504,8 +511,6 @@ ECPGget_desc(int lineno, const char *desc_name, int index,...)
504511
#ifdefHAVE_USELOCALE
505512
if (stmt.oldlocale!= (locale_t)0)
506513
uselocale(stmt.oldlocale);
507-
if (stmt.clocale)
508-
freelocale(stmt.clocale);
509514
#else
510515
if (stmt.oldlocale)
511516
{

‎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
@@ -101,10 +101,7 @@ free_statement(struct statement *stmt)
101101
free_variable(stmt->outlist);
102102
ecpg_free(stmt->command);
103103
ecpg_free(stmt->name);
104-
#ifdefHAVE_USELOCALE
105-
if (stmt->clocale)
106-
freelocale(stmt->clocale);
107-
#else
104+
#ifndefHAVE_USELOCALE
108105
ecpg_free(stmt->oldlocale);
109106
#endif
110107
ecpg_free(stmt);
@@ -1965,6 +1962,15 @@ ecpg_do_prologue(int lineno, const int compat, const int force_indicator,
19651962
return false;
19661963
}
19671964

1965+
#ifdefENABLE_THREAD_SAFETY
1966+
ecpg_pthreads_init();
1967+
#endif
1968+
1969+
con=ecpg_get_connection(connection_name);
1970+
1971+
if (!ecpg_init(con,connection_name,lineno))
1972+
return false;
1973+
19681974
stmt= (structstatement*)ecpg_alloc(sizeof(structstatement),lineno);
19691975

19701976
if (stmt==NULL)
@@ -1979,13 +1985,13 @@ ecpg_do_prologue(int lineno, const int compat, const int force_indicator,
19791985
* treat that situation as if the function doesn't exist.
19801986
*/
19811987
#ifdefHAVE_USELOCALE
1982-
stmt->clocale=newlocale(LC_NUMERIC_MASK,"C", (locale_t)0);
1983-
if (stmt->clocale== (locale_t)0)
1984-
{
1985-
ecpg_do_epilogue(stmt);
1986-
return false;
1987-
}
1988-
stmt->oldlocale=uselocale(stmt->clocale);
1988+
1989+
/*
1990+
* Since ecpg_init() succeeded, we have a connection. Any successful
1991+
* connection initializes ecpg_clocale.
1992+
*/
1993+
Assert(ecpg_clocale);
1994+
stmt->oldlocale=uselocale(ecpg_clocale);
19891995
if (stmt->oldlocale== (locale_t)0)
19901996
{
19911997
ecpg_do_epilogue(stmt);
@@ -2004,18 +2010,6 @@ ecpg_do_prologue(int lineno, const int compat, const int force_indicator,
20042010
setlocale(LC_NUMERIC,"C");
20052011
#endif
20062012

2007-
#ifdefENABLE_THREAD_SAFETY
2008-
ecpg_pthreads_init();
2009-
#endif
2010-
2011-
con=ecpg_get_connection(connection_name);
2012-
2013-
if (!ecpg_init(con,connection_name,lineno))
2014-
{
2015-
ecpg_do_epilogue(stmt);
2016-
return false;
2017-
}
2018-
20192013
/*
20202014
* If statement type is ECPGst_prepnormal we are supposed to prepare the
20212015
* statement before executing them

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp