Columnar: support relation options with ALTER TABLE. (#5935)

Columnar: support relation options with ALTER TABLE.

Use ALTER TABLE ... SET/RESET to specify relation options rather than
alter_columnar_table_set() and alter_columnar_table_reset().

Not only is this more ergonomic, but it also allows better integration
because it can be treated like DDL on a regular table. For instance,
citus can use its own ProcessUtility_hook to distribute the new
settings to the shards.

DESCRIPTION: Columnar: support relation options with ALTER TABLE.
use-CreateViewDDLCommand
jeff-davis 2022-05-20 08:35:00 -07:00 committed by GitHub
parent 16fa0dad85
commit a9f8a60007
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
52 changed files with 1056 additions and 816 deletions

View File

@ -90,38 +90,25 @@ data.
Set options using:
```sql
alter_columnar_table_set(
relid REGCLASS,
chunk_group_row_limit INT4 DEFAULT NULL,
stripe_row_limit INT4 DEFAULT NULL,
compression NAME DEFAULT NULL,
compression_level INT4)
```
For example:
```sql
SELECT alter_columnar_table_set(
'my_columnar_table',
compression => 'none',
stripe_row_limit => 10000);
ALTER TABLE my_columnar_table SET
(columnar.compression = none, columnar.stripe_row_limit = 10000);
```
The following options are available:
* **compression**: `[none|pglz|zstd|lz4|lz4hc]` - set the compression type
* **columnar.compression**: `[none|pglz|zstd|lz4|lz4hc]` - set the compression type
for _newly-inserted_ data. Existing data will not be
recompressed/decompressed. The default value is `zstd` (if support
has been compiled in).
* **compression_level**: ``<integer>`` - Sets compression level. Valid
* **columnar.compression_level**: ``<integer>`` - Sets compression level. Valid
settings are from 1 through 19. If the compression method does not
support the level chosen, the closest level will be selected
instead.
* **stripe_row_limit**: ``<integer>`` - the maximum number of rows per
* **columnar.stripe_row_limit**: ``<integer>`` - the maximum number of rows per
stripe for _newly-inserted_ data. Existing stripes of data will not
be changed and may have more rows than this maximum value. The
default value is `150000`.
* **chunk_group_row_limit**: ``<integer>`` - the maximum number of rows per
* **columnar.chunk_group_row_limit**: ``<integer>`` - the maximum number of rows per
chunk for _newly-inserted_ data. Existing chunks of data will not be
changed and may have more rows than this maximum value. The default
value is `10000`.

View File

@ -59,6 +59,7 @@
#include "utils/rel.h"
#include "utils/relfilenodemap.h"
#define COLUMNAR_RELOPTION_NAMESPACE "columnar"
typedef struct
{
@ -82,6 +83,7 @@ typedef enum RowNumberLookupMode
FIND_GREATER
} RowNumberLookupMode;
static void ParseColumnarRelOptions(List *reloptions, ColumnarOptions *options);
static void InsertEmptyStripeMetadataRow(uint64 storageId, uint64 stripeId,
uint32 columnCount, uint32 chunkGroupRowCount,
uint64 firstRowNumber);
@ -218,6 +220,154 @@ InitColumnarOptions(Oid regclass)
}
/*
* ParseColumnarRelOptions - update the given 'options' using the given list
* of DefElem.
*/
static void
ParseColumnarRelOptions(List *reloptions, ColumnarOptions *options)
{
ListCell *lc = NULL;
foreach(lc, reloptions)
{
DefElem *elem = castNode(DefElem, lfirst(lc));
if (elem->defnamespace == NULL ||
strcmp(elem->defnamespace, COLUMNAR_RELOPTION_NAMESPACE) != 0)
{
ereport(ERROR, (errmsg("columnar options must have the prefix \"%s\"",
COLUMNAR_RELOPTION_NAMESPACE)));
}
if (strcmp(elem->defname, "chunk_group_row_limit") == 0)
{
options->chunkRowCount = (elem->arg == NULL) ?
columnar_chunk_group_row_limit : defGetInt64(elem);
if (options->chunkRowCount < CHUNK_ROW_COUNT_MINIMUM ||
options->chunkRowCount > CHUNK_ROW_COUNT_MAXIMUM)
{
ereport(ERROR, (errmsg("chunk group row count limit out of range"),
errhint("chunk group row count limit must be between "
UINT64_FORMAT " and " UINT64_FORMAT,
(uint64) CHUNK_ROW_COUNT_MINIMUM,
(uint64) CHUNK_ROW_COUNT_MAXIMUM)));
}
}
else if (strcmp(elem->defname, "stripe_row_limit") == 0)
{
options->stripeRowCount = (elem->arg == NULL) ?
columnar_stripe_row_limit : defGetInt64(elem);
if (options->stripeRowCount < STRIPE_ROW_COUNT_MINIMUM ||
options->stripeRowCount > STRIPE_ROW_COUNT_MAXIMUM)
{
ereport(ERROR, (errmsg("stripe row count limit out of range"),
errhint("stripe row count limit must be between "
UINT64_FORMAT " and " UINT64_FORMAT,
(uint64) STRIPE_ROW_COUNT_MINIMUM,
(uint64) STRIPE_ROW_COUNT_MAXIMUM)));
}
}
else if (strcmp(elem->defname, "compression") == 0)
{
options->compressionType = (elem->arg == NULL) ?
columnar_compression : ParseCompressionType(
defGetString(elem));
if (options->compressionType == COMPRESSION_TYPE_INVALID)
{
ereport(ERROR, (errmsg("unknown compression type for columnar table: %s",
quote_identifier(defGetString(elem)))));
}
}
else if (strcmp(elem->defname, "compression_level") == 0)
{
options->compressionLevel = (elem->arg == NULL) ?
columnar_compression_level : defGetInt64(elem);
if (options->compressionLevel < COMPRESSION_LEVEL_MIN ||
options->compressionLevel > COMPRESSION_LEVEL_MAX)
{
ereport(ERROR, (errmsg("compression level out of range"),
errhint("compression level must be between %d and %d",
COMPRESSION_LEVEL_MIN,
COMPRESSION_LEVEL_MAX)));
}
}
else
{
ereport(ERROR, (errmsg("unrecognized columnar storage parameter \"%s\"",
elem->defname)));
}
}
}
/*
* ExtractColumnarOptions - extract columnar options from inOptions, appending
* to inoutColumnarOptions. Return the remaining (non-columnar) options.
*/
List *
ExtractColumnarRelOptions(List *inOptions, List **inoutColumnarOptions)
{
List *otherOptions = NIL;
ListCell *lc = NULL;
foreach(lc, inOptions)
{
DefElem *elem = castNode(DefElem, lfirst(lc));
if (elem->defnamespace != NULL &&
strcmp(elem->defnamespace, COLUMNAR_RELOPTION_NAMESPACE) == 0)
{
*inoutColumnarOptions = lappend(*inoutColumnarOptions, elem);
}
else
{
otherOptions = lappend(otherOptions, elem);
}
}
/* validate options */
ColumnarOptions dummy = { 0 };
ParseColumnarRelOptions(*inoutColumnarOptions, &dummy);
return otherOptions;
}
/*
* SetColumnarRelOptions - apply the list of DefElem options to the
* relation. If there are duplicates, the last one in the list takes effect.
*/
void
SetColumnarRelOptions(RangeVar *rv, List *reloptions)
{
ColumnarOptions options = { 0 };
if (reloptions == NIL)
{
return;
}
Relation rel = relation_openrv(rv, AccessShareLock);
Oid relid = RelationGetRelid(rel);
relation_close(rel, NoLock);
/* get existing or default options */
if (!ReadColumnarOptions(relid, &options))
{
/* if extension doesn't exist, just return */
return;
}
ParseColumnarRelOptions(reloptions, &options);
SetColumnarOptions(relid, &options);
}
/*
* SetColumnarOptions writes the passed table options as the authoritive options to the
* table irregardless of the optiones already existing or not. This can be used to put a

View File

@ -20,6 +20,7 @@
#include "access/xact.h"
#include "catalog/catalog.h"
#include "catalog/index.h"
#include "catalog/namespace.h"
#include "catalog/objectaccess.h"
#include "catalog/pg_am.h"
#include "catalog/pg_publication.h"
@ -103,9 +104,6 @@ typedef struct IndexFetchColumnarData
MemoryContext scanContext;
} IndexFetchColumnarData;
/* available to other extensions using find_rendezvous_variable() */
static ColumnarTableSetOptions_hook_type ColumnarTableSetOptions_hook = NULL;
static object_access_hook_type PrevObjectAccessHook = NULL;
static ProcessUtility_hook_type PrevProcessUtilityHook = NULL;
@ -116,6 +114,8 @@ static void ColumnarTriggerCreateHook(Oid tgid);
static void ColumnarTableAMObjectAccessHook(ObjectAccessType access, Oid classId,
Oid objectId, int subId,
void *arg);
static RangeVar * ColumnarProcessAlterTable(AlterTableStmt *alterTableStmt,
List **columnarOptions);
static void ColumnarProcessUtility(PlannedStmt *pstmt,
const char *queryString,
#if PG_VERSION_NUM >= PG_VERSION_14
@ -1902,11 +1902,6 @@ ColumnarSubXactCallback(SubXactEvent event, SubTransactionId mySubid,
void
columnar_tableam_init()
{
ColumnarTableSetOptions_hook_type **ColumnarTableSetOptions_hook_ptr =
(ColumnarTableSetOptions_hook_type **) find_rendezvous_variable(
COLUMNAR_SETOPTIONS_HOOK_SYM);
*ColumnarTableSetOptions_hook_ptr = &ColumnarTableSetOptions_hook;
RegisterXactCallback(ColumnarXactCallback, NULL);
RegisterSubXactCallback(ColumnarSubXactCallback, NULL);
@ -2080,6 +2075,71 @@ ColumnarTableAMObjectAccessHook(ObjectAccessType access, Oid classId, Oid object
}
/*
* ColumnarProcessAlterTable - if modifying a columnar table, extract columnar
* options and return the table's RangeVar.
*/
static RangeVar *
ColumnarProcessAlterTable(AlterTableStmt *alterTableStmt, List **columnarOptions)
{
RangeVar *columnarRangeVar = NULL;
Relation rel = relation_openrv_extended(alterTableStmt->relation, AccessShareLock,
alterTableStmt->missing_ok);
if (rel == NULL)
{
return NULL;
}
/* track separately in case of ALTER TABLE ... SET ACCESS METHOD */
bool srcIsColumnar = rel->rd_tableam == GetColumnarTableAmRoutine();
bool destIsColumnar = srcIsColumnar;
ListCell *lc = NULL;
foreach(lc, alterTableStmt->cmds)
{
AlterTableCmd *alterTableCmd = castNode(AlterTableCmd, lfirst(lc));
if (alterTableCmd->subtype == AT_SetRelOptions ||
alterTableCmd->subtype == AT_ResetRelOptions)
{
List *options = castNode(List, alterTableCmd->def);
alterTableCmd->def = (Node *) ExtractColumnarRelOptions(
options, columnarOptions);
if (destIsColumnar)
{
columnarRangeVar = alterTableStmt->relation;
}
}
#if PG_VERSION_NUM >= PG_VERSION_15
else if (alterTableCmd->subtype == AT_SetAccessMethod)
{
if (columnarRangeVar || *columnarOptions)
{
ereport(ERROR, (errmsg(
"ALTER TABLE cannot alter the access method after altering storage parameters"),
errhint(
"Specify SET ACCESS METHOD before storage parameters, or use separate ALTER TABLE commands.")));
}
destIsColumnar = (strcmp(alterTableCmd->name, COLUMNAR_AM_NAME) == 0);
if (srcIsColumnar && !destIsColumnar)
{
DeleteColumnarTableOptions(RelationGetRelid(rel), true);
}
}
#endif /* PG_VERSION_15 */
}
relation_close(rel, NoLock);
return columnarRangeVar;
}
/*
* Utility hook for columnar tables.
*/
@ -2104,31 +2164,116 @@ ColumnarProcessUtility(PlannedStmt *pstmt,
Node *parsetree = pstmt->utilityStmt;
if (IsA(parsetree, IndexStmt))
RangeVar *columnarRangeVar = NULL;
List *columnarOptions = NIL;
switch (nodeTag(parsetree))
{
IndexStmt *indexStmt = (IndexStmt *) parsetree;
Relation rel = relation_openrv(indexStmt->relation,
indexStmt->concurrent ? ShareUpdateExclusiveLock :
ShareLock);
if (rel->rd_tableam == GetColumnarTableAmRoutine())
case T_IndexStmt:
{
CheckCitusColumnarVersion(ERROR);
if (!ColumnarSupportsIndexAM(indexStmt->accessMethod))
IndexStmt *indexStmt = (IndexStmt *) parsetree;
Relation rel = relation_openrv(indexStmt->relation,
indexStmt->concurrent ?
ShareUpdateExclusiveLock :
ShareLock);
if (rel->rd_tableam == GetColumnarTableAmRoutine())
{
ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("unsupported access method for the "
"index on columnar table %s",
RelationGetRelationName(rel))));
CheckCitusColumnarVersion(ERROR);
if (!ColumnarSupportsIndexAM(indexStmt->accessMethod))
{
ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("unsupported access method for the "
"index on columnar table %s",
RelationGetRelationName(rel))));
}
}
RelationClose(rel);
break;
}
RelationClose(rel);
case T_CreateStmt:
{
CreateStmt *createStmt = castNode(CreateStmt, parsetree);
bool no_op = false;
if (createStmt->if_not_exists)
{
Oid existing_relid;
/* use same check as transformCreateStmt */
(void) RangeVarGetAndCheckCreationNamespace(
createStmt->relation, AccessShareLock, &existing_relid);
no_op = OidIsValid(existing_relid);
}
if (!no_op && createStmt->accessMethod != NULL &&
!strcmp(createStmt->accessMethod, COLUMNAR_AM_NAME))
{
columnarRangeVar = createStmt->relation;
createStmt->options = ExtractColumnarRelOptions(createStmt->options,
&columnarOptions);
}
break;
}
case T_CreateTableAsStmt:
{
CreateTableAsStmt *createTableAsStmt = castNode(CreateTableAsStmt, parsetree);
IntoClause *into = createTableAsStmt->into;
bool no_op = false;
if (createTableAsStmt->if_not_exists)
{
Oid existing_relid;
/* use same check as transformCreateStmt */
(void) RangeVarGetAndCheckCreationNamespace(
into->rel, AccessShareLock, &existing_relid);
no_op = OidIsValid(existing_relid);
}
if (!no_op && into->accessMethod != NULL &&
!strcmp(into->accessMethod, COLUMNAR_AM_NAME))
{
columnarRangeVar = into->rel;
into->options = ExtractColumnarRelOptions(into->options,
&columnarOptions);
}
break;
}
case T_AlterTableStmt:
{
AlterTableStmt *alterTableStmt = castNode(AlterTableStmt, parsetree);
columnarRangeVar = ColumnarProcessAlterTable(alterTableStmt,
&columnarOptions);
break;
}
default:
/* FALL THROUGH */
break;
}
if (columnarOptions != NIL && columnarRangeVar == NULL)
{
ereport(ERROR,
(errmsg("columnar storage parameters specified on non-columnar table")));
}
PrevProcessUtilityHook_compat(pstmt, queryString, false, context,
params, queryEnv, dest, completionTag);
if (columnarOptions != NIL)
{
SetColumnarRelOptions(columnarRangeVar, columnarOptions);
}
}
@ -2325,219 +2470,36 @@ ColumnarCheckLogicalReplication(Relation rel)
/*
* alter_columnar_table_set is a UDF exposed in postgres to change settings on a columnar
* table. Calling this function on a non-columnar table gives an error.
* alter_columnar_table_set()
*
* sql syntax:
* pg_catalog.alter_columnar_table_set(
* table_name regclass,
* chunk_group_row_limit int DEFAULT NULL,
* stripe_row_limit int DEFAULT NULL,
* compression name DEFAULT null)
* Deprecated in 11.1-1: should issue ALTER TABLE ... SET instead. Function
* still available, but implemented in PL/pgSQL instead of C.
*
* All arguments except the table name are optional. The UDF is supposed to be called
* like:
* SELECT alter_columnar_table_set('table', compression => 'pglz');
*
* This will only update the compression of the table, keeping all other settings the
* same. Multiple settings can be changed at the same time by providing multiple
* arguments. Calling the argument with the NULL value will be interperted as not having
* provided the argument.
* C code is removed -- the symbol may still be required in some
* upgrade/downgrade paths, but it should not be called.
*/
PG_FUNCTION_INFO_V1(alter_columnar_table_set);
Datum
alter_columnar_table_set(PG_FUNCTION_ARGS)
{
CheckCitusColumnarVersion(ERROR);
Oid relationId = PG_GETARG_OID(0);
Relation rel = table_open(relationId, AccessExclusiveLock); /* ALTER TABLE LOCK */
if (!IsColumnarTableAmTable(relationId))
{
ereport(ERROR, (errmsg("table %s is not a columnar table",
quote_identifier(RelationGetRelationName(rel)))));
}
if (!pg_class_ownercheck(relationId, GetUserId()))
{
aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_TABLE,
get_rel_name(relationId));
}
ColumnarOptions options = { 0 };
if (!ReadColumnarOptions(relationId, &options))
{
ereport(ERROR, (errmsg("unable to read current options for table")));
}
/* chunk_group_row_limit => not null */
if (!PG_ARGISNULL(1))
{
options.chunkRowCount = PG_GETARG_INT32(1);
if (options.chunkRowCount < CHUNK_ROW_COUNT_MINIMUM ||
options.chunkRowCount > CHUNK_ROW_COUNT_MAXIMUM)
{
ereport(ERROR, (errmsg("chunk group row count limit out of range"),
errhint("chunk group row count limit must be between "
UINT64_FORMAT " and " UINT64_FORMAT,
(uint64) CHUNK_ROW_COUNT_MINIMUM,
(uint64) CHUNK_ROW_COUNT_MAXIMUM)));
}
ereport(DEBUG1,
(errmsg("updating chunk row count to %d", options.chunkRowCount)));
}
/* stripe_row_limit => not null */
if (!PG_ARGISNULL(2))
{
options.stripeRowCount = PG_GETARG_INT32(2);
if (options.stripeRowCount < STRIPE_ROW_COUNT_MINIMUM ||
options.stripeRowCount > STRIPE_ROW_COUNT_MAXIMUM)
{
ereport(ERROR, (errmsg("stripe row count limit out of range"),
errhint("stripe row count limit must be between "
UINT64_FORMAT " and " UINT64_FORMAT,
(uint64) STRIPE_ROW_COUNT_MINIMUM,
(uint64) STRIPE_ROW_COUNT_MAXIMUM)));
}
ereport(DEBUG1, (errmsg(
"updating stripe row count to " UINT64_FORMAT,
options.stripeRowCount)));
}
/* compression => not null */
if (!PG_ARGISNULL(3))
{
Name compressionName = PG_GETARG_NAME(3);
options.compressionType = ParseCompressionType(NameStr(*compressionName));
if (options.compressionType == COMPRESSION_TYPE_INVALID)
{
ereport(ERROR, (errmsg("unknown compression type for columnar table: %s",
quote_identifier(NameStr(*compressionName)))));
}
ereport(DEBUG1, (errmsg("updating compression to %s",
CompressionTypeStr(options.compressionType))));
}
/* compression_level => not null */
if (!PG_ARGISNULL(4))
{
options.compressionLevel = PG_GETARG_INT32(4);
if (options.compressionLevel < COMPRESSION_LEVEL_MIN ||
options.compressionLevel > COMPRESSION_LEVEL_MAX)
{
ereport(ERROR, (errmsg("compression level out of range"),
errhint("compression level must be between %d and %d",
COMPRESSION_LEVEL_MIN,
COMPRESSION_LEVEL_MAX)));
}
ereport(DEBUG1, (errmsg("updating compression level to %d",
options.compressionLevel)));
}
if (ColumnarTableSetOptions_hook != NULL)
{
ColumnarTableSetOptions_hook(relationId, options);
}
SetColumnarOptions(relationId, &options);
table_close(rel, NoLock);
PG_RETURN_VOID();
elog(ERROR, "alter_columnar_table_set is deprecated");
}
/*
* alter_columnar_table_reset is a UDF exposed in postgres to reset the settings on a
* columnar table. Calling this function on a non-columnar table gives an error.
* alter_columnar_table_reset()
*
* sql syntax:
* pg_catalog.alter_columnar_table_re
* teset(
* table_name regclass,
* chunk_group_row_limit bool DEFAULT FALSE,
* stripe_row_limit bool DEFAULT FALSE,
* compression bool DEFAULT FALSE)
* Deprecated in 11.1-1: should issue ALTER TABLE ... RESET instead. Function
* still available, but implemented in PL/pgSQL instead of C.
*
* All arguments except the table name are optional. The UDF is supposed to be called
* like:
* SELECT alter_columnar_table_set('table', compression => true);
*
* All options set to true will be reset to the default system value.
* C code is removed -- the symbol may still be required in some
* upgrade/downgrade paths, but it should not be called.
*/
PG_FUNCTION_INFO_V1(alter_columnar_table_reset);
Datum
alter_columnar_table_reset(PG_FUNCTION_ARGS)
{
CheckCitusColumnarVersion(ERROR);
Oid relationId = PG_GETARG_OID(0);
Relation rel = table_open(relationId, AccessExclusiveLock); /* ALTER TABLE LOCK */
if (!IsColumnarTableAmTable(relationId))
{
ereport(ERROR, (errmsg("table %s is not a columnar table",
quote_identifier(RelationGetRelationName(rel)))));
}
if (!pg_class_ownercheck(relationId, GetUserId()))
{
aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_TABLE,
get_rel_name(relationId));
}
ColumnarOptions options = { 0 };
if (!ReadColumnarOptions(relationId, &options))
{
ereport(ERROR, (errmsg("unable to read current options for table")));
}
/* chunk_group_row_limit => true */
if (!PG_ARGISNULL(1) && PG_GETARG_BOOL(1))
{
options.chunkRowCount = columnar_chunk_group_row_limit;
ereport(DEBUG1,
(errmsg("resetting chunk row count to %d", options.chunkRowCount)));
}
/* stripe_row_limit => true */
if (!PG_ARGISNULL(2) && PG_GETARG_BOOL(2))
{
options.stripeRowCount = columnar_stripe_row_limit;
ereport(DEBUG1,
(errmsg("resetting stripe row count to " UINT64_FORMAT,
options.stripeRowCount)));
}
/* compression => true */
if (!PG_ARGISNULL(3) && PG_GETARG_BOOL(3))
{
options.compressionType = columnar_compression;
ereport(DEBUG1, (errmsg("resetting compression to %s",
CompressionTypeStr(options.compressionType))));
}
/* compression_level => true */
if (!PG_ARGISNULL(4) && PG_GETARG_BOOL(4))
{
options.compressionLevel = columnar_compression_level;
ereport(DEBUG1, (errmsg("reseting compression level to %d",
columnar_compression_level)));
}
if (ColumnarTableSetOptions_hook != NULL)
{
ColumnarTableSetOptions_hook(relationId, options);
}
SetColumnarOptions(relationId, &options);
table_close(rel, NoLock);
PG_RETURN_VOID();
elog(ERROR, "alter_columnar_table_reset is deprecated");
}

