text:
#include "postgres.h"

#include "access/genam.h"
#include "access/hash.h"
#include "catalog/index.h"
#include "catalog/pg_constraint.h"
#include "catalog/pg_partition_rule.h"
#include "cdb/cdbpartition.h"
#include "cdb/partitionselection.h"
#include "cdb/cdbvars.h"
#include "nodes/makefuncs.h"
#include "parser/parse_expr.h"
#include "utils/builtins.h"
#include "utils/fmgroids.h"
#include "utils/lsyscache.h"
#include "utils/memutils.h"

/* initial estimate for number of logical indexes */
#define INITIAL_NUM_LOGICAL_INDEXES_ESTIMATE 100

static int logicalIndexId = 1;
static int numLogicalIndexes = 0;
static int numIndexesOnDefaultParts = 0;

/*
 * hash table to identify distinct "logical indexes". Each index with the same
 * index key, index pred, index expr is considered equivalent.
 */
static HTAB *PartitionIndexHash;

/* hash table to hold information about distinct logical indexes. */
static HTAB *LogicalIndexInfoHash;

/*
 * Hash entry for PartionIndexHash
 * hashkey is (indexkey + indexpred + indexexprs)
 */
typedef struct
{
	char 		*key;
	int 		logicalIndexId;
} PartitionIndexHashEntry;

/*
 * Hashentry for LogicalIndexInfoHash
 * hashkey is (logicalIndexId)
 */
typedef struct
{
	char 		*key;
	int 		logicalIndexId;
	Oid		logicalIndexOid;
	struct 		IndexInfo *ii;
	LogicalIndexType indType;
	List		*partList;
	List		*defaultPartList;
} LogicalIndexInfoHashEntry;

/*
 * Each node in the PartitionIndexNode tree describes a partition
 * and a list of it's logical indexes
 */
typedef struct PartitionIndexNode
{
	Oid		paroid;		/* OID of row in pg_partition */
	Oid		parparentrule;	/* OID of row in pg_partition_rule */
	Oid 		parchildrelid;	/* table oid of the part */
	Oid		parrelid;	/* needed to map attnums */
	bool		isDefault;	/* is this a default part */
	Bitmapset	*index; 	/* logical indexes for this part */
	List		*children;	/* child parts */
	List		*defaultLevels; /* the level at which the part key is default */
} PartitionIndexNode;

static void recordIndexesOnLeafPart(PartitionIndexNode **pNodePtr,
					Oid partOid, Oid rootOid);
static void recordIndexes(PartitionIndexNode **partIndexTree);
static void getPartitionIndexNode(Oid rootOid, int2 level,
					Oid parent, PartitionIndexNode **n,
					bool isDefault, List *defaultLevels);
static void indexParts(PartitionIndexNode **np, bool isDefault);
static void dumpPartsIndexInfo(PartitionIndexNode *n, int level);
static LogicalIndexes * createPartsIndexResult(Oid root);
static bool collapseIndexes(PartitionIndexNode **partitionIndexNode,
					LogicalIndexInfoHashEntry **entry);
static void createIndexHashTables(void);
static IndexInfo *populateIndexInfo(Relation indRel);
static Node *mergeIntervals(Node *intervalFst, Node *intervalSnd);
static void extractStartEndRange(Node *clause, Node **ppnodeStart, Node **ppnodeEnd);
static void extractOpExprComponents(OpExpr *opexpr, Var **ppvar, Const **ppconst, Oid *opno);

/*
 * TODO: similar routines in cdbpartition.c. Move up to cdbpartition.h ?
 */

/* Hash entire string */
static uint32
key_string_hash(const void *key, Size keysize)
{
	Size		s_len = strlen((const char *) key);

	Assert(keysize == sizeof(char*));
	return DatumGetUInt32(hash_any((const unsigned char *) key, (int) s_len));
}

/* Compare entire string. */
static int
key_string_compare(const void *key1, const void *key2, Size keysize)
{
	Assert(keysize == sizeof(char*));
	return strcmp(((PartitionIndexHashEntry*)key1)->key, key2);
}

/* Copy string by copying pointer. */
static void *
key_string_copy(void *dest, const void *src, Size keysize)
{
	Assert(keysize == sizeof(char*));

	*((char**)dest) = (char*)src; /* trust caller re allocation */
	return NULL; /* not used */
}

/*
 * BuildLogicalIndexInfo
 *   Returns an array of "logical indexes" on partitioned
 *   tables.
 *
 *   Memory for result is allocated from caller context.
 *
 *   If input relid does not represent a partitioned table, the function
 *   returns NULL.
 *
 *   This function does the following
 *	1) Builds a PartitionIndexNode tree representing the partitioned
 *	   table hierarchy.
 * 	2) Builds 2 hash tables -
 *	 	- 1st hash table is used to find the logical indexes in a
 *		  partitioning tree hierarchy - a logical
 * 		  index corresponds to multiple physical indexes each
 *		  of which have the same index key + index pred + index exprs. Each
 *		  logical index is assigned a unique logicalIndexId.
 *		- The 2nd hash table table is used to hold information associated
 *		  with a logical index for easy lookup.
 *	3) Annotates leaves of hierarchy with logical index ids.
 *	   See recordIndexes function comments.
 *	4) Consolidates logical index information i.e. if a logical index exists on all
 * 	   child parts of a parent part, the parent part is annotated with the logical
 *	   index id and logical index id is cleared from child parts.
 *	5) For each logical index, OR the check constraints of the part on which
 * 	   the index exists (i.e. generate a partial index predicate for each
 *	   logical index)
 * 	6) Since default parts, don't have constraints associated with them,
 * 	   each logical index on a default part is represented as a separate
 *	   logical index in the output. Some additional information is
 *	   included so the specific default partition may be identified.
 *
 *	Example of a partitioning hierarchy, and the output generated.
 *	I1..In are logical index ids.
 *
 *	After Step 3 (leaves annotated with logical index ids)
 *
 *				Root
 *		  / 		|		\
 *		 /		|		 \
 *		/		|		  \
 *		A1 		A2		default  - pk1 is partkey at level 0
 *	     /      \	       /    \		/       \
 *	    /	     \        /      \	       /         \
 *	   /          \	     /        \	      /           \
 * B1(I1,I2)   def(I1,I2) B1(I1,I2)  def(I2) B1(I1,I2,I4) def(I1,I2,I3) - pk2 is partkey at level 1
 *
 *
 * 	After step 4 - (consolidation of logical indexes)
 *
 *			      Root (I2)
 *		 / 		| 	       \
 *		/		|		\
 * 	       /             	|		 \
 *   	    A1 (I1)		A2		default	(I1)
 *	 /      \            /      \            /     \
 *	/        \          /        \	 	/       \
 *     /          \	   /          \	       /         \
 *    B1         def   B1(I1)         def   B1(I4)    def(I3)
 *
 * The output returned from BuildLogicalIndexInfo will be
 *
 * logicalIndexOid 	nColumns  indexKeys  indPred indExprs  indIsUnique  partCons   				defaultLevels
 * 	I2		..	  ..	     ..	     ..	       ..           -						-
 * 	I1		..	  ..	     ..	     ..	       ..           pk1=A1 OR (pk1=A2 AND pk2=B1)		-
 * 	I1'		..	  ..	     ..	     ..	       ..           -						0
 * 	I3		..	  ..	     ..	     ..	       ..           -						0,1
 * 	I4		..	  ..	     ..	     ..	       ..           pk2=B1	 				0
 */
LogicalIndexes *
BuildLogicalIndexInfo(Oid relid)
{
	MemoryContext   callerContext = NULL;
	MemoryContext   partContext = NULL;
	LogicalIndexes *partsLogicalIndexes = NULL;
	HASH_SEQ_STATUS hash_seq;
	LogicalIndexInfoHashEntry *entry;
	PartitionIndexNode *n = NULL;

	/*
	 * create a memory context to hold allocations, so we can get rid of
	 * at the end of this function.
	 */
	partContext = AllocSetContextCreate(CurrentMemoryContext,
					"Partitioned Logical Index Context",
					ALLOCSET_DEFAULT_MINSIZE,
					ALLOCSET_DEFAULT_INITSIZE,
					ALLOCSET_DEFAULT_MAXSIZE);

	/* switch to the new context */
	callerContext = MemoryContextSwitchTo(partContext);

	/* initialize globals */
	logicalIndexId = 1;
	numLogicalIndexes = 0;
	numIndexesOnDefaultParts = 0;

	/* construct the partition node tree */
	getPartitionIndexNode(relid, 0, InvalidOid, &n, false, NIL);

	if (!n)
		return NULL;

	/* create the hash tables to hold the logical index info */
	createIndexHashTables();

	/* now walk the tree and annotate with logical index id at each leaf */
	recordIndexes(&n);

	hash_freeze(LogicalIndexInfoHash);

	/* get rid of first hash table here as we have identified all logical indexes */
	hash_destroy(PartitionIndexHash);

	/* walk the tree and pull-up indexes for each logical index */
	hash_seq_init(&hash_seq, LogicalIndexInfoHash);
	while ((entry = hash_seq_search(&hash_seq)))
	{
		collapseIndexes(&n, &entry);
		numLogicalIndexes++;
	}

	dumpPartsIndexInfo(n, 0);

	/* associate index with parts */
	indexParts(&n, false);

	/* switch to caller context and handle results */
	MemoryContextSwitchTo(callerContext);

	/* generate output rows */
	if ((numLogicalIndexes+numIndexesOnDefaultParts) > 0)
		partsLogicalIndexes = createPartsIndexResult(relid);

	hash_destroy(LogicalIndexInfoHash);

	/* all information has been copied into caller context */
	MemoryContextDelete(partContext);

	return partsLogicalIndexes;
}

/*
 * getPartitionIndexNode
 *   Construct a PartitionIndexNode tree for the given part.
 *   Recurs to construct branches.
 */
static void
getPartitionIndexNode(Oid rootOid,
			int2 level,
			Oid parent,
			PartitionIndexNode **n,
			bool isDefault,
			List *defaultLevels)
{
	HeapTuple	tuple;
	ScanKeyData scankey[3];
	SysScanDesc sscan;
	Relation	partRel;
	Relation	partRuleRel;
	Form_pg_partition partDesc;
	Oid		parOid;
	bool 		inctemplate = false;

	if (Gp_role != GP_ROLE_DISPATCH)
		return;

	/* select oid as partid, *
	 * from pg_partition
	 * where
   	 * 	parrelid = :relid and
	 * 	parlevel = :level and
	 *	paristemplate = false;
	 */
	partRel = heap_open(PartitionRelationId, AccessShareLock);

	ScanKeyInit(&scankey[0],
				Anum_pg_partition_parrelid,
				BTEqualStrategyNumber, F_OIDEQ,
				ObjectIdGetDatum(rootOid));
	ScanKeyInit(&scankey[1],
				Anum_pg_partition_parlevel,
				BTEqualStrategyNumber, F_INT2EQ,
				Int16GetDatum(level));
	ScanKeyInit(&scankey[2],
				Anum_pg_partition_paristemplate,
				BTEqualStrategyNumber, F_BOOLEQ,
				BoolGetDatum(inctemplate));

	sscan = systable_beginscan(partRel, PartitionParrelidParlevelParistemplateIndexId, true,
							   SnapshotNow, 3, scankey);
	tuple = systable_getnext(sscan);
	if (HeapTupleIsValid(tuple))
	{
		parOid = HeapTupleGetOid(tuple);
		partDesc = (Form_pg_partition) GETSTRUCT(tuple);

		if (level == 0)
		{
			Assert(parent == InvalidOid);
			Assert(*n == NULL);

			/* handle root part specially */
			*n = palloc0(sizeof(PartitionIndexNode));
			(*n)->paroid = parOid;
			(*n)->parrelid = (*n)->parchildrelid = partDesc->parrelid;
			(*n)->isDefault = false;
		}
		systable_endscan(sscan);
		heap_close(partRel, AccessShareLock);
	}
	else
	{
		systable_endscan(sscan);
		heap_close(partRel, AccessShareLock);
		return;
	}

	/* recurse to fill the children */
	partRuleRel = heap_open(PartitionRuleRelationId, AccessShareLock);

	/* SELECT * FROM pg_partition_rule WHERE paroid = :1 AND parparentrule = :2 */
	ScanKeyInit(&scankey[0],
				Anum_pg_partition_rule_paroid,
				BTEqualStrategyNumber, F_OIDEQ,
				ObjectIdGetDatum(parOid));
	ScanKeyInit(&scankey[1],
				Anum_pg_partition_rule_parparentrule,
				BTEqualStrategyNumber, F_OIDEQ,
				ObjectIdGetDatum(parent));
	sscan = systable_beginscan(partRuleRel, PartitionRuleParoidParparentruleParruleordIndexId, true,
							   SnapshotNow, 2, scankey);
	while (HeapTupleIsValid(tuple = systable_getnext(sscan)))
	{
		PartitionIndexNode *child;
		Form_pg_partition_rule rule_desc = (Form_pg_partition_rule)GETSTRUCT(tuple);

		child = palloc(sizeof(PartitionIndexNode));
		memset(child, 0, sizeof(PartitionIndexNode));
		child->paroid = HeapTupleGetOid(tuple);
		child->parrelid = partDesc->parrelid;
		child->parchildrelid = rule_desc->parchildrelid;

		/* For every node, we keep track of every level at which this node has default partitioning */
		child->isDefault = isDefault;
		child->defaultLevels = defaultLevels;

		/* current part is a default part */
		if (rule_desc->parisdefault)
		{
			child->isDefault = true;
			child->defaultLevels = lappend_int(child->defaultLevels, partDesc->parlevel);
		}

		/* insert child into children */
		(*n)->children = lappend((*n)->children, child);

		getPartitionIndexNode(rootOid, level + 1, HeapTupleGetOid(tuple),
					&child, child->isDefault, child->defaultLevels);
	}

	systable_endscan(sscan);
	heap_close(partRuleRel, AccessShareLock);
}

