1
0
mirror of https://github.com/postgres/postgres.git synced 2025-11-09 06:21:09 +03:00

Add FILLFACTOR to CREATE INDEX.

ITAGAKI Takahiro
This commit is contained in:
Bruce Momjian
2006-07-02 02:23:23 +00:00
parent 5d5c1416bf
commit 277807bd9e
65 changed files with 1458 additions and 309 deletions

View File

@@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/backend/parser/analyze.c,v 1.336 2006/06/27 03:43:20 momjian Exp $
* $PostgreSQL: pgsql/src/backend/parser/analyze.c,v 1.337 2006/07/02 02:23:20 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -757,7 +757,7 @@ transformCreateStmt(ParseState *pstate, CreateStmt *stmt,
cxt.blist = NIL;
cxt.alist = NIL;
cxt.pkey = NULL;
cxt.hasoids = interpretOidsOption(stmt->hasoids);
cxt.hasoids = interpretOidsOption(stmt->options);
/*
* Run through each primary element in the table creation clause. Separate
@@ -1282,6 +1282,7 @@ transformIndexConstraints(ParseState *pstate, CreateStmtContext *cxt)
index->relation = cxt->relation;
index->accessMethod = DEFAULT_INDEX_TYPE;
index->options = constraint->options;
index->tableSpace = constraint->indexspace;
index->indexParams = NIL;
index->whereClause = NULL;
@@ -1881,7 +1882,8 @@ transformSelectStmt(ParseState *pstate, SelectStmt *stmt)
if (stmt->intoColNames)
applyColumnNames(qry->targetList, stmt->intoColNames);
qry->intoHasOids = interpretOidsOption(stmt->intoHasOids);
qry->intoHasOids = interpretOidsOption(stmt->intoOptions);
qry->intoOptions = copyObject(stmt->intoOptions);
qry->intoOnCommit = stmt->intoOnCommit;
qry->intoTableSpaceName = stmt->intoTableSpaceName;
@@ -2752,7 +2754,7 @@ transformExecuteStmt(ParseState *pstate, ExecuteStmt *stmt)
paramtypes = FetchPreparedStatementParams(stmt->name);
stmt->into_has_oids = interpretOidsOption(stmt->into_contains_oids);
stmt->into_has_oids = interpretOidsOption(stmt->intoOptions);
if (stmt->params || paramtypes)
{

View File

@@ -11,7 +11,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.549 2006/07/02 01:58:36 momjian Exp $
* $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.550 2006/07/02 02:23:21 momjian Exp $
*
* HISTORY
* AUTHOR DATE MAJOR EVENT
@@ -53,6 +53,7 @@
#include "catalog/index.h"
#include "catalog/namespace.h"
#include "commands/defrem.h"
#include "nodes/makefuncs.h"
#include "parser/gramparse.h"
#include "storage/lmgr.h"
@@ -123,7 +124,6 @@ static void doNegateFloat(Value *v);
JoinType jtype;
DropBehavior dbehavior;
OnCommitAction oncommit;
ContainsOids withoids;
List *list;
Node *node;
Value *value;
@@ -228,11 +228,11 @@ static void doNegateFloat(Value *v);
%type <list> stmtblock stmtmulti
OptTableElementList TableElementList OptInherit definition
opt_distinct opt_definition func_args func_args_list
OptWith opt_distinct opt_definition func_args func_args_list
func_as createfunc_opt_list alterfunc_opt_list
aggr_args aggr_args_list old_aggr_definition old_aggr_list
oper_argtypes RuleActionList RuleActionMulti
opt_column_list columnList opt_name_list
opt_column_list columnList opt_name_list
sort_clause opt_sort_clause sortby_list index_params
name_list from_clause from_list opt_array_bounds
qualified_name_list any_name any_name_list
@@ -255,7 +255,6 @@ static void doNegateFloat(Value *v);
%type <boolean> TriggerForType OptTemp
%type <oncommit> OnCommitOption
%type <withoids> OptWithOids
%type <node> for_locking_item
%type <list> for_locking_clause opt_for_locking_clause for_locking_items
@@ -1559,6 +1558,32 @@ alter_rel_cmd:
n->name = $3;
$$ = (Node *)n;
}
/* ALTER [TABLE|INDEX] <name> SET (...) */
| SET definition
{
AlterTableCmd *n = makeNode(AlterTableCmd);
n->subtype = AT_SetOptions;
n->def = (Node *)$2;
$$ = (Node *)n;
}
| RESET definition
{
AlterTableCmd *n;
ListCell *cell;
foreach(cell, $2)
{
if (((DefElem *) lfirst(cell))->arg != NULL)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("parameters for RESET should not take values")));
}
n = makeNode(AlterTableCmd);
n->subtype = AT_SetOptions;
n->def = (Node *)$2;
$$ = (Node *)n;
}
;
alter_column_default:
@@ -1744,7 +1769,7 @@ opt_using:
*****************************************************************************/
CreateStmt: CREATE OptTemp TABLE qualified_name '(' OptTableElementList ')'
OptInherit OptWithOids OnCommitOption OptTableSpace
OptInherit OptWith OnCommitOption OptTableSpace
{
CreateStmt *n = makeNode(CreateStmt);
$4->istemp = $2;
@@ -1752,13 +1777,13 @@ CreateStmt: CREATE OptTemp TABLE qualified_name '(' OptTableElementList ')'
n->tableElts = $6;
n->inhRelations = $8;
n->constraints = NIL;
n->hasoids = $9;
n->options = $9;
n->oncommit = $10;
n->tablespacename = $11;
$$ = (Node *)n;
}
| CREATE OptTemp TABLE qualified_name OF qualified_name
'(' OptTableElementList ')' OptWithOids OnCommitOption OptTableSpace
'(' OptTableElementList ')' OptWith OnCommitOption OptTableSpace
{
/* SQL99 CREATE TABLE OF <UDT> (cols) seems to be satisfied
* by our inheritance capabilities. Let's try it...
@@ -1769,7 +1794,7 @@ CreateStmt: CREATE OptTemp TABLE qualified_name '(' OptTableElementList ')'
n->tableElts = $8;
n->inhRelations = list_make1($6);
n->constraints = NIL;
n->hasoids = $10;
n->options = $10;
n->oncommit = $11;
n->tablespacename = $12;
$$ = (Node *)n;
@@ -1905,7 +1930,7 @@ ColConstraintElem:
n->indexspace = $2;
$$ = (Node *)n;
}
| PRIMARY KEY OptConsTableSpace
| PRIMARY KEY opt_definition OptConsTableSpace
{
Constraint *n = makeNode(Constraint);
n->contype = CONSTR_PRIMARY;
@@ -1913,7 +1938,8 @@ ColConstraintElem:
n->raw_expr = NULL;
n->cooked_expr = NULL;
n->keys = NULL;
n->indexspace = $3;
n->options = $3;
n->indexspace = $4;
$$ = (Node *)n;
}
| CHECK '(' a_expr ')'
@@ -2085,7 +2111,7 @@ ConstraintElem:
n->indexspace = $5;
$$ = (Node *)n;
}
| PRIMARY KEY '(' columnList ')' OptConsTableSpace
| PRIMARY KEY '(' columnList ')' opt_definition OptConsTableSpace
{
Constraint *n = makeNode(Constraint);
n->contype = CONSTR_PRIMARY;
@@ -2093,7 +2119,8 @@ ConstraintElem:
n->raw_expr = NULL;
n->cooked_expr = NULL;
n->keys = $4;
n->indexspace = $6;
n->options = $6;
n->indexspace = $7;
$$ = (Node *)n;
}
| FOREIGN KEY '(' columnList ')' REFERENCES qualified_name
@@ -2187,10 +2214,13 @@ OptInherit: INHERITS '(' qualified_name_list ')' { $$ = $3; }
| /*EMPTY*/ { $$ = NIL; }
;
OptWithOids:
WITH OIDS { $$ = MUST_HAVE_OIDS; }
| WITHOUT OIDS { $$ = MUST_NOT_HAVE_OIDS; }
| /*EMPTY*/ { $$ = DEFAULT_OIDS; }
OptWith:
WITH OIDS { $$ = list_make1(defWithOids(true)); }
| WITHOUT OIDS { $$ = list_make1(defWithOids(false)); }
| WITH definition { $$ = $2; }
| WITH OIDS WITH definition { $$ = lappend($4, defWithOids(true)); }
| WITHOUT OIDS WITH definition { $$ = lappend($4, defWithOids(false)); }
| /*EMPTY*/ { $$ = NIL; }
;
OnCommitOption: ON COMMIT DROP { $$ = ONCOMMIT_DROP; }
@@ -2215,7 +2245,7 @@ OptConsTableSpace: USING INDEX TABLESPACE name { $$ = $4; }
CreateAsStmt:
CREATE OptTemp TABLE qualified_name OptCreateAs
OptWithOids OnCommitOption OptTableSpace AS SelectStmt
OptWith OnCommitOption OptTableSpace AS SelectStmt
{
/*
* When the SelectStmt is a set-operation tree, we must
@@ -2232,7 +2262,7 @@ CreateAsStmt:
$4->istemp = $2;
n->into = $4;
n->intoColNames = $5;
n->intoHasOids = $6;
n->intoOptions = $6;
n->intoOnCommit = $7;
n->intoTableSpaceName = $8;
$$ = $10;
@@ -3630,7 +3660,7 @@ opt_granted_by: GRANTED BY RoleId { $$ = $3; }
*****************************************************************************/
IndexStmt: CREATE index_opt_unique INDEX index_name ON qualified_name
access_method_clause '(' index_params ')' OptTableSpace where_clause
access_method_clause '(' index_params ')' opt_definition OptTableSpace where_clause
{
IndexStmt *n = makeNode(IndexStmt);
n->unique = $2;
@@ -3638,8 +3668,9 @@ IndexStmt: CREATE index_opt_unique INDEX index_name ON qualified_name
n->relation = $6;
n->accessMethod = $7;
n->indexParams = $9;
n->tableSpace = $11;
n->whereClause = $12;
n->options = $11;
n->tableSpace = $12;
n->whereClause = $13;
$$ = (Node *)n;
}
;
@@ -5264,7 +5295,7 @@ ExecuteStmt: EXECUTE name execute_param_clause
$$ = (Node *) n;
}
| CREATE OptTemp TABLE qualified_name OptCreateAs
OptWithOids OnCommitOption OptTableSpace AS
OptWith OnCommitOption OptTableSpace AS
EXECUTE name execute_param_clause
{
ExecuteStmt *n = makeNode(ExecuteStmt);
@@ -5272,7 +5303,7 @@ ExecuteStmt: EXECUTE name execute_param_clause
n->params = $12;
$4->istemp = $2;
n->into = $4;
n->into_contains_oids = $6;
n->intoOptions = $6;
n->into_on_commit = $7;
n->into_tbl_space = $8;
if ($5)
@@ -5606,7 +5637,6 @@ simple_select:
n->targetList = $3;
n->into = $4;
n->intoColNames = NIL;
n->intoHasOids = DEFAULT_OIDS;
n->fromClause = $5;
n->whereClause = $6;
n->groupClause = $7;

View File

@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/parser/parse_clause.c,v 1.149 2006/03/16 00:31:55 tgl Exp $
* $PostgreSQL: pgsql/src/backend/parser/parse_clause.c,v 1.150 2006/07/02 02:23:21 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -17,6 +17,7 @@
#include "access/heapam.h"
#include "catalog/heap.h"
#include "commands/defrem.h"
#include "nodes/makefuncs.h"
#include "optimizer/clauses.h"
#include "optimizer/tlist.h"
@@ -33,6 +34,7 @@
#include "rewrite/rewriteManip.h"
#include "utils/builtins.h"
#include "utils/guc.h"
#include "utils/memutils.h"
#define ORDER_CLAUSE 0
@@ -64,6 +66,8 @@ static Node *buildMergedJoinVar(ParseState *pstate, JoinType jointype,
Var *l_colvar, Var *r_colvar);
static TargetEntry *findTargetlistEntry(ParseState *pstate, Node *node,
List **tlist, int clause);
static bool OptionMatches(text *t, const char* kw, char **str, Size *len);
static Datum OptionToText(DefElem *def);
/*
@@ -212,29 +216,280 @@ interpretInhOption(InhOption inhOpt)
}
/*
* Given an enum that indicates whether WITH / WITHOUT OIDS was
* Given a List that indicates whether WITH / WITHOUT OIDS was
* specified by the user, return true iff the specified table/result
* set should be created with OIDs. This needs to be done after
* parsing the query string because the return value can depend upon
* the default_with_oids GUC var.
*/
bool
interpretOidsOption(ContainsOids opt)
interpretOidsOption(List *options)
{
switch (opt)
ListCell *cell;
foreach(cell, options)
{
case MUST_HAVE_OIDS:
return true;
DefElem *def = (DefElem *) lfirst(cell);
case MUST_NOT_HAVE_OIDS:
return false;
case DEFAULT_OIDS:
return default_with_oids;
if (pg_strcasecmp(def->defname, "oids") == 0)
return defGetBoolean(def);
}
elog(ERROR, "bogus ContainsOids value: %d", opt);
return false; /* keep compiler quiet */
/* oids option is not specified. */
return default_with_oids;
}
/*
* Test if t is start with 'kw='.
*/
static bool
OptionMatches(text *t, const char* kw, char **str, Size *len)
{
char *text_str = (char *) VARATT_DATA(t);
int text_len = VARATT_SIZE(t) - VARHDRSZ;
Size kwlen = strlen(kw);
if (text_len > kwlen && text_str[kwlen] == '=' &&
pg_strncasecmp(text_str, kw, kwlen) == 0)
{
*str = text_str + kwlen + 1;
*len = text_len - kwlen - 1;
return true;
}
return false;
}
/*
* Flatten a DefElem to a text like as 'defname=arg'.
*/
static Datum
OptionToText(DefElem *def)
{
text *t;
char *value = defGetString(def);
Size len = VARHDRSZ + strlen(def->defname) + 1 + strlen(value);
t = palloc(len + 1);
VARATT_SIZEP(t) = len;
sprintf((char *) VARATT_DATA(t), "%s=%s", def->defname, value);
return PointerGetDatum(t);
}
/*
* Merge option array and option list.
*
* array Existing option, or NULL if new option.
* list List of DefElems to be added to array.
*/
ArrayType *
OptionBuild(ArrayType *array, List *list)
{
ListCell *cell;
bool *used;
int index;
int o;
ArrayType *result;
ArrayBuildState *astate;
MemoryContext myContext;
MemoryContext oldContext;
if (list_length(list) == 0)
{
/* no additinal elements, so just clone. */
if (array == NULL)
return NULL;
result = palloc(VARATT_SIZE(array));
memcpy(result, array, VARATT_SIZE(array));
return result;
}
/* Make a temporary context to hold all the junk */
myContext = AllocSetContextCreate(CurrentMemoryContext,
"OptionBuild",
ALLOCSET_DEFAULT_MINSIZE,
ALLOCSET_DEFAULT_INITSIZE,
ALLOCSET_DEFAULT_MAXSIZE);
oldContext = MemoryContextSwitchTo(myContext);
astate = NULL;
used = (bool *) palloc0(sizeof(bool) * list_length(list));
if (array)
{
Assert(ARR_ELEMTYPE(array) == TEXTOID);
Assert(ARR_NDIM(array) == 1);
Assert(ARR_LBOUND(array)[0] == 1);
for (o = 1; o <= ARR_DIMS(array)[0]; o++)
{
bool isnull;
Datum datum;
datum = array_ref(array, 1, &o,
-1 /* varlenarray */ ,
-1 /* TEXT's typlen */ ,
false /* TEXT's typbyval */ ,
'i' /* TEXT's typalign */ ,
&isnull);
if (isnull)
continue;
index = 0;
foreach(cell, list)
{
DefElem *def = lfirst(cell);
/*
* We ignore 'oids' item because it is stored
* in pg_class.relhasoids.
*/
if (!used[index] &&
pg_strcasecmp(def->defname, "oids") != 0)
{
char *value_str;
Size value_len;
if (OptionMatches(DatumGetTextP(datum),
def->defname, &value_str, &value_len))
{
used[index] = true;
if (def->arg)
{
/* Replace an existing option. */
datum = OptionToText(def);
goto next; /* skip remain items in list */
}
else
{
/* Remove the option from array. */
goto skip;
}
}
}
index++;
}
/*
* The datum is an existing parameter and is not modified.
* Fall down.
*/
next:
astate = accumArrayResult(astate, datum, false, TEXTOID, myContext);
skip:
;
}
}
/*
* add options not in array
*/
index = 0;
foreach(cell, list)
{
DefElem *def = lfirst(cell);
if (!used[index] && def->arg &&
pg_strcasecmp(def->defname, "oids") != 0)
{
astate = accumArrayResult(astate, OptionToText(def),
false, TEXTOID, myContext);
}
index++;
}
if (astate)
result = DatumGetArrayTypeP(makeArrayResult(astate, oldContext));
else
result = NULL;
MemoryContextSwitchTo(oldContext);
MemoryContextDelete(myContext);
return result;
}
/*
* Support routine to parse options.
*
* options List of DefElems
* num length of kwds
* kwds supported keywords
* strict Throw error if unsupported option is found.
*
* FIXME: memory is leaked in kwds[].arg.
*/
void
OptionParse(ArrayType *options, Size num, DefElem kwds[], bool strict)
{
Size k;
int o;
for (k = 0; k < num; k++)
{
Assert(kwds[k].defname);
kwds[k].arg = NULL;
}
if (options == NULL)
return; /* use default for all */
Assert(ARR_ELEMTYPE(options) == TEXTOID);
Assert(ARR_NDIM(options) == 1);
Assert(ARR_LBOUND(options)[0] == 1);
for (o = 1; o <= ARR_DIMS(options)[0]; o++)
{
bool isnull;
Datum datum;
datum = array_ref(options, 1, &o,
-1 /* varlenarray */ ,
-1 /* TEXT's typlen */ ,
false /* TEXT's typbyval */ ,
'i' /* TEXT's typalign */ ,
&isnull);
if (isnull)
continue;
for (k = 0; k < num; k++)
{
char *value_str;
Size value_len;
if (OptionMatches(DatumGetTextP(datum),
kwds[k].defname, &value_str, &value_len))
{
char *value;
if (kwds[k].arg != NULL)
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("duplicated parameter %s",
kwds[k].defname)));
/* copy value as Value node */
value = (char *) palloc(value_len + 1);
strncpy(value, value_str, value_len);
value[value_len] = '\0';
kwds[k].arg = (Node *) makeString(value);
goto next; /* skip remain keywords */
}
}
/* parameter is not in kwds */
if (strict)
{
char *c = DatumGetCString(DirectFunctionCall1(textout, datum));
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("unsupported parameter %s", c)));
}
next:;
}
}
/*