예제 #1
0
/*
 * Examine parameters and prepare for a sample scan.
 */
static void
system_time_beginsamplescan(SampleScanState *node,
							Datum *params,
							int nparams,
							uint32 seed)
{
	SystemTimeSamplerData *sampler = (SystemTimeSamplerData *) node->tsm_state;
	double		millis = DatumGetFloat8(params[0]);

	if (millis < 0 || isnan(millis))
		ereport(ERROR,
				(errcode(ERRCODE_INVALID_TABLESAMPLE_ARGUMENT),
				 errmsg("sample collection time must not be negative")));

	sampler->seed = seed;
	sampler->millis = millis;
	sampler->lt = InvalidOffsetNumber;
	sampler->doneblocks = 0;
	/* start_time, lb will be initialized during first NextSampleBlock call */
	/* we intentionally do not change nblocks/firstblock/step here */
}
예제 #2
0
Datum smithwaterman_op(PG_FUNCTION_ARGS)
{
    float8	res;

    /*
     * store *_is_normalized value temporarily 'cause
     * threshold (we're comparing against) is normalized
     */
    bool	tmp = pgs_sw_is_normalized;
    pgs_sw_is_normalized = true;

    res = DatumGetFloat8(DirectFunctionCall2(
                             smithwaterman,
                             PG_GETARG_DATUM(0),
                             PG_GETARG_DATUM(1)));

    /* we're done; back to the previous value */
    pgs_sw_is_normalized = tmp;

    PG_RETURN_BOOL(res >= pgs_sw_threshold);
}
예제 #3
0
static void
fetch_restrict(HeapTuple *tuple, TupleDesc *tupdesc, 
           restrict_columns_t *restrict_columns, restrict_t *rest)
{
  Datum binval;
  bool isnull;
  int t;

  for(t=0; t<MAX_RULE_LENGTH;++t)
    rest->via[t] = -1;

  binval = SPI_getbinval(*tuple, *tupdesc, restrict_columns->target_id, &isnull);
  if (isnull)
    elog(ERROR, "target_id contains a null value");
  rest->target_id = DatumGetInt32(binval);

  binval = SPI_getbinval(*tuple, *tupdesc, restrict_columns->to_cost, &isnull);
  if (isnull)
    elog(ERROR, "to_cost contains a null value");
  rest->to_cost = DatumGetFloat8(binval);
  char *str = DatumGetCString(SPI_getvalue(*tuple, *tupdesc, restrict_columns->via_path));

  //PGR_DBG("restriction: %f, %i, %s", rest->to_cost, rest->target_id, str);

  if (str != NULL) {
    char* pch = NULL;
    int ci = 0;

    pch = (char *)strtok (str," ,");

    while (pch != NULL && ci < MAX_RULE_LENGTH)
    {
      rest->via[ci] = atoi(pch);
      //PGR_DBG("    rest->via[%i]=%i", ci, rest->via[ci]);
      ci++;
      pch = (char *)strtok (NULL, " ,");
    }
  }

}
예제 #4
0
static void
fetch_edge_astar(HeapTuple *tuple, TupleDesc *tupdesc, 
         edge_astar_columns_t *edge_columns, 
         edge_astar_t *target_edge)
{
  Datum binval;
  bool isnull;

  binval = SPI_getbinval(*tuple, *tupdesc, edge_columns->id, &isnull);
  if (isnull) elog(ERROR, "id contains a null value");
  target_edge->id = DatumGetInt32(binval);

  binval = SPI_getbinval(*tuple, *tupdesc, edge_columns->source, &isnull);
  if (isnull) elog(ERROR, "source contains a null value");
  target_edge->source = DatumGetInt32(binval);

  binval = SPI_getbinval(*tuple, *tupdesc, edge_columns->target, &isnull);
  if (isnull) elog(ERROR, "target contains a null value");
  target_edge->target = DatumGetInt32(binval);

  binval = SPI_getbinval(*tuple, *tupdesc, edge_columns->cost, &isnull);
  if (isnull) elog(ERROR, "cost contains a null value");
  target_edge->cost = DatumGetFloat8(binval);

  if (edge_columns->reverse_cost != -1) {
      binval = SPI_getbinval(*tuple, *tupdesc, 
                 edge_columns->reverse_cost, &isnull);
      if (isnull) elog(ERROR, "reverse_cost contains a null value");
      target_edge->reverse_cost =  DatumGetFloat8(binval);
  }

  binval = SPI_getbinval(*tuple, *tupdesc, edge_columns->s_x, &isnull);
  if (isnull) elog(ERROR, "source x contains a null value");
  target_edge->s_x = DatumGetFloat8(binval);

  binval = SPI_getbinval(*tuple, *tupdesc, edge_columns->s_y, &isnull);
  if (isnull) elog(ERROR, "source y contains a null value");
  target_edge->s_y = DatumGetFloat8(binval);

  binval = SPI_getbinval(*tuple, *tupdesc, edge_columns->t_x, &isnull);
  if (isnull) elog(ERROR, "target x contains a null value");
  target_edge->t_x = DatumGetFloat8(binval);

  binval = SPI_getbinval(*tuple, *tupdesc, edge_columns->t_y, &isnull);
  if (isnull) elog(ERROR, "target y contains a null value");
  target_edge->t_y = DatumGetFloat8(binval);
}
예제 #5
0
/*
 * Binary search on length histogram. Returns greatest index of range length in
 * histogram which is less than (less than or equal) the given length value. If
 * all lengths in the histogram are greater than (greater than or equal) the
 * given length, returns -1.
 */
static int
length_hist_bsearch(Datum *length_hist_values, int length_hist_nvalues,
					double value, bool equal)
{
	int			lower = -1,
				upper = length_hist_nvalues - 1,
				middle;

	while (lower < upper)
	{
		double		middleval;

		middle = (lower + upper + 1) / 2;

		middleval = DatumGetFloat8(length_hist_values[middle]);
		if (middleval < value || (equal && middleval <= value))
			lower = middle;
		else
			upper = middle - 1;
	}
	return lower;
}
예제 #6
0
Datum
regress_dist_ptpath(PG_FUNCTION_ARGS)
{
	Point	   *pt = PG_GETARG_POINT_P(0);
	PATH	   *path = PG_GETARG_PATH_P(1);
	float8		result = 0.0;	/* keep compiler quiet */
	float8		tmp;
	int			i;
	LSEG		lseg;

	switch (path->npts)
	{
		case 0:
			PG_RETURN_NULL();
		case 1:
			result = point_dt(pt, &path->p[0]);
			break;
		default:

			/*
			 * the distance from a point to a path is the smallest distance
			 * from the point to any of its constituent segments.
			 */
			Assert(path->npts > 1);
			for (i = 0; i < path->npts - 1; ++i)
			{
				regress_lseg_construct(&lseg, &path->p[i], &path->p[i + 1]);
				tmp = DatumGetFloat8(DirectFunctionCall2(dist_ps,
														 PointPGetDatum(pt),
													  LsegPGetDatum(&lseg)));
				if (i == 0 || tmp < result)
					result = tmp;
			}
			break;
	}
	PG_RETURN_FLOAT8(result);
}
예제 #7
0
Datum
regress_path_dist(PG_FUNCTION_ARGS)
{
	PATH	   *p1 = PG_GETARG_PATH_P(0);
	PATH	   *p2 = PG_GETARG_PATH_P(1);
	bool		have_min = false;
	float8		min = 0.0;		/* initialize to keep compiler quiet */
	float8		tmp;
	int			i,
				j;
	LSEG		seg1,
				seg2;

	for (i = 0; i < p1->npts - 1; i++)
	{
		for (j = 0; j < p2->npts - 1; j++)
		{
			regress_lseg_construct(&seg1, &p1->p[i], &p1->p[i + 1]);
			regress_lseg_construct(&seg2, &p2->p[j], &p2->p[j + 1]);

			tmp = DatumGetFloat8(DirectFunctionCall2(lseg_distance,
													 LsegPGetDatum(&seg1),
													 LsegPGetDatum(&seg2)));
			if (!have_min || tmp < min)
			{
				min = tmp;
				have_min = true;
			}
		}
	}

	if (!have_min)
		PG_RETURN_NULL();

	PG_RETURN_FLOAT8(min);
}
예제 #8
0
Datum
spg_kd_choose(PG_FUNCTION_ARGS)
{
	spgChooseIn *in = (spgChooseIn *) PG_GETARG_POINTER(0);
	spgChooseOut *out = (spgChooseOut *) PG_GETARG_POINTER(1);
	Point	   *inPoint = DatumGetPointP(in->datum);
	double		coord;

	if (in->allTheSame)
		elog(ERROR, "allTheSame should not occur for k-d trees");

	Assert(in->hasPrefix);
	coord = DatumGetFloat8(in->prefixDatum);

	Assert(in->nNodes == 2);

	out->resultType = spgMatchNode;
	out->result.matchNode.nodeN =
		(getSide(coord, in->level % 2, inPoint) > 0) ? 0 : 1;
	out->result.matchNode.levelAdd = 1;
	out->result.matchNode.restDatum = PointPGetDatum(inPoint);

	PG_RETURN_VOID();
}
예제 #9
0
/*
 * Add an attribute to the hash calculation.
 * **IMPORTANT: any new hard coded support for a data type in here
 * must be added to isGreenplumDbHashable() below!
 *
 * Note that the caller should provide the base type if the datum is
 * of a domain type. It is quite expensive to call get_typtype() and
 * getBaseType() here since this function gets called a lot for the
 * same set of Datums.
 *
 * @param hashFn called to update the hash value.
 * @param clientData passed to hashFn.
 */