View File

@ -0,0 +1,2 @@
#include "udfs/alter_columnar_table_set/11.1-1.sql"
#include "udfs/alter_columnar_table_reset/11.1-1.sql"

View File

@ -0,0 +1,2 @@
#include "../udfs/alter_columnar_table_set/10.0-1.sql"
#include "../udfs/alter_columnar_table_reset/10.0-1.sql"

View File

@ -0,0 +1,48 @@
CREATE OR REPLACE FUNCTION pg_catalog.alter_columnar_table_reset(
table_name regclass,
chunk_group_row_limit bool DEFAULT false,
stripe_row_limit bool DEFAULT false,
compression bool DEFAULT false,
compression_level bool DEFAULT false)
RETURNS void
LANGUAGE plpgsql AS
$alter_columnar_table_reset$
declare
noop BOOLEAN := true;
cmd TEXT := 'ALTER TABLE ' || table_name::text || ' RESET (';
begin
if (chunk_group_row_limit) then
if (not noop) then cmd := cmd || ', '; end if;
cmd := cmd || 'columnar.chunk_group_row_limit';
noop := false;
end if;
if (stripe_row_limit) then
if (not noop) then cmd := cmd || ', '; end if;
cmd := cmd || 'columnar.stripe_row_limit';
noop := false;
end if;
if (compression) then
if (not noop) then cmd := cmd || ', '; end if;
cmd := cmd || 'columnar.compression';
noop := false;
end if;
if (compression_level) then
if (not noop) then cmd := cmd || ', '; end if;
cmd := cmd || 'columnar.compression_level';
noop := false;
end if;
cmd := cmd || ')';
if (not noop) then
execute cmd;
end if;
return;
end;
$alter_columnar_table_reset$;
COMMENT ON FUNCTION pg_catalog.alter_columnar_table_reset(
table_name regclass,
chunk_group_row_limit bool,
stripe_row_limit bool,
compression bool,
compression_level bool)
IS 'reset on or more options on a columnar table to the system defaults';

View File

