Re: [PATCHES] Another Plpgsql trigger example - summary table

2005-01-10 Thread Mark Kirkwood
Mark Kirkwood wrote:
 
2) Perhaps leave the trigger + plpgsql function as a plpgsql example,
and refer to it in the (new) data warehouse section/chapter.

Looking at option 2, it seems reasonable to add a trimmed trigger 
example into the plpgsql examples section now, and leave the data 
warehouse introductory stuff for its own chapter at some later stage.

--- plpgsql.sgml.orig   Tue Jan 11 12:39:17 2005
+++ plpgsql.sgmlTue Jan 11 13:43:35 2005
@@ -2646,6 +2646,162 @@
 FOR EACH ROW EXECUTE PROCEDURE process_emp_audit();
 

+
+   
+An area where triggers can be useful is maintaining a summary table
+of another table. The resulting summary can be used in place of the 
+original table for certain queries - with often vastly reduced run 
+times.
+   
+
+   
+This technique is commonly used in Data Warehousing, where the tables
+of measured or observed data (called fact tables) can be extremely large.
+ shows an example of a
+trigger procedure in PL/pgSQL that maintains
+a summary table for a fact table in a data warehouse.
+   
+
+
+   
+A PL/pgSQL Trigger Procedure For 
Maintaining A Summary Table
+
+
+ The schema detailed here is partly based on the Grocery Store
+  example from The Data Warehouse Toolkit 
+ by Ralph Kimball.
+
+
+
+--
+-- Main tables - time dimension and sales fact.
+--
+CREATE TABLE time_dimension (
+time_keyinteger NOT NULL,
+day_of_week integer NOT NULL,
+day_of_monthinteger NOT NULL,
+month   integer NOT NULL,
+quarter integer NOT NULL,
+yearinteger NOT NULL
+);
+CREATE UNIQUE INDEX time_dimension_key ON time_dimension(time_key);
+
+CREATE TABLE sales_fact (
+time_keyinteger NOT NULL,
+product_key integer NOT NULL,
+store_key   integer NOT NULL,
+amount_sold numeric(12,2) NOT NULL,
+units_sold  integer NOT NULL,
+amount_cost numeric(12,2) NOT NULL
+);
+CREATE INDEX sales_fact_time ON sales_fact(time_key);
+
+--
+-- Summary table - sales by time.
+--
+CREATE TABLE sales_summary_bytime (
+time_keyinteger NOT NULL,
+amount_sold numeric(15,2) NOT NULL,
+units_sold  numeric(12) NOT NULL,
+amount_cost numeric(15,2) NOT NULL
+);
+CREATE UNIQUE INDEX sales_summary_bytime_key ON sales_summary_bytime(time_key);
+
+--
+-- Function and trigger to amend summarized column(s) on UPDATE, INSERT, 
DELETE.
+--
+CREATE OR REPLACE FUNCTION maint_sales_summary_bytime() RETURNS TRIGGER AS 
$maint_sales_summary_bytime$
+DECLARE
+delta_time_key  integer;
+delta_amount_sold   numeric(15,2);
+delta_units_soldnumeric(12);
+delta_amount_cost   numeric(15,2);
+BEGIN
+
+-- Work out the increment/decrement amount(s).
+IF (TG_OP = 'DELETE') THEN
+
+delta_time_key = OLD.time_key;
+delta_amount_sold = -1 * OLD.amount_sold;
+delta_units_sold = -1 * OLD.units_sold;
+delta_amount_cost = -1 * OLD.amount_cost;
+
+ELSIF (TG_OP = 'UPDATE') THEN
+
+-- forbid updates that change the time_key -
+-- (probably not too onerous, as DELETE + INSERT is how most 
+-- changes will be made).
+IF ( OLD.time_key != NEW.time_key) THEN
+RAISE EXCEPTION 'Update of time_key : % -> % not allowed', 
OLD.time_key, NEW.time_key;
+END IF;
+
+delta_time_key = OLD.time_key;
+delta_amount_sold = NEW.amount_sold - OLD.amount_sold;
+delta_units_sold = NEW.units_sold - OLD.units_sold;
+delta_amount_cost = NEW.amount_cost - OLD.amount_cost;
+
+ELSIF (TG_OP = 'INSERT') THEN
+
+delta_time_key = NEW.time_key;
+delta_amount_sold = NEW.amount_sold;
+delta_units_sold = NEW.units_sold;
+delta_amount_cost = NEW.amount_cost;
+
+END IF;
+
+
+-- Update the summary row with the new values.
+UPDATE sales_summary_bytime
+SET amount_sold = amount_sold + delta_amount_sold,
+units_sold = units_sold + delta_units_sold,
+amount_cost = amount_cost + delta_amount_cost
+WHERE time_key = delta_time_key;
+
+
+-- There might have been no row with this time_key (e.g new data!).
+IF (NOT FOUND) THEN
+BEGIN
+INSERT INTO sales_summary_bytime (
+time_key, 
+amount_sold, 
+units_sold, 
+amount_cost)
+SELECT  f.time_key, 
+sum(f.amount_sold), 
+sum(f.unit

[PATCHES] "SMgrRelation hashtable corrupted" fix, phase 1

2005-01-10 Thread Tom Lane
Attached is a patch that fixes the recently isolated "SMgrRelation
hashtable corrupted" bug by allowing smgrclose() to happen safely
without being called directly by the relcache.  The reason this is
an issue is that the relcache might contain a pointer to the
SMgrRelation entry, and if that pointer isn't cleared then we have a
dangling pointer, which on use will cause the "hashtable corrupted"
failure if not worse things.  The fix is for smgr.c to be aware of
the possible existence of a long-lived pointer to each SMgrRelation
entry, and to zero out any such pointer when smgrclose() is called.

I believe this is considerably more robust than the previous approach.
It's a bit uglier than before, but it's not quite tantamount to smgr
depending on relcache --- smgr only knows there is a pointer, not what
sort of structure it's stored in.

Note that this problem doesn't exist pre-8.0 since the separate smgr
cache table didn't exist in prior releases.  Basically what's at stake
here is keeping the relcache and smgr cache in step.

The bulk of the patch consists of replacing the common patterns for
smgropen() and smgrclose() calls associated with relcache entries
with two new macros RelationOpenSmgr and RelationCloseSmgr, which is
doubtless the way it should have been coded in the first place.
Ignoring that, the changes reduce to the addition of smgrsetowner(),
changing smgrclose() to clear the reference pointer if set,
simplifying RelationCacheInvalidateEntry back to the way it was in 7.4,
and simplifying LocalExecuteInvalidationMessage to treat relcache and
smgr cache inval as independent operations.

With the last change, there is no longer a reason for shared inval
messages to handle relcache and smgr invals as a single operation;
we can send those as two separate messages instead.  I want to do
this because it'll allow sizeof(SharedInvalidationMessage) to go back
to 16 bytes as it was in prior releases instead of 24 bytes as it is
now, saving a fair amount of shared memory space.  I'm going to post
that as a separate patch though, since it's logically separate.

regards, tom lane


*** src/backend/access/transam/xlogutils.c.orig Fri Dec 31 17:45:32 2004
--- src/backend/access/transam/xlogutils.c  Mon Jan 10 13:41:19 2005
***
*** 125,132 
if (hentry == NULL)
elog(PANIC, "_xl_remove_hash_entry: file was not found in 
cache");
  
!   if (rdesc->reldata.rd_smgr != NULL)
!   smgrclose(rdesc->reldata.rd_smgr);
  
memset(rdesc, 0, sizeof(XLogRelDesc));
memset(tpgc, 0, sizeof(FormData_pg_class));
--- 125,131 
if (hentry == NULL)
elog(PANIC, "_xl_remove_hash_entry: file was not found in 
cache");
  
!   RelationCloseSmgr(&(rdesc->reldata));
  
memset(rdesc, 0, sizeof(XLogRelDesc));
memset(tpgc, 0, sizeof(FormData_pg_class));
***
*** 233,239 
hentry->rdesc = res;
  
res->reldata.rd_targblock = InvalidBlockNumber;
!   res->reldata.rd_smgr = smgropen(res->reldata.rd_node);
  
/*
 * Create the target file if it doesn't already exist.  This 
lets
--- 232,239 
hentry->rdesc = res;
  
res->reldata.rd_targblock = InvalidBlockNumber;
!   res->reldata.rd_smgr = NULL;
!   RelationOpenSmgr(&(res->reldata));
  
/*
 * Create the target file if it doesn't already exist.  This 
lets
***
*** 278,284 
  
rdesc = hentry->rdesc;
  
!   if (rdesc->reldata.rd_smgr != NULL)
!   smgrclose(rdesc->reldata.rd_smgr);
!   rdesc->reldata.rd_smgr = NULL;
  }
--- 278,282 
  
rdesc = hentry->rdesc;
  
!   RelationCloseSmgr(&(rdesc->reldata));
  }
*** src/backend/catalog/heap.c.orig Fri Dec 31 17:45:32 2004
--- src/backend/catalog/heap.c  Mon Jan 10 12:38:30 2005
***
*** 322,328 
if (create_storage)
{
Assert(rel->rd_smgr == NULL);
!   rel->rd_smgr = smgropen(rel->rd_node);
smgrcreate(rel->rd_smgr, rel->rd_istemp, false);
}
  
--- 322,328 
if (create_storage)
{
Assert(rel->rd_smgr == NULL);
!   RelationOpenSmgr(rel);
smgrcreate(rel->rd_smgr, rel->rd_istemp, false);
}
  
***
*** 1186,1195 
if (rel->rd_rel->relkind != RELKIND_VIEW &&
rel->rd_rel->relkind != RELKIND_COMPOSITE_TYPE)
{
!   if (rel->rd_smgr == NULL)
!   rel->rd_smgr = smgropen(rel->rd_node);
smgrscheduleunlink(rel->rd_smgr, rel->rd_istemp);
-   rel->rd_smgr = NULL;
}
  
/*
--- 1186,1193 
if (rel->rd_rel->relkind != RELKIND_VIEW &&
rel->rd_rel->relkind != RELKIND_COMPOSITE_TYPE)
{
!  

Re: [PATCHES] re-enable MSVC builds

2005-01-10 Thread Tom Lane
Andrew Dunstan <[EMAIL PROTECTED]> writes:
> Magnus Hagander wrote:
>> I'm sure it still eneds the shell32 linking.

> I don't see where to put it in the bcc.mak file anyway.

Yeah, I looked in bcc32.mak and didn't see any reference to the other
*32.dll files that win32.mak references.  So either Borland does not
need any of them, or the Borland build has been broken for awhile.

If someone steps up to fix it, great, otherwise it's on the path to
extinction...

regards, tom lane

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


Re: [PATCHES] re-enable MSVC builds

2005-01-10 Thread Andrew Dunstan

Magnus Hagander wrote:
The attached patch allows MSCV builds to complete.
 

Applied.
(I wonder whether the Borland build still works...)
   

I'm sure it still eneds the shell32 linking. The suorce part should be
the same - AFAIK they ship the MS headers. But I don't have a way to
test it, so...
 

 

Me either, and I don't have time to acquire/test before release. I don't 
see where to put it in the bcc.mak file anyway. So, either it's not 
broken, or it is broken and will stay that way, or it is broken and 
somebody else will step in *real* quick to fix it :-) I am not betting 
on this last.

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


Re: [PATCHES] Turkish translation update

2005-01-10 Thread Peter Eisentraut
Devrim GUNDUZ wrote:
> http://postgresql.gunduz.org/translation/PostgreSQL-8.0/PgSQL-DilDosy
>alari/postgres-tr.po
> Could you please apply it to -HEAD?

Done.

-- 
Peter Eisentraut
http://developer.postgresql.org/~petere/

---(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: [PATCHES] re-enable MSVC builds

2005-01-10 Thread Magnus Hagander
> > The attached patch allows MSCV builds to complete.
> 
> Applied.
> 
> (I wonder whether the Borland build still works...)

I'm sure it still eneds the shell32 linking. The suorce part should be
the same - AFAIK they ship the MS headers. But I don't have a way to
test it, so...


> > The warnings still shown (see recent -hackers email) are 
> identical to 
> > those that were present in RC2, so they are not the 
> products of recent 
> > homedir changes.
> 
> With the possible exception of the mkdir warning, these seem 
> cosmetic and not worth worrying about at this stage of the 
> release cycle.

Definitly. There have been cosmetic warnings in the win32 build ever
since it was created.

//Magnus

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

   http://archives.postgresql.org