Question

I have the following stored procedure:

CREATE OR REPLACE FUNCTION get_next_network()
    RETURNS inet AS
$BODY$
/* get the next networkd */
DECLARE 
      ip inet;
BEGIN
      select into ip (inet'10.41.142.0' + nextval('NetworkAddress_seq'));
  return ip;
END;
$BODY$
LANGUAGE plpgsql VOLATILE;

the sequence NetworkAddress_seq increments with 256:

CREATE SEQUENCE "NetworkAddress_seq"
    INCREMENT 256
    MINVALUE 256
    MAXVALUE 9223372036854775807
    START 256
    CACHE 256;
    ALTER TABLE "NetworkAddress_seq"
    OWNER TO my_user;

When I call the function from pgAdmin I get: 10.41.143.0

When I call it from php/Doctrine/ORM:

$stmt = $this->_em->getConnection()->prepare("select get_next_network()");
$stmt->execute();
$stmt->fetchColumn(0);

I get something like 10.56.142.0

Why?

Edit: I checked that I'm using the same procedure by hardcoding the return value - in this case I get the same value both in pgadmin and in php. This also puts the question mark on the sequence but as I'm querying it from the procedure and not directly I would assume that no matter from where I call the get_next_network procedure it will use the same sequence... or am I wrong about this?

Edit2: The strange behavior is not related to the php side - I get the same strange results if open multiple pgAdmin SQL query windows (different DB connections?). For example: in Window1 I run

select * from get_next_network();

end get: 10.43.143.0 and if I run it again I get: 10.43.144.0, 10.43.145.0, ... etc. In Window2 - the same query returns: 10.44.143.0 and all the subsequent queries get: 10.44.144.0, 10.44.145.0,..etc.

Was it helpful?

Solution 3

The problem was the CACHE setting to 256. I removed it (default 1) and now no matter from where I call my procedure I get the next value..

An explanation from here

In the case of PostgreSQL, a sequence object can be configured to cache multiple values within a single backend process so that if you are generating large numbers of values, a particular backend might " lay claim" to a range of 100 values all at once, making clashes between concurrent processes go away.

A disadvantage to cacheing is that values can and will get skipped along the way. If you were expecting them to fall in some exact serial order, that expectation will fail.

I was expecting that each call to the procedure will grow the sequence with the increment no matter from where it was executing.

OTHER TIPS

Situations like these usually point to that your are not connecting to the correct database.

Next to a possible confusion with the database connection like hinted by @Marek, there is another typical pitfall:

A different setting for the search_path, which could resolve 'NetworkAddress_seq' to a SEQUENCE of the same name in a different schema, or even find a function get_next_network() in a different schema.

  select into ip (inet'10.41.142.0' + nextval('NetworkAddress_seq'));

BTW, I never use CaMeL-case identifiers in Postgres. That's just asking for trouble.

The call nextval('NetworkAddress_seq') looks for a sequence with CaMeL-case name, created with:

CREATE SEQUENCE "NetworkAddress_seq";  -- with double-quotes!

But not:

CREATE SEQUENCE NetworkAddress_seq;

.. which results in a sequence named networkaddress_seq, and you would have to use:

nextval('networkaddress_seq')

May be part of the problem.


Also, everything might be correct and the sequence has been incremented that many times in between. You ruled that out, right?

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top