Refactor tablespace handling

Attaching tablespaces to hypertables is now handled
in native code, with improved permissions checking and
caching of tablespaces in the Hypertable data object.
This commit is contained in:
Erik Nordström 2017-11-20 13:40:27 +01:00 committed by Erik Nordström
parent c4a46ac8a1
commit e593876cb0
22 changed files with 442 additions and 89 deletions

View File

@ -34,3 +34,7 @@ FOR EACH STATEMENT EXECUTE PROCEDURE _timescaledb_cache.invalidate_relcache_trig
DROP TRIGGER IF EXISTS "0_cache_inval" ON _timescaledb_catalog.dimension;
CREATE TRIGGER "0_cache_inval" AFTER INSERT OR UPDATE OR DELETE OR TRUNCATE ON _timescaledb_catalog.dimension
FOR EACH STATEMENT EXECUTE PROCEDURE _timescaledb_cache.invalidate_relcache_trigger();
DROP TRIGGER IF EXISTS "0_cache_inval" ON _timescaledb_catalog.tablespace;
CREATE TRIGGER "0_cache_inval" AFTER INSERT OR UPDATE OR DELETE OR TRUNCATE ON _timescaledb_catalog.tablespace
FOR EACH STATEMENT EXECUTE PROCEDURE _timescaledb_cache.invalidate_relcache_trigger();

View File

@ -298,33 +298,8 @@ BEGIN
END
$BODY$;
CREATE OR REPLACE FUNCTION attach_tablespace(
hypertable REGCLASS,
tablespace NAME
)
RETURNS VOID LANGUAGE PLPGSQL VOLATILE
SECURITY DEFINER SET search_path = ''
AS
CREATE OR REPLACE FUNCTION attach_tablespace(tablespace NAME, hypertable REGCLASS)
RETURNS VOID LANGUAGE SQL AS
$BODY$
DECLARE
hypertable_id INTEGER;
tablespace_oid OID;
BEGIN
PERFORM _timescaledb_internal.check_role(hypertable);
SELECT id
FROM _timescaledb_catalog.hypertable h, pg_class c, pg_namespace n
WHERE h.schema_name = n.nspname
AND h.table_name = c.relname
AND c.oid = hypertable
AND n.oid = c.relnamespace
INTO hypertable_id;
IF hypertable_id IS NULL THEN
RAISE EXCEPTION 'No hypertable "%" exists', main_table_name
USING ERRCODE = 'IO101';
END IF;
PERFORM _timescaledb_internal.attach_tablespace(hypertable_id, tablespace);
END
SELECT * FROM _timescaledb_internal.attach_tablespace(tablespace, hypertable);
$BODY$;

View File

@ -80,11 +80,6 @@ BEGIN
)
RETURNING * INTO hypertable_row;
--add default tablespace, if any
IF tablespace IS NOT NULL THEN
PERFORM _timescaledb_internal.attach_tablespace(hypertable_row.id, tablespace);
END IF;
--create time dimension
PERFORM _timescaledb_internal.add_dimension(main_table,
hypertable_row,
@ -112,6 +107,11 @@ BEGIN
PERFORM _timescaledb_internal.create_default_indexes(hypertable_row, main_table, partitioning_column);
END IF;
--add default tablespace, if any
IF tablespace IS NOT NULL THEN
PERFORM _timescaledb_internal.attach_tablespace(tablespace, main_table);
END IF;
RETURN hypertable_row;
END
$BODY$;
@ -618,6 +618,8 @@ BEGIN
END
$BODY$;
CREATE OR REPLACE FUNCTION _timescaledb_internal.attach_tablespace(tablespace NAME, hypertable REGCLASS) RETURNS VOID
AS '$libdir/timescaledb', 'tablespace_attach' LANGUAGE C VOLATILE;
--documentation of these function located in chunk_index.h
CREATE OR REPLACE FUNCTION _timescaledb_internal.chunk_index_clone(chunk_index_oid OID) RETURNS OID

View File

@ -88,34 +88,3 @@ $BODY$
(SELECT hypertable_id FROM _timescaledb_catalog.chunk WHERE id = chunk_id),
chunk_id);
$BODY$;
CREATE OR REPLACE FUNCTION _timescaledb_internal.attach_tablespace(
hypertable_id INTEGER,
tablespace_name NAME
)
RETURNS VOID LANGUAGE PLPGSQL VOLATILE AS
$BODY$
DECLARE
tablespace_oid OID;
BEGIN
SELECT oid
FROM pg_catalog.pg_tablespace
WHERE spcname = tablespace_name
INTO tablespace_oid;
IF tablespace_oid IS NULL THEN
RAISE EXCEPTION 'No tablespace "%" exists. A tablespace needs to be created before assigning it to a hypertable dimension', tablespace_name
USING ERRCODE = 'IO101';
END IF;
BEGIN
INSERT INTO _timescaledb_catalog.tablespace (hypertable_id, tablespace_name)
VALUES (hypertable_id, tablespace_name);
EXCEPTION
WHEN unique_violation THEN
RAISE EXCEPTION 'Tablespace "%" already assigned to hypertable "%"',
tablespace_name, (SELECT table_name FROM _timescaledb_catalog.hypertable
WHERE id = hypertable_id);
END;
END
$BODY$;