void
hashDatum(Datum datum, Oid type, datumHashFunction hashFn, void *clientData)
{

	void	   *buf = NULL;		/* pointer to the data */
	size_t		len = 0;		/* length for the data buffer */
	
	int64		intbuf;			/* an 8 byte buffer for all integer sizes */
		
	float4		buf_f4;
	float8		buf_f8;
	Timestamp	tsbuf;			/* timestamp data dype is either a double or
								 * int8 (determined in compile time) */
	TimestampTz tstzbuf;
	DateADT		datebuf;
	TimeADT		timebuf;
	TimeTzADT  *timetzptr;
	Interval   *intervalptr;
	AbsoluteTime abstime_buf;
	RelativeTime reltime_buf;
	TimeInterval tinterval;
	AbsoluteTime tinterval_len;
	
	Numeric		num;
	bool		bool_buf;
	char        char_buf;
	Name		namebuf;
	
	ArrayType  *arrbuf;
	inet		 *inetptr; /* inet/cidr */
	unsigned char inet_hkey[sizeof(inet_struct)];
	macaddr		*macptr; /* MAC address */
	
	VarBit		*vbitptr;
	
	int2vector *i2vec_buf;
	oidvector  *oidvec_buf;
	
	Cash		cash_buf;
	AclItem	   *aclitem_ptr;
	uint32		aclitem_buf;
	
	/*
	 * special case buffers
	 */
	uint32		nanbuf;
	uint32		invalidbuf;

	void *tofree = NULL;

	/*
	 * Select the hash to be performed according to the field type we are adding to the
	 * hash.
	 */
	switch (type)
	{
		/*
		 * ======= NUMERIC TYPES ========
		 */
		case INT2OID:			/* -32 thousand to 32 thousand, 2-byte storage */
			intbuf = (int64) DatumGetInt16(datum);		/* cast to 8 byte before
														 * hashing */
			buf = &intbuf;
			len = sizeof(intbuf);
			break;

		case INT4OID:			/* -2 billion to 2 billion integer, 4-byte
								 * storage */
			intbuf = (int64) DatumGetInt32(datum);		/* cast to 8 byte before
														 * hashing */
			buf = &intbuf;
			len = sizeof(intbuf);
			break;
			
		case INT8OID:			/* ~18 digit integer, 8-byte storage */
			intbuf = DatumGetInt64(datum);		/* cast to 8 byte before
												 * hashing */
			buf = &intbuf;
			len = sizeof(intbuf);
			break;

		case FLOAT4OID: /* single-precision floating point number,
								 * 4-byte storage */
			buf_f4 = DatumGetFloat4(datum);

			/*
			 * On IEEE-float machines, minus zero and zero have different bit
			 * patterns but should compare as equal.  We must ensure that they
			 * have the same hash value, which is most easily done this way:
			 */
			if (buf_f4 == (float4) 0)
				buf_f4 = 0.0;

			buf = &buf_f4;
			len = sizeof(buf_f4);
			break;

		case FLOAT8OID: /* double-precision floating point number,
								 * 8-byte storage */
			buf_f8 = DatumGetFloat8(datum);

			/*
			 * On IEEE-float machines, minus zero and zero have different bit
			 * patterns but should compare as equal.  We must ensure that they
			 * have the same hash value, which is most easily done this way:
			 */
			if (buf_f8 == (float8) 0)
				buf_f8 = 0.0;

			buf = &buf_f8;
			len = sizeof(buf_f8);
			break;

		case NUMERICOID:

			num = DatumGetNumeric(datum);

			if (NUMERIC_IS_NAN(num))
			{
				nanbuf = NAN_VAL;
				buf = &nanbuf;
				len = sizeof(nanbuf);
			}
			else
				/* not a nan */
			{
				buf = num->n_data;
				len = (VARSIZE(num) - NUMERIC_HDRSZ);
			}

            /* 
             * If we did a pg_detoast_datum, we need to remember to pfree, 
             * or we will leak memory.  Because of the 1-byte varlena header stuff.
             */
            if (num != DatumGetPointer(datum)) 
                tofree = num;

			break;
		
		/*
		 * ====== CHARACTER TYPES =======
		 */
		case CHAROID:			/* char(1), single character */
			char_buf = DatumGetChar(datum);
			buf = &char_buf;
			len = 1;
			break;

		case BPCHAROID: /* char(n), blank-padded string, fixed storage */
		case TEXTOID:   /* text */
		case VARCHAROID: /* varchar */ 
		case BYTEAOID:   /* bytea */
			{
				int tmplen;
				varattrib_untoast_ptr_len(datum, (char **) &buf, &tmplen, &tofree);
				/* adjust length to not include trailing blanks */
				if (type != BYTEAOID && tmplen > 1)
					tmplen = ignoreblanks((char *) buf, tmplen);

				len = tmplen;
				break;
			}

		case NAMEOID:
			namebuf = DatumGetName(datum);
			len = NAMEDATALEN;
			buf = NameStr(*namebuf);

			/* adjust length to not include trailing blanks */
			if (len > 1)
				len = ignoreblanks((char *) buf, len);
			break;
		
		/*
		 * ====== OBJECT IDENTIFIER TYPES ======
		 */
		case OIDOID:				/* object identifier(oid), maximum 4 billion */
		case REGPROCOID:			/* function name */
		case REGPROCEDUREOID:		/* function name with argument types */
		case REGOPEROID:			/* operator name */
		case REGOPERATOROID:		/* operator with argument types */
		case REGCLASSOID:			/* relation name */
		case REGTYPEOID:			/* data type name */
			intbuf = (int64) DatumGetUInt32(datum);	/* cast to 8 byte before hashing */
			buf = &intbuf;
			len = sizeof(intbuf);
			break;

        case TIDOID:                /* tuple id (6 bytes) */
            buf = DatumGetPointer(datum);
            len = SizeOfIptrData;
            break;
			
		/*
		 * ====== DATE/TIME TYPES ======
		 */
		case TIMESTAMPOID:		/* date and time */
			tsbuf = DatumGetTimestamp(datum);
			buf = &tsbuf;
			len = sizeof(tsbuf);
			break;

		case TIMESTAMPTZOID:	/* date and time with time zone */
			tstzbuf = DatumGetTimestampTz(datum);
			buf = &tstzbuf;
			len = sizeof(tstzbuf);
			break;

		case DATEOID:			/* ANSI SQL date */
			datebuf = DatumGetDateADT(datum);
			buf = &datebuf;
			len = sizeof(datebuf);
			break;

		case TIMEOID:			/* hh:mm:ss, ANSI SQL time */
			timebuf = DatumGetTimeADT(datum);
			buf = &timebuf;
			len = sizeof(timebuf);
			break;

		case TIMETZOID: /* time with time zone */
			
			/*
			 * will not compare to TIMEOID on equal values.
			 * Postgres never attempts to compare the two as well.
			 */
			timetzptr = DatumGetTimeTzADTP(datum);
			buf = (unsigned char *) timetzptr;
			
			/*
			 * Specify hash length as sizeof(double) + sizeof(int4), not as
			 * sizeof(TimeTzADT), so that any garbage pad bytes in the structure
			 * won't be included in the hash!
			 */
			len = sizeof(timetzptr->time) + sizeof(timetzptr->zone);
			break;

		case INTERVALOID:		/* @ <number> <units>, time interval */
			intervalptr = DatumGetIntervalP(datum);
			buf = (unsigned char *) intervalptr;
			/*
			 * Specify hash length as sizeof(double) + sizeof(int4), not as
			 * sizeof(Interval), so that any garbage pad bytes in the structure
			 * won't be included in the hash!
			 */
			len = sizeof(intervalptr->time) + sizeof(intervalptr->month);
			break;
			
		case ABSTIMEOID:
			abstime_buf = DatumGetAbsoluteTime(datum);
			
			if (abstime_buf == INVALID_ABSTIME)
			{
				/* hash to a constant value */
				invalidbuf = INVALID_VAL;
				len = sizeof(invalidbuf);
				buf = &invalidbuf;
			}
			else
			{
				len = sizeof(abstime_buf);
				buf = &abstime_buf;
			}
					
			break;

		case RELTIMEOID:
			reltime_buf = DatumGetRelativeTime(datum);
			
			if (reltime_buf == INVALID_RELTIME)
			{
				/* hash to a constant value */
				invalidbuf = INVALID_VAL;
				len = sizeof(invalidbuf);
				buf = &invalidbuf;
			}
			else
			{
				len = sizeof(reltime_buf);
				buf = &reltime_buf;
			}
				
			break;
			
		case TINTERVALOID:
			tinterval = DatumGetTimeInterval(datum);
			
			/*
			 * check if a valid interval. the '0' status code
			 * stands for T_INTERVAL_INVAL which is defined in
			 * nabstime.c. We use the actual value instead
			 * of defining it again here.
			 */
			if(tinterval->status == 0 ||
			   tinterval->data[0] == INVALID_ABSTIME ||
			   tinterval->data[1] == INVALID_ABSTIME)
			{
				/* hash to a constant value */
				invalidbuf = INVALID_VAL;
				len = sizeof(invalidbuf);
				buf = &invalidbuf;				
			}
			else
			{
				/* normalize on length of the time interval */
				tinterval_len = tinterval->data[1] -  tinterval->data[0];
				len = sizeof(tinterval_len);
				buf = &tinterval_len;	
			}

			break;
			
		/*
		 * ======= NETWORK TYPES ========
		 */
		case INETOID:
		case CIDROID:
			
			inetptr = DatumGetInetP(datum);
			len = inet_getkey(inetptr, inet_hkey, sizeof(inet_hkey)); /* fill-in inet_key & get len */
			buf = inet_hkey;
			break;
		
		case MACADDROID:
			
			macptr = DatumGetMacaddrP(datum);
			len = sizeof(macaddr);
			buf = (unsigned char *) macptr;
			break;
			
		/*
		 * ======== BIT STRINGS ========
		 */
		case BITOID:
		case VARBITOID:
			
			/*
			 * Note that these are essentially strings.
			 * we don't need to worry about '10' and '010'
			 * to compare, b/c they will not, by design.
			 * (see SQL standard, and varbit.c)
			 */
			vbitptr = DatumGetVarBitP(datum);
			len = VARBITBYTES(vbitptr);
			buf = (char *) VARBITS(vbitptr);
			break;

		/*
		 * ======= other types =======
		 */
		case BOOLOID:			/* boolean, 'true'/'false' */
			bool_buf = DatumGetBool(datum);
			buf = &bool_buf;
			len = sizeof(bool_buf);
			break;
			
		/*
		 * We prepare the hash key for aclitems just like postgresql does.
		 * (see code and comment in acl.c: hash_aclitem() ).
		 */
		case ACLITEMOID:
			aclitem_ptr = DatumGetAclItemP(datum);
			aclitem_buf = (uint32) (aclitem_ptr->ai_privs + aclitem_ptr->ai_grantee + aclitem_ptr->ai_grantor);
			buf = &aclitem_buf;
			len = sizeof(aclitem_buf);
			break;
			
		/*
		 * ANYARRAY is a pseudo-type. We use it to include
		 * any of the array types (OIDs 1007-1033 in pg_type.h).
		 * caller needs to be sure the type is ANYARRAYOID
		 * before calling cdbhash on an array (INSERT and COPY do so).
		 */
		case ANYARRAYOID:	
					
			arrbuf = DatumGetArrayTypeP(datum);
			len = VARSIZE(arrbuf) - VARHDRSZ;
			buf = VARDATA(arrbuf);
			break;
			
		case INT2VECTOROID:
			i2vec_buf = (int2vector *) DatumGetPointer(datum);
			len = i2vec_buf->dim1 * sizeof(int2);
			buf = (void *)i2vec_buf->values;
			break;
			
		case OIDVECTOROID:	
			oidvec_buf = (oidvector *) DatumGetPointer(datum);
			len = oidvec_buf->dim1 * sizeof(Oid);
			buf = oidvec_buf->values;
			break;
			
		case CASHOID: /* cash is stored in int32 internally */
			cash_buf = (* (Cash *)DatumGetPointer(datum));
			len = sizeof(Cash);
			buf = &cash_buf;
			break;
				
		default:
			ereport(ERROR,
					(errcode(ERRCODE_CDB_FEATURE_NOT_YET),
					 errmsg("Type %u is not hashable.", type)));

	}							/* switch(type) */

	/* do the hash using the selected algorithm */
	hashFn(clientData, buf, len);
	if(tofree)
		pfree(tofree);
}
예제 #10
0
Datum generate_sparse_vector(PG_FUNCTION_ARGS)
{
    SvecType    *output_sfv;
    int16_t     typlen;
	bool        typbyval;
	char        typalign;
	bool        *nulls;

	if (PG_NARGS() != 3)
		elog(ERROR, "Invalid number of arguments.");

	ArrayType   *term_index = PG_GETARG_ARRAYTYPE_P(0);
	ArrayType   *term_count = PG_GETARG_ARRAYTYPE_P(1);

	int64_t dict_size = PG_GETARG_INT64(2);

	/* Check if arrays have null entries */
	if (ARR_HASNULL(term_index) || ARR_HASNULL(term_count))
		elog(ERROR, "One or both of the argument arrays has one or more null entries.");

	if (dict_size <= 0)
		elog(ERROR, "Dictionary size cannot be zero or negative.");

	/* Check if any of the argument arrays is empty */
	if ((ARR_NDIM(term_index) == 0) || (ARR_NDIM(term_count) == 0))
		elog(ERROR, "One or more argument arrays is empty.");

	int term_index_nelems = ARR_DIMS(term_index)[0];
	int term_count_nelems = ARR_DIMS(term_count)[0];


	/* If no. of elements in the arrays are not equal, throw an error */
	if (term_index_nelems != term_count_nelems)
		elog(ERROR, "No. of elements in the argument arrays are not equal.");

	Datum *term_index_data;
	Datum *term_count_data;

	/* Deconstruct the arrays */
	get_typlenbyvalalign(INT8OID, &typlen, &typbyval, &typalign);
	deconstruct_array(term_index, INT8OID, typlen, typbyval, typalign,
	                  &term_index_data, &nulls, &term_index_nelems);

	get_typlenbyvalalign(FLOAT8OID, &typlen, &typbyval, &typalign);
	deconstruct_array(term_count, FLOAT8OID, typlen, typbyval, typalign,
	                  &term_count_data, &nulls, &term_count_nelems);

	/* Check if term index array has indexes in proper order or not */
	for(int i = 0; i < term_index_nelems; i++)
	{
		if (DatumGetInt64(term_index_data[i]) < 0 ||
                DatumGetInt64(term_index_data[i]) >= dict_size)
			elog(ERROR, "Term indexes must range from 0 to total number of elements in the dictonary - 1.");
	}
        

    float8 *histogram = (float8 *)palloc0(sizeof(float8) * dict_size);
    for (int k = 0; k < dict_size; k++)
    {
        histogram[k] = 0;
    }
    for (int i = 0; i < term_index_nelems; i++)
    {
        uint64_t idx = DatumGetInt64(term_index_data[i]);
        histogram[idx] += DatumGetFloat8(term_count_data[i]);
    }

    output_sfv = svec_from_float8arr(histogram, dict_size);
    pfree(histogram);

    PG_RETURN_POINTER(output_sfv);
}
GISTENTRY *
gbt_num_compress(GISTENTRY *retval, GISTENTRY *entry, const gbtree_ninfo *tinfo)
{
	if (entry->leafkey)
	{
		union
		{
			int16		i2;
			int32		i4;
			int64		i8;
			float4		f4;
			float8		f8;
			DateADT		dt;
			TimeADT		tm;
			Timestamp	ts;
			Cash		ch;
		}			v;

		GBT_NUMKEY *r = (GBT_NUMKEY *) palloc0(2 * tinfo->size);
		void	   *leaf = NULL;

		switch (tinfo->t)
		{
			case gbt_t_int2:
				v.i2 = DatumGetInt16(entry->key);
				leaf = &v.i2;
				break;
			case gbt_t_int4:
				v.i4 = DatumGetInt32(entry->key);
				leaf = &v.i4;
				break;
			case gbt_t_int8:
				v.i8 = DatumGetInt64(entry->key);
				leaf = &v.i8;
				break;
			case gbt_t_oid:
				v.i4 = DatumGetObjectId(entry->key);
				leaf = &v.i4;
				break;
			case gbt_t_float4:
				v.f4 = DatumGetFloat4(entry->key);
				leaf = &v.f4;
				break;
			case gbt_t_float8:
				v.f8 = DatumGetFloat8(entry->key);
				leaf = &v.f8;
				break;
			case gbt_t_date:
				v.dt = DatumGetDateADT(entry->key);
				leaf = &v.dt;
				break;
			case gbt_t_time:
				v.tm = DatumGetTimeADT(entry->key);
				leaf = &v.tm;
				break;
			case gbt_t_ts:
				v.ts = DatumGetTimestamp(entry->key);
				leaf = &v.ts;
				break;
			case gbt_t_cash:
				v.ch = DatumGetCash(entry->key);
				leaf = &v.ch;
				break;
			default:
				leaf = DatumGetPointer(entry->key);
		}

		memcpy((void *) &r[0], leaf, tinfo->size);
		memcpy((void *) &r[tinfo->size], leaf, tinfo->size);
		retval = palloc(sizeof(GISTENTRY));
		gistentryinit(*retval, PointerGetDatum(r), entry->rel, entry->page,
					  entry->offset, FALSE);
	}
	else
		retval = entry;

	return retval;
}
예제 #12
0
void
ParquetColumnReader_readPATH(
		ParquetColumnReader readers[],
		Datum *value,
		bool *null)
{
	PATH *path;
	Datum child_values[3] = {0};	/* is_open, points.x, points.y */
	bool  child_nulls[3] = {0};
	int npts, maxnpts;

	ParquetColumnReader_readValue(&readers[0], &child_values[0], &child_nulls[0], HAWQ_TYPE_BOOL);
	if (child_nulls[0])
	{
		ParquetColumnReader_readValue(&readers[1], &child_values[1], &child_nulls[1], HAWQ_TYPE_FLOAT8);
		ParquetColumnReader_readValue(&readers[2], &child_values[2], &child_nulls[2], HAWQ_TYPE_FLOAT8);
		Insist(child_nulls[1] && child_nulls[2]);
		*null = true;
		return;
	}

	npts = 0;
	path = readers[0].geoval;
	if (path == NULL)
	{
		maxnpts = 10;
		path = (PATH *)palloc0(get_path_size(maxnpts));
	}
	else
	{
		maxnpts = path->npts;
	}
	path->closed = !DatumGetBool(child_values[0]);

	while (true)
	{
		if (npts >= maxnpts)
		{
			maxnpts *= 2;
			path = (PATH *)repalloc(path, get_path_size(maxnpts));
		}
		
		ParquetColumnReader_readValue(&readers[1], &child_values[1], &child_nulls[1], HAWQ_TYPE_FLOAT8);
		ParquetColumnReader_readValue(&readers[2], &child_values[2], &child_nulls[2], HAWQ_TYPE_FLOAT8);
		
		path->p[npts].x = DatumGetFloat8(child_values[1]);
		path->p[npts].y = DatumGetFloat8(child_values[2]);
		npts++;

		if (NextRepetitionLevel(&readers[1]) == 0)
			break;	/* no more points in this path */
	}

	path = (PATH *)repalloc(path, get_path_size(npts));
	SET_VARSIZE(path, get_path_size(npts));
	path->npts = npts;

	*value = PointerGetDatum(path);
	*null = false;

	readers[0].geoval = path;
}
Datum
gbt_numeric_penalty(PG_FUNCTION_ARGS)
{
	GISTENTRY  *o = (GISTENTRY *) PG_GETARG_POINTER(0);
	GISTENTRY  *n = (GISTENTRY *) PG_GETARG_POINTER(1);
	float	   *result = (float *) PG_GETARG_POINTER(2);

	Numeric		us,
				os,
				ds;

	GBT_VARKEY *org = (GBT_VARKEY *) DatumGetPointer(o->key);
	GBT_VARKEY *newe = (GBT_VARKEY *) DatumGetPointer(n->key);
	Datum		uni;
	GBT_VARKEY_R rk,
				ok,
				uk;

	rk = gbt_var_key_readable(org);
	uni = PointerGetDatum(gbt_var_key_copy(&rk, TRUE));
	gbt_var_bin_union(&uni, newe, &tinfo);
	ok = gbt_var_key_readable(org);
	uk = gbt_var_key_readable((GBT_VARKEY *) DatumGetPointer(uni));

	us = DatumGetNumeric(DirectFunctionCall2(
											 numeric_sub,
											 PointerGetDatum(uk.upper),
											 PointerGetDatum(uk.lower)
											 ));

	os = DatumGetNumeric(DirectFunctionCall2(
											 numeric_sub,
											 PointerGetDatum(ok.upper),
											 PointerGetDatum(ok.lower)
											 ));

	ds = DatumGetNumeric(DirectFunctionCall2(
											 numeric_sub,
											 NumericGetDatum(us),
											 NumericGetDatum(os)
											 ));

	if (numeric_is_nan(us))
	{
		if (numeric_is_nan(os))
			*result = 0.0;
		else
			*result = 1.0;
	}
	else
	{
		Numeric		nul = DatumGetNumeric(DirectFunctionCall1(int4_numeric, Int32GetDatum(0)));

		*result = 0.0;

		if (DirectFunctionCall2(numeric_gt, NumericGetDatum(ds), NumericGetDatum(nul)))
		{
			*result += FLT_MIN;
			os = DatumGetNumeric(DirectFunctionCall2(
													 numeric_div,
													 NumericGetDatum(ds),
													 NumericGetDatum(us)
													 ));
			*result += (float4) DatumGetFloat8(DirectFunctionCall1(numeric_float8_no_overflow, NumericGetDatum(os)));
		}
	}

	if (*result > 0)
		*result *= (FLT_MAX / (((GISTENTRY *) PG_GETARG_POINTER(0))->rel->rd_att->natts + 1));

	PG_RETURN_POINTER(result);
}
예제 #14
0
static jvalue _Double_coerceDatum(Type self, Datum arg)
{
	jvalue result;
	result.l = JNI_newObject(s_Double_class, s_Double_init, DatumGetFloat8(arg));
	return result;
}
예제 #15
0
static jvalue _double_coerceDatum(Type self, Datum arg)
{
	jvalue result;
	result.d = DatumGetFloat8(arg);
	return result;
}
예제 #16
0
파일: algorithm.c 프로젝트: Khalefa/Miracle
double 
getNextValue(ModelInfo *model, int num) 
{
	return DatumGetFloat8(FunctionCall2(&model->algInfo->algGetNextValue,PointerGetDatum(model->model),Int32GetDatum(num)));
}
예제 #17
0
파일: tsp2.c 프로젝트: mrdapotts/pgrouting
static DTYPE *get_pgarray(int *num, ArrayType *input)
{
    int         ndims, *dims, *lbs;
    bool       *nulls;
    Oid         i_eltype;
    int16       i_typlen;
    bool        i_typbyval;
    char        i_typalign;
    Datum      *i_data;
    int         i, n;
    DTYPE      *data;

    /* get input array element type */
    i_eltype = ARR_ELEMTYPE(input);
    get_typlenbyvalalign(i_eltype, &i_typlen, &i_typbyval, &i_typalign);


    /* validate input data type */
    switch(i_eltype) {
    case INT2OID:
    case INT4OID:
    case FLOAT4OID:
    case FLOAT8OID:
        break;
    default:
        elog(ERROR, "Invalid input data type");
        break;
    }

    /* get various pieces of data from the input array */
    ndims = ARR_NDIM(input);
    dims = ARR_DIMS(input);
    lbs = ARR_LBOUND(input);

    if (ndims != 2 || dims[0] != dims[1]) {
        elog(ERROR, "Error: matrix[num][num] in its definition.");
    }

    /* get src data */
    deconstruct_array(input, i_eltype, i_typlen, i_typbyval, i_typalign,
                      &i_data, &nulls, &n);

    DBG("get_pgarray: ndims=%d, n=%d", ndims, n);

#ifdef DEBUG
    for (i=0; i<ndims; i++) {
        DBG("   dims[%d]=%d, lbs[%d]=%d", i, dims[i], i, lbs[i]);
    }
#endif

    /* construct a C array */
    data = (DTYPE *) palloc(n * sizeof(DTYPE));
    if (!data) {
        elog(ERROR, "Error: Out of memory!");
    }

    for (i=0; i<n; i++) {
        if (nulls[i]) {
            data[i] = INFINITY;
        }
        else {
            switch(i_eltype) {
            case INT2OID:
                data[i] = (DTYPE) DatumGetInt16(i_data[i]);
                break;
            case INT4OID:
                data[i] = (DTYPE) DatumGetInt32(i_data[i]);
                break;
            case FLOAT4OID:
                data[i] = (DTYPE) DatumGetFloat4(i_data[i]);
                break;
            case FLOAT8OID:
                data[i] = (DTYPE) DatumGetFloat8(i_data[i]);
                break;
            }
            /* we assume negative values are INFINTY */
            /********************************************************
               TODO: based on trying to add an endpt it is likely
               that this will not work and you will get and error in
               findEulerianPath
            **********************************************************/
            if (data[i] < 0)
                data[i] = INFINITY;
        }
        DBG("    data[%d]=%.4f", i, data[i]);
    }

    pfree(nulls);
    pfree(i_data);

    *num = dims[0];

    return data;
}
예제 #18
0
/*
 * Reading quantiles from an input array, based mostly on
 * array_to_text_internal (it's a modified copy). This expects
 * to receive a single-dimensional float8 array as input, fails
 * otherwise.
 */
