1
0
mirror of https://github.com/postgres/postgres.git synced 2025-11-06 07:49:08 +03:00

Revise aggregate functions per earlier discussions in pghackers.

There's now only one transition value and transition function.
NULL handling in aggregates is a lot cleaner.  Also, use Numeric
accumulators instead of integer accumulators for sum/avg on integer
datatypes --- this avoids overflow at the cost of being a little slower.
Implement VARIANCE() and STDDEV() aggregates in the standard backend.

Also, enable new LIKE selectivity estimators by default.  Unrelated
change, but as long as I had to force initdb anyway...
This commit is contained in:
Tom Lane
2000-07-17 03:05:41 +00:00
parent 139f19c302
commit bec98a31c5
55 changed files with 1949 additions and 1813 deletions

View File

@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/storage/lmgr/lock.c,v 1.70 2000/06/28 03:32:07 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/storage/lmgr/lock.c,v 1.71 2000/07/17 03:05:08 tgl Exp $
*
* NOTES
* Outside modules can create a lock table and acquire/release
@@ -20,7 +20,7 @@
* Interface:
*
* LockAcquire(), LockRelease(), LockMethodTableInit(),
* LockMethodTableRename(), LockReleaseAll, LockOwners()
* LockMethodTableRename(), LockReleaseAll,
* LockResolveConflicts(), GrantLock()
*
* NOTE: This module is used to define new lock tables. The
@@ -35,9 +35,11 @@
#include <signal.h>
#include "postgres.h"
#include "access/xact.h"
#include "miscadmin.h"
#include "storage/proc.h"
#include "utils/memutils.h"
#include "utils/ps_status.h"
static int WaitOnLock(LOCKMETHOD lockmethod, LOCK *lock, LOCKMODE lockmode);
@@ -1722,181 +1724,6 @@ nxtl: ;
return false;
}
#ifdef NOT_USED
/*
* Return an array with the pids of all processes owning a lock.
* This works only for user locks because normal locks have no
* pid information in the corresponding XIDLookupEnt.
*/
ArrayType *
LockOwners(LOCKMETHOD lockmethod, LOCKTAG *locktag)
{
XIDLookupEnt *xidLook = NULL;
SPINLOCK masterLock;
LOCK *lock;
SHMEM_OFFSET lock_offset;
int count = 0;
LOCKMETHODTABLE *lockMethodTable;
HTAB *xidTable;
bool found;
int ndims,
nitems,
hdrlen,
size;
int lbounds[1],
hbounds[1];
ArrayType *array;
int *data_ptr;
/* Assume that no one will modify the result */
static int empty_array[] = {20, 1, 0, 0, 0};
#ifdef LOCK_DEBUG
if (lockmethod == USER_LOCKMETHOD && Trace_userlocks)
elog(DEBUG, "LockOwners: user lock tag [%u]", locktag->objId.blkno);
#endif
/* This must be changed when short term locks will be used */
locktag->lockmethod = lockmethod;
Assert((lockmethod >= MIN_LOCKMETHOD) && (lockmethod < NumLockMethods));
lockMethodTable = LockMethodTable[lockmethod];
if (!lockMethodTable)
{
elog(NOTICE, "lockMethodTable is null in LockOwners");
return (ArrayType *) &empty_array;
}
if (LockingIsDisabled)
return (ArrayType *) &empty_array;
masterLock = lockMethodTable->ctl->masterLock;
SpinAcquire(masterLock);
/*
* Find a lock with this tag
*/
Assert(lockMethodTable->lockHash->hash == tag_hash);
lock = (LOCK *) hash_search(lockMethodTable->lockHash, (Pointer) locktag,
HASH_FIND, &found);
/*
* let the caller print its own error message, too. Do not elog(WARN).
*/
if (!lock)
{
SpinRelease(masterLock);
elog(NOTICE, "LockOwners: locktable corrupted");
return (ArrayType *) &empty_array;
}
if (!found)
{
SpinRelease(masterLock);
elog(NOTICE, "LockOwners: no such lock");
return (ArrayType *) &empty_array;
}
LOCK_PRINT("LockOwners: found", lock, 0);
Assert((lock->nHolding > 0) && (lock->nActive > 0));
Assert(lock->nActive <= lock->nHolding);
lock_offset = MAKE_OFFSET(lock);
/* Construct a 1-dimensional array */
ndims = 1;
hdrlen = ARR_OVERHEAD(ndims);
lbounds[0] = 0;
hbounds[0] = lock->nActive;
size = hdrlen + sizeof(int) * hbounds[0];
array = (ArrayType *) palloc(size);
MemSet(array, 0, size);
memmove((char *) array, (char *) &size, sizeof(int));
memmove((char *) ARR_NDIM_PTR(array), (char *) &ndims, sizeof(int));
memmove((char *) ARR_DIMS(array), (char *) hbounds, ndims * sizeof(int));
memmove((char *) ARR_LBOUND(array), (char *) lbounds, ndims * sizeof(int));
SET_LO_FLAG(false, array);
data_ptr = (int *) ARR_DATA_PTR(array);
xidTable = lockMethodTable->xidHash;
hash_seq(NULL);
nitems = 0;
while ((xidLook = (XIDLookupEnt *) hash_seq(xidTable)) &&
(xidLook != (XIDLookupEnt *) TRUE))
{
if (count++ > 1000)
{
elog(NOTICE, "LockOwners: possible loop, giving up");
break;
}
if (xidLook->tag.pid == 0)
{
XID_PRINT("LockOwners: no pid", xidLook);
continue;
}
if (!xidLook->tag.lock)
{
XID_PRINT("LockOwners: NULL LOCK", xidLook);
continue;
}
if (xidLook->tag.lock != lock_offset)
{
XID_PRINT("LockOwners: different lock", xidLook);
continue;
}
if (LOCK_LOCKMETHOD(*lock) != lockmethod)
{
XID_PRINT("LockOwners: other table", xidLook);
continue;
}
if (xidLook->nHolding <= 0)
{
XID_PRINT("LockOwners: not holding", xidLook);
continue;
}
if (nitems >= hbounds[0])
{
elog(NOTICE, "LockOwners: array size exceeded");
break;
}
/*
* Check that the holding process is still alive by sending him an
* unused (ignored) signal. If the kill fails the process is not
* alive.
*/
if ((xidLook->tag.pid != MyProcPid) \
&&(kill(xidLook->tag.pid, SIGCHLD)) != 0)
{
/* Return a negative pid to signal that process is dead */
data_ptr[nitems++] = -(xidLook->tag.pid);
XID_PRINT("LockOwners: not alive", xidLook);
/* XXX - TODO: remove this entry and update lock stats */
continue;
}
/* Found a process holding the lock */
XID_PRINT("LockOwners: holding", xidLook);
data_ptr[nitems++] = xidLook->tag.pid;
}
SpinRelease(masterLock);
/* Adjust the actual size of the array */
hbounds[0] = nitems;
size = hdrlen + sizeof(int) * hbounds[0];
memmove((char *) array, (char *) &size, sizeof(int));
memmove((char *) ARR_DIMS(array), (char *) hbounds, ndims * sizeof(int));
return array;
}
#endif /* NOT_USED */
#ifdef LOCK_DEBUG
/*
* Dump all locks in the proc->lockQueue. Must have already acquired