View File

@ -35,3 +35,6 @@ DROP FUNCTION create_hypertable(regclass,name,name,integer,name,name,anyelement,
DROP FUNCTION add_dimension(regclass,name,integer,bigint);
DROP FUNCTION _timescaledb_internal.create_hypertable_row(regclass,name,name,name,name,integer,name,name,bigint,name);
DROP FUNCTION _timescaledb_internal.add_dimension(regclass,_timescaledb_catalog.hypertable,name,integer,bigint,boolean);
-- Tablespace functions
DROP FUNCTION _timescaledb_internal.attach_tablespace(integer, name);

View File

@ -1,6 +1,11 @@
DROP FUNCTION _timescaledb_cache.invalidate_relcache(oid);
DROP FUNCTION set_chunk_time_interval(REGCLASS, BIGINT);
DROP FUNCTION add_dimension(REGCLASS, NAME, INTEGER, BIGINT, REGPROC);
DROP FUNCTION _timescaledb_internal.add_dimension(REGCLASS, _timescaledb_catalog.hypertable, NAME, INTEGER, BIGINT, REGPROC, BOOLEAN);
DROP FUNCTION _timescaledb_internal.time_interval_specification_to_internal(REGTYPE, anyelement, INTERVAL, TEXT);
-- Tablespace changes
DROP FUNCTION _timescaledb_internal.attach_tablespace(integer, name);
DROP FUNCTION attach_tablespace(regclass, name);

View File

@ -63,6 +63,7 @@ set(HEADERS
process_utility.h
scanner.h
subspace_store.h
tablespace.h
trigger.h
utils.h)
@ -105,6 +106,7 @@ set(SOURCES
scanner.c
sort_transform.c
subspace_store.c
tablespace.c
trigger.c
utils.c
version.c)

View File

@ -28,6 +28,7 @@ static const char *catalog_table_names[_MAX_CATALOG_TABLES + 1] = {
[CHUNK] = CHUNK_TABLE_NAME,
[CHUNK_CONSTRAINT] = CHUNK_CONSTRAINT_TABLE_NAME,
[CHUNK_INDEX] = CHUNK_INDEX_TABLE_NAME,
[TABLESPACE] = TABLESPACE_TABLE_NAME,
[_MAX_CATALOG_TABLES] = "invalid table",
};
@ -79,6 +80,13 @@ static const TableIndexDef catalog_table_index_definitions[_MAX_CATALOG_TABLES]
[CHUNK_INDEX_CHUNK_ID_INDEX_NAME_IDX] = "chunk_index_chunk_id_index_name_key",
[CHUNK_INDEX_HYPERTABLE_ID_HYPERTABLE_INDEX_NAME_IDX] = "chunk_index_hypertable_id_hypertable_index_name_idx",
}
},
[TABLESPACE] = {
.length = _MAX_TABLESPACE_INDEX,
.names = (char *[]) {
[TABLESPACE_PKEY_IDX] = "tablespace_pkey",
[TABLESPACE_HYPERTABLE_ID_TABLESPACE_NAME_IDX] = "tablespace_hypertable_id_tablespace_name_key",
}
}
};
@ -88,6 +96,8 @@ static const char *catalog_table_serial_id_names[_MAX_CATALOG_TABLES] = {
[DIMENSION_SLICE] = CATALOG_SCHEMA_NAME ".dimension_slice_id_seq",
[CHUNK] = CATALOG_SCHEMA_NAME ".chunk_id_seq",
[CHUNK_CONSTRAINT] = NULL,
[CHUNK_INDEX] = NULL,
[TABLESPACE] = CATALOG_SCHEMA_NAME ".tablespace_id_seq",
};
typedef struct InternalFunctionDef