static double *
array_to_double(FunctionCallInfo fcinfo, ArrayType *v, int * len)
{
    double     *result;
    int         nitems,
               *dims,
                ndims;
    Oid         element_type;
    int         typlen;
    bool        typbyval;
    char        typalign;
    char       *p;
    int         i, idx = 0;
    
    ArrayMetaState *my_extra;

    ndims = ARR_NDIM(v);
    dims = ARR_DIMS(v);
    nitems = ArrayGetNItems(ndims, dims);
    
    /* this is a special-purpose function for single-dimensional arrays */
    if (ndims != 1) {
        elog(ERROR, "error, array_to_double expects a single-dimensional array"
                    "(dims = %d)", ndims);
    }

    /* if there are no elements, set the length to 0 and return NULL */
    if (nitems == 0) {
        (*len) = 0;
        return NULL;
    }
    
    element_type = ARR_ELEMTYPE(v);
    
    result = (double*)palloc(nitems * sizeof(double));

    /*
     * We arrange to look up info about element type, including its output
     * conversion proc, only once per series of calls, assuming the element
     * type doesn't change underneath us.
     */
    my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
    if (my_extra == NULL)
    {
        fcinfo->flinfo->fn_extra = MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
                                                      sizeof(ArrayMetaState));
        my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
        my_extra->element_type = ~element_type;
    }

    if (my_extra->element_type != element_type)
    {
        /*
         * Get info about element type, including its output conversion proc
         */
        get_type_io_data(element_type, IOFunc_output,
                         &my_extra->typlen, &my_extra->typbyval,
                         &my_extra->typalign, &my_extra->typdelim,
                         &my_extra->typioparam, &my_extra->typiofunc);
        fmgr_info_cxt(my_extra->typiofunc, &my_extra->proc,
                      fcinfo->flinfo->fn_mcxt);
        my_extra->element_type = element_type;
    }
    
    typlen = my_extra->typlen;
    typbyval = my_extra->typbyval;
    typalign = my_extra->typalign;
    
    p = ARR_DATA_PTR(v);

    for (i = 0; i < nitems; i++) {

        Datum itemvalue = fetch_att(p, typbyval, typlen);
        
        double val = DatumGetFloat8(itemvalue);
        
        result[idx++] = val;
        
        p = att_addlength_pointer(p, typlen, p);
        p = (char *) att_align_nominal(p, typalign);

    }
    
    (*len) = idx;

    return result;
}
예제 #19
0
int create_spatial_index(sqlite3 *db,char  *dataset_name, char *idx_tbl,char * idx_geom, char *idx_id, char *sql_string, int create)
{
	char sql_txt_pg[SQLSTRLEN];
	char sql_txt_sqlite[SQLSTRLEN];
	int rc;
	char *err_msg;
	SPIPlanPtr plan;
	sqlite3_stmt *prepared_statement;
	Portal cur;
	char *pg_type;
	int val_int, proc,j;
	float8 val_float;
	
	int64 val_int64;
	bool null_check;
		TupleDesc tupdesc;
	SPITupleTable *tuptable;
	HeapTuple tuple;
	int tot_rows = 0;
	
	if(create)
	{
		snprintf(sql_txt_pg,sizeof(sql_txt_pg), " %s%s%s",
		"CREATE VIRTUAL TABLE ",
		dataset_name,
		"_idx_geom USING rtree(id,minX, maxX,minY, maxY)");
		
			rc = sqlite3_exec(db, sql_txt_pg, NULL, 0, &err_msg);
		    
		    if (rc != SQLITE_OK ) {	
			    sqlite3_free(err_msg);
			sqlite3_close(db);	
			    ereport(ERROR,  ( errmsg("Problem creating table: %s", err_msg)));
			//fprintf(stderr, "SQL error: %s\n", err_msg);		
		    } 	
		   elog(INFO, "create table string: %s", sql_txt_pg); 
    }
	snprintf(sql_txt_pg,sizeof(sql_txt_pg), " %s%s%s%s%s%s%s%s%s",
	"with o as (",
	    sql_string,
	    "), g as( select ",
	idx_id,
	" id,", 
	idx_geom,
	" geom from ",
	    idx_tbl,
	    ") select g.id, st_xmin(g.geom) minx,st_xmax(g.geom) maxx,st_ymin(g.geom) miny,st_ymax(g.geom) maxy from g inner join o on g.id=o.id");

	   elog(INFO, "select table string: %s", sql_txt_pg); 
	plan =  SPI_prepare(sql_txt_pg,0,NULL);
	//ret = SPI_exec(sql_string, 0);
	cur = SPI_cursor_open("index_cursor", plan,NULL,NULL,true);

	snprintf(sql_txt_sqlite,sizeof(sql_txt_sqlite), " %s%s%s",
	"insert into ",
	dataset_name,
	"_idx_geom  (id,minX, maxX,minY, maxY) values(?,?,?,?,?)"); 
  
  
	   elog(INFO, "insert table string: %s", sql_txt_sqlite); 
	    
	     sqlite3_prepare_v2(db,sql_txt_sqlite,strlen(sql_txt_sqlite), &prepared_statement,NULL);
	     
	     
	do
	{
		
	sqlite3_exec(db, "BEGIN TRANSACTION", NULL, NULL, &err_msg);
		
		SPI_cursor_fetch(cur, true,100000);
		
		proc = SPI_processed;
		tot_rows += proc;
//	    if (ret > 0 && SPI_tuptable != NULL)
//	    {
		    
		 tupdesc = SPI_tuptable->tupdesc;
		tuptable = SPI_tuptable;
		

		for (j = 0; j < proc; j++)
		{
			
		    tuple = tuptable->vals[j];

				pg_type = SPI_gettype(tupdesc, 1);
				

				if(strcmp(pg_type, "int2")==0)
				{			
					val_int = (int) DatumGetInt16(SPI_getbinval(tuple,tupdesc,1, &null_check));
					//TODO add error handling
					if(null_check)
						sqlite3_bind_null(prepared_statement, 1);
					else
					sqlite3_bind_int(prepared_statement, 1,val_int);
				}
				else if(strcmp(pg_type, "int4")==0)
				{			
					val_int = (int) DatumGetInt32(SPI_getbinval(tuple,tupdesc,1, &null_check));
					//TODO add error handling
					if(null_check)
						sqlite3_bind_null(prepared_statement, 1);
					else
					sqlite3_bind_int(prepared_statement, 1,val_int);
					
				}	
				else if(strcmp(pg_type, "int8")==0)
				{			
					val_int64 = (int64) DatumGetInt64(SPI_getbinval(tuple,tupdesc,1, &null_check));
					//TODO add error handling
					if(null_check)
						sqlite3_bind_null(prepared_statement, 1);
					else
					sqlite3_bind_int64(prepared_statement,1,val_int64);
				}	



	
					val_float = (float8) DatumGetFloat8(SPI_getbinval(tuple,tupdesc,2, &null_check));
					//TODO add error handling
					if(null_check)
						sqlite3_bind_null(prepared_statement, 2);
					else
					sqlite3_bind_double(prepared_statement,2,val_float);
				
					val_float = (float8) DatumGetFloat8(SPI_getbinval(tuple,tupdesc,3, &null_check));
					//TODO add error handling
					if(null_check)
						sqlite3_bind_null(prepared_statement, 3);
					else
					sqlite3_bind_double(prepared_statement,3,val_float);
				
					val_float = (float8) DatumGetFloat8(SPI_getbinval(tuple,tupdesc,4, &null_check));
					//TODO add error handling
					if(null_check)
						sqlite3_bind_null(prepared_statement, 4);
					else
					sqlite3_bind_double(prepared_statement,4,val_float);
				
					val_float = (float8) DatumGetFloat8(SPI_getbinval(tuple,tupdesc,5, &null_check));
					//TODO add error handling
					if(null_check)
						sqlite3_bind_null(prepared_statement, 5);
					else
					sqlite3_bind_double(prepared_statement,5,val_float);
				
					
					
					
		
	    	sqlite3_step(prepared_statement);	
		sqlite3_clear_bindings(prepared_statement);
				sqlite3_reset(prepared_statement);
		}
		
	sqlite3_exec(db, "END TRANSACTION", NULL, NULL, &err_msg);
	elog(INFO, "inserted %d rows in index",tot_rows);
	}
	while (proc > 0);
	   
	    
	    
	    
	return 0;
}
예제 #20
0
/*
 * Get relative position of value in histogram bin in [0,1] range.
 */
