From 0ba0e321726e02c54c4440282b51f25078fe8d81 Mon Sep 17 00:00:00 2001 From: Bruce Momjian Date: Tue, 12 Sep 2000 04:15:58 +0000 Subject: [PATCH] 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 --- src/backend/commands/view.c | 10 +++++++- src/backend/rewrite/rewriteDefine.c | 9 ++++--- src/backend/utils/adt/ruleutils.c | 37 +++++++++++++---------------- src/bin/pg_dump/pg_dump.c | 14 +++++++++-- 4 files changed, 44 insertions(+), 26 deletions(-) diff --git a/src/backend/commands/view.c b/src/backend/commands/view.c index 8503eb3a7e..01e23d1315 100644 --- a/src/backend/commands/view.c +++ b/src/backend/commands/view.c @@ -6,7 +6,7 @@ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc * 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); 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; } diff --git a/src/backend/rewrite/rewriteDefine.c b/src/backend/rewrite/rewriteDefine.c index 5f9907080b..c9315f6d33 100644 --- a/src/backend/rewrite/rewriteDefine.c +++ b/src/backend/rewrite/rewriteDefine.c @@ -8,7 +8,7 @@ * * * 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 "rewrite/rewriteDefine.h" #include "rewrite/rewriteSupport.h" +#include "commands/view.h" /* @@ -218,7 +219,7 @@ DefineQueryRewrite(RuleStmt *stmt) Form_pg_attribute attr; char *attname; int i; - char expected_name[NAMEDATALEN + 5]; + char *expected_name; /* * So there cannot be INSTEAD NOTHING, ... @@ -305,12 +306,14 @@ DefineQueryRewrite(RuleStmt *stmt) /* * ... 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) { elog(ERROR, "view rule for %s must be named %s", event_obj->relname, expected_name); } + pfree(expected_name); } /* diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c index 7d44657429..571854d446 100644 --- a/src/backend/utils/adt/ruleutils.c +++ b/src/backend/utils/adt/ruleutils.c @@ -3,7 +3,7 @@ * out of its tuple * * 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. * @@ -51,6 +51,7 @@ #include "parser/parse_expr.h" #include "parser/parsetree.h" #include "utils/lsyscache.h" +#include "commands/view.h" /* ---------- @@ -79,7 +80,7 @@ static char *rulename = NULL; static void *plan_getrule = NULL; static char *query_getrule = "SELECT * FROM pg_rewrite WHERE rulename = $1"; 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 char *query_getam = "SELECT * FROM pg_am WHERE oid = $1"; static void *plan_getopclass = NULL; @@ -138,7 +139,7 @@ pg_get_ruledef(PG_FUNCTION_ARGS) 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)); @@ -226,23 +227,22 @@ pg_get_ruledef(PG_FUNCTION_ARGS) Datum pg_get_viewdef(PG_FUNCTION_ARGS) { - Name rname = PG_GETARG_NAME(0); + Name vname = PG_GETARG_NAME(0); text *ruledef; - Datum args[2]; - char nulls[3]; + Datum args[1]; + char nulls[2]; int spirc; HeapTuple ruletup; TupleDesc rulettc; StringInfoData buf; int len; - char name1[NAMEDATALEN + 5]; - char name2[NAMEDATALEN + 5]; + char *name; /* ---------- - * 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 @@ -259,28 +259,24 @@ pg_get_viewdef(PG_FUNCTION_ARGS) */ if (plan_getview == NULL) { - Oid argtypes[2]; + Oid argtypes[1]; void *plan; argtypes[0] = NAMEOID; - argtypes[1] = NAMEOID; - plan = SPI_prepare(query_getview, 2, argtypes); + plan = SPI_prepare(query_getview, 1, argtypes); if (plan == NULL) elog(ERROR, "SPI_prepare() failed for \"%s\"", query_getview); 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); - sprintf(name2, "_ret%s", rulename); - args[0] = PointerGetDatum(name1); - args[1] = PointerGetDatum(name2); + name = MakeRetrieveViewRuleName(rulename); + args[0] = PointerGetDatum(name); nulls[0] = ' '; - nulls[1] = ' '; - nulls[2] = '\0'; + nulls[1] = '\0'; spirc = SPI_execp(plan_getview, args, nulls, 1); if (spirc != SPI_OK_SELECT) 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; memcpy(VARDATA(ruledef), buf.data, buf.len); pfree(buf.data); + pfree(name); /* ---------- * Disconnect from SPI manager diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c index d581f13a4a..372ff9be4c 100644 --- a/src/bin/pg_dump/pg_dump.c +++ b/src/bin/pg_dump/pg_dump.c @@ -22,7 +22,7 @@ * * * 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 * @@ -256,12 +256,22 @@ isViewRule(char *relname) { PGresult *res; int ntups; + char rulename[NAMEDATALEN + 5]; PQExpBuffer query = createPQExpBuffer(); appendPQExpBuffer(query, "select relname from pg_class, pg_rewrite "); appendPQExpBuffer(query, "where pg_class.oid = ev_class "); 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); if (!res ||