View File

@ -29,6 +29,7 @@ typedef enum CatalogTable
CHUNK,
CHUNK_CONSTRAINT,
CHUNK_INDEX,
TABLESPACE,
_MAX_CATALOG_TABLES,
} CatalogTable;
@ -375,7 +376,6 @@ enum Anum_chunk_index_chunk_id_index_name_idx
_Anum_chunk_index_chunk_id_index_name_idx_max,
};
enum Anum_chunk_index_hypertable_id_hypertable_index_name_idx
{
Anum_chunk_index_hypertable_id_hypertable_index_name_idx_hypertable_id = 1,
@ -383,6 +383,66 @@ enum Anum_chunk_index_hypertable_id_hypertable_index_name_idx
Anum_chunk_index_hypertable_id_hypertable_index_name_idx_max,
};
/************************************
*
* Tablespace table definitions
*
************************************/
#define TABLESPACE_TABLE_NAME "tablespace"
enum Anum_tablespace
{
Anum_tablespace_id = 1,
Anum_tablespace_hypertable_id,
Anum_tablespace_tablespace_name,
_Anum_tablespace_max,
};
#define Natts_tablespace \
(_Anum_tablespace_max - 1)
typedef struct FormData_tablespace
{
int32 id;
int32 hypertable_id;
NameData tablespace_name;
} FormData_tablespace;
typedef FormData_tablespace *Form_tablespace;
enum
{
TABLESPACE_PKEY_IDX = 0,
TABLESPACE_HYPERTABLE_ID_TABLESPACE_NAME_IDX,
_MAX_TABLESPACE_INDEX,
};
enum Anum_tablespace_pkey_idx
{
Anum_tablespace_pkey_idx_tablespace_id = 1,
_Anum_tablespace_pkey_idx_max,
};
typedef struct FormData_tablespace_pkey_idx
{
int32 tablespace_id;
} FormData_tablespace_pkey_idx;
enum Anum_tablespace_hypertable_id_tablespace_name_idx
{
Anum_tablespace_hypertable_id_tablespace_name_idx_hypertable_id = 1,
Anum_tablespace_hypertable_id_tablespace_name_idx_tablespace_name,
_Anum_tablespace_hypertable_id_tablespace_name_idx_max,
};
typedef struct FormData_tablespace_hypertable_id_tablespace_name_idx
{
int32 hypertable_id;
NameData tablespace_name;
} FormData_tablespace_hypertable_id_tablespace_name_idx;
#define MAX(a, b) \
((long)(a) > (long)(b) ? (a) : (b))
@ -392,7 +452,8 @@ enum Anum_chunk_index_hypertable_id_hypertable_index_name_idx
MAX(_MAX_DIMENSION_SLICE_INDEX, \
MAX(_MAX_CHUNK_CONSTRAINT_INDEX, \
MAX(_MAX_CHUNK_INDEX_INDEX, \
_MAX_CHUNK_INDEX)))))
MAX(_MAX_TABLESPACE_INDEX, \
_MAX_CHUNK_INDEX))))))
typedef enum CacheType
{

View File

@ -27,6 +27,7 @@
#define ERRCODE_IO_HYPERTABLE_EXISTS MAKE_SQLSTATE('I','O','1','1','0')
#define ERRCODE_IO_NODE_EXISTS MAKE_SQLSTATE('I','O','1','2','0')
#define ERRCODE_IO_USER_EXISTS MAKE_SQLSTATE('I','O','1','3','0')
#define ERRCODE_IO_TABLESPACE_ALREADY_ATTACHED MAKE_SQLSTATE('I','O','1','4','0')
/*
--IO500 - GROUP: internal error

View File

@ -28,6 +28,7 @@ hypertable_from_tuple(HeapTuple tuple)
h->main_table_relid = get_relname_relid(NameStr(h->fd.table_name), namespace_oid);
h->space = dimension_scan(h->fd.id, h->main_table_relid, h->fd.num_dimensions);
h->chunk_cache = subspace_store_init(h->space->num_dimensions, CurrentMemoryContext);
h->tablespaces = tablespace_scan(h->fd.id);
return h;
}
@ -213,6 +214,25 @@ hypertable_get_chunk(Hypertable *h, Point *point)
return cce->chunk;
}
bool
hypertable_has_tablespace(Hypertable *ht, Oid tspc_oid)
{
Tablespaces *tspcs = ht->tablespaces;
int i;
for (i = 0; i < tspcs->num_tablespaces; i++)
if (tspc_oid == tspcs->tablespaces[i].tablespace_oid)
return true;
return false;
}
Tablespace *
hypertable_add_tablespace(Hypertable *ht, int32 tspc_id, Oid tspc_oid)
{
return tablespaces_add(ht->tablespaces, tspc_id, tspc_oid);
}
static inline Oid
hypertable_relid_lookup(Oid relid)
{

View File

@ -6,6 +6,7 @@
#include "catalog.h"
#include "dimension.h"
#include "tablespace.h"
typedef struct SubspaceStore SubspaceStore;
typedef struct Chunk Chunk;
@ -17,6 +18,7 @@ typedef struct Hypertable
Oid main_table_relid;
Hyperspace *space;
SubspaceStore *chunk_cache;
Tablespaces *tablespaces;
} Hypertable;
extern Hypertable *hypertable_from_tuple(HeapTuple tuple);
@ -26,5 +28,7 @@ extern Oid hypertable_id_to_relid(int32 hypertable_id);
extern Chunk *hypertable_get_chunk(Hypertable *h, Point *point);
extern Oid hypertable_relid(RangeVar *rv);
extern bool is_hypertable(Oid relid);
extern bool hypertable_has_tablespace(Hypertable *ht, Oid tspc_oid);
extern Tablespace *hypertable_add_tablespace(Hypertable *ht, int32 tspc_id, Oid tspc_oid);
#endif /* TIMESCALEDB_HYPERTABLE_H */

View File

@ -11,6 +11,7 @@
#include "utils.h"
#include "scanner.h"
#include "dimension.h"
#include "tablespace.h"
static void *hypertable_cache_create_entry(Cache *cache, CacheQuery *query);

View File

@ -1594,7 +1594,7 @@ timescaledb_ddl_command_start(
ProcessUtilityContext context,
ParamListInfo params,
#if PG10
QueryEnvironment *queryEnv,
QueryEnvironment * queryEnv,
#endif
DestReceiver *dest,
char *completion_tag)

224
src/tablespace.c Normal file
View File

@ -0,0 +1,224 @@
#include <postgres.h>
#include <fmgr.h>
#include <utils/lsyscache.h>
#include <utils/syscache.h>
#include <utils/spccache.h>
#include <utils/acl.h>
#include <utils/builtins.h>
#include <utils/fmgroids.h>
#include <commands/tablespace.h>
#include <miscadmin.h>
#include "hypertable_cache.h"
#include "errors.h"
#include "catalog.h"
#include "scanner.h"
#include "tablespace.h"
#include "compat.h"
#define TABLESPACE_DEFAULT_CAPACITY 4
static Oid
rel_get_owner(Oid relid)
{
HeapTuple tuple;
Oid ownerid;
tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
if (!HeapTupleIsValid(tuple))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_TABLE),
errmsg("relation with OID %u does not exist", relid)));
ownerid = ((Form_pg_class) GETSTRUCT(tuple))->relowner;
ReleaseSysCache(tuple);
return ownerid;
}
static Tablespaces *
tablespaces_alloc(int capacity)
{
Tablespaces *tspcs;
tspcs = palloc(sizeof(Tablespaces));
tspcs->capacity = capacity;
tspcs->num_tablespaces = 0;
tspcs->tablespaces = palloc(sizeof(Tablespace) * tspcs->capacity);
return tspcs;
}
Tablespace *
tablespaces_add(Tablespaces *tspcs, int32 tspc_id, Oid tspc_oid)
{
Tablespace *tspc;
if (tspcs->num_tablespaces >= tspcs->capacity)
{
tspcs->capacity += TABLESPACE_DEFAULT_CAPACITY;
tspcs->tablespaces = repalloc(tspcs->tablespaces, sizeof(Tablespace) * tspcs->capacity);
}
tspc = &tspcs->tablespaces[tspcs->num_tablespaces++];
tspc->tablespace_id = tspc_id;
tspc->tablespace_oid = tspc_oid;
return tspc;
}
static bool
tablespace_tuple_found(TupleInfo *ti, void *data)
{
Tablespaces *tspcs = data;
FormData_tablespace *form = (FormData_tablespace *) GETSTRUCT(ti->tuple);
tablespaces_add(tspcs,
form->id,
get_tablespace_oid(NameStr(form->tablespace_name), true));
return true;
}
Tablespaces *
tablespace_scan(int32 hypertable_id)
{
Catalog *catalog = catalog_get();
Tablespaces *tspcs = tablespaces_alloc(TABLESPACE_DEFAULT_CAPACITY);
ScanKeyData scankey[1];
ScannerCtx scanctx = {
.table = catalog->tables[TABLESPACE].id,
.index = catalog->tables[TABLESPACE].index_ids[TABLESPACE_HYPERTABLE_ID_TABLESPACE_NAME_IDX],
.scantype = ScannerTypeIndex,
.nkeys = 1,
.scankey = scankey,
.data = tspcs,
.tuple_found = tablespace_tuple_found,
.lockmode = AccessShareLock,
.scandirection = ForwardScanDirection,
};
ScanKeyInit(&scankey[0], Anum_tablespace_hypertable_id_tablespace_name_idx_hypertable_id,
BTEqualStrategyNumber, F_INT4EQ, Int32GetDatum(hypertable_id));
scanner_scan(&scanctx);
return tspcs;
}
static int32
tablespace_insert_relation(Relation rel, int32 hypertable_id, const char *tspcname)
{
TupleDesc desc = RelationGetDescr(rel);
Datum values[Natts_tablespace];
bool nulls[Natts_tablespace] = {false};
int32 id;
memset(values, 0, sizeof(values));
id = catalog_table_next_seq_id(catalog_get(), TABLESPACE);
values[Anum_tablespace_id - 1] = Int32GetDatum(id);
values[Anum_tablespace_hypertable_id - 1] = Int32GetDatum(hypertable_id);
values[Anum_tablespace_tablespace_name - 1] =
DirectFunctionCall1(namein, CStringGetDatum(tspcname));
catalog_insert_values(rel, desc, values, nulls);
return id;
}
static int32
tablespace_insert(int32 hypertable_id, const char *tspcname)
{
Catalog *catalog = catalog_get();
Relation rel;
int32 id;
rel = heap_open(catalog->tables[TABLESPACE].id, RowExclusiveLock);
id = tablespace_insert_relation(rel, hypertable_id, tspcname);
heap_close(rel, RowExclusiveLock);
return id;
}
TS_FUNCTION_INFO_V1(tablespace_attach);
Datum
tablespace_attach(PG_FUNCTION_ARGS)
{
Oid hypertable_oid;
Name tspcname;
Cache *hcache;
Hypertable *ht;
Oid tspc_oid;
int32 tspc_id;
Oid user_oid = GetUserId();
Oid ownerid;
AclResult aclresult;
MemoryContext old;
CatalogSecurityContext sec_ctx;
if (PG_NARGS() != 2)
elog(ERROR, "Invalid number of arguments");
if (PG_ARGISNULL(0))
elog(ERROR, "Invalid tablespace name");
if (PG_ARGISNULL(1))
elog(ERROR, "Invalid hypertable");
tspcname = PG_GETARG_NAME(0);
hypertable_oid = PG_GETARG_OID(1);
tspc_oid = get_tablespace_oid(NameStr(*tspcname), true);
if (!OidIsValid(tspc_oid))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("Tablespace \"%s\" does not exist", NameStr(*tspcname)),
errhint("A tablespace needs to be created"
" before attaching it to a hypertable")));
ownerid = rel_get_owner(hypertable_oid);
if (!has_privs_of_role(user_oid, ownerid))
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("User \"%s\" lacks permissions on table \"%s\"",
GetUserNameFromId(user_oid, true), get_rel_name(hypertable_oid))));
aclresult = pg_tablespace_aclcheck(tspc_oid, ownerid, ACL_CREATE);
if (aclresult != ACLCHECK_OK)
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("Table owner \"%s\" lacks permissions for tablespace \"%s\"",
GetUserNameFromId(ownerid, true), NameStr(*tspcname))));
hcache = hypertable_cache_pin();
ht = hypertable_cache_get_entry(hcache, hypertable_oid);
if (NULL == ht)
ereport(ERROR,
(errcode(ERRCODE_IO_HYPERTABLE_NOT_EXIST),
errmsg("Table \"%s\" is not a hypertable", get_rel_name(hypertable_oid))));
if (hypertable_has_tablespace(ht, tspc_oid))
ereport(ERROR,
(errcode(ERRCODE_IO_TABLESPACE_ALREADY_ATTACHED),
errmsg("Tablespace \"%s\" is already attached to hypertable \"%s\"",
NameStr(*tspcname), get_rel_name(hypertable_oid))));
catalog_become_owner(catalog_get(), &sec_ctx);
tspc_id = tablespace_insert(ht->fd.id, NameStr(*tspcname));
catalog_restore_user(&sec_ctx);
/* Add the tablespace to the hypertable */
old = cache_switch_to_memory_context(hcache);
hypertable_add_tablespace(ht, tspc_id, tspc_oid);
MemoryContextSwitchTo(old);
cache_release(hcache);
PG_RETURN_VOID();
}

