diff --git a/src/backend/access/index/indexam.c b/src/backend/access/index/indexam.c
index cc5ac8b..bec3983 100644
--- a/src/backend/access/index/indexam.c
+++ b/src/backend/access/index/indexam.c
@@ -154,7 +154,8 @@ index_open(Oid relationId, LOCKMODE lockmode)
 
 	r = relation_open(relationId, lockmode);
 
-	if (r->rd_rel->relkind != RELKIND_INDEX)
+	if (r->rd_rel->relkind != RELKIND_INDEX &&
+		r->rd_rel->relkind != RELKIND_LOCAL_INDEX)
 		ereport(ERROR,
 				(errcode(ERRCODE_WRONG_OBJECT_TYPE),
 				 errmsg("\"%s\" is not an index",
diff --git a/src/backend/catalog/dependency.c b/src/backend/catalog/dependency.c
index fc088b2..26a10e9 100644
--- a/src/backend/catalog/dependency.c
+++ b/src/backend/catalog/dependency.c
@@ -1107,7 +1107,8 @@ doDeletion(const ObjectAddress *object, int flags)
 			{
 				char		relKind = get_rel_relkind(object->objectId);
 
-				if (relKind == RELKIND_INDEX)
+				if (relKind == RELKIND_INDEX ||
+					relKind == RELKIND_LOCAL_INDEX)
 				{
 					bool		concurrent = ((flags & PERFORM_DELETION_CONCURRENTLY) != 0);
 
diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c
index 36917c8..91ac740 100644
--- a/src/backend/catalog/heap.c
+++ b/src/backend/catalog/heap.c
@@ -293,6 +293,7 @@ heap_create(const char *relname,
 		case RELKIND_COMPOSITE_TYPE:
 		case RELKIND_FOREIGN_TABLE:
 		case RELKIND_PARTITIONED_TABLE:
+		case RELKIND_LOCAL_INDEX:
 			create_storage = false;
 
 			/*
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index 7924c30..36452a9 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -41,6 +41,7 @@
 #include "catalog/pg_collation.h"
 #include "catalog/pg_constraint.h"
 #include "catalog/pg_constraint_fn.h"
+#include "catalog/pg_depend.h"
 #include "catalog/pg_operator.h"
 #include "catalog/pg_opclass.h"
 #include "catalog/pg_tablespace.h"
@@ -726,6 +727,7 @@ index_create(Relation heapRelation,
 	Oid			namespaceId;
 	int			i;
 	char		relpersistence;
+	char		index_relkind;
 
 	is_exclusion = (indexInfo->ii_ExclusionOps != NULL);
 
@@ -843,6 +845,10 @@ index_create(Relation heapRelation,
 		}
 	}
 
+	index_relkind =
+		(heapRelation->rd_rel->relkind != RELKIND_PARTITIONED_TABLE) ?
+			RELKIND_INDEX : RELKIND_LOCAL_INDEX;
+
 	/*
 	 * create the index relation's relcache entry and physical disk file. (If
 	 * we fail further down, it's the smgr's responsibility to remove the disk
@@ -854,7 +860,7 @@ index_create(Relation heapRelation,
 								indexRelationId,
 								relFileNode,
 								indexTupDesc,
-								RELKIND_INDEX,
+								index_relkind,
 								relpersistence,
 								shared_relation,
 								mapped_relation,
@@ -1548,10 +1554,14 @@ index_drop(Oid indexId, bool concurrent)
 		TransferPredicateLocksToHeapRelation(userIndexRelation);
 	}
 
-	/*
-	 * Schedule physical removal of the files
-	 */
-	RelationDropStorage(userIndexRelation);
+	if (userIndexRelation->rd_rel->relkind != RELKIND_LOCAL_INDEX)
+	{
+
+		/*
+		 * Schedule physical removal of the files
+		 */
+		RelationDropStorage(userIndexRelation);
+	}
 
 	/*
 	 * Close and flush the index's relcache entry, to ensure relcache doesn't
@@ -3300,6 +3310,109 @@ IndexGetRelation(Oid indexId, bool missing_ok)
 }
 
 /*
+ * Find all leaf indexes included into local index with 'indexId' oid and lock
+ * all dependent indexes and respective relations.
+ *
+ * Search is performed in pg_depend table since all indexes belonging to child
+ * tables depends on index from parent table.
+ *
+ *	indexId: the oid of local index whose leaf indexes need to find
+ *	result: list of result leaf indexes
+ *	depRel: already opened pg_depend relation
+ *	indexLockmode: lockmode for indexes' locks
+ *	heapLockmode: lockmode for relations' locks
+ */
+static void
+findDepedentLeafIndexes(Oid indexId, List **result, Relation depRel,
+						LOCKMODE indexLockmode, LOCKMODE heapLockmode)
+{
+	ScanKeyData 		key[3];
+	int					nkeys;
+	SysScanDesc 		scan;
+	HeapTuple			tup;
+	List			   *localSubIndexIds = NIL;
+	ListCell		   *lc;
+
+	ScanKeyInit(&key[0],
+				Anum_pg_depend_refclassid,
+				BTEqualStrategyNumber, F_OIDEQ,
+				ObjectIdGetDatum(RelationRelationId));
+	ScanKeyInit(&key[1],
+				Anum_pg_depend_refobjid,
+				BTEqualStrategyNumber, F_OIDEQ,
+				ObjectIdGetDatum(indexId));
+	nkeys = 2;
+
+	scan = systable_beginscan(depRel, DependReferenceIndexId, true,
+							  NULL, nkeys, key);
+
+	while (HeapTupleIsValid(tup = systable_getnext(scan)))
+	{
+		Form_pg_depend 	foundDep = (Form_pg_depend) GETSTRUCT(tup);
+		Relation		index;
+
+		if (foundDep->classid != RelationRelationId)
+			continue;
+
+		/* Open and lock child index */
+		index = relation_open(foundDep->objid, indexLockmode);
+
+		/* Lock relation */
+		LockRelationOid(IndexGetRelation(index->rd_id, false), heapLockmode);
+
+		if (index->rd_rel->relkind == RELKIND_INDEX)
+			*result = lappend_oid(*result, index->rd_id);
+		else if (index->rd_rel->relkind == RELKIND_LOCAL_INDEX)
+			localSubIndexIds = lappend_oid(localSubIndexIds, index->rd_id);
+
+		relation_close(index, NoLock);
+	}
+
+	systable_endscan(scan);
+
+	/* Iterate thorugh local subindexes to extract their leaf indexes */
+	foreach(lc, localSubIndexIds)
+	{
+		findDepedentLeafIndexes(lfirst_oid(lc), result, depRel, indexLockmode,
+								heapLockmode);
+	}
+}
+
+/*
+ * Reindex all real indexes included into local index with 'parent_index_id' oid
+ */
+static void
+reindex_local_index(Oid parent_index_id, bool skip_constraint_checks,
+					char persistence, int options)
+{
+	List	   *leaf_indexes = NIL;
+	ListCell   *lc;
+	Relation 	deprel;
+
+	/*
+	 * We open pg_depend just once and passing the Relation pointer down to all
+	 * the recursive searching of leaf indexes steps.
+	 */
+	deprel = heap_open(DependRelationId, AccessShareLock);
+
+	/*
+	 * Extract all leaf indexes, and lock all indexes belonging with parent
+	 * local index using AccessExclusive lock and corresponding relations using
+	 * Share lock
+	 */
+	findDepedentLeafIndexes(parent_index_id, &leaf_indexes, deprel,
+							AccessExclusiveLock, ShareLock);
+
+	foreach(lc, leaf_indexes)
+	{
+		reindex_index(lfirst_oid(lc), skip_constraint_checks, persistence,
+					  options);
+	}
+
+	heap_close(deprel, AccessShareLock);
+}
+
+/*
  * reindex_index - This routine is used to recreate a single index
  */
 void
@@ -3338,6 +3451,19 @@ reindex_index(Oid indexId, bool skip_constraint_checks, char persistence,
 			   errmsg("cannot reindex temporary tables of other sessions")));
 
 	/*
+	 * Reindex local index belonging to partitioned table
+	 */
+	if (heapRelation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
+	{
+		index_close(iRel, NoLock);
+		heap_close(heapRelation, NoLock);
+
+		reindex_local_index(indexId, skipped_constraint, persistence, options);
+
+		return;
+	}
+
+	/*
 	 * Also check for active uses of the index in the current transaction; we
 	 * don't want to reindex underneath an open indexscan.
 	 */
diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c
index 9618032..8bbe3d0 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -23,7 +23,9 @@
 #include "catalog/catalog.h"
 #include "catalog/index.h"
 #include "catalog/indexing.h"
+#include "catalog/partition.h"
 #include "catalog/pg_am.h"
+#include "catalog/pg_inherits_fn.h"
 #include "catalog/pg_opclass.h"
 #include "catalog/pg_opfamily.h"
 #include "catalog/pg_tablespace.h"
@@ -283,6 +285,30 @@ CheckIndexCompatible(Oid oldId,
 	return ret;
 }
 
+#define PUSH_REL_PARTITION_OIDS(rel, part_oids, rel_index_oid, \
+								parent_index_oids) \
+		do\
+		{\
+			if (RelationGetPartitionDesc((rel)))\
+			{\
+				int		i;\
+				for (i = 0; i < (rel)->rd_partdesc->nparts; ++i)\
+				{\
+					(part_oids) = lcons_oid((rel)->rd_partdesc->oids[i],\
+							(part_oids));\
+					(parent_index_oids) = lcons_oid((rel_index_oid),\
+							(parent_index_oids));\
+				}\
+			}\
+		} while(0)
+
+#define POP_REL_PARTITION_OIDS(part_oids, parent_index_oids) \
+		do\
+		{\
+			(part_oids) = list_delete_first((part_oids));\
+			(parent_index_oids) = list_delete_first((parent_index_oids));\
+		} while(0)
+
 /*
  * DefineIndex
  *		Creates a new index.
@@ -372,7 +398,8 @@ DefineIndex(Oid relationId,
 	namespaceId = RelationGetNamespace(rel);
 
 	if (rel->rd_rel->relkind != RELKIND_RELATION &&
-		rel->rd_rel->relkind != RELKIND_MATVIEW)
+		rel->rd_rel->relkind != RELKIND_MATVIEW &&
+		rel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
 	{
 		if (rel->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
 
@@ -384,11 +411,6 @@ DefineIndex(Oid relationId,
 					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
 					 errmsg("cannot create index on foreign table \"%s\"",
 							RelationGetRelationName(rel))));
-		else if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
-			ereport(ERROR,
-					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
-					 errmsg("cannot create index on partitioned table \"%s\"",
-							RelationGetRelationName(rel))));
 		else
 			ereport(ERROR,
 					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
@@ -396,6 +418,12 @@ DefineIndex(Oid relationId,
 							RelationGetRelationName(rel))));
 	}
 
+	if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE && stmt->concurrent)
+		ereport(ERROR,
+				(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+				 errmsg("cannot create local index on partitioned table \"%s\" concurrently",
+					 RelationGetRelationName(rel))));
+
 	/*
 	 * Don't try to CREATE INDEX on temp tables of other backends.
 	 */
@@ -660,7 +688,8 @@ DefineIndex(Oid relationId,
 					 coloptions, reloptions, stmt->primary,
 					 stmt->isconstraint, stmt->deferrable, stmt->initdeferred,
 					 allowSystemTableMods,
-					 skip_build || stmt->concurrent,
+					 skip_build || stmt->concurrent ||
+						rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE,
 					 stmt->concurrent, !check_rights,
 					 stmt->if_not_exists);
 
@@ -677,8 +706,89 @@ DefineIndex(Oid relationId,
 		CreateComments(indexRelationId, RelationRelationId, 0,
 					   stmt->idxcomment);
 
+	/*
+	 * Create local index on partitioned table that comes down to creating of
+	 * indexes on child relations using depth-first traversal
+	 */
+	if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
+	{
+
+		List   *part_oids = NIL,			/* stack for concerned partion oids */
+			   *parent_index_oids = NIL;	/* stack for corresponding parent
+											   index oids */
+
+		Assert(!stmt->concurrent);
+
+		/*
+		 * Initially push child oids of current relation and related
+		 * parent index oids
+		 */
+		PUSH_REL_PARTITION_OIDS(rel, part_oids, indexRelationId,
+				parent_index_oids);
+
+		while (list_length(part_oids) > 0)
+		{
+			Relation	childrel;
+			Oid			parent_index_oid,
+						child_index_oid;
+			ObjectAddress	index_address,
+							parent_index_address;
+			char	   *child_index_name;
+
+			/* Extract top child relation and related parent index oid from stacks */
+			childrel = relation_open(linitial_oid(part_oids), lockmode);
+			parent_index_oid = linitial_oid(parent_index_oids);
+
+			/* Choose name for child index */
+			child_index_name =
+				ChooseIndexName(RelationGetRelationName(childrel),
+						namespaceId, indexColNames,
+						stmt->excludeOpNames, stmt->primary,
+						stmt->isconstraint);
+
+			/* Create index for child node */
+			child_index_oid =
+				index_create(childrel, child_index_name, InvalidOid,
+						InvalidOid, indexInfo, indexColNames,
+						accessMethodId, tablespaceId,
+						collationObjectId, classObjectId,
+						coloptions, reloptions, stmt->primary,
+						stmt->isconstraint, stmt->deferrable,
+						stmt->initdeferred, allowSystemTableMods,
+						skip_build || childrel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE,
+						stmt->concurrent, !check_rights,
+						stmt->if_not_exists);
+
+			/* Pop current reloid and related parent index oid from stacks */
+			POP_REL_PARTITION_OIDS(part_oids, parent_index_oids);
+
+			/*
+			 * Push new childs of current child relation and
+			 * related parent indexes to stacks
+			 */
+			PUSH_REL_PARTITION_OIDS(childrel, part_oids, child_index_oid,
+					parent_index_oids);
+
+			/* Release relcache entry from childrel */
+			relation_close(childrel, NoLock);
+
+			/*
+			 * Add entry to pg_depend to specify dependancy child index
+			 * from parent one
+			 */
+			ObjectAddressSet(index_address, RelationRelationId,
+					child_index_oid);
+			ObjectAddressSet(parent_index_address, RelationRelationId,
+					parent_index_oid);
+			recordDependencyOn(&index_address, &parent_index_address,
+					DEPENDENCY_NORMAL);
+		}
+	}
+
+
 	if (!stmt->concurrent)
 	{
+
 		/* Close the heap and we're done, in the non-concurrent case */
 		heap_close(rel, NoLock);
 		return address;
@@ -1800,7 +1910,7 @@ RangeVarCallbackForReindexIndex(const RangeVar *relation,
 	relkind = get_rel_relkind(relId);
 	if (!relkind)
 		return;
-	if (relkind != RELKIND_INDEX)
+	if (relkind != RELKIND_INDEX && relkind != RELKIND_LOCAL_INDEX)
 		ereport(ERROR,
 				(errcode(ERRCODE_WRONG_OBJECT_TYPE),
 				 errmsg("\"%s\" is not an index", relation->relname)));
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 3b28e8c..da92211 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -1113,9 +1113,13 @@ RangeVarCallbackForDropRelation(const RangeVar *rel, Oid relOid, Oid oldRelOid,
 	 * It chooses RELKIND_RELATION for both regular and partitioned tables.
 	 * That means we must be careful before giving the wrong type error when
 	 * the relation is RELKIND_PARTITIONED_TABLE.
+	 *
+	 * Similar statements hold for RELKIND_LOCAL_INDEX and RELKIND_INDEX.
 	 */
 	if (classform->relkind == RELKIND_PARTITIONED_TABLE)
 		expected_relkind = RELKIND_RELATION;
+	else if (classform->relkind == RELKIND_LOCAL_INDEX)
+		expected_relkind = RELKIND_INDEX;
 	else
 		expected_relkind = classform->relkind;
 
diff --git a/src/include/catalog/pg_class.h b/src/include/catalog/pg_class.h
index d1d493e..21af6fa 100644
--- a/src/include/catalog/pg_class.h
+++ b/src/include/catalog/pg_class.h
@@ -159,6 +159,8 @@ DESCR("");
 
 #define		  RELKIND_RELATION		  'r'		/* ordinary table */
 #define		  RELKIND_INDEX			  'i'		/* secondary index */
+#define		  RELKIND_LOCAL_INDEX     'l'		/* local index for
+												   partitioned table */
 #define		  RELKIND_SEQUENCE		  'S'		/* sequence object */
 #define		  RELKIND_TOASTVALUE	  't'		/* for out-of-line values */
 #define		  RELKIND_VIEW			  'v'		/* view */