/*
 * constructIndexHashKey
 *   The index hash key is a string representing the index key,
 *   index predicate, and index exprs
 *
 *   Note, all attnums are mapped to the root.
 */
static char *
constructIndexHashKey(Oid partOid,
			Oid rootOid,
			HeapTuple tup,
			AttrNumber *attMap,
			IndexInfo *ii,
			LogicalIndexType indType)
{
	StringInfoData  buf;
	Expr 		*predExpr = NULL;
	Expr 		*exprsExpr = NULL;

	initStringInfo(&buf);

	/* map the attrnos in the indKey to root part */
	for (int i = 0; i < ii->ii_NumIndexAttrs; i++)
	{
		if (attMap && ii->ii_KeyAttrNumbers[i] != 0)
		{
			ii->ii_KeyAttrNumbers[i] = attMap[(ii->ii_KeyAttrNumbers[i]) - 1];
		}
		appendStringInfo(&buf, "%d", ii->ii_KeyAttrNumbers[i]);
	}

	/* map the attrnos in indPred */
	predExpr = (Expr *)ii->ii_Predicate;

	change_varattnos_of_a_node((Node *)predExpr, attMap);

	appendStringInfo(&buf, "%s", nodeToString(predExpr));

	/* remember mapped predicate */
	ii->ii_Predicate = (List *)predExpr;

	exprsExpr = (Expr *)ii->ii_Expressions;

	change_varattnos_of_a_node((Node *)exprsExpr, attMap);

	appendStringInfo(&buf, "%s", nodeToString(exprsExpr));
	appendStringInfo(&buf, "%d", (int) indType);

	/* remember mapped exprsList */
	ii->ii_Expressions = (List *)exprsExpr;

	return buf.data;
}

/*
 * createIndexHashTables
 *  create the hash tables to hold logical indexes
 */
static void
createIndexHashTables()
{
	MemoryContext	context = NULL;
	HASHCTL		hash_ctl;

	/*
	 * this hash is to identify the logical indexes. 1 logical index corresponds to
	 * multiple physical indexes which have the same indkey + indpred + indexprs
	 */
	memset(&hash_ctl, 0, sizeof(hash_ctl));
	hash_ctl.keysize = sizeof(char *);
	hash_ctl.entrysize = sizeof(PartitionIndexHashEntry);
	hash_ctl.hash = key_string_hash;
	hash_ctl.match = key_string_compare;
	hash_ctl.keycopy = key_string_copy;
	hash_ctl.hcxt = context;
	PartitionIndexHash = hash_create("Partition Index Hash",
				INITIAL_NUM_LOGICAL_INDEXES_ESTIMATE,
				&hash_ctl,
				HASH_ELEM | HASH_FUNCTION |
				HASH_COMPARE | HASH_KEYCOPY |
				HASH_CONTEXT);

	Assert(PartitionIndexHash != NULL);

	/*  this hash is used to hold the logical indexes for easy lookup */
	memset(&hash_ctl, 0, sizeof(hash_ctl));
	hash_ctl.keysize = sizeof(uint32);
	hash_ctl.entrysize = sizeof(LogicalIndexInfoHashEntry);
	hash_ctl.hash = tag_hash;
	hash_ctl.hcxt = context;
	LogicalIndexInfoHash = hash_create("Logical Index Info Hash",
				INITIAL_NUM_LOGICAL_INDEXES_ESTIMATE,
				&hash_ctl,
				HASH_ELEM | HASH_FUNCTION );
	Assert(LogicalIndexInfoHash != NULL);
}

/*
 * recordIndexes
 *   Invoke the recordIndexesOnPart routine on every leaf partition.
 */
static void
recordIndexes(PartitionIndexNode **partIndexTree)
{
	ListCell *lc;
	PartitionIndexNode *partIndexNode = *partIndexTree;

	if (partIndexNode->children)
	{
		foreach (lc, partIndexNode->children)
		{
			PartitionIndexNode *child = (PartitionIndexNode *) lfirst(lc);
			recordIndexes(&child);
		}
	}
	else
		/* at a leaf */
		recordIndexesOnLeafPart(partIndexTree,
					partIndexNode->parchildrelid,
					partIndexNode->parrelid);
}

/*
 * recordIndexesOnLeafPart
 *   Given a part
 * 	- fetch each index on the part from pg_index
 *	- map attnums in index key, index expr, index pred to the root attnums
 *	- insert the logical index into the PartitionIndexHash using the
 *		index key, index exprs, index pred as hash  key.
 *	- fetch the associated logical index id from the hash and record it in the tree.
 *	- insert the logical index into the LogicalIndexInfo Hash using the logical index id
 * 	  as the hash key.
 */
static void
recordIndexesOnLeafPart(PartitionIndexNode **pNodePtr,
			Oid partOid,
			Oid rootOid)
{
	char 				*partIndexHashKey;
	bool 				foundPartIndexHash;
	bool 				foundLogicalIndexHash;
	AttrNumber 			*attmap = NULL;
	struct IndexInfo 		*ii = NULL;
	PartitionIndexHashEntry 	*partIndexHashEntry;
	LogicalIndexInfoHashEntry	*logicalIndexInfoHashEntry;
	PartitionIndexNode		*pNode = *pNodePtr;
	List		   *indexoidlist;
	ListCell	   *lc;

	Relation partRel = heap_open(partOid, AccessShareLock);

	char relstorage = partRel->rd_rel->relstorage;

	heap_close(partRel, AccessShareLock);

	/* fetch each index on part */
	indexoidlist = RelationGetIndexList(partRel);
	foreach(lc, indexoidlist)
	{
		Oid			indexoid = lfirst_oid(lc);
		LogicalIndexType indType = INDTYPE_BITMAP;
		Relation indRel;

		/*
		 * We're holding a lock on the table. We assume that's enough to
		 * prevent concurrent DDL on the index.
		 */
		indRel = index_open(indexoid, NoLock);

		/* for AO and AOCO tables we assume the index is bitmap, for heap partitions
		 * look up the access method from the catalog
		 */
		if (RELSTORAGE_HEAP == relstorage)
		{
			if (BTREE_AM_OID == indRel->rd_rel->relam)
			{
				indType = INDTYPE_BTREE;
			}
		}

		/*
		 * when constructing hash key, we need to map attnums in part indexes
		 * to root attnums. Get the attMap needed for mapping.
		 */
		if (!attmap)
		{
			Relation partRel = heap_open(partOid, AccessShareLock);
			Relation rootRel = heap_open(rootOid, AccessShareLock);

			TupleDesc rootTupDesc = rootRel->rd_att;
			TupleDesc partTupDesc = partRel->rd_att;

			attmap = varattnos_map(partTupDesc, rootTupDesc);

			/* can we close here ? */
			heap_close(partRel, AccessShareLock);
			heap_close(rootRel, AccessShareLock);
		}

		/* populate index info structure */
		ii = populateIndexInfo(indRel);

		index_close(indRel, NoLock);

		/* construct hash key for the index */
		partIndexHashKey = constructIndexHashKey(partOid, rootOid, indRel->rd_indextuple, attmap, ii, indType);

		/* lookup PartitionIndexHash table */
		partIndexHashEntry = (PartitionIndexHashEntry *)hash_search(PartitionIndexHash,
							(void *)partIndexHashKey,
							HASH_ENTER,
							&foundPartIndexHash);

		if (!foundPartIndexHash)
		{
			/* first time seeing this index */
			partIndexHashEntry->key = partIndexHashKey;

			/* assign a logical index id */
			partIndexHashEntry->logicalIndexId = logicalIndexId++;

			/* insert the entry into LogicalIndexInfoHash to keep track of logical indexes */
			logicalIndexInfoHashEntry = (LogicalIndexInfoHashEntry *)hash_search(LogicalIndexInfoHash,
								  (void *)&(partIndexHashEntry->logicalIndexId),
								  HASH_ENTER,
							 	  &foundLogicalIndexHash);

			if (foundLogicalIndexHash)
			{
				/*
				 * we should not find the entry in the logical index hash as this is the first
				 * time we are seeing it
				 */
				ereport(ERROR,
						(errcode(ERRCODE_INTERNAL_ERROR),
						 errmsg("error during BuildLogicalIndexInfo. Found indexrelid \"%d\" in hash",
								indexoid
							 )));
			}

			logicalIndexInfoHashEntry->logicalIndexId = partIndexHashEntry->logicalIndexId;
			logicalIndexInfoHashEntry->logicalIndexOid = indexoid;
			logicalIndexInfoHashEntry->ii = ii;
			logicalIndexInfoHashEntry->partList = NIL;
			logicalIndexInfoHashEntry->defaultPartList = NIL;
			logicalIndexInfoHashEntry->indType = indType;
		}
		else
		{
			/* we can release IndexInfo as we already have the information in the hash */
			if (ii->ii_Expressions)
				pfree(ii->ii_Expressions);
			if (ii->ii_Predicate)
				pfree(ii->ii_Predicate);
			pfree(ii);
		}

		/* update the PartitionIndexNode -> index bitmap */
		pNode->index = bms_add_member(pNode->index, partIndexHashEntry->logicalIndexId);
	}
}

/*
 * collapseIndexes
 *   Walk the PartitionNode tree
 *	- For every node
 *		- If a logical index exists on all the children of the node, record the index
 *	  	  on the node and wipeout the index from the children
 *	- recurse up the tree to the root.
 */
static bool
collapseIndexes(PartitionIndexNode **partitionIndexNode,
			LogicalIndexInfoHashEntry **entry)
{
	ListCell *lc, *lc1;
	PartitionIndexNode *pn = *partitionIndexNode;
	bool exists = TRUE;
	int lid= (*entry)->logicalIndexId;
	int childStatus = TRUE;

	if (pn->children)
	{
		foreach(lc, pn->children)
		{
			PartitionIndexNode *child = (PartitionIndexNode *) lfirst(lc);

			/* not a leaf, so check the children */
			exists = collapseIndexes(&child, entry);

			/* For every logical index we are traversing the WHOLE tree. */
			if (!exists)
			{
				/* there is a child that doesn't have the index */
				childStatus = FALSE;
			}
		}

		if (childStatus)
		{
			/* if index exists on every child, record in the parent */
			pn->index = bms_add_member(pn->index, lid);

			/* remove the index from the children */
			foreach (lc1, pn->children)
			{
				PartitionIndexNode *child = (PartitionIndexNode *) lfirst(lc1);
				bms_del_member(child->index, lid);
			}
		}
	}
	else
	{
		/* a leaf - check if index exists */
		if (!bms_is_member(lid, pn->index))
			exists = FALSE;
	}

	return exists;
}