static float8
get_position(TypeCacheEntry *typcache, RangeBound *value, RangeBound *hist1,
			 RangeBound *hist2)
{
	bool		has_subdiff = OidIsValid(typcache->rng_subdiff_finfo.fn_oid);
	float8		position;

	if (!hist1->infinite && !hist2->infinite)
	{
		float8		bin_width;

		/*
		 * Both bounds are finite. Assuming the subtype's comparison function
		 * works sanely, the value must be finite, too, because it lies
		 * somewhere between the bounds. If it doesn't, just return something.
		 */
		if (value->infinite)
			return 0.5;

		/* Can't interpolate without subdiff function */
		if (!has_subdiff)
			return 0.5;

		/* Calculate relative position using subdiff function. */
		bin_width = DatumGetFloat8(FunctionCall2Coll(
												&typcache->rng_subdiff_finfo,
													 typcache->rng_collation,
													 hist2->val,
													 hist1->val));
		if (bin_width <= 0.0)
			return 0.5;			/* zero width bin */

		position = DatumGetFloat8(FunctionCall2Coll(
												&typcache->rng_subdiff_finfo,
													typcache->rng_collation,
													value->val,
													hist1->val))
			/ bin_width;

		/* Relative position must be in [0,1] range */
		position = Max(position, 0.0);
		position = Min(position, 1.0);
		return position;
	}
	else if (hist1->infinite && !hist2->infinite)
	{
		/*
		 * Lower bin boundary is -infinite, upper is finite. If the value is
		 * -infinite, return 0.0 to indicate it's equal to the lower bound.
		 * Otherwise return 1.0 to indicate it's infinitely far from the lower
		 * bound.
		 */
		return ((value->infinite && value->lower) ? 0.0 : 1.0);
	}
	else if (!hist1->infinite && hist2->infinite)
	{
		/* same as above, but in reverse */
		return ((value->infinite && !value->lower) ? 1.0 : 0.0);
	}
	else
	{
		/*
		 * If both bin boundaries are infinite, they should be equal to each
		 * other, and the value should also be infinite and equal to both
		 * bounds. (But don't Assert that, to avoid crashing if a user creates
		 * a datatype with a broken comparison function).
		 *
		 * Assume the value to lie in the middle of the infinite bounds.
		 */
		return 0.5;
	}
}
예제 #21
0
int write2sqlite(char *sqlitedb_name,char *dataset_name, char *sql_string, char *twkb_name,char *id_name,char *idx_geom,char *idx_tbl, char *idx_id, int create)
{
	char *err_msg;
	int spi_conn;
	int  proc, rc;
	/*Sqlite*/
	sqlite3 *db;
	TupleDesc tupdesc;
	SPITupleTable *tuptable;
	HeapTuple tuple;
	int i, j;
	SPIPlanPtr plan;
	char insert_str[SQLSTRLEN];
	Portal cur;
	void *val_p;
	int val_int;
	int64 val_int64;
	float8 val_float;
	bool null_check;
	char *pg_type;	
	int tot_rows = 0;
	
	sqlite3_stmt *prepared_statement;
	
	spi_conn = SPI_connect();
	if (spi_conn!=SPI_OK_CONNECT)
		ereport(ERROR,  ( errmsg("Failed to open SPI Connection")));
	
	/*Open the sqlite db to write to*/
	rc = sqlite3_open(sqlitedb_name, &db);
		
		
	if (rc != SQLITE_OK) {	
		sqlite3_close(db);			
		ereport(ERROR,  ( errmsg("Cannot open SQLite database")));
	}
	
	plan =  SPI_prepare(sql_string,0,NULL);
	//ret = SPI_exec(sql_string, 0);
	cur = SPI_cursor_open("our_cursor", plan,NULL,NULL,true);

	
	elog(INFO, "build sql-strings and create table if : %d",create);
		create_sqlite_table(&cur,db, insert_str,dataset_name,twkb_name, id_name,create);
	
	   elog(INFO, "back from creating table"); 
	elog(INFO, "inserted sql = %s",insert_str);
//TODO add error handling	
 sqlite3_prepare_v2(db,insert_str,strlen(insert_str), &prepared_statement,NULL);

	do
	{
		
	sqlite3_exec(db, "BEGIN TRANSACTION", NULL, NULL, &err_msg);
		
		SPI_cursor_fetch(cur, true,10000);
		
		proc = SPI_processed;
		
		tot_rows += proc;
//	    if (ret > 0 && SPI_tuptable != NULL)
//	    {
		    
		 tupdesc = SPI_tuptable->tupdesc;
		tuptable = SPI_tuptable;
		

		for (j = 0; j < proc; j++)
		{
			
		    tuple = tuptable->vals[j];


		    for (i = 1; i <= tupdesc->natts; i++)
			{
					pg_type = SPI_gettype(tupdesc, i);						
				if(strcmp(pg_type, "bool")==0)
				{			
					val_int = (bool) (DatumGetBool(SPI_getbinval(tuple,tupdesc,i, &null_check)) ? 1:0);
					if(null_check)
						sqlite3_bind_null(prepared_statement, i);
					else
					sqlite3_bind_int(prepared_statement, i,(int) val_int);
				}
				if(strcmp(pg_type, "int2")==0)
				{			
					val_int = (int) DatumGetInt16(SPI_getbinval(tuple,tupdesc,i, &null_check));
					//TODO add error handling
					if(null_check)
						sqlite3_bind_null(prepared_statement, i);
					else
					sqlite3_bind_int(prepared_statement, i,val_int);
				}
				else if(strcmp(pg_type, "int4")==0)
				{			
					val_int = (int) DatumGetInt32(SPI_getbinval(tuple,tupdesc,i, &null_check));
					//TODO add error handling
					if(null_check)
						sqlite3_bind_null(prepared_statement, i);
					else
					sqlite3_bind_int(prepared_statement, i,val_int);
					
				}	
				else if(strcmp(pg_type, "int8")==0)
				{			
					val_int64 = (int64) DatumGetInt64(SPI_getbinval(tuple,tupdesc,i, &null_check));
					//TODO add error handling
					if(null_check)
						sqlite3_bind_null(prepared_statement, i);
					else
					sqlite3_bind_int64(prepared_statement, i,val_int64);
				}			
				else if(strcmp(pg_type, "float4")==0)
				{			
					val_float = (float8) DatumGetFloat4(SPI_getbinval(tuple,tupdesc,i, &null_check));
					//TODO add error handling
					if(null_check)
						sqlite3_bind_null(prepared_statement, i);
					else
					sqlite3_bind_double(prepared_statement, i,val_float);
					
				}
				else if(strcmp(pg_type, "float8")==0)
				{			
					val_float = (float8) DatumGetFloat8(SPI_getbinval(tuple,tupdesc,i, &null_check));
					//TODO add error handling
					if(null_check)
						sqlite3_bind_null(prepared_statement, i);
					else
					sqlite3_bind_double(prepared_statement, i,val_float);
				}	
				else if(strcmp(pg_type, "bytea")==0)
				{			
					val_p = (void*) PG_DETOAST_DATUM(SPI_getbinval(tuple,tupdesc,i, &null_check));
					//TODO add error handling
					if(null_check)
						sqlite3_bind_null(prepared_statement, i);
					else
					sqlite3_bind_blob(prepared_statement, i, (const void*) VARDATA_ANY(val_p), VARSIZE_ANY(val_p)-VARHDRSZ, SQLITE_TRANSIENT);
				}		
				else
				{			
				//	val = (void*) PG_DETOAST_DATUM(SPI_getbinval(tuple,tupdesc,i, &null_check));
					//TODO add error handling
					sqlite3_bind_text(prepared_statement,i,SPI_getvalue(tuple, tupdesc, i),-1,NULL);
				}		

		}
	    			sqlite3_step(prepared_statement);	
		sqlite3_clear_bindings(prepared_statement);
				sqlite3_reset(prepared_statement);
		}
		
	sqlite3_exec(db, "END TRANSACTION", NULL, NULL, &err_msg);
		
	elog(INFO, "inserted %d rows in table",tot_rows);
	}
	while (proc > 0);
	
	if(dataset_name && idx_geom && idx_id)
		create_spatial_index(db,dataset_name,idx_tbl, idx_geom, idx_id, sql_string,create);
	else
		elog(INFO, "Finnishing without spatial index");
	
	SPI_finish();
	    sqlite3_close(db);
	    
return 0;
}
예제 #22
0
/**
 * Returns a histogram from an array of numbers.
 * by Paul A. Jungwirth
 */
Datum
array_to_hist(PG_FUNCTION_ARGS)
{
  // Our arguments:
  ArrayType *vals;
  pgnum bucketsStart;
  pgnum bucketsSize;
  int32 bucketsCount;

  // The array element type:
  Oid valsType;

  // The array element type widths for our input and output arrays:
  int16 valsTypeWidth;
  int16 histTypeWidth;

  // The array element type "is passed by value" flags (not really used):
  bool valsTypeByValue;
  bool histTypeByValue;

  // The array element type alignment codes (not really used):
  char valsTypeAlignmentCode;
  char histTypeAlignmentCode;

  // The array contents, as PostgreSQL "Datum" objects:
  Datum *valsContent;
  Datum *histContent;

  // List of "is null" flags for the array contents (not used):
  bool *valsNullFlags;

  // The size of the input array:
  int valsLength;

  // The output array:
  ArrayType* histArray;

  pgnum histMax;
  pgnum v;
  int i;

  if (PG_ARGISNULL(0) || PG_ARGISNULL(1) || PG_ARGISNULL(2) || PG_ARGISNULL(3)) {
    ereport(ERROR, (errmsg("Null arguments not accepted")));
  }

  vals = PG_GETARG_ARRAYTYPE_P(0);

  if (ARR_NDIM(vals) > 1) {
    ereport(ERROR, (errmsg("One-dimesional arrays are required")));
  }

  if (array_contains_nulls(vals)) {
    ereport(ERROR, (errmsg("Array contains null elements")));
  }

  // Determine the array element types.
  valsType = ARR_ELEMTYPE(vals);

  if (valsType != INT2OID &&
      valsType != INT4OID &&
      valsType != INT8OID &&
      valsType != FLOAT4OID &&
      valsType != FLOAT8OID) {
    ereport(ERROR, (errmsg("Histogram subject must be SMALLINT, INTEGER, BIGINT, REAL, or DOUBLE PRECISION values")));
  }

  valsLength = (ARR_DIMS(vals))[0];

  switch (valsType) {
    case INT2OID:
      bucketsStart.i16 = PG_GETARG_INT16(1);
      bucketsSize.i16 = PG_GETARG_INT16(2);
      break;
    case INT4OID:
      bucketsStart.i32 = PG_GETARG_INT32(1);
      bucketsSize.i32 = PG_GETARG_INT32(2);
      break;
    case INT8OID:
      bucketsStart.i64 = PG_GETARG_INT64(1);
      bucketsSize.i64 = PG_GETARG_INT64(2);
      break;
    case FLOAT4OID:
      bucketsStart.f4 = PG_GETARG_FLOAT4(1);
      bucketsSize.f4 = PG_GETARG_FLOAT4(2);
      break;
    case FLOAT8OID:
      bucketsStart.f8 = PG_GETARG_FLOAT8(1);
      bucketsSize.f8 = PG_GETARG_FLOAT8(2);
      break;
    default:
      break;
  }
  bucketsCount = PG_GETARG_INT32(3);

  get_typlenbyvalalign(valsType, &valsTypeWidth, &valsTypeByValue, &valsTypeAlignmentCode);

  // Extract the array contents (as Datum objects).
  deconstruct_array(vals, valsType, valsTypeWidth, valsTypeByValue, valsTypeAlignmentCode,
&valsContent, &valsNullFlags, &valsLength);

  // Create a new array of histogram bins (as Datum objects).
  // Memory we palloc is freed automatically at the end of the transaction.
  histContent = palloc0(sizeof(Datum) * bucketsCount);

  // Generate the histogram
  switch (valsType) {
    case INT2OID:
      histMax.i16 = bucketsStart.i16 + (bucketsSize.i16 * bucketsCount);
      for (i = 0; i < valsLength; i++) {
        v.i16 = DatumGetInt16(valsContent[i]);
        if (v.i16 >= bucketsStart.i16 && v.i16 <= histMax.i16) {
          int b = (v.i16 - bucketsStart.i16) / bucketsSize.i16;
          if (b >= 0 && b < bucketsCount) {
            histContent[b] = Int32GetDatum(DatumGetInt32(histContent[b]) + 1);
          }
        }
      }
      break;
    case INT4OID:
      histMax.i32 = bucketsStart.i32 + (bucketsSize.i32 * bucketsCount);
      for (i = 0; i < valsLength; i++) {
        v.i32 = DatumGetInt32(valsContent[i]);
        if (v.i32 >= bucketsStart.i32 && v.i32 <= histMax.i32) {
          int b = (v.i32 - bucketsStart.i32) / bucketsSize.i32;
          if (b >= 0 && b < bucketsCount) {
            histContent[b] = Int32GetDatum(DatumGetInt32(histContent[b]) + 1);
          }
        }
      }
      break;
    case INT8OID:
      histMax.i64 = bucketsStart.i64 + (bucketsSize.i64 * bucketsCount);
      for (i = 0; i < valsLength; i++) {
        v.i64 = DatumGetInt64(valsContent[i]);
        if (v.i64 >= bucketsStart.i64 && v.i64 <= histMax.i64) {
          int b = (v.i64 - bucketsStart.i64) / bucketsSize.i64;
          if (b >= 0 && b < bucketsCount) {
            histContent[b] = Int64GetDatum(DatumGetInt64(histContent[b]) + 1);
          }
        }
      }
      break;
    case FLOAT4OID:
      histMax.f4 = bucketsStart.f4 + (bucketsSize.f4 * bucketsCount);
      for (i = 0; i < valsLength; i++) {
        v.f4 = DatumGetFloat4(valsContent[i]);
        if (v.f4 >= bucketsStart.f4 && v.f4 <= histMax.f4) {
          int b = (v.f4 - bucketsStart.f4) / bucketsSize.f4;
          if (b >= 0 && b < bucketsCount) {
            histContent[b] = Int32GetDatum(DatumGetInt32(histContent[b]) + 1);
          }
        }
      }
      break;
    case FLOAT8OID:
      histMax.f8 = bucketsStart.f8 + (bucketsSize.f8 * bucketsCount);
      for (i = 0; i < valsLength; i++) {
        v.f8 = DatumGetFloat8(valsContent[i]);
        if (v.f8 >= bucketsStart.f8 && v.f8 <= histMax.f8) {
          int b = (v.f8 - bucketsStart.f8) / bucketsSize.f8;
          if (b >= 0 && b < bucketsCount) {
            histContent[b] = Int32GetDatum(DatumGetInt32(histContent[b]) + 1);
          }
        }
      }
      break;
    default:
      break;
  }

  // Wrap the buckets in a new PostgreSQL array object.
  get_typlenbyvalalign(INT4OID, &histTypeWidth, &histTypeByValue, &histTypeAlignmentCode);
  histArray = construct_array(histContent, bucketsCount, INT4OID, histTypeWidth, histTypeByValue, histTypeAlignmentCode);

  // Return the final PostgreSQL array object.
  PG_RETURN_ARRAYTYPE_P(histArray);
}
예제 #23
0
파일: gistget.c 프로젝트: Brar/postgres
/*
 * gistindex_keytest() -- does this index tuple satisfy the scan key(s)?
 *
 * The index tuple might represent either a heap tuple or a lower index page,
 * depending on whether the containing page is a leaf page or not.
 *
 * On success return for a heap tuple, *recheck_p is set to indicate whether
 * the quals need to be rechecked.  We recheck if any of the consistent()
 * functions request it.  recheck is not interesting when examining a non-leaf
 * entry, since we must visit the lower index page if there's any doubt.
 * Similarly, *recheck_distances_p is set to indicate whether the distances
 * need to be rechecked, and it is also ignored for non-leaf entries.
 *
 * If we are doing an ordered scan, so->distances[] is filled with distance
 * data from the distance() functions before returning success.
 *
 * We must decompress the key in the IndexTuple before passing it to the
 * sk_funcs (which actually are the opclass Consistent or Distance methods).
 *
 * Note that this function is always invoked in a short-lived memory context,
 * so we don't need to worry about cleaning up allocated memory, either here
 * or in the implementation of any Consistent or Distance methods.
 */