22
src/tablespace.h Normal file
View File

@ -0,0 +1,22 @@
#ifndef TIMESCALEDB_TABLESPACE_H
#define TIMESCALEDB_TABLESPACE_H
#include <postgres.h>
typedef struct Tablespace
{
int32 tablespace_id;
Oid tablespace_oid;
} Tablespace;
typedef struct Tablespaces
{
int capacity;
int num_tablespaces;
Tablespace *tablespaces;
} Tablespaces;
extern Tablespace *tablespaces_add(Tablespaces *tablespaces, int32 tspc_id, Oid tspc_oid);
extern Tablespaces *tablespace_scan(int32 hypertable_id);
#endif /* TIMESCALEDB_TABLESPACE_H */

View File

@ -55,8 +55,8 @@ SELECT set_chunk_time_interval('"one_Partition"', 1::bigint);
ERROR: Permission denied for relation public."one_Partition"
select add_dimension('"one_Partition"', 'device_id', 2);
ERROR: Permission denied for relation public."one_Partition"
select attach_tablespace('"one_Partition"', 'tablespace1');
ERROR: Permission denied for relation public."one_Partition"
select attach_tablespace('tablespace1', '"one_Partition"');
ERROR: Tablespace "tablespace1" does not exist
\set ON_ERROR_STOP 1
CREATE TABLE "1dim"(time timestamp, temp float);
SELECT create_hypertable('"1dim"', 'time');
@ -414,7 +414,7 @@ ALTER TABLE PUBLIC."Hypertable_1" ADD COLUMN sensor_3 BIGINT NOT NULL DEFAULT 13
--create column with same name as previously dropped one
ALTER TABLE PUBLIC."Hypertable_1" ADD COLUMN sensor_4 BIGINT NOT NULL DEFAULT 131;
--test proper denials for all security definer functions:
\c single :ROLE_SUPERUSER
\c single :ROLE_SUPERUSER
CREATE TABLE plain_table_su (time timestamp, temp float);
CREATE TABLE hypertable_su (time timestamp, temp float);
SELECT create_hypertable('hypertable_su', 'time');
@ -487,7 +487,7 @@ ERROR: must be owner of relation hypertable_su
ALTER TABLE hypertable_su ADD COLUMN val2 integer;
ERROR: must be owner of relation hypertable_su
\set ON_ERROR_STOP 1
--change owner
--change owner
\c single :ROLE_SUPERUSER
ALTER TABLE hypertable_su OWNER TO :ROLE_DEFAULT_PERM_USER_2;
\c single :ROLE_DEFAULT_PERM_USER_2