/*
 * indexParts
 *   Walks the tree of nodes and for each logical index that exists on the node,
 *   records the node (partition id) with the logical index in the hash.
 *   If the logical index exists on a default part, record some additional
 *   information to indentify the specific default part.
 *
 *   This consolidates all the information regarding the logical index in the
 *   hash table. As we exit from the function we have a hash table with an entry
 *   for every logical index
 * 	logical index id -> (logicalIndexOid, IndexInfo, partList, defaultPartList)
 */
static void
indexParts(PartitionIndexNode **np, bool isDefault)
{
	LogicalIndexInfoHashEntry  *entry;
	PartitionIndexNode		   *n = *np;
	bool						found;
	int							x;

	if (!n)
		return;

	x = bms_first_from(n->index, 0);
	while (x >= 0)
	{
		entry = (LogicalIndexInfoHashEntry *) hash_search(LogicalIndexInfoHash,
							  (void *)&x, HASH_FIND, &found);
		if (!found)
		{
			ereport(ERROR,
					(errcode(ERRCODE_INTERNAL_ERROR),
					errmsg("error during BuildLogicalIndexInfo. Index not found \"%d\" in hash",
						   x)));
		}

		if (n->isDefault || isDefault)
		{
			/*
			 * We keep track of the default node in the PartitionIndexNode
			 * tree, since we need to output the defaultLevels information
			 * to the caller.
			 */
			entry->defaultPartList = lappend(entry->defaultPartList, n);
			numIndexesOnDefaultParts++;
		}
		else
			/*
			 * For regular non-default parts we just track the part oid
			 * which will be used to get the part constraint.
			 */
			entry->partList = lappend_oid(entry->partList, n->parchildrelid);

		x = bms_first_from(n->index, x + 1);
	}

	if (n->children)
	{
		ListCell *lc;
		foreach (lc, n->children)
		{
			PartitionIndexNode *child = (PartitionIndexNode *) lfirst(lc);
			indexParts(&child, n->isDefault);
		}
	}
}

/*
 * getPartConstraints
 *   Given an OID, returns a Node that represents all the check constraints
 *   on the table AND'd together, only if these constraints cover the keys in
 *   the given list. Otherwise, it returns NULL
 */
static Node *
getPartConstraints(Oid partOid, Oid rootOid, List *partKey)
{
	ScanKeyData scankey;
	SysScanDesc sscan;
	Relation        conRel;
	HeapTuple       conTup;
	Node            *conExpr;
	Node            *result = NULL;
	Datum           conBinDatum;
	Datum			conKeyDatum;
	char            *conBin;
	bool            conbinIsNull = false;
	bool			conKeyIsNull = false;
	AttrMap		*map;

	/* create the map needed for mapping attnums */
	Relation rootRel = heap_open(rootOid, AccessShareLock);
	Relation partRel = heap_open(partOid, AccessShareLock);

	map_part_attrs(partRel, rootRel, &map, false);

	heap_close(rootRel, AccessShareLock);
	heap_close(partRel, AccessShareLock);

	/* Fetch the pg_constraint row. */
	conRel = heap_open(ConstraintRelationId, AccessShareLock);

	ScanKeyInit(&scankey,
				Anum_pg_constraint_conrelid,
				BTEqualStrategyNumber, F_OIDEQ,
				ObjectIdGetDatum(partOid));
	sscan = systable_beginscan(conRel, ConstraintRelidIndexId, true,
							   SnapshotNow, 1, &scankey);

	// list of keys referenced in the found constraints
	List *keys = NIL;

	while (HeapTupleIsValid(conTup = systable_getnext(sscan)))
	{
		/* we defer the filter on contype to here in order to take advantage of
		 * the index on conrelid */
		Form_pg_constraint conEntry = (Form_pg_constraint) GETSTRUCT(conTup);
		if (conEntry->contype != 'c')
		{
			continue;
		}
		/* Fetch the constraint expression in parsetree form */
		conBinDatum = heap_getattr(conTup, Anum_pg_constraint_conbin,
				RelationGetDescr(conRel), &conbinIsNull);

		Assert (!conbinIsNull);
		/* map the attnums in constraint expression to root attnums */
		conBin = TextDatumGetCString(conBinDatum);
		conExpr = stringToNode(conBin);
		conExpr = attrMapExpr(map, conExpr);

		if (result)
			result = (Node *)make_andclause(list_make2(result, conExpr));
		else
			result = conExpr;

		// fetch the key associated with this constraint
		conKeyDatum = heap_getattr(conTup, Anum_pg_constraint_conkey,
				RelationGetDescr(conRel), &conKeyIsNull);
		Datum *dats = NULL;
		int numKeys = 0;

		// extract key elements
		deconstruct_array(DatumGetArrayTypeP(conKeyDatum), INT2OID, 2, true, 's', &dats, NULL, &numKeys);
		for (int i = 0; i < numKeys; i++)
		{
			int16 key_elem =  DatumGetInt16(dats[i]);
			keys = lappend_int(keys, key_elem);
		}
	}

	systable_endscan(sscan);
	heap_close(conRel, AccessShareLock);

	ListCell *lc = NULL;
	foreach (lc, partKey)
	{
		int partKeyCol = lfirst_int(lc);

		if (!list_member_int(keys, partKeyCol))
		{
			// passed in key is not found in the constraint. return NULL
			if (NULL != result)
			{
				pfree(result);
			}

			result = NULL;
			break;
		}
	}

	if (map)
	{
		pfree(map);
	}
	list_free(keys);
	return result;
}

/*
 * get_relation_part_constraints
 *  return the part constraints for a partitioned table given the oid of the root
 */
Node *
get_relation_part_constraints(Oid rootOid, List **defaultLevels)
{
	if (!rel_is_partitioned(rootOid))
	{
		return NULL;
	}

	// get number of partitioning levels
	List *partkeys = rel_partition_keys_ordered(rootOid);
	int nLevels = list_length(partkeys);

	Node *allCons = NULL;
	for (int level = 0; level < nLevels; level++)
	{
		List *partKey = (List *) list_nth(partkeys, level);

		PartitionNode *pn = get_parts(rootOid, level, 0 /*parent*/, false /* inctemplate */, false /*includesubparts*/);

		Assert(NULL != pn);
		List *partOids = all_partition_relids(pn);

		Node *partCons = NULL;
		ListCell *lc = NULL;
		foreach(lc, partOids)
		{
			Oid partOid = lfirst_oid(lc);
			// fetch part constraint mapped to root
			partCons = getPartConstraints(partOid, rootOid, partKey);

			if (NULL == partCons)
			{
				// default partition has NULL constriant in GPDB's catalog
				*defaultLevels = lappend_int(*defaultLevels, level);
				continue;
			}

			// OR them to current constraints
			if (NULL == allCons)
			{
				allCons = partCons;
			}
			else
			{
				allCons = (Node *) mergeIntervals(allCons, partCons);
			}
		}
	}

	if (NULL == allCons)
	{
		allCons = makeBoolConst(false /*value*/, false /*isnull*/);
	}

	list_free(partkeys);
	return allCons;
}

/*
 * populateIndexInfo
 *  Populate the IndexInfo structure with the information from pg_index tuple.
 */
static IndexInfo *
populateIndexInfo(Relation indRel)
{
	IndexInfo 	*ii;

 	/*
	 * We could just call existing BuildIndexInfo here. But BuildIndexInfo needs to open each index,
 	 * and populate the relcache entry for the index relation. We can get the information by
	 * just looking into pg_index tuple.
	 */
	ii = makeNode(IndexInfo);

	ii->ii_Unique = indRel->rd_index->indisunique;
	ii->ii_NumIndexAttrs = indRel->rd_index->indnatts;

	for (int i = 0; i < indRel->rd_index->indnatts; i++)
	{
		ii->ii_KeyAttrNumbers[i] = indRel->rd_index->indkey.values[i];
	}

	ii->ii_Expressions = RelationGetIndexExpressions(indRel);
	ii->ii_Predicate = RelationGetIndexPredicate(indRel);

	return ii;
}

/*
 * generateLogicalIndexPred
 *  generate the partial index predicate associated with each logical index.
 *  The predicate is generated by OR'ing the constraints of all parts on which the logical
 *  index exists.
 */
static void
generateLogicalIndexPred(LogicalIndexes *li,
				int *curIdx,
				LogicalIndexInfoHashEntry *entry,
				Oid root,
				int *numLogicalIndexes)
{
	Node            *conList;
	ListCell *lc;
	AttrNumber	*indexKeys;

	if (list_length(entry->partList) > 0)
	{
		/* populate the index information */
		li->logicalIndexInfo[*curIdx]->partCons = NULL;
		li->logicalIndexInfo[*curIdx]->logicalIndexOid = entry->logicalIndexOid;
		li->logicalIndexInfo[*curIdx]->nColumns = entry->ii->ii_NumIndexAttrs;
		indexKeys = palloc(sizeof(AttrNumber) * entry->ii->ii_NumIndexAttrs);
		memcpy((char *)indexKeys,
				&(entry->ii->ii_KeyAttrNumbers), sizeof(AttrNumber) * entry->ii->ii_NumIndexAttrs);
		li->logicalIndexInfo[*curIdx]->indexKeys = indexKeys;
		li->logicalIndexInfo[*curIdx]->indExprs = (List *)copyObject(entry->ii->ii_Expressions);
		li->logicalIndexInfo[*curIdx]->indPred = (List *)copyObject(entry->ii->ii_Predicate);
		li->logicalIndexInfo[*curIdx]->indIsUnique = entry->ii->ii_Unique;
		li->logicalIndexInfo[*curIdx]->indType = entry->indType;

		/* fetch the partList from the logical index hash entry */
		foreach(lc, entry->partList)
		{
			Oid partOid = lfirst_oid(lc);

			if (partOid != root)
			{
				/* fetch part constraint mapped to root */
				conList = getPartConstraints(partOid, root, NIL /*partKey*/);

				/* OR them to current constraints */
				if (li->logicalIndexInfo[*curIdx]->partCons)
				{
					li->logicalIndexInfo[*curIdx]->partCons = mergeIntervals(li->logicalIndexInfo[*curIdx]->partCons, conList);
				}
				else
				{
					li->logicalIndexInfo[*curIdx]->partCons = conList;
				}
			}
		}

		(*curIdx)++;
		(*numLogicalIndexes)++;
	}

	/* from the hash entry, fetch the defaultPartList */
	foreach(lc, entry->defaultPartList)
	{
		PartitionIndexNode *node = (PartitionIndexNode *)lfirst(lc);
		AttrNumber *indexKeys;

		li->logicalIndexInfo[*curIdx]->partCons = NULL;
		li->logicalIndexInfo[*curIdx]->logicalIndexOid = entry->logicalIndexOid;
		li->logicalIndexInfo[*curIdx]->nColumns = entry->ii->ii_NumIndexAttrs;
		indexKeys = palloc(sizeof(AttrNumber) * entry->ii->ii_NumIndexAttrs);
		memcpy((char *)indexKeys,
			&(entry->ii->ii_KeyAttrNumbers), sizeof(AttrNumber) * entry->ii->ii_NumIndexAttrs);
		li->logicalIndexInfo[*curIdx]->indexKeys = indexKeys;
		li->logicalIndexInfo[*curIdx]->indExprs = (List *)copyObject(entry->ii->ii_Expressions);
		li->logicalIndexInfo[*curIdx]->indPred = (List *)copyObject(entry->ii->ii_Predicate);
		li->logicalIndexInfo[*curIdx]->indIsUnique = entry->ii->ii_Unique;
		li->logicalIndexInfo[*curIdx]->indType = entry->indType;

		/*
		 * Default parts don't have constraints, so they cannot be represented
		 * as part of the partial index predicate.
		 *
		 * Instead each index on a default part is represented as a different logical
		 * index. Since we need a way to identify the specific default part, we include
		 * the defaultLevels information, in addition to ANY constraint on the default
		 * part.
		 */
		li->logicalIndexInfo[*curIdx]->partCons = getPartConstraints(node->parchildrelid, root, NIL /*partKey*/);

		/* get the level on which partitioning key is default */
		li->logicalIndexInfo[*curIdx]->defaultLevels = list_copy(node->defaultLevels);
		(*curIdx)++;
		(*numLogicalIndexes)++;
	}
}

