/*
* PgBouncer - Lightweight connection pooler for PostgreSQL.
- *
+ *
* Copyright (c) 2007-2009 Marko Kreen, Skype Technologies OÜ
- *
+ *
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
- *
+ *
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
#include "bouncer.h"
+#include <usual/pgutil.h>
+
struct var_lookup {
const char *name;
enum VarCacheIdx idx;
static const struct var_lookup lookup [] = {
{"client_encoding", VClientEncoding },
- {"datestyle", VDateStyle },
- {"timezone", VTimeZone },
+ {"DateStyle", VDateStyle },
+ {"TimeZone", VTimeZone },
{"standard_conforming_strings", VStdStr },
+ {"application_name", VAppName },
{NULL},
};
struct PStr *pstr = NULL;
if (!vpool) {
- vpool = strpool_create();
+ vpool = strpool_create(USUAL_ALLOC);
if (!vpool)
return false;
}
strpool_decref(cache->var_list[lk->idx]);
cache->var_list[lk->idx] = NULL;
- /* ignore empty value */
- if (!value && !value[0])
+ /* NULL value? */
+ if (!value)
return false;
/* set new value */
return true;
}
-static bool is_std_quote(VarCache *vars)
-{
- const struct PStr *s = vars->var_list[VStdStr];
- return s && strcasecmp(s->str, "on") == 0;
-}
-
-static bool quote_literal(char *buf, int buflen, const char *src, bool std_quote)
-{
- char *dst = buf;
- char *end = buf + buflen - 2;
-
- if (buflen < 3)
- return false;
-
- *dst++ = '\'';
- while (*src && dst < end) {
- if (*src == '\'')
- *dst++ = '\'';
- else if (*src == '\\' && !std_quote)
- *dst++ = '\\';
- *dst++ = *src++;
- }
- if (*src || dst > end)
- return false;
-
- *dst++ = '\'';
- *dst = 0;
-
- return true;
-}
-
static int apply_var(PktBuf *pkt, const char *key,
- const char *cval, const char *sval,
- bool std_quote)
+ const struct PStr *cval,
+ const struct PStr *sval)
{
char buf[128];
char qbuf[128];
unsigned len;
- if (strcasecmp(cval, sval) == 0)
+ /* if unset, skip */
+ if (!cval || !sval || !*cval->str)
return 0;
- /* if unset, ignore */
- if (!*cval)
+ /* if equal, skip */
+ if (cval == sval)
+ return 0;
+
+ /* ignore case difference */
+ if (strcasecmp(cval->str, sval->str) == 0)
return 0;
/* the string may have been taken from startup pkt */
- if (!quote_literal(qbuf, sizeof(qbuf), cval, std_quote))
+ if (!pg_quote_literal(qbuf, cval->str, sizeof(qbuf)))
return 0;
/* add SET statement to packet */
struct PStr *cval, *sval;
const struct var_lookup *lk;
int sql_ofs;
- bool std_quote = is_std_quote(&server->vars);
struct PktBuf *pkt = pktbuf_temp();
pktbuf_start_packet(pkt, 'Q');
- /* grab quory position inside pkt */
+ /* grab query position inside pkt */
sql_ofs = pktbuf_written(pkt);
for (lk = lookup; lk->name; lk++) {
sval = get_value(&server->vars, lk);
cval = get_value(&client->vars, lk);
- if (cval)
- changes += apply_var(pkt, lk->name, cval->str, sval->str, std_quote);
+ changes += apply_var(pkt, lk->name, cval, sval);
}
*changes_p = changes > 0;
if (!changes)
pktbuf_finish_packet(pkt);
slog_debug(server, "varcache_apply: %s", pkt->buf + sql_ofs);
- return pktbuf_send_immidiate(pkt, server);
+ return pktbuf_send_immediate(pkt, server);
}
void varcache_fill_unset(VarCache *src, PgSocket *dst)
}
}
+void varcache_deinit(void)
+{
+ strpool_free(vpool);
+ vpool = NULL;
+}