Ejemplo n.º 1
0
Datum
ipaddr_cast_from_inet(PG_FUNCTION_ARGS)
{
    inet *inetptr = PG_GETARG_INET_P(0);
    inet_struct *in = INET_STRUCT_DATA(inetptr);
	IP ip;

	switch (in->family)
	{
		case PGSQL_AF_INET:
			ip.ip4 = DatumGetIP4(DirectFunctionCall1(ip4_cast_from_inet, InetPGetDatum(inetptr)));
			PG_RETURN_IP_P(ip_pack(PGSQL_AF_INET, &ip));
		case PGSQL_AF_INET6:
			ip.ip6 = *(DatumGetIP6P(DirectFunctionCall1(ip6_cast_from_inet, InetPGetDatum(inetptr))));
			PG_RETURN_IP_P(ip_pack(PGSQL_AF_INET6, &ip));
	}

    ereport(ERROR,
            (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
             errmsg("invalid INET value for conversion to IP")));
    PG_RETURN_NULL();
}
Ejemplo n.º 2
0
/*
 * The SP-GiST query consistency check for leaf tuples
 */
Datum
inet_spg_leaf_consistent(PG_FUNCTION_ARGS)
{
	spgLeafConsistentIn *in = (spgLeafConsistentIn *) PG_GETARG_POINTER(0);
	spgLeafConsistentOut *out = (spgLeafConsistentOut *) PG_GETARG_POINTER(1);
	inet	   *leaf = DatumGetInetPP(in->leafDatum);

	/* All tests are exact. */
	out->recheck = false;

	/* Leaf is what it is... */
	out->leafValue = InetPGetDatum(leaf);

	/* Use common code to apply the tests. */
	PG_RETURN_BOOL(inet_spg_consistent_bitmap(leaf, in->nkeys, in->scankeys,
											  true));
}
Ejemplo n.º 3
0
/*
 * The SP-GiST choose function
 */
Datum
inet_spg_choose(PG_FUNCTION_ARGS)
{
	spgChooseIn *in = (spgChooseIn *) PG_GETARG_POINTER(0);
	spgChooseOut *out = (spgChooseOut *) PG_GETARG_POINTER(1);
	inet	   *val = DatumGetInetPP(in->datum),
			   *prefix;
	int			commonbits;

	/*
	 * If we're looking at a tuple that splits by address family, choose the
	 * appropriate subnode.
	 */
	if (!in->hasPrefix)
	{
		/* allTheSame isn't possible for such a tuple */
		Assert(!in->allTheSame);
		Assert(in->nNodes == 2);

		out->resultType = spgMatchNode;
		out->result.matchNode.nodeN = (ip_family(val) == PGSQL_AF_INET) ? 0 : 1;
		out->result.matchNode.restDatum = InetPGetDatum(val);

		PG_RETURN_VOID();
	}

	/* Else it must split by prefix */
	Assert(in->nNodes == 4 || in->allTheSame);

	prefix = DatumGetInetPP(in->prefixDatum);
	commonbits = ip_bits(prefix);

	/*
	 * We cannot put addresses from different families under the same inner
	 * node, so we have to split if the new value's family is different.
	 */
	if (ip_family(val) != ip_family(prefix))
	{
		/* Set up 2-node tuple */
		out->resultType = spgSplitTuple;
		out->result.splitTuple.prefixHasPrefix = false;
		out->result.splitTuple.prefixNNodes = 2;
		out->result.splitTuple.prefixNodeLabels = NULL;

		/* Identify which node the existing data goes into */
		out->result.splitTuple.childNodeN =
			(ip_family(prefix) == PGSQL_AF_INET) ? 0 : 1;

		out->result.splitTuple.postfixHasPrefix = true;
		out->result.splitTuple.postfixPrefixDatum = InetPGetDatum(prefix);

		PG_RETURN_VOID();
	}

	/*
	 * If the new value does not match the existing prefix, we have to split.
	 */
	if (ip_bits(val) < commonbits ||
		bitncmp(ip_addr(prefix), ip_addr(val), commonbits) != 0)
	{
		/* Determine new prefix length for the split tuple */
		commonbits = bitncommon(ip_addr(prefix), ip_addr(val),
								Min(ip_bits(val), commonbits));

		/* Set up 4-node tuple */
		out->resultType = spgSplitTuple;
		out->result.splitTuple.prefixHasPrefix = true;
		out->result.splitTuple.prefixPrefixDatum =
			InetPGetDatum(cidr_set_masklen_internal(val, commonbits));
		out->result.splitTuple.prefixNNodes = 4;
		out->result.splitTuple.prefixNodeLabels = NULL;

		/* Identify which node the existing data goes into */
		out->result.splitTuple.childNodeN =
			inet_spg_node_number(prefix, commonbits);

		out->result.splitTuple.postfixHasPrefix = true;
		out->result.splitTuple.postfixPrefixDatum = InetPGetDatum(prefix);

		PG_RETURN_VOID();
	}

	/*
	 * All OK, choose the node to descend into.  (If this tuple is marked
	 * allTheSame, the core code will ignore our choice of nodeN; but we need
	 * not account for that case explicitly here.)
	 */
	out->resultType = spgMatchNode;
	out->result.matchNode.nodeN = inet_spg_node_number(val, commonbits);
	out->result.matchNode.restDatum = InetPGetDatum(val);

	PG_RETURN_VOID();
}
Ejemplo n.º 4
0
/*
 * The GiST PickSplit method
 */