/*
 * createPartsIndexResult
 *  Populate the result array of logical indexes. Most of the information needed
 *  is in the IndexInfoHash. The partial index predicate needs to be generated
 *  by a call to generateLogicalIndexPred.
 */
static LogicalIndexes *
createPartsIndexResult(Oid root)
{
	HASH_SEQ_STATUS hash_seq;
	int numResultRows = 0;
	LogicalIndexes *li;
	LogicalIndexInfoHashEntry *entry;

	hash_seq_init(&hash_seq, LogicalIndexInfoHash);

	/*
	 * we allocate space for twice the number of logical indexes.
	 * this is because, every index on a default part will be
	 * returned as a separate index.
	 */
	numResultRows = numLogicalIndexes + numIndexesOnDefaultParts;

	li = (LogicalIndexes *) palloc0(sizeof(LogicalIndexes));

	li->numLogicalIndexes = 0;
	li->logicalIndexInfo = NULL;

	li->logicalIndexInfo = (LogicalIndexInfo **)palloc0(numResultRows * sizeof(LogicalIndexInfo *));

	/* should we limit the amount of memory being allocated here ? */
	for (int i=0; i < numResultRows; i++)
		li->logicalIndexInfo[i] = (LogicalIndexInfo *)palloc0(sizeof(LogicalIndexInfo));

	int curIdx = 0;

	/* for each logical index, get the part constraints as partial index predicates */
	while ((entry = hash_seq_search(&hash_seq)))
	{
		generateLogicalIndexPred(li, &curIdx, entry, root, &li->numLogicalIndexes);
	}

	return li;
}

/*
 * getPhysicalIndexRelid
 *   This function returns the physical index relid corresponding
 *   to the index described by the logicalIndexInfo input structure
 *   in the relation identified by the partOid.
 *   The 1st matching index is returned.
 *
 * NOTE: index attnums in the provided logicalIndexInfo input structure
 * have to be mapped to the root.
 */
Oid
getPhysicalIndexRelid(Relation partRel, LogicalIndexInfo *iInfo)
{
	Oid             resultOid = InvalidOid;
	bool		indKeyEqual;
	List	   *indexoidlist;
	ListCell   *lc;
	Relation	indRel = NULL;

	/* fetch each index on partition */
	indexoidlist = RelationGetIndexList(partRel);
	foreach(lc, indexoidlist)
	{
		Oid			indexoid = lfirst_oid(lc);
		Form_pg_index indForm;

		if (indRel)
			index_close(indRel, NoLock);

		/*
		 * We're holding a lock on the table. We assume that's enough to
		 * prevent concurrent DDL on the index.
		 */
		indRel = index_open(indexoid, NoLock);
		indForm = indRel->rd_index;

		if (indForm->indnatts != iInfo->nColumns)
			continue;

		/* compare indKey */
		indKeyEqual = true;
		for (int i = 0; i < indForm->indnatts; i++)
		{
			if (indForm->indkey.values[i] != iInfo->indexKeys[i])
			{
				indKeyEqual = false;
				break;
			}
		}

		if (!indKeyEqual)
			continue;

		/* compare uniqueness attribute */
		if (iInfo->indIsUnique != indForm->indisunique)
			continue;

		/* compare indPred */
		List *indPred = RelationGetIndexPredicate(indRel);
		if (!equal(iInfo->indPred, indPred))
			continue;
		list_free(indPred);

		/* compare indExprs */
		List *indExprs = RelationGetIndexExpressions(indRel);
		if (equal(iInfo->indExprs, indExprs))
		{
			/* found matching index */
			resultOid = indForm->indexrelid;
			break;
		}
		list_free(indExprs);

		// TODO: antova - Mar 28, 2014; compare if this is a bitmap index
	}

	if (indRel)
		index_close(indRel, NoLock);

	return resultOid;
}

/*
 * dumpPartsIndexInfo
 *   print debugging info
 */
static void
dumpPartsIndexInfo(PartitionIndexNode *n, int level)
{
	ListCell 	   *lc;
	StringInfoData	logicalIndexes;
	int				x;

	initStringInfo(&logicalIndexes);

	if (!n)
		return;

	for (int i = 0; i <= level; i++)
		appendStringInfo(&logicalIndexes, "%s", "   ");

	appendStringInfo(&logicalIndexes, "%d ", n->parchildrelid);

	x = bms_first_from(n->index, 0);
	appendStringInfo(&logicalIndexes, "%s ", " (");

	while (x >= 0)
	{
		appendStringInfo(&logicalIndexes, "%d ", x);
		x = bms_first_from(n->index, x + 1);
	}

	appendStringInfo(&logicalIndexes, "%s ", " )");

	elog(DEBUG5, "%s", logicalIndexes.data);

	if (n->children)
	{
		foreach (lc, n->children)
		{
			PartitionIndexNode *child = (PartitionIndexNode *) lfirst(lc);
			dumpPartsIndexInfo(child, level+1);
			appendStringInfo(&logicalIndexes, "     ");
		}
	}
}

/*
 * 	mergeIntervals
 *   merge the two intervals by creating a disjunction of the given intervals, or collapsing
 *   them into one interval when possible
 *
 *   This function's arguments represent two range constraints, which the function attempts
 *   to collapse into one if they share a common boundary. If no collapse is possible,
 *   the function returns a disjunction of the two intervals.
 */
static Node *
mergeIntervals(Node *intervalFst, Node *intervalSnd)
{
	Node *pnodeStart1 = NULL;
	Node *pnodeEnd1 = NULL;
	Node *pnodeStart2 = NULL;
	Node *pnodeEnd2 = NULL;

	extractStartEndRange(intervalFst, &pnodeStart1, &pnodeEnd1);
	extractStartEndRange(intervalSnd, &pnodeStart2, &pnodeEnd2);

	if (NULL != pnodeEnd1 && NULL != pnodeStart2)
	{
		OpExpr *opexprEnd1 = (OpExpr *) pnodeEnd1;
		OpExpr *opexprStart2 = (OpExpr *) pnodeStart2;
		Var *pvarEnd1 = NULL;
		Var *pvarStart2 = NULL;
		Const *pconstEnd1 = NULL;
		Const *pconstStart2 = NULL;
		Oid opnoEnd1 = InvalidOid;
		Oid opnoStart2 = InvalidOid;

		/* extract boundaries of the two intervals */
		extractOpExprComponents(opexprEnd1, &pvarEnd1, &pconstEnd1, &opnoEnd1);
		extractOpExprComponents(opexprStart2, &pvarStart2, &pconstStart2, &opnoStart2);
		if (InvalidOid != opnoEnd1 && InvalidOid != opnoStart2 &&
			equal(pvarEnd1, pvarStart2) && equal(pconstEnd1, pconstStart2) && /* middle point is the same */
			opnoEnd1 == get_negator(opnoStart2) /* this guaranteed that the middle point is included in exactly 1 of the intervals */
			)
		{
			if (NULL != pnodeStart1 && NULL != pnodeEnd2)
			{
				/* merge intervals of the form (x,y), [y, z) into (x,z) */
				return (Node *) make_andclause(list_make2(pnodeStart1, pnodeEnd2));
			}

			if (NULL != pnodeStart1)
			{
				/* merge intervals of the form (x,y), [y, inf) into (x, inf) */
				Var *pvarStart1 = NULL;
				Const *pconstStart1 = NULL;
				Oid opnoStart1 = InvalidOid;
				OpExpr *opexprStart1 = (OpExpr *) pnodeStart1;
				extractOpExprComponents(opexprStart1, &pvarStart1, &pconstStart1, &opnoStart1);

				return (Node *) make_opclause(opnoStart1, opexprStart1->opresulttype, opexprStart1->opretset, (Expr *) pvarStart1, (Expr *) pconstStart1);
			}

			if (NULL != pnodeEnd2)
			{
				/* merge intervals of the form (-inf,x), [x, y) into (-inf, y) */
				Var *pvarEnd2 = NULL;
				Const *pconstEnd2 = NULL;
				Oid opnoEnd2 = InvalidOid;
				OpExpr *opexprEnd2 = (OpExpr *) pnodeEnd2;

				extractOpExprComponents(opexprEnd2, &pvarEnd2, &pconstEnd2, &opnoEnd2);

				return (Node *) make_opclause(opnoEnd2, opexprEnd2->opresulttype, opexprEnd2->opretset, (Expr *) pvarEnd2, (Expr *) pconstEnd2);
			}

			Assert(NULL == pnodeStart1 && NULL == pnodeEnd2);

			/* merge (-inf, x), [x,inf) into true */

			return (Node *) makeBoolConst(true /*value*/, false /*isnull*/);
		}
	}
	return (Node *) make_orclause(list_make2(intervalFst, intervalSnd));
}

/*
 * extractStartEndRange
 *   Given an expression representing an interval constraint, extract the expressions defining the interval's start and end
 */
static void extractStartEndRange(Node *clause, Node **ppnodeStart, Node **ppnodeEnd)
{
	if (IsA(clause, OpExpr))
	{
		OpExpr *opexpr = (OpExpr *) clause;
		Expr *pexprLeft = list_nth(opexpr->args, 0);
		Expr *pexprRight = list_nth(opexpr->args, 1);
		CmpType cmptype = get_comparison_type(opexpr->opno, exprType((Node *) pexprLeft), exprType((Node *) pexprRight));

		if (CmptEq == cmptype)
		{
			*ppnodeStart = *ppnodeEnd = clause;
			return;
		}

		if ((CmptLEq == cmptype || CmptLT == cmptype) && IsA(pexprRight, Const))
		{
			/* op expr of the form pk <= Const or pk < Const */
			*ppnodeStart = NULL;
			*ppnodeEnd = clause;
			return;
		}

		if ((CmptGEq == cmptype || CmptGT == cmptype) && IsA(pexprRight, Const))
		{
			/* op expr of the form pk >= Const or pk > Const */
			*ppnodeEnd = NULL;
			*ppnodeStart = clause;
			return;
		}
	}

	/* only expressions of the form x > C1 and x < C2 supported: ignore all other expression types */

	if (!IsA(clause, BoolExpr) ||
			AND_EXPR != ((BoolExpr *) clause)->boolop ||
			2 < list_length(((BoolExpr *) clause)->args))
	{
		return;
	}

	BoolExpr *bool_expr = (BoolExpr *) clause;

	Node *nodeStart = list_nth(bool_expr->args, 0);
	Node *nodeEnd = list_nth(bool_expr->args, 1);

	if (!IsA(nodeStart, OpExpr) || !IsA(nodeEnd, OpExpr))
	{
		return;
	}

	OpExpr *opexprStart = (OpExpr *) nodeStart;
	OpExpr *opexprEnd = (OpExpr *) nodeEnd;

	CmpType cmptLeft = get_comparison_type(opexprStart->opno, exprType(list_nth(opexprStart->args, 0)), exprType(list_nth(opexprStart->args, 1)));
	CmpType cmptRight = get_comparison_type(opexprEnd->opno, exprType(list_nth(opexprEnd->args, 0)), exprType(list_nth(opexprEnd->args, 1)));

	if ((CmptGT != cmptLeft && CmptGEq != cmptLeft) || (CmptLT != cmptRight && CmptLEq != cmptRight))
	{
		return;
	}

	*ppnodeStart = nodeStart;
	*ppnodeEnd = nodeEnd;
}

/*
 * extractOpExprComponents
 *   for an opexpr of type Var op Const, extract its components
 */
