Attached is a patch that replaces a bunch of places where StringInfos
authorNeil Conway <neilc@samurai.com>
Wed, 1 Mar 2006 06:51:01 +0000 (06:51 +0000)
committerNeil Conway <neilc@samurai.com>
Wed, 1 Mar 2006 06:51:01 +0000 (06:51 +0000)
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.

contrib/dblink/dblink.c
contrib/tablefunc/tablefunc.c
contrib/xml2/xpath.c
src/backend/commands/explain.c
src/backend/utils/adt/varlena.c

index 4fd17c3227158b662c4e25cdd7981d8a91b62187..b1b863ea1e45a4cac3aa5ef5f6b7a0d4c3dcfd47 100644 (file)
@@ -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
index 0beb44f584570f2ad9dec2bed9efeb3d0dca80d4..aacc949ff28e725a5e3b1881a8816f10c14e1549 100644 (file)
@@ -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);
        }
    }
 
index 662731b5c04c63bfe9fb5d6e095d6898c43d389d..3dfcdadf96b4a42f717fa0ef740a456b467442de 100644 (file)
@@ -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); */
index 755a64a9446f9a7ac05aced19c7650dcfb860e81..767d4c9f806cd27473d1f3e3d7bdcaac30106e27 100644 (file)
@@ -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);
 }
 
index c2119edcecc4504501389b7616dfa70ef47d8d7e..cbfcf52ffe33a22ddac57c412646fe316585b6e4 100644 (file)
@@ -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