static bool
gistindex_keytest(IndexScanDesc scan,
				  IndexTuple tuple,
				  Page page,
				  OffsetNumber offset,
				  bool *recheck_p,
				  bool *recheck_distances_p)
{
	GISTScanOpaque so = (GISTScanOpaque) scan->opaque;
	GISTSTATE  *giststate = so->giststate;
	ScanKey		key = scan->keyData;
	int			keySize = scan->numberOfKeys;
	double	   *distance_p;
	Relation	r = scan->indexRelation;

	*recheck_p = false;
	*recheck_distances_p = false;

	/*
	 * If it's a leftover invalid tuple from pre-9.1, treat it as a match with
	 * minimum possible distances.  This means we'll always follow it to the
	 * referenced page.
	 */
	if (GistTupleIsInvalid(tuple))
	{
		int			i;

		if (GistPageIsLeaf(page))	/* shouldn't happen */
			elog(ERROR, "invalid GiST tuple found on leaf page");
		for (i = 0; i < scan->numberOfOrderBys; i++)
			so->distances[i] = -get_float8_infinity();
		return true;
	}

	/* Check whether it matches according to the Consistent functions */
	while (keySize > 0)
	{
		Datum		datum;
		bool		isNull;

		datum = index_getattr(tuple,
							  key->sk_attno,
							  giststate->tupdesc,
							  &isNull);

		if (key->sk_flags & SK_ISNULL)
		{
			/*
			 * On non-leaf page we can't conclude that child hasn't NULL
			 * values because of assumption in GiST: union (VAL, NULL) is VAL.
			 * But if on non-leaf page key IS NULL, then all children are
			 * NULL.
			 */
			if (key->sk_flags & SK_SEARCHNULL)
			{
				if (GistPageIsLeaf(page) && !isNull)
					return false;
			}
			else
			{
				Assert(key->sk_flags & SK_SEARCHNOTNULL);
				if (isNull)
					return false;
			}
		}
		else if (isNull)
		{
			return false;
		}
		else
		{
			Datum		test;
			bool		recheck;
			GISTENTRY	de;

			gistdentryinit(giststate, key->sk_attno - 1, &de,
						   datum, r, page, offset,
						   false, isNull);

			/*
			 * Call the Consistent function to evaluate the test.  The
			 * arguments are the index datum (as a GISTENTRY*), the comparison
			 * datum, the comparison operator's strategy number and subtype
			 * from pg_amop, and the recheck flag.
			 *
			 * (Presently there's no need to pass the subtype since it'll
			 * always be zero, but might as well pass it for possible future
			 * use.)
			 *
			 * We initialize the recheck flag to true (the safest assumption)
			 * in case the Consistent function forgets to set it.
			 */
			recheck = true;

			test = FunctionCall5Coll(&key->sk_func,
									 key->sk_collation,
									 PointerGetDatum(&de),
									 key->sk_argument,
									 Int16GetDatum(key->sk_strategy),
									 ObjectIdGetDatum(key->sk_subtype),
									 PointerGetDatum(&recheck));

			if (!DatumGetBool(test))
				return false;
			*recheck_p |= recheck;
		}

		key++;
		keySize--;
	}

	/* OK, it passes --- now let's compute the distances */
	key = scan->orderByData;
	distance_p = so->distances;
	keySize = scan->numberOfOrderBys;
	while (keySize > 0)
	{
		Datum		datum;
		bool		isNull;

		datum = index_getattr(tuple,
							  key->sk_attno,
							  giststate->tupdesc,
							  &isNull);

		if ((key->sk_flags & SK_ISNULL) || isNull)
		{
			/* Assume distance computes as null and sorts to the end */
			*distance_p = get_float8_infinity();
		}
		else
		{
			Datum		dist;
			bool		recheck;
			GISTENTRY	de;

			gistdentryinit(giststate, key->sk_attno - 1, &de,
						   datum, r, page, offset,
						   false, isNull);

			/*
			 * Call the Distance function to evaluate the distance.  The
			 * arguments are the index datum (as a GISTENTRY*), the comparison
			 * datum, the ordering operator's strategy number and subtype from
			 * pg_amop, and the recheck flag.
			 *
			 * (Presently there's no need to pass the subtype since it'll
			 * always be zero, but might as well pass it for possible future
			 * use.)
			 *
			 * If the function sets the recheck flag, the returned distance is
			 * a lower bound on the true distance and needs to be rechecked.
			 * We initialize the flag to 'false'.  This flag was added in
			 * version 9.5; distance functions written before that won't know
			 * about the flag, but are expected to never be lossy.
			 */
			recheck = false;
			dist = FunctionCall5Coll(&key->sk_func,
									 key->sk_collation,
									 PointerGetDatum(&de),
									 key->sk_argument,
									 Int16GetDatum(key->sk_strategy),
									 ObjectIdGetDatum(key->sk_subtype),
									 PointerGetDatum(&recheck));
			*recheck_distances_p |= recheck;
			*distance_p = DatumGetFloat8(dist);
		}

		key++;
		distance_p++;
		keySize--;
	}

	return true;
}
예제 #24
0
/*
 * GetFileSegInfo
 *
 * Get the catalog entry for an appendonly (row-oriented) relation from the
 * pg_aoseg_* relation that belongs to the currently used
 * AppendOnly table.
 *
 * If a caller intends to append to this file segment entry they must
 * already hold a relation Append-Only segment file (transaction-scope) lock (tag
 * LOCKTAG_RELATION_APPENDONLY_SEGMENT_FILE) in order to guarantee
 * stability of the pg_aoseg information on this segment file and exclusive right
 * to append data to the segment file.
 */
ParquetFileSegInfo *
GetParquetFileSegInfo(Relation parentrel, AppendOnlyEntry *aoEntry,
		Snapshot parquetMetaDataSnapshot, int segno) {

	Relation pg_parquetseg_rel;
	TupleDesc pg_parquetseg_dsc;
	HeapTuple tuple;
	ScanKeyData key[1];
	SysScanDesc parquetscan;
	Datum eof, eof_uncompressed, tupcount;
	bool isNull;
	bool indexOK;
	Oid indexid;
	ParquetFileSegInfo *fsinfo;

	/*
	 * Check the pg_paqseg relation to be certain the parquet table segment file
	 * is there.
	 */
	pg_parquetseg_rel = heap_open(aoEntry->segrelid, AccessShareLock);
	pg_parquetseg_dsc = RelationGetDescr(pg_parquetseg_rel);

	if (Gp_role == GP_ROLE_EXECUTE) {
		indexOK = FALSE;
		indexid = InvalidOid;
	} else {
		indexOK = TRUE;
		indexid = aoEntry->segidxid;
	}

	/*
	 * Setup a scan key to fetch from the index by segno.
	 */
	ScanKeyInit(&key[0], (AttrNumber) Anum_pg_parquetseg_segno,
			BTEqualStrategyNumber, F_INT4EQ, Int32GetDatum(segno));

	parquetscan = systable_beginscan(pg_parquetseg_rel, indexid, indexOK,
			SnapshotNow, 1, &key[0]);

	tuple = systable_getnext(parquetscan);

	if (!HeapTupleIsValid(tuple)) {
		/* This segment file does not have an entry. */
		systable_endscan(parquetscan);
		heap_close(pg_parquetseg_rel, AccessShareLock);
		return NULL ;
	}

	tuple = heap_copytuple(tuple);

	systable_endscan(parquetscan);

	Assert(HeapTupleIsValid(tuple));

	fsinfo = (ParquetFileSegInfo *) palloc0(sizeof(ParquetFileSegInfo));

	/* get the eof */
	eof = fastgetattr(tuple, Anum_pg_parquetseg_eof, pg_parquetseg_dsc,
			&isNull);

	if (isNull)
		ereport(ERROR,
				(errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("got invalid eof value: NULL")));

	/* get the tupcount */
	tupcount = fastgetattr(tuple, Anum_pg_parquetseg_tupcount,
			pg_parquetseg_dsc, &isNull);

	if (isNull)
		ereport(ERROR,
				(errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("got invalid tupcount value: NULL")));

	/* get the uncompressed eof */
	eof_uncompressed = fastgetattr(tuple, Anum_pg_parquetseg_eofuncompressed,
			pg_parquetseg_dsc, &isNull);
	/*
	 * Confusing: This eof_uncompressed variable is never used.  It appears we only
	 * call fastgetattr to get the isNull value.  this variable "eof_uncompressed" is
	 * not at all the same as fsinfo->eof_uncompressed.
	 */

	if (isNull) {
		/*
		 * NULL is allowed. Tables that were created before the release of the
		 * eof_uncompressed catalog column will have a NULL instead of a value.
		 */
		fsinfo->eof_uncompressed = InvalidUncompressedEof;
	} else {
		fsinfo->eof_uncompressed = (int64) DatumGetFloat8(eof_uncompressed);
	}

	fsinfo->segno = segno;
	fsinfo->eof = (int64) DatumGetFloat8(eof);
	fsinfo->tupcount = (int64) DatumGetFloat8(tupcount);

	ItemPointerSetInvalid(&fsinfo->sequence_tid);

	if (fsinfo->eof < 0)
		ereport(ERROR,
				(errcode(ERRCODE_GP_INTERNAL_ERROR),
						errmsg("invalid eof " INT64_FORMAT " for relation %s",
								fsinfo->eof,
								RelationGetRelationName(parentrel))));

	/* Finish up scan and close appendonly catalog. */
	heap_close(pg_parquetseg_rel, AccessShareLock);

	return fsinfo;
}
예제 #25
0
void
ParquetColumnReader_readPOLYGON(
		ParquetColumnReader readers[],
		Datum *value,
		bool *null)
{
	POLYGON *polygon;
	Datum child_values[6] = {0};	/* boundbox:{x1,y1,x2,y2}, points:{x,y} */
	bool  child_nulls[6] = {0};
	int npts, maxnpts;

	/*
	 * read BOX boundbox
	 */
	ParquetColumnReader_readValue(&readers[0], &child_values[0], &child_nulls[0], HAWQ_TYPE_FLOAT8);
	ParquetColumnReader_readValue(&readers[1], &child_values[1], &child_nulls[1], HAWQ_TYPE_FLOAT8);
	ParquetColumnReader_readValue(&readers[2], &child_values[2], &child_nulls[2], HAWQ_TYPE_FLOAT8);
	ParquetColumnReader_readValue(&readers[3], &child_values[3], &child_nulls[3], HAWQ_TYPE_FLOAT8);

	Insist(child_nulls[0] == child_nulls[1] &&
		   child_nulls[2] == child_nulls[3] &&
		   child_nulls[0] == child_nulls[2]);
	
	if (child_nulls[0])
	{
		ParquetColumnReader_readValue(&readers[4], &child_values[4], &child_nulls[4], HAWQ_TYPE_FLOAT8);
		ParquetColumnReader_readValue(&readers[5], &child_values[5], &child_nulls[5], HAWQ_TYPE_FLOAT8);
		Insist(child_nulls[4] && child_nulls[5]);
		*null = true;
		return;
	}

	npts = 0;
	polygon = readers[0].geoval;
	if (polygon == NULL)
	{
		maxnpts = 10;
		polygon = palloc(get_polygon_size(maxnpts));
	}
	else
	{
		maxnpts = polygon->npts;
	}

	polygon->boundbox.high.x = DatumGetFloat8(child_values[0]);
	polygon->boundbox.high.y = DatumGetFloat8(child_values[1]);
	polygon->boundbox.low.x = DatumGetFloat8(child_values[2]);
	polygon->boundbox.low.y = DatumGetFloat8(child_values[3]);

	/*
	 * read repeated points
	 */
	while (true)
	{
		if (npts >= maxnpts)
		{
			maxnpts *= 2;
			polygon = repalloc(polygon, get_polygon_size(maxnpts));
		}
		
		ParquetColumnReader_readValue(&readers[4], &child_values[4], &child_nulls[4], HAWQ_TYPE_FLOAT8);
		ParquetColumnReader_readValue(&readers[5], &child_values[5], &child_nulls[5], HAWQ_TYPE_FLOAT8);
		
		polygon->p[npts].x = DatumGetFloat8(child_values[4]);
		polygon->p[npts].y = DatumGetFloat8(child_values[5]);
		npts++;

		if (NextRepetitionLevel(&readers[4]) == 0)
			break;	/* no more points in this polygon */
	}

	polygon = repalloc(polygon, get_polygon_size(npts));
	SET_VARSIZE(polygon, get_polygon_size(npts));
	polygon->npts = npts;

	*value = PointerGetDatum(polygon);
	*null = false;

	readers[0].geoval = polygon;
}
예제 #26
0
Datum
spg_kd_inner_consistent(PG_FUNCTION_ARGS)
{
	spgInnerConsistentIn *in = (spgInnerConsistentIn *) PG_GETARG_POINTER(0);
	spgInnerConsistentOut *out = (spgInnerConsistentOut *) PG_GETARG_POINTER(1);
	double		coord;
	int			which;
	int			i;

	Assert(in->hasPrefix);
	coord = DatumGetFloat8(in->prefixDatum);

	if (in->allTheSame)
		elog(ERROR, "allTheSame should not occur for k-d trees");

	Assert(in->nNodes == 2);

	/* "which" is a bitmask of children that satisfy all constraints */
	which = (1 << 1) | (1 << 2);

	for (i = 0; i < in->nkeys; i++)
	{
		Point	   *query = DatumGetPointP(in->scankeys[i].sk_argument);
		BOX		   *boxQuery;

		switch (in->scankeys[i].sk_strategy)
		{
			case RTLeftStrategyNumber:
				if ((in->level % 2) != 0 && FPlt(query->x, coord))
					which &= (1 << 1);
				break;
			case RTRightStrategyNumber:
				if ((in->level % 2) != 0 && FPgt(query->x, coord))
					which &= (1 << 2);
				break;
			case RTSameStrategyNumber:
				if ((in->level % 2) != 0)
				{
					if (FPlt(query->x, coord))
						which &= (1 << 1);
					else if (FPgt(query->x, coord))
						which &= (1 << 2);
				}
				else
				{
					if (FPlt(query->y, coord))
						which &= (1 << 1);
					else if (FPgt(query->y, coord))
						which &= (1 << 2);
				}
				break;
			case RTBelowStrategyNumber:
				if ((in->level % 2) == 0 && FPlt(query->y, coord))
					which &= (1 << 1);
				break;
			case RTAboveStrategyNumber:
				if ((in->level % 2) == 0 && FPgt(query->y, coord))
					which &= (1 << 2);
				break;
			case RTContainedByStrategyNumber:

				/*
				 * For this operator, the query is a box not a point.  We
				 * cheat to the extent of assuming that DatumGetPointP won't
				 * do anything that would be bad for a pointer-to-box.
				 */
				boxQuery = DatumGetBoxP(in->scankeys[i].sk_argument);

				if ((in->level % 2) != 0)
				{
					if (FPlt(boxQuery->high.x, coord))
						which &= (1 << 1);
					else if (FPgt(boxQuery->low.x, coord))
						which &= (1 << 2);
				}
				else
				{
					if (FPlt(boxQuery->high.y, coord))
						which &= (1 << 1);
					else if (FPgt(boxQuery->low.y, coord))
						which &= (1 << 2);
				}
				break;
			default:
				elog(ERROR, "unrecognized strategy number: %d",
					 in->scankeys[i].sk_strategy);
				break;
		}

		if (which == 0)
			break;				/* no need to consider remaining conditions */
	}

	/* We must descend into the children identified by which */
	out->nodeNumbers = (int *) palloc(sizeof(int) * 2);
	out->nNodes = 0;
	for (i = 1; i <= 2; i++)
	{
		if (which & (1 << i))
			out->nodeNumbers[out->nNodes++] = i - 1;
	}

	/* Set up level increments, too */
	out->levelAdds = (int *) palloc(sizeof(int) * 2);
	out->levelAdds[0] = 1;
	out->levelAdds[1] = 1;

	PG_RETURN_VOID();
}
예제 #27
0
/*
 * Calculate the average of function P(x), in the interval [length1, length2],
 * where P(x) is the fraction of tuples with length < x (or length <= x if
 * 'equal' is true).
 */