static void extractOpExprComponents(OpExpr *opexpr, Var **ppvar, Const **ppconst, Oid *opno)
{
	Node *pnodeLeft = list_nth(opexpr->args, 0);
	Node *pnodeRight = list_nth(opexpr->args, 1);
	if (IsA(pnodeLeft, Var) && IsA(pnodeRight, Const))
	{
		*ppvar = (Var *) pnodeLeft;
		*ppconst = (Const *) pnodeRight;
		*opno = opexpr->opno;
	}
	else if (IsA(pnodeLeft, Const) && IsA(pnodeRight, Var) && InvalidOid != get_commutator(opexpr->opno))
	{
		*ppvar = (Var *) pnodeRight;
		*ppconst = (Const *) pnodeLeft;
		*opno = get_commutator(opexpr->opno);
	}
}

/*
 * LogicalIndexInfoForIndexOid
 *   construct the logical index info for a given index oid
 */
LogicalIndexInfo *
logicalIndexInfoForIndexOid(Oid rootOid, Oid indexOid)
{
	Relation	indRel;

	indRel = index_open(indexOid, AccessShareLock);

	IndexInfo *pindexInfo = populateIndexInfo(indRel);
	Oid partOid = indRel->rd_index->indrelid;

	// remap attributes
	Relation rootRel = heap_open(rootOid, AccessShareLock);
	Relation partRel = heap_open(partOid, AccessShareLock);

	TupleDesc rootTupDesc = rootRel->rd_att;
	TupleDesc partTupDesc = partRel->rd_att;

	char relstorage = partRel->rd_rel->relstorage;
	AttrNumber	*attMap = varattnos_map(rootTupDesc, partTupDesc);
	heap_close(rootRel, AccessShareLock);
	heap_close(partRel, AccessShareLock);

	// populate the index information
	LogicalIndexInfo *plogicalIndexInfo = (LogicalIndexInfo *) palloc0(sizeof(LogicalIndexInfo));
	plogicalIndexInfo->nColumns = pindexInfo->ii_NumIndexAttrs;
	plogicalIndexInfo->indIsUnique = pindexInfo->ii_Unique;
	plogicalIndexInfo->logicalIndexOid = indexOid;

	int numIndexKeys = pindexInfo->ii_NumIndexAttrs;
	plogicalIndexInfo->indexKeys = palloc(sizeof(AttrNumber) * numIndexKeys);
	memcpy((char *)plogicalIndexInfo->indexKeys, &(pindexInfo->ii_KeyAttrNumbers), sizeof(AttrNumber) * numIndexKeys);

	plogicalIndexInfo->indExprs = copyObject(pindexInfo->ii_Expressions);
	plogicalIndexInfo->indPred = copyObject(pindexInfo->ii_Predicate);

	/* remap expression fields */
	/* map the attrnos if necessary */
	if (attMap)
	{
		for (int i = 0; i < plogicalIndexInfo->nColumns; i++)
		{
			if (plogicalIndexInfo->indexKeys[i] != 0)
			{
				plogicalIndexInfo->indexKeys[i] = attMap[(plogicalIndexInfo->indexKeys[i]) - 1];
			}
		}
		change_varattnos_of_a_node((Node *) plogicalIndexInfo->indExprs, attMap);
		change_varattnos_of_a_node((Node *) plogicalIndexInfo->indPred, attMap);
	}

	plogicalIndexInfo->indType = INDTYPE_BITMAP;
	if (RELSTORAGE_HEAP == relstorage)
	{
		if (BTREE_AM_OID == indRel->rd_rel->relam)
		{
			plogicalIndexInfo->indType = INDTYPE_BTREE;
		}
	}

	index_close(indRel, AccessShareLock);

	return plogicalIndexInfo;
}


text:
The Crowdfunding Agency - Empower tabletop games creators and support their crowdfunding campaigns
© 2023 The Crowdfunding Agency – Empower tabletop games creators and support their crowdfunding campaigns
The Crowdfunding Agency is a uniquely set-up service whose mission is to empower games related projects creators and support their crowdfunding campaigns from its preparation to the rewards delivery, leveraging our team's experience in this exercise, mitigating the risks for the backers, and maximising the opportunity for the creators.
In order to match your needs, we offer two options to support you:
Consulting: The agency advises you on various strategic key points of the campaign.
Campaign management: The agency is involved in the creation and management of the campaign, before, during and even after, according to your needs.
For each project, and after studying the information about your project, the agency reserves the right to accept or not your request for consulting or campaign management.
The agency does not manage the campaign, but supports the partner through a consulting mission on a daily rate basis, dividing the time budget according to your needs, before, during and after the campaign. For a majority of the campaigns that have opted for this formula, the agency manages to provide the required support within two days of consulting.
Topics on which the agency can work on a consulting mission
Campaign strategy (rewards, stretch goals, financial goal, animation of the campaign…),
Campaign page texts and illustrations,
Video content,
Marketing strategy,
Communication content review (publications on social networks, newsletters…),
Community management during the campaign (how to answer particular comments),
Updates content,
Pledge management/Late pledge tool.
Consulting rates (Flat fees)
The agency provides you with a quote based on your needs, including a number of days/person.
Rate: EUR 1,000 per day/person
The agency is involved in the creation and management of the campaign, before, during and even after, depending on your needs.
Topics on which the agency can work on a campaign management mission
Creation of the campaign page
Writing of the campaign page,
Management of the illustrations creation for the campaign page*,
Management of the video creation*.
Media/Influencers contact,
Social networks Community management,
Newsletters creation and sending,
Community forums (BGG) community management,
Campaign page community management (comments),
Ads management (banner ads, social networks ads)*,
Writing updates during the campaign.
Campaign follow-up
Writing updates after the campaign,
Setting up the Pledge management/Late pledge tool.
*The external costs (graphics creation, video creation, ads budget) are supported by the publisher.
Campaign management rates (Flat fees + Profit-sharing)
The agency provides you with a quote based on your needs, including a number of days/person, for the work done before and during the campaign. The work done after the campaign will follow the same rate, but a new quote will be provided.
To the amount paid for the work done by the agency before and during the campaign will be added a profit-sharing formula, which is a percentage of the net amount raised by the campaign.
By remunerating the agency partly based on the success of the campaign, the interests of both parties are aligned to make the campaign as successful as possible.
The fixed cost, estimated in the quote (work done by the agency before and during the campaign), is guaranteed for the agency on a EUR 400 day/person basis,
Profit-sharing formula corresponding to 5 to 8% of the amount raised during the campaign (depending on the scope of the action of the agency), which will be added to the fixed cost.
Post-campaign mission on the basis of EUR 400 days/person.
Fill out this form which will collect all the information we need to get back to you with an offer that meets your needs. We look forward to learning more about your project!
Facebook Twitter Discord

redpajama_set_name: RedPajamaCommonCrawl


SKU: PB0405201846. Category: Potli Bag. Tags: Beaded Potli Bags, Birthday Return Gifts Bag, Bridal Potli Bags, Brocade Potli Bag, Dry Fruit Potlis, Favor Indian Gift Bag, Gifting Potli Bags, Hand Potli Bags, Ladies Potli Bag, Marriage Gift Bag, Potli Bag For Bridal, Potli Bags, Potli Purse, Potlis, Return Gifts for Mehndi Function.
Potli Bag We are Manufacturer & Supplier, Exporter of Beaded HandBag for Wedding Gifts, We are Basically situated in New Delhi India & Operate thought the World. We came the wide array of Highly Beautiful Handicrafts in India Made by skilled and Professionally team.


Wolves chasing prey over cliffs ..
2 recent massacres in France bring this hunting technique to mind ..
.. wild ungulates driven by wolves or cattle and sheep harassed until they break their electric fences and flee; pursued towards a cliff.
* 53 sheep victims to wolves in the Mercantour National Park, some of which jumped from a rock face.
This is a well known wolves' hunting tactic depicted by the highly respected and internationally known authority on wolves – professor Dr. Bibikov.
Excerpt from "The Wolf" Professor Dr. Bibikov. Published by Nauka publishers Moscow 1985.
This is not uncommon on livestock in France and is known in the US.
A spectacular pile up occurred in Idaho in 2013 where 176 sheep perished.
This is not to be confused with another hunting phenomenon called "surplus killing".
Over 80 sheep killed in France, June 2014, strewn among the woods, taking over a fortnight to count.
First – Sheep lifted by helicopter after being pursued by wolves over the side of a ravine.
Second Photo: Sheep piled up after being pushed over a rock face.


A fervent film buff, Beverley knows a winning performance and she also knows how to direct one in environmental design, excelling in all aspects, from retail to signage and wayfinding. She single-handedly manages projects and organizes scheduling in our bustling environmental department.
Beverley's extensive experience enables her to troubleshoot potential pitfalls and consistently direct every project toward a successful result, and her tremendous attention to detail ensures a project's initial vision is fully realized.
Focused and resourceful, she directs the progress of each retail project from conception through to implementation. She works closely with our graphics department to seamlessly integrate a project's brand strategy within its retail environment to guarantee a consistent message and a cohesive look and feel. Clients include TD Bank Group, Toronto Blue Jays, OfficeMax, Seneca College and Tim Hortons.


In orthodox Christianity Jesus is regarded as the Divine Son and Second Person of the Trinity; nothing less than God. Theologians – referring to those who presume to speak authoritatively about God (logos, the study of or talk about theos, god) – have ensconced him fully inside their doctrinal systems.
Over the centuries believers have witnessed to direct encounters with Jesus himself, but theologians are typically cautious when it comes to validating their authenticity. How can you recognize someone you've never met?
This point should not be dismissed too quickly. None of us today has a personal memory of meeting the historical Jesus, so the recognition must be based on popular depictions (like the gorgeous wavy-haired European Jesus in a Warner Sallman painting) or a conception more symptomatic of our individual and cultural biases. Maybe you saw the scars in his hands and feet. But then again, thousands in history besides Jesus have been crucified, so how can you know for sure?
The Jesus of orthodox theology is not the same Jesus who came from Nazareth, who lived and died in the first century. Archaeologists and historians are more helpful when it comes to clarifying our picture of what that Jesus may have been like.
But what about the New Testament Gospels? An internal comparison of the narratives themselves shows them to be more myth than history. I don't mean this as an excuse to ignore what they have to say or relegate them to nothing more than Palestinian fairy tales.
These Gospel narratives were composed after the death of Jesus but before the dogma-machine of Christian orthodoxy got underway. They are not exercises in theology as much as productions in mythology, stories told as meditations on Jesus as a symbol of God. Not Jesus as God as later theologians would insist, but on Jesus as a threshold figure linking the realm of everyday life to the present mystery of reality, beyond names and forms.
Not one of the New Testament authors had known Jesus personally.
The traditional appellations of "Matthew" (a disciple of Jesus) "Mark" (an assistant of the apostle Paul) "Luke" (a disciple and biographer of Paul) and "John" (another disciple of Jesus) were added later. Their contribution was to collect and invent stories that featured Jesus as one who mediated for others an experience of spirit, but who could now only be remembered, not encountered. Even Paul, writing perhaps 15 to 20 years prior to the earliest Gospel (Mark c. 70 CE), had never met the historical Jesus.
Since they lived in closer proximity in time and place to where Jesus had been alive, the New Testament storytellers could depict him with greater realism than can a twenty-first century North American believer. Consequently those stories have seemed more like historical accounts to us than sacred fiction. Add to that our modern prejudice against fiction generally, which regards it as more fantasy than truth, and it's no wonder that so many Christians (and others) read the Gospels as history.
This gives me an opportunity to reach back to a couple recent posts in this blog of mine, published under the general title "Idols of Orthodoxy." There I offered a way of interpreting symbols – not mathematical or roadside symbols, but specifically symbolic objects like national flags, wedding rings, religious icons, and the human figure of Jesus.
A symbol in this sense will always have a tangible (i.e., sensory-physical) aspect – colored patterns on cloth; a band of precious metal; a portrait in stone, wood, or paint; or the body and behavior of a living person.
Who the historical Jesus was, what he said and did, and the effect he had on his contemporaries – some of whom felt arrested and transformed in his presence, others who conspired in his arrest and execution for rousing the rabble – are what the Gospel writers attempted to render in their mythological depictions of him. Again, they hadn't actually been there, but they tried to capture his influence by placing their fictional subject within a constellation of mythological themes, heroic characters, and revealing episodes.
Thus Jesus the symbol of God became the Second Adam, a New Moses, the son of David, Suffering Servant, Lamb of God, and Word-made-flesh. By wrapping Jesus into this web of myth, they attempted to re-present him to their contemporary audiences, labeling and linking him to ideas then current in the way people characterized the transcendent mystery or Spirit of God. Under none of those titles was Jesus understood to be equal with God in any straightforward sense (which is our working definition of idolatry).
What we have in the early centuries of Christianity, then, is a progression – forward movement but not necessarily improvement – from the historical figure of Jesus, into the contemplation of Jesus as a symbol of God, and arriving finally in a theological orthodoxy that effectively ignores Jesus by making him God.
The paradoxical tension of the second phase (New Testament mythology) has snapped, leaving us with a deity out of this world – but coming soon! – and a Jesus long gone and all but forgotten.
As my diagram shows, the second-phase storytellers inserted what we might call transitional mechanisms into their narratives in order to get Jesus out of the historical past and into their contemplative present (in the episode of his resurrection), and then later (with the ascension) into his identification with God.
By rotating the diagram 90° to the left we thus have the phenomenology of symbol perfectly illustrated: the (once-) tangible Jesus of history, the symbol in whom both human and divine are paradoxically united, and the transcendent mystery beyond name and form – although theologians are famously reluctant to admit it.
As a few early Christian theologians (particularly the so-called Cappadocian Fathers: Basil the Great, his brother Gregory of Nyssa, and their close friend Gregory of Nazianzus) were bending logic in their contemplation on Jesus as a symbol of God – "fully divine, fully human, neither separate nor confused" – the emperor Constantine was urging his new kingdom of bishops to make a decision for one side or the other.
The council decided in favor of making Jesus into God. And now he is nowhere to be found.