View File

@ -254,3 +254,6 @@ NOTICE: hypertable test_schema.test_1dim already exists, skipping
select create_hypertable('test_schema.test_1dim', 'time');
ERROR: hypertable test_schema.test_1dim already exists
\set ON_ERROR_STOP 1
-- Reset GRANTS
\c single :ROLE_SUPERUSER
REVOKE :ROLE_DEFAULT_PERM_USER FROM :ROLE_DEFAULT_PERM_USER_2;

View File

@ -26,17 +26,36 @@ INNER JOIN _timescaledb_catalog.chunk ch ON (ch.table_name = c.relname);
_hyper_1_1_chunk | tablespace1
(1 row)
--check some error conditions
SELECT attach_tablespace('tablespace2', NULL);
ERROR: Invalid hypertable
SELECT attach_tablespace(NULL, 'tspace_2dim');
ERROR: Invalid tablespace name
SELECT attach_tablespace('none_existing_tablespace', 'tspace_2dim');
ERROR: Tablespace "none_existing_tablespace" does not exist
SELECT attach_tablespace('tablespace2', 'none_existing_table');
ERROR: relation "none_existing_table" does not exist at character 41
--attach another tablespace without first creating it --> should generate error
SELECT attach_tablespace('tspace_2dim', 'tablespace2');
ERROR: No tablespace "tablespace2" exists. A tablespace needs to be created before assigning it to a hypertable dimension
SELECT attach_tablespace('tablespace2', 'tspace_2dim');
ERROR: Tablespace "tablespace2" does not exist
--attach the same tablespace twice to same table should also generate error
SELECT attach_tablespace('tspace_2dim', 'tablespace1');
ERROR: Tablespace "tablespace1" already assigned to hypertable "tspace_2dim"
SELECT attach_tablespace('tablespace1', 'tspace_2dim');
ERROR: Tablespace "tablespace1" is already attached to hypertable "tspace_2dim"
\c single :ROLE_SUPERUSER
CREATE TABLESPACE tablespace2 OWNER :ROLE_DEFAULT_PERM_USER LOCATION :TEST_TABLESPACE2_PATH;
CREATE TABLESPACE tablespace2 OWNER :ROLE_DEFAULT_PERM_USER_2 LOCATION :TEST_TABLESPACE2_PATH;
\c single :ROLE_DEFAULT_PERM_USER_2
--attach without permissions on the table should fail
SELECT attach_tablespace('tablespace2', 'tspace_2dim');
ERROR: User "default_perm_user_2" lacks permissions on table "tspace_2dim"
\c single :ROLE_DEFAULT_PERM_USER
--attach after creating --> should work
SELECT attach_tablespace('tspace_2dim', 'tablespace2');
--attach without permissions on the tablespace should also fail
SELECT attach_tablespace('tablespace2', 'tspace_2dim');
ERROR: Table owner "default_perm_user" lacks permissions for tablespace "tablespace2"
\c single :ROLE_SUPERUSER
GRANT :ROLE_DEFAULT_PERM_USER_2 TO :ROLE_DEFAULT_PERM_USER;
\c single :ROLE_DEFAULT_PERM_USER
--should work with permissions on both the table and the tablespace
SELECT attach_tablespace('tablespace2', 'tspace_2dim');
attach_tablespace
-------------------
@ -46,7 +65,7 @@ SELECT * FROM _timescaledb_catalog.tablespace;
id | hypertable_id | tablespace_name
----+---------------+-----------------
1 | 1 | tablespace1
3 | 1 | tablespace2
2 | 1 | tablespace2
(2 rows)
--insert into another chunk
@ -69,7 +88,7 @@ NOTICE: Adding NOT NULL constraint to time column time (NULL time values not al
(1 row)
SELECT attach_tablespace('tspace_1dim', 'tablespace2');
SELECT attach_tablespace('tablespace2', 'tspace_1dim');
attach_tablespace
-------------------
@ -93,3 +112,6 @@ DROP TABLE tspace_1dim CASCADE;
DROP TABLE tspace_2dim CASCADE;
DROP TABLESPACE tablespace1;
DROP TABLESPACE tablespace2;
-- revoke grants
\c single :ROLE_SUPERUSER
REVOKE :ROLE_DEFAULT_PERM_USER_2 FROM :ROLE_DEFAULT_PERM_USER;

View File

@ -13,7 +13,7 @@ CREATE SCHEMA IF NOT EXISTS "customSchema" AUTHORIZATION :ROLE_DEFAULT_PERM_USER
SELECT * FROM "one_Partition";
SELECT set_chunk_time_interval('"one_Partition"', 1::bigint);
select add_dimension('"one_Partition"', 'device_id', 2);
select attach_tablespace('"one_Partition"', 'tablespace1');
select attach_tablespace('tablespace1', '"one_Partition"');
\set ON_ERROR_STOP 1
CREATE TABLE "1dim"(time timestamp, temp float);
@ -28,7 +28,7 @@ SELECT * FROM "1dim";
\ir include/ddl_ops_2.sql
--test proper denials for all security definer functions:
\c single :ROLE_SUPERUSER
\c single :ROLE_SUPERUSER
CREATE TABLE plain_table_su (time timestamp, temp float);
CREATE TABLE hypertable_su (time timestamp, temp float);
SELECT create_hypertable('hypertable_su', 'time');
@ -77,7 +77,7 @@ CREATE INDEX ON hypertable_su (time, temp);
ALTER TABLE hypertable_su ADD COLUMN val2 integer;
\set ON_ERROR_STOP 1
--change owner
--change owner
\c single :ROLE_SUPERUSER
ALTER TABLE hypertable_su OWNER TO :ROLE_DEFAULT_PERM_USER_2;

View File

@ -121,3 +121,7 @@ select create_hypertable('test_schema.test_1dim', 'time', if_not_exists => true)
\set ON_ERROR_STOP 0
select create_hypertable('test_schema.test_1dim', 'time');
\set ON_ERROR_STOP 1
-- Reset GRANTS
\c single :ROLE_SUPERUSER
REVOKE :ROLE_DEFAULT_PERM_USER FROM :ROLE_DEFAULT_PERM_USER_2;

View File

@ -21,17 +21,35 @@ SELECT relname, spcname FROM pg_class c
INNER JOIN pg_tablespace t ON (c.reltablespace = t.oid)
INNER JOIN _timescaledb_catalog.chunk ch ON (ch.table_name = c.relname);
--check some error conditions
SELECT attach_tablespace('tablespace2', NULL);
SELECT attach_tablespace(NULL, 'tspace_2dim');
SELECT attach_tablespace('none_existing_tablespace', 'tspace_2dim');
SELECT attach_tablespace('tablespace2', 'none_existing_table');
--attach another tablespace without first creating it --> should generate error
SELECT attach_tablespace('tspace_2dim', 'tablespace2');
SELECT attach_tablespace('tablespace2', 'tspace_2dim');
--attach the same tablespace twice to same table should also generate error
SELECT attach_tablespace('tspace_2dim', 'tablespace1');
SELECT attach_tablespace('tablespace1', 'tspace_2dim');
\c single :ROLE_SUPERUSER
CREATE TABLESPACE tablespace2 OWNER :ROLE_DEFAULT_PERM_USER LOCATION :TEST_TABLESPACE2_PATH;
CREATE TABLESPACE tablespace2 OWNER :ROLE_DEFAULT_PERM_USER_2 LOCATION :TEST_TABLESPACE2_PATH;
\c single :ROLE_DEFAULT_PERM_USER_2
--attach without permissions on the table should fail
SELECT attach_tablespace('tablespace2', 'tspace_2dim');
\c single :ROLE_DEFAULT_PERM_USER
--attach after creating --> should work
SELECT attach_tablespace('tspace_2dim', 'tablespace2');
--attach without permissions on the tablespace should also fail
SELECT attach_tablespace('tablespace2', 'tspace_2dim');
\c single :ROLE_SUPERUSER
GRANT :ROLE_DEFAULT_PERM_USER_2 TO :ROLE_DEFAULT_PERM_USER;
\c single :ROLE_DEFAULT_PERM_USER
--should work with permissions on both the table and the tablespace
SELECT attach_tablespace('tablespace2', 'tspace_2dim');
SELECT * FROM _timescaledb_catalog.tablespace;
@ -45,7 +63,7 @@ INNER JOIN _timescaledb_catalog.chunk ch ON (ch.table_name = c.relname);
--
CREATE TABLE tspace_1dim(time timestamp, temp float, device text) TABLESPACE tablespace1;
SELECT create_hypertable('tspace_1dim', 'time');
SELECT attach_tablespace('tspace_1dim', 'tablespace2');
SELECT attach_tablespace('tablespace2', 'tspace_1dim');
INSERT INTO tspace_1dim VALUES ('2017-01-20T09:00:01', 24.3, 'blue');
INSERT INTO tspace_1dim VALUES ('2017-03-20T09:00:01', 24.3, 'brown');
@ -61,3 +79,6 @@ DROP TABLE tspace_2dim CASCADE;
DROP TABLESPACE tablespace1;
DROP TABLESPACE tablespace2;
-- revoke grants
\c single :ROLE_SUPERUSER
REVOKE :ROLE_DEFAULT_PERM_USER_2 FROM :ROLE_DEFAULT_PERM_USER;