static double
calc_length_hist_frac(Datum *length_hist_values, int length_hist_nvalues,
					  double length1, double length2, bool equal)
{
	double		frac;
	double		A,
				B,
				PA,
				PB;
	double		pos;
	int			i;
	double		area;

	Assert(length2 >= length1);

	if (length2 < 0.0)
		return 0.0;				/* shouldn't happen, but doesn't hurt to check */

	/* All lengths in the table are <= infinite. */
	if (is_infinite(length2) && equal)
		return 1.0;

	/*----------
	 * The average of a function between A and B can be calculated by the
	 * formula:
	 *
	 *			B
	 *	  1		/
	 * -------	| P(x)dx
	 *	B - A	/
	 *			A
	 *
	 * The geometrical interpretation of the integral is the area under the
	 * graph of P(x). P(x) is defined by the length histogram. We calculate
	 * the area in a piecewise fashion, iterating through the length histogram
	 * bins. Each bin is a trapezoid:
	 *
	 *		 P(x2)
	 *		  /|
	 *		 / |
	 * P(x1)/  |
	 *	   |   |
	 *	   |   |
	 *	---+---+--
	 *	   x1  x2
	 *
	 * where x1 and x2 are the boundaries of the current histogram, and P(x1)
	 * and P(x1) are the cumulative fraction of tuples at the boundaries.
	 *
	 * The area of each trapezoid is 1/2 * (P(x2) + P(x1)) * (x2 - x1)
	 *
	 * The first bin contains the lower bound passed by the caller, so we
	 * use linear interpolation between the previous and next histogram bin
	 * boundary to calculate P(x1). Likewise for the last bin: we use linear
	 * interpolation to calculate P(x2). For the bins in between, x1 and x2
	 * lie on histogram bin boundaries, so P(x1) and P(x2) are simply:
	 * P(x1) =	  (bin index) / (number of bins)
	 * P(x2) = (bin index + 1 / (number of bins)
	 */

	/* First bin, the one that contains lower bound */
	i = length_hist_bsearch(length_hist_values, length_hist_nvalues, length1, equal);
	if (i >= length_hist_nvalues - 1)
		return 1.0;

	if (i < 0)
	{
		i = 0;
		pos = 0.0;
	}
	else
	{
		/* interpolate length1's position in the bin */
		pos = get_len_position(length1,
							   DatumGetFloat8(length_hist_values[i]),
							   DatumGetFloat8(length_hist_values[i + 1]));
	}
	PB = (((double) i) + pos) / (double) (length_hist_nvalues - 1);
	B = length1;

	/*
	 * In the degenerate case that length1 == length2, simply return
	 * P(length1). This is not merely an optimization: if length1 == length2,
	 * we'd divide by zero later on.
	 */
	if (length2 == length1)
		return PB;

	/*
	 * Loop through all the bins, until we hit the last bin, the one that
	 * contains the upper bound. (if lower and upper bounds are in the same
	 * bin, this falls out immediately)
	 */
	area = 0.0;
	for (; i < length_hist_nvalues - 1; i++)
	{
		double		bin_upper = DatumGetFloat8(length_hist_values[i + 1]);

		/* check if we've reached the last bin */
		if (!(bin_upper < length2 || (equal && bin_upper <= length2)))
			break;

		/* the upper bound of previous bin is the lower bound of this bin */
		A = B;
		PA = PB;

		B = bin_upper;
		PB = (double) i / (double) (length_hist_nvalues - 1);

		/*
		 * Add the area of this trapezoid to the total. The point of the
		 * if-check is to avoid NaN, in the corner case that PA == PB == 0,
		 * and B - A == Inf. The area of a zero-height trapezoid (PA == PB ==
		 * 0) is zero, regardless of the width (B - A).
		 */
		if (PA > 0 || PB > 0)
			area += 0.5 * (PB + PA) * (B - A);
	}

	/* Last bin */
	A = B;
	PA = PB;

	B = length2;				/* last bin ends at the query upper bound */
	if (i >= length_hist_nvalues - 1)
		pos = 0.0;
	else
	{
		if (DatumGetFloat8(length_hist_values[i]) == DatumGetFloat8(length_hist_values[i + 1]))
			pos = 0.0;
		else
			pos = get_len_position(length2, DatumGetFloat8(length_hist_values[i]), DatumGetFloat8(length_hist_values[i + 1]));
	}
	PB = (((double) i) + pos) / (double) (length_hist_nvalues - 1);

	if (PA > 0 || PB > 0)
		area += 0.5 * (PB + PA) * (B - A);

	/*
	 * Ok, we have calculated the area, ie. the integral. Divide by width to
	 * get the requested average.
	 *
	 * Avoid NaN arising from infinite / infinite. This happens at least if
	 * length2 is infinite. It's not clear what the correct value would be in
	 * that case, so 0.5 seems as good as any value.
	 */
	if (is_infinite(area) && is_infinite(length2))
		frac = 0.5;
	else
		frac = area / (length2 - length1);

	return frac;
}
예제 #28
0
Datum
alpine_miner_nn_ca_o(PG_FUNCTION_ARGS)
{

	ArrayType  *weight_arg, *columns_arg, *input_range_arg, *input_base_arg,*hidden_node_number_arg, *result;
    Datum     *weight_data, *columns_data, *input_range_data, *input_base_data, *hidden_node_number_data, *result_data;
    bool       *weight_nulls, *columns_nulls, *input_range_nulls, *input_base_nulls, *hidden_node_number_nulls,*result_nulls;
	int         weight_count, columns_count, input_range_count, input_base_count, hidden_node_number_count,result_count ;
    Oid         result_eltype;
	int16 result_typlen;
	bool result_typbyval;
	char result_typalign;

	double output_range_arg,output_base_arg;
	int hidden_layer_number_arg, output_node_no_arg;
	bool normalize_arg, numerical_label_arg ;
        int         ndims, *dims, *lbs;

	int i;
	int j;
	int k;

	int all_hidden_node_count;

	int weight_index;
	int hidden_node_number_index = 0;

	bool null_data;
	double * input;
	double * output;
	int * hidden_node_number;
	double *weight;
	double *hidden_node_output;
	if (PG_ARGISNULL(0) || PG_ARGISNULL(1) || PG_ARGISNULL(2) || PG_ARGISNULL(3) || PG_ARGISNULL(4) || PG_ARGISNULL(5) || PG_ARGISNULL(6) || PG_ARGISNULL(7) || PG_ARGISNULL(8) || PG_ARGISNULL(9) || PG_ARGISNULL(10))
	{
		PG_RETURN_NULL();
	}

        /* get weight_arg args */
        weight_arg = PG_GETARG_ARRAYTYPE_P(0);

	null_data = alpine_miner_deconstruct_array(weight_arg, &weight_data, &weight_nulls,&weight_count);
	if (null_data)
	{
		PG_RETURN_NULL();
	}

        columns_arg = PG_GETARG_ARRAYTYPE_P(1);
	null_data = alpine_miner_deconstruct_array(columns_arg, &columns_data, &columns_nulls,&columns_count);
	if (null_data)
	{
		PG_RETURN_NULL();
	}

    /* get input_range_arg args */
    input_range_arg = PG_GETARG_ARRAYTYPE_P(2);
	null_data = alpine_miner_deconstruct_array(input_range_arg, &input_range_data, &input_range_nulls,&input_range_count);
	if (null_data)
	{
		PG_RETURN_NULL();
	}

    /* get input_base_arg args */
    input_base_arg = PG_GETARG_ARRAYTYPE_P(3);
	null_data = alpine_miner_deconstruct_array(input_base_arg, &input_base_data, &input_base_nulls,&input_base_count);
	if (null_data)
	{
		PG_RETURN_NULL();
	}

    /* get hidden_node_number_arg args */
    hidden_node_number_arg = PG_GETARG_ARRAYTYPE_P(4);
	null_data = alpine_miner_deconstruct_array(hidden_node_number_arg, &hidden_node_number_data, &hidden_node_number_nulls,&hidden_node_number_count);
	if (null_data)
	{
		PG_RETURN_NULL();
	}

	hidden_layer_number_arg= PG_GETARG_INT32(5);

	output_range_arg = PG_GETARG_FLOAT8(6);
	output_base_arg = PG_GETARG_FLOAT8(7);
	output_node_no_arg  = PG_GETARG_INT32(8);
	normalize_arg = PG_GETARG_BOOL(9); 
	numerical_label_arg = PG_GETARG_BOOL(10); 

#ifdef ALPINE_DEBUG 
	elog(WARNING,"%f",DatumGetFloat8(columns_data[0]));
#endif
	input =  (double*)palloc(columns_count * sizeof(double));;




	output = (double*)palloc(output_node_no_arg * sizeof(double));
	hidden_node_number = (int*) palloc(hidden_node_number_count * sizeof(int));


	weight = (double*)palloc(weight_count * sizeof(double));
	for (i = 0; i < weight_count; i++)
	{
		weight[i] = DatumGetFloat8(weight_data[i]);
	}
	all_hidden_node_count = 0;
	for (i = 0; i < hidden_layer_number_arg; i++)
	{
		hidden_node_number[i] = DatumGetInt32(hidden_node_number_data[i]);
		all_hidden_node_count += hidden_node_number[i];
	}

	hidden_node_output = (double*)palloc(all_hidden_node_count * sizeof(double));


        /* get output array element type */
	result_eltype = FLOAT8OID;
        get_typlenbyvalalign(result_eltype, &result_typlen, &result_typbyval, &result_typalign);

        /* construct result array */
	result_count = output_node_no_arg;
        result_data = (Datum *)palloc(result_count * sizeof(Datum));
        result_nulls = (bool *)palloc(result_count * sizeof(bool));
	for (i = 0; i < result_count; i++)
	{
		result_nulls[i] = false;
	}

	//caculate input 
        if (normalize_arg) 
        {
            i = 0;
            while (i < columns_count)
            {
                if (DatumGetFloat8(input_range_data[i]) != 0)
                {
                   input[i] = ((DatumGetFloat8(columns_data[i])-DatumGetFloat8(input_base_data[i]))/DatumGetFloat8(input_range_data[i]));
		}
                else
		{
                   input[i] = (DatumGetFloat8(columns_data[i])-DatumGetFloat8(input_base_data[i]));
                }
#ifdef ALPINE_DEBUG 
		elog(WARNING, "input:%f", input[i]);
#endif
		i = i + 1;
            }
	}
        else
	{
		i = 0;
        	while (i < columns_count)
		{
               	    input[i] = DatumGetFloat8(columns_data[i]);
               	    i = i + 1;
        	}
	}

	// caculate hidden node output of 1st layer 
        i = 0;
        while (i < hidden_node_number[0])
	{
                hidden_node_output[i] = weight[0+i*(columns_count + 1)];
                j = 0;
                while (j < columns_count)
		{
                        hidden_node_output[i] = hidden_node_output[i]+input[j]*weight[1 + j  + i *(columns_count + 1)];
#ifdef ALPINE_DEBUG 
			elog(WARNING,"hiddensum[%d] input[%d] %f weight[%d] %f", i, j,input[j] , 1+j  +(i)*(columns_count +1), weight[1+j +i*(columns_count + 1)]);
#endif
                        j = j + 1;
		}

		if (hidden_node_output[i] < -45.0)
		{
			hidden_node_output[i] = 0;
		}
		else if (hidden_node_output[i] > 45.0)
		{
			hidden_node_output[i] = 1;
		}
		else
		{
            	    hidden_node_output[i] = (1.0/(1.0+exp( -1.0 * hidden_node_output[i])));
		}
#ifdef ALPINE_DEBUG 
		 elog(WARNING,"hidden[%d] %f", i, hidden_node_output[i]);
#endif
                i = i + 1;
	}
//       calculate hidden layer 2~last output
        weight_index = hidden_node_number[0] * (columns_count + 1) ;

        if (hidden_layer_number_arg > 1)
	{
	        hidden_node_number_index = 0;
	        i = 1;
	        while (i < hidden_layer_number_arg )
		{
	                hidden_node_number_index = hidden_node_number_index + hidden_node_number[i - 1];
	                j = 0;
	                while (j < hidden_node_number[i]) 
			{
	                        hidden_node_output[hidden_node_number_index + j] = weight[weight_index + (hidden_node_number[i - 1] +1) * j];
	                        k = 0;
	                        while (k < hidden_node_number[i - 1])
				{ 
	                                hidden_node_output[hidden_node_number_index + j] = hidden_node_output[hidden_node_number_index + j]+hidden_node_output[hidden_node_number_index - hidden_node_number[i - 1] + k]*weight[weight_index + (hidden_node_number[i - 1] +1) * j + k + 1];
	                                k = k + 1;
				}
				if (hidden_node_output[hidden_node_number_index + j] < -45.0)
				{
					hidden_node_output[hidden_node_number_index + j] = 0;
				}
				else if (hidden_node_output[hidden_node_number_index + j] > 45.0)
				{
					hidden_node_output[hidden_node_number_index + j] = 1;
				}
				else
				{
	                        	hidden_node_output[hidden_node_number_index + j] = (1.0/(1+exp(-1.0*hidden_node_output[hidden_node_number_index+j])));
				}
	                        j = j + 1;
	                }
	                weight_index = weight_index + hidden_node_number[i] * (hidden_node_number[i - 1] + 1);
	                i = i + 1;
	       }
        }

	//compute output value of  output node;
        i = 0;
        while (i < output_node_no_arg)
	{
                output[i] = weight[weight_index + (hidden_node_number[hidden_layer_number_arg-1]+1) * i];
#ifdef ALPINE_DEBUG 
		elog(WARNING,"weightindex:%d,weight[%d] %f",weight_index, weight_index + (hidden_node_number[hidden_layer_number_arg-1]+1) * i, output[i]);
#endif
                j = 0;
                while (j < hidden_node_number[hidden_layer_number_arg-1])
		{
#ifdef ALPINE_DEBUG 
			elog(WARNING,"ouput[%d]:%f ,hidden_node_number_index:%d,j:%d, weight[%d]:%f",i,output[i], hidden_node_number_index ,j,1+j + weight_index + (hidden_node_number[hidden_layer_number_arg-1]+1) * i , weight[1 + j + weight_index + (hidden_node_number[hidden_layer_number_arg-1]+1) * i ]);
#endif
                        output[i] = output[i]+hidden_node_output[hidden_node_number_index + j]
					* weight[1 + j + weight_index + (hidden_node_number[hidden_layer_number_arg-1]+1) * i ];
                        j = j + 1;
                }
#ifdef ALPINE_DEBUG 
		 elog(WARNING,"ouputsum[%d] %f", i, output[i]);
#endif
		if (numerical_label_arg)
		{
                	output[i] = ((output[i]) * output_range_arg+output_base_arg);
#ifdef ALPINE_DEBUG 
			elog(WARNING,"output:%f, %f,%f",output[i],output_range_arg,output_base_arg);
#endif
		}
		else
		{
			if (output[i] < -45.0)
			{
				output[i] = 0;
			}
			else if (output[i] > 45.0)
			{
				output[i] = 1;
			}
			else
			{
				output[i] = (1.0/(1+exp(-1.0*output[i])));
			}
		}
#ifdef ALPINE_DEBUG 
		 elog(WARNING,"ouputsum2[%d] %f", i, output[i]);
#endif
                i = i + 1;
	}



	ndims = 1;
	dims = (int *) palloc(sizeof(int));
	dims[0] = result_count;
	lbs = (int *) palloc(sizeof(int));
	lbs[0] = 1;
	for (i = 0; i < output_node_no_arg; i++)
	{
		result_data[i] = Float8GetDatum(output[i]);
#ifdef ALPINE_DEBUG 
		elog(WARNING,"output[%d]:%f",i, output[i]);
#endif
	}

	result = construct_md_array((void *)result_data, result_nulls, ndims, dims,
			lbs, result_eltype, result_typlen, result_typbyval, result_typalign);

//	pfree(result);
	pfree(weight_data);
	pfree(columns_data);
	pfree(input_range_data);
	pfree(input_base_data);
	pfree(hidden_node_number_data);
	pfree(result_data);
	pfree(weight_nulls);
	pfree(columns_nulls);
	pfree(input_range_nulls);
	pfree(input_base_nulls);
	pfree(hidden_node_number_nulls);
	pfree(result_nulls);
	pfree(input);
	pfree(output);
	pfree(lbs);
	pfree(dims);
	pfree(hidden_node_output);
	pfree(weight);
	pfree(hidden_node_number);

        PG_RETURN_ARRAYTYPE_P(result);
}
예제 #29
0
파일: gistget.c 프로젝트: adam8157/gpdb
/*
 * gistindex_keytest() -- does this index tuple satisfy the scan key(s)?
 *
 * The index tuple might represent either a heap tuple or a lower index page,
 * depending on whether the containing page is a leaf page or not.
 *
 * On success return for a heap tuple, *recheck_p is set to indicate
 * whether recheck is needed.  We recheck if any of the consistent() functions
 * request it.  recheck is not interesting when examining a non-leaf entry,
 * since we must visit the lower index page if there's any doubt.
 *
 * If we are doing an ordered scan, so->distances[] is filled with distance
 * data from the distance() functions before returning success.
 *
 * We must decompress the key in the IndexTuple before passing it to the
 * sk_funcs (which actually are the opclass Consistent or Distance methods).
 *
 * Note that this function is always invoked in a short-lived memory context,
 * so we don't need to worry about cleaning up allocated memory, either here
 * or in the implementation of any Consistent or Distance methods.
 */
