Skip to content

Commit

Permalink
Add function to detach tablespaces from hypertables
Browse files Browse the repository at this point in the history
Tablespaces can now be detached from hypertables using
`tablespace_detach()`. This function can either detach
a tablespace from all tables or only a specific table.

Having the ability to detach tablespace allows more
advanced storage management, for instance, one can detach
tablespaces that are running low on diskspace while attaching
new ones to replace the old ones.
  • Loading branch information
erimatnor committed Dec 9, 2017
1 parent e593876 commit 6e92383
Show file tree
Hide file tree
Showing 15 changed files with 493 additions and 46 deletions.
14 changes: 14 additions & 0 deletions sql/ddl_api.sql
Original file line number Diff line number Diff line change
Expand Up @@ -303,3 +303,17 @@ CREATE OR REPLACE FUNCTION attach_tablespace(tablespace NAME, hypertable REGCLAS
$BODY$
SELECT * FROM _timescaledb_internal.attach_tablespace(tablespace, hypertable);
$BODY$;

-- Detach the given tablespace from a hypertable
CREATE OR REPLACE FUNCTION detach_tablespace(tablespace NAME, hypertable REGCLASS = NULL)
RETURNS INTEGER LANGUAGE SQL AS
$BODY$
SELECT * FROM _timescaledb_internal.detach_tablespace(tablespace, hypertable);
$BODY$;

-- Detach all tablespaces from the a hypertable
CREATE OR REPLACE FUNCTION detach_tablespaces(hypertable REGCLASS)
RETURNS INTEGER LANGUAGE SQL AS
$BODY$
SELECT * FROM _timescaledb_internal.detach_tablespaces(hypertable);
$BODY$;
8 changes: 7 additions & 1 deletion sql/ddl_internal.sql
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ BEGIN
-- Create the schema for the hypertable data if needed
PERFORM _timescaledb_internal.create_hypertable_schema(associated_schema_name);

id := nextval(pg_get_serial_sequence('_timescaledb_catalog.hypertable','id'));
id := nextval(pg_get_serial_sequence('_timescaledb_catalog.hypertable','id'));

IF associated_table_prefix IS NULL THEN
associated_table_prefix = format('_hyper_%s', id);
Expand Down Expand Up @@ -621,6 +621,12 @@ $BODY$;
CREATE OR REPLACE FUNCTION _timescaledb_internal.attach_tablespace(tablespace NAME, hypertable REGCLASS) RETURNS VOID
AS '$libdir/timescaledb', 'tablespace_attach' LANGUAGE C VOLATILE;

CREATE OR REPLACE FUNCTION _timescaledb_internal.detach_tablespace(tablespace NAME, hypertable REGCLASS) RETURNS INTEGER
AS '$libdir/timescaledb', 'tablespace_detach' LANGUAGE C VOLATILE;

CREATE OR REPLACE FUNCTION _timescaledb_internal.detach_tablespaces(hypertable REGCLASS) RETURNS INTEGER
AS '$libdir/timescaledb', 'tablespace_detach_all_from_hypertable' 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
AS '$libdir/timescaledb', 'chunk_index_clone' LANGUAGE C VOLATILE STRICT;
Expand Down
3 changes: 0 additions & 3 deletions sql/updates/pre-0.6.1--0.7.0.sql
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,3 @@ 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);
6 changes: 6 additions & 0 deletions src/catalog.c
Original file line number Diff line number Diff line change
Expand Up @@ -467,6 +467,11 @@ catalog_delete(Relation rel, HeapTuple tuple)
catalog_delete_tid(rel, &tuple->t_self);
}

void
catalog_delete_only(Relation rel, HeapTuple tuple)
{
CatalogTupleDelete(rel, &tuple->t_self);
}

/*
* Invalidate TimescaleDB catalog caches.
Expand Down Expand Up @@ -510,6 +515,7 @@ catalog_invalidate_cache(Oid catalog_relid, CmdType operation)
break;
case HYPERTABLE:
case DIMENSION:
case TABLESPACE:
relid = catalog_get_cache_proxy_id(catalog, CACHE_TYPE_HYPERTABLE);
CacheInvalidateRelcacheByRelid(relid);
break;
Expand Down
3 changes: 3 additions & 0 deletions src/catalog.h
Original file line number Diff line number Diff line change
Expand Up @@ -519,4 +519,7 @@ void catalog_delete_tid(Relation rel, ItemPointer tid);
void catalog_delete(Relation rel, HeapTuple tuple);
void catalog_invalidate_cache(Oid catalog_relid, CmdType operation);

/* Delete only: do not increment command counter or invalidate caches */
void catalog_delete_only(Relation rel, HeapTuple tuple);