@ -5,8 +5,39 @@ CREATE OR REPLACE FUNCTION pg_catalog.alter_columnar_table_reset(
compression bool DEFAULT false,
compression_level bool DEFAULT false)
RETURNS void
LANGUAGE C
AS 'MODULE_PATHNAME', 'alter_columnar_table_reset';
LANGUAGE plpgsql AS
$alter_columnar_table_reset$
declare
noop BOOLEAN := true;
cmd TEXT := 'ALTER TABLE ' || table_name::text || ' RESET (';
begin
if (chunk_group_row_limit) then
if (not noop) then cmd := cmd || ', '; end if;
cmd := cmd || 'columnar.chunk_group_row_limit';
noop := false;
end if;
if (stripe_row_limit) then
if (not noop) then cmd := cmd || ', '; end if;
cmd := cmd || 'columnar.stripe_row_limit';
noop := false;
end if;
if (compression) then
if (not noop) then cmd := cmd || ', '; end if;
cmd := cmd || 'columnar.compression';
noop := false;
end if;
if (compression_level) then
if (not noop) then cmd := cmd || ', '; end if;
cmd := cmd || 'columnar.compression_level';
noop := false;
end if;
cmd := cmd || ')';
if (not noop) then
execute cmd;
end if;
return;
end;
$alter_columnar_table_reset$;
COMMENT ON FUNCTION pg_catalog.alter_columnar_table_reset(
table_name regclass,

View File

@ -0,0 +1,48 @@
CREATE OR REPLACE FUNCTION pg_catalog.alter_columnar_table_set(
table_name regclass,
chunk_group_row_limit int DEFAULT NULL,
stripe_row_limit int DEFAULT NULL,
compression name DEFAULT null,
compression_level int DEFAULT NULL)
RETURNS void
LANGUAGE plpgsql AS
$alter_columnar_table_set$
declare
noop BOOLEAN := true;
cmd TEXT := 'ALTER TABLE ' || table_name::text || ' SET (';
begin
if (chunk_group_row_limit is not null) then
if (not noop) then cmd := cmd || ', '; end if;
cmd := cmd || 'columnar.chunk_group_row_limit=' || chunk_group_row_limit;
noop := false;
end if;
if (stripe_row_limit is not null) then
if (not noop) then cmd := cmd || ', '; end if;
cmd := cmd || 'columnar.stripe_row_limit=' || stripe_row_limit;
noop := false;
end if;
if (compression is not null) then
if (not noop) then cmd := cmd || ', '; end if;
cmd := cmd || 'columnar.compression=' || compression;
noop := false;
end if;
if (compression_level is not null) then
if (not noop) then cmd := cmd || ', '; end if;
cmd := cmd || 'columnar.compression_level=' || compression_level;
noop := false;
end if;
cmd := cmd || ')';
if (not noop) then
execute cmd;
end if;
return;
end;
$alter_columnar_table_set$;
COMMENT ON FUNCTION pg_catalog.alter_columnar_table_set(
table_name regclass,
chunk_group_row_limit int,
stripe_row_limit int,
compression name,
compression_level int)
IS 'set one or more options on a columnar table, when set to NULL no change is made';

View File

@ -5,8 +5,39 @@ CREATE OR REPLACE FUNCTION pg_catalog.alter_columnar_table_set(
compression name DEFAULT null,
compression_level int DEFAULT NULL)
RETURNS void
LANGUAGE C
AS 'MODULE_PATHNAME', 'alter_columnar_table_set';
LANGUAGE plpgsql AS
$alter_columnar_table_set$
declare
noop BOOLEAN := true;
cmd TEXT := 'ALTER TABLE ' || table_name::text || ' SET (';
begin
if (chunk_group_row_limit is not null) then
if (not noop) then cmd := cmd || ', '; end if;
cmd := cmd || 'columnar.chunk_group_row_limit=' || chunk_group_row_limit;
noop := false;
end if;
if (stripe_row_limit is not null) then
if (not noop) then cmd := cmd || ', '; end if;
cmd := cmd || 'columnar.stripe_row_limit=' || stripe_row_limit;
noop := false;
end if;
if (compression is not null) then
if (not noop) then cmd := cmd || ', '; end if;
cmd := cmd || 'columnar.compression=' || compression;
noop := false;
end if;
if (compression_level is not null) then
if (not noop) then cmd := cmd || ', '; end if;
cmd := cmd || 'columnar.compression_level=' || compression_level;
noop := false;
end if;
cmd := cmd || ')';
if (not noop) then
execute cmd;
end if;
return;
end;
$alter_columnar_table_set$;
COMMENT ON FUNCTION pg_catalog.alter_columnar_table_set(
table_name regclass,

View File

@ -711,7 +711,7 @@ ConvertTable(TableConversionState *con)
char *columnarOptionsSql = GetShardedTableDDLCommandColumnar(con->hashOfName,
context);
ExecuteQueryViaSPI(columnarOptionsSql, SPI_OK_SELECT);
ExecuteQueryViaSPI(columnarOptionsSql, SPI_OK_UTILITY);
}
con->newRelationId = get_relname_relid(con->tempName, con->schemaId);

View File

@ -85,6 +85,7 @@ static int activeDropSchemaOrDBs = 0;
static bool ConstraintDropped = false;
ProcessUtility_hook_type PrevProcessUtility = NULL;
int UtilityHookLevel = 0;
@ -179,8 +180,8 @@ multi_ProcessUtility(PlannedStmt *pstmt,
* that state. Since we never need to intercept transaction statements,
* skip our checks and immediately fall into standard_ProcessUtility.
*/
standard_ProcessUtility_compat(pstmt, queryString, false, context,
params, queryEnv, dest, completionTag);
PrevProcessUtility_compat(pstmt, queryString, false, context,
params, queryEnv, dest, completionTag);
return;
}
@ -198,8 +199,8 @@ multi_ProcessUtility(PlannedStmt *pstmt,
* Ensure that utility commands do not behave any differently until CREATE
* EXTENSION is invoked.
*/
standard_ProcessUtility_compat(pstmt, queryString, false, context,
params, queryEnv, dest, completionTag);
PrevProcessUtility_compat(pstmt, queryString, false, context,
params, queryEnv, dest, completionTag);
return;
}
@ -230,8 +231,8 @@ multi_ProcessUtility(PlannedStmt *pstmt,
PG_TRY();
{
standard_ProcessUtility_compat(pstmt, queryString, false, context,
params, queryEnv, dest, completionTag);
PrevProcessUtility_compat(pstmt, queryString, false, context,
params, queryEnv, dest, completionTag);
StoredProcedureLevel -= 1;
@ -264,8 +265,8 @@ multi_ProcessUtility(PlannedStmt *pstmt,
PG_TRY();
{
standard_ProcessUtility_compat(pstmt, queryString, false, context,
params, queryEnv, dest, completionTag);
PrevProcessUtility_compat(pstmt, queryString, false, context,
params, queryEnv, dest, completionTag);
DoBlockLevel -= 1;
}
@ -616,8 +617,8 @@ ProcessUtilityInternal(PlannedStmt *pstmt,
citusCanBeUpdatedToAvailableVersion = !InstalledAndAvailableVersionsSame();
}
standard_ProcessUtility_compat(pstmt, queryString, false, context,
params, queryEnv, dest, completionTag);
PrevProcessUtility_compat(pstmt, queryString, false, context,
params, queryEnv, dest, completionTag);
/*
* if we are running ALTER EXTENSION citus UPDATE (to "<version>") command, we may need
@ -1612,26 +1613,3 @@ DropSchemaOrDBInProgress(void)
{
return activeDropSchemaOrDBs > 0;
}
/*
* ColumnarTableSetOptionsHook propagates columnar table options to shards, if
* necessary.
*/
void
ColumnarTableSetOptionsHook(Oid relationId, ColumnarOptions options)
{
if (EnableDDLPropagation && IsCitusTable(relationId))
{
/* when a columnar table is distributed update all settings on the shards */
Oid namespaceId = get_rel_namespace(relationId);
char *schemaName = get_namespace_name(namespaceId);
char *relationName = get_rel_name(relationId);
TableDDLCommand *command = ColumnarGetCustomTableOptionsDDL(schemaName,
relationName,
options);
DDLJob *ddljob = CreateCustomDDLTaskList(relationId, command);
ExecuteDistributedDDLJob(ddljob);
}
}

View File

@ -1039,12 +1039,12 @@ CitusCreateAlterColumnarTableSet(char *qualifiedRelationName,
initStringInfo(&buf);
appendStringInfo(&buf,
"SELECT alter_columnar_table_set(%s, "
"chunk_group_row_limit => %d, "
"stripe_row_limit => %lu, "
"compression_level => %d, "
"compression => %s);",
quote_literal_cstr(qualifiedRelationName),
"ALTER TABLE %s SET ("
"columnar.chunk_group_row_limit = %d, "
"columnar.stripe_row_limit = %lu, "
"columnar.compression_level = %d, "
"columnar.compression = %s);",
qualifiedRelationName,
options->chunkRowCount,
options->stripeRowCount,
options->compressionLevel,

View File

@ -334,9 +334,6 @@ _PG_init(void)
/* intercept planner */
planner_hook = distributed_planner;
/* register utility hook */
ProcessUtility_hook = multi_ProcessUtility;
/* register for planner hook */
set_rel_pathlist_hook = multi_relation_restriction_hook;
set_join_pathlist_hook = multi_join_restriction_hook;
@ -388,19 +385,15 @@ _PG_init(void)
load_file(COLUMNAR_MODULE_NAME, false);
/*
* Now, acquire symbols from columnar module. First, acquire
* the address of the set options hook, and set it so that we
* can propagate options changes.
* Register utility hook. This must be done after loading columnar, so
* that the citus hook is called first, followed by the columnar hook,
* followed by standard_ProcessUtility. That allows citus to distribute
* ALTER TABLE commands before columnar strips out the columnar-specific
* options.
*/
ColumnarTableSetOptions_hook_type **ColumnarTableSetOptions_hook_ptr =
(ColumnarTableSetOptions_hook_type **) find_rendezvous_variable(
COLUMNAR_SETOPTIONS_HOOK_SYM);
/* rendezvous variable registered during columnar initialization */
Assert(ColumnarTableSetOptions_hook_ptr != NULL);
Assert(*ColumnarTableSetOptions_hook_ptr != NULL);
**ColumnarTableSetOptions_hook_ptr = ColumnarTableSetOptionsHook;
PrevProcessUtility = (ProcessUtility_hook != NULL) ?
ProcessUtility_hook : standard_ProcessUtility;
ProcessUtility_hook = multi_ProcessUtility;
/*
* Acquire symbols for columnar functions that citus calls.

View File

@ -6,3 +6,5 @@ DROP FUNCTION pg_catalog.worker_hash_partition_table(bigint, integer, text, text
DROP FUNCTION pg_catalog.worker_merge_files_into_table(bigint, integer, text[], text[]);
DROP FUNCTION pg_catalog.worker_range_partition_table(bigint, integer, text, text, oid, anyarray);
DROP FUNCTION pg_catalog.worker_repartition_cleanup(bigint);
#include "../../columnar/sql/columnar--11.0-2--11.1-1.sql"

View File

@ -44,4 +44,6 @@ CREATE FUNCTION pg_catalog.worker_repartition_cleanup(bigint)
RETURNS void
LANGUAGE c
STRICT
AS 'MODULE_PATHNAME', $function$worker_repartition_cleanup$function$
AS 'MODULE_PATHNAME', $function$worker_repartition_cleanup$function$;
#include "../../../columnar/sql/downgrades/columnar--11.1-1--11.0-2.sql"

View File

@ -25,6 +25,7 @@
#include "columnar/columnar_compression.h"
#include "columnar/columnar_metadata.h"
#define COLUMNAR_AM_NAME "columnar"
#define COLUMNAR_MODULE_NAME "citus_columnar"
#define COLUMNAR_SETOPTIONS_HOOK_SYM "ColumnarTableSetOptions_hook"

View File

@ -51,5 +51,7 @@ typedef struct EmptyStripeReservation
extern List * StripesForRelfilenode(RelFileNode relfilenode);
extern void ColumnarStorageUpdateIfNeeded(Relation rel, bool isUpgrade);
extern List * ExtractColumnarRelOptions(List *inOptions, List **outColumnarOptions);
extern void SetColumnarRelOptions(RangeVar *rv, List *reloptions);
#endif /* COLUMNAR_METADATA_H */

View File

@ -75,6 +75,7 @@ typedef struct DDLJob
List *taskList; /* worker DDL tasks to execute */
} DDLJob;
extern ProcessUtility_hook_type PrevProcessUtility;
extern void multi_ProcessUtility(PlannedStmt *pstmt, const char *queryString,
#if PG_VERSION_NUM >= PG_VERSION_14

View File

@ -77,6 +77,8 @@ RelationGetSmgr(Relation rel)
standard_ProcessUtility(a, b, c, d, e, f, g, h)
#define ProcessUtility_compat(a, b, c, d, e, f, g, h) \
ProcessUtility(a, b, c, d, e, f, g, h)
#define PrevProcessUtility_compat(a, b, c, d, e, f, g, h) \
PrevProcessUtility(a, b, c, d, e, f, g, h)
#define SetTuplestoreDestReceiverParams_compat(a, b, c, d, e, f) \
SetTuplestoreDestReceiverParams(a, b, c, d, e, f)
#define pgproc_statusflags_compat(pgproc) ((pgproc)->statusFlags)
@ -106,6 +108,8 @@ RelationGetSmgr(Relation rel)
#define standard_ProcessUtility_compat(a, b, c, d, e, f, g, h) \
standard_ProcessUtility(a, b, d, e, f, g, h)
#define ProcessUtility_compat(a, b, c, d, e, f, g, h) ProcessUtility(a, b, d, e, f, g, h)
#define PrevProcessUtility_compat(a, b, c, d, e, f, g, h) \
PrevProcessUtility(a, b, d, e, f, g, h)
#define COPY_FRONTEND COPY_NEW_FE
#define SetTuplestoreDestReceiverParams_compat(a, b, c, d, e, f) \
SetTuplestoreDestReceiverParams(a, b, c, d)

View File

@ -27,6 +27,7 @@ test: columnar_clean
test: columnar_types_without_comparison
test: columnar_chunk_filtering
test: columnar_join
test: columnar_pg15
test: columnar_trigger
test: columnar_tableoptions
test: columnar_recursive

View File

@ -1,4 +1,23 @@
SET columnar.compression TO 'none';
SELECT success, result FROM run_command_on_all_nodes($cmd$
ALTER SYSTEM SET columnar.compression TO 'none'
$cmd$);
success | result
---------------------------------------------------------------------
t | ALTER SYSTEM
t | ALTER SYSTEM
t | ALTER SYSTEM
(3 rows)
SELECT success, result FROM run_command_on_all_nodes($cmd$
SELECT pg_reload_conf()
$cmd$);
success | result
---------------------------------------------------------------------
t | t
t | t
t | t
(3 rows)
CREATE SCHEMA columnar_citus_integration;
SET search_path TO columnar_citus_integration;
SET citus.next_shard_id TO 20090000;
@ -27,12 +46,7 @@ $cmd$);
(4 rows)
-- change setting
SELECT alter_columnar_table_set('table_option', compression => 'pglz');
alter_columnar_table_set
---------------------------------------------------------------------
(1 row)
ALTER TABLE table_option SET (columnar.compression = pglz);
-- verify setting
SELECT run_command_on_placements('table_option',$cmd$
SELECT compression FROM columnar.options WHERE regclass = '%s'::regclass;
@ -46,12 +60,7 @@ $cmd$);
(4 rows)
-- reset setting
SELECT alter_columnar_table_reset('table_option', compression => true);
alter_columnar_table_reset
---------------------------------------------------------------------
(1 row)
ALTER TABLE table_option RESET (columnar.compression);
-- verify setting
SELECT run_command_on_placements('table_option',$cmd$
SELECT compression FROM columnar.options WHERE regclass = '%s'::regclass;
@ -78,12 +87,7 @@ $cmd$);
(4 rows)
-- change setting
SELECT alter_columnar_table_set('table_option', compression_level => 13);
alter_columnar_table_set
---------------------------------------------------------------------
(1 row)
ALTER TABLE table_option SET (columnar.compression_level = 13);
-- verify setting
SELECT run_command_on_placements('table_option',$cmd$
SELECT compression_level FROM columnar.options WHERE regclass = '%s'::regclass;
@ -97,12 +101,7 @@ $cmd$);
(4 rows)
-- reset setting
SELECT alter_columnar_table_reset('table_option', compression_level => true);
alter_columnar_table_reset
---------------------------------------------------------------------
(1 row)
ALTER TABLE table_option RESET (columnar.compression_level);
-- verify setting
SELECT run_command_on_placements('table_option',$cmd$
SELECT compression_level FROM columnar.options WHERE regclass = '%s'::regclass;
@ -129,12 +128,7 @@ $cmd$);
(4 rows)
-- change setting
SELECT alter_columnar_table_set('table_option', chunk_group_row_limit => 2000);
alter_columnar_table_set
---------------------------------------------------------------------
(1 row)
ALTER TABLE table_option SET (columnar.chunk_group_row_limit = 2000);
-- verify setting
SELECT run_command_on_placements('table_option',$cmd$
SELECT chunk_group_row_limit FROM columnar.options WHERE regclass = '%s'::regclass;
@ -148,12 +142,7 @@ $cmd$);
(4 rows)
-- reset setting
SELECT alter_columnar_table_reset('table_option', chunk_group_row_limit => true);
alter_columnar_table_reset
---------------------------------------------------------------------
(1 row)
ALTER TABLE table_option RESET (columnar.chunk_group_row_limit);
-- verify setting
SELECT run_command_on_placements('table_option',$cmd$
SELECT chunk_group_row_limit FROM columnar.options WHERE regclass = '%s'::regclass;
@ -180,12 +169,7 @@ $cmd$);
(4 rows)
-- change setting
SELECT alter_columnar_table_set('table_option', stripe_row_limit => 2000);
alter_columnar_table_set
---------------------------------------------------------------------
(1 row)
ALTER TABLE table_option SET (columnar.stripe_row_limit = 2000);
-- verify setting
SELECT run_command_on_placements('table_option',$cmd$
SELECT stripe_row_limit FROM columnar.options WHERE regclass = '%s'::regclass;
@ -199,12 +183,7 @@ $cmd$);
(4 rows)
-- reset setting
SELECT alter_columnar_table_reset('table_option', stripe_row_limit => true);
alter_columnar_table_reset
---------------------------------------------------------------------
(1 row)
ALTER TABLE table_option RESET (columnar.stripe_row_limit);
-- verify setting
SELECT run_command_on_placements('table_option',$cmd$
SELECT stripe_row_limit FROM columnar.options WHERE regclass = '%s'::regclass;
@ -219,16 +198,11 @@ $cmd$);
-- verify settings are propagated when creating a table
CREATE TABLE table_option_2 (a int, b text) USING columnar;
SELECT alter_columnar_table_set('table_option_2',
chunk_group_row_limit => 2000,
stripe_row_limit => 20000,
compression => 'pglz',
compression_level => 15);
alter_columnar_table_set
---------------------------------------------------------------------
(1 row)
ALTER TABLE table_option_2 SET
(columnar.chunk_group_row_limit = 2000,
columnar.stripe_row_limit = 20000,
columnar.compression = pglz,
columnar.compression_level = 15);
SELECT create_distributed_table('table_option_2', 'a');
create_distributed_table
---------------------------------------------------------------------
@ -298,12 +272,7 @@ $cmd$);
(8 rows)
-- change setting
SELECT alter_columnar_table_set('table_option', compression => 'pglz');
alter_columnar_table_set
---------------------------------------------------------------------
(1 row)
ALTER TABLE table_option SET (columnar.compression = pglz);
-- verify setting
SELECT run_command_on_placements('table_option',$cmd$
SELECT compression FROM columnar.options WHERE regclass = '%s'::regclass;
@ -321,12 +290,7 @@ $cmd$);
(8 rows)
-- reset setting
SELECT alter_columnar_table_reset('table_option', compression => true);
alter_columnar_table_reset
---------------------------------------------------------------------
(1 row)
ALTER TABLE table_option RESET (columnar.compression);
-- verify setting
SELECT run_command_on_placements('table_option',$cmd$
SELECT compression FROM columnar.options WHERE regclass = '%s'::regclass;
@ -361,12 +325,7 @@ $cmd$);
(8 rows)
-- change setting
SELECT alter_columnar_table_set('table_option', compression_level => 17);
alter_columnar_table_set
---------------------------------------------------------------------
(1 row)
ALTER TABLE table_option SET (columnar.compression_level = 17);
-- verify setting
SELECT run_command_on_placements('table_option',$cmd$
SELECT compression_level FROM columnar.options WHERE regclass = '%s'::regclass;
@ -384,12 +343,7 @@ $cmd$);
(8 rows)
-- reset setting
SELECT alter_columnar_table_reset('table_option', compression_level => true);
alter_columnar_table_reset
---------------------------------------------------------------------
(1 row)
ALTER TABLE table_option RESET (columnar.compression_level);
-- verify setting
SELECT run_command_on_placements('table_option',$cmd$
SELECT compression_level FROM columnar.options WHERE regclass = '%s'::regclass;
@ -424,12 +378,7 @@ $cmd$);
(8 rows)
-- change setting
SELECT alter_columnar_table_set('table_option', chunk_group_row_limit => 2000);
alter_columnar_table_set
---------------------------------------------------------------------
(1 row)
ALTER TABLE table_option SET (columnar.chunk_group_row_limit = 2000);
-- verify setting
SELECT run_command_on_placements('table_option',$cmd$
SELECT chunk_group_row_limit FROM columnar.options WHERE regclass = '%s'::regclass;
@ -447,12 +396,7 @@ $cmd$);
(8 rows)
-- reset setting
SELECT alter_columnar_table_reset('table_option', chunk_group_row_limit => true);
alter_columnar_table_reset
---------------------------------------------------------------------
(1 row)
ALTER TABLE table_option RESET (columnar.chunk_group_row_limit);
-- verify setting
SELECT run_command_on_placements('table_option',$cmd$
SELECT chunk_group_row_limit FROM columnar.options WHERE regclass = '%s'::regclass;
@ -487,12 +431,7 @@ $cmd$);
(8 rows)
-- change setting
SELECT alter_columnar_table_set('table_option', stripe_row_limit => 2000);
alter_columnar_table_set
---------------------------------------------------------------------
(1 row)
ALTER TABLE table_option SET (columnar.stripe_row_limit = 2000);
-- verify setting
SELECT run_command_on_placements('table_option',$cmd$
SELECT stripe_row_limit FROM columnar.options WHERE regclass = '%s'::regclass;
@ -510,12 +449,7 @@ $cmd$);
(8 rows)
-- reset setting
SELECT alter_columnar_table_reset('table_option', stripe_row_limit => true);
alter_columnar_table_reset
---------------------------------------------------------------------
(1 row)
ALTER TABLE table_option RESET (columnar.stripe_row_limit);
-- verify setting
SELECT run_command_on_placements('table_option',$cmd$
SELECT stripe_row_limit FROM columnar.options WHERE regclass = '%s'::regclass;
@ -534,16 +468,11 @@ $cmd$);
-- verify settings are propagated when creating a table
CREATE TABLE table_option_2 (a int, b text) USING columnar;
SELECT alter_columnar_table_set('table_option_2',
chunk_group_row_limit => 2000,
stripe_row_limit => 20000,
compression => 'pglz',
compression_level => 19);
alter_columnar_table_set
---------------------------------------------------------------------
(1 row)
ALTER TABLE table_option_2 SET
(columnar.chunk_group_row_limit = 2000,
columnar.stripe_row_limit = 20000,
columnar.compression = pglz,
columnar.compression_level = 19);
SELECT create_distributed_table('table_option_2', 'a');
create_distributed_table
---------------------------------------------------------------------
@ -609,12 +538,7 @@ $cmd$);
(2 rows)
-- change setting
SELECT alter_columnar_table_set('table_option_reference', compression => 'pglz');
alter_columnar_table_set
---------------------------------------------------------------------
(1 row)
ALTER TABLE table_option_reference SET (columnar.compression = pglz);
-- verify setting
SELECT run_command_on_placements('table_option_reference',$cmd$
SELECT compression FROM columnar.options WHERE regclass = '%s'::regclass;
@ -626,12 +550,7 @@ $cmd$);
(2 rows)
-- reset setting
SELECT alter_columnar_table_reset('table_option_reference', compression => true);
alter_columnar_table_reset
---------------------------------------------------------------------
(1 row)
ALTER TABLE table_option_reference RESET (columnar.compression);
-- verify setting
SELECT run_command_on_placements('table_option_reference',$cmd$
SELECT compression FROM columnar.options WHERE regclass = '%s'::regclass;
@ -654,12 +573,7 @@ $cmd$);
(2 rows)
-- change setting
SELECT alter_columnar_table_set('table_option_reference', compression_level => 11);
alter_columnar_table_set
---------------------------------------------------------------------
(1 row)
ALTER TABLE table_option_reference SET (columnar.compression_level = 11);
-- verify setting
SELECT run_command_on_placements('table_option_reference',$cmd$
SELECT compression_level FROM columnar.options WHERE regclass = '%s'::regclass;
@ -671,12 +585,7 @@ $cmd$);
(2 rows)
-- reset setting
SELECT alter_columnar_table_reset('table_option_reference', compression_level => true);
alter_columnar_table_reset
---------------------------------------------------------------------
(1 row)
ALTER TABLE table_option_reference RESET (columnar.compression_level);
-- verify setting
SELECT run_command_on_placements('table_option_reference',$cmd$
SELECT compression_level FROM columnar.options WHERE regclass = '%s'::regclass;
@ -699,12 +608,7 @@ $cmd$);
(2 rows)
-- change setting
SELECT alter_columnar_table_set('table_option_reference', chunk_group_row_limit => 2000);
alter_columnar_table_set
---------------------------------------------------------------------
(1 row)
ALTER TABLE table_option_reference SET (columnar.chunk_group_row_limit = 2000);
-- verify setting
SELECT run_command_on_placements('table_option_reference',$cmd$
SELECT chunk_group_row_limit FROM columnar.options WHERE regclass = '%s'::regclass;
@ -716,12 +620,7 @@ $cmd$);
(2 rows)
-- reset setting
SELECT alter_columnar_table_reset('table_option_reference', chunk_group_row_limit => true);
alter_columnar_table_reset
---------------------------------------------------------------------
(1 row)
ALTER TABLE table_option_reference RESET (columnar.chunk_group_row_limit);
-- verify setting
SELECT run_command_on_placements('table_option_reference',$cmd$
SELECT chunk_group_row_limit FROM columnar.options WHERE regclass = '%s'::regclass;
@ -744,12 +643,7 @@ $cmd$);
(2 rows)
-- change setting
SELECT alter_columnar_table_set('table_option_reference', stripe_row_limit => 2000);
alter_columnar_table_set
---------------------------------------------------------------------
(1 row)
ALTER TABLE table_option_reference SET (columnar.stripe_row_limit = 2000);
-- verify setting
SELECT run_command_on_placements('table_option_reference',$cmd$
SELECT stripe_row_limit FROM columnar.options WHERE regclass = '%s'::regclass;
@ -761,12 +655,7 @@ $cmd$);
(2 rows)
-- reset setting
SELECT alter_columnar_table_reset('table_option_reference', stripe_row_limit => true);
alter_columnar_table_reset
---------------------------------------------------------------------
(1 row)
ALTER TABLE table_option_reference RESET (columnar.stripe_row_limit);
-- verify setting
SELECT run_command_on_placements('table_option_reference',$cmd$
SELECT stripe_row_limit FROM columnar.options WHERE regclass = '%s'::regclass;
@ -779,16 +668,11 @@ $cmd$);
-- verify settings are propagated when creating a table
CREATE TABLE table_option_reference_2 (a int, b text) USING columnar;
SELECT alter_columnar_table_set('table_option_reference_2',
chunk_group_row_limit => 2000,
stripe_row_limit => 20000,
compression => 'pglz',
compression_level => 9);
alter_columnar_table_set
---------------------------------------------------------------------
(1 row)
ALTER TABLE table_option_reference_2 SET
(columnar.chunk_group_row_limit = 2000,
columnar.stripe_row_limit = 20000,
columnar.compression = pglz,
columnar.compression_level = 9);
SELECT create_reference_table('table_option_reference_2');
create_reference_table
---------------------------------------------------------------------
@ -855,12 +739,7 @@ $cmd$);
(1 row)
-- change setting
SELECT alter_columnar_table_set('table_option_citus_local', compression => 'pglz');
alter_columnar_table_set
---------------------------------------------------------------------
(1 row)
ALTER TABLE table_option_citus_local SET (columnar.compression = pglz);
-- verify setting
SELECT run_command_on_placements('table_option_citus_local',$cmd$
SELECT compression FROM columnar.options WHERE regclass = '%s'::regclass;
@ -871,12 +750,7 @@ $cmd$);
(1 row)
-- reset setting
SELECT alter_columnar_table_reset('table_option_citus_local', compression => true);
alter_columnar_table_reset
---------------------------------------------------------------------
(1 row)
ALTER TABLE table_option_citus_local RESET (columnar.compression);
-- verify setting
SELECT run_command_on_placements('table_option_citus_local',$cmd$
SELECT compression FROM columnar.options WHERE regclass = '%s'::regclass;
@ -897,12 +771,7 @@ $cmd$);
(1 row)
-- change setting
SELECT alter_columnar_table_set('table_option_citus_local', compression_level => 11);
alter_columnar_table_set
---------------------------------------------------------------------
(1 row)
ALTER TABLE table_option_citus_local SET (columnar.compression_level = 11);
-- verify setting
SELECT run_command_on_placements('table_option_citus_local',$cmd$
SELECT compression_level FROM columnar.options WHERE regclass = '%s'::regclass;
@ -913,12 +782,7 @@ $cmd$);
(1 row)
-- reset setting
SELECT alter_columnar_table_reset('table_option_citus_local', compression_level => true);
alter_columnar_table_reset
---------------------------------------------------------------------
(1 row)
ALTER TABLE table_option_citus_local RESET (columnar.compression_level);
-- verify setting
SELECT run_command_on_placements('table_option_citus_local',$cmd$
SELECT compression_level FROM columnar.options WHERE regclass = '%s'::regclass;
@ -939,12 +803,7 @@ $cmd$);
(1 row)
-- change setting
SELECT alter_columnar_table_set('table_option_citus_local', chunk_group_row_limit => 2000);
alter_columnar_table_set
---------------------------------------------------------------------
(1 row)
ALTER TABLE table_option_citus_local SET (columnar.chunk_group_row_limit = 2000);
-- verify setting
SELECT run_command_on_placements('table_option_citus_local',$cmd$
SELECT chunk_group_row_limit FROM columnar.options WHERE regclass = '%s'::regclass;
@ -955,12 +814,7 @@ $cmd$);
(1 row)
-- reset setting
SELECT alter_columnar_table_reset('table_option_citus_local', chunk_group_row_limit => true);
alter_columnar_table_reset
---------------------------------------------------------------------
(1 row)
ALTER TABLE table_option_citus_local RESET (columnar.chunk_group_row_limit);
-- verify setting
SELECT run_command_on_placements('table_option_citus_local',$cmd$
SELECT chunk_group_row_limit FROM columnar.options WHERE regclass = '%s'::regclass;
@ -981,12 +835,7 @@ $cmd$);
(1 row)
-- change setting
SELECT alter_columnar_table_set('table_option_citus_local', stripe_row_limit => 2000);
alter_columnar_table_set
---------------------------------------------------------------------
(1 row)
ALTER TABLE table_option_citus_local SET (columnar.stripe_row_limit = 2000);
-- verify setting
SELECT run_command_on_placements('table_option_citus_local',$cmd$
SELECT stripe_row_limit FROM columnar.options WHERE regclass = '%s'::regclass;
@ -997,12 +846,7 @@ $cmd$);
(1 row)
-- reset setting
SELECT alter_columnar_table_reset('table_option_citus_local', stripe_row_limit => true);
alter_columnar_table_reset
---------------------------------------------------------------------
(1 row)
ALTER TABLE table_option_citus_local RESET (columnar.stripe_row_limit);
-- verify setting
SELECT run_command_on_placements('table_option_citus_local',$cmd$
SELECT stripe_row_limit FROM columnar.options WHERE regclass = '%s'::regclass;
@ -1014,16 +858,11 @@ $cmd$);
-- verify settings are propagated when creating a table
CREATE TABLE table_option_citus_local_2 (a int, b text) USING columnar;
SELECT alter_columnar_table_set('table_option_citus_local_2',
chunk_group_row_limit => 2000,
stripe_row_limit => 20000,
compression => 'pglz',
compression_level => 9);
alter_columnar_table_set
---------------------------------------------------------------------
(1 row)
ALTER TABLE table_option_citus_local_2 SET
(columnar.chunk_group_row_limit = 2000,
columnar.stripe_row_limit = 20000,
columnar.compression = pglz,
columnar.compression_level = 9);
SELECT citus_add_local_table_to_metadata('table_option_citus_local_2');
citus_add_local_table_to_metadata
---------------------------------------------------------------------

View File

@ -5,12 +5,7 @@
CREATE TABLE contestant (handle TEXT, birthdate DATE, rating INT,
percentile FLOAT, country CHAR(3), achievements TEXT[])
USING columnar;
SELECT alter_columnar_table_set('contestant', compression => 'none');
alter_columnar_table_set
---------------------------------------------------------------------
(1 row)
ALTER TABLE contestant SET (columnar.compression = none);
CREATE INDEX contestant_idx on contestant(handle);
-- Create zstd compressed table
CREATE TABLE contestant_compressed (handle TEXT, birthdate DATE, rating INT,

View File

@ -5,24 +5,9 @@ SET citus.compression to 'none';
create table t_uncompressed(a int) using columnar;
create table t_compressed(a int) using columnar;
-- set options
SELECT alter_columnar_table_set('t_compressed', compression => 'pglz');
alter_columnar_table_set
---------------------------------------------------------------------
(1 row)
SELECT alter_columnar_table_set('t_compressed', stripe_row_limit => 2000);
alter_columnar_table_set
---------------------------------------------------------------------
(1 row)
SELECT alter_columnar_table_set('t_compressed', chunk_group_row_limit => 1000);
alter_columnar_table_set
---------------------------------------------------------------------
(1 row)
ALTER TABLE t_compressed SET (columnar.compression = pglz);
ALTER TABLE t_compressed SET (columnar.stripe_row_limit = 2000);
ALTER TABLE t_compressed SET (columnar.chunk_group_row_limit = 1000);
SELECT * FROM columnar.options WHERE regclass = 't_compressed'::regclass;
regclass | chunk_group_row_limit | stripe_row_limit | compression_level | compression
---------------------------------------------------------------------

View File

@ -8,12 +8,7 @@
set columnar.enable_custom_scan = false;
create table fallback_scan(i int) using columnar;
-- large enough to test parallel_workers > 1
select alter_columnar_table_set('fallback_scan', compression => 'none');
alter_columnar_table_set
---------------------------------------------------------------------
(1 row)
ALTER TABLE fallback_scan SET (columnar.compression = none);
insert into fallback_scan select generate_series(1,150000);
vacuum analyze fallback_scan;
select count(*), min(i), max(i), avg(i) from fallback_scan;

View File

@ -7,12 +7,7 @@ BEGIN;
INSERT INTO col_table_1 SELECT i FROM generate_series(1, 11) i;
ROLLBACK;
INSERT INTO col_table_1 SELECT i FROM generate_series(1, 12) i;
SELECT alter_columnar_table_set('col_table_1', stripe_row_limit => 1000);
alter_columnar_table_set
---------------------------------------------------------------------
(1 row)
ALTER TABLE col_table_1 SET (columnar.stripe_row_limit = 1000);
INSERT INTO col_table_1 SELECT i FROM generate_series(1, 2350) i;
SELECT row_count, first_row_number FROM columnar.stripe a
WHERE a.storage_id = columnar_test_helpers.columnar_relation_storageid('col_table_1'::regclass)

View File

@ -171,12 +171,7 @@ DROP TABLE test_toast_columnar;
-- We support writing into zero column tables, but not reading from them.
-- We test that metadata makes sense so we can fix the read path in future.
CREATE TABLE zero_col() USING columnar;
SELECT alter_columnar_table_set('zero_col', chunk_group_row_limit => 1000);
alter_columnar_table_set
---------------------------------------------------------------------
(1 row)
ALTER TABLE zero_col SET (columnar.chunk_group_row_limit = 1000);
INSERT INTO zero_col DEFAULT VALUES;
INSERT INTO zero_col DEFAULT VALUES;
INSERT INTO zero_col DEFAULT VALUES;
@ -231,12 +226,7 @@ ORDER BY 1,2,3,4;
(5 rows)
CREATE TABLE selfinsert(x int) USING columnar;
SELECT alter_columnar_table_set('selfinsert', stripe_row_limit => 1000);
alter_columnar_table_set
---------------------------------------------------------------------
(1 row)
ALTER TABLE selfinsert SET (columnar.stripe_row_limit = 1000);
BEGIN;
INSERT INTO selfinsert SELECT generate_series(1,1010);
INSERT INTO selfinsert SELECT * FROM selfinsert;

View File

@ -32,12 +32,7 @@ WHERE regclass = 't_view'::regclass;
(1 row)
-- show we can set options on a materialized view
SELECT alter_columnar_table_set('t_view', compression => 'pglz');
alter_columnar_table_set
---------------------------------------------------------------------
(1 row)
ALTER TABLE t_view SET (columnar.compression = pglz);
SELECT * FROM columnar.options
WHERE regclass = 't_view'::regclass;
regclass | chunk_group_row_limit | stripe_row_limit | compression_level | compression

View File

@ -1,3 +1,4 @@
create table no_access (i int) using columnar;
select current_user \gset
create user columnar_user;
NOTICE: not propagating CREATE ROLE/USER commands to worker nodes
@ -6,8 +7,41 @@ HINT: Connect to worker nodes directly to manually create all necessary users a
create table columnar_permissions(i int) using columnar;
insert into columnar_permissions values(1);
alter table columnar_permissions add column j int;
alter table columnar_permissions reset (columnar.compression);
alter table columnar_permissions set (columnar.compression = none);
select alter_columnar_table_reset('columnar_permissions', stripe_row_limit => true);
alter_columnar_table_reset
---------------------------------------------------------------------
(1 row)
select alter_columnar_table_set('columnar_permissions', stripe_row_limit => 2222);
alter_columnar_table_set
---------------------------------------------------------------------
(1 row)
select * from columnar.options where regclass = 'columnar_permissions'::regclass;
regclass | chunk_group_row_limit | stripe_row_limit | compression_level | compression
---------------------------------------------------------------------
columnar_permissions | 10000 | 2222 | 3 | none
(1 row)
insert into columnar_permissions values(2,20);
vacuum columnar_permissions;
truncate columnar_permissions;
drop table columnar_permissions;
-- should error
alter table no_access reset (columnar.stripe_row_limit);
ERROR: must be owner of table no_access
alter table no_access set (columnar.stripe_row_limit = 12000);
ERROR: must be owner of table no_access
select alter_columnar_table_reset('no_access', chunk_group_row_limit => true);
ERROR: must be owner of table no_access
CONTEXT: SQL statement "ALTER TABLE no_access RESET (columnar.chunk_group_row_limit)"
PL/pgSQL function alter_columnar_table_reset(regclass,boolean,boolean,boolean,boolean) line XX at EXECUTE
select alter_columnar_table_set('no_access', chunk_group_row_limit => 1111);
ERROR: must be owner of table no_access
CONTEXT: SQL statement "ALTER TABLE no_access SET (columnar.chunk_group_row_limit=1111)"
PL/pgSQL function alter_columnar_table_set(regclass,integer,integer,name,integer) line XX at EXECUTE
\c - :current_user

View File

@ -0,0 +1,60 @@
SHOW server_version \gset
SELECT substring(:'server_version', '\d+')::int >= 15 AS server_version_ge_15
\gset
\if :server_version_ge_15
\else
\q
\endif
CREATE TABLE alter_am(i int);
CREATE TABLE
INSERT INTO alter_am SELECT generate_series(1,1000000);
INSERT 0 1000000
SELECT * FROM columnar.options WHERE regclass = 'alter_am'::regclass;
regclass | chunk_group_row_limit | stripe_row_limit | compression_level | compression
---------------------------------------------------------------------
(0 rows)
SELECT SUM(i) FROM alter_am;
sum
---------------------------------------------------------------------
500000500000
(1 row)
ALTER TABLE alter_am
SET ACCESS METHOD columnar,
SET (columnar.compression = pglz, fillfactor = 20);
ALTER TABLE
SELECT * FROM columnar.options WHERE regclass = 'alter_am'::regclass;
regclass | chunk_group_row_limit | stripe_row_limit | compression_level | compression
---------------------------------------------------------------------
alter_am | 10000 | 150000 | 3 | pglz
(1 row)
SELECT SUM(i) FROM alter_am;
sum
---------------------------------------------------------------------
500000500000
(1 row)
ALTER TABLE alter_am SET ACCESS METHOD heap;
ALTER TABLE
-- columnar options should be gone
SELECT * FROM columnar.options WHERE regclass = 'alter_am'::regclass;
regclass | chunk_group_row_limit | stripe_row_limit | compression_level | compression
---------------------------------------------------------------------
(0 rows)
SELECT SUM(i) FROM alter_am;
sum
---------------------------------------------------------------------
500000500000
(1 row)
-- error: setting columnar options must happen after converting to columnar
ALTER TABLE alter_am
SET (columnar.stripe_row_limit = 1111),
SET ACCESS METHOD columnar;
ERROR: ALTER TABLE cannot alter the access method after altering storage parameters
HINT: Specify SET ACCESS METHOD before storage parameters, or use separate ALTER TABLE commands.
DROP TABLE alter_am;
DROP TABLE

View File

@ -0,0 +1,6 @@
SHOW server_version \gset
SELECT substring(:'server_version', '\d+')::int >= 15 AS server_version_ge_15
\gset
\if :server_version_ge_15
\else
\q

View File

@ -12,12 +12,7 @@ WHERE regclass = 'table_options'::regclass;
(1 row)
-- test changing the compression
SELECT alter_columnar_table_set('table_options', compression => 'pglz');
alter_columnar_table_set
---------------------------------------------------------------------
(1 row)
ALTER TABLE table_options SET (columnar.compression = pglz);
-- show table_options settings
SELECT * FROM columnar.options
WHERE regclass = 'table_options'::regclass;
@ -27,12 +22,7 @@ WHERE regclass = 'table_options'::regclass;
(1 row)
-- test changing the compression level
SELECT alter_columnar_table_set('table_options', compression_level => 5);
alter_columnar_table_set
---------------------------------------------------------------------
(1 row)
ALTER TABLE table_options SET (columnar.compression_level = 5);
-- show table_options settings
SELECT * FROM columnar.options
WHERE regclass = 'table_options'::regclass;
@ -42,12 +32,7 @@ WHERE regclass = 'table_options'::regclass;
(1 row)
-- test changing the chunk_group_row_limit
SELECT alter_columnar_table_set('table_options', chunk_group_row_limit => 2000);
alter_columnar_table_set
---------------------------------------------------------------------
(1 row)
ALTER TABLE table_options SET (columnar.chunk_group_row_limit = 2000);
-- show table_options settings
SELECT * FROM columnar.options
WHERE regclass = 'table_options'::regclass;
@ -57,12 +42,7 @@ WHERE regclass = 'table_options'::regclass;
(1 row)
-- test changing the chunk_group_row_limit
SELECT alter_columnar_table_set('table_options', stripe_row_limit => 4000);
alter_columnar_table_set
---------------------------------------------------------------------
(1 row)
ALTER TABLE table_options SET (columnar.stripe_row_limit = 4000);
-- show table_options settings
SELECT * FROM columnar.options
WHERE regclass = 'table_options'::regclass;
@ -82,12 +62,11 @@ WHERE regclass = 'table_options'::regclass;
(1 row)
-- set all settings at the same time
SELECT alter_columnar_table_set('table_options', stripe_row_limit => 8000, chunk_group_row_limit => 4000, compression => 'none', compression_level => 7);
alter_columnar_table_set
---------------------------------------------------------------------
(1 row)
ALTER TABLE table_options SET
(columnar.stripe_row_limit = 8000,
columnar.chunk_group_row_limit = 4000,
columnar.compression = none,
columnar.compression_level = 7);
-- show table_options settings
SELECT * FROM columnar.options
WHERE regclass = 'table_options'::regclass;
@ -149,12 +128,7 @@ WHERE regclass = 'table_options'::regclass;
table_options | 4000 | 8000 | 7 | none
(1 row)
SELECT alter_columnar_table_reset('table_options', chunk_group_row_limit => true);
alter_columnar_table_reset
---------------------------------------------------------------------
(1 row)
ALTER TABLE table_options RESET (columnar.chunk_group_row_limit);
-- show table_options settings
SELECT * FROM columnar.options
WHERE regclass = 'table_options'::regclass;
@ -163,12 +137,7 @@ WHERE regclass = 'table_options'::regclass;
table_options | 1000 | 8000 | 7 | none
(1 row)
SELECT alter_columnar_table_reset('table_options', stripe_row_limit => true);
alter_columnar_table_reset
---------------------------------------------------------------------
(1 row)
ALTER TABLE table_options RESET (columnar.stripe_row_limit);
-- show table_options settings
SELECT * FROM columnar.options
WHERE regclass = 'table_options'::regclass;
@ -177,12 +146,7 @@ WHERE regclass = 'table_options'::regclass;
table_options | 1000 | 10000 | 7 | none
(1 row)
SELECT alter_columnar_table_reset('table_options', compression => true);
alter_columnar_table_reset
---------------------------------------------------------------------
(1 row)
ALTER TABLE table_options RESET (columnar.compression);
-- show table_options settings
SELECT * FROM columnar.options
WHERE regclass = 'table_options'::regclass;
@ -191,12 +155,7 @@ WHERE regclass = 'table_options'::regclass;
table_options | 1000 | 10000 | 7 | pglz
(1 row)
SELECT alter_columnar_table_reset('table_options', compression_level => true);
alter_columnar_table_reset
---------------------------------------------------------------------
(1 row)
ALTER TABLE table_options RESET (columnar.compression_level);
-- show table_options settings
SELECT * FROM columnar.options
WHERE regclass = 'table_options'::regclass;
@ -218,17 +177,11 @@ WHERE regclass = 'table_options'::regclass;
table_options | 1000 | 10000 | 11 | pglz
(1 row)
SELECT alter_columnar_table_reset(
'table_options',
chunk_group_row_limit => true,
stripe_row_limit => true,
compression => true,
compression_level => true);
alter_columnar_table_reset
---------------------------------------------------------------------
(1 row)
ALTER TABLE table_options RESET
(columnar.chunk_group_row_limit,
columnar.stripe_row_limit,
columnar.compression,
columnar.compression_level);
-- show table_options settings
SELECT * FROM columnar.options
WHERE regclass = 'table_options'::regclass;
@ -240,37 +193,112 @@ WHERE regclass = 'table_options'::regclass;
-- verify edge cases
-- first start with a table that is not a columnar table
CREATE TABLE not_a_columnar_table (a int);
SELECT alter_columnar_table_set('not_a_columnar_table', compression => 'pglz');
ERROR: table not_a_columnar_table is not a columnar table
SELECT alter_columnar_table_reset('not_a_columnar_table', compression => true);
ERROR: table not_a_columnar_table is not a columnar table
ALTER TABLE not_a_columnar_table SET (columnar.compression = pglz);
ERROR: columnar storage parameters specified on non-columnar table
ALTER TABLE not_a_columnar_table RESET (columnar.compression);
ERROR: columnar storage parameters specified on non-columnar table
-- verify you can't use a compression that is not known
SELECT alter_columnar_table_set('table_options', compression => 'foobar');
ALTER TABLE table_options SET (columnar.compression = foobar);
ERROR: unknown compression type for columnar table: foobar
-- verify you can't use a columnar setting that is not known
ALTER TABLE table_options SET (columnar.foobar = 123);
ERROR: unrecognized columnar storage parameter "foobar"
ALTER TABLE table_options RESET (columnar.foobar);
ERROR: unrecognized columnar storage parameter "foobar"
-- verify that invalid options are caught early, before query executes
-- (error should be about invalid options, not division-by-zero)
CREATE TABLE fail(i) USING columnar WITH (columnar.foobar = 123) AS SELECT 1/0;
ERROR: unrecognized columnar storage parameter "foobar"
CREATE TABLE fail(i) USING columnar WITH (columnar.compression = foobar) AS SELECT 1/0;
ERROR: unknown compression type for columnar table: foobar
-- verify cannot set out of range compression levels
SELECT alter_columnar_table_set('table_options', compression_level => 0);
ALTER TABLE table_options SET (columnar.compression_level = 0);
ERROR: compression level out of range
HINT: compression level must be between 1 and 19
SELECT alter_columnar_table_set('table_options', compression_level => 20);
ALTER TABLE table_options SET (columnar.compression_level = 20);
ERROR: compression level out of range
HINT: compression level must be between 1 and 19
-- verify cannot set out of range stripe_row_limit & chunk_group_row_limit options
SELECT alter_columnar_table_set('table_options', stripe_row_limit => 999);
ALTER TABLE table_options SET (columnar.stripe_row_limit = 999);
ERROR: stripe row count limit out of range
HINT: stripe row count limit must be between 1000 and 10000000
SELECT alter_columnar_table_set('table_options', stripe_row_limit => 10000001);
ALTER TABLE table_options SET (columnar.stripe_row_limit = 10000001);
ERROR: stripe row count limit out of range
HINT: stripe row count limit must be between 1000 and 10000000
SELECT alter_columnar_table_set('table_options', chunk_group_row_limit => 999);
ALTER TABLE table_options SET (columnar.chunk_group_row_limit = 999);
ERROR: chunk group row count limit out of range
HINT: chunk group row count limit must be between 1000 and 100000
SELECT alter_columnar_table_set('table_options', chunk_group_row_limit => 100001);
ALTER TABLE table_options SET (columnar.chunk_group_row_limit = 100001);
ERROR: chunk group row count limit out of range
HINT: chunk group row count limit must be between 1000 and 100000
SELECT alter_columnar_table_set('table_options', chunk_group_row_limit => 0);
ALTER TABLE table_options SET (columnar.chunk_group_row_limit = 0);
ERROR: chunk group row count limit out of range
HINT: chunk group row count limit must be between 1000 and 100000
INSERT INTO table_options VALUES (1);
-- multiple SET/RESET clauses
ALTER TABLE table_options
SET (columnar.compression = pglz, columnar.compression_level = 7),
SET (columnar.compression_level = 6);
SELECT * FROM columnar.options
WHERE regclass = 'table_options'::regclass;
regclass | chunk_group_row_limit | stripe_row_limit | compression_level | compression
---------------------------------------------------------------------
table_options | 10000 | 100000 | 6 | pglz
(1 row)
ALTER TABLE table_options
SET (columnar.compression = pglz, columnar.stripe_row_limit = 7777),
RESET (columnar.stripe_row_limit),
SET (columnar.chunk_group_row_limit = 5555);
SELECT * FROM columnar.options
WHERE regclass = 'table_options'::regclass;
regclass | chunk_group_row_limit | stripe_row_limit | compression_level | compression
---------------------------------------------------------------------
table_options | 5555 | 100000 | 6 | pglz
(1 row)
-- a no-op; shouldn't throw an error
ALTER TABLE IF EXISTS what SET (columnar.compression = lz4);
NOTICE: relation "what" does not exist, skipping
-- a no-op; shouldn't throw an error
CREATE TABLE IF NOT EXISTS table_options(a int) USING columnar
WITH (columnar.compression_level = 4);
NOTICE: relation "table_options" already exists, skipping
-- test old interface based on functions
SELECT alter_columnar_table_reset('table_options', compression => true);
alter_columnar_table_reset
---------------------------------------------------------------------
(1 row)
SELECT * FROM columnar.options WHERE regclass = 'table_options'::regclass;
regclass | chunk_group_row_limit | stripe_row_limit | compression_level | compression
---------------------------------------------------------------------
table_options | 5555 | 100000 | 6 | none
(1 row)
SELECT alter_columnar_table_set('table_options', compression_level => 1);
alter_columnar_table_set
---------------------------------------------------------------------
(1 row)
SELECT * FROM columnar.options WHERE regclass = 'table_options'::regclass;
regclass | chunk_group_row_limit | stripe_row_limit | compression_level | compression
---------------------------------------------------------------------
table_options | 5555 | 100000 | 1 | none
(1 row)
-- error: set columnar options on heap tables
CREATE TABLE heap_options(i int) ;
ALTER TABLE heap_options SET (columnar.stripe_row_limit = 12000);
ERROR: columnar storage parameters specified on non-columnar table
-- ordinarily, postgres allows bogus options for a RESET clause,
-- but if it's a heap table and someone specifies columnar options,
-- we block them
ALTER TABLE heap_options RESET (columnar.stripe_row_limit, foobar);
ERROR: columnar storage parameters specified on non-columnar table
DROP TABLE heap_options;
-- verify options are removed when table is dropped
DROP TABLE table_options;
-- we expect no entries in çstore.options for anything not found int pg_class

View File

@ -62,12 +62,7 @@ select
(1 row)
-- test the case when all data cannot fit into a single stripe
SELECT alter_columnar_table_set('t', stripe_row_limit => 1000);
alter_columnar_table_set
---------------------------------------------------------------------
(1 row)
ALTER TABLE t SET (columnar.stripe_row_limit = 1000);
INSERT INTO t SELECT i, 2 * i FROM generate_series(1,2500) i;
SELECT sum(a), sum(b) FROM t;
sum | sum
@ -207,25 +202,15 @@ SELECT count(*) FROM t;
-- add some stripes with different compression types and create some gaps,
-- then vacuum to print stats
BEGIN;
SELECT alter_columnar_table_set('t',
chunk_group_row_limit => 1000,
stripe_row_limit => 2000,
compression => 'pglz');
alter_columnar_table_set
---------------------------------------------------------------------
(1 row)
ALTER TABLE t SET
(columnar.chunk_group_row_limit = 1000,
columnar.stripe_row_limit = 2000,
columnar.compression = pglz);
SAVEPOINT s1;
INSERT INTO t SELECT i FROM generate_series(1, 1500) i;
ROLLBACK TO SAVEPOINT s1;
INSERT INTO t SELECT i / 5 FROM generate_series(1, 1500) i;
SELECT alter_columnar_table_set('t', compression => 'none');
alter_columnar_table_set
---------------------------------------------------------------------
(1 row)
ALTER TABLE t SET (columnar.compression = none);
SAVEPOINT s2;
INSERT INTO t SELECT i FROM generate_series(1, 1500) i;
ROLLBACK TO SAVEPOINT s2;
@ -274,12 +259,7 @@ chunk count: 11, containing data for dropped columns: 2, none compressed: 9, pgl
-- vacuum full should remove chunks for dropped columns
-- note that, a chunk will be stored in non-compressed for if compression
-- doesn't reduce its size.
SELECT alter_columnar_table_set('t', compression => 'pglz');
alter_columnar_table_set
---------------------------------------------------------------------
(1 row)
ALTER TABLE t SET (columnar.compression = pglz);
VACUUM FULL t;
VACUUM VERBOSE t;
INFO: statistics for "t":

View File

@ -36,12 +36,7 @@ SELECT DISTINCT * FROM test_zstd ORDER BY a, b, c LIMIT 5;
VACUUM FULL test_zstd;
SELECT pg_relation_size('test_zstd') AS size_comp_level_default \gset
-- change compression level
SELECT alter_columnar_table_set('test_zstd', compression_level => 19);
alter_columnar_table_set
---------------------------------------------------------------------
(1 row)
ALTER TABLE test_zstd SET (columnar.compression_level = 19);
VACUUM FULL test_zstd;
SELECT pg_relation_size('test_zstd') AS size_comp_level_19 \gset
-- verify that higher compression level compressed better

View File

@ -759,9 +759,9 @@ DROP TABLE columnar_table;
ERROR: loaded Citus library version differs from installed extension version
CREATE INDEX ON columnar_table (a);
ERROR: loaded Citus library version differs from installed extension version
SELECT alter_columnar_table_set('columnar_table', compression => 'pglz');
ALTER TABLE columnar_table SET (columnar.compression = pglz);
ERROR: loaded Citus library version differs from installed extension version
SELECT alter_columnar_table_reset('columnar_table');
ALTER TABLE columnar_table RESET (columnar.compression);
ERROR: loaded Citus library version differs from installed extension version
INSERT INTO columnar_table SELECT * FROM columnar_table;
ERROR: loaded Citus library version differs from installed extension version

View File

@ -648,7 +648,7 @@ NOTICE: issuing BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED;SELECT assign_
DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx
NOTICE: issuing SELECT worker_apply_shard_ddl_command (915002, 'fix_idx_names', 'CREATE TABLE fix_idx_names.p2 (dist_col integer NOT NULL, another_col integer, partition_col timestamp without time zone NOT NULL, name text) USING columnar')
DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx
NOTICE: issuing SELECT alter_columnar_table_set('fix_idx_names.p2_915002', chunk_group_row_limit => 10000, stripe_row_limit => 150000, compression_level => 3, compression => 'zstd');
NOTICE: issuing ALTER TABLE fix_idx_names.p2_915002 SET (columnar.chunk_group_row_limit = 10000, columnar.stripe_row_limit = 150000, columnar.compression_level = 3, columnar.compression = 'zstd');
DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx
NOTICE: issuing SELECT worker_apply_shard_ddl_command (915002, 'fix_idx_names', 'ALTER TABLE fix_idx_names.p2 OWNER TO postgres')
DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx
@ -662,9 +662,9 @@ NOTICE: issuing CREATE TABLE fix_idx_names.p2 (dist_col integer NOT NULL, anoth
DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx
NOTICE: issuing CREATE TABLE fix_idx_names.p2 (dist_col integer NOT NULL, another_col integer, partition_col timestamp without time zone NOT NULL, name text) USING columnar
DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx
NOTICE: issuing SELECT alter_columnar_table_set('fix_idx_names.p2', chunk_group_row_limit => 10000, stripe_row_limit => 150000, compression_level => 3, compression => 'zstd');
NOTICE: issuing ALTER TABLE fix_idx_names.p2 SET (columnar.chunk_group_row_limit = 10000, columnar.stripe_row_limit = 150000, columnar.compression_level = 3, columnar.compression = 'zstd');
DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx
NOTICE: issuing SELECT alter_columnar_table_set('fix_idx_names.p2', chunk_group_row_limit => 10000, stripe_row_limit => 150000, compression_level => 3, compression => 'zstd');
NOTICE: issuing ALTER TABLE fix_idx_names.p2 SET (columnar.chunk_group_row_limit = 10000, columnar.stripe_row_limit = 150000, columnar.compression_level = 3, columnar.compression = 'zstd');
DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx
NOTICE: issuing ALTER TABLE fix_idx_names.p2 OWNER TO postgres
DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx

View File

@ -240,12 +240,7 @@ SET columnar.chunk_group_row_limit = 1050;
-- create columnar table
CREATE TABLE columnar_table (a int) USING columnar;
-- alter a columnar table that is created by that unprivileged user
SELECT alter_columnar_table_set('columnar_table', chunk_group_row_limit => 2000);
alter_columnar_table_set
---------------------------------------------------------------------
(1 row)
ALTER TABLE columnar_table SET (columnar.chunk_group_row_limit = 2000);
-- insert some data and read
INSERT INTO columnar_table VALUES (1), (1);
SELECT * FROM columnar_table;
@ -257,10 +252,10 @@ SELECT * FROM columnar_table;
-- Fail to alter a columnar table that is created by a different user
SET ROLE full_access;
SELECT alter_columnar_table_set('columnar_table', chunk_group_row_limit => 2000);
ALTER TABLE columnar_table SET (columnar.chunk_group_row_limit = 2000);
ERROR: must be owner of table columnar_table
-- Fail to reset a columnar table value created by a different user
SELECT alter_columnar_table_reset('columnar_table', chunk_group_row_limit => true);
ALTER TABLE columnar_table RESET (columnar.chunk_group_row_limit);
ERROR: must be owner of table columnar_table
SET ROLE read_access;
-- and drop it

View File

@ -656,12 +656,12 @@ CREATE USER read_access;
NOTICE: not propagating CREATE ROLE/USER commands to worker nodes
HINT: Connect to worker nodes directly to manually create all necessary users and roles.
SET ROLE read_access;
-- user shouldn't be able to execute alter_columnar_table_set
-- or alter_columnar_table_reset for a columnar table that it
-- user shouldn't be able to execute ALTER TABLE ... SET
-- or ALTER TABLE ... RESET for a columnar table that it
-- doesn't own
SELECT alter_columnar_table_set('test_pg12.superuser_columnar_table', chunk_group_row_limit => 100);
ALTER TABLE test_pg12.superuser_columnar_table SET(columnar.chunk_group_row_limit = 100);
ERROR: permission denied for schema test_pg12
SELECT alter_columnar_table_reset('test_pg12.superuser_columnar_table');
ALTER TABLE test_pg12.superuser_columnar_table RESET (columnar.chunk_group_row_limit);
ERROR: permission denied for schema test_pg12
RESET ROLE;
DROP USER read_access;

View File

@ -1,4 +1,10 @@
SET columnar.compression TO 'none';
SELECT success, result FROM run_command_on_all_nodes($cmd$
ALTER SYSTEM SET columnar.compression TO 'none'
$cmd$);
SELECT success, result FROM run_command_on_all_nodes($cmd$
SELECT pg_reload_conf()
$cmd$);
CREATE SCHEMA columnar_citus_integration;
SET search_path TO columnar_citus_integration;
@ -18,13 +24,13 @@ SELECT run_command_on_placements('table_option',$cmd$
SELECT compression FROM columnar.options WHERE regclass = '%s'::regclass;
$cmd$);
-- change setting
SELECT alter_columnar_table_set('table_option', compression => 'pglz');
ALTER TABLE table_option SET (columnar.compression = pglz);
-- verify setting
SELECT run_command_on_placements('table_option',$cmd$
SELECT compression FROM columnar.options WHERE regclass = '%s'::regclass;
$cmd$);
-- reset setting
SELECT alter_columnar_table_reset('table_option', compression => true);
ALTER TABLE table_option RESET (columnar.compression);
-- verify setting
SELECT run_command_on_placements('table_option',$cmd$
SELECT compression FROM columnar.options WHERE regclass = '%s'::regclass;
@ -36,13 +42,13 @@ SELECT run_command_on_placements('table_option',$cmd$
SELECT compression_level FROM columnar.options WHERE regclass = '%s'::regclass;
$cmd$);
-- change setting
SELECT alter_columnar_table_set('table_option', compression_level => 13);
ALTER TABLE table_option SET (columnar.compression_level = 13);
-- verify setting
SELECT run_command_on_placements('table_option',$cmd$
SELECT compression_level FROM columnar.options WHERE regclass = '%s'::regclass;
$cmd$);
-- reset setting
SELECT alter_columnar_table_reset('table_option', compression_level => true);
ALTER TABLE table_option RESET (columnar.compression_level);
-- verify setting
SELECT run_command_on_placements('table_option',$cmd$
SELECT compression_level FROM columnar.options WHERE regclass = '%s'::regclass;
@ -54,13 +60,13 @@ SELECT run_command_on_placements('table_option',$cmd$
SELECT chunk_group_row_limit FROM columnar.options WHERE regclass = '%s'::regclass;
$cmd$);
-- change setting
SELECT alter_columnar_table_set('table_option', chunk_group_row_limit => 2000);
ALTER TABLE table_option SET (columnar.chunk_group_row_limit = 2000);
-- verify setting
SELECT run_command_on_placements('table_option',$cmd$
SELECT chunk_group_row_limit FROM columnar.options WHERE regclass = '%s'::regclass;
$cmd$);
-- reset setting
SELECT alter_columnar_table_reset('table_option', chunk_group_row_limit => true);
ALTER TABLE table_option RESET (columnar.chunk_group_row_limit);
-- verify setting
SELECT run_command_on_placements('table_option',$cmd$
SELECT chunk_group_row_limit FROM columnar.options WHERE regclass = '%s'::regclass;
@ -72,13 +78,13 @@ SELECT run_command_on_placements('table_option',$cmd$
SELECT stripe_row_limit FROM columnar.options WHERE regclass = '%s'::regclass;
$cmd$);
-- change setting
SELECT alter_columnar_table_set('table_option', stripe_row_limit => 2000);
ALTER TABLE table_option SET (columnar.stripe_row_limit = 2000);
-- verify setting
SELECT run_command_on_placements('table_option',$cmd$
SELECT stripe_row_limit FROM columnar.options WHERE regclass = '%s'::regclass;
$cmd$);
-- reset setting
SELECT alter_columnar_table_reset('table_option', stripe_row_limit => true);
ALTER TABLE table_option RESET (columnar.stripe_row_limit);
-- verify setting
SELECT run_command_on_placements('table_option',$cmd$
SELECT stripe_row_limit FROM columnar.options WHERE regclass = '%s'::regclass;
@ -86,11 +92,11 @@ $cmd$);
-- verify settings are propagated when creating a table
CREATE TABLE table_option_2 (a int, b text) USING columnar;
SELECT alter_columnar_table_set('table_option_2',
chunk_group_row_limit => 2000,
stripe_row_limit => 20000,
compression => 'pglz',
compression_level => 15);
ALTER TABLE table_option_2 SET
(columnar.chunk_group_row_limit = 2000,
columnar.stripe_row_limit = 20000,
columnar.compression = pglz,
columnar.compression_level = 15);
SELECT create_distributed_table('table_option_2', 'a');
-- verify settings on placements
@ -118,13 +124,13 @@ SELECT run_command_on_placements('table_option',$cmd$
SELECT compression FROM columnar.options WHERE regclass = '%s'::regclass;
$cmd$);
-- change setting
SELECT alter_columnar_table_set('table_option', compression => 'pglz');
ALTER TABLE table_option SET (columnar.compression = pglz);
-- verify setting
SELECT run_command_on_placements('table_option',$cmd$
SELECT compression FROM columnar.options WHERE regclass = '%s'::regclass;
$cmd$);
-- reset setting
SELECT alter_columnar_table_reset('table_option', compression => true);
ALTER TABLE table_option RESET (columnar.compression);
-- verify setting
SELECT run_command_on_placements('table_option',$cmd$
SELECT compression FROM columnar.options WHERE regclass = '%s'::regclass;
@ -136,13 +142,13 @@ SELECT run_command_on_placements('table_option',$cmd$
SELECT compression_level FROM columnar.options WHERE regclass = '%s'::regclass;
$cmd$);
-- change setting
SELECT alter_columnar_table_set('table_option', compression_level => 17);
ALTER TABLE table_option SET (columnar.compression_level = 17);
-- verify setting
SELECT run_command_on_placements('table_option',$cmd$
SELECT compression_level FROM columnar.options WHERE regclass = '%s'::regclass;
$cmd$);
-- reset setting
SELECT alter_columnar_table_reset('table_option', compression_level => true);
ALTER TABLE table_option RESET (columnar.compression_level);
-- verify setting
SELECT run_command_on_placements('table_option',$cmd$
SELECT compression_level FROM columnar.options WHERE regclass = '%s'::regclass;
@ -154,13 +160,13 @@ SELECT run_command_on_placements('table_option',$cmd$
SELECT chunk_group_row_limit FROM columnar.options WHERE regclass = '%s'::regclass;
$cmd$);
-- change setting
SELECT alter_columnar_table_set('table_option', chunk_group_row_limit => 2000);
ALTER TABLE table_option SET (columnar.chunk_group_row_limit = 2000);
-- verify setting
SELECT run_command_on_placements('table_option',$cmd$
SELECT chunk_group_row_limit FROM columnar.options WHERE regclass = '%s'::regclass;
$cmd$);
-- reset setting
SELECT alter_columnar_table_reset('table_option', chunk_group_row_limit => true);
ALTER TABLE table_option RESET (columnar.chunk_group_row_limit);
-- verify setting
SELECT run_command_on_placements('table_option',$cmd$
SELECT chunk_group_row_limit FROM columnar.options WHERE regclass = '%s'::regclass;
@ -172,13 +178,13 @@ SELECT run_command_on_placements('table_option',$cmd$
SELECT stripe_row_limit FROM columnar.options WHERE regclass = '%s'::regclass;
$cmd$);
-- change setting
SELECT alter_columnar_table_set('table_option', stripe_row_limit => 2000);
ALTER TABLE table_option SET (columnar.stripe_row_limit = 2000);
-- verify setting
SELECT run_command_on_placements('table_option',$cmd$
SELECT stripe_row_limit FROM columnar.options WHERE regclass = '%s'::regclass;
$cmd$);
-- reset setting
SELECT alter_columnar_table_reset('table_option', stripe_row_limit => true);
ALTER TABLE table_option RESET (columnar.stripe_row_limit);
-- verify setting
SELECT run_command_on_placements('table_option',$cmd$
SELECT stripe_row_limit FROM columnar.options WHERE regclass = '%s'::regclass;
@ -186,11 +192,11 @@ $cmd$);
-- verify settings are propagated when creating a table
CREATE TABLE table_option_2 (a int, b text) USING columnar;
SELECT alter_columnar_table_set('table_option_2',
chunk_group_row_limit => 2000,
stripe_row_limit => 20000,
compression => 'pglz',
compression_level => 19);
ALTER TABLE table_option_2 SET
(columnar.chunk_group_row_limit = 2000,
columnar.stripe_row_limit = 20000,
columnar.compression = pglz,
columnar.compression_level = 19);
SELECT create_distributed_table('table_option_2', 'a');
-- verify settings on placements
@ -215,13 +221,13 @@ SELECT run_command_on_placements('table_option_reference',$cmd$
SELECT compression FROM columnar.options WHERE regclass = '%s'::regclass;
$cmd$);
-- change setting
SELECT alter_columnar_table_set('table_option_reference', compression => 'pglz');
ALTER TABLE table_option_reference SET (columnar.compression = pglz);
-- verify setting
SELECT run_command_on_placements('table_option_reference',$cmd$
SELECT compression FROM columnar.options WHERE regclass = '%s'::regclass;
$cmd$);
-- reset setting
SELECT alter_columnar_table_reset('table_option_reference', compression => true);
ALTER TABLE table_option_reference RESET (columnar.compression);
-- verify setting
SELECT run_command_on_placements('table_option_reference',$cmd$
SELECT compression FROM columnar.options WHERE regclass = '%s'::regclass;
@ -233,13 +239,13 @@ SELECT run_command_on_placements('table_option_reference',$cmd$
SELECT compression_level FROM columnar.options WHERE regclass = '%s'::regclass;
$cmd$);
-- change setting
SELECT alter_columnar_table_set('table_option_reference', compression_level => 11);
ALTER TABLE table_option_reference SET (columnar.compression_level = 11);
-- verify setting
SELECT run_command_on_placements('table_option_reference',$cmd$
SELECT compression_level FROM columnar.options WHERE regclass = '%s'::regclass;
$cmd$);
-- reset setting
SELECT alter_columnar_table_reset('table_option_reference', compression_level => true);
ALTER TABLE table_option_reference RESET (columnar.compression_level);
-- verify setting
SELECT run_command_on_placements('table_option_reference',$cmd$
SELECT compression_level FROM columnar.options WHERE regclass = '%s'::regclass;
@ -251,13 +257,13 @@ SELECT run_command_on_placements('table_option_reference',$cmd$
SELECT chunk_group_row_limit FROM columnar.options WHERE regclass = '%s'::regclass;
$cmd$);
-- change setting
SELECT alter_columnar_table_set('table_option_reference', chunk_group_row_limit => 2000);
ALTER TABLE table_option_reference SET (columnar.chunk_group_row_limit = 2000);
-- verify setting
SELECT run_command_on_placements('table_option_reference',$cmd$
SELECT chunk_group_row_limit FROM columnar.options WHERE regclass = '%s'::regclass;
$cmd$);
-- reset setting
SELECT alter_columnar_table_reset('table_option_reference', chunk_group_row_limit => true);
ALTER TABLE table_option_reference RESET (columnar.chunk_group_row_limit);
-- verify setting
SELECT run_command_on_placements('table_option_reference',$cmd$
SELECT chunk_group_row_limit FROM columnar.options WHERE regclass = '%s'::regclass;
@ -269,13 +275,13 @@ SELECT run_command_on_placements('table_option_reference',$cmd$
SELECT stripe_row_limit FROM columnar.options WHERE regclass = '%s'::regclass;
$cmd$);
-- change setting
SELECT alter_columnar_table_set('table_option_reference', stripe_row_limit => 2000);
ALTER TABLE table_option_reference SET (columnar.stripe_row_limit = 2000);
-- verify setting
SELECT run_command_on_placements('table_option_reference',$cmd$
SELECT stripe_row_limit FROM columnar.options WHERE regclass = '%s'::regclass;
$cmd$);
-- reset setting
SELECT alter_columnar_table_reset('table_option_reference', stripe_row_limit => true);
ALTER TABLE table_option_reference RESET (columnar.stripe_row_limit);
-- verify setting
SELECT run_command_on_placements('table_option_reference',$cmd$
SELECT stripe_row_limit FROM columnar.options WHERE regclass = '%s'::regclass;
@ -283,11 +289,11 @@ $cmd$);
-- verify settings are propagated when creating a table
CREATE TABLE table_option_reference_2 (a int, b text) USING columnar;
SELECT alter_columnar_table_set('table_option_reference_2',
chunk_group_row_limit => 2000,
stripe_row_limit => 20000,
compression => 'pglz',
compression_level => 9);
ALTER TABLE table_option_reference_2 SET
(columnar.chunk_group_row_limit = 2000,
columnar.stripe_row_limit = 20000,
columnar.compression = pglz,
columnar.compression_level = 9);
SELECT create_reference_table('table_option_reference_2');
-- verify settings on placements
@ -315,13 +321,13 @@ SELECT run_command_on_placements('table_option_citus_local',$cmd$
SELECT compression FROM columnar.options WHERE regclass = '%s'::regclass;
$cmd$);
-- change setting
SELECT alter_columnar_table_set('table_option_citus_local', compression => 'pglz');
ALTER TABLE table_option_citus_local SET (columnar.compression = pglz);
-- verify setting
SELECT run_command_on_placements('table_option_citus_local',$cmd$
SELECT compression FROM columnar.options WHERE regclass = '%s'::regclass;
$cmd$);
-- reset setting
SELECT alter_columnar_table_reset('table_option_citus_local', compression => true);
ALTER TABLE table_option_citus_local RESET (columnar.compression);
-- verify setting
SELECT run_command_on_placements('table_option_citus_local',$cmd$
SELECT compression FROM columnar.options WHERE regclass = '%s'::regclass;
@ -333,13 +339,13 @@ SELECT run_command_on_placements('table_option_citus_local',$cmd$
SELECT compression_level FROM columnar.options WHERE regclass = '%s'::regclass;
$cmd$);
-- change setting
SELECT alter_columnar_table_set('table_option_citus_local', compression_level => 11);
ALTER TABLE table_option_citus_local SET (columnar.compression_level = 11);
-- verify setting
SELECT run_command_on_placements('table_option_citus_local',$cmd$
SELECT compression_level FROM columnar.options WHERE regclass = '%s'::regclass;
$cmd$);
-- reset setting
SELECT alter_columnar_table_reset('table_option_citus_local', compression_level => true);
ALTER TABLE table_option_citus_local RESET (columnar.compression_level);
-- verify setting
SELECT run_command_on_placements('table_option_citus_local',$cmd$
SELECT compression_level FROM columnar.options WHERE regclass = '%s'::regclass;
@ -351,13 +357,13 @@ SELECT run_command_on_placements('table_option_citus_local',$cmd$
SELECT chunk_group_row_limit FROM columnar.options WHERE regclass = '%s'::regclass;
$cmd$);
-- change setting
SELECT alter_columnar_table_set('table_option_citus_local', chunk_group_row_limit => 2000);
ALTER TABLE table_option_citus_local SET (columnar.chunk_group_row_limit = 2000);
-- verify setting
SELECT run_command_on_placements('table_option_citus_local',$cmd$
SELECT chunk_group_row_limit FROM columnar.options WHERE regclass = '%s'::regclass;
$cmd$);
-- reset setting
SELECT alter_columnar_table_reset('table_option_citus_local', chunk_group_row_limit => true);
ALTER TABLE table_option_citus_local RESET (columnar.chunk_group_row_limit);
-- verify setting
SELECT run_command_on_placements('table_option_citus_local',$cmd$
SELECT chunk_group_row_limit FROM columnar.options WHERE regclass = '%s'::regclass;
@ -369,13 +375,13 @@ SELECT run_command_on_placements('table_option_citus_local',$cmd$
SELECT stripe_row_limit FROM columnar.options WHERE regclass = '%s'::regclass;
$cmd$);
-- change setting
SELECT alter_columnar_table_set('table_option_citus_local', stripe_row_limit => 2000);
ALTER TABLE table_option_citus_local SET (columnar.stripe_row_limit = 2000);
-- verify setting
SELECT run_command_on_placements('table_option_citus_local',$cmd$
SELECT stripe_row_limit FROM columnar.options WHERE regclass = '%s'::regclass;
$cmd$);
-- reset setting
SELECT alter_columnar_table_reset('table_option_citus_local', stripe_row_limit => true);
ALTER TABLE table_option_citus_local RESET (columnar.stripe_row_limit);
-- verify setting
SELECT run_command_on_placements('table_option_citus_local',$cmd$
SELECT stripe_row_limit FROM columnar.options WHERE regclass = '%s'::regclass;
@ -383,11 +389,11 @@ $cmd$);
-- verify settings are propagated when creating a table
CREATE TABLE table_option_citus_local_2 (a int, b text) USING columnar;
SELECT alter_columnar_table_set('table_option_citus_local_2',
chunk_group_row_limit => 2000,
stripe_row_limit => 20000,
compression => 'pglz',
compression_level => 9);
ALTER TABLE table_option_citus_local_2 SET
(columnar.chunk_group_row_limit = 2000,
columnar.stripe_row_limit = 20000,
columnar.compression = pglz,
columnar.compression_level = 9);
SELECT citus_add_local_table_to_metadata('table_option_citus_local_2');
-- verify settings on placements

View File

@ -7,7 +7,7 @@
CREATE TABLE contestant (handle TEXT, birthdate DATE, rating INT,
percentile FLOAT, country CHAR(3), achievements TEXT[])
USING columnar;
SELECT alter_columnar_table_set('contestant', compression => 'none');
ALTER TABLE contestant SET (columnar.compression = none);
CREATE INDEX contestant_idx on contestant(handle);

View File

@ -7,9 +7,9 @@ create table t_uncompressed(a int) using columnar;
create table t_compressed(a int) using columnar;
-- set options
SELECT alter_columnar_table_set('t_compressed', compression => 'pglz');
SELECT alter_columnar_table_set('t_compressed', stripe_row_limit => 2000);
SELECT alter_columnar_table_set('t_compressed', chunk_group_row_limit => 1000);
ALTER TABLE t_compressed SET (columnar.compression = pglz);
ALTER TABLE t_compressed SET (columnar.stripe_row_limit = 2000);
ALTER TABLE t_compressed SET (columnar.chunk_group_row_limit = 1000);
SELECT * FROM columnar.options WHERE regclass = 't_compressed'::regclass;

View File

@ -10,7 +10,7 @@ set columnar.enable_custom_scan = false;
create table fallback_scan(i int) using columnar;
-- large enough to test parallel_workers > 1
select alter_columnar_table_set('fallback_scan', compression => 'none');
ALTER TABLE fallback_scan SET (columnar.compression = none);
insert into fallback_scan select generate_series(1,150000);
vacuum analyze fallback_scan;

View File

@ -12,7 +12,7 @@ ROLLBACK;
INSERT INTO col_table_1 SELECT i FROM generate_series(1, 12) i;
SELECT alter_columnar_table_set('col_table_1', stripe_row_limit => 1000);
ALTER TABLE col_table_1 SET (columnar.stripe_row_limit = 1000);
INSERT INTO col_table_1 SELECT i FROM generate_series(1, 2350) i;

View File

@ -119,7 +119,7 @@ DROP TABLE test_toast_columnar;
-- We support writing into zero column tables, but not reading from them.
-- We test that metadata makes sense so we can fix the read path in future.
CREATE TABLE zero_col() USING columnar;
SELECT alter_columnar_table_set('zero_col', chunk_group_row_limit => 1000);
ALTER TABLE zero_col SET (columnar.chunk_group_row_limit = 1000);
INSERT INTO zero_col DEFAULT VALUES;
INSERT INTO zero_col DEFAULT VALUES;
@ -157,7 +157,7 @@ ORDER BY 1,2,3,4;
CREATE TABLE selfinsert(x int) USING columnar;
SELECT alter_columnar_table_set('selfinsert', stripe_row_limit => 1000);
ALTER TABLE selfinsert SET (columnar.stripe_row_limit = 1000);
BEGIN;
INSERT INTO selfinsert SELECT generate_series(1,1010);

View File

@ -22,7 +22,7 @@ SELECT * FROM columnar.options
WHERE regclass = 't_view'::regclass;
-- show we can set options on a materialized view
SELECT alter_columnar_table_set('t_view', compression => 'pglz');
ALTER TABLE t_view SET (columnar.compression = pglz);
SELECT * FROM columnar.options
WHERE regclass = 't_view'::regclass;

View File

@ -1,4 +1,6 @@
create table no_access (i int) using columnar;
select current_user \gset
create user columnar_user;
@ -8,10 +10,20 @@ create user columnar_user;
create table columnar_permissions(i int) using columnar;
insert into columnar_permissions values(1);
alter table columnar_permissions add column j int;
alter table columnar_permissions reset (columnar.compression);
alter table columnar_permissions set (columnar.compression = none);
select alter_columnar_table_reset('columnar_permissions', stripe_row_limit => true);
select alter_columnar_table_set('columnar_permissions', stripe_row_limit => 2222);
select * from columnar.options where regclass = 'columnar_permissions'::regclass;
insert into columnar_permissions values(2,20);
vacuum columnar_permissions;
truncate columnar_permissions;
drop table columnar_permissions;
\c - :current_user
-- should error
alter table no_access reset (columnar.stripe_row_limit);
alter table no_access set (columnar.stripe_row_limit = 12000);
select alter_columnar_table_reset('no_access', chunk_group_row_limit => true);
select alter_columnar_table_set('no_access', chunk_group_row_limit => 1111);
\c - :current_user

View File

@ -0,0 +1,34 @@
SHOW server_version \gset
SELECT substring(:'server_version', '\d+')::int >= 15 AS server_version_ge_15
\gset
\if :server_version_ge_15
\else
\q
\endif
CREATE TABLE alter_am(i int);
INSERT INTO alter_am SELECT generate_series(1,1000000);
SELECT * FROM columnar.options WHERE regclass = 'alter_am'::regclass;
SELECT SUM(i) FROM alter_am;
ALTER TABLE alter_am
SET ACCESS METHOD columnar,
SET (columnar.compression = pglz, fillfactor = 20);
SELECT * FROM columnar.options WHERE regclass = 'alter_am'::regclass;
SELECT SUM(i) FROM alter_am;
ALTER TABLE alter_am SET ACCESS METHOD heap;
-- columnar options should be gone
SELECT * FROM columnar.options WHERE regclass = 'alter_am'::regclass;
SELECT SUM(i) FROM alter_am;
-- error: setting columnar options must happen after converting to columnar
ALTER TABLE alter_am
SET (columnar.stripe_row_limit = 1111),
SET ACCESS METHOD columnar;
DROP TABLE alter_am;

View File

@ -10,28 +10,28 @@ SELECT * FROM columnar.options
WHERE regclass = 'table_options'::regclass;
-- test changing the compression
SELECT alter_columnar_table_set('table_options', compression => 'pglz');
ALTER TABLE table_options SET (columnar.compression = pglz);
-- show table_options settings
SELECT * FROM columnar.options
WHERE regclass = 'table_options'::regclass;
-- test changing the compression level
SELECT alter_columnar_table_set('table_options', compression_level => 5);
ALTER TABLE table_options SET (columnar.compression_level = 5);
-- show table_options settings
SELECT * FROM columnar.options
WHERE regclass = 'table_options'::regclass;
-- test changing the chunk_group_row_limit
SELECT alter_columnar_table_set('table_options', chunk_group_row_limit => 2000);
ALTER TABLE table_options SET (columnar.chunk_group_row_limit = 2000);
-- show table_options settings
SELECT * FROM columnar.options
WHERE regclass = 'table_options'::regclass;
-- test changing the chunk_group_row_limit
SELECT alter_columnar_table_set('table_options', stripe_row_limit => 4000);
ALTER TABLE table_options SET (columnar.stripe_row_limit = 4000);
-- show table_options settings
SELECT * FROM columnar.options
@ -45,7 +45,11 @@ SELECT * FROM columnar.options
WHERE regclass = 'table_options'::regclass;
-- set all settings at the same time
SELECT alter_columnar_table_set('table_options', stripe_row_limit => 8000, chunk_group_row_limit => 4000, compression => 'none', compression_level => 7);
ALTER TABLE table_options SET
(columnar.stripe_row_limit = 8000,
columnar.chunk_group_row_limit = 4000,
columnar.compression = none,
columnar.compression_level = 7);
-- show table_options settings
SELECT * FROM columnar.options
@ -85,24 +89,24 @@ SET columnar.compression_level TO 11;
SELECT * FROM columnar.options
WHERE regclass = 'table_options'::regclass;
SELECT alter_columnar_table_reset('table_options', chunk_group_row_limit => true);
ALTER TABLE table_options RESET (columnar.chunk_group_row_limit);
-- show table_options settings
SELECT * FROM columnar.options
WHERE regclass = 'table_options'::regclass;
SELECT alter_columnar_table_reset('table_options', stripe_row_limit => true);
ALTER TABLE table_options RESET (columnar.stripe_row_limit);
-- show table_options settings
SELECT * FROM columnar.options
WHERE regclass = 'table_options'::regclass;
SELECT alter_columnar_table_reset('table_options', compression => true);
ALTER TABLE table_options RESET (columnar.compression);
-- show table_options settings
SELECT * FROM columnar.options
WHERE regclass = 'table_options'::regclass;
SELECT alter_columnar_table_reset('table_options', compression_level => true);
ALTER TABLE table_options RESET (columnar.compression_level);
-- show table_options settings
SELECT * FROM columnar.options
@ -118,12 +122,11 @@ SET columnar.compression_level TO 13;
SELECT * FROM columnar.options
WHERE regclass = 'table_options'::regclass;
SELECT alter_columnar_table_reset(
'table_options',
chunk_group_row_limit => true,
stripe_row_limit => true,
compression => true,
compression_level => true);
ALTER TABLE table_options RESET
(columnar.chunk_group_row_limit,
columnar.stripe_row_limit,
columnar.compression,
columnar.compression_level);
-- show table_options settings
SELECT * FROM columnar.options
@ -132,24 +135,72 @@ WHERE regclass = 'table_options'::regclass;
-- verify edge cases
-- first start with a table that is not a columnar table
CREATE TABLE not_a_columnar_table (a int);
SELECT alter_columnar_table_set('not_a_columnar_table', compression => 'pglz');
SELECT alter_columnar_table_reset('not_a_columnar_table', compression => true);
ALTER TABLE not_a_columnar_table SET (columnar.compression = pglz);
ALTER TABLE not_a_columnar_table RESET (columnar.compression);
-- verify you can't use a compression that is not known
SELECT alter_columnar_table_set('table_options', compression => 'foobar');
ALTER TABLE table_options SET (columnar.compression = foobar);
-- verify you can't use a columnar setting that is not known
ALTER TABLE table_options SET (columnar.foobar = 123);
ALTER TABLE table_options RESET (columnar.foobar);
-- verify that invalid options are caught early, before query executes
-- (error should be about invalid options, not division-by-zero)
CREATE TABLE fail(i) USING columnar WITH (columnar.foobar = 123) AS SELECT 1/0;
CREATE TABLE fail(i) USING columnar WITH (columnar.compression = foobar) AS SELECT 1/0;
-- verify cannot set out of range compression levels
SELECT alter_columnar_table_set('table_options', compression_level => 0);
SELECT alter_columnar_table_set('table_options', compression_level => 20);
ALTER TABLE table_options SET (columnar.compression_level = 0);
ALTER TABLE table_options SET (columnar.compression_level = 20);
-- verify cannot set out of range stripe_row_limit & chunk_group_row_limit options
SELECT alter_columnar_table_set('table_options', stripe_row_limit => 999);
SELECT alter_columnar_table_set('table_options', stripe_row_limit => 10000001);
SELECT alter_columnar_table_set('table_options', chunk_group_row_limit => 999);
SELECT alter_columnar_table_set('table_options', chunk_group_row_limit => 100001);
SELECT alter_columnar_table_set('table_options', chunk_group_row_limit => 0);
ALTER TABLE table_options SET (columnar.stripe_row_limit = 999);
ALTER TABLE table_options SET (columnar.stripe_row_limit = 10000001);
ALTER TABLE table_options SET (columnar.chunk_group_row_limit = 999);
ALTER TABLE table_options SET (columnar.chunk_group_row_limit = 100001);
ALTER TABLE table_options SET (columnar.chunk_group_row_limit = 0);
INSERT INTO table_options VALUES (1);
-- multiple SET/RESET clauses
ALTER TABLE table_options
SET (columnar.compression = pglz, columnar.compression_level = 7),
SET (columnar.compression_level = 6);
SELECT * FROM columnar.options
WHERE regclass = 'table_options'::regclass;
ALTER TABLE table_options
SET (columnar.compression = pglz, columnar.stripe_row_limit = 7777),
RESET (columnar.stripe_row_limit),
SET (columnar.chunk_group_row_limit = 5555);
SELECT * FROM columnar.options
WHERE regclass = 'table_options'::regclass;
-- a no-op; shouldn't throw an error
ALTER TABLE IF EXISTS what SET (columnar.compression = lz4);
-- a no-op; shouldn't throw an error
CREATE TABLE IF NOT EXISTS table_options(a int) USING columnar
WITH (columnar.compression_level = 4);
-- test old interface based on functions
SELECT alter_columnar_table_reset('table_options', compression => true);
SELECT * FROM columnar.options WHERE regclass = 'table_options'::regclass;
SELECT alter_columnar_table_set('table_options', compression_level => 1);
SELECT * FROM columnar.options WHERE regclass = 'table_options'::regclass;
-- error: set columnar options on heap tables
CREATE TABLE heap_options(i int) USING heap;
ALTER TABLE heap_options SET (columnar.stripe_row_limit = 12000);
-- ordinarily, postgres allows bogus options for a RESET clause,
-- but if it's a heap table and someone specifies columnar options,
-- we block them
ALTER TABLE heap_options RESET (columnar.stripe_row_limit, foobar);
DROP TABLE heap_options;
-- verify options are removed when table is dropped
DROP TABLE table_options;
-- we expect no entries in çstore.options for anything not found int pg_class

View File

@ -34,7 +34,7 @@ select
from columnar_test_helpers.columnar_storage_info('t');
-- test the case when all data cannot fit into a single stripe
SELECT alter_columnar_table_set('t', stripe_row_limit => 1000);
ALTER TABLE t SET (columnar.stripe_row_limit = 1000);
INSERT INTO t SELECT i, 2 * i FROM generate_series(1,2500) i;
SELECT sum(a), sum(b) FROM t;
@ -91,15 +91,15 @@ SELECT count(*) FROM t;
-- then vacuum to print stats
BEGIN;
SELECT alter_columnar_table_set('t',
chunk_group_row_limit => 1000,
stripe_row_limit => 2000,
compression => 'pglz');
ALTER TABLE t SET
(columnar.chunk_group_row_limit = 1000,
columnar.stripe_row_limit = 2000,
columnar.compression = pglz);
SAVEPOINT s1;
INSERT INTO t SELECT i FROM generate_series(1, 1500) i;
ROLLBACK TO SAVEPOINT s1;
INSERT INTO t SELECT i / 5 FROM generate_series(1, 1500) i;
SELECT alter_columnar_table_set('t', compression => 'none');
ALTER TABLE t SET (columnar.compression = none);
SAVEPOINT s2;
INSERT INTO t SELECT i FROM generate_series(1, 1500) i;
ROLLBACK TO SAVEPOINT s2;
@ -125,7 +125,7 @@ VACUUM VERBOSE t;
-- vacuum full should remove chunks for dropped columns
-- note that, a chunk will be stored in non-compressed for if compression
-- doesn't reduce its size.
SELECT alter_columnar_table_set('t', compression => 'pglz');
ALTER TABLE t SET (columnar.compression = pglz);
VACUUM FULL t;
VACUUM VERBOSE t;

View File

@ -26,7 +26,7 @@ VACUUM FULL test_zstd;
SELECT pg_relation_size('test_zstd') AS size_comp_level_default \gset
-- change compression level
SELECT alter_columnar_table_set('test_zstd', compression_level => 19);
ALTER TABLE test_zstd SET (columnar.compression_level = 19);
VACUUM FULL test_zstd;
SELECT pg_relation_size('test_zstd') AS size_comp_level_19 \gset

View File

@ -315,8 +315,8 @@ VACUUM columnar_table;
TRUNCATE columnar_table;
DROP TABLE columnar_table;
CREATE INDEX ON columnar_table (a);
SELECT alter_columnar_table_set('columnar_table', compression => 'pglz');
SELECT alter_columnar_table_reset('columnar_table');
ALTER TABLE columnar_table SET(columnar.compression = pglz);
ALTER TABLE columnar_table RESET (columnar.compression);
INSERT INTO columnar_table SELECT * FROM columnar_table;
SELECT 1 FROM columnar_table; -- columnar custom scan

View File

@ -137,15 +137,15 @@ SET columnar.chunk_group_row_limit = 1050;
-- create columnar table
CREATE TABLE columnar_table (a int) USING columnar;
-- alter a columnar table that is created by that unprivileged user
SELECT alter_columnar_table_set('columnar_table', chunk_group_row_limit => 2000);
ALTER TABLE columnar_table SET (columnar.chunk_group_row_limit = 2000);
-- insert some data and read
INSERT INTO columnar_table VALUES (1), (1);
SELECT * FROM columnar_table;
-- Fail to alter a columnar table that is created by a different user
SET ROLE full_access;
SELECT alter_columnar_table_set('columnar_table', chunk_group_row_limit => 2000);
ALTER TABLE columnar_table SET (columnar.chunk_group_row_limit = 2000);
-- Fail to reset a columnar table value created by a different user
SELECT alter_columnar_table_reset('columnar_table', chunk_group_row_limit => true);
ALTER TABLE columnar_table RESET (columnar.chunk_group_row_limit);
SET ROLE read_access;
-- and drop it
DROP TABLE columnar_table;

View File

@ -388,11 +388,11 @@ CREATE TABLE superuser_columnar_table (a int) USING columnar;
CREATE USER read_access;
SET ROLE read_access;
-- user shouldn't be able to execute alter_columnar_table_set
-- or alter_columnar_table_reset for a columnar table that it
-- user shouldn't be able to execute ALTER TABLE ... SET
-- or ALTER TABLE ... RESET for a columnar table that it
-- doesn't own
SELECT alter_columnar_table_set('test_pg12.superuser_columnar_table', chunk_group_row_limit => 100);
SELECT alter_columnar_table_reset('test_pg12.superuser_columnar_table');
ALTER TABLE test_pg12.superuser_columnar_table SET(columnar.chunk_group_row_limit = 100);
ALTER TABLE test_pg12.superuser_columnar_table RESET (columnar.chunk_group_row_limit);
RESET ROLE;
DROP USER read_access;