[GENERAL] How do write schema independent install files for functions.

2012-07-16 Thread Philip Couling
Hi

I have a number of functions which I wish to wrap up in a SQL script
(well technically DDL script).  The functions reference one another and
for safety it is necessary for them to ether set the search_path or
directly reference the schema for one another.

I was wondering if there is good / recommended way to write the install
script to easily install to an arbitrary schema.

The problem I have is that some functions need to set the search_path
for code security. As an example below, the function bar() needs to
set search_path or it would accidently reference the wrong foo().
However in order to install the same functions to a different schema I
would have to re-write the script with numerous changes to the various
set search_path = my_schema lines.


SET search_path = my_schema;

CREATE OR REPLACE FUNCTION foo()
  RETURNS INTEGER AS
$BODY$
BEGIN
RETURN 42;
END;
$BODY$
  LANGUAGE plpgsql IMMUTABLE
  COST 100;

CREATE OR REPLACE FUNCTION bar()
  RETURNS INTEGER AS
$BODY$
BEGIN
RETURN foo();
END;
$BODY$
  LANGUAGE plpgsql IMMUTABLE
  SET search_path = my_schema
  COST 100;


Is there any more flexible way to do this?

Thanks

-- 
Sent via pgsql-general mailing list (pgsql-general@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-general


Re: [GENERAL] How do write schema independent install files for functions.

2012-07-16 Thread Philip Couling
On 16/07/2012 20:44, Tom Lane wrote:
 Philip Couling p...@pedal.me.uk writes:
 I have a number of functions which I wish to wrap up in a SQL script
 (well technically DDL script).  The functions reference one another and
 for safety it is necessary for them to ether set the search_path or
 directly reference the schema for one another.
 
 I was wondering if there is good / recommended way to write the install
 script to easily install to an arbitrary schema.
 
 CREATE FUNCTION's SET search_path FROM CURRENT option might help you.
 
   regards, tom lane
 

Thanks tom. That was exactly what I was looking for and what I'd missed
in the manual.

For the sake of future readers FROM CURRENT is documented here:
http://www.postgresql.org/docs/current/static/sql-createfunction.html

Regards

-- 
Sent via pgsql-general mailing list (pgsql-general@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-general


Re: [GENERAL] Feature discussion: Should syntax errors abort a transaction?

2012-06-20 Thread Philip Couling
On 20/06/2012 08:24, Chris Travers wrote:
 It seems to me there is one very simple reason not to change current
 behavior which those in favor are glossing over.
 
 Most interactions with a database are not occurring over an interface
 like psql with one person typing on one side and the db executing on
 the other.If that were the case I would understand the concern
 that a typo should give the user an opportunity to pick up the
 statement where he/she left off.
 
 However most interactions with the database are purely through
 intermediary software.  Adding a lot of do what I mean or give me a
 chance to retry that adds a great deal of complexity to the job of
 the software in trapping and handling errors.  It is far, far more
 simple to say syntax errors abort transactions and leave it at that.
  I know as a developer I don't want that behavior to change.
 
 I guess it seems to me that I would not object to a new option for
 transaction behavior where one could do something like SET TRANSACTION
 INTERACTIVE; and have no errors abort the transaction at all (explicit
 commit or rollback required) but I would complain loudly if this were
 to be the default, and I don't see a real need for it.
 
 Best Wishes,
 Chris Travers
 

It would be very nice to turn this feature off completely as a property
of your session.

I generally see it as necessary to do everything inside a transaction
when working in the DB manually. It adds greater protection against
forgotten WHERE clauses etc.  I've seen too many DBs mashed because of a
careless typo. The current behavior encourages admins not to use
transactions because any error (typo or not) forces them to re-do all
their work so far or put in a lot of extra typing to wrap everything.


On the idea of different error behavior between bad syntax and pragmatics...

Splitting hairs between a syntax error and other errors is dangerous.
There are too many cases where the division can not be clear.  And any
implementation would find it difficult not to fall foul of the principle
of least astonishment.
http://en.wikipedia.org/wiki/Principle_of_least_astonishment

For example pg/plsql executing dynamic SQL.  An error may have been
caused by faulty arguments. However one of the arguments may have been a
SQL statement in part or full.  How should PostgreSQL behave? See the
argument as bad (data error) or the SQL it contains as a syntax error.
You can always find an answer to this that works, but will that answer
be obvious to every developer?

Regards

Phil

-- 
Sent via pgsql-general mailing list (pgsql-general@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-general


Re: [GENERAL] || versus concat( ), diff behavior

2012-03-02 Thread Philip Couling

On 02/03/12 20:58, david.sahag...@emc.com wrote:

Can anybody please point me to where this difference of behavior is 
explained/documented ?
Thanks,
-dvs-

-- version = 9.1.3
do $$
declare
   v_str  char(10);
begin
   v_str := 'abc' ;
   raise info '%', concat(v_str, v_str) ;
   raise info '%', v_str||v_str ;
end
$$;

INFO:  abc   abc
INFO:  abcabc




Concat is a function which concatenates whatever you give it blindly. 
Hence it has the behavior that includes the blanks.


The || operator reflects the more general PostgreSQL principle that 
trailing blanks are insignificant for char fields.  You see the same 
behavior when comparing char variables.



This can be found in the manual:

http://www.postgresql.org/docs/current/static/datatype-character.html

Values of type character are physically padded with spaces to the 
specified width n, and are stored and displayed that way. However, the 
padding spaces are treated as semantically insignificant. Trailing 
spaces are disregarded when comparing two values of type character, and 
they will be removed when converting a character value to one of the 
other string types. Note that trailing spaces are semantically 
significant in character varying and text values, and when using pattern 
matching, e.g. LIKE, regular expressions.



Hope this makes it just a little clearer.

Regards

--
Sent via pgsql-general mailing list (pgsql-general@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-general


Re: [GENERAL] Easy form of insert if it isn't already there?

2012-02-15 Thread Philip Couling
This must be a function or trigger to break one statement into two.  You
could of course simply use two separate statements in PHP as long as
they are in the same transaction.  If you're going to perform this
action in two steps then putting both in a function or trigger is often
preferable.

Looking back at your original question.  Although your option 2 feels
chunky, it feels to me a generally better option.

INSERT INTO table_name (col1,col2,col3) SELECT val1,val2,val3 WHERE NOT
EXISTS (SELECT * FROM table WHERE col1=val1 AND col2=val2)

or

INSERT INTO table (col1,col2,col3) SELECT val1,val2,val3 WHERE
(val1,val2,val3) NOT IN (SELECT col1,col2,col3 FROM table)

It does what it says on the tin and someone else maintaining your code
will understand what it does at a glance.  The same can not be said for
triggers and perhaps functions.  My gut feeling is that the performance
of this will be better too.

Regards,
Phil



On 15/02/2012 07:14, Bartosz Dmytrak wrote:
 Yes it is.
 You can implement trigger on table to check if inserted record is new.
 Still it is on DB side.
 I don't know PHP well enough but I think You can call function e.g.
 SELECT myschema.InsertWhenNew (val1, val2, val3); in the same
 way as You call INSERTS
 
 Regards,
 Bartek
 
 
 2012/2/15 Chris Angelico ros...@gmail.com mailto:ros...@gmail.com
 
 On Wed, Feb 15, 2012 at 5:26 PM, Bartosz Dmytrak bdmyt...@eranet.pl
 mailto:bdmyt...@eranet.pl wrote:
  Hi,
  similar topic is in NOVICE mailing
  list: http://archives.postgresql.org/pgsql-novice/2012-02/msg00034.php
 
  e.g. You can use BEGIN... EXCEPTION END, good example of
  such approach is
 
 there: 
 http://www.postgresql.org/docs/9.1/static/plpgsql-control-structures.html#PLPGSQL-UPSERT-EXAMPLE;
 
 Ah, thanks for that!
 
 Currently the query is a single PHP pg_query_params() call, and it's
 inside a larger transaction. By the look of it, this requires writing
 a function to do the job, rather than embedding the logic straight
 into the query - is this correct?
 
 ChrisA
 
 --
 Sent via pgsql-general mailing list (pgsql-general@postgresql.org
 mailto:pgsql-general@postgresql.org)
 To make changes to your subscription:
 http://www.postgresql.org/mailpref/pgsql-general
 
 


-- 
Sent via pgsql-general mailing list (pgsql-general@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-general


Re: [GENERAL] last entry per person

2012-02-03 Thread Philip Couling

On 03/02/2012 08:30, Chris Travers wrote:



On Fri, Feb 3, 2012 at 12:26 AM, garry ga...@scholarpack.com 
mailto:ga...@scholarpack.com wrote:


I have a table which holds a user name and their results in exams.
There can be multiple entries per user. I am trying to return the
last entry for each user. I can get the last entry in the table
using the order by/limit method but how would this be applied per
user. My table definition is like the following:

gradeid serial primary key,
user text,
grade char(1),
entered timestamp,

Any help would be appreciated.
Regards


What about a combination of a common table expression and a windowing 
function?  You ought to be able to order by your criteria and then 
pull where the rowcount in the window is 1.


Best Wishes,
Chris Travers


Garry



--
Sent via pgsql-general mailing list (pgsql-general@postgresql.org
mailto:pgsql-general@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-general



There is no simple solution like there is for the last row in the table.
Window functions are one option, sub queries are another:

SELECT *
  FROM results,
   ( SELECT student_id,
max(result_date) result_date
   FROM results
   GROUP BY student_id
   ) as latest
 WHERE results.student_id = latest.student_id
   AND results.result_date = latest.result_date

Note that for this to work correctly, result_date will need to be unique.

Regards