mirror of
https://github.com/postgres/postgres.git
synced 2025-05-01 01:04:50 +03:00
172 lines
3.3 KiB
C
172 lines
3.3 KiB
C
/*-------------------------------------------------------------------------
|
|
*
|
|
* ordering.c--
|
|
* Routines to manipulate and compare merge and path orderings
|
|
*
|
|
* Copyright (c) 1994, Regents of the University of California
|
|
*
|
|
*
|
|
* IDENTIFICATION
|
|
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/Attic/ordering.c,v 1.13 1999/02/11 17:00:48 momjian Exp $
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
#include <sys/types.h>
|
|
|
|
#include "postgres.h"
|
|
|
|
#include "optimizer/internal.h"
|
|
#include "optimizer/ordering.h"
|
|
|
|
static bool equal_sortops_order(Oid *ordering1, Oid *ordering2, int *better_sort);
|
|
|
|
/*
|
|
* equal-path-ordering--
|
|
* Returns t iff two path orderings are equal.
|
|
*
|
|
*/
|
|
bool
|
|
pathorder_match(PathOrder *path_ordering1,
|
|
PathOrder *path_ordering2,
|
|
int *better_sort)
|
|
{
|
|
|
|
*better_sort = 0;
|
|
|
|
if (path_ordering1 == path_ordering2)
|
|
return true;
|
|
|
|
if (!path_ordering2)
|
|
{
|
|
*better_sort = 1;
|
|
return true;
|
|
}
|
|
|
|
if (!path_ordering1)
|
|
{
|
|
*better_sort = 2;
|
|
return true;
|
|
}
|
|
|
|
if (path_ordering1->ordtype == MERGE_ORDER &&
|
|
path_ordering2->ordtype == MERGE_ORDER)
|
|
{
|
|
return equal(path_ordering1->ord.merge, path_ordering2->ord.merge);
|
|
}
|
|
else if (path_ordering1->ordtype == SORTOP_ORDER &&
|
|
path_ordering2->ordtype == SORTOP_ORDER)
|
|
{
|
|
return equal_sortops_order(path_ordering1->ord.sortop,
|
|
path_ordering2->ord.sortop,
|
|
better_sort);
|
|
}
|
|
else if (path_ordering1->ordtype == MERGE_ORDER &&
|
|
path_ordering2->ordtype == SORTOP_ORDER)
|
|
{
|
|
if (!path_ordering2->ord.sortop)
|
|
{
|
|
*better_sort = 1;
|
|
return true;
|
|
}
|
|
return path_ordering1->ord.merge->left_operator == path_ordering2->ord.sortop[0];
|
|
}
|
|
else
|
|
{
|
|
if (!path_ordering1->ord.sortop)
|
|
{
|
|
*better_sort = 2;
|
|
return true;
|
|
}
|
|
return path_ordering1->ord.sortop[0] == path_ordering2->ord.merge->left_operator;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* equal-path-merge-ordering--
|
|
* Returns t iff a path ordering is usable for ordering a merge join.
|
|
*
|
|
* XXX Presently, this means that the first sortop of the path matches
|
|
* either of the merge sortops. Is there a "right" and "wrong"
|
|
* sortop to match?
|
|
*
|
|
*/
|
|
bool
|
|
equal_path_merge_ordering(Oid *path_ordering,
|
|
MergeOrder *merge_ordering)
|
|
{
|
|
if (path_ordering == NULL || merge_ordering == NULL)
|
|
return false;
|
|
|
|
if (path_ordering[0] == merge_ordering->left_operator ||
|
|
path_ordering[0] == merge_ordering->right_operator)
|
|
return true;
|
|
else
|
|
return false;
|
|
}
|
|
|
|
/*
|
|
* equal-merge-ordering--
|
|
* Returns t iff two merge orderings are equal.
|
|
*
|
|
*/
|
|
bool
|
|
equal_merge_ordering(MergeOrder *merge_ordering1,
|
|
MergeOrder *merge_ordering2)
|
|
{
|
|
return equal(merge_ordering1, merge_ordering2);
|
|
}
|
|
|
|
|
|
/*
|
|
* sortops
|
|
*
|
|
*/
|
|
|
|
/*
|
|
* equal_sort_ops_order -
|
|
* Returns true iff the sort operators are in the same order.
|
|
*/
|
|
static bool
|
|
equal_sortops_order(Oid *ordering1, Oid *ordering2, int *better_sort)
|
|
{
|
|
int i = 0;
|
|
|
|
*better_sort = 0;
|
|
|
|
if (ordering1 == ordering2)
|
|
return true;
|
|
|
|
if (!ordering2)
|
|
{
|
|
*better_sort = 1;
|
|
return true;
|
|
}
|
|
|
|
if (!ordering1)
|
|
{
|
|
*better_sort = 2;
|
|
return true;
|
|
}
|
|
|
|
while (ordering1[i] != 0 && ordering2[i] != 0)
|
|
{
|
|
if (ordering1[i] != ordering2[i])
|
|
break;
|
|
i++;
|
|
}
|
|
|
|
if (ordering1[i] != 0 && ordering2[i] == 0)
|
|
{
|
|
*better_sort = 1;
|
|
return true;
|
|
}
|
|
|
|
if (ordering1[i] == 0 && ordering2[i] != 0)
|
|
{
|
|
*better_sort = 2;
|
|
return true;
|
|
}
|
|
|
|
return ordering1[i] == 0 && ordering2[i] == 0;
|
|
}
|