static bool
gistindex_keytest(IndexScanDesc scan,
				  IndexTuple tuple,
				  Page page,
				  OffsetNumber offset,
				  bool *recheck_p)
{
	GISTScanOpaque so = (GISTScanOpaque) scan->opaque;
	GISTSTATE  *giststate = so->giststate;
	ScanKey		key = scan->keyData;
	int			keySize = scan->numberOfKeys;
	double	   *distance_p;
	Relation	r = scan->indexRelation;

	*recheck_p = false;

	/*
	 * If it's a leftover invalid tuple from pre-9.1, treat it as a match with
	 * minimum possible distances.  This means we'll always follow it to the
	 * referenced page.
	 *
	 * GPDB: the virtual TIDs created for AO tables use the full range of
	 * offset numbers from 0 to 65535. So a tuple on leaf page that looks like
	 * an invalid tuple, is actually ok.
	 */
	if (!GistPageIsLeaf(page) && GistTupleIsInvalid(tuple))
	{
		int			i;

		for (i = 0; i < scan->numberOfOrderBys; i++)
			so->distances[i] = -get_float8_infinity();
		return true;
	}

	/* Check whether it matches according to the Consistent functions */
	while (keySize > 0)
	{
		Datum		datum;
		bool		isNull;

		datum = index_getattr(tuple,
							  key->sk_attno,
							  giststate->tupdesc,
							  &isNull);

		if (key->sk_flags & SK_ISNULL)
		{
			/*
			 * On non-leaf page we can't conclude that child hasn't NULL
			 * values because of assumption in GiST: union (VAL, NULL) is VAL.
			 * But if on non-leaf page key IS NULL, then all children are
			 * NULL.
			 */
			if (key->sk_flags & SK_SEARCHNULL)
			{
				if (GistPageIsLeaf(page) && !isNull)
					return false;
			}
			else
			{
				Assert(key->sk_flags & SK_SEARCHNOTNULL);
				if (isNull)
					return false;
			}
		}
		else if (isNull)
		{
			return false;
		}
		else
		{
			Datum		test;
			bool		recheck;
			GISTENTRY	de;

			gistdentryinit(giststate, key->sk_attno - 1, &de,
						   datum, r, page, offset,
						   FALSE, isNull);

			/*
			 * Call the Consistent function to evaluate the test.  The
			 * arguments are the index datum (as a GISTENTRY*), the comparison
			 * datum, the comparison operator's strategy number and subtype
			 * from pg_amop, and the recheck flag.
			 *
			 * (Presently there's no need to pass the subtype since it'll
			 * always be zero, but might as well pass it for possible future
			 * use.)
			 *
			 * We initialize the recheck flag to true (the safest assumption)
			 * in case the Consistent function forgets to set it.
			 */
			recheck = true;

			test = FunctionCall5Coll(&key->sk_func,
									 key->sk_collation,
									 PointerGetDatum(&de),
									 key->sk_argument,
									 Int32GetDatum(key->sk_strategy),
									 ObjectIdGetDatum(key->sk_subtype),
									 PointerGetDatum(&recheck));

			if (!DatumGetBool(test))
				return false;
			*recheck_p |= recheck;
		}

		key++;
		keySize--;
	}

	/* OK, it passes --- now let's compute the distances */
	key = scan->orderByData;
	distance_p = so->distances;
	keySize = scan->numberOfOrderBys;
	while (keySize > 0)
	{
		Datum		datum;
		bool		isNull;

		datum = index_getattr(tuple,
							  key->sk_attno,
							  giststate->tupdesc,
							  &isNull);

		if ((key->sk_flags & SK_ISNULL) || isNull)
		{
			/* Assume distance computes as null and sorts to the end */
			*distance_p = get_float8_infinity();
		}
		else
		{
			Datum		dist;
			GISTENTRY	de;

			gistdentryinit(giststate, key->sk_attno - 1, &de,
						   datum, r, page, offset,
						   FALSE, isNull);

			/*
			 * Call the Distance function to evaluate the distance.  The
			 * arguments are the index datum (as a GISTENTRY*), the comparison
			 * datum, and the ordering operator's strategy number and subtype
			 * from pg_amop.
			 *
			 * (Presently there's no need to pass the subtype since it'll
			 * always be zero, but might as well pass it for possible future
			 * use.)
			 *
			 * Note that Distance functions don't get a recheck argument. We
			 * can't tolerate lossy distance calculations on leaf tuples;
			 * there is no opportunity to re-sort the tuples afterwards.
			 */
			dist = FunctionCall4Coll(&key->sk_func,
									 key->sk_collation,
									 PointerGetDatum(&de),
									 key->sk_argument,
									 Int32GetDatum(key->sk_strategy),
									 ObjectIdGetDatum(key->sk_subtype));

			*distance_p = DatumGetFloat8(dist);
		}

		key++;
		distance_p++;
		keySize--;
	}

	return true;
}
예제 #30
0
Datum
alpine_miner_nn_ca_change(PG_FUNCTION_ARGS)
{
    ArrayType  *weight_arg, *columns_arg, *input_range_arg, *input_base_arg,*hidden_node_number_arg, *result;
    Datum     *weight_data, *columns_data, *input_range_data, *input_base_data, *hidden_node_number_data, *result_data;
    bool       *weight_nulls, *columns_nulls, *input_range_nulls, *input_base_nulls, *hidden_node_number_nulls,*result_nulls;
	int         weight_count, columns_count, input_range_count, input_base_count, hidden_node_number_count,result_count ;
        Oid         result_eltype;
	int16 result_typlen;
	bool result_typbyval;
	char result_typalign;

	double output_range_arg,output_base_arg, learning_rate_ar, label_arg;
	int hidden_layer_number_arg, output_node_no_arg, set_size_arg;
	bool normalize_arg, numerical_label_arg ;
        int         ndims, *dims, *lbs;

	int i;
	int j;
	int k;

	int all_hidden_node_count;

	int weight_index;
	int hidden_node_number_index = 0;

	bool null_data;
	double * input;
	double * output;
	int * hidden_node_number;
	double *weight;
	double *hidden_node_output;

	double delta = 0.0;
	double total_error = 0.0;
	double * output_error;
	double direct_output_error = 0.0;

	double * hidden_node_error;
	double error_sum = 0.0;

	double current_change = 0.0;
	double threshold_change = 0.0;

	if (PG_ARGISNULL(0) || PG_ARGISNULL(1) || PG_ARGISNULL(2) || PG_ARGISNULL(3) || PG_ARGISNULL(4) || PG_ARGISNULL(5) || PG_ARGISNULL(6) || PG_ARGISNULL(7) || PG_ARGISNULL(8) || PG_ARGISNULL(9) || PG_ARGISNULL(10) || PG_ARGISNULL(11) || PG_ARGISNULL(12)){
		PG_RETURN_NULL();
	}

        /* get weight_arg args */
        weight_arg = PG_GETARG_ARRAYTYPE_P(0);

	null_data = alpine_miner_deconstruct_array(weight_arg, &weight_data, &weight_nulls,&weight_count);
	if (null_data)
	{
		PG_RETURN_NULL();
	}

        columns_arg = PG_GETARG_ARRAYTYPE_P(1);
	null_data = alpine_miner_deconstruct_array(columns_arg, &columns_data, &columns_nulls,&columns_count);
	if (null_data)
	{
		PG_RETURN_NULL();
	}

        /* get input_range_arg args */
        input_range_arg = PG_GETARG_ARRAYTYPE_P(2);
	null_data = alpine_miner_deconstruct_array(input_range_arg, &input_range_data, &input_range_nulls,&input_range_count);
	if (null_data)
	{
		PG_RETURN_NULL();
	}

        /* get input_base_arg args */
        input_base_arg = PG_GETARG_ARRAYTYPE_P(3);
	null_data = alpine_miner_deconstruct_array(input_base_arg, &input_base_data, &input_base_nulls,&input_base_count);
	if (null_data)
	{
		PG_RETURN_NULL();
	}

        /* get hidden_node_number_arg args */
        hidden_node_number_arg = PG_GETARG_ARRAYTYPE_P(4);
	null_data = alpine_miner_deconstruct_array(hidden_node_number_arg, &hidden_node_number_data, &hidden_node_number_nulls,&hidden_node_number_count);
	if (null_data)
	{
		PG_RETURN_NULL();
	}

	hidden_layer_number_arg= PG_GETARG_INT32(5);

	output_range_arg = PG_GETARG_FLOAT8(6);
	output_base_arg = PG_GETARG_FLOAT8(7);
	output_node_no_arg  = PG_GETARG_INT32(8);
	normalize_arg = PG_GETARG_BOOL(9); 
	numerical_label_arg = PG_GETARG_BOOL(10); 
	label_arg = PG_GETARG_FLOAT8(11);
	set_size_arg = PG_GETARG_INT32(12);
	if (set_size_arg <= 0)
	{
		set_size_arg = 1;
	}

#ifdef ALPINE_DEBUG 
	elog(WARNING,"%f",DatumGetFloat8(columns_data[0]));
#endif
	input =  (double*)palloc(columns_count * sizeof(double));;

	output = (double*)palloc(output_node_no_arg * sizeof(double));
	hidden_node_number = (int*) palloc(hidden_node_number_count * sizeof(int));

	weight = (double*)palloc(weight_count * sizeof(double));
	for (i = 0; i < weight_count; i++)
	{
		weight[i] = DatumGetFloat8(weight_data[i]);
	}
	all_hidden_node_count = 0;
	for (i = 0; i < hidden_layer_number_arg; i++)
	{
		hidden_node_number[i] = DatumGetInt32(hidden_node_number_data[i]);
		all_hidden_node_count += hidden_node_number[i];
	}

	hidden_node_output = (double*)palloc(all_hidden_node_count * sizeof(double));


	//caculate input 
        if (normalize_arg) 
        {
            i = 0;
            while (i < columns_count)
            {
                if (DatumGetFloat8(input_range_data[i]) != 0)
                {
                   input[i] = ((DatumGetFloat8(columns_data[i])-DatumGetFloat8(input_base_data[i]))/DatumGetFloat8(input_range_data[i]));
		}
                else
		{
                   input[i] = (DatumGetFloat8(columns_data[i])-DatumGetFloat8(input_base_data[i]));
                }
#ifdef ALPINE_DEBUG 
		elog(WARNING, "input:%f", input[i]);
#endif
		i = i + 1;
            }
	}
        else
	{
		i = 0;
        	while (i < columns_count)
		{
               	    input[i] = DatumGetFloat8(columns_data[i]);
               	    i = i + 1;
        	}
	}

	// caculate hidden node output of 1st layer 
        i = 0;
        while (i < hidden_node_number[0])
	{
                hidden_node_output[i] = weight[0+i*(columns_count + 1)];
                j = 0;
                while (j < columns_count)
		{
                        hidden_node_output[i] = hidden_node_output[i]+input[j]*weight[1 + j  + i *(columns_count + 1)];
#ifdef ALPINE_DEBUG 
			elog(WARNING,"hiddensum[%d] input[%d] %f weight[%d] %f", i, j,input[j] , 1+j  +(i)*(columns_count +1), weight[1+j +i*(columns_count + 1)]);
#endif
                        j = j + 1;
		}

		if (hidden_node_output[i] < -45.0)
		{
			hidden_node_output[i] = 0;
		}
		else if (hidden_node_output[i] > 45.0)
		{
			hidden_node_output[i] = 1;
		}
		else
		{
            	    hidden_node_output[i] = (1.0/(1.0+exp( -1.0 * hidden_node_output[i])));
		}
#ifdef ALPINE_DEBUG 
		 elog(WARNING,"hidden[%d] %f", i, hidden_node_output[i]);
#endif
                i = i + 1;
	}
//       calculate hidden layer 2~last output
        weight_index = hidden_node_number[0] * (columns_count + 1) ;

        if (hidden_layer_number_arg > 1)
	{
	        hidden_node_number_index = 0;
	        i = 1;
	        while (i < hidden_layer_number_arg )
		{
	                hidden_node_number_index = hidden_node_number_index + hidden_node_number[i - 1];
	                j = 0;
	                while (j < hidden_node_number[i]) 
			{
	                        hidden_node_output[hidden_node_number_index + j] = weight[weight_index + (hidden_node_number[i - 1] +1) * j];
	                        k = 0;
	                        while (k < hidden_node_number[i - 1])
				{ 
	                                hidden_node_output[hidden_node_number_index + j] = hidden_node_output[hidden_node_number_index + j]+hidden_node_output[hidden_node_number_index - hidden_node_number[i - 1] + k]*weight[weight_index + (hidden_node_number[i - 1] +1) * j + k + 1];
	                                k = k + 1;
				}
				if (hidden_node_output[hidden_node_number_index + j] < -45.0)
				{
					hidden_node_output[hidden_node_number_index + j] = 0;
				}
				else if (hidden_node_output[hidden_node_number_index + j] > 45.0)
				{
					hidden_node_output[hidden_node_number_index + j] = 1;
				}
				else
				{
	                        	hidden_node_output[hidden_node_number_index + j] = (1.0/(1+exp(-1.0*hidden_node_output[hidden_node_number_index+j])));
				}
	                        j = j + 1;
	                }
	                weight_index = weight_index + hidden_node_number[i] * (hidden_node_number[i - 1] + 1);
	                i = i + 1;
	       }
        }

	//compute output value of  output node;
        i = 0;
        while (i < output_node_no_arg)
		{
                output[i] = weight[weight_index + (hidden_node_number[hidden_layer_number_arg-1]+1) * i];
#ifdef ALPINE_DEBUG 
		elog(WARNING,"weightindex:%d,weight[%d] %f",weight_index, weight_index + (hidden_node_number[hidden_layer_number_arg-1]+1) * i, output[i]);
#endif
                j = 0;
                while (j < hidden_node_number[hidden_layer_number_arg-1])
		{
#ifdef ALPINE_DEBUG 
			elog(WARNING,"ouput[%d]:%f ,hidden_node_number_index:%d,j:%d, weight[%d]:%f",i,output[i], hidden_node_number_index ,j,1+j + weight_index + (hidden_node_number[hidden_layer_number_arg-1]+1) * i , weight[1 + j + weight_index + (hidden_node_number[hidden_layer_number_arg-1]+1) * i ]);
#endif
                        output[i] = output[i]+hidden_node_output[hidden_node_number_index + j]
					* weight[1 + j + weight_index + (hidden_node_number[hidden_layer_number_arg-1]+1) * i ];
                        j = j + 1;
				}
#ifdef ALPINE_DEBUG 
		 elog(WARNING,"ouputsum[%d] %f", i, output[i]);
#endif
		if (numerical_label_arg)
		{
                	output[i] = ((output[i]) * output_range_arg+output_base_arg);
#ifdef ALPINE_DEBUG 
			elog(WARNING,"output:%f, %f,%f",output[i],output_range_arg,output_base_arg);
#endif
		}
		else
		{
			if (output[i] < -45.0)
			{
				output[i] = 0;
			}
			else if (output[i] > 45.0)
			{
				output[i] = 1;
			}
			else
			{
				output[i] = (1.0/(1+exp(-1.0*output[i])));
			}
		}
#ifdef ALPINE_DEBUG 
		 elog(WARNING,"ouputsum2[%d] %f", i, output[i]);
#endif
                i = i + 1;
	}

	/* get output array element type */
	result_eltype = FLOAT8OID;
	get_typlenbyvalalign(result_eltype, &result_typlen, &result_typbyval, &result_typalign);

	/* construct result array */
	result_count = weight_count + 1;
	result_data = (Datum *)palloc(result_count * sizeof(Datum));
	result_nulls = (bool *)palloc(result_count * sizeof(bool));
	for (i = 0; i < result_count; i++)
	{
		result_nulls[i] = false;
	}
	//compute error of output node
	output_error = (double *)palloc(output_node_no_arg * sizeof(double));
	for(i = 0; i < output_node_no_arg; i++)
	{
		if(numerical_label_arg)
		{
			if (output_range_arg == 0.0)
			{
				direct_output_error = 0.0;
			}
			else
			{
				direct_output_error = (label_arg - output[i])/output_range_arg;
			}
			output_error[i] = direct_output_error;
		}
		else
		{
			if (((int)label_arg) == i)
			{
				direct_output_error = 1.0 - output[i];
			}
			else
			{
				direct_output_error = 0.0 - output[i];
			}
#ifdef ALPINE_DEBUG 
		elog(WARNING,"label_arg :%f %d %d", label_arg, i, (((int)label_arg) == i));
#endif
			output_error[i] = direct_output_error * output[i] * (1- output[i]);
		}
		total_error += direct_output_error*direct_output_error;
#ifdef ALPINE_DEBUG 
		elog(WARNING,"output_error[%d] %f  totalerror:%f", i, output_error[i], total_error);
#endif
	}

	//compute hidden_node_error of last layer hidden_node----
	hidden_node_error = (double*)palloc(all_hidden_node_count * sizeof(double));
	weight_index = weight_count - output_node_no_arg*(hidden_node_number[hidden_layer_number_arg - 1] + 1)  ;
	hidden_node_number_index = all_hidden_node_count - hidden_node_number[hidden_layer_number_arg - 1];
	for(i = 0; i < hidden_node_number[hidden_layer_number_arg - 1]; i++)
	{
		error_sum = 0.0;
		for(k = 0; k < output_node_no_arg; k++)
		{
			error_sum = error_sum+output_error[k]*weight[weight_index + (hidden_node_number[hidden_layer_number_arg - 1] + 1)*k + i + 1];
#ifdef ALPINE_DEBUG 
		elog(WARNING,"output_error[%d]:%f,weight[%d]:%f",k,output_error[k],weight_index + (hidden_node_number[hidden_layer_number_arg - 1] + 1)*k + i + 1, weight[weight_index + (hidden_node_number[hidden_layer_number_arg - 1] + 1)*k + i + 1]);
#endif
		}
		hidden_node_error[hidden_node_number_index + i] = error_sum*hidden_node_output[hidden_node_number_index + i]*(1.0-hidden_node_output[hidden_node_number_index + i]);
#ifdef ALPINE_DEBUG 
		elog(WARNING,"hidden_node_error[%d] %f ", hidden_node_number_index+i, hidden_node_error[hidden_node_number_index + i]);
#endif
	}

	//compute hidden_node_error  of 1 layer to the one before last layer hidden node
	if (hidden_layer_number_arg > 1)
	{
		weight_index = weight_index - (hidden_node_number[hidden_layer_number_arg - 2] + 1)*hidden_node_number[hidden_layer_number_arg - 1];
		hidden_node_number_index = hidden_node_number_index - hidden_node_number[hidden_layer_number_arg - 2];
		for(i = hidden_layer_number_arg - 2; i >= 0; i--)
		{
			for(j = 0; j < hidden_node_number[i]; j++)
			{
				error_sum = 0.0;
				for (k = 0; k < hidden_node_number[i + 1]; k++)
				{
					error_sum = error_sum+hidden_node_error[hidden_node_number_index + hidden_node_number[i] + k]*weight[weight_index + (hidden_node_number[i]+1)*(k) + j + 1];
#ifdef ALPINE_DEBUG 
		elog(WARNING,"i:%d j:%d k:%d; hidden_node_error[%d]:%f,weight[%d]:%f",i,j,k,hidden_node_number_index + hidden_node_number[i] + k, hidden_node_error[hidden_node_number_index + hidden_node_number[i] + k], weight_index + (hidden_node_number[i]+1)*(k) + j + 1,weight[weight_index + (hidden_node_number[i]+1)*(k) + j + 1]);
#endif
				}
				hidden_node_error[hidden_node_number_index + j] = error_sum*hidden_node_output[hidden_node_number_index + j]*(1-hidden_node_output[hidden_node_number_index + j]);
#ifdef ALPINE_DEBUG 
                elog(WARNING,"hidden_node_error[%d] %f ", hidden_node_number_index+j, hidden_node_error[hidden_node_number_index + j]);
#endif
			}
			weight_index = weight_index - (hidden_node_number[i - 1]+1) * hidden_node_number[i];
			hidden_node_number_index = hidden_node_number_index - hidden_node_number[i - 1];
		}
	}

	//compute weight change of output node
	weight_index = weight_count - (hidden_node_number[hidden_layer_number_arg - 1]+ 1)* output_node_no_arg;
	hidden_node_number_index = all_hidden_node_count - hidden_node_number[hidden_layer_number_arg - 1];
	for(i = 0; i < output_node_no_arg; i++)
	{
		delta = 1.0/set_size_arg*output_error[i];
		threshold_change = delta;
		result_data[weight_index +(hidden_node_number[hidden_layer_number_arg - 1]+ 1)*(i)] = Float8GetDatum(threshold_change);
#ifdef ALPINE_DEBUG 
                elog(WARNING, " result_data [%d] %f ", weight_index +(hidden_node_number[hidden_layer_number_arg - 1]+ 1)*(i), threshold_change);
#endif

		for(j = 0; j < hidden_node_number[hidden_layer_number_arg - 1] ; j++)
		{
			current_change = delta * hidden_node_output[hidden_node_number_index + j];
			result_data[weight_index +(hidden_node_number[hidden_layer_number_arg - 1]+ 1)*(i) + 1 +j] = Float8GetDatum(current_change);
#ifdef ALPINE_DEBUG 
                elog(WARNING, " result_data [%d] %f , i:%d j:%d output_error[%d]:%f, hidden_node_output[%d]:%f", weight_index +(hidden_node_number[hidden_layer_number_arg - 1]+ 1)*(i) + 1+ j, current_change, i,j,i,output_error[i],hidden_node_number_index + j, hidden_node_output[hidden_node_number_index + j]);
#endif
		}
	}

	//compute weight change of hidden node last layer  to  2 layer
	if (hidden_layer_number_arg > 1)
	{
		for(i = hidden_layer_number_arg - 1; i >= 1; i--)
		{
			weight_index = weight_index - (hidden_node_number[i - 1]+1)*hidden_node_number[i];
			hidden_node_number_index = hidden_node_number_index - hidden_node_number[i - 1];
			delta = 0.0;
			for (j = 0; j < hidden_node_number[i]; j++)
			{
				delta = (1.0/set_size_arg*hidden_node_error[hidden_node_number_index + hidden_node_number[i - 1] + j]);
				threshold_change = delta;
				result_data[weight_index + (hidden_node_number[i - 1] + 1) * (j)] = Float8GetDatum(threshold_change);
#ifdef ALPINE_DEBUG 
                elog(WARNING, " result_data [%d] %f ", weight_index + (hidden_node_number[i - 1] + 1) * (j), threshold_change);
#endif
				for(k = 0; k < hidden_node_number[i - 1]; k++)
				{
					current_change = delta * hidden_node_output[hidden_node_number_index + k];
					result_data[weight_index + (hidden_node_number[i - 1] + 1) * (j) + 1 +  k] = Float8GetDatum(current_change);
#ifdef ALPINE_DEBUG 
                elog(WARNING, " result_data [%d] %f i:%d, j:%d k:%d hidden_node_error[%d]:%f hidden_node_output[%d]:%f", weight_index + (hidden_node_number[i - 1] + 1) * (j) + 1 +  k, current_change,i,j,k,hidden_node_number_index + hidden_node_number[i - 1] + j, hidden_node_error[hidden_node_number_index + hidden_node_number[i - 1] + j], hidden_node_number_index + k,hidden_node_output[hidden_node_number_index + k]);
#endif
				}
			}
		}
	}


	//compute weight change of first layer hidden node
	weight_index = 0; 
	hidden_node_number_index = 0;
	delta = 0.0;
	for(j = 0; j < hidden_node_number[0]; j++)
	{
		delta = 1.0/set_size_arg*hidden_node_error[hidden_node_number_index + j];
		threshold_change = delta;
		result_data[weight_index + (columns_count+1)*(j)] = Float8GetDatum(threshold_change);
#ifdef ALPINE_DEBUG 
                elog(WARNING, " result_data [%d] %f ", weight_index + (columns_count+1)*(j), threshold_change);
#endif
		for(k = 0; k < columns_count; k++)
		{
			current_change = delta*input[k];
			result_data[weight_index +  (columns_count+1)*(j) + k + 1] = Float8GetDatum(current_change);
#ifdef ALPINE_DEBUG 
                elog(WARNING, " result_data [%d] %f j:%d k:%d hidden_node_error[%d]:%f input[%d]:%f", weight_index +  (columns_count+1)*(j) + k + 1, current_change,j,k,hidden_node_number_index + j, hidden_node_error[hidden_node_number_index + j], k, input[k]);
#endif
		}
	}

	result_data[weight_count] = Float8GetDatum(total_error);
	ndims = 1;
	dims = (int *) palloc(sizeof(int));
	dims[0] = result_count;
	lbs = (int *) palloc(sizeof(int));
	lbs[0] = 1;

	result = construct_md_array((void *)result_data, result_nulls, ndims, dims,
			lbs, result_eltype, result_typlen, result_typbyval, result_typalign);

//	pfree(result);
	pfree(weight_data);
	pfree(columns_data);
	pfree(input_range_data);
	pfree(input_base_data);
	pfree(hidden_node_number_data);
	pfree(result_data);
	pfree(weight_nulls);
	pfree(columns_nulls);
	pfree(input_range_nulls);
	pfree(input_base_nulls);
	pfree(hidden_node_number_nulls);
	pfree(result_nulls);
	pfree(input);
	pfree(output);
	pfree(lbs);
	pfree(dims);
	pfree(hidden_node_output);
	pfree(weight);
	pfree(hidden_node_number);

	pfree(hidden_node_error);
	pfree(output_error);

        PG_RETURN_ARRAYTYPE_P(result);
}