#endif /* TIMESCALEDB_CATALOG_H */
1 change: 1 addition & 0 deletions src/errors.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#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')
#define ERRCODE_IO_TABLESPACE_NOT_ATTACHED MAKE_SQLSTATE('I','O','1','5','0')

/*
--IO500 - GROUP: internal error
Expand Down
71 changes: 70 additions & 1 deletion src/hypertable.c
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
#include <postgres.h>
#include <access/htup_details.h>
#include <utils/lsyscache.h>
#include <utils/syscache.h>
#include <utils/memutils.h>
#include <utils/builtins.h>
#include <nodes/memnodes.h>
#include <catalog/namespace.h>
#include <commands/tablespace.h>
#include <miscadmin.h>

#include "hypertable.h"
#include "dimension.h"
Expand All @@ -16,6 +19,48 @@
#include "scanner.h"
#include "catalog.h"

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;
}

bool
hypertable_has_privs_of(Oid hypertable_oid, Oid userid)
{
return has_privs_of_role(userid, rel_get_owner(hypertable_oid));
}

Oid
hypertable_permissions_check(Oid hypertable_oid, Oid userid)
{
Oid ownerid = rel_get_owner(hypertable_oid);

if (!has_privs_of_role(userid, ownerid))
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("User \"%s\" lacks permissions on table \"%s\"",
GetUserNameFromId(userid, true),
get_rel_name(hypertable_oid))));

return ownerid;
}


Hypertable *
hypertable_from_tuple(HeapTuple tuple)
{
Expand Down Expand Up @@ -230,7 +275,31 @@ hypertable_has_tablespace(Hypertable *ht, Oid tspc_oid)
Tablespace *
hypertable_add_tablespace(Hypertable *ht, int32 tspc_id, Oid tspc_oid)
{
return tablespaces_add(ht->tablespaces, tspc_id, tspc_oid);
FormData_tablespace form = {
.id = tspc_id,
.hypertable_id = ht->fd.id,
};

namestrcpy(&form.tablespace_name, get_tablespace_name(tspc_oid));
return tablespaces_add(ht->tablespaces, &form, tspc_oid);
}

bool
hypertable_delete_tablespace(Hypertable *ht, Oid tspc_oid)
{
if (NULL == ht->tablespaces)
return false;

return tablespaces_delete(ht->tablespaces, tspc_oid);
}

int
hypertable_delete_all_tablespaces(Hypertable *ht)
{
if (NULL == ht->tablespaces)
return 0;

return tablespaces_clear(ht->tablespaces);
}

static inline Oid
Expand Down
4 changes: 4 additions & 0 deletions src/hypertable.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ typedef struct Hypertable
Tablespaces *tablespaces;
} Hypertable;

extern bool hypertable_has_privs_of(Oid hypertable_oid, Oid userid);
extern Oid hypertable_permissions_check(Oid hypertable_oid, Oid userid);
extern Hypertable *hypertable_from_tuple(HeapTuple tuple);
extern int hypertable_set_name(Hypertable *ht, const char *newname);
extern int hypertable_set_schema(Hypertable *ht, const char *newname);
Expand All @@ -30,5 +32,7 @@ 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);
extern bool hypertable_delete_tablespace(Hypertable *ht, Oid tspc_id);
extern int hypertable_delete_all_tablespaces(Hypertable *ht);

#endif /* TIMESCALEDB_HYPERTABLE_H */
2 changes: 1 addition & 1 deletion src/process_utility.c
Original file line number Diff line number Diff line change
Expand Up @@ -1594,7 +1594,7 @@ timescaledb_ddl_command_start(
ProcessUtilityContext context,
ParamListInfo params,
#if PG10
QueryEnvironment * queryEnv,
QueryEnvironment *queryEnv,
#endif
DestReceiver *dest,
char *completion_tag)
Expand Down
Loading

0 comments on commit 6e92383

Please sign in to comment.