Who uses the WHOOP strap.
Why if you're a hard charger you should probably be wearing one.
Some fun stories about the WHOOP.
In this podcast AJ Baker and I talk about how the idea for the WHOOP started, and how it took about 4 years for the idea to turn into a wearable device.
We talk about what AJ does within WHOOP, and the type of people that work at WHOOP that make it the fun company that it is today.
AJ talks about how some of the most popular athletes that have used WHOOP are LeBron James, and Michael Phelps, as well as top CrossFitter Sam Dancer.
We also discuss how wearing the WHOOP strap is changing the way athletes look at their recovery, and how often they need to be training to get maximal results.
It's interesting, more often than not, it's seem like athletes are learning that they don't need to be training as much as they thought to get maximal results.
Or that if they have a high recovery day, they should add extra to that day, but step back on the days where their recovery isn't as high.
In the interview we talk about the sensors that WHOOP uses to gather all of the data to give you a recovery score, sleep tracking, and strain number.
At the end of the day I hope that you listen to this podcast, and learn how the WHOOP strap can improve your performance, and make you an all around healthier person!
You can also checkout my WHOOP product review by clicking here.


has been a member since May 2011 and goes by Smck.
I am a photographer currently residing in St Louis, MO. I love taking pictures of everything. Comments and criticism are always welcome so tell me what you think.


1 Alvissa: Well I think we should go on this quest.
2 Mordekai: And what's that?
4 Kyros: Let's do it!
4 Lambert: Hey, no-one digs Elijah!
Of course, if I keep it realistic and they're like most RPG characters, they can keep going for quite a while yet.
2013-07-13 Rerun commentary: More prescient words were never said.
These early Fantasy strips were made about the time that the Lord of the Rings movies were being released, so they were still very fresh in everyone's memories.
I learnt an interesting thing about Sean Bean (who played Boromir) the other day. I was discussing him at work with friends and idly commented on the pronunciation of his name and how it was at odds with the fact that his first and last names were spelt as though they really should rhyme. Yet is name is pronounced SHAUN BEAN, rather than either SEEN BEEN or SHAUN BAUN.
And then someone checked, and discovered that he was actually given the name Shaun Bean, and only changed the spelling to Sean Bean as a stage name!
Last Modified: Saturday, 13 July 2013; 03:11:02 PST.


text:
Guide: Fight for abortion rights with FFRF
Women across the country desperately need your help in defending abortion rights from religious attacks. These are troubling times, and the onslaught of abortion bans feels disheartening and scary, especially for women of color, immigrants, rural women and members of the LGBTQ community. The Freedom From Religion Foundation is committed to defending secular values and the separation of state and church. This includes abortion. Please read how FFRF has been fighting for these precious rights and how you can defend abortion rights in your community.
Abortion bans are anti-science
Stick to science and facts when discussing abortion rights. To be sure, everyone is entitled to their own opinion and personal decisions about abortion. However, as we live in a secular nation, health care laws should only reflect science and should be immune from religious impositions. The science proves that there is no basis for abortion bans — there are only religious motivations.
• Abortion is an extremely safe procedure, especially when conducted early in a pregnancy. Indeed, 90 percent of abortions happen within the first 12 weeks of gestation.
• Major complications occur in less than a quarter of 1 percent. To put that in context, there are more complications from wisdom tooth removals and tonsillectomies than from abortions.
• Researchers have found that pregnant people are 14 times more likely to die during childbirth than they are from any abortion complications.
• Studies have shown that 99 percent of individuals who obtain an abortion feel relief, not regret.
• Countries that have banned abortion prove that abortion restrictions do not reduce abortion rates. Instead, they make abortion care more dangerous. This has resulted in numerous preventable pregnancy-related deaths around the world every year.
• In Texas, maternal deaths rose from 72 deaths per 100,000 live births in 2010 to 148 deaths per 100,000 live births in 2012 after abortion restrictions.
• The American Medical Association does not support abortion bans and says that it will always defend science.
• The U.N. Human Rights Commission has asserted that abortion is a human right, that denying abortion access is linked to discrimination and that it can constitute gender-based violence, torture, and/or cruel, inhuman and degrading treatment.
• The so-called "fetal heartbeat" in so many abortion legislation is a misnomer. Dr. Ted Anderson, president of the American College of Obstetricians and Gynecologists, an organization representing 58,000 physicians in the United States, remarks that the phrase is intended to hide its anti-science roots. Instead, Anderson explains that the pulsing is "electrically induced flickering of a portion of the fetal tissue that will become the heart as the embryo develops."
And yet, despite these facts, abortion restrictions abound. To be sure, abortion bans are driven by a religious minority which seeks to impose its extremist worldview on a secular nation. The year 2021 has been record-setting in adoption of abortion restrictions —106 abortion restrictions have become law in this year alone. For context, the previous record for anti-abortion legislation was in 2011 with 89 restrictions.
The Women's Health Protection Act
Because of these rampant anti-abortion bills, it is imperative that we pass legislation to protect the right to an abortion throughout the United States. Perhaps the most well-known threat to abortion is SB 8, the Texas abortion ban.
It has been six weeks since Texas passed the most restrictive abortion ban in the country on Sept. 1. After the Supreme Court shockingly allowed the law to remain in place, the courts have been battling about the legality of this severely anti-science, anti-woman bill. As a reminder, this bill not only bans virtually all abortions, but also deputizes private citizens to be abortion bounty hunters. This means that Uber drivers, friends who lend money and abortion providers alike can be sued for assisting someone in receiving an abortion after six weeks of gestation. To be clear, most women do not realize that they are pregnant at six weeks gestation since it is only two weeks after a missed period. So this is a flagrant violation of women's right to reproductive care. That means that millions of women are without comprehensive reproductive care. Those who can afford the burdensome time and expense have been fleeing to Oklahoma for abortion care. However, clinics in Oklahoma are now overwhelmed with patients as they battle their own pending anti-abortion ban.
FFRF has actively urged overturning this law and supports the Justice Department in its bid to ask the Supreme Court intervene and block the unconstitutional abortion ban. FFRF has also been vocal in supporting the Women's Health Protection Act.
The Women's Health Protection Act would render unenforceable medically unnecessary and burdensome restrictions against abortion passed by state legislatures. FFRF submitted formal testimony in support of this crucial bill, explaining that "the general welfare is being endangered by anti-abortion zealotry at the state level." You can read the full letter here.
Thanks to the work of many activist citizens, including FFRF members, the act passed the House, but faces major resistance in the Senate. That's why we need you to call on your senators and ask them to pass this important piece of abortion legislation so that hundreds of restrictions are nullified.
Dobbs v. Jackson Women's Health Organization
The Supreme Court will hear oral arguments for the Mississippi abortion ban. on Dec. 1. Mississippi Bill 1510 would ban abortions after 15 weeks of gestation, which is antithetical to the foundation of Roe v. Wade. Should the ultraconservative Supreme Court allow the law to stand, the principles undergirding Roe v. Wade would effectively be overturned. FFRF attorneys have filed an amicus brief, explaining the religious impetus of the anti-abortion bill. In the brief, FFRF explained that "Religion has always been at the heart of anti-abortion legislation, and Mississippi House Bill 1510 is likewise motivated by religious ideology." FFRF Associate Counsel Elizabeth Cavell drafted the amicus brief for the organization, with help from FFRF Legal Director Rebecca Markert, Senior Counsel Patrick Elliott and FFRF Reproductive Rights Intern Barbara Alvarez. The Center for Inquiry and American Atheists are the other groups that have joined in FFRF's brief. Read the full amicus brief here.
Global HER Act
Reproductive Rights Intern Barbara Alvarez defended reproductive rights on Capitol Hill, urging senators and members of the House to pass the Global Health, Empowerment and Rights Act (Global HER Act). This necessary legislation would prevent any future president from imposing the Global Gag Rule, formally known as the Mexico City Policy, which was first introduced in 1984 by President Reagan. It prevents U.S. funding to any foreign nongovernmental organization that provides or even mentions abortion services, and has been re-enacted by every Republican president and overturned by every Democratic president.
FFRF submitted formal public comment opposing action by the Trump administration to expand the already prohibitive gag eule to all U.S. global fund assistance. And while FFRF cheered the Biden administration for reversing the Global Gag Rule, it is important that FFRF members call on their representatives to pass the Global Her Act so that it can't be reinstated by a future religiously rooted president. Contact your representatives now.
Title X funding restored to abortion providers
FFRF submitted a formal comment to the Department of Health and Human Services about reversing the Trump administration's domestic gag rule. This rule stripped public funding under Title X from health care providers who offered abortion services, referrals, or information. Planned Parenthood was most severely impacted by this decision, since it serves 40 percent of Title X' 4 million patients with reproductive care, such as cancer screenings and birth control. In the public comment, FFRF wrote that this callous move "undermine[d] women's reproductive rights, access, and health."
FFRF heartily cheered the Biden administration's reversal of this horrific policy, which takes effect on Nov. 8.
Historic moves by the House of Representatives
FFRF and its members have been instrumental in voicing their opposition to the religiously rooted Hyde and Weldon Amendments. History was made in July when the U.S. House of Representatives passed a spending bill without their inclusion. The Hyde Amendment, in effect for 45 years, has denied low-income women on Medicaid (one in five women in the United States), as well as those in the Indian Health Services Plan and Peace Corps, from receiving affordable abortion care. Very few states have picked up coverage to ensure abortion access for low-income women.The Hyde Amendment was introduced by Rep. Henry J. Hyde, a staunch Catholic who was religiously motivated to stomp out abortion rights in the country. The Weldon Amendment, passed in 2005, allows health care providers to refuse to cover, provide, pay or refer someone for an abortion based on "religious or moral grounds."
Reproductive Rights Intern Barbara Alvarez published an op-ed in the Madison Capital Times urging U.S. Sen. Ron Johnson, R-Wis., to pass the budget without these amendments. We ask you to contact your senators to do the same.
Abortion stigma letter
At the core of the anti-abortion movement is the stigma surrounding abortion. This stigma manifests in harmful misinformation about abortion and in draconian anti-abortion legislation. That is why it is so important for public officials and policymakers to end this unjust stigma and be fearless in saying the word "abortion." FFRF joined 117 organizations, including NARAL Pro-Choice America, Planned Parenthood Federation of America, American Humanist Association, American Atheists, American Civil Liberties Union, Guttmacher Institute, SisterSong: Women of Color Collective and Whole Women's Health, in an open letter that affirms abortion is health care and not something that is shameful. You can read the full letter here and learn more about destigmatizing abortion through language here.
In its home state of Wisconsin, FFRF submitted testimony opposing three major anti-abortion restrictions that are making their way through the Capitol. FFRF Co-Presidents Dan Barker and Annie Laurie Gaylor wrote to Committee on Health and Human Services Chair Rep. Joe Sanfelippo to object to bills limiting medication abortion and overall access to care, explaining: "States that have more abortion restrictions have higher rates of maternal and infant mortality. Structural racism contributes to those poor maternal health outcomes for women of color who experience higher levels of stress, discrimination, and exclusion from the health care system."
FFRF members also called upon their representatives and asked them to reject these bills.
Freethinkers in Massachusetts stood up to religious zealots when FFRF called on them to reject an anti-abortion education proposal and New York members supported reproductive freedom bills regarding rights to pregnant inmates and emergency contraception access on college campuses.
Action alerts are crucial to defending reproductive rights. Your voice matters! Sign up for action alerts and be part of this important movement.
Your voice is needed more than ever
There is no scientific rationale for restricting reproductive health care and public opinion agrees. A recent Pew study found that the majority of Americans believe that abortion should be legal in all or most cases. Additionally, 82 percent of religiously unaffiliated people support legal abortions.
We cannot depend on the courts to save us from harmful abortion legislation. Serious court reform is needed to protect individual liberties. And until that happens, we need voices of science and reason. Essentially, we need you in this fight! In a recent membership survey conducted by the Freedom From Religion Foundation, a whopping 98.8 percent of FFRF members support the constitutional right to legal abortion.
It is time to make your voices known and heard.
• Speak to your friends, family, and neighbors about abortion rights and secular values.
• Contact your representatives.
• Submit a letter to your local newspaper.
• Sign up for action alerts.
• Consider donating to the Women's Medical Fund, which was co-founded by Anne Nicol Gaylor, FFRF's principal founder. Gaylor oversaw this fund as a volunteer from the late 1970s until her death in 2015. The fund annually helps an average of 900-1,000 Wisconsin residents without means exercise their constitutional rights under Roe v. Wade. It is all-volunteer, with donations paying for abortion care. Make a donation, deductible for income-tax purposes.
Women's rights demand our secular voices and we are grateful to have you in this important fight.
Written by FFRF's Anne Nicol Gaylor Reproductive Rights Intern Barbara Alvarez. Photo by Chris Line.