Datum
inet_spg_picksplit(PG_FUNCTION_ARGS)
{
	spgPickSplitIn *in = (spgPickSplitIn *) PG_GETARG_POINTER(0);
	spgPickSplitOut *out = (spgPickSplitOut *) PG_GETARG_POINTER(1);
	inet	   *prefix,
			   *tmp;
	int			i,
				commonbits;
	bool		differentFamilies = false;

	/* Initialize the prefix with the first item */
	prefix = DatumGetInetPP(in->datums[0]);
	commonbits = ip_bits(prefix);

	/* Examine remaining items to discover minimum common prefix length */
	for (i = 1; i < in->nTuples; i++)
	{
		tmp = DatumGetInetPP(in->datums[i]);

		if (ip_family(tmp) != ip_family(prefix))
		{
			differentFamilies = true;
			break;
		}

		if (ip_bits(tmp) < commonbits)
			commonbits = ip_bits(tmp);
		commonbits = bitncommon(ip_addr(prefix), ip_addr(tmp), commonbits);
		if (commonbits == 0)
			break;
	}

	/* Don't need labels; allocate output arrays */
	out->nodeLabels = NULL;
	out->mapTuplesToNodes = (int *) palloc(sizeof(int) * in->nTuples);
	out->leafTupleDatums = (Datum *) palloc(sizeof(Datum) * in->nTuples);

	if (differentFamilies)
	{
		/* Set up 2-node tuple */
		out->hasPrefix = false;
		out->nNodes = 2;

		for (i = 0; i < in->nTuples; i++)
		{
			tmp = DatumGetInetPP(in->datums[i]);
			out->mapTuplesToNodes[i] =
				(ip_family(tmp) == PGSQL_AF_INET) ? 0 : 1;
			out->leafTupleDatums[i] = InetPGetDatum(tmp);
		}
	}
	else
	{
		/* Set up 4-node tuple */
		out->hasPrefix = true;
		out->prefixDatum =
			InetPGetDatum(cidr_set_masklen_internal(prefix, commonbits));
		out->nNodes = 4;

		for (i = 0; i < in->nTuples; i++)
		{
			tmp = DatumGetInetPP(in->datums[i]);
			out->mapTuplesToNodes[i] = inet_spg_node_number(tmp, commonbits);
			out->leafTupleDatums[i] = InetPGetDatum(tmp);
		}
	}

	PG_RETURN_VOID();
}