Attached is a patch that replaces a bunch of places where StringInfos
are unnecessarily allocated on the heap rather than the stack. If the StringInfo doesn't outlive the stack frame in which it is created, there is no need to allocate it on the heap via makeStringInfo() -- stack allocation is faster. While it's not a big deal unless the code is in a critical path, I don't see a reason not to save a few cycles -- using stack allocation is not less readable. I also cleaned up a bit of code along the way: moved variable declarations into a more tightly-enclosing scope where possible, fixed some pointless copying of strings in dblink, etc.
This commit is contained in:
parent
8e5a10d46c
commit
0d9742f99a
@ -301,11 +301,12 @@ dblink_open(PG_FUNCTION_ARGS)
|
||||
char *curname = NULL;
|
||||
char *sql = NULL;
|
||||
char *conname = NULL;
|
||||
StringInfo str = makeStringInfo();
|
||||
StringInfoData buf;
|
||||
remoteConn *rconn = NULL;
|
||||
bool fail = true; /* default to backward compatible behavior */
|
||||
|
||||
DBLINK_INIT;
|
||||
initStringInfo(&buf);
|
||||
|
||||
if (PG_NARGS() == 2)
|
||||
{
|
||||
@ -361,8 +362,8 @@ dblink_open(PG_FUNCTION_ARGS)
|
||||
if (rconn->newXactForCursor)
|
||||
(rconn->openCursorCount)++;
|
||||
|
||||
appendStringInfo(str, "DECLARE %s CURSOR FOR %s", curname, sql);
|
||||
res = PQexec(conn, str->data);
|
||||
appendStringInfo(&buf, "DECLARE %s CURSOR FOR %s", curname, sql);
|
||||
res = PQexec(conn, buf.data);
|
||||
if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
|
||||
{
|
||||
if (fail)
|
||||
@ -389,12 +390,13 @@ dblink_close(PG_FUNCTION_ARGS)
|
||||
PGresult *res = NULL;
|
||||
char *curname = NULL;
|
||||
char *conname = NULL;
|
||||
StringInfo str = makeStringInfo();
|
||||
StringInfoData buf;
|
||||
char *msg;
|
||||
remoteConn *rconn = NULL;
|
||||
bool fail = true; /* default to backward compatible behavior */
|
||||
|
||||
DBLINK_INIT;
|
||||
initStringInfo(&buf);
|
||||
|
||||
if (PG_NARGS() == 1)
|
||||
{
|
||||
@ -432,10 +434,10 @@ dblink_close(PG_FUNCTION_ARGS)
|
||||
else
|
||||
conn = rconn->conn;
|
||||
|
||||
appendStringInfo(str, "CLOSE %s", curname);
|
||||
appendStringInfo(&buf, "CLOSE %s", curname);
|
||||
|
||||
/* close the cursor */
|
||||
res = PQexec(conn, str->data);
|
||||
res = PQexec(conn, buf.data);
|
||||
if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
|
||||
{
|
||||
if (fail)
|
||||
@ -493,7 +495,7 @@ dblink_fetch(PG_FUNCTION_ARGS)
|
||||
if (SRF_IS_FIRSTCALL())
|
||||
{
|
||||
PGconn *conn = NULL;
|
||||
StringInfo str = makeStringInfo();
|
||||
StringInfoData buf;
|
||||
char *curname = NULL;
|
||||
int howmany = 0;
|
||||
bool fail = true; /* default to backward compatible */
|
||||
@ -542,6 +544,9 @@ dblink_fetch(PG_FUNCTION_ARGS)
|
||||
if (!conn)
|
||||
DBLINK_CONN_NOT_AVAIL;
|
||||
|
||||
initStringInfo(&buf);
|
||||
appendStringInfo(&buf, "FETCH %d FROM %s", howmany, curname);
|
||||
|
||||
/* create a function context for cross-call persistence */
|
||||
funcctx = SRF_FIRSTCALL_INIT();
|
||||
|
||||
@ -550,9 +555,7 @@ dblink_fetch(PG_FUNCTION_ARGS)
|
||||
*/
|
||||
oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
|
||||
|
||||
appendStringInfo(str, "FETCH %d FROM %s", howmany, curname);
|
||||
|
||||
res = PQexec(conn, str->data);
|
||||
res = PQexec(conn, buf.data);
|
||||
if (!res ||
|
||||
(PQresultStatus(res) != PGRES_COMMAND_OK &&
|
||||
PQresultStatus(res) != PGRES_TUPLES_OK))
|
||||
@ -1547,13 +1550,14 @@ get_sql_insert(Oid relid, int2vector *pkattnums, int16 pknumatts, char **src_pka
|
||||
HeapTuple tuple;
|
||||
TupleDesc tupdesc;
|
||||
int natts;
|
||||
StringInfo str = makeStringInfo();
|
||||
char *sql;
|
||||
StringInfoData buf;
|
||||
char *val;
|
||||
int16 key;
|
||||
int i;
|
||||
bool needComma;
|
||||
|
||||
initStringInfo(&buf);
|
||||
|
||||
/* get relation name including any needed schema prefix and quoting */
|
||||
relname = generate_relation_name(relid);
|
||||
|
||||
@ -1570,7 +1574,7 @@ get_sql_insert(Oid relid, int2vector *pkattnums, int16 pknumatts, char **src_pka
|
||||
(errcode(ERRCODE_CARDINALITY_VIOLATION),
|
||||
errmsg("source row not found")));
|
||||
|
||||
appendStringInfo(str, "INSERT INTO %s(", relname);
|
||||
appendStringInfo(&buf, "INSERT INTO %s(", relname);
|
||||
|
||||
needComma = false;
|
||||
for (i = 0; i < natts; i++)
|
||||
@ -1579,14 +1583,14 @@ get_sql_insert(Oid relid, int2vector *pkattnums, int16 pknumatts, char **src_pka
|
||||
continue;
|
||||
|
||||
if (needComma)
|
||||
appendStringInfo(str, ",");
|
||||
appendStringInfo(&buf, ",");
|
||||
|
||||
appendStringInfo(str, "%s",
|
||||
appendStringInfoString(&buf,
|
||||
quote_ident_cstr(NameStr(tupdesc->attrs[i]->attname)));
|
||||
needComma = true;
|
||||
}
|
||||
|
||||
appendStringInfo(str, ") VALUES(");
|
||||
appendStringInfo(&buf, ") VALUES(");
|
||||
|
||||
/*
|
||||
* remember attvals are 1 based
|
||||
@ -1598,7 +1602,7 @@ get_sql_insert(Oid relid, int2vector *pkattnums, int16 pknumatts, char **src_pka
|
||||
continue;
|
||||
|
||||
if (needComma)
|
||||
appendStringInfo(str, ",");
|
||||
appendStringInfo(&buf, ",");
|
||||
|
||||
if (tgt_pkattvals != NULL)
|
||||
key = get_attnum_pk_pos(pkattnums, pknumatts, i + 1);
|
||||
@ -1612,21 +1616,17 @@ get_sql_insert(Oid relid, int2vector *pkattnums, int16 pknumatts, char **src_pka
|
||||
|
||||
if (val != NULL)
|
||||
{
|
||||
appendStringInfo(str, "%s", quote_literal_cstr(val));
|
||||
appendStringInfoString(&buf, quote_literal_cstr(val));
|
||||
pfree(val);
|
||||
}
|
||||
else
|
||||
appendStringInfo(str, "NULL");
|
||||
appendStringInfo(&buf, "NULL");
|
||||
needComma = true;
|
||||
}
|
||||
appendStringInfo(str, ")");
|
||||
appendStringInfo(&buf, ")");
|
||||
|
||||
sql = pstrdup(str->data);
|
||||
pfree(str->data);
|
||||
pfree(str);
|
||||
relation_close(rel, AccessShareLock);
|
||||
|
||||
return (sql);
|
||||
return (buf.data);
|
||||
}
|
||||
|
||||
static char *
|
||||
@ -1636,10 +1636,11 @@ get_sql_delete(Oid relid, int2vector *pkattnums, int16 pknumatts, char **tgt_pka
|
||||
char *relname;
|
||||
TupleDesc tupdesc;
|
||||
int natts;
|
||||
StringInfo str = makeStringInfo();
|
||||
char *sql;
|
||||
StringInfoData buf;
|
||||
int i;
|
||||
|
||||
initStringInfo(&buf);
|
||||
|
||||
/* get relation name including any needed schema prefix and quoting */
|
||||
relname = generate_relation_name(relid);
|
||||
|
||||
@ -1650,15 +1651,15 @@ get_sql_delete(Oid relid, int2vector *pkattnums, int16 pknumatts, char **tgt_pka
|
||||
tupdesc = rel->rd_att;
|
||||
natts = tupdesc->natts;
|
||||
|
||||
appendStringInfo(str, "DELETE FROM %s WHERE ", relname);
|
||||
appendStringInfo(&buf, "DELETE FROM %s WHERE ", relname);
|
||||
for (i = 0; i < pknumatts; i++)
|
||||
{
|
||||
int16 pkattnum = pkattnums->values[i];
|
||||
|
||||
if (i > 0)
|
||||
appendStringInfo(str, " AND ");
|
||||
appendStringInfo(&buf, " AND ");
|
||||
|
||||
appendStringInfo(str, "%s",
|
||||
appendStringInfoString(&buf,
|
||||
quote_ident_cstr(NameStr(tupdesc->attrs[pkattnum - 1]->attname)));
|
||||
|
||||
if (tgt_pkattvals == NULL)
|
||||
@ -1666,18 +1667,14 @@ get_sql_delete(Oid relid, int2vector *pkattnums, int16 pknumatts, char **tgt_pka
|
||||
elog(ERROR, "target key array must not be NULL");
|
||||
|
||||
if (tgt_pkattvals[i] != NULL)
|
||||
appendStringInfo(str, " = %s",
|
||||
appendStringInfo(&buf, " = %s",
|
||||
quote_literal_cstr(tgt_pkattvals[i]));
|
||||
else
|
||||
appendStringInfo(str, " IS NULL");
|
||||
appendStringInfo(&buf, " IS NULL");
|
||||
}
|
||||
|
||||
sql = pstrdup(str->data);
|
||||
pfree(str->data);
|
||||
pfree(str);
|
||||
relation_close(rel, AccessShareLock);
|
||||
|
||||
return (sql);
|
||||
return (buf.data);
|
||||
}
|
||||
|
||||
static char *
|
||||
@ -1688,13 +1685,14 @@ get_sql_update(Oid relid, int2vector *pkattnums, int16 pknumatts, char **src_pka
|
||||
HeapTuple tuple;
|
||||
TupleDesc tupdesc;
|
||||
int natts;
|
||||
StringInfo str = makeStringInfo();
|
||||
char *sql;
|
||||
StringInfoData buf;
|
||||
char *val;
|
||||
int16 key;
|
||||
int i;
|
||||
bool needComma;
|
||||
|
||||
initStringInfo(&buf);
|
||||
|
||||
/* get relation name including any needed schema prefix and quoting */
|
||||
relname = generate_relation_name(relid);
|
||||
|
||||
@ -1711,7 +1709,7 @@ get_sql_update(Oid relid, int2vector *pkattnums, int16 pknumatts, char **src_pka
|
||||
(errcode(ERRCODE_CARDINALITY_VIOLATION),
|
||||
errmsg("source row not found")));
|
||||
|
||||
appendStringInfo(str, "UPDATE %s SET ", relname);
|
||||
appendStringInfo(&buf, "UPDATE %s SET ", relname);
|
||||
|
||||
needComma = false;
|
||||
for (i = 0; i < natts; i++)
|
||||
@ -1720,9 +1718,9 @@ get_sql_update(Oid relid, int2vector *pkattnums, int16 pknumatts, char **src_pka
|
||||
continue;
|
||||
|
||||
if (needComma)
|
||||
appendStringInfo(str, ", ");
|
||||
appendStringInfo(&buf, ", ");
|
||||
|
||||
appendStringInfo(str, "%s = ",
|
||||
appendStringInfo(&buf, "%s = ",
|
||||
quote_ident_cstr(NameStr(tupdesc->attrs[i]->attname)));
|
||||
|
||||
if (tgt_pkattvals != NULL)
|
||||
@ -1737,24 +1735,24 @@ get_sql_update(Oid relid, int2vector *pkattnums, int16 pknumatts, char **src_pka
|
||||
|
||||
if (val != NULL)
|
||||
{
|
||||
appendStringInfo(str, "%s", quote_literal_cstr(val));
|
||||
appendStringInfoString(&buf, quote_literal_cstr(val));
|
||||
pfree(val);
|
||||
}
|
||||
else
|
||||
appendStringInfo(str, "NULL");
|
||||
appendStringInfoString(&buf, "NULL");
|
||||
needComma = true;
|
||||
}
|
||||
|
||||
appendStringInfo(str, " WHERE ");
|
||||
appendStringInfo(&buf, " WHERE ");
|
||||
|
||||
for (i = 0; i < pknumatts; i++)
|
||||
{
|
||||
int16 pkattnum = pkattnums->values[i];
|
||||
|
||||
if (i > 0)
|
||||
appendStringInfo(str, " AND ");
|
||||
appendStringInfo(&buf, " AND ");
|
||||
|
||||
appendStringInfo(str, "%s",
|
||||
appendStringInfo(&buf, "%s",
|
||||
quote_ident_cstr(NameStr(tupdesc->attrs[pkattnum - 1]->attname)));
|
||||
|
||||
if (tgt_pkattvals != NULL)
|
||||
@ -1764,19 +1762,15 @@ get_sql_update(Oid relid, int2vector *pkattnums, int16 pknumatts, char **src_pka
|
||||
|
||||
if (val != NULL)
|
||||
{
|
||||
appendStringInfo(str, " = %s", quote_literal_cstr(val));
|
||||
appendStringInfo(&buf, " = %s", quote_literal_cstr(val));
|
||||
pfree(val);
|
||||
}
|
||||
else
|
||||
appendStringInfo(str, " IS NULL");
|
||||
appendStringInfo(&buf, " IS NULL");
|
||||
}
|
||||
|
||||
sql = pstrdup(str->data);
|
||||
pfree(str->data);
|
||||
pfree(str);
|
||||
relation_close(rel, AccessShareLock);
|
||||
|
||||
return (sql);
|
||||
return (buf.data);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1836,12 +1830,13 @@ get_tuple_of_interest(Oid relid, int2vector *pkattnums, int16 pknumatts, char **
|
||||
Relation rel;
|
||||
char *relname;
|
||||
TupleDesc tupdesc;
|
||||
StringInfo str = makeStringInfo();
|
||||
char *sql = NULL;
|
||||
StringInfoData buf;
|
||||
int ret;
|
||||
HeapTuple tuple;
|
||||
int i;
|
||||
|
||||
initStringInfo(&buf);
|
||||
|
||||
/* get relation name including any needed schema prefix and quoting */
|
||||
relname = generate_relation_name(relid);
|
||||
|
||||
@ -1863,34 +1858,30 @@ get_tuple_of_interest(Oid relid, int2vector *pkattnums, int16 pknumatts, char **
|
||||
* Build sql statement to look up tuple of interest Use src_pkattvals as
|
||||
* the criteria.
|
||||
*/
|
||||
appendStringInfo(str, "SELECT * FROM %s WHERE ", relname);
|
||||
appendStringInfo(&buf, "SELECT * FROM %s WHERE ", relname);
|
||||
|
||||
for (i = 0; i < pknumatts; i++)
|
||||
{
|
||||
int16 pkattnum = pkattnums->values[i];
|
||||
|
||||
if (i > 0)
|
||||
appendStringInfo(str, " AND ");
|
||||
appendStringInfo(&buf, " AND ");
|
||||
|
||||
appendStringInfo(str, "%s",
|
||||
appendStringInfoString(&buf,
|
||||
quote_ident_cstr(NameStr(tupdesc->attrs[pkattnum - 1]->attname)));
|
||||
|
||||
if (src_pkattvals[i] != NULL)
|
||||
appendStringInfo(str, " = %s",
|
||||
appendStringInfo(&buf, " = %s",
|
||||
quote_literal_cstr(src_pkattvals[i]));
|
||||
else
|
||||
appendStringInfo(str, " IS NULL");
|
||||
appendStringInfo(&buf, " IS NULL");
|
||||
}
|
||||
|
||||
sql = pstrdup(str->data);
|
||||
pfree(str->data);
|
||||
pfree(str);
|
||||
|
||||
/*
|
||||
* Retrieve the desired tuple
|
||||
*/
|
||||
ret = SPI_exec(sql, 0);
|
||||
pfree(sql);
|
||||
ret = SPI_exec(buf.data, 0);
|
||||
pfree(buf.data);
|
||||
|
||||
/*
|
||||
* Only allow one qualifying tuple
|
||||
|
@ -1260,13 +1260,10 @@ build_tuplestore_recursively(char *key_fld,
|
||||
{
|
||||
TupleDesc tupdesc = attinmeta->tupdesc;
|
||||
MemoryContext oldcontext;
|
||||
StringInfo sql = makeStringInfo();
|
||||
int ret;
|
||||
int proc;
|
||||
int serial_column;
|
||||
StringInfo branchstr = NULL;
|
||||
StringInfo chk_branchstr = NULL;
|
||||
StringInfo chk_current_key = NULL;
|
||||
StringInfoData sql;
|
||||
char **values;
|
||||
char *current_key;
|
||||
char *current_key_parent;
|
||||
@ -1278,17 +1275,12 @@ build_tuplestore_recursively(char *key_fld,
|
||||
if (max_depth > 0 && level > max_depth)
|
||||
return tupstore;
|
||||
|
||||
/* start a new branch */
|
||||
branchstr = makeStringInfo();
|
||||
|
||||
/* need these to check for recursion */
|
||||
chk_branchstr = makeStringInfo();
|
||||
chk_current_key = makeStringInfo();
|
||||
initStringInfo(&sql);
|
||||
|
||||
/* Build initial sql statement */
|
||||
if (!show_serial)
|
||||
{
|
||||
appendStringInfo(sql, "SELECT %s, %s FROM %s WHERE %s = %s AND %s IS NOT NULL AND %s <> %s",
|
||||
appendStringInfo(&sql, "SELECT %s, %s FROM %s WHERE %s = %s AND %s IS NOT NULL AND %s <> %s",
|
||||
key_fld,
|
||||
parent_key_fld,
|
||||
relname,
|
||||
@ -1299,7 +1291,7 @@ build_tuplestore_recursively(char *key_fld,
|
||||
}
|
||||
else
|
||||
{
|
||||
appendStringInfo(sql, "SELECT %s, %s FROM %s WHERE %s = %s AND %s IS NOT NULL AND %s <> %s ORDER BY %s",
|
||||
appendStringInfo(&sql, "SELECT %s, %s FROM %s WHERE %s = %s AND %s IS NOT NULL AND %s <> %s ORDER BY %s",
|
||||
key_fld,
|
||||
parent_key_fld,
|
||||
relname,
|
||||
@ -1359,7 +1351,7 @@ build_tuplestore_recursively(char *key_fld,
|
||||
}
|
||||
|
||||
/* Retrieve the desired rows */
|
||||
ret = SPI_execute(sql->data, true, 0);
|
||||
ret = SPI_execute(sql.data, true, 0);
|
||||
proc = SPI_processed;
|
||||
|
||||
/* Check for qualifying tuples */
|
||||
@ -1369,6 +1361,9 @@ build_tuplestore_recursively(char *key_fld,
|
||||
SPITupleTable *tuptable = SPI_tuptable;
|
||||
TupleDesc spi_tupdesc = tuptable->tupdesc;
|
||||
int i;
|
||||
StringInfoData branchstr;
|
||||
StringInfoData chk_branchstr;
|
||||
StringInfoData chk_current_key;
|
||||
|
||||
/* First time through, do a little more setup */
|
||||
if (level == 0)
|
||||
@ -1389,28 +1384,35 @@ build_tuplestore_recursively(char *key_fld,
|
||||
|
||||
for (i = 0; i < proc; i++)
|
||||
{
|
||||
/* start a new branch */
|
||||
initStringInfo(&branchstr);
|
||||
|
||||
/* need these to check for recursion */
|
||||
initStringInfo(&chk_branchstr);
|
||||
initStringInfo(&chk_current_key);
|
||||
|
||||
/* initialize branch for this pass */
|
||||
appendStringInfo(branchstr, "%s", branch);
|
||||
appendStringInfo(chk_branchstr, "%s%s%s", branch_delim, branch, branch_delim);
|
||||
appendStringInfo(&branchstr, "%s", branch);
|
||||
appendStringInfo(&chk_branchstr, "%s%s%s", branch_delim, branch, branch_delim);
|
||||
|
||||
/* get the next sql result tuple */
|
||||
spi_tuple = tuptable->vals[i];
|
||||
|
||||
/* get the current key and parent */
|
||||
current_key = SPI_getvalue(spi_tuple, spi_tupdesc, 1);
|
||||
appendStringInfo(chk_current_key, "%s%s%s", branch_delim, current_key, branch_delim);
|
||||
appendStringInfo(&chk_current_key, "%s%s%s", branch_delim, current_key, branch_delim);
|
||||
current_key_parent = pstrdup(SPI_getvalue(spi_tuple, spi_tupdesc, 2));
|
||||
|
||||
/* get the current level */
|
||||
sprintf(current_level, "%d", level);
|
||||
|
||||
/* check to see if this key is also an ancestor */
|
||||
if (strstr(chk_branchstr->data, chk_current_key->data))
|
||||
if (strstr(chk_branchstr.data, chk_current_key.data))
|
||||
elog(ERROR, "infinite recursion detected");
|
||||
|
||||
/* OK, extend the branch */
|
||||
appendStringInfo(branchstr, "%s%s", branch_delim, current_key);
|
||||
current_branch = branchstr->data;
|
||||
appendStringInfo(&branchstr, "%s%s", branch_delim, current_key);
|
||||
current_branch = branchstr.data;
|
||||
|
||||
/* build a tuple */
|
||||
values[0] = pstrdup(current_key);
|
||||
@ -1461,14 +1463,9 @@ build_tuplestore_recursively(char *key_fld,
|
||||
tupstore);
|
||||
|
||||
/* reset branch for next pass */
|
||||
xpfree(branchstr->data);
|
||||
initStringInfo(branchstr);
|
||||
|
||||
xpfree(chk_branchstr->data);
|
||||
initStringInfo(chk_branchstr);
|
||||
|
||||
xpfree(chk_current_key->data);
|
||||
initStringInfo(chk_current_key);
|
||||
xpfree(branchstr.data);
|
||||
xpfree(chk_branchstr.data);
|
||||
xpfree(chk_current_key.data);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -668,7 +668,7 @@ xpath_table(PG_FUNCTION_ARGS)
|
||||
* document */
|
||||
int had_values; /* To determine end of nodeset results */
|
||||
|
||||
StringInfo querysql;
|
||||
StringInfoData query_buf;
|
||||
|
||||
/* We only have a valid tuple description in table function mode */
|
||||
if (rsinfo == NULL || !IsA(rsinfo, ReturnSetInfo))
|
||||
@ -746,11 +746,10 @@ xpath_table(PG_FUNCTION_ARGS)
|
||||
} while ((pos != NULL) && (numpaths < (ret_tupdesc->natts - 1)));
|
||||
|
||||
/* Now build query */
|
||||
|
||||
querysql = makeStringInfo();
|
||||
initStringInfo(&query_buf);
|
||||
|
||||
/* Build initial sql statement */
|
||||
appendStringInfo(querysql, "SELECT %s, %s FROM %s WHERE %s",
|
||||
appendStringInfo(&query_buf, "SELECT %s, %s FROM %s WHERE %s",
|
||||
pkeyfield,
|
||||
xmlfield,
|
||||
relname,
|
||||
@ -761,8 +760,8 @@ xpath_table(PG_FUNCTION_ARGS)
|
||||
if ((ret = SPI_connect()) < 0)
|
||||
elog(ERROR, "xpath_table: SPI_connect returned %d", ret);
|
||||
|
||||
if ((ret = SPI_exec(querysql->data, 0)) != SPI_OK_SELECT)
|
||||
elog(ERROR, "xpath_table: SPI execution failed for query %s", querysql->data);
|
||||
if ((ret = SPI_exec(query_buf.data, 0)) != SPI_OK_SELECT)
|
||||
elog(ERROR, "xpath_table: SPI execution failed for query %s", query_buf.data);
|
||||
|
||||
proc = SPI_processed;
|
||||
/* elog(DEBUG1,"xpath_table: SPI returned %d rows",proc); */
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1994-5, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/commands/explain.c,v 1.144 2006/02/28 04:10:27 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/commands/explain.c,v 1.145 2006/03/01 06:51:01 neilc Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -232,7 +232,7 @@ ExplainOnePlan(QueryDesc *queryDesc, ExplainStmt *stmt,
|
||||
instr_time starttime;
|
||||
double totaltime = 0;
|
||||
ExplainState *es;
|
||||
StringInfo str;
|
||||
StringInfoData buf;
|
||||
int eflags;
|
||||
|
||||
INSTR_TIME_SET_CURRENT(starttime);
|
||||
@ -285,9 +285,8 @@ ExplainOnePlan(QueryDesc *queryDesc, ExplainStmt *stmt,
|
||||
}
|
||||
}
|
||||
|
||||
str = makeStringInfo();
|
||||
|
||||
explain_outNode(str, queryDesc->plantree, queryDesc->planstate,
|
||||
initStringInfo(&buf);
|
||||
explain_outNode(&buf, queryDesc->plantree, queryDesc->planstate,
|
||||
NULL, 0, es);
|
||||
|
||||
/*
|
||||
@ -335,18 +334,18 @@ ExplainOnePlan(QueryDesc *queryDesc, ExplainStmt *stmt,
|
||||
if (trig->tgisconstraint &&
|
||||
(conname = GetConstraintNameForTrigger(trig->tgoid)) != NULL)
|
||||
{
|
||||
appendStringInfo(str, "Trigger for constraint %s",
|
||||
appendStringInfo(&buf, "Trigger for constraint %s",
|
||||
conname);
|
||||
pfree(conname);
|
||||
}
|
||||
else
|
||||
appendStringInfo(str, "Trigger %s", trig->tgname);
|
||||
appendStringInfo(&buf, "Trigger %s", trig->tgname);
|
||||
|
||||
if (numrels > 1)
|
||||
appendStringInfo(str, " on %s",
|
||||
appendStringInfo(&buf, " on %s",
|
||||
RelationGetRelationName(rInfo->ri_RelationDesc));
|
||||
|
||||
appendStringInfo(str, ": time=%.3f calls=%.0f\n",
|
||||
appendStringInfo(&buf, ": time=%.3f calls=%.0f\n",
|
||||
1000.0 * instr->total,
|
||||
instr->ntuples);
|
||||
}
|
||||
@ -370,12 +369,11 @@ ExplainOnePlan(QueryDesc *queryDesc, ExplainStmt *stmt,
|
||||
totaltime += elapsed_time(&starttime);
|
||||
|
||||
if (stmt->analyze)
|
||||
appendStringInfo(str, "Total runtime: %.3f ms\n",
|
||||
appendStringInfo(&buf, "Total runtime: %.3f ms\n",
|
||||
1000.0 * totaltime);
|
||||
do_text_output_multiline(tstate, str->data);
|
||||
do_text_output_multiline(tstate, buf.data);
|
||||
|
||||
pfree(str->data);
|
||||
pfree(str);
|
||||
pfree(buf.data);
|
||||
pfree(es);
|
||||
}
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/varlena.c,v 1.143 2006/02/26 02:23:41 neilc Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/varlena.c,v 1.144 2006/03/01 06:51:01 neilc Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -2038,7 +2038,7 @@ replace_text(PG_FUNCTION_ARGS)
|
||||
text *buf_text;
|
||||
text *ret_text;
|
||||
int curr_posn;
|
||||
StringInfo str;
|
||||
StringInfoData str;
|
||||
|
||||
if (src_text_len == 0 || from_sub_text_len == 0)
|
||||
PG_RETURN_TEXT_P(src_text);
|
||||
@ -2049,7 +2049,7 @@ replace_text(PG_FUNCTION_ARGS)
|
||||
if (curr_posn == 0)
|
||||
PG_RETURN_TEXT_P(src_text);
|
||||
|
||||
str = makeStringInfo();
|
||||
initStringInfo(&str);
|
||||
buf_text = src_text;
|
||||
|
||||
while (curr_posn > 0)
|
||||
@ -2059,8 +2059,8 @@ replace_text(PG_FUNCTION_ARGS)
|
||||
right_text = text_substring(PointerGetDatum(buf_text),
|
||||
curr_posn + from_sub_text_len, -1, true);
|
||||
|
||||
appendStringInfoText(str, left_text);
|
||||
appendStringInfoText(str, to_sub_text);
|
||||
appendStringInfoText(&str, left_text);
|
||||
appendStringInfoText(&str, to_sub_text);
|
||||
|
||||
if (buf_text != src_text)
|
||||
pfree(buf_text);
|
||||
@ -2069,13 +2069,12 @@ replace_text(PG_FUNCTION_ARGS)
|
||||
curr_posn = TEXTPOS(buf_text, from_sub_text);
|
||||
}
|
||||
|
||||
appendStringInfoText(str, buf_text);
|
||||
appendStringInfoText(&str, buf_text);
|
||||
if (buf_text != src_text)
|
||||
pfree(buf_text);
|
||||
|
||||
ret_text = PG_STR_GET_TEXT(str->data);
|
||||
pfree(str->data);
|
||||
pfree(str);
|
||||
ret_text = PG_STR_GET_TEXT(str.data);
|
||||
pfree(str.data);
|
||||
|
||||
PG_RETURN_TEXT_P(ret_text);
|
||||
}
|
||||
@ -2227,8 +2226,7 @@ replace_text_regexp(text *src_text, void *regexp,
|
||||
text *ret_text;
|
||||
regex_t *re = (regex_t *) regexp;
|
||||
int src_text_len = VARSIZE(src_text) - VARHDRSZ;
|
||||
StringInfo str = makeStringInfo();
|
||||
int regexec_result;
|
||||
StringInfoData buf;
|
||||
regmatch_t pmatch[REGEXP_REPLACE_BACKREF_CNT];
|
||||
pg_wchar *data;
|
||||
size_t data_len;
|
||||
@ -2236,6 +2234,8 @@ replace_text_regexp(text *src_text, void *regexp,
|
||||
int data_pos;
|
||||
bool have_escape;
|
||||
|
||||
initStringInfo(&buf);
|
||||
|
||||
/* Convert data string to wide characters. */
|
||||
data = (pg_wchar *) palloc((src_text_len + 1) * sizeof(pg_wchar));
|
||||
data_len = pg_mb2wchar_with_len(VARDATA(src_text), data, src_text_len);
|
||||
@ -2245,6 +2245,8 @@ replace_text_regexp(text *src_text, void *regexp,
|
||||
|
||||
for (search_start = data_pos = 0; search_start <= data_len;)
|
||||
{
|
||||
int regexec_result;
|
||||
|
||||
regexec_result = pg_regexec(re,
|
||||
data,
|
||||
data_len,
|
||||
@ -2254,20 +2256,19 @@ replace_text_regexp(text *src_text, void *regexp,
|
||||
pmatch,
|
||||
0);
|
||||
|
||||
if (regexec_result != REG_OKAY && regexec_result != REG_NOMATCH)
|
||||
if (regexec_result == REG_NOMATCH)
|
||||
break;
|
||||
|
||||
if (regexec_result != REG_OKAY)
|
||||
{
|
||||
char errMsg[100];
|
||||
|
||||
/* re failed??? */
|
||||
pg_regerror(regexec_result, re, errMsg, sizeof(errMsg));
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_REGULAR_EXPRESSION),
|
||||
errmsg("regular expression failed: %s", errMsg)));
|
||||
}
|
||||
|
||||
if (regexec_result == REG_NOMATCH)
|
||||
break;
|
||||
|
||||
/*
|
||||
* Copy the text to the left of the match position. Because we are
|
||||
* working with character not byte indexes, it's easiest to use
|
||||
@ -2281,7 +2282,7 @@ replace_text_regexp(text *src_text, void *regexp,
|
||||
data_pos + 1,
|
||||
pmatch[0].rm_so - data_pos,
|
||||
false);
|
||||
appendStringInfoText(str, left_text);
|
||||
appendStringInfoText(&buf, left_text);
|
||||
pfree(left_text);
|
||||
}
|
||||
|
||||
@ -2290,9 +2291,9 @@ replace_text_regexp(text *src_text, void *regexp,
|
||||
* replace_text has escape characters.
|
||||
*/
|
||||
if (have_escape)
|
||||
appendStringInfoRegexpSubstr(str, replace_text, pmatch, src_text);
|
||||
appendStringInfoRegexpSubstr(&buf, replace_text, pmatch, src_text);
|
||||
else
|
||||
appendStringInfoText(str, replace_text);
|
||||
appendStringInfoText(&buf, replace_text);
|
||||
|
||||
search_start = data_pos = pmatch[0].rm_eo;
|
||||
|
||||
@ -2318,13 +2319,12 @@ replace_text_regexp(text *src_text, void *regexp,
|
||||
|
||||
right_text = text_substring(PointerGetDatum(src_text),
|
||||
data_pos + 1, -1, true);
|
||||
appendStringInfoText(str, right_text);
|
||||
appendStringInfoText(&buf, right_text);
|
||||
pfree(right_text);
|
||||
}
|
||||
|
||||
ret_text = PG_STR_GET_TEXT(str->data);
|
||||
pfree(str->data);
|
||||
pfree(str);
|
||||
ret_text = PG_STR_GET_TEXT(buf.data);
|
||||
pfree(buf.data);
|
||||
pfree(data);
|
||||
|
||||
return ret_text;
|
||||
@ -2512,7 +2512,7 @@ array_to_text(PG_FUNCTION_ARGS)
|
||||
int typlen;
|
||||
bool typbyval;
|
||||
char typalign;
|
||||
StringInfo result_str = makeStringInfo();
|
||||
StringInfoData buf;
|
||||
bool printed = false;
|
||||
char *p;
|
||||
bits8 *bitmap;
|
||||
@ -2529,6 +2529,7 @@ array_to_text(PG_FUNCTION_ARGS)
|
||||
PG_RETURN_TEXT_P(PG_STR_GET_TEXT(""));
|
||||
|
||||
element_type = ARR_ELEMTYPE(v);
|
||||
initStringInfo(&buf);
|
||||
|
||||
/*
|
||||
* We arrange to look up info about element type, including its output
|
||||
@ -2583,9 +2584,9 @@ array_to_text(PG_FUNCTION_ARGS)
|
||||
itemvalue));
|
||||
|
||||
if (printed)
|
||||
appendStringInfo(result_str, "%s%s", fldsep, value);
|
||||
appendStringInfo(&buf, "%s%s", fldsep, value);
|
||||
else
|
||||
appendStringInfoString(result_str, value);
|
||||
appendStringInfoString(&buf, value);
|
||||
printed = true;
|
||||
|
||||
p = att_addlength(p, typlen, PointerGetDatum(p));
|
||||
@ -2604,7 +2605,7 @@ array_to_text(PG_FUNCTION_ARGS)
|
||||
}
|
||||
}
|
||||
|
||||
PG_RETURN_TEXT_P(PG_STR_GET_TEXT(result_str->data));
|
||||
PG_RETURN_TEXT_P(PG_STR_GET_TEXT(buf.data));
|
||||
}
|
||||
|
||||
#define HEXBASE 16
|
||||
|
Loading…
Reference in New Issue
Block a user