O.K. -
Here's the multibyte aware version of my patch to fix the truncation of the rulename autogenerated during a CREATE VIEW. I've modified all the places in the backend that want to construct the rulename to use the MakeRetrieveViewRuleName(), where I put the #ifdef MULTIBYTE, so that's the only place that knows how to construct a view rulename. Except pg_dump, where I replicated the code, since it's a standalone binary. The only effect the enduser will see is that views with names len(name) > NAMEDATALEN-4 will fail to be created, if the derived rulename clases with an existing rule: i.e. the user is trying to create two views with long names whose first difference is past NAMEDATALEN-4 (but before NAMEDATALEN: that'll error out after the viewname truncation.) In no case will the user get left with a table without a view rule, as the current code does. Ross Reedstrom
This commit is contained in:
parent
b1777d5f99
commit
0ba0e32172
@ -6,7 +6,7 @@
|
|||||||
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
|
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $Id: view.c,v 1.45 2000/07/04 06:11:30 tgl Exp $
|
* $Id: view.c,v 1.46 2000/09/12 04:15:56 momjian Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -120,6 +120,14 @@ MakeRetrieveViewRuleName(char *viewName)
|
|||||||
buf = palloc(strlen(viewName) + 5);
|
buf = palloc(strlen(viewName) + 5);
|
||||||
snprintf(buf, strlen(viewName) + 5, "_RET%s", viewName);
|
snprintf(buf, strlen(viewName) + 5, "_RET%s", viewName);
|
||||||
|
|
||||||
|
#ifdef MULTIBYTE
|
||||||
|
int len;
|
||||||
|
len = pg_mbcliplen(buf,strlen(buf),NAMEDATALEN-1);
|
||||||
|
buf[len] = '\0';
|
||||||
|
#else
|
||||||
|
buf[NAMEDATALEN-1] = '\0';
|
||||||
|
#endif
|
||||||
|
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteDefine.c,v 1.49 2000/07/30 22:13:51 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteDefine.c,v 1.50 2000/09/12 04:15:57 momjian Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -23,6 +23,7 @@
|
|||||||
#include "parser/parse_relation.h"
|
#include "parser/parse_relation.h"
|
||||||
#include "rewrite/rewriteDefine.h"
|
#include "rewrite/rewriteDefine.h"
|
||||||
#include "rewrite/rewriteSupport.h"
|
#include "rewrite/rewriteSupport.h"
|
||||||
|
#include "commands/view.h"
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -218,7 +219,7 @@ DefineQueryRewrite(RuleStmt *stmt)
|
|||||||
Form_pg_attribute attr;
|
Form_pg_attribute attr;
|
||||||
char *attname;
|
char *attname;
|
||||||
int i;
|
int i;
|
||||||
char expected_name[NAMEDATALEN + 5];
|
char *expected_name;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* So there cannot be INSTEAD NOTHING, ...
|
* So there cannot be INSTEAD NOTHING, ...
|
||||||
@ -305,12 +306,14 @@ DefineQueryRewrite(RuleStmt *stmt)
|
|||||||
/*
|
/*
|
||||||
* ... and finally the rule must be named _RETviewname.
|
* ... and finally the rule must be named _RETviewname.
|
||||||
*/
|
*/
|
||||||
sprintf(expected_name, "_RET%s", event_obj->relname);
|
|
||||||
|
expected_name = MakeRetrieveViewRuleName(event_obj->relname);
|
||||||
if (strcmp(expected_name, stmt->rulename) != 0)
|
if (strcmp(expected_name, stmt->rulename) != 0)
|
||||||
{
|
{
|
||||||
elog(ERROR, "view rule for %s must be named %s",
|
elog(ERROR, "view rule for %s must be named %s",
|
||||||
event_obj->relname, expected_name);
|
event_obj->relname, expected_name);
|
||||||
}
|
}
|
||||||
|
pfree(expected_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
* out of its tuple
|
* out of its tuple
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.59 2000/08/12 04:04:53 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.60 2000/09/12 04:15:58 momjian Exp $
|
||||||
*
|
*
|
||||||
* This software is copyrighted by Jan Wieck - Hamburg.
|
* This software is copyrighted by Jan Wieck - Hamburg.
|
||||||
*
|
*
|
||||||
@ -51,6 +51,7 @@
|
|||||||
#include "parser/parse_expr.h"
|
#include "parser/parse_expr.h"
|
||||||
#include "parser/parsetree.h"
|
#include "parser/parsetree.h"
|
||||||
#include "utils/lsyscache.h"
|
#include "utils/lsyscache.h"
|
||||||
|
#include "commands/view.h"
|
||||||
|
|
||||||
|
|
||||||
/* ----------
|
/* ----------
|
||||||
@ -79,7 +80,7 @@ static char *rulename = NULL;
|
|||||||
static void *plan_getrule = NULL;
|
static void *plan_getrule = NULL;
|
||||||
static char *query_getrule = "SELECT * FROM pg_rewrite WHERE rulename = $1";
|
static char *query_getrule = "SELECT * FROM pg_rewrite WHERE rulename = $1";
|
||||||
static void *plan_getview = NULL;
|
static void *plan_getview = NULL;
|
||||||
static char *query_getview = "SELECT * FROM pg_rewrite WHERE rulename = $1 or rulename = $2";
|
static char *query_getview = "SELECT * FROM pg_rewrite WHERE rulename = $1";
|
||||||
static void *plan_getam = NULL;
|
static void *plan_getam = NULL;
|
||||||
static char *query_getam = "SELECT * FROM pg_am WHERE oid = $1";
|
static char *query_getam = "SELECT * FROM pg_am WHERE oid = $1";
|
||||||
static void *plan_getopclass = NULL;
|
static void *plan_getopclass = NULL;
|
||||||
@ -138,7 +139,7 @@ pg_get_ruledef(PG_FUNCTION_ARGS)
|
|||||||
int len;
|
int len;
|
||||||
|
|
||||||
/* ----------
|
/* ----------
|
||||||
* We need the rules name somewhere deep down
|
* We need the rules name somewhere deep down: rulename is global
|
||||||
* ----------
|
* ----------
|
||||||
*/
|
*/
|
||||||
rulename = pstrdup(NameStr(*rname));
|
rulename = pstrdup(NameStr(*rname));
|
||||||
@ -226,23 +227,22 @@ pg_get_ruledef(PG_FUNCTION_ARGS)
|
|||||||
Datum
|
Datum
|
||||||
pg_get_viewdef(PG_FUNCTION_ARGS)
|
pg_get_viewdef(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
Name rname = PG_GETARG_NAME(0);
|
Name vname = PG_GETARG_NAME(0);
|
||||||
text *ruledef;
|
text *ruledef;
|
||||||
Datum args[2];
|
Datum args[1];
|
||||||
char nulls[3];
|
char nulls[2];
|
||||||
int spirc;
|
int spirc;
|
||||||
HeapTuple ruletup;
|
HeapTuple ruletup;
|
||||||
TupleDesc rulettc;
|
TupleDesc rulettc;
|
||||||
StringInfoData buf;
|
StringInfoData buf;
|
||||||
int len;
|
int len;
|
||||||
char name1[NAMEDATALEN + 5];
|
char *name;
|
||||||
char name2[NAMEDATALEN + 5];
|
|
||||||
|
|
||||||
/* ----------
|
/* ----------
|
||||||
* We need the rules name somewhere deep down
|
* We need the view name somewhere deep down
|
||||||
* ----------
|
* ----------
|
||||||
*/
|
*/
|
||||||
rulename = pstrdup(NameStr(*rname));
|
rulename = pstrdup(NameStr(*vname));
|
||||||
|
|
||||||
/* ----------
|
/* ----------
|
||||||
* Connect to SPI manager
|
* Connect to SPI manager
|
||||||
@ -259,28 +259,24 @@ pg_get_viewdef(PG_FUNCTION_ARGS)
|
|||||||
*/
|
*/
|
||||||
if (plan_getview == NULL)
|
if (plan_getview == NULL)
|
||||||
{
|
{
|
||||||
Oid argtypes[2];
|
Oid argtypes[1];
|
||||||
void *plan;
|
void *plan;
|
||||||
|
|
||||||
argtypes[0] = NAMEOID;
|
argtypes[0] = NAMEOID;
|
||||||
argtypes[1] = NAMEOID;
|
plan = SPI_prepare(query_getview, 1, argtypes);
|
||||||
plan = SPI_prepare(query_getview, 2, argtypes);
|
|
||||||
if (plan == NULL)
|
if (plan == NULL)
|
||||||
elog(ERROR, "SPI_prepare() failed for \"%s\"", query_getview);
|
elog(ERROR, "SPI_prepare() failed for \"%s\"", query_getview);
|
||||||
plan_getview = SPI_saveplan(plan);
|
plan_getview = SPI_saveplan(plan);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ----------
|
/* ----------
|
||||||
* Get the pg_rewrite tuple for this rule
|
* Get the pg_rewrite tuple for this rule: rulename is actually viewname here
|
||||||
* ----------
|
* ----------
|
||||||
*/
|
*/
|
||||||
sprintf(name1, "_RET%s", rulename);
|
name = MakeRetrieveViewRuleName(rulename);
|
||||||
sprintf(name2, "_ret%s", rulename);
|
args[0] = PointerGetDatum(name);
|
||||||
args[0] = PointerGetDatum(name1);
|
|
||||||
args[1] = PointerGetDatum(name2);
|
|
||||||
nulls[0] = ' ';
|
nulls[0] = ' ';
|
||||||
nulls[1] = ' ';
|
nulls[1] = '\0';
|
||||||
nulls[2] = '\0';
|
|
||||||
spirc = SPI_execp(plan_getview, args, nulls, 1);
|
spirc = SPI_execp(plan_getview, args, nulls, 1);
|
||||||
if (spirc != SPI_OK_SELECT)
|
if (spirc != SPI_OK_SELECT)
|
||||||
elog(ERROR, "failed to get pg_rewrite tuple for view %s", rulename);
|
elog(ERROR, "failed to get pg_rewrite tuple for view %s", rulename);
|
||||||
@ -302,6 +298,7 @@ pg_get_viewdef(PG_FUNCTION_ARGS)
|
|||||||
VARATT_SIZEP(ruledef) = len;
|
VARATT_SIZEP(ruledef) = len;
|
||||||
memcpy(VARDATA(ruledef), buf.data, buf.len);
|
memcpy(VARDATA(ruledef), buf.data, buf.len);
|
||||||
pfree(buf.data);
|
pfree(buf.data);
|
||||||
|
pfree(name);
|
||||||
|
|
||||||
/* ----------
|
/* ----------
|
||||||
* Disconnect from SPI manager
|
* Disconnect from SPI manager
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.163 2000/08/07 12:32:54 pjw Exp $
|
* $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.164 2000/09/12 04:15:58 momjian Exp $
|
||||||
*
|
*
|
||||||
* Modifications - 6/10/96 - dave@bensoft.com - version 1.13.dhb
|
* Modifications - 6/10/96 - dave@bensoft.com - version 1.13.dhb
|
||||||
*
|
*
|
||||||
@ -256,12 +256,22 @@ isViewRule(char *relname)
|
|||||||
{
|
{
|
||||||
PGresult *res;
|
PGresult *res;
|
||||||
int ntups;
|
int ntups;
|
||||||
|
char rulename[NAMEDATALEN + 5];
|
||||||
PQExpBuffer query = createPQExpBuffer();
|
PQExpBuffer query = createPQExpBuffer();
|
||||||
|
|
||||||
appendPQExpBuffer(query, "select relname from pg_class, pg_rewrite ");
|
appendPQExpBuffer(query, "select relname from pg_class, pg_rewrite ");
|
||||||
appendPQExpBuffer(query, "where pg_class.oid = ev_class ");
|
appendPQExpBuffer(query, "where pg_class.oid = ev_class ");
|
||||||
appendPQExpBuffer(query, "and pg_rewrite.ev_type = '1' ");
|
appendPQExpBuffer(query, "and pg_rewrite.ev_type = '1' ");
|
||||||
appendPQExpBuffer(query, "and rulename = '_RET%s'", relname);
|
snprintf(rulename,NAMEDATALEN + 5,"_RET%s",relname);
|
||||||
|
#ifdef MULTIBYTE
|
||||||
|
int len;
|
||||||
|
len = pg_mbcliplen(rulename,strlen(rulename),NAMEDATALEN-1);
|
||||||
|
rulename[len] = '\0';
|
||||||
|
#else
|
||||||
|
rulename[NAMEDATALEN-1] = '\0';
|
||||||
|
#endif
|
||||||
|
|
||||||
|
appendPQExpBuffer(query, "and rulename = '%s'", rulename);
|
||||||
|
|
||||||
res = PQexec(g_conn, query->data);
|
res = PQexec(g_conn, query->data);
|
||||||
if (!res ||
|
if (!res ||
|
||||||
|
Loading…
x
Reference in New Issue
Block a user