예제 #1
0
QTNode *
QTNCopy(QTNode *in)
{
	QTNode	   *out;

	/* since this function recurses, it could be driven to stack overflow. */
	check_stack_depth();

	out = (QTNode *) palloc(sizeof(QTNode));

	*out = *in;
	out->valnode = (QueryItem *) palloc(sizeof(QueryItem));
	*(out->valnode) = *(in->valnode);
	out->flags |= QTN_NEEDFREE;

	if (in->valnode->type == QI_VAL)
	{
		out->word = palloc(in->valnode->qoperand.length + 1);
		memcpy(out->word, in->word, in->valnode->qoperand.length);
		out->word[in->valnode->qoperand.length] = '\0';
		out->flags |= QTN_WORDFREE;
	}
	else
	{
		int			i;

		out->child = (QTNode **) palloc(sizeof(QTNode *) * in->nchild);

		for (i = 0; i < in->nchild; i++)
			out->child[i] = QTNCopy(in->child[i]);
	}

	return out;
}
예제 #2
0
static QTNode *
findeq(QTNode * node, QTNode * ex, MemoryType memtype, QTNode * subs, bool *isfind)
{

	if ((node->sign & ex->sign) != ex->sign || node->valnode->type != ex->valnode->type || node->valnode->val != ex->valnode->val)
		return node;

	if (node->flags & QTN_NOCHANGE)
		return node;

	if (node->valnode->type == OPR)
	{
		if (node->nchild == ex->nchild)
		{
			if (QTNEq(node, ex))
			{
				QTNFree(node);
				if (subs)
				{
					node = QTNCopy(subs, memtype);
					node->flags |= QTN_NOCHANGE;
				}
				else
					node = NULL;
				*isfind = true;
			}
		}
		else if (node->nchild > ex->nchild)
		{
			int		   *counters = (int *) palloc(sizeof(int) * node->nchild);
			int			i;
			QTNode	   *tnode = (QTNode *) MEMALLOC(memtype, sizeof(QTNode));

			memset(tnode, 0, sizeof(QTNode));
			tnode->child = (QTNode **) MEMALLOC(memtype, sizeof(QTNode *) * ex->nchild);
			tnode->nchild = ex->nchild;
			tnode->valnode = (ITEM *) MEMALLOC(memtype, sizeof(ITEM));
			*(tnode->valnode) = *(ex->valnode);

			for (i = 0; i < ex->nchild; i++)
				counters[i] = i;

			do
			{
				tnode->sign = 0;
				for (i = 0; i < ex->nchild; i++)
				{
					tnode->child[i] = node->child[counters[i]];
					tnode->sign |= tnode->child[i]->sign;
				}

				if (QTNEq(tnode, ex))
				{
					int			j = 0;

					MEMFREE(memtype, tnode->valnode);
					MEMFREE(memtype, tnode->child);
					MEMFREE(memtype, tnode);
					if (subs)
					{
						tnode = QTNCopy(subs, memtype);
						tnode->flags = QTN_NOCHANGE | QTN_NEEDFREE;
					}
					else
						tnode = NULL;

					node->child[counters[0]] = tnode;

					for (i = 1; i < ex->nchild; i++)
						node->child[counters[i]] = NULL;
					for (i = 0; i < node->nchild; i++)
					{
						if (node->child[i])
						{
							node->child[j] = node->child[i];
							j++;
						}
					}

					node->nchild = j;

					*isfind = true;

					break;
				}
			} while (addone(counters, ex->nchild - 1, node->nchild));
			if (tnode && (tnode->flags & QTN_NOCHANGE) == 0)
			{
				MEMFREE(memtype, tnode->valnode);
				MEMFREE(memtype, tnode->child);
				MEMFREE(memtype, tnode);
			}
			else
				QTNSort(node);
			pfree(counters);
		}
	}
	else if (QTNEq(node, ex))
	{
		QTNFree(node);
		if (subs)
		{
			node = QTNCopy(subs, memtype);
			node->flags |= QTN_NOCHANGE;
		}
		else
		{
			node = NULL;
		}
		*isfind = true;
	}

	return node;
}
예제 #3
0
/*
 * If node is equal to ex, replace it with subs. Replacement is actually done
 * by returning either node or a copy of subs.
 */
static QTNode *
findeq(QTNode *node, QTNode *ex, QTNode *subs, bool *isfind)
{
	if ((node->sign & ex->sign) != ex->sign ||
		node->valnode->type != ex->valnode->type)
		return node;

	if (node->flags & QTN_NOCHANGE)
		return node;

	if (node->valnode->type == QI_OPR)
	{
		if (node->valnode->qoperator.oper != ex->valnode->qoperator.oper)
			return node;

		if (node->nchild == ex->nchild)
		{
			if (QTNEq(node, ex))
			{
				QTNFree(node);
				if (subs)
				{
					node = QTNCopy(subs);
					node->flags |= QTN_NOCHANGE;
				}
				else
					node = NULL;
				*isfind = true;
			}
		}
		else if (node->nchild > ex->nchild)
		{
			/*
			 * AND and NOT are commutative, so we check if a subset of the
			 * children match. For example, if tnode is A | B | C, and ex is B
			 * | C, we have a match after we convert tnode to A | (B | C).
			 */
			int		   *counters = (int *) palloc(sizeof(int) * node->nchild);
			int			i;
			QTNode	   *tnode = (QTNode *) palloc(sizeof(QTNode));

			memset(tnode, 0, sizeof(QTNode));
			tnode->child = (QTNode **) palloc(sizeof(QTNode *) * ex->nchild);
			tnode->nchild = ex->nchild;
			tnode->valnode = (QueryItem *) palloc(sizeof(QueryItem));
			*(tnode->valnode) = *(ex->valnode);

			for (i = 0; i < ex->nchild; i++)
				counters[i] = i;

			do
			{
				tnode->sign = 0;
				for (i = 0; i < ex->nchild; i++)
				{
					tnode->child[i] = node->child[counters[i]];
					tnode->sign |= tnode->child[i]->sign;
				}

				if (QTNEq(tnode, ex))
				{
					int			j = 0;

					pfree(tnode->valnode);
					pfree(tnode->child);
					pfree(tnode);
					if (subs)
					{
						tnode = QTNCopy(subs);
						tnode->flags = QTN_NOCHANGE | QTN_NEEDFREE;
					}
					else
						tnode = NULL;

					node->child[counters[0]] = tnode;

					for (i = 1; i < ex->nchild; i++)
						node->child[counters[i]] = NULL;
					for (i = 0; i < node->nchild; i++)
					{
						if (node->child[i])
						{
							node->child[j] = node->child[i];
							j++;
						}
					}

					node->nchild = j;

					*isfind = true;

					break;
				}
			} while (addone(counters, ex->nchild - 1, node->nchild));
			if (tnode && (tnode->flags & QTN_NOCHANGE) == 0)
			{
				pfree(tnode->valnode);
				pfree(tnode->child);
				pfree(tnode);
			}
			else
				QTNSort(node);
			pfree(counters);
		}
	}
	else
	{
		Assert(node->valnode->type == QI_VAL);

		if (node->valnode->qoperand.valcrc != ex->valnode->qoperand.valcrc)
			return node;
		else if (QTNEq(node, ex))
		{
			QTNFree(node);
			if (subs)
			{
				node = QTNCopy(subs);
				node->flags |= QTN_NOCHANGE;
			}
			else
			{
				node = NULL;
			}
			*isfind = true;
		}
	}

	return node;
}