Every hill should have a pagoda. Well some people blame Myanmar for that, but here in North Thailand they are also good at it. Stairs protected by Naga's leading up to a lovely pagoda. Luckily there was also a road going up. Nice cool and quite. A a stunning view over the valley of Pua in North Thailand. For more information about the beautiful Nan province in North Thailand see Destination Travel Guide Nan - Thailand.


Leefbaarheidsbudget' is a budget provided by the municipality of Utrecht for each of its ten districts. Translated literally, it means 'livability- budget'. Within the municipality every district has a fixed budget reserved for improvement of livability, were 'livability' is defined as 'the quality of the residential and living environment'.
A project designed to revitalize inner city neighbourhoods by empowering local residents to set priorities, suggest projects and assist in their implementation.


Here at Marathon Kids, we know that active kids do better. We also know that kids who are able to listen, communicate, and problem-solve are better equipped to succeed in school and in life. These are all skills they need to navigate the world around them.
Using the pillars of the Marathon Kids program, many of our coaches are using their running clubs not only for physical activity, but also to prime their kids' brains, to encourage them to build relationships, and to help their runners unlock the key concepts of social emotional learning.
The Collaborative for Academic, Social, and Emotional Learning, or CASEL, is on mission to help make evidence-based social emotional learning (SEL) an integral part of the school day, from Pre-K to high school. CASEL's five competencies are embedded in SEL curriculum and help a child succeed in their personal and relationship skills. More importantly, these five competencies help educate hearts, inspire minds, and help students navigate the world more effectively. Schools and youth organizations across the nation are now increasingly implementing social emotional learning into a student's day.
The five competencies are: Self-Awareness, Self-Management, Social Awareness, Relationship Skills, and Responsible Decision-Making.
It is about how teaching and learning happen, as well as what you teach and where you learn.
Through SEL curriculum, kids learn positive self-talk, problem solving skills, and how to build relationships with others. They start to recognize that everyone is unique, that listening to understand can help resolve misunderstandings, and that people sometimes interpret information or experiences differently. And that's okay!
While technology can make our lives easier, it can also cause children to spend less time communicating face to face, to have difficulty expressing how they feel in appropriate ways, and to need guidance in navigating relationships with others.
Soft skills—which are needed to effectively communicate, problem-solve, collaborate and organize—are becoming increasingly important for success later in life. Recruiters and employment experts have started reporting a "soft skills gap," especially among young workers more accustomed to texting than talking. Some employers are expressing frustration that while they can teach employees a new skill, they can't teach them how to communicate, listen, or get along with others.
Social emotional learning plays an integral key role in helping students achieve both academically and interpersonally. The world needs more critical thinkers, problem-solvers, and well-balanced, relationship-building humans to face new challenges and demands.
Through running, we show kids they can achieve more than they ever thought possible. And, the success kids find in setting goals and tracking their progress at running club trickles down to other parts of their lives as well. When kids have higher self-confidence, they are more willing to break out of their shell, try new things, and persevere when things get tough.
Not only are Marathon Kids participants reaping the benefits of physical activity and building endurance, they are also learning the importance of goal-setting, determination, and relationship-building.
Through stories we've collected, we know our simple, fun and effective running clubs create a space for so much more to happen than just conquering laps. Kids are self-evaluating and reflecting on their performance. Some kids who aren't involved in sports feel like they are athletes—possibly for the first time—and that they are part of a team. Running club becomes a social outlet to create community and spark friendships with a diverse group of peers.
Whether you are a teacher, coach, parent, principal, administrator, or volunteer, we want to help you incorporate physical activity into your school's schedule. There's power in movement. Use it to ignite and regulate kids' brains, build relationships, and create well-balanced kids who are ready to navigate the world around them. The Marathon Kids program can be integrated into SEL curriculum, brain breaks, and your school culture.
Marathon Kids strives to empower our coaches through trainings, featured media stories, and Ambassador status for those who go above and beyond. We are fortunate to have so many dedicated coaches across the nation investing in kids' lives. If you're already involved with Marathon Kids, we hope you'll join our movement to get kids moving!
Want to learn more about the physical and social emotional learning connection? We'd love to hear from you. For more information about our program and trainings, including a social emotional learning module, please contact us at info@marathonkids.org.


Looking for a new house to rent in Denton County, TX? Currently, there are 57 houses for rent available in Denton County, TX with rents starting from $1,079. Whether looking to lease a luxury house with panoramic views, a spacious single-family home or a cozy residence in a pet-friendly community, you can use our advanced search tools to find the home that best caters to your needs. Search and browse through lots of Denton County, TX houses for rent and submit your rental application today!


text:
Island Realty
Island Realty - Cathie Child Rasch
HHI Neighborhoods
Matterport 3D Interactive Marketing for Your Home
Vacation Rental on Hilton Head Island
Home > Advice & About > Communities of Hilton Head Island
Communities of Hilton Head Island
The Communities of Hilton Head Island
Sea Pines Plantation
Home of the Sea Pines Resort and the RBC Heritage Golf Tournament presented by Boeing, Sea Pines is
situated on 5000 acres on the southern tip of the island. There are three public golf courses, the Harbourtown Golf
Links, the Ocean Course and the Heron Pointe course, start out from the new Plantation Golf Club with it's state of the art Golf Learning Center. Sea Pines is also home to the Sea Pines Country Club. Ride your bikes to Harbourtown, Sea Pines Center or South Beach Marina on the miles of bike paths and enjoy the fine restaurants and shopping that Sea Pines is famous for or sing along with Greg Russell under the Liberty Oak. Spend your day on the beach at the newly opened Sea Pines Beach Club and enjoy dinner beach side. Go fishing on Lake Joe in the Sea Pines Forest Preserve.
Palmetto Dunes(including Shelter Cove & Leamington)
This popular resort and residential community is located mid-island, sitting on 1,800 well-preserved acres. Inside its guarded gates are three miles of world-famous Atlantic Ocean beaches, 11 miles of winding lagoons, and one of the largest tennis centers on the island, with 25 courts. Palmetto Dunes is also home to the Omni Resort and the Hilton Head Marriott Beach and Golf Resort. Its three public, 28-hole golf courses were designed by PGA favorites George Fazio, Robert Trent Jones, and Arthur Hills.
The community ranges from year-round residents to weekend visitors due to the wide range of property types (homes, villas, oceanfront condos and the two hotels). Also part of Palmetto Dunes is Shelter Cove Marina and the private enclave known as Leamington. Palmetto Dunes has 1,012 homes and 1,470 villas.
Golf Digest magazine has rated Long Cove Club's private golf course, the number one Golf Course in South Carolina for ten years straight. A membership to this challenging golf course is included with ownership in Long Cove club. In the 1980s, the plantation's developers chose to carefully preserve the area's live oaks, magnolia and palmetto palm trees, which create a serene, wooded environment in which its signature golf course is nestled. In addition to the Pete Dye golf course, a new tennis center was opened in 2002. Residents also enjoy deepwater access to Broad Creek from the community's boat docks. This plantation is situated between Yacht Cove and Wexford Plantation toward the island's south end has 569 homes.
Shipyard Plantation
Shipyard is situated on 803 acres on the Atlantic Ocean side of Hilton Head. Shipyard features 27 holes of golf, a 24-court racquet club and a pleasant stretch of limited access beach. In addition to single family homes, Shipyard is primarily geared towards vacation oriented villas (250 total).
Additional amenities include bike paths, jogging trails, fishing, and swimming. The Sonesta Resort is located within the plantation's gate.
Hilton Head Plantation, the Island's second-largest community is quietly residential, and encompasses 4,000 wooded acres at the northern end of the Island. Recreational facilities include four separate equity golf clubs, tennis courts, a beach park, pools, stables, and a full service marina. Bounded on two sides by Port Royal Sound and Skull creek, its breathtaking sunsets and water views are unsurpassed. Well planned and meticulously maintained, this friendly and socially oriented community of predominantly full-sized and patio home sites is designed to accommodate approximately four thousand families.
Wexford Plantation is an exclusive, private yachting and golf community offering an elegant lifestyle. Many of Wexford's impressive residences are built along the edges of the lock-controlled deep-water harbor and charming canals that wind through Wexford's 500 very private acres. Activities center around Wexford's luxurious clubhouse and yacht basin. Amenities include golf, boating, croquet and fun social activities. For pure luxury you can't beat Wexford.
Port Royal Plantation
Port Royal Plantation is a 1000 acre private beach-front community limited to single family homes and was the second Island community to be developed (in 1968). Its three miles of wide sandy beach round the curve from the sparkling Atlantic Ocean to Port Royal Sound At the gates of this tranquil community are resort facilities that include a magnificent Southern Clubhouse, three golf courses, a championship croquet court, and a five star racquet club. The Westin Resort calls Port Royal Plantation its oceanfront home offering fine dining and superb health club facilities.
Palmetto Hall Plantation
Palmetto Hall, the Island's newest community is a unique residential community that features two distinctly different, yet challenging championship golf courses by world renowned architects Arthur Hills and Robert Cupp. With generously sized golf-oriented home sites, Palmetto Hall is a place to experience the warmth of a real neighborhood with the pleasures of a friendly country club lifestyle. With just 525 home sites on 750 acres, Palmetto Hall boasts one of the lowest ratio of homes to golf holes on Hilton Head Island. Palmetto Hall offers variety, value and challenging golf in what is known as the best private golf club community on Hilton Head Island.
North and South Forest Beach
Located on the south end of the Island, the Forest Beach area is unlike any other. It's an interesting mix of old, new, modest and large. A popular short term vacation rental area due to its close proximity to the beach, the Coligny shopping area, restaurants, and evening activities. There are about 600 residential homes & lots, and a couple of thousand villas located either on the beach, or within a short stroll to the beach. The Forest Beach area is not a gated community or a planned resort.
Indigo Run is a private residential and golf community located directly across Highway 278 from Hilton Head Plantation. The community encompasses 1,712 acres and at maturity will include 1200 to 1400 residences. Home sites in Indigo Run overlook the golf courses, lagoons or the marshes of Broad Creek. The Golden Bear Golf Course, designed by Golden Bear Design Associates, a Nicklaus company, includes a clubhouse with casual grill and pro shop. The Golf Club at Indigo Run is a members-only signature golf course and includes a clubhouse and a full array of recreational amenities.
For those individuals who treasure waterfront privacy and tranquility, Spanish Wells Plantation is the answer. A peninsula of single-family homes, Spanish Wells home sites range from 1/2 acre to two acres in size. Views include deep water, golf and private wooded settings. The Spanish Wells peninsula features some of the most beautiful homes on the island along with fabulous views of Broad Creek, the open waters of the Calibogue Sound and the Intercostal Waterway. The 350-acre community has a semi-private nine-hole golf course and a private pool complex.
Windmill Harbour is a 172 acre private residential community reserved for 500 residences. The community on the Inter-costal Waterway offers beautiful views of the Intracostal and saltwater marshes. It is also the home of the South Carolina Yacht Club. The primary focal point of Windmill Harbour is a 15-acre inland harbor – twice the size of Harbour Town. The sports center at Windmill Harbour offers four clay tennis courts, saunas, Jacuzzi, dressing rooms, a pro shop and 25 meter swimming pool. Jogging and bike trails also found throughout the community.
Cathie Child Rasch
RE/MAX ISLAND REALTY
24 New Orleans Rd #210
Hilton Head Island, SC 29928


