Re: [HACKERS] Function to kill backend

2004-04-03 Thread Magnus Hagander
> Tom Lane wrote:
>>> it would definitely need to be a lot more constrained than
>>> send-any-signal-to-any-postgres-process ... even for a superuser,
>>> that's a mighty fat-gauge foot-gun.
>
>> What sort of constraints do you have in mind?
>
>I'd limit it to SIGINT (query cancel) and SIGTERM (fast shutdown),

Actually, that is a restriction that's already there - just didn't get
into those details. Since the functino as I wrote it so far just takes
signal name as a string (can't rely on signal numbers being identical
across platforms, right?), and then comparing it with a fixed set of
signals.


>and I'm not even real sure about SIGTERM.  That facility is designed to
>work in the case of shutting down all backends together --- 
>I'm not sure
>I want to promise that it behaves pleasantly to SIGTERM one backend and
>leave the rest going.  Nor do I see a real good use-case for it.

Really? Then what is the recommended way of shutting down a backend that
you are not connected to, as an administrator? Even if you are logged in
with shell access?

I may have been doing things wrong for a long time, because I have
certainly killed backends with TERM many times without problems. If
that's not safe, there really ought to be a tip on the mailinglists to
complement the  "don't kill -9 the postmaster" with "and don't ever kill
the backends, period"? I'm sure I'm not the only one who has done
that...

>Also, no killing processes that aren't regular backends (eg, the
>bgwriter, the stats processes, and most especially the postmaster).

That sounds like a reasonable limitation to add. Either by specifically
excluding these processes, or by limiting it to only work on the
backends currently listed in pg_stat_activity.


>Another point is that killing by PID is not necessarily what 
>you want to
>do --- kill by transaction ID might be a better API, especially for
>query-cancel cases.

Well, in my scenarios, killing by PID is what I need. But I guess
transaction IDs might be added to the pg_stat_activity, which would give
me the same functionality (I usually check that one first to see what a
backend does, before I do anything) - and then some, because the
transaction id carries other information as well.
Question on that - how will it handle an idle backend (that has not
explicitly opened a transaction, and is not executing a command in an
implicit transaction)?

> I think any such facility is inherently a security risk, since it
means
> that a remote attacker who's managed to break into your superuser
> account can randomly zap other backends.  Now admittedly there's
plenty
> of other mischief he can do with superuser privs, but that doesn't
mean
> we should hand him a pre-loaded, pre-sighted cannon. 
> Having to log into the database server locally to execute such
> operations doesn't seem that bad to me.

It does to me. I prefer being able to admin the server without having to
do a separate login. I also much prefer being able to delegate the
capability to terminate a backend, interrupt a long-running query, etc
to someone who does not have to have shell access on the server. I guess
it depends on the environment.

> Bruce Momjian <[EMAIL PROTECTED]> writes:

>> If they can read/write your data (as superuser), killing backends is
the
>> least worry.

That's pretty much the assumption I was working under.


//Magnus

---(end of broadcast)---
TIP 1: subscribe and unsubscribe commands go to [EMAIL PROTECTED]


Re: [HACKERS] Problems Vacuum'ing

2004-04-03 Thread Jochem van Dieten
Tom Lane wrote:
It's the oldest xmin of any transaction that's local to your database,
but those xmin values themselves were computed globally --- so what
matters is the oldest transaction that was running when any local
transaction started.  In this case I expect it's the VACUUM's own
transaction that's seeing the other guy as determining its xmin.
We could fix this by making every transaction compute, and advertise in
the PGPROC array, both local and global xmin values.  In previous
iterations of this discussion we concluded that the extra cycles (which
would be spent in *every* transaction start) could not be justified by
making VACUUM better able to reclaim space in the face of misbehaving
clients.
I don't suppose it is possible to find out to which database a 
transaction was local after it was committed?


That conclusion might be wrong, but it's not instantly obvious
that it is...
Would it be possible to find out how long a transaction has been 
open already? It is quite simple to find the oldest uncommitted 
transaction using the pg_locks table, but from there we don't 
know yet how old it is. If it were possible to determine when it 
started the vacuum verbose output could perhaps include something 
like :
DETAIL:  113590 dead row versions cannot be removed yet.
Transaction 1234567 is has been in progress for 01:45:21,
only dead row versions committed before that are removable.
Nonremovable row versions range from 64 to 88 bytes long.

Jochem

PS Sorry about messing up the threading, I read the archives.

--
I don't get it
immigrants don't work
and steal our jobs
- Loesje


