Postgres + doCalcDefaults + Bigserial Column = 2 on 2 seq.!
Moderators: gto, cipto_kh, EgonHugeist, olehs
-
- Junior Boarder
- Posts: 35
- Joined: 30.08.2005, 16:30
- Location: Olinda / PE
- Contact:
Postgres + doCalcDefaults + Bigserial Column = 2 on 2 seq.!
Hello Everybody!
I'll be direct on my post...
I'm using now the PostgreSQL database. I'm using BIGSERIAL columns, to take advantage of sequences to primary keys. This is very usual, i guess.
So, I've done a little application to test this behaviour. Everything was fine, except that my primary key column is being filled with values like: 2, 4, 6, 8, 10... 2 on 2.
When i turn off the "doCalcDefaults" option, the sequence works like a charm, but, eventual blank fields with default values aren't being automatically filled after insert because the state of doCalcDefaults is "off"
Doing a debug i found that TZGenericCachedResolver.FormCalculateStatement is generating a SQL with the default value of my bigserial column. Something like "SELECT NEXTVAL(COLUMNNAME)". On postgres, the default value of a column is used to make sequences.
Well. I do not want to change this source code. You, commiters/developers of ZeosLib, have some plan to fix this?
I'll be direct on my post...
I'm using now the PostgreSQL database. I'm using BIGSERIAL columns, to take advantage of sequences to primary keys. This is very usual, i guess.
So, I've done a little application to test this behaviour. Everything was fine, except that my primary key column is being filled with values like: 2, 4, 6, 8, 10... 2 on 2.
When i turn off the "doCalcDefaults" option, the sequence works like a charm, but, eventual blank fields with default values aren't being automatically filled after insert because the state of doCalcDefaults is "off"
Doing a debug i found that TZGenericCachedResolver.FormCalculateStatement is generating a SQL with the default value of my bigserial column. Something like "SELECT NEXTVAL(COLUMNNAME)". On postgres, the default value of a column is used to make sequences.
Well. I do not want to change this source code. You, commiters/developers of ZeosLib, have some plan to fix this?
-
- Junior Boarder
- Posts: 35
- Joined: 30.08.2005, 16:30
- Location: Olinda / PE
- Contact:
- mdaems
- Zeos Project Manager
- Posts: 2766
- Joined: 20.09.2005, 15:28
- Location: Brussels, Belgium
- Contact:
Ðerek wildstar,
I could say 'DOWN', but that would be rude, I suppose.
I don't really understand the nature of your problem. Maybe because I'm not a postgres user.
Do I understand correctly that you're using a simple TZQuery component not combined with TZSequence component? Or are you combining both components AND setting a default value on your database column which also calculates using the same sequence?
In the first case there's probably a zeoslib issue.
But when you're combining the 2 components that's a bad idea. Zeoslib is smart enough to fill the data field with your database default value with doCalcDefaults, so you should not use the same sequence to overwrite the value again.
Concerning
Mark
I could say 'DOWN', but that would be rude, I suppose.
I don't really understand the nature of your problem. Maybe because I'm not a postgres user.
Do I understand correctly that you're using a simple TZQuery component not combined with TZSequence component? Or are you combining both components AND setting a default value on your database column which also calculates using the same sequence?
In the first case there's probably a zeoslib issue.
But when you're combining the 2 components that's a bad idea. Zeoslib is smart enough to fill the data field with your database default value with doCalcDefaults, so you should not use the same sequence to overwrite the value again.
Concerning
Unfortunately, I don't have the time nor the knowledge to fix this when it turns out to be a real zeoslib problem. You might have noticed we're really looking for commiters. Just come forward with your sourceforge username and I give you commit rights so the problem can be fixed by you.You, commiters/developers of ZeosLib, have some plan to fix this?
Mark
-
- Junior Boarder
- Posts: 35
- Joined: 30.08.2005, 16:30
- Location: Olinda / PE
- Contact:
Sorry for UP...
Well I'm not using two components only one. The last paragraph is very explanatory. I will complete it:
Doing a debug i found that TZGenericCachedResolver.FormCalculateStatement is generating a SQL with the default value of my bigserial column. Something like "SELECT NEXTVAL(COLUMNNAME)". On postgres, the default value of a column is used to make sequences.
This way every time Zeos get the default value for a column with this "autoincrement" then the autoincrement value increases, but this is not to be done. On execute "SELECT NEXTVAL(COLUMNNAME)" the autoincrement value increases, and because of this the autogenerated keys are being generated "2 on 2".
Sorry my very bad english.
Well I'm not using two components only one. The last paragraph is very explanatory. I will complete it:
Doing a debug i found that TZGenericCachedResolver.FormCalculateStatement is generating a SQL with the default value of my bigserial column. Something like "SELECT NEXTVAL(COLUMNNAME)". On postgres, the default value of a column is used to make sequences.
This way every time Zeos get the default value for a column with this "autoincrement" then the autoincrement value increases, but this is not to be done. On execute "SELECT NEXTVAL(COLUMNNAME)" the autoincrement value increases, and because of this the autogenerated keys are being generated "2 on 2".
Sorry my very bad english.
- mdaems
- Zeos Project Manager
- Posts: 2766
- Joined: 20.09.2005, 15:28
- Location: Brussels, Belgium
- Contact:
Does that mean a BIGSERIAL column ALWAYS increments, even if it gets a value passd in the insert statement?
Why do you need a DEFAULT value in the column definition then? Or is that something that's generated automatically by postgres in the special case of a bigserial? If that's true, the somebody should disable this behaviour of getting a default value for bigserial columns (and similar datatypes, of course) AND make sure the autoincremented value is retrieved in a way that's similar to the method used for mysql autoincrements.
So please can you confirm this special BIGSERIAL behaviour works the way I understand and
- direct us to the documentation that proves this
- think if you could be the one who fixes this
Mark
Why do you need a DEFAULT value in the column definition then? Or is that something that's generated automatically by postgres in the special case of a bigserial? If that's true, the somebody should disable this behaviour of getting a default value for bigserial columns (and similar datatypes, of course) AND make sure the autoincremented value is retrieved in a way that's similar to the method used for mysql autoincrements.
So please can you confirm this special BIGSERIAL behaviour works the way I understand and
- direct us to the documentation that proves this
- think if you could be the one who fixes this
Mark
-
- Junior Boarder
- Posts: 35
- Joined: 30.08.2005, 16:30
- Location: Olinda / PE
- Contact:
Hello Mark, thanks for the answer. Here comes more informations...
In PostGres the BIGSERIAL type is lika an alias for a BIGINT column with a automatically generated default value of something like "nextval('sequencename'::regclass)". More detailed:
After execute the following DDL
The real table definition turns
When doCalcDefaults are "ON" the ZeosLib PostGres implementation in "TZGenericCachedResolver.FormCalculateStatement" does "SELECT DEFAULT VALUE". If i have an integer or varchar default value, this approach is perfect, however on this special case the generated select will be
This command does not raise any exception. In fact it's correct by itself, but, on execute it, the 'test_id_seq' will be incremented on database server, so, a subsequent insert will not fill the ID column with the next value but with the next next value, ie, one for the insert and another for the "get default value", triggered when doCalcDefaults = true
For this special case, the following command would be used
This command gets the current value of the sequence, more or less like the MySQL LAST_INSERT_ID()
Sorry, I have no time now to do this fix on Zeos. I do not even have a login to do it also . And, I guess, I'm not the correct person to do that becouse I do not know the possible impacts of change something on Zeos Trunk.
In PostGres the BIGSERIAL type is lika an alias for a BIGINT column with a automatically generated default value of something like "nextval('sequencename'::regclass)". More detailed:
After execute the following DDL
Code: Select all
create table TEST (
ID BIGSERIAL NOT NULL,
CONSTRAINT PK_TEST PRIMARY KEY (ID)
)
Code: Select all
CREATE TABLE test
(
id bigint NOT NULL DEFAULT nextval('test_id_seq'::regclass),
column_name character varying(10),
CONSTRAINT pk_test PRIMARY KEY (id )
)
Code: Select all
SELECT nextval('test_id_seq'::regclass)
For this special case, the following command would be used
Code: Select all
SELECT CURRVAL('test_id_seq')
Sorry, I have no time now to do this fix on Zeos. I do not even have a login to do it also . And, I guess, I'm not the correct person to do that becouse I do not know the possible impacts of change something on Zeos Trunk.
-
- Expert Boarder
- Posts: 113
- Joined: 06.10.2006, 14:41
- Location: Chapecó - Santa Catarina
- Contact:
-
- Junior Boarder
- Posts: 35
- Joined: 30.08.2005, 16:30
- Location: Olinda / PE
- Contact:
...
Oi "papelhigienico" (!)papelhigienico wrote:Can you post a small example of your problem (with database) here? A example will make my life more easy
Na verdade já coloquei toda informação aqui. Não há mais nada para exemplificar. A funcionalidade ativada com a opção "doCalcDefaults" faz com que a sequencia do PostGres associada com o campo chave seja executada uma vez mais, após um registro ter sido salvo (post).
Dessa forma, postagens de inserts subsequentes sempre terão o valor da chave +2 ao invés de +1.
Isso acontece porque esta funcionalidade (doCalcDefaults) não é suficientemente inteligente para distinguir entre o valor de um campo default ser um simples varchar ou integer de uma função de sequencia (nextval).
Code: Select all
ID INTEGER NOT NULL DEFAULT 1
Code: Select all
ID INTEGER NOT NULL DEFAULT NEXTVAL('SEQUENCIA'::regclass)
Code: Select all
SELECT NEXTVAL('SEQUENCIA'::regclass)
Code: Select all
SELECT CURRVAL('SEQUENCIA')
In English (Google Translator)
Hi "papelhigienico" (!)
In fact I already put all the information here. There's nothing else to exemplify. The functionality enabled with the "doCalcDefaults" makes Postgres sequence associated with the key field to run again after a record has been saved (post).
Thus, subsequent postings will always inserts the key value +2 instead of +1.
This is because this feature (doCalcDefaults) is not smart enough to distinguish between the value of a default to be a simple integer or varchar from a sequence function (nextval).
Code: Select all
ID INTEGER NOT NULL DEFAULT 1
Code: Select all
ID INTEGER NOT NULL DEFAULT nextval ('sequence':: regclass)
Code: Select all
SELECT NEXTVAL ('sequence':: regclass)
Code: Select all
CURRVAL SELECT ('sequence')
-
- Expert Boarder
- Posts: 113
- Joined: 06.10.2006, 14:41
- Location: Chapecó - Santa Catarina
- Contact:
-
- Expert Boarder
- Posts: 113
- Joined: 06.10.2006, 14:41
- Location: Chapecó - Santa Catarina
- Contact:
-
- Junior Boarder
- Posts: 35
- Joined: 30.08.2005, 16:30
- Location: Olinda / PE
- Contact:
-
- Junior Boarder
- Posts: 35
- Joined: 30.08.2005, 16:30
- Location: Olinda / PE
- Contact:
Since the day of first post of this thread i could not reproduce the error anymore, but I guess it's simple
1 TZConnection (autocommit = true)
1 TZQuery
1 TDataSource
1 TZUpdateSQL
1 TDBGrid
1 TDBNavigator
1 Postgres Database
1. Configure and link everything
2. Keep the doCalcDefaults of the TZQuery activated (default)
3. Create a postgres table with only two columns, one of them is a bigserial colum. The other can be anything.
4. Configure the TZReadOnlyQuery with the three SQLs. On Insert SQL use only the second column; as the first is BigSerial you do not need to care about it
5. Configure the TDBGrid to see all columns, including the BIGSERIAL one
6. Run the application
7. Insert a new field
8. Post and press refresh
9. Insert another new field
10. Post and press refresh
11. See the BIGSERIAL column
If the test is successful the first record has 1 on the bigserial column and the second has 3, not two. I'm not sure about the first and second values but do not matter. What only matter is that the bigserial column is being incremented two on two
1 TZConnection (autocommit = true)
1 TZQuery
1 TDataSource
1 TZUpdateSQL
1 TDBGrid
1 TDBNavigator
1 Postgres Database
1. Configure and link everything
2. Keep the doCalcDefaults of the TZQuery activated (default)
3. Create a postgres table with only two columns, one of them is a bigserial colum. The other can be anything.
4. Configure the TZReadOnlyQuery with the three SQLs. On Insert SQL use only the second column; as the first is BigSerial you do not need to care about it
5. Configure the TDBGrid to see all columns, including the BIGSERIAL one
6. Run the application
7. Insert a new field
8. Post and press refresh
9. Insert another new field
10. Post and press refresh
11. See the BIGSERIAL column
If the test is successful the first record has 1 on the bigserial column and the second has 3, not two. I'm not sure about the first and second values but do not matter. What only matter is that the bigserial column is being incremented two on two
-
- Expert Boarder
- Posts: 113
- Joined: 06.10.2006, 14:41
- Location: Chapecó - Santa Catarina
- Contact:
-
- Junior Boarder
- Posts: 35
- Joined: 30.08.2005, 16:30
- Location: Olinda / PE
- Contact:
Yes. That's the problem. On error, the persistent field try to get the default value, and so the sequence is executed! SELECT DEFAULTVALUE translates into SELECT NEXTVAL('SEQUENCENAME') but would be SELECT CURRVAL('SEQUENCENAME'). This is a special case for the postgres database and auto increment fields (sequences)
papelhigienico wrote:I found another issue related with bigserial. If you try insert, and something on the record inserted is wrong (like key duplicity) the value of SERIAL/BIGSERIAL is incremented 2 or more times.