Interested in learning native iOS SDK development? Now is the perfect time to get started. Mobiletuts+ is pleased to announce an in-depth, fully updated, complete session on how to become an iOS SDK developer.


Brochures, design style, email graphics, website graphics.
"The team at Storm12 understand our business and numerous challenges exceedingly well and are always happily on hand to help us meet them. Whether this is a conceptual positioning for an in- depth acquisition campaign or an internal quick win, they apply exactly the right amount of strategic thinking and resource to do any excellent job, on budget - and not a penny more! Their refreshing approach is very much based on maximum creativity for return on investment with minimum fuss. They have begun to feel almost as an extension of the marketing team and it's great to know we can absolutely rely on them. Oh yes... and sometimes they bring us great cakes too!"


text:
Staying in the US?
By David Butwin Special to The Christian Science Monitor
Even as Europe braces for a summer invasion by that wide-ranging species, Touristus Americanus, it appears that a good number of travelers will leave their passports and phrase books at home to fan out across the United States.
All signs point to revived touring patterns in the US, according to Arnold Fury, manager of travel programs for Mobil Oil and the editor of the Mobil Travel Guides. ''Things are shaping up very well,'' said Mr. Fury from his Fairfax, Va., office the other day. ''Most people - 80 percent or better - use the auto when they travel, and the good news for them is that gas is stable, or even below prices of a year ago. Also, because the economy has been soft, there is an abundance of good deals to be found out there.''
Mr. Fury included in this abundance the coupons one can clip from a Mobil Travel Guide to a particular region, offering reductions of 10 to 50 percent for six hotel chains and any number of attractions, from the Baseball Hall of Fame at Cooperstown, N.Y., to Sea World in San Diego.
He said that while national parks and theme parks suffered through recent travel-thin summers, they are due for promising seasons in '83. As for what strategy the American highwayman should use in the coming summer, Mr. Fury advised:
''Travel early in the day to avoid the afternoon heat. This will mean less traffic and less air conditioning, thus lower fuel costs. Avoid traveling on weekends when everyone else goes on the road. Try to do the bulk of your driving during the week.''
While it appears that air fares will be comparatively better abroad than at home (transatlantic fares are actually down from last summer), there are still Super Savers worth booking to various points in the US. Most call for a 7-day advance purchase and stays of 7 to 14 days. United Airlines recently came out with a different version of the Super Saver that, while not as low-priced, provides a much longer stay, up to 60 days - almost, in other words, a full summer.
Summer may be defined by some as school's-out to school's-back or the life span of a bathing suit, but for me it runs from the Spoleto Festival USA in late May to the Pendleton (Ore.) Roundup in mid-September. Spoleto, scheduled this year from May 20 to June 5, perennially ushers in the first sultry summer heat of the South Carolina low country. Charleston is both stage and backdrop for the lively series of arts performances and exhibitions.
Spoleto weekend package tours can be had by writing PO Box 704, Charleston, S.C. 29402. Hotels in the area help promote the 16-day festival, and these range from the luxe, such as the Sheraton Charleston and the Mills House, to the economical, like the private homes and carriage houses that are part of Historic Charleston Bed & Breakfast; (803) 722-6606.
On the way to Pendleton, which this year erupts from Sept. 14 to 17, are scores of fairs, festivals, and annual events worth dropping in on. Philadelphia , proving you don't need a round number to have a birthday celebration (like the Brooklyn Bridge's 100th) is trying to draw visitors to its 301st. Shakespeare theater is scattered all across the land and, in fact, around the calendar. In addition to the well-known Shakespeare festivals at Stratford, Ontario, and Stratford, Conn. (recently rescued from the brink of financial ruin in time for the '83 season) there are smaller fetes at Ashland, Ore., hard by the Rogue River, to the end of October; at High Point, N.C., from mid-July to December; at Cedar City, Utah, a short drive from the equally dramatic Bryce and Zion National Parks, from mid-July to late August - and no doubt a few I haven't heard of.
Summer is also the time to visit places you'd only think of going to in the winter. And I don't mean Death Valley. Two of Florida's grandest dames, the Breakers at Palm Beach and the Boca Raton Hotel and Club, 22 miles south, lower their prices by up to 40 percent in the off-season to try to fill their sumptuous rooms.
The Breakers, one of three US hotels to win five stars from Mobil and five diamonds from AAA, makes its 1926 Italianate splendor available for $65 a day for two (and no charge for kids under 12 sharing their parents' room). Boca's Moorish air, not to mention its 22 clay courts, marina, and golf course, can be had for $90 to $150 MAP (two meals) per day from June 1 to Sept. 30.
Summer isn't a particularly economical time to ride the rails (most of the bargain fares are offered in the laxer months), but those who do will encounter fewer overheated and stalled cars than at any time since Amtrak was born in 1971 . New and refurbished equipment is also improving the on-time record steadily. And as of April 25, Amtrak had a glorious new route - at least on paper.
That was the day the California Zephyr was supposed to begin running from Denver, through the Rockies and across the Wasatch Range en route to Salt Lake City and Oakland. But massive mudslides in eastern Utah have forced Amtrak to divert - but only temporarily - to its former route across southern Wyoming.
One of the high points, in more ways than one, of the scenic new run will be the circuit of the six-mile-long Moffatt Tunnel just before Winter Park, Colo. It's the longest tunnel and the highest elevation on Amtrak's system. It may be one of the few places to keep the American traveler in the dark during the bright summer ahead.
Amtrak train derailment: Several injured in South Carolina accident
Chapter & Verse Amtrak launches writers' residency program
First Look With new trainsets, Amtrak hopes to pick up the pace


text:
@interface PodsDummy_ProgressKit : NSObject
@end
@implementation PodsDummy_ProgressKit
@end

redpajama_set_name: RedPajamaGithub


Adaptive variable bias control (AVBC) is an improved technique for controlling the currents supplied to the electromagnets in magnetic bearings. In AVBC, the bias currents are varied in such a way as to reduce overall power consumption.
Open-cell silicon carbide foam coated with a ferrite-filled absorbing resin has been found to be useful for black-body absorbers at millimeter and submillimeter wavelengths. The panels can be used as calibration targets for radiometers that operate at these wavelengths.


text:
- Throw Back
Tom Joyner News: Avant Faces the Music!
Posted By Ahmaad Crump
http://blackamericaweb.com
Crooner Avant has been behind several R&B hits from ballads like "When It Hurts," duets with Keke Wyatt like "Separated" and "My First Love" and sexy anthems like "Makin' Good Love" and "Break Your Back." This month, he releases his seventh studio CD, "Face the Music" on indie Mo-B Entertainment, distributed through Capitol. His first single "You and I" reunites him with his favorite duet partner, Wyatt, now one of the stars of "R&B Divas" on TV One.
"With her it's seamless," Avant told Vibe.com."It's a whole different spirit when she's in the studio. We have a chemistry and bond that can't be broken. I've worked with a lot of different female artists and she's the easiest to work with. When we did "My First Love" she was only 16, and never heard the original song, but she sang it like a champ. From that point on I knew there was something special about her. I'll put her up against any female in the game, and I mean that."
Though R&B has been diminished in its influence since Avant began his career and many "old-school" R&B acts have been cast aside for newcomers like Miguel, Frank Ocean and The Weeknd, Avant stays in his lane for "Face the Music."
"It's a taste of new school and old school," explains Avant. "You might hear a piece of, say, Stevie Wonder or Babyface, then I spin right back around and offer up some new age R&B. It's a well-rounded album with something for everyone. At the end of the day, "Face the Music" is about who we are and what we live by; it's about respecting that as well as the music."
Read more at http://blackamericaweb.com/
In Studio Jam: Avant Faces the Music
More By Ahmaad Crump
Are We Only Teaching Kids Black History For 28 Days Of The Year?
Slow Ticket Sales For Mariah Carey & Lionel Richie's Tour
Will Morris Day Pay Tribute To Prince At The Grammys?


text:
A partial lunar eclipse will take place on Wednesday, January 12, 2028.

Visibility
It will be completely visible over Europe, western Africa and the Americas, and will be seen setting over the rest of Africa and western Asia.

Related lunar eclipses

Eclipses in 2028
 A partial lunar eclipse on Wednesday, 12 January 2028.
 An annular solar eclipse on Wednesday, 26 January 2028.
 A partial lunar eclipse on Thursday, 6 July 2028.
 A total solar eclipse on Saturday, 22 July 2028.
 A total lunar eclipse on Sunday, 31 December 2028.

Saros series
It is part of Saros series 115.

Lunar year series

Half-Saros cycle
A lunar eclipse will be preceded and followed by solar eclipses by 9 years and 5.5 days (a half saros). This lunar eclipse is related to two partial solar eclipses of Solar Saros 122.

See also
List of lunar eclipses and List of 21st-century lunar eclipses

Notes

External links

2028-01
2028-01
2028 in science

redpajama_set_name: RedPajamaWikipedia


text:
Q: Definite article in front of "nineteenth-century United States"? Should it be:

In nineteenth-century United States, many railroads were constructed.

Or

In the nineteenth-century United States, many railroads were constructed.

Certainly if America were used in place of United States, then there'd be no definite article. But if I insist on saying United States, should there be one?
This question is different from the other. In my opinion, the latter sentence is somehow awkward and there is the possibility that the first sentence is 'correct'. If you think it obvious that the first sentence is wrong and the second sentence is correct, then please, instead of closing this question, answer it and explain why it is so obvious. Or why the other linked question clearly explains my question here.

A: The answer to your question is yes.
These are wrong:

*

*In *United States, many railroads were constructed.

*In nineteenth-century *United States, many railroads were constructed.

These are right:

*In America, many railroads were constructed.

*In nineteenth-century America, many railroads were constructed.

*In the United States, many railroads were constructed.

*In the nineteenth-century United States, many railroads were constructed.

*In the United States of the nineteenth century, many railroads were constructed.

*Many railroads were constructed in the United States during the nineteenth century.

You cannot dispense with the article simply by interposing an adjective here.  Number 6 does not sound as good as 7 and 8 do. It's ok with 4, but for some reason 6 sounds awkward.

redpajama_set_name: RedPajamaStackExchange