---(end of broadcast)---
TIP 9: the planner will ignore your desire to choose an index scan if your
 joining column's datatypes do not match


Re: [HACKERS] Inconsistent behavior on Array & Is Null?

2004-04-03 Thread Greg Stark

Joe Conway <[EMAIL PROTECTED]> writes:

> Greg Stark wrote:
> > This really ought to work, it obviously shouldn't allow you to set a[5] and
> > then surreptitiously move it to a[1]. But nor should it generate an error,
> > since I may well have a specific meaning for a[5] and may be planning to fill
> > in a[1]..a[4] later.
> > The logical thing to do, I think, is pre-fill the entries a[1]..a[4] with
> > null. This could be implemented by actually storing the NULLs or else storing
> > some notation that's used to adjust the base of the index to save space.
> 
> I agree. I had always envisioned something exactly like that once we supported
> NULL elements. As far as the implementation goes, I think it would be very
> similar to tuples -- a null bitmask that would exist if any elements are NULL.

Well you might still want to store an internal "all indexes below this are
null". That way update foo set a[1000]=1 doesn't require storing even a bitmap
for the first 999 elements. Though might make maintaining the bitmap kind of a
pain. Maintaining the bitmap might be kind of a pain anyways though because
unlike tuples the array size isn't constant.

> A related question is how to deal with non-existing array elements. Until now,
> you could do:

I would have to think about it some more, but my first reaction is that
looking up [0] should generate an error if there can never be a valid entry at
[0]. But looking up indexes above the highest index should return NULL.

There are two broad use cases I see for arrays. Using them to represent tuples
where a[i] means something specific for each i, and using them to represent
sets where order doesn't matter.

In the former case I might want to initialize my column to an empty array and
set only the relevant columns as needed. In that case returning NULL for
entries that haven't been set yet whether they're above the last entry set or
below is most consistent.

In the latter case you really don't want to be looking up anything past the
end and don't want to be storing NULLs at all. So it doesn't really matter
what the behaviour is for referencing elements past the end, but you might
conceivably want to write code like "while (e = a[i++]) ...".




Incidentally I'm using both of these models in my current project. 

I use text[] to represent localized strings, str[1] is always English and
str[2] is always French. When I need to expand to more languages I'll add
str[3] for Spanish or whatever else. It would be a problem if I stored
something in str[2] and then found it in str[1] later. And it could be a bit
awkward to have to prefill str[3] everywhere in the whole database when the
time comes. Having it just silently return NULL would be more convenient.

I also use arrays for sets in a cache table. In that case there would never be
NULLs and the arrays are variable sized. Sometimes with thousands of entries.
The purpose of the cache table is to speed things up so storing the arrays
densely is important.

-- 
greg


---(end of broadcast)---
TIP 4: Don't 'kill -9' the postmaster


Re: [HACKERS] Better support for whole-row operations and composite

2004-04-03 Thread Joe Conway
Tom Lane wrote:
No, it's a HeapTupleHeader pointer.  You need to reconstruct a
HeapTuple on top of that to work with heap_getattr and most other
core backend routines.
Thanks.

For triggers, I was previously building up the arguments thus:

slot = TupleDescGetSlot(tupdesc);
slot->val = trigdata->tg_trigtuple;
arg[7] = PointerGetDatum(slot);
I suppose now I should do this instead?

arg[7] = PointerGetDatum(trigdata->tg_trigtuple->t_data);


Also don't forget to ensure that you detoast the datum; this is not
useful at the moment but will be important Real Soon Now. I added
standard argument-fetch macros to fmgr.h to help with the detoasting
bit.
OK. This is the net result:

#ifdef PG_VERSION_75_COMPAT
  Oid   tupType;
  int32 tupTypmod;
  TupleDesc tupdesc;
  HeapTuple tuple = palloc(sizeof(HeapTupleData));
  HeapTupleHeader   tuple_hdr = DatumGetHeapTupleHeader(arg[i]);
  tupType = HeapTupleHeaderGetTypeId(tuple_hdr);
  tupTypmod = HeapTupleHeaderGetTypMod(tuple_hdr);
  tupdesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
  tuple->t_len = HeapTupleHeaderGetDatumLength(tuple_hdr);
  ItemPointerSetInvalid(&(tuple->t_self));
  tuple->t_tableOid = InvalidOid;
  tuple->t_data = tuple_hdr;
  PROTECT(el = pg_tuple_get_r_frame(1, &tuple, tupdesc));

  pfree(tuple);
#else
  TupleTableSlot *slot = (TupleTableSlot *) arg[i];
  HeapTuple   tuple = slot->val;
  TupleDesc   tupdesc = slot->ttc_tupleDescriptor;
  PROTECT(el = pg_tuple_get_r_frame(1, &tuple, tupdesc));
#endif /* PG_VERSION_75_COMPAT */
Given the above changes, it's almost working now -- only problem left is 
with triggers:

  insert into foo values(11,'cat99',1.89);
+ ERROR:  record type has not been registered
+ CONTEXT:  In PL/R function rejectfoo
  delete from foo;
+ ERROR:  cache lookup failed for type 0
+ CONTEXT:  In PL/R function rejectfoo
(and a few other similar failures)

Any ideas why the trigger tuple type isn't registered, or what I'm doing 
wrong?

Thanks,

Joe

---(end of broadcast)---
TIP 8: explain analyze is your friend


Re: [HACKERS] Inconsistent behavior on Array & Is Null?

2004-04-03 Thread Joe Conway
Greg Stark wrote:
Joe Conway <[EMAIL PROTECTED]> writes:
I agree. I had always envisioned something exactly like that once we supported
NULL elements. As far as the implementation goes, I think it would be very
similar to tuples -- a null bitmask that would exist if any elements are NULL.
Well you might still want to store an internal "all indexes below this are
null". That way update foo set a[1000]=1 doesn't require storing even a bitmap
for the first 999 elements. Though might make maintaining the bitmap kind of a
pain. Maintaining the bitmap might be kind of a pain anyways though because
unlike tuples the array size isn't constant.
I don't think it will be worth the complication to do other than a 
straight bitmap -- at least not the first attempt.

A related question is how to deal with non-existing array elements. Until now,
you could do:
I would have to think about it some more, but my first reaction is that
looking up [0] should generate an error if there can never be a valid entry at
[0]. But looking up indexes above the highest index should return NULL.
There are two broad use cases I see for arrays. Using them to represent tuples
where a[i] means something specific for each i, and using them to represent
sets where order doesn't matter.
In the former case I might want to initialize my column to an empty array and
set only the relevant columns as needed. In that case returning NULL for
entries that haven't been set yet whether they're above the last entry set or
below is most consistent.
Maybe, but you're still going to need to explicitly set the real upper 
bound element in order for the length/cardinality to be correct. In 
other words, if you really want an array with elements 1 to 1000, but 2 
through 1000 are NULL, you'll need to explicitly set A[1000] = NULL; 
otherwise we'll have no way of knowing that you really want 1000 
elements. Perhaps we'll want some kind of array_init function to create 
an array of a given size filled with all NULL elements (or even some 
arbitrary constant element).

I'd think given the preceding, it would make more sense to throw an 
error whenever trying to access an element greater than the length.

In the latter case you really don't want to be looking up anything past the
end and don't want to be storing NULLs at all. So it doesn't really matter
what the behaviour is for referencing elements past the end, but you might
conceivably want to write code like "while (e = a[i++]) ...".
See reasoning as above. And if you did somehow wind up with a "real" 
NULL element in this scenario, you'd never know about it. The looping 
could always be:
  while (i++ <= length)
or
  for (i = 1; i <= length, i++)

Joe

---(end of broadcast)---
TIP 8: explain analyze is your friend


Re: [HACKERS] Better support for whole-row operations and composite

2004-04-03 Thread Joe Conway
Joe Conway wrote:
Given the above changes, it's almost working now -- only problem left is 
with triggers:

  insert into foo values(11,'cat99',1.89);
+ ERROR:  record type has not been registered
+ CONTEXT:  In PL/R function rejectfoo
  delete from foo;
+ ERROR:  cache lookup failed for type 0
+ CONTEXT:  In PL/R function rejectfoo
(and a few other similar failures)

Any ideas why the trigger tuple type isn't registered, or what I'm doing 
wrong?
A little more info on this. It appears that the tuple type is set to 
either 2249 (RECORDOID) or 0. In the case of RECORDOID this traces all 
the way back to here:

/* 
 *   CreateTemplateTupleDesc
 *
 *   This function allocates and zeros a tuple descriptor structure.
 *
 *   Tuple type ID information is initially set for an anonymous record
 *   type; caller can overwrite this if needed.
 * 
 */
But the type id is never overwritten for a BEFORE INSERT trigger. It 
appears that somewhere it is explictly set to InvalidOid for both BEFORE 
DELETE and AFTER INSERT triggers (and possibly others). My take is that 
we now need to explicitly set the tuple type id for INSERT/UPDATE/DELETE 
statements -- not sure where the best place to do that is though. Does 
this sound correct?

Joe

---(end of broadcast)---
TIP 6: Have you searched our list archives?
  http://archives.postgresql.org


Re: [HACKERS] Function to kill backend

2004-04-03 Thread Josh Berkus
Tom,

> > Seems like useful functionality.  Right now, how does an administrator
> > kill another backend from psql?  They can't.
> 
> The question to ask is "should they be able to?"

And the answer is, "Yes".

This is a commonly requested feature by DBA's migrating from SQL Server and 
Oracle.In those databases, there is a GUI to monitor database requests, 
and potentially kill them to resolve deadlocks or runaway queries (though, in 
the case of SQL server, it does not work).  Right now, it is very difficult 
for any of our GUI projects to construct such an interface due to the 
necessity of root shell access.

> I think any such facility is inherently a security risk, since it means
> that a remote attacker who's managed to break into your superuser
> account can randomly zap other backends.  Now admittedly there's plenty
> of other mischief he can do with superuser privs, but that doesn't mean
> we should hand him a pre-loaded, pre-sighted cannon.

And requiring DBAs to use root shell access whenever they want to stop a 
runaway query is somehow a good security approach? If nothing else, it 
exposes lots of DBAs to the temptation to use SIGKILL instead off SIGINT or 
SIGTERM, making the database shut down.   And I, personally, worry about the 
number of root shells I have to use, becuase every once in a while I forget 
and leave one open at the end of the day.

Killing backends with runaway queries is a routine administrative task.   It 
should be possible to accomplish it remotely, using tools provided by 
PostgreSQL instead of the command shell, because then it is possible for us 
to limit what those tools can do.

Further, if an intruder has superuser access, having them kill random backends 
is the last thing I'm worried about.  "DROP DATABASE" ranks a lot higher.   
In fact, it would be nice if they started killing random backends because 
then I'd know something was wrong.

-- 
-Josh Berkus
 Aglio Database Solutions
 San Francisco


---(end of broadcast)---
TIP 6: Have you searched our list archives?

   http://archives.postgresql.org


Re: [HACKERS] Function to kill backend

2004-04-03 Thread Christopher Kings-Lynne
This is a commonly requested feature by DBA's migrating from SQL Server and 
Oracle.In those databases, there is a GUI to monitor database requests, 
and potentially kill them to resolve deadlocks or runaway queries (though, in 
the case of SQL server, it does not work).  Right now, it is very difficult 
for any of our GUI projects to construct such an interface due to the 
necessity of root shell access.
Yes, MySQL can do it too.

http://www.mysql.com/doc/en/KILL.html

I would love to have a KILL  command in postgres.  I don't know how 
you would restrict it to only being able to kill postgres backends though.

Chris

---(end of broadcast)---
TIP 2: you can get off all lists at once with the unregister command
   (send "unregister YourEmailAddressHere" to [EMAIL PROTECTED])


Re: [HACKERS] Function to kill backend

2004-04-03 Thread Neil Conway
On 2-Apr-04, at 5:16 PM, Andrew Dunstan wrote:
If' we're going to have this shouldn't it be a proper command?
Why? What benefit would this offer over implementing this feature as a 
function?

-Neil

---(end of broadcast)---
TIP 1: subscribe and unsubscribe commands go to [EMAIL PROTECTED]


Re: [HACKERS] Better support for whole-row operations and composite types

2004-04-03 Thread Tom Lane
Joe Conway <[EMAIL PROTECTED]> writes:
> For triggers, I was previously building up the arguments thus:
>  slot = TupleDescGetSlot(tupdesc);
>  slot->val = trigdata->tg_trigtuple;
>  arg[7] = PointerGetDatum(slot);

> I suppose now I should do this instead?
>  arg[7] = PointerGetDatum(trigdata->tg_trigtuple->t_data);

Hm, no, that won't work because a tuple being passed to a trigger
probably isn't going to contain valid type information.  The API for
calling triggers is different from calling ordinary functions, so
I never thought about trying to make it look the same.  At what point
are you trying to do the above, anyway?

regards, tom lane

---(end of broadcast)---
TIP 4: Don't 'kill -9' the postmaster


Re: [HACKERS] Better support for whole-row operations and composite

2004-04-03 Thread Tom Lane
Joe Conway <[EMAIL PROTECTED]> writes:
>> Any ideas why the trigger tuple type isn't registered, or what I'm doing 
>> wrong?

> A little more info on this. It appears that the tuple type is set to 
> either 2249 (RECORDOID) or 0.

After further thought, we could possibly make it work for BEFORE
triggers, but there's just no way for AFTER triggers: in that case what
you are getting is an image of what went to disk, which is going to
contain transaction info not type info.

If you really want the trigger API for PL/R to be indistinguishable from
the function-call API, then I think you will need to copy the passed
tuple and insert type information.  This is more or less what
ExecEvalVar does now in the whole-tuple case (the critical code is
actually in heap_getsysattr though):

HeapTupleHeaderdtup;

dtup = (HeapTupleHeader) palloc(tup->t_len);
memcpy((char *) dtup, (char *) tup->t_data, tup->t_len);

HeapTupleHeaderSetDatumLength(dtup, tup->t_len);
HeapTupleHeaderSetTypeId(dtup, tupleDesc->tdtypeid);
HeapTupleHeaderSetTypMod(dtup, tupleDesc->tdtypmod);

result = PointerGetDatum(dtup);

regards, tom lane

---(end of broadcast)---
TIP 8: explain analyze is your friend


Re: [HACKERS] Better support for whole-row operations and composite

2004-04-03 Thread Joe Conway
Tom Lane wrote:

Joe Conway <[EMAIL PROTECTED]> writes:

For triggers, I was previously building up the arguments thus:
slot = TupleDescGetSlot(tupdesc);
slot->val = trigdata->tg_trigtuple;
arg[7] = PointerGetDatum(slot);


I suppose now I should do this instead?
arg[7] = PointerGetDatum(trigdata->tg_trigtuple->t_data);


Hm, no, that won't work because a tuple being passed to a trigger
probably isn't going to contain valid type information.  The API for
calling triggers is different from calling ordinary functions, so
I never thought about trying to make it look the same.  At what point
are you trying to do the above, anyway?
That's a shame -- it used to work fine -- done this way so the same 
function could handle tuple arguments to regular functions, and old/new 
tuples to trigger functions. It is in plr_trigger_handler(); vaguely 
similar to pltcl_trigger_handler(). I'll have to figure out a workaround 
I guess.

Joe

---(end of broadcast)---
TIP 5: Have you checked our extensive FAQ?
  http://www.postgresql.org/docs/faqs/FAQ.html


Re: [HACKERS] Function to kill backend

2004-04-03 Thread Tom Lane
Josh Berkus <[EMAIL PROTECTED]> writes:
> Killing backends with runaway queries is a routine administrative
> task.

Cancelling runaway queries is a routine task.  I'm less convinced that a
remote kill (ie SIGTERM) facility is such a great idea.

regards, tom lane

---(end of broadcast)---
TIP 3: if posting/reading through Usenet, please send an appropriate
  subscribe-nomail command to [EMAIL PROTECTED] so that your
  message can get through to the mailing list cleanly


Re: [HACKERS] Better support for whole-row operations and composite

2004-04-03 Thread Joe Conway
Tom Lane wrote:
If you really want the trigger API for PL/R to be indistinguishable from
the function-call API, then I think you will need to copy the passed
tuple and insert type information.  This is more or less what
ExecEvalVar does now in the whole-tuple case (the critical code is
actually in heap_getsysattr though):
That got me there. It may not be the best in terms of pure speed, but it 
is easier and simpler than refactoring, at least at the moment. And I 
don't think the reason people will choose PL/R for triggers is speed in 
any case ;-)

Thanks!

Joe

---(end of broadcast)---
TIP 7: don't forget to increase your free space map settings


Re: [HACKERS] Function to kill backend

2004-04-03 Thread Mike Mascari
Tom Lane wrote:

Josh Berkus <[EMAIL PROTECTED]> writes:

Killing backends with runaway queries is a routine administrative
task.


Cancelling runaway queries is a routine task.  I'm less convinced that a
remote kill (ie SIGTERM) facility is such a great idea.
Of course, cancelling runaway queries on Oracle is only a necessity 
if the DBA hasn't made use of resource limits - PROFILEs. ;-)

Mike Mascari



---(end of broadcast)---
TIP 6: Have you searched our list archives?
  http://archives.postgresql.org


Re: [HACKERS] Function to kill backend

2004-04-03 Thread Andrew Dunstan
Neil Conway said:
> On 2-Apr-04, at 5:16 PM, Andrew Dunstan wrote:
>> If' we're going to have this shouldn't it be a proper command?
>
> Why? What benefit would this offer over implementing this feature as a
> function?
>

psql help

cheers

andrew



---(end of broadcast)---
TIP 6: Have you searched our list archives?

   http://archives.postgresql.org