mirror of
https://github.com/postgres/postgres.git
synced 2025-06-16 06:01:02 +03:00
Repair core dump when trying to delete an entry from an already-NULL
datconfig or useconfig field. Per report from Dustin Sallings.
This commit is contained in:
@ -9,7 +9,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/commands/dbcommands.c,v 1.107 2002/11/02 18:41:21 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/commands/dbcommands.c,v 1.108 2002/12/02 05:20:47 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -561,7 +561,10 @@ AlterDatabaseSet(AlterDatabaseSetStmt *stmt)
|
|||||||
else
|
else
|
||||||
a = GUCArrayDelete(a, stmt->variable);
|
a = GUCArrayDelete(a, stmt->variable);
|
||||||
|
|
||||||
|
if (a)
|
||||||
repl_val[Anum_pg_database_datconfig - 1] = PointerGetDatum(a);
|
repl_val[Anum_pg_database_datconfig - 1] = PointerGetDatum(a);
|
||||||
|
else
|
||||||
|
repl_null[Anum_pg_database_datconfig - 1] = 'n';
|
||||||
}
|
}
|
||||||
|
|
||||||
newtuple = heap_modifytuple(tuple, rel, repl_val, repl_null, repl_repl);
|
newtuple = heap_modifytuple(tuple, rel, repl_val, repl_null, repl_repl);
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $Header: /cvsroot/pgsql/src/backend/commands/user.c,v 1.113 2002/10/21 19:46:45 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/commands/user.c,v 1.114 2002/12/02 05:20:47 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -915,8 +915,10 @@ AlterUserSet(AlterUserSetStmt *stmt)
|
|||||||
|
|
||||||
repl_repl[Anum_pg_shadow_useconfig - 1] = 'r';
|
repl_repl[Anum_pg_shadow_useconfig - 1] = 'r';
|
||||||
if (strcmp(stmt->variable, "all") == 0 && valuestr == NULL)
|
if (strcmp(stmt->variable, "all") == 0 && valuestr == NULL)
|
||||||
|
{
|
||||||
/* RESET ALL */
|
/* RESET ALL */
|
||||||
repl_null[Anum_pg_shadow_useconfig - 1] = 'n';
|
repl_null[Anum_pg_shadow_useconfig - 1] = 'n';
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Datum datum;
|
Datum datum;
|
||||||
@ -935,7 +937,10 @@ AlterUserSet(AlterUserSetStmt *stmt)
|
|||||||
else
|
else
|
||||||
array = GUCArrayDelete(array, stmt->variable);
|
array = GUCArrayDelete(array, stmt->variable);
|
||||||
|
|
||||||
|
if (array)
|
||||||
repl_val[Anum_pg_shadow_useconfig - 1] = PointerGetDatum(array);
|
repl_val[Anum_pg_shadow_useconfig - 1] = PointerGetDatum(array);
|
||||||
|
else
|
||||||
|
repl_null[Anum_pg_shadow_useconfig - 1] = 'n';
|
||||||
}
|
}
|
||||||
|
|
||||||
newtuple = heap_modifytuple(oldtuple, rel, repl_val, repl_null, repl_repl);
|
newtuple = heap_modifytuple(oldtuple, rel, repl_val, repl_null, repl_repl);
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
* command, configuration file, and command line options.
|
* command, configuration file, and command line options.
|
||||||
* See src/backend/utils/misc/README for more information.
|
* See src/backend/utils/misc/README for more information.
|
||||||
*
|
*
|
||||||
* $Header: /cvsroot/pgsql/src/backend/utils/misc/guc.c,v 1.107 2002/11/21 00:42:19 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/utils/misc/guc.c,v 1.108 2002/12/02 05:20:47 tgl Exp $
|
||||||
*
|
*
|
||||||
* Copyright 2000 by PostgreSQL Global Development Group
|
* Copyright 2000 by PostgreSQL Global Development Group
|
||||||
* Written by Peter Eisentraut <peter_e@gmx.net>.
|
* Written by Peter Eisentraut <peter_e@gmx.net>.
|
||||||
@ -2754,7 +2754,7 @@ assign_defaultxactisolevel(const char *newval, bool doit, bool interactive)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Handle options fetched from pg_database.datconfig or pg_shadow.useconfig.
|
* Handle options fetched from pg_database.datconfig or pg_shadow.useconfig.
|
||||||
* The array parameter must be an array of TEXT.
|
* The array parameter must be an array of TEXT (it must not be NULL).
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
ProcessGUCArray(ArrayType *array, GucSource source)
|
ProcessGUCArray(ArrayType *array, GucSource source)
|
||||||
@ -2809,7 +2809,10 @@ ProcessGUCArray(ArrayType *array, GucSource source)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Add an entry to an option array. The array parameter may be NULL
|
||||||
|
* to indicate the current table entry is NULL.
|
||||||
|
*/
|
||||||
ArrayType *
|
ArrayType *
|
||||||
GUCArrayAdd(ArrayType *array, const char *name, const char *value)
|
GUCArrayAdd(ArrayType *array, const char *name, const char *value)
|
||||||
{
|
{
|
||||||
@ -2880,7 +2883,11 @@ GUCArrayAdd(ArrayType *array, const char *name, const char *value)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Delete an entry from an option array. The array parameter may be NULL
|
||||||
|
* to indicate the current table entry is NULL. Also, if the return value
|
||||||
|
* is NULL then a null should be stored.
|
||||||
|
*/
|
||||||
ArrayType *
|
ArrayType *
|
||||||
GUCArrayDelete(ArrayType *array, const char *name)
|
GUCArrayDelete(ArrayType *array, const char *name)
|
||||||
{
|
{
|
||||||
@ -2889,16 +2896,17 @@ GUCArrayDelete(ArrayType *array, const char *name)
|
|||||||
int index;
|
int index;
|
||||||
|
|
||||||
Assert(name);
|
Assert(name);
|
||||||
Assert(array);
|
|
||||||
|
|
||||||
/* test if the option is valid */
|
/* test if the option is valid */
|
||||||
set_config_option(name, NULL,
|
set_config_option(name, NULL,
|
||||||
superuser() ? PGC_SUSET : PGC_USERSET,
|
superuser() ? PGC_SUSET : PGC_USERSET,
|
||||||
PGC_S_SESSION, false, false);
|
PGC_S_SESSION, false, false);
|
||||||
|
|
||||||
newarray = construct_array(NULL, 0,
|
/* if array is currently null, then surely nothing to delete */
|
||||||
TEXTOID,
|
if (!array)
|
||||||
-1, false, 'i');
|
return NULL;
|
||||||
|
|
||||||
|
newarray = NULL;
|
||||||
index = 1;
|
index = 1;
|
||||||
|
|
||||||
for (i = 1; i <= ARR_DIMS(array)[0]; i++)
|
for (i = 1; i <= ARR_DIMS(array)[0]; i++)
|
||||||
@ -2917,10 +2925,14 @@ GUCArrayDelete(ArrayType *array, const char *name)
|
|||||||
continue;
|
continue;
|
||||||
val = DatumGetCString(DirectFunctionCall1(textout, d));
|
val = DatumGetCString(DirectFunctionCall1(textout, d));
|
||||||
|
|
||||||
|
/* ignore entry if it's what we want to delete */
|
||||||
if (strncmp(val, name, strlen(name)) == 0
|
if (strncmp(val, name, strlen(name)) == 0
|
||||||
&& val[strlen(name)] == '=')
|
&& val[strlen(name)] == '=')
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
/* else add it to the output array */
|
||||||
|
if (newarray)
|
||||||
|
{
|
||||||
isnull = false;
|
isnull = false;
|
||||||
newarray = array_set(newarray, 1, &index,
|
newarray = array_set(newarray, 1, &index,
|
||||||
d,
|
d,
|
||||||
@ -2929,6 +2941,12 @@ GUCArrayDelete(ArrayType *array, const char *name)
|
|||||||
false /* TEXT's typbyval */ ,
|
false /* TEXT's typbyval */ ,
|
||||||
'i' /* TEXT's typalign */ ,
|
'i' /* TEXT's typalign */ ,
|
||||||
&isnull);
|
&isnull);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
newarray = construct_array(&d, 1,
|
||||||
|
TEXTOID,
|
||||||
|
-1, false, 'i');
|
||||||
|
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user