diff --git a/doc/src/sgml/ref/create_warehouse.sgml b/doc/src/sgml/ref/create_warehouse.sgml
new file mode 100644
index 00000000000..65ba0cf272f
--- /dev/null
+++ b/doc/src/sgml/ref/create_warehouse.sgml
@@ -0,0 +1,53 @@
+
+
+
+
+ CREATE WAREHOUSE
+
+
+
+ CREATE WAREHOUSE
+ 7
+ SQL - Language Statements
+
+
+
+ CREATE WAREHOUSE
+ define a new warehouse for query processing
+
+
+
+
+CREATE WAREHOUSE name
+[ WAREHOUSE_SIZE size ]
+
+
+
+
+ Description
+
+
+ CREATE WAREHOUSE Creates a new virtual warehouse in the system.
+ Initial creation of a virtual warehouse might take some time to provision the compute resources.
+
+
+
+
+
+ Parameters
+
+
+ WAREHOUSE_SIZE
+
+
+ The size of the warehouse.
+
+
+
+
+
+
+
diff --git a/gpcontrib/gp_inject_fault/gp_inject_fault.c b/gpcontrib/gp_inject_fault/gp_inject_fault.c
index 22c31cf72a0..009873941d7 100644
--- a/gpcontrib/gp_inject_fault/gp_inject_fault.c
+++ b/gpcontrib/gp_inject_fault/gp_inject_fault.c
@@ -119,35 +119,46 @@ get_segment_configuration(int dbid, char **hostname, int *port, int *content)
SysScanDesc scan;
Datum attr;
bool isNull;
+ Oid warehouseid = InvalidOid;
+ bool find_config = false;
configrel = table_open(GpSegmentConfigRelationId, AccessShareLock);
ScanKeyInit(&scankey[0],
Anum_gp_segment_configuration_dbid,
BTEqualStrategyNumber, F_INT2EQ,
Int16GetDatum(dbid));
- scan = systable_beginscan(configrel, GpSegmentConfigDbidIndexId, true,
+ scan = systable_beginscan(configrel, GpSegmentConfigDbidWarehouseIndexId, true,
NULL, 1, scankey);
- tuple = systable_getnext(scan);
-
- if (HeapTupleIsValid(tuple))
+ while (HeapTupleIsValid(tuple = systable_getnext(scan)))
{
- attr = heap_getattr(tuple, Anum_gp_segment_configuration_hostname,
+ attr = heap_getattr(tuple, Anum_gp_segment_configuration_warehouseid,
RelationGetDescr(configrel), &isNull);
Assert(!isNull);
- *hostname = TextDatumGetCString(attr);
+ warehouseid = DatumGetObjectId(attr);
- attr = heap_getattr(tuple, Anum_gp_segment_configuration_port,
- RelationGetDescr(configrel), &isNull);
- Assert(!isNull);
- *port = DatumGetInt32(attr);
+ if (!OidIsValid(warehouseid) || warehouseid == GetCurrentWarehouseId())
+ {
+ attr = heap_getattr(tuple, Anum_gp_segment_configuration_hostname,
+ RelationGetDescr(configrel), &isNull);
+ Assert(!isNull);
+ *hostname = TextDatumGetCString(attr);
- attr = heap_getattr(tuple, Anum_gp_segment_configuration_content,
- RelationGetDescr(configrel), &isNull);
- Assert(!isNull);
- *content = DatumGetInt32(attr);
+ attr = heap_getattr(tuple, Anum_gp_segment_configuration_port,
+ RelationGetDescr(configrel), &isNull);
+ Assert(!isNull);
+ *port = DatumGetInt32(attr);
+
+ attr = heap_getattr(tuple, Anum_gp_segment_configuration_content,
+ RelationGetDescr(configrel), &isNull);
+ Assert(!isNull);
+ *content = DatumGetInt32(attr);
+
+ find_config = true;
+ break;
+ }
}
- else
+ if (!find_config)
elog(ERROR, "dbid %d not found", dbid);
systable_endscan(scan);
diff --git a/src/backend/catalog/Makefile b/src/backend/catalog/Makefile
index 0fe440e8d98..6b800053526 100644
--- a/src/backend/catalog/Makefile
+++ b/src/backend/catalog/Makefile
@@ -78,6 +78,7 @@ CATALOG_HEADERS := \
pg_resqueue.h pg_resqueuecapability.h pg_resourcetype.h \
pg_resgroup.h pg_resgroupcapability.h \
gp_configuration_history.h gp_id.h gp_distribution_policy.h gp_version_at_initdb.h \
+ gp_warehouse.h \
pg_appendonly.h \
gp_fastsequence.h pg_extprotocol.h \
pg_attribute_encoding.h \
diff --git a/src/backend/catalog/catalog.c b/src/backend/catalog/catalog.c
index 52112416628..814188d1ade 100644
--- a/src/backend/catalog/catalog.c
+++ b/src/backend/catalog/catalog.c
@@ -59,6 +59,7 @@
#include "catalog/gp_configuration_history.h"
#include "catalog/gp_id.h"
#include "catalog/gp_version_at_initdb.h"
+#include "catalog/gp_warehouse.h"
#include "catalog/pg_event_trigger.h"
#include "catalog/pg_largeobject_metadata.h"
#include "catalog/pg_resourcetype.h"
@@ -459,8 +460,8 @@ IsSharedRelation(Oid relationId)
relationId == AuthIdRolResQueueIndexId ||
relationId == AuthIdRolResGroupIndexId ||
#ifdef USE_INTERNAL_FTS
- relationId == GpSegmentConfigContentPreferred_roleIndexId ||
- relationId == GpSegmentConfigDbidIndexId ||
+ relationId == GpSegmentConfigContentPreferred_roleWarehouseIndexId ||
+ relationId == GpSegmentConfigDbidWarehouseIndexId ||
#endif
relationId == AuthTimeConstraintAuthIdIndexId)
{
@@ -505,6 +506,14 @@ IsSharedRelation(Oid relationId)
return true;
}
+ /* warehouse table and its indexes */
+ if (relationId == GpWarehouseRelationId ||
+ relationId == GpWarehouseOidIndexId ||
+ relationId == GpWarehouseNameIndexId)
+ {
+ return true;
+ }
+
return false;
}
diff --git a/src/backend/cdb/cdbutil.c b/src/backend/cdb/cdbutil.c
index 09d77d2cde4..0d6f7147d30 100644
--- a/src/backend/cdb/cdbutil.c
+++ b/src/backend/cdb/cdbutil.c
@@ -241,6 +241,7 @@ readGpSegConfigFromCatalog(int *total_dbs)
int array_size;
bool isNull;
Datum attr;
+ Oid warehouseid = InvalidOid;
Relation gp_seg_config_rel;
HeapTuple gp_seg_config_tuple = NULL;
SysScanDesc gp_seg_config_scan;
@@ -256,6 +257,13 @@ readGpSegConfigFromCatalog(int *total_dbs)
while (HeapTupleIsValid(gp_seg_config_tuple = systable_getnext(gp_seg_config_scan)))
{
+ /* warehouseid */
+ attr = heap_getattr(gp_seg_config_tuple, Anum_gp_segment_configuration_warehouseid, RelationGetDescr(gp_seg_config_rel), &isNull);
+ Assert(!isNull);
+ warehouseid = DatumGetObjectId(attr);
+ if (OidIsValid(warehouseid) && warehouseid != GetCurrentWarehouseId())
+ continue;
+
config = &configs[idx];
/* dbid */
@@ -1511,93 +1519,101 @@ dbid_get_dbinfo(int16 dbid)
Anum_gp_segment_configuration_dbid,
BTEqualStrategyNumber, F_INT2EQ,
Int16GetDatum(dbid));
- scan = systable_beginscan(rel, GpSegmentConfigDbidIndexId, true,
+ scan = systable_beginscan(rel, GpSegmentConfigDbidWarehouseIndexId, true,
NULL, 1, &scankey);
- tuple = systable_getnext(scan);
- if (HeapTupleIsValid(tuple))
+ while (HeapTupleIsValid(tuple = systable_getnext(scan)))
{
Datum attr;
bool isNull;
+ Oid warehouseid = InvalidOid;
- i = palloc(sizeof(GpSegConfigEntry));
-
- /*
- * dbid
- */
- attr = heap_getattr(tuple, Anum_gp_segment_configuration_dbid,
+ attr = heap_getattr(tuple, Anum_gp_segment_configuration_warehouseid,
RelationGetDescr(rel), &isNull);
Assert(!isNull);
- i->dbid = DatumGetInt16(attr);
+ warehouseid = DatumGetObjectId(attr);
- /*
- * content
- */
- attr = heap_getattr(tuple, Anum_gp_segment_configuration_content,
- RelationGetDescr(rel), &isNull);
- Assert(!isNull);
- i->segindex = DatumGetInt16(attr);
+ if (!OidIsValid(warehouseid) || warehouseid == GetCurrentWarehouseId())
+ {
+ i = palloc(sizeof(GpSegConfigEntry));
- /*
- * role
- */
- attr = heap_getattr(tuple, Anum_gp_segment_configuration_role,
- RelationGetDescr(rel), &isNull);
- Assert(!isNull);
- i->role = DatumGetChar(attr);
+ /*
+ * dbid
+ */
+ attr = heap_getattr(tuple, Anum_gp_segment_configuration_dbid,
+ RelationGetDescr(rel), &isNull);
+ Assert(!isNull);
+ i->dbid = DatumGetInt16(attr);
- /*
- * preferred-role
- */
- attr = heap_getattr(tuple,
- Anum_gp_segment_configuration_preferred_role,
- RelationGetDescr(rel), &isNull);
- Assert(!isNull);
- i->preferred_role = DatumGetChar(attr);
+ /*
+ * content
+ */
+ attr = heap_getattr(tuple, Anum_gp_segment_configuration_content,
+ RelationGetDescr(rel), &isNull);
+ Assert(!isNull);
+ i->segindex = DatumGetInt16(attr);
- /*
- * mode
- */
- attr = heap_getattr(tuple, Anum_gp_segment_configuration_mode,
- RelationGetDescr(rel), &isNull);
- Assert(!isNull);
- i->mode = DatumGetChar(attr);
+ /*
+ * role
+ */
+ attr = heap_getattr(tuple, Anum_gp_segment_configuration_role,
+ RelationGetDescr(rel), &isNull);
+ Assert(!isNull);
+ i->role = DatumGetChar(attr);
- /*
- * status
- */
- attr = heap_getattr(tuple, Anum_gp_segment_configuration_status,
- RelationGetDescr(rel), &isNull);
- Assert(!isNull);
- i->status = DatumGetChar(attr);
+ /*
+ * preferred-role
+ */
+ attr = heap_getattr(tuple,
+ Anum_gp_segment_configuration_preferred_role,
+ RelationGetDescr(rel), &isNull);
+ Assert(!isNull);
+ i->preferred_role = DatumGetChar(attr);
- /*
- * hostname
- */
- attr = heap_getattr(tuple, Anum_gp_segment_configuration_hostname,
- RelationGetDescr(rel), &isNull);
- Assert(!isNull);
- i->hostname = TextDatumGetCString(attr);
+ /*
+ * mode
+ */
+ attr = heap_getattr(tuple, Anum_gp_segment_configuration_mode,
+ RelationGetDescr(rel), &isNull);
+ Assert(!isNull);
+ i->mode = DatumGetChar(attr);
- /*
- * address
- */
- attr = heap_getattr(tuple, Anum_gp_segment_configuration_address,
- RelationGetDescr(rel), &isNull);
- Assert(!isNull);
- i->address = TextDatumGetCString(attr);
+ /*
+ * status
+ */
+ attr = heap_getattr(tuple, Anum_gp_segment_configuration_status,
+ RelationGetDescr(rel), &isNull);
+ Assert(!isNull);
+ i->status = DatumGetChar(attr);
- /*
- * port
- */
- attr = heap_getattr(tuple, Anum_gp_segment_configuration_port,
- RelationGetDescr(rel), &isNull);
- Assert(!isNull);
- i->port = DatumGetInt32(attr);
+ /*
+ * hostname
+ */
+ attr = heap_getattr(tuple, Anum_gp_segment_configuration_hostname,
+ RelationGetDescr(rel), &isNull);
+ Assert(!isNull);
+ i->hostname = TextDatumGetCString(attr);
- Assert(systable_getnext(scan) == NULL); /* should be only 1 */
+ /*
+ * address
+ */
+ attr = heap_getattr(tuple, Anum_gp_segment_configuration_address,
+ RelationGetDescr(rel), &isNull);
+ Assert(!isNull);
+ i->address = TextDatumGetCString(attr);
+
+ /*
+ * port
+ */
+ attr = heap_getattr(tuple, Anum_gp_segment_configuration_port,
+ RelationGetDescr(rel), &isNull);
+ Assert(!isNull);
+ i->port = DatumGetInt32(attr);
+
+ break;
+ }
}
- else
+ if (i == NULL)
{
elog(ERROR, "could not find configuration entry for dbid %i", dbid);
}
@@ -1619,7 +1635,8 @@ contentid_get_dbid(int16 contentid, char role, bool getPreferredRoleNotCurrentRo
{
int16 dbid = 0;
Relation rel;
- ScanKeyData scankey[2];
+ ScanKeyData scankey[3];
+ int nkeys = 2;
SysScanDesc scan;
HeapTuple tup;
@@ -1648,8 +1665,17 @@ contentid_get_dbid(int16 contentid, char role, bool getPreferredRoleNotCurrentRo
Anum_gp_segment_configuration_preferred_role,
BTEqualStrategyNumber, F_CHAREQ,
CharGetDatum(role));
- scan = systable_beginscan(rel, GpSegmentConfigContentPreferred_roleIndexId, true,
- NULL, 2, scankey);
+ if (contentid != MASTER_CONTENT_ID)
+ {
+ nkeys++;
+ ScanKeyInit(&scankey[2],
+ Anum_gp_segment_configuration_warehouseid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(GetCurrentWarehouseId()));
+ }
+
+ scan = systable_beginscan(rel, GpSegmentConfigContentPreferred_roleWarehouseIndexId, true,
+ NULL, nkeys, scankey);
}
else
{
@@ -1665,9 +1691,17 @@ contentid_get_dbid(int16 contentid, char role, bool getPreferredRoleNotCurrentRo
Anum_gp_segment_configuration_role,
BTEqualStrategyNumber, F_CHAREQ,
CharGetDatum(role));
+ if (contentid != MASTER_CONTENT_ID)
+ {
+ nkeys++;
+ ScanKeyInit(&scankey[2],
+ Anum_gp_segment_configuration_warehouseid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(GetCurrentWarehouseId()));
+ }
/* no index */
scan = systable_beginscan(rel, InvalidOid, false,
- NULL, 2, scankey);
+ NULL, nkeys, scankey);
}
tup = systable_getnext(scan);
diff --git a/src/backend/fts/fts.c b/src/backend/fts/fts.c
index cdec9dcf7aa..3da780092d4 100644
--- a/src/backend/fts/fts.c
+++ b/src/backend/fts/fts.c
@@ -228,18 +228,22 @@ probeWalRepUpdateConfig(int16 dbid, int16 segindex, char role,
bool confignulls[Natts_gp_segment_configuration] = { false };
bool repls[Natts_gp_segment_configuration] = { false };
- ScanKeyData scankey;
+ ScanKeyData scankey[2];
SysScanDesc sscan;
configrel = table_open(GpSegmentConfigRelationId,
RowExclusiveLock);
- ScanKeyInit(&scankey,
+ ScanKeyInit(&scankey[0],
Anum_gp_segment_configuration_dbid,
BTEqualStrategyNumber, F_INT2EQ,
Int16GetDatum(dbid));
- sscan = systable_beginscan(configrel, GpSegmentConfigDbidIndexId,
- true, NULL, 1, &scankey);
+ ScanKeyInit(&scankey[1],
+ Anum_gp_segment_configuration_warehouseid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(GetCurrentWarehouseId()));
+ sscan = systable_beginscan(configrel, GpSegmentConfigDbidWarehouseIndexId,
+ true, NULL, 2, scankey);
configtuple = systable_getnext(sscan);
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 4f286ad13a4..45e22f74bab 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -294,8 +294,8 @@ static void check_expressions_in_partition_key(PartitionSpec *spec, core_yyscan_
CreateFdwStmt CreateForeignServerStmt CreateForeignTableStmt
CreateAssertionStmt CreateTransformStmt CreateTrigStmt CreateEventTrigStmt
CreateUserStmt CreateUserMappingStmt CreateRoleStmt CreatePolicyStmt
- CreatedbStmt DeclareCursorStmt DefineStmt DeleteStmt DiscardStmt DoStmt
- DropOpClassStmt DropOpFamilyStmt DropStmt
+ CreatedbStmt CreateWarehouseStmt DeclareCursorStmt DefineStmt DeleteStmt DiscardStmt DoStmt
+ DropOpClassStmt DropOpFamilyStmt DropStmt DropWarehouseStmt
DropCastStmt DropRoleStmt
DropdbStmt DropTableSpaceStmt
DropTransformStmt
@@ -705,6 +705,8 @@ static void check_expressions_in_partition_key(PartitionSpec *spec, core_yyscan_
%type hash_partbound
%type hash_partbound_elem
+%type OptWarehouseOptList WarehouseOptList
+%type WarehouseOptElem
/*
* Non-keyword token types. These are hard-wired into the "flex" lexer.
@@ -872,6 +874,10 @@ static void check_expressions_in_partition_key(PartitionSpec *spec, core_yyscan_
VALIDATION
+ WAREHOUSE
+
+ WAREHOUSE_SIZE
+
WEB WRITABLE
/*
@@ -1420,6 +1426,7 @@ stmt:
| CreateOpClassStmt
| CreateOpFamilyStmt
| CreatePublicationStmt
+ | CreateWarehouseStmt
| AlterOpFamilyStmt
| CreatePolicyStmt
| CreatePLangStmt
@@ -1459,6 +1466,7 @@ stmt:
| DropRoleStmt
| DropUserMappingStmt
| DropdbStmt
+ | DropWarehouseStmt
| ExecuteStmt
| ExplainStmt
| FetchStmt
@@ -12333,6 +12341,48 @@ publication_for_tables:
;
+/*****************************************************************************
+ *
+ * QUERY:
+ * CREATE WAREHOUSE name
+ * [WAREHOUSE_SIZE ]
+ *
+ *****************************************************************************/
+
+CreateWarehouseStmt: CREATE WAREHOUSE name OptWarehouseOptList
+ {
+ CreateWarehouseStmt *n = makeNode(CreateWarehouseStmt);
+ n->whname = $3;
+ n->options = $4;
+ $$ = (Node *) n;
+ }
+ ;
+
+OptWarehouseOptList: WarehouseOptList { $$ = $1; }
+ | /*EMPTY*/ { $$ = NIL; }
+ ;
+
+WarehouseOptList: WarehouseOptElem { $$ = list_make1($1); }
+ | WarehouseOptList WarehouseOptElem { $$ = lappend($1, $2); }
+ ;
+
+WarehouseOptElem:
+ WAREHOUSE_SIZE SignedIconst
+ {
+ $$ = makeDefElem("warehouse_size", (Node *)makeInteger($2), @1);
+ }
+ ;
+
+
+DropWarehouseStmt: DROP WAREHOUSE name
+ {
+ DropWarehouseStmt *n = makeNode(DropWarehouseStmt);
+ n->whname = $3;
+ $$ = (Node *) n;
+ }
+ ;
+
+
/*****************************************************************************
*
* ALTER PUBLICATION name SET ( options )
@@ -18795,6 +18845,8 @@ unreserved_keyword:
| VIEW
| VIEWS
| VOLATILE
+ | WAREHOUSE
+ | WAREHOUSE_SIZE
| WEB /* gp */
| WHITESPACE_P
| WITHIN
@@ -19783,6 +19835,8 @@ bare_label_keyword:
| VIEW
| VIEWS
| VOLATILE
+ | WAREHOUSE
+ | WAREHOUSE_SIZE
| WEB
| WHEN
| WHITESPACE_P
diff --git a/src/backend/storage/lmgr/lmgr.c b/src/backend/storage/lmgr/lmgr.c
index e4bc2f0c977..34c17a00db0 100644
--- a/src/backend/storage/lmgr/lmgr.c
+++ b/src/backend/storage/lmgr/lmgr.c
@@ -803,6 +803,26 @@ GxactLockTableWait(DistributedTransactionId gxid)
LockRelease(&tag, ShareLock, false);
}
+void
+LockWarehouse(Oid warehouseOid, LOCKMODE lockmode)
+{
+ LOCKTAG tag;
+
+ SET_LOCKTAG_WAREHOUSE(tag, warehouseOid);
+
+ (void) LockAcquire(&tag, lockmode, true, false);
+}
+
+void
+UnlockWarehouse(Oid warehouseOid, LOCKMODE lockmode)
+{
+ LOCKTAG tag;
+
+ SET_LOCKTAG_WAREHOUSE(tag, warehouseOid);
+
+ LockRelease(&tag, lockmode, true);
+}
+
/*
* ConditionalXactLockTableWait
*
@@ -1284,6 +1304,11 @@ DescribeLockTag(StringInfo buf, const LOCKTAG *tag)
_("resource queue %u"),
tag->locktag_field1);
break;
+ case LOCKTAG_WAREHOUSE:
+ appendStringInfo(buf,
+ _("warehouse %u"),
+ tag->locktag_field1);
+ break;
default:
appendStringInfo(buf,
_("unrecognized locktag type %d"),
@@ -1330,6 +1355,7 @@ LockTagIsTemp(const LOCKTAG *tag)
break;
case LOCKTAG_USERLOCK:
case LOCKTAG_ADVISORY:
+ case LOCKTAG_WAREHOUSE:
/* assume these aren't temp */
break;
}
diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c
index 966b355e98e..b558ae1db4d 100644
--- a/src/backend/tcop/utility.c
+++ b/src/backend/tcop/utility.c
@@ -241,8 +241,10 @@ ClassifyUtilityCommandAsReadOnly(Node *parsetree)
case T_DropTaskStmt:
case T_DropQueueStmt:
case T_DropResourceGroupStmt:
+ case T_DropWarehouseStmt:
case T_CreateExternalStmt:
case T_RetrieveStmt:
+ case T_CreateWarehouseStmt:
{
/* DDL is not read-only, and neither is TRUNCATE. */
return COMMAND_IS_NOT_READ_ONLY;
@@ -3729,6 +3731,13 @@ CreateCommandTag(Node *parsetree)
tag = CMDTAG_RETRIEVE;
break;
+ case T_CreateWarehouseStmt:
+ tag = CMDTAG_CREATE_WAREHOUSE;
+ break;
+ case T_DropWarehouseStmt:
+ tag = CMDTAG_DROP_WAREHOUSE;
+ break;
+
default:
elog(WARNING, "unrecognized node type: %d",
(int) nodeTag(parsetree));
@@ -4206,6 +4215,14 @@ GetCommandLogLevel(Node *parsetree)
case T_AlterCollationStmt:
lev = LOGSTMT_DDL;
break;
+
+ case T_CreateWarehouseStmt:
+ lev = LOGSTMT_DDL;
+ break;
+
+ case T_DropWarehouseStmt:
+ lev = LOGSTMT_DDL;
+ break;
/* already-planned queries */
case T_PlannedStmt:
diff --git a/src/backend/utils/adt/lockfuncs.c b/src/backend/utils/adt/lockfuncs.c
index 7afbbd33817..bc0da11a729 100644
--- a/src/backend/utils/adt/lockfuncs.c
+++ b/src/backend/utils/adt/lockfuncs.c
@@ -44,10 +44,11 @@ const char *const LockTagTypeNames[] = {
"resource queue",
"distributed xid",
"userlock",
- "advisory"
+ "advisory",
+ "warehouse"
};
-StaticAssertDecl(lengthof(LockTagTypeNames) == (LOCKTAG_ADVISORY + 1),
+StaticAssertDecl(lengthof(LockTagTypeNames) == (LOCKTAG_WAREHOUSE + 1),
"array length mismatch");
/* This must match enum PredicateLockTargetType (predicate_internals.h) */
@@ -459,6 +460,7 @@ pg_lock_status(PG_FUNCTION_ARGS)
nulls[9] = true;
break;
case LOCKTAG_RESOURCE_QUEUE:
+ case LOCKTAG_WAREHOUSE:
#if 0
values[1] = ObjectIdGetDatum(proc->databaseId);
#endif
diff --git a/src/backend/utils/gp/segadmin.c b/src/backend/utils/gp/segadmin.c
index 31baed7394e..cc2eacb31fb 100644
--- a/src/backend/utils/gp/segadmin.c
+++ b/src/backend/utils/gp/segadmin.c
@@ -194,13 +194,24 @@ remove_segment_config(int16 dbid)
Anum_gp_segment_configuration_dbid,
BTEqualStrategyNumber, F_INT2EQ,
Int16GetDatum(dbid));
-
- sscan = systable_beginscan(rel, GpSegmentConfigDbidIndexId, true,
+ sscan = systable_beginscan(rel, GpSegmentConfigDbidWarehouseIndexId, true,
NULL, 1, &scankey);
while ((tuple = systable_getnext(sscan)) != NULL)
{
- CatalogTupleDelete(rel, &tuple->t_self);
- numDel++;
+ Datum attr;
+ bool isNull;
+ Oid warehouseid = InvalidOid;
+
+ attr = heap_getattr(tuple, Anum_gp_segment_configuration_warehouseid,
+ RelationGetDescr(rel), &isNull);
+ Assert(!isNull);
+ warehouseid = DatumGetObjectId(attr);
+
+ if (!OidIsValid(warehouseid) || warehouseid == GetCurrentWarehouseId())
+ {
+ CatalogTupleDelete(rel, &tuple->t_self);
+ numDel++;
+ }
}
systable_endscan(sscan);
@@ -240,6 +251,8 @@ add_segment_config_entry(GpSegConfigEntry *i)
CStringGetTextDatum(i->address);
values[Anum_gp_segment_configuration_datadir - 1] =
CStringGetTextDatum(i->datadir);
+ values[Anum_gp_segment_configuration_warehouseid - 1] =
+ ObjectIdGetDatum(i->warehouseid);
tuple = heap_form_tuple(RelationGetDescr(rel), values, nulls);
@@ -393,6 +406,11 @@ gp_add_segment(PG_FUNCTION_ARGS)
elog(ERROR, "datadir cannot be NULL");
new.datadir = TextDatumGetCString(PG_GETARG_DATUM(9));
+ if (new.segindex == MASTER_CONTENT_ID)
+ new.warehouseid = InvalidOid;
+ else
+ new.warehouseid = GetCurrentWarehouseId();
+
mirroring_sanity_check(MASTER_ONLY | SUPERUSER, "gp_add_segment");
new.mode = GP_SEGMENT_CONFIGURATION_MODE_NOTINSYNC;
@@ -472,7 +490,12 @@ gp_add_segment_mirror(PG_FUNCTION_ARGS)
if (PG_ARGISNULL(4))
elog(ERROR, "datadir cannot be NULL");
new.datadir = TextDatumGetCString(PG_GETARG_DATUM(4));
-
+
+ if (new.segindex == MASTER_CONTENT_ID)
+ new.warehouseid = InvalidOid;
+ else
+ new.warehouseid = GetCurrentWarehouseId();
+
mirroring_sanity_check(MASTER_ONLY | SUPERUSER, "gp_add_segment_mirror");
new.dbid = get_availableDbId();
@@ -609,7 +632,9 @@ gp_add_master_standby(PG_FUNCTION_ARGS)
config->address = TextDatumGetCString(PG_GETARG_TEXT_P(1));
config->datadir = TextDatumGetCString(PG_GETARG_TEXT_P(2));
-
+
+ config->warehouseid = InvalidOid;
+
/* Use the new port number if specified */
if (PG_NARGS() > 3 && !PG_ARGISNULL(3))
config->port = PG_GETARG_INT32(3);
@@ -665,7 +690,7 @@ catalog_activate_standby(int16 standby_dbid, int16 master_dbid)
Anum_gp_segment_configuration_dbid,
BTEqualStrategyNumber, F_INT2EQ,
Int16GetDatum(master_dbid));
- sscan = systable_beginscan(rel, GpSegmentConfigDbidIndexId, true,
+ sscan = systable_beginscan(rel, GpSegmentConfigDbidWarehouseIndexId, true,
NULL, 1, &scankey);
while ((tuple = systable_getnext(sscan)) != NULL)
{
@@ -682,7 +707,7 @@ catalog_activate_standby(int16 standby_dbid, int16 master_dbid)
Anum_gp_segment_configuration_dbid,
BTEqualStrategyNumber, F_INT2EQ,
Int16GetDatum(standby_dbid));
- sscan = systable_beginscan(rel, GpSegmentConfigDbidIndexId, true,
+ sscan = systable_beginscan(rel, GpSegmentConfigDbidWarehouseIndexId, true,
NULL, 1, &scankey);
tuple = systable_getnext(sscan);
@@ -830,16 +855,20 @@ gp_update_segment_configuration_mode_status(PG_FUNCTION_ARGS)
/* we use AccessExclusiveLock to prevent races */
Relation rel = table_open(GpSegmentConfigRelationId, AccessExclusiveLock);
HeapTuple tuple;
- ScanKeyData scankey;
+ ScanKeyData scankey[2];
SysScanDesc sscan;
/* now, set out rows for old standby. */
- ScanKeyInit(&scankey,
+ ScanKeyInit(&scankey[0],
Anum_gp_segment_configuration_dbid,
BTEqualStrategyNumber, F_INT2EQ,
Int16GetDatum(dbid));
- sscan = systable_beginscan(rel, GpSegmentConfigDbidIndexId, true,
- NULL, 1, &scankey);
+ ScanKeyInit(&scankey[1],
+ Anum_gp_segment_configuration_warehouseid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(GetCurrentWarehouseId()));
+ sscan = systable_beginscan(rel, GpSegmentConfigDbidWarehouseIndexId, true,
+ NULL, 2, scankey);
tuple = systable_getnext(sscan);
diff --git a/src/backend/utils/init/miscinit.c b/src/backend/utils/init/miscinit.c
index abdc2567914..a4214ad0662 100644
--- a/src/backend/utils/init/miscinit.c
+++ b/src/backend/utils/init/miscinit.c
@@ -478,6 +478,8 @@ static int SecurityRestrictionContext = 0;
/* We also remember if a SET ROLE is currently active */
static bool SetRoleIsActive = false;
+static Oid CurrentWarehouseId = InvalidOid;
+
/*
* GetUserId - get the current effective user ID.
*
@@ -963,6 +965,18 @@ GetUserNameFromId(Oid roleid, bool noerr)
return result;
}
+Oid
+GetCurrentWarehouseId(void)
+{
+ return CurrentWarehouseId;
+}
+
+void
+SetCurrentWarehouseId(Oid warehouseid)
+{
+ AssertArg(OidIsValid(warehouseid));
+ CurrentWarehouseId = warehouseid;
+}
/*-------------------------------------------------------------------------
* Interlock-file support
diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c
index aea25234a23..e38a602d8a9 100644
--- a/src/bin/psql/tab-complete.c
+++ b/src/bin/psql/tab-complete.c
@@ -1142,6 +1142,7 @@ static const pgsql_thing_t words_after_create[] = {
{"USER", Query_for_list_of_roles " UNION SELECT 'MAPPING FOR'"},
{"USER MAPPING FOR", NULL, NULL, NULL},
{"VIEW", NULL, NULL, &Query_for_list_of_views},
+ {"WAREHOUSE", NULL},
{NULL} /* end of list */
};
@@ -2735,6 +2736,10 @@ psql_completion(const char *text, int start, int end)
Matches("CREATE", "TASK", MatchAny, "SCHEDULE", MatchAny, "USER", MatchAny))
COMPLETE_WITH("AS");
+/* CREATE WAREHOUSE */
+ else if (Matches("CREATE", "WAREHOUSE", MatchAny))
+ COMPLETE_WITH("WAREHOUSE_SIZE");
+
/* CREATE SERVER */
else if (Matches("CREATE", "SERVER", MatchAny))
COMPLETE_WITH("TYPE", "VERSION", "FOREIGN DATA WRAPPER");
diff --git a/src/include/catalog/gp_segment_configuration.h b/src/include/catalog/gp_segment_configuration.h
index 46ac37e02c2..1705924e23b 100644
--- a/src/include/catalog/gp_segment_configuration.h
+++ b/src/include/catalog/gp_segment_configuration.h
@@ -58,6 +58,7 @@ CATALOG(gp_segment_configuration,7026,GpSegmentConfigRelationId) BKI_SHARED_RELA
text address;
text datadir;
+ Oid warehouseid BKI_DEFAULT(0);
#endif
} FormData_gp_segment_configuration;
diff --git a/src/include/catalog/gp_segment_configuration_indexing.h b/src/include/catalog/gp_segment_configuration_indexing.h
index 4d530aa1e22..7d72782e6d4 100644
--- a/src/include/catalog/gp_segment_configuration_indexing.h
+++ b/src/include/catalog/gp_segment_configuration_indexing.h
@@ -14,9 +14,9 @@
#include "catalog/genbki.h"
-DECLARE_UNIQUE_INDEX(gp_segment_config_content_preferred_role_index, 7139, on gp_segment_configuration using btree(content int2_ops, preferred_role char_ops));
-#define GpSegmentConfigContentPreferred_roleIndexId 7139
-DECLARE_UNIQUE_INDEX(gp_segment_config_dbid_index, 7140, on gp_segment_configuration using btree(dbid int2_ops));
-#define GpSegmentConfigDbidIndexId 7140
+DECLARE_UNIQUE_INDEX(gp_segment_config_content_preferred_role_warehouse_index, 7139, on gp_segment_configuration using btree(content int2_ops, preferred_role char_ops, warehouseid oid_ops));
+#define GpSegmentConfigContentPreferred_roleWarehouseIndexId 7139
+DECLARE_UNIQUE_INDEX(gp_segment_config_dbid_warehouse_index, 7140, on gp_segment_configuration using btree(dbid int2_ops, warehouseid oid_ops));
+#define GpSegmentConfigDbidWarehouseIndexId 7140
#endif // GP_SEGMENT_CONFIGURATION_INDEXING_H
\ No newline at end of file
diff --git a/src/include/catalog/gp_warehouse.h b/src/include/catalog/gp_warehouse.h
new file mode 100644
index 00000000000..87646361569
--- /dev/null
+++ b/src/include/catalog/gp_warehouse.h
@@ -0,0 +1,23 @@
+#ifndef GP_WAREHOUSE_H
+#define GP_WAREHOUSE_H
+
+#include "catalog/genbki.h"
+#include "catalog/gp_warehouse_d.h"
+
+/*
+ * Defines for gp_version_at_initdb table
+ */
+CATALOG(gp_warehouse,8690,GpWarehouseRelationId) BKI_SHARED_RELATION
+{
+ Oid oid; /* oid */
+ text warehouse_name; /* warehouse name */
+} FormData_gp_warehouse;
+
+typedef FormData_gp_warehouse *Form_gp_warehouse;
+
+DECLARE_UNIQUE_INDEX(gp_warehouse_oid_index, 8086, on gp_warehouse using btree(oid oid_ops));
+#define GpWarehouseOidIndexId 8086
+DECLARE_UNIQUE_INDEX(gp_warehouse_name_index, 8059, on gp_warehouse using btree(warehouse_name text_ops));
+#define GpWarehouseNameIndexId 8059
+
+#endif /* GP_WAREHOUSE_H */
diff --git a/src/include/miscadmin.h b/src/include/miscadmin.h
index d67953e5126..07e375dfea0 100644
--- a/src/include/miscadmin.h
+++ b/src/include/miscadmin.h
@@ -460,6 +460,8 @@ extern void InitializeSessionUserIdStandalone(void);
extern void SetSessionAuthorization(Oid userid, bool is_superuser);
extern Oid GetCurrentRoleId(void);
extern void SetCurrentRoleId(Oid roleid, bool is_superuser);
+extern Oid GetCurrentWarehouseId(void);
+extern void SetCurrentWarehouseId(Oid warehouseid);
/* in utils/misc/superuser.c */
extern bool superuser(void); /* current user is superuser */
diff --git a/src/include/nodes/nodes.h b/src/include/nodes/nodes.h
index 89469a8c316..0912902eb21 100644
--- a/src/include/nodes/nodes.h
+++ b/src/include/nodes/nodes.h
@@ -542,6 +542,8 @@ typedef enum NodeTag
T_GpDropPartitionCmd,
T_GpSplitPartitionCmd,
T_GpAlterPartitionCmd,
+ T_CreateWarehouseStmt,
+ T_DropWarehouseStmt,
/*
* TAGS FOR PARSE TREE NODES (parsenodes.h)
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index 77e60a68765..4af6cbc1f9f 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -4260,4 +4260,21 @@ typedef struct RetrieveStmt
bool is_all;
} RetrieveStmt;
+/* ----------------------
+ * Warehouse Statement
+ * ----------------------
+ */
+typedef struct CreateWarehouseStmt
+{
+ NodeTag type;
+ char *whname;
+ List *options; /* List of DefElem nodes */
+} CreateWarehouseStmt;
+
+typedef struct DropWarehouseStmt
+{
+ NodeTag type;
+ char *whname;
+} DropWarehouseStmt;
+
#endif /* PARSENODES_H */
diff --git a/src/include/parser/kwlist.h b/src/include/parser/kwlist.h
index 3df64f49ca1..a6e840fc4fe 100644
--- a/src/include/parser/kwlist.h
+++ b/src/include/parser/kwlist.h
@@ -520,6 +520,8 @@ PG_KEYWORD("version", VERSION_P, UNRESERVED_KEYWORD, BARE_LABEL)
PG_KEYWORD("view", VIEW, UNRESERVED_KEYWORD, BARE_LABEL)
PG_KEYWORD("views", VIEWS, UNRESERVED_KEYWORD, BARE_LABEL)
PG_KEYWORD("volatile", VOLATILE, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("warehouse", WAREHOUSE, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("warehouse_size", WAREHOUSE_SIZE, UNRESERVED_KEYWORD, BARE_LABEL)
PG_KEYWORD("web", WEB, UNRESERVED_KEYWORD, BARE_LABEL)
PG_KEYWORD("when", WHEN, RESERVED_KEYWORD, BARE_LABEL)
PG_KEYWORD("where", WHERE, RESERVED_KEYWORD, AS_LABEL)
diff --git a/src/include/postmaster/fts_comm.h b/src/include/postmaster/fts_comm.h
index 765ad45e994..16fc53247c2 100644
--- a/src/include/postmaster/fts_comm.h
+++ b/src/include/postmaster/fts_comm.h
@@ -148,6 +148,7 @@ typedef struct GpSegConfigEntry
char *hostname; /* name or ip address of host machine */
char *address; /* ip address of host machine */
char *datadir; /* absolute path to data directory on the host. */
+ Oid warehouseid;
/* additional cached info */
char *hostip; /* cached lookup of name */
diff --git a/src/include/storage/lmgr.h b/src/include/storage/lmgr.h
index 42014da620f..a8806269fa6 100644
--- a/src/include/storage/lmgr.h
+++ b/src/include/storage/lmgr.h
@@ -120,4 +120,8 @@ extern bool LockTagIsTemp(const LOCKTAG *tag);
extern void GxactLockTableInsert(DistributedTransactionId xid);
extern void GxactLockTableWait(DistributedTransactionId xid);
+
+/* Lock a warehouse */
+extern void LockWarehouse(Oid warehouseOid, LOCKMODE lockmode);
+extern void UnlockWarehouse(Oid warehouseOid, LOCKMODE lockmode);
#endif /* LMGR_H */
diff --git a/src/include/storage/lock.h b/src/include/storage/lock.h
index b70eea63d6e..5f77b5f942a 100644
--- a/src/include/storage/lock.h
+++ b/src/include/storage/lock.h
@@ -168,10 +168,11 @@ typedef enum LockTagType
LOCKTAG_RESOURCE_QUEUE, /* ID info for resource queue is QUEUE ID */
LOCKTAG_DISTRIB_TRANSACTION,/* CDB: distributed transaction (for waiting for distributed xact done) */
LOCKTAG_USERLOCK, /* reserved for old contrib/userlock code */
- LOCKTAG_ADVISORY /* advisory user locks */
+ LOCKTAG_ADVISORY, /* advisory user locks */
+ LOCKTAG_WAREHOUSE /* warehouse locks */
} LockTagType;
-#define LOCKTAG_LAST_TYPE LOCKTAG_ADVISORY
+#define LOCKTAG_LAST_TYPE LOCKTAG_WAREHOUSE
extern const char *const LockTagTypeNames[];
@@ -317,6 +318,14 @@ typedef struct LOCKTAG
(locktag).locktag_type = LOCKTAG_RESOURCE_QUEUE, \
(locktag).locktag_lockmethodid = RESOURCE_LOCKMETHOD)
+#define SET_LOCKTAG_WAREHOUSE(locktag,warehouseid) \
+ ((locktag).locktag_field1 = (warehouseid), \
+ (locktag).locktag_field2 = 0, \
+ (locktag).locktag_field3 = 0, \
+ (locktag).locktag_field4 = 0, \
+ (locktag).locktag_type = LOCKTAG_WAREHOUSE, \
+ (locktag).locktag_lockmethodid = DEFAULT_LOCKMETHOD)
+
/*
* Per-locked-object lock information:
*
diff --git a/src/include/tcop/cmdtaglist.h b/src/include/tcop/cmdtaglist.h
index a6c36d31350..61469142633 100644
--- a/src/include/tcop/cmdtaglist.h
+++ b/src/include/tcop/cmdtaglist.h
@@ -135,6 +135,7 @@ PG_CMDTAG(CMDTAG_CREATE_TYPE, "CREATE TYPE", true, false, false)
PG_CMDTAG(CMDTAG_CREATE_TASK, "CREATE TASK", true, false, false)
PG_CMDTAG(CMDTAG_CREATE_USER_MAPPING, "CREATE USER MAPPING", true, false, false)
PG_CMDTAG(CMDTAG_CREATE_VIEW, "CREATE VIEW", true, false, false)
+PG_CMDTAG(CMDTAG_CREATE_WAREHOUSE, "CREATE WAREHOUSE", true, false, false)
PG_CMDTAG(CMDTAG_DEALLOCATE, "DEALLOCATE", false, false, false)
PG_CMDTAG(CMDTAG_DEALLOCATE_ALL, "DEALLOCATE ALL", false, false, false)
PG_CMDTAG(CMDTAG_DECLARE_CURSOR, "DECLARE CURSOR", false, false, false)
@@ -201,6 +202,7 @@ PG_CMDTAG(CMDTAG_DROP_TRIGGER, "DROP TRIGGER", true, false, false)
PG_CMDTAG(CMDTAG_DROP_TYPE, "DROP TYPE", true, false, false)
PG_CMDTAG(CMDTAG_DROP_USER_MAPPING, "DROP USER MAPPING", true, false, false)
PG_CMDTAG(CMDTAG_DROP_VIEW, "DROP VIEW", true, false, false)
+PG_CMDTAG(CMDTAG_DROP_WAREHOUSE, "DROP WAREHOUSE", true, false, false)
diff --git a/src/test/regress/expected/misc_sanity.out b/src/test/regress/expected/misc_sanity.out
index 13947c53237..4f7ef1d12b7 100644
--- a/src/test/regress/expected/misc_sanity.out
+++ b/src/test/regress/expected/misc_sanity.out
@@ -105,6 +105,7 @@ ORDER BY 1, 2;
--------------------------+--------------------+--------------
gp_configuration_history | desc | text
gp_version_at_initdb | productversion | text
+ gp_warehouse | warehouse_name | text
pg_attribute | attacl | aclitem[]
pg_attribute | attfdwoptions | text[]
pg_attribute | attmissingval | anyarray
@@ -133,7 +134,7 @@ ORDER BY 1, 2;
pg_task_run_history | return_message | text
pg_task_run_history | status | text
pg_task_run_history | username | text
-(30 rows)
+(31 rows)
-- system catalogs without primary keys
--
@@ -153,6 +154,7 @@ ORDER BY 1;
gp_id
gp_partition_template
gp_version_at_initdb
+ gp_warehouse
pg_appendonly
pg_attribute_encoding
pg_auth_time_constraint
@@ -169,7 +171,7 @@ ORDER BY 1;
pg_stat_last_operation
pg_stat_last_shoperation
pg_type_encoding
-(22 rows)
+(23 rows)
-- system catalog unique indexes not wrapped in a constraint
-- (There should be none.)
diff --git a/src/test/regress/output/dispatch.source b/src/test/regress/output/dispatch.source
index 109f6a2e8fa..d4c6ed0f383 100644
--- a/src/test/regress/output/dispatch.source
+++ b/src/test/regress/output/dispatch.source
@@ -894,8 +894,8 @@ SELECT gp_inject_fault('cdbcomponent_recycle_idle_qe_error', 'interrupt', dbid,
(1 row)
select * from gp_segment_configuration a, t13393 ,gp_segment_configuration b where a.dbid = t13393.tc1 limit 0;
- dbid | content | role | preferred_role | mode | status | port | hostname | address | datadir | tc1 | dbid | content | role | preferred_role | mode | status | port | hostname | address | datadir
-------+---------+------+----------------+------+--------+------+----------+---------+---------+-----+------+---------+------+----------------+------+--------+------+----------+---------+---------
+ dbid | content | role | preferred_role | mode | status | port | hostname | address | datadir | warehouseid | tc1 | dbid | content | role | preferred_role | mode | status | port | hostname | address | datadir | warehouseid
+------+---------+------+----------------+------+--------+------+----------+---------+---------+-------------+-----+------+---------+------+----------------+------+--------+------+----------+---------+---------+-------------
(0 rows)
SELECT gp_inject_fault('cdbcomponent_recycle_idle_qe_error', 'reset', dbid, current_setting('gp_session_id')::int)