Re: [fpc-pascal] How are Assigned, Free, Nil and Destroy related?
I understand Assigned as being the same as nil, so Assigned(Object) = Object nil I vaguely remember that it could be safer in some corner case, but I don't remember ever meting that. Free is how you release the memory allocated for a object. Free calls Destroy. Never call Destroy manually. When you implement the destructor you always implement Destroy, never change Free. Nil is not a routine, it is a value, it means that the object is empty, it does not exist / is not allocated. Nil in existing implementations that I know is represented by the value zero. The typical life-cycle of a object is: MyObject := TMyObject.Create; try MyObject.DoSomething(); finally MyObject.Free; end; To implement this object you should implement Create, DoSomething and Destroy. -- Felipe Monteiro de Carvalho ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] How are Assigned, Free, Nil and Destroy related?
22.10.2011 10:20, Felipe Monteiro de Carvalho пишет: I understand Assigned as being the same as nil, so Assigned(Object) = Object nil I vaguely remember that it could be safer in some corner case, but I don't remember ever meting that. Method pointers? ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] How are Assigned, Free, Nil and Destroy related?
On 22 October 2011 07:20, Felipe Monteiro de Carvalho felipemonteiro.carva...@gmail.com wrote: I understand Assigned as being the same as nil, so Assigned(Object) = Object nil I vaguely remember that it could be safer in some corner case, but I don't remember ever meting that. Free is how you release the memory allocated for a object. Free calls Destroy. Never call Destroy manually. When you implement the destructor you always implement Destroy, never change Free. Nil is not a routine, it is a value, it means that the object is empty, it does not exist / is not allocated. Nil in existing implementations that I know is represented by the value zero. The typical life-cycle of a object is: MyObject := TMyObject.Create; try MyObject.DoSomething(); finally MyObject.Free; end; To implement this object you should implement Create, DoSomething and Destroy. -- Felipe Monteiro de Carvalho ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-pascal This code is the source of my woes. SCStrings and FBreakStrings are part of an object. They are repeatedly used in a loop and I need to free the memory after the loop runs or free the space taken up by their strings type TRuntimeMonitor = class(TThread) private Frequency: Integer; IniFile: TMemIniFile; SCStrings: TStringList; FBreakStrings: TStringList; procedure DispatchOutput; procedure DisplayRawOutput; protected procedure Execute; override; public constructor Create(CreateSuspended: Boolean); end; * * procedure InitVars; begin if not Assigned(SCStrings) then SCStrings := TStringList.Create; if not Assigned(FBreakStrings) then FBreakStrings := TStringList.Create; IniFile := TMemIniFile.Create('zxtyu'); end; procedure FreeVars; begin IniFile.Free; if Assigned(SCStrings) then SCStrings.Free; if Assigned(FBreakStrings) then FBreakStrings.Free; if Assigned(FBreakStrings) then debugln('FBreakStrings is still assigned'); end; * *InitVars and FreeVars run in the Execute procedure of the thread* *When the loop runs again Assigned in InitVars is false so as soon as those FBreakStrings and SCStrings are accessed within the loop a SIGSEGV occurs. So what I want to know is whether Assigned remains true when Free is executed. In the mean time instead of using Free in FreeVars I will set the text property to the blank string to release the memory used by the strings. -- Frank Church === http://devblog.brahmancreations.com ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-pascal
RE : [fpc-pascal] How are Assigned, Free, Nil and Destroy related?
Nil is not a routine, it is a value, it means that the object is empty, it does not exist / is not allocated. Nil in existing implementations that I know is represented by the value zero. The typical life-cycle of a object is: MyObject := TMyObject.Create; try MyObject.DoSomething(); finally MyObject.Free; end; One pitfall: the variable MyObject before MyObject := TMyObject.Create; is undefined and not necessarily nil. Variables are not initialized by default and can contain anything. In general, MyObject.Free does not set MyObject to nil neither. Good practice is to initialize pointer variables to nil and resetting them to nil after freeing them whenever assigned() or nil is going to be used. Ludo ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-pascal
RE : [fpc-pascal] How are Assigned, Free, Nil and Destroy related?
When the loop runs again Assigned in InitVars is false so as soon as those FBreakStrings and SCStrings are accessed within the loop a SIGSEGV occurs. So what I want to know is whether Assigned remains true when Free is executed. See my previous answer. There is a helper function procedure FreeAndNil(var obj); that calls obj.free and sets obj to nil. So instead of SCStrings.Free; SCStrings:=nil; call FreeAndNil(SCStrings); Ludo ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Re: RE : [fpc-pascal] How are Assigned, Free, Nil and Destroy related?
On 22 October 2011 08:14, Ludo Brands ludo.bra...@free.fr wrote: Nil is not a routine, it is a value, it means that the object is empty, it does not exist / is not allocated. Nil in existing implementations that I know is represented by the value zero. The typical life-cycle of a object is: MyObject := TMyObject.Create; try MyObject.DoSomething(); finally MyObject.Free; end; One pitfall: the variable MyObject before MyObject := TMyObject.Create; is undefined and not necessarily nil. Variables are not initialized by default and can contain anything. In general, MyObject.Free does not set MyObject to nil neither. Good practice is to initialize pointer variables to nil and resetting them to nil after freeing them whenever assigned() or nil is going to be used. Does that mean that Free itself reclaims the memory used by the object's fields and properties but does not release the memory used by the TObject or pointer itself, where as setting it to nil or executing Destroy does, or does Destroy do something different? Ludo ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-pascal -- Frank Church === http://devblog.brahmancreations.com ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] How are Assigned, Free, Nil and Destroy related?
Hello, Instead of .Free in your FreeVars routine, you should use FreeAndNil( theobject). The correct lifecycle for class objects is : var anObject : TMyObject; begin anObject := nil; //not needed for class attributes. Required for local function or global unit variables. anObject := TMyObject.Create( params) //if an exception is raised here, the anObject reference will still be nill. try //... do some code on anObject... finally FreeAndNil( anObject); //after this, the memory referenced by anObject is freed, and the reference anObject is set to nil. end; end; Hope this helps, Thierry - Mail Original - De: Frank Church vfcli...@gmail.com À: FPC-Pascal users discussions fpc-pascal@lists.freepascal.org Envoyé: Samedi 22 Octobre 2011 09h08:17 GMT +01:00 Amsterdam / Berlin / Berne / Rome / Stockholm / Vienne Objet: Re: [fpc-pascal] How are Assigned, Free, Nil and Destroy related? On 22 October 2011 07:20, Felipe Monteiro de Carvalho felipemonteiro.carva...@gmail.com wrote: I understand Assigned as being the same as nil, so Assigned(Object) = Object nil I vaguely remember that it could be safer in some corner case, but I don't remember ever meting that. Free is how you release the memory allocated for a object. Free calls Destroy. Never call Destroy manually. When you implement the destructor you always implement Destroy, never change Free. Nil is not a routine, it is a value, it means that the object is empty, it does not exist / is not allocated. Nil in existing implementations that I know is represented by the value zero. The typical life-cycle of a object is: MyObject := TMyObject.Create; try MyObject.DoSomething(); finally MyObject.Free; end; To implement this object you should implement Create, DoSomething and Destroy. -- Felipe Monteiro de Carvalho ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-pascal This code is the source of my woes. SCStrings and FBreakStrings are part of an object. They are repeatedly used in a loop and I need to free the memory after the loop runs or free the space taken up by their strings type TRuntimeMonitor = class(TThread) private Frequency: Integer; IniFile: TMemIniFile; SCStrings: TStringList; FBreakStrings: TStringList; procedure DispatchOutput; procedure DisplayRawOutput; protected procedure Execute; override; public constructor Create(CreateSuspended: Boolean); end; procedure InitVars; begin if not Assigned(SCStrings) then SCStrings := TStringList.Create; if not Assigned(FBreakStrings) then FBreakStrings := TStringList.Create; IniFile := TMemIniFile.Create('zxtyu'); end; procedure FreeVars; begin IniFile.Free; if Assigned(SCStrings) then SCStrings.Free; if Assigned(FBreakStrings) then FBreakStrings.Free; if Assigned(FBreakStrings) then debugln('FBreakStrings is still assigned'); end; InitVars and FreeVars run in the Execute procedure of the thread When the loop runs again Assigned in InitVars is false so as soon as those FBreakStrings and SCStrings are accessed within the loop a SIGSEGV occurs. So what I want to know is whether Assigned remains true when Free is executed. In the mean time instead of using Free in FreeVars I will set the text property to the blank string to release the memory used by the strings. -- Frank Church === http://devblog.brahmancreations.com ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-pascal ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-pascal
RE : RE : [fpc-pascal] How are Assigned, Free, Nil and Destroy related?
Does that mean that Free itself reclaims the memory used by the object's fields and properties but does not release the memory used by the TObject or pointer itself, where as setting it to nil or executing Destroy does, or does Destroy do something different? All memory is released including TObject but the variable pointing to the TObject (fe: SCStrings) isn't set to nil. It still points to where the TObject was. Warning: setting a TObject variable to nil does not free the object unless it is reference counted! Strings and COM style interfaces are reference counted. Pascal is not VB. Ludo ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Re: RE : [fpc-pascal] How are Assigned, Free, Nil and Destroy related?
On Sat, Oct 22, 2011 at 9:36 AM, Frank Church vfcli...@gmail.com wrote: Does that mean that Free itself reclaims the memory used by the object's fields and properties but does not release the memory used by the TObject or pointer itself, where as setting it to nil or executing Destroy does, or does Destroy do something different? No, you got parts of it wrong: *Free calls Destroy which releases the memory of the object itself. *Nothing releases the memory of the pointer to the object. You don't want to release the 4 or 8 bytes of the pointer. If you did release it, then your application would crash when trying to read the pointer to check if it is nil. *Destroy implements releasing the memory of the object. Free calls Destroy. *Setting the object to nil does just that. It changes the pointer to the object to have the value nil (zero). It does not release the pointer. -- Felipe Monteiro de Carvalho ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] Delphi's anonymous functions in Free Pascal
2011/10/22 Gregory M. Turner g...@malth.us Taking these terms in the broadest sense possible, wouldn't we say that OOP is mostly a functional development paradigm? Not a rhetorical question, I seriously am not sure. OP's somewhat idiosyncratic requirement to put all the OOP metadata in a separate interface section of your code kind of underlines what I'm talking about. It seems to me that in OOP, whatever we might happen to do procedurally, there's a strong declarative odor to everything happening at the class/interface level. Now you are mixing the well-established terms. Functional programming paradigm is based on lambda calculus. There are no loop constructs or even variables in normal sense. There are only functions which return a value without side-effects. In Object Pascal you must define types in interface, but it doesn't change the object oriented paradigm anyhow. In Java or C# you don't have interface definitions but they still have the same paradigm. Wikipedia has amazingly much info. See: http://en.wikipedia.org/wiki/Functional_programming On the right edge there is a list Programming Paradigms. Regards, Juha ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] How are Assigned, Free, Nil and Destroy related?
Felipe Monteiro de Carvalho wrote: Free is how you release the memory allocated for a object. Free calls Destroy. Never call Destroy manually. When you implement the destructor you always implement Destroy, never change Free. A number of years ago, Matthew Jones's wife looked over his shoulder and caught him using Create and Destroy. Bit violent, isn't it? When he told the story somebody else pointed out that he should be using Create and Free, I find this anecdote makes it easy to remember. Nil is not a routine, it is a value, it means that the object is empty, it does not exist / is not allocated. Nil in existing implementations that I know is represented by the value zero. I've once seen a compiler using a non-zero value, I think it was the first Logitech protected-mode Modula-2 and it used :. Apart from that I think that C specifies that nil has a bit pattern of all zeros, and anything with even the slightest interest in compatibility sticks to this as a convention. -- Mark Morgan Lloyd markMLl .AT. telemetry.co .DOT. uk [Opinions above are the author's, not those of his employers or colleagues] ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] How are Assigned, Free, Nil and Destroy related?
In our previous episode, Felipe Monteiro de Carvalho said: Nil is not a routine, it is a value, it means that the object is empty, it does not exist / is not allocated. Nil in existing implementations that I know is represented by the value zero. Look better in, euh, Free Pascal, and see what is assigned in this case:-) type t = procedure (a,b:integer) of object; var x : t; begin x:=nil; end. nil is not always zero. Sometimes it is double zero :-) ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-pascal
[fpc-pascal] How to insert a record and get the primary key with sqldb?
Hello, Yet another chapter of my database problems =) Ok, now I want to insert a record in my table and I would like to obtain the auto-generated PrimaryKey I tryed a number of options: SQLGameSession.Insert(); SQLGameSession.Edit; SQLGameSession.FieldByName('GameEvent').AsInteger := lGameEventId; SQLGameSession.Post; This one just failed silently. Nothing was added to the database, no idea why. I had done a SELECT * FROM WHERE which selected nothing. Should I instead make a full selection of the table? Isn't that very inneficient for just inserting 1 record? (My app is already very slow in the database connection as my profiling shows) And another attempt: DBComm.SQLTransaction.StartTransaction; -- Fails here with transaction already active SQLText := Format('INSERT INTO GameSession (GameEvent, TableId) values (%d, %d);', [lGameEventId, ARequest.GameId]); DBComm.PQConnection.ExecuteDirect(SQLText); DBComm.SQLTransaction.Commit; Not to mention that in this second way I would have no idea how to obtain the primary key... any suggestions welcome. thanks, -- Felipe Monteiro de Carvalho ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-pascal
[fpc-pascal] Re: How to insert a record and get the primary key with sqldb?
Hello, Ok, searching some more I see that select scope_identity() could return the generated primary key. But how to get the value? DBComm.PQConnection.ExecuteDirect(SQLText); The method above has no return value =( -- Felipe Monteiro de Carvalho ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] How to insert a record and get the primary key with sqldb?
On Sat, 22 Oct 2011, Felipe Monteiro de Carvalho wrote: Hello, Yet another chapter of my database problems =) Ok, now I want to insert a record in my table and I would like to obtain the auto-generated PrimaryKey I tryed a number of options: SQLGameSession.Insert(); SQLGameSession.Edit; Remove this call. Edit must be called to edit an existing record. SQLGameSession.FieldByName('GameEvent').AsInteger := lGameEventId; SQLGameSession.Post; You should add ApplyUpdates. Post posts the changes in the internal memory buffer; Nothing is saved to the database untill you call ApplyUpdates. This one just failed silently. Nothing was added to the database, no idea why. I had done a SELECT * FROM WHERE which selected nothing. Should I instead make a full selection of the table? Isn't that very inneficient for just inserting 1 record? (My app is already very slow in the database connection as my profiling shows) And another attempt: DBComm.SQLTransaction.StartTransaction; -- Fails here with transaction already active Correct. The default transaction is made active after connecting. You should call StartTransaction on this transaction only after a commit or rollback. SQLText := Format('INSERT INTO GameSession (GameEvent, TableId) values (%d, %d);', [lGameEventId, ARequest.GameId]); DBComm.PQConnection.ExecuteDirect(SQLText); DBComm.SQLTransaction.Commit; It's not recommended to use ExecuteDirect. Instead do a With TSQLQuery.Create(Self) Do try Database:=MyDatabase; Transaction:=MyDatabase.SQLTransaction; SQL.Text:='INSERT INTO GameSession (GameEvent, TableId) values (:EventID, :GameId);'; ParamByName('GameEvent).AsInteger:=lGameEventId; ParamByName('GameID').AsInteger:=ARequest.GameId; ExecSQL; (Transaction as TSQLTransaction).Commit; finally Free; end; The use of parameters is recommended, it avoids SQL injection. Not to mention that in this second way I would have no idea how to obtain the primary key... By reading the just created record, see my reply from yesterday. If the table uses a sequence, first get the new sequence value, and then do the insert with the generated value. Didn't you get a copy of the Lazarus book ? There is a whole chapter on database programming with Lazarus. All the above is explained there. Michael. ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] How to insert a record and get the primary key with sqldb?
In our previous episode, Felipe Monteiro de Carvalho said: Ok, now I want to insert a record in my table and I would like to obtain the auto-generated PrimaryKey This is a classic problem, since SQL simply doesn't support this. So all DBs do something else, for postgresql there are sequence objects that can be queried, while other allow to return the id of the autogenerated fields. Afaik sqldb does not abstract this yet. ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] How to insert a record and get the primary key with sqldb?
On Sat, 22 Oct 2011, Marco van de Voort wrote: In our previous episode, Felipe Monteiro de Carvalho said: Ok, now I want to insert a record in my table and I would like to obtain the auto-generated PrimaryKey This is a classic problem, since SQL simply doesn't support this. So all DBs do something else, for postgresql there are sequence objects that can be queried, while other allow to return the id of the autogenerated fields. Afaik sqldb does not abstract this yet. That's because it can't be abstracted correctly. There are 2 incompatible mechanisms. 1. autogenerated fields (mysql, MS SQL server) which must be retrieved after the insert using a special API. 2. or sequences, which must be generated manually before the insert (DB2, Oracle, Firebird) using a special API, but which may or may not be generated in an AFTER INSERT trigger. In which case it's impossible to retrieve the sequence value after the insert except by re-reading the record. I don't know which mechanism postgresql follows. Michael. ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] Re: How to insert a record and get the primary key with sqldb?
On Sat, 22 Oct 2011, Felipe Monteiro de Carvalho wrote: Hello, Ok, searching some more I see that select scope_identity() could return the generated primary key. But how to get the value? DBComm.PQConnection.ExecuteDirect(SQLText); The method above has no return value =( Use a TSQLQuery with SQL select scope_identity() as theid and read field 0. I repeat, do not use ExecuteDirect. Michael.___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] Re: How to insert a record and get the primary key with sqldb?
Ok, searching some more I see that select scope_identity() could return the generated primary key. But how to get the value? Better use the RETURNING* clause** as it clearly state the column value you are expecting; The scope_identity() may be a source of subtle bugs that are difficult to resolve, for example : what if the table make use of two sequences (yes sometime this is needed) what if the table's insert trigger generates a insert query(or stored procedure) into another table which make use of sequence (*) http://www.postgresql.org/docs/8.3/interactive/sql-insert.html (**) this clause is at least supported by Firebird, MS SQL SERVER, ORACLE -- Inoussa O. ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] How to insert a record and get the primary key with sqldb?
On Saturday 22 October 2011 15.21:40 Marco van de Voort wrote: In our previous episode, Felipe Monteiro de Carvalho said: Ok, now I want to insert a record in my table and I would like to obtain the auto-generated PrimaryKey This is a classic problem, since SQL simply doesn't support this. So all DBs do something else, for postgresql there are sequence objects that can be queried, while other allow to return the id of the autogenerated fields. Afaik sqldb does not abstract this yet. MSEgui updates inserted primary key fields automatically for MySQL and SQLite3 by lastinsertid. IIRC sqldb does the same? For database which support the returning clause tmse*field.providerflags1 pf1_refreshinsert and pf1_refreshupdate can be used, this works for all fields. Martin ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] How to insert a record and get the primary key with sqldb?
On Sat, 22 Oct 2011, Martin Schreiber wrote: On Saturday 22 October 2011 15.21:40 Marco van de Voort wrote: In our previous episode, Felipe Monteiro de Carvalho said: Ok, now I want to insert a record in my table and I would like to obtain the auto-generated PrimaryKey This is a classic problem, since SQL simply doesn't support this. So all DBs do something else, for postgresql there are sequence objects that can be queried, while other allow to return the id of the autogenerated fields. Afaik sqldb does not abstract this yet. MSEgui updates inserted primary key fields automatically for MySQL and SQLite3 by lastinsertid. IIRC sqldb does the same? Not to my knowledge. It stores the lastinsertid in the cursor, but this is not made available to the programmer. For database which support the returning clause tmse*field.providerflags1 pf1_refreshinsert and pf1_refreshupdate can be used, this works for all fields. Hardly an abstraction, it's just some automatisms :-) But good to know. We should really overhaul sqldb and add some of the MSEgui features. Thanks, Martin. Michael. ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] How to insert a record and get the primary key with sqldb?
On Sat, Oct 22, 2011 at 3:33 PM, michael.vancann...@wisa.be wrote: 2. or sequences, which must be generated manually before the insert (DB2, Oracle, Firebird) using a special API, but which may or may not be generated in an AFTER INSERT trigger. In which case it's impossible to retrieve the sequence value after the insert except by re-reading the record. Indeed, it looks like that Postgres uses this second method, because I did this: SQLText:='INSERT INTO GameSession (GameEvent, TableId) values (:GameEventParam, :TableIdParam);'; SQLGameSession.SQL.Text := SQLText; SQLGameSession.Params.ParamByName('GameEventParam').AsInteger:=lGameEventId; SQLGameSession.Params.ParamByName('TableIdParam').AsInteger:=ARequest.GameId; SQLGameSession.ExecSQL; DBComm.SQLTransaction.Commit; SQLGameSession.Active := True; And I get a message saying that my value for SessionId is missing ... but I thought it would be auto-generated, because I created my table like this: CREATE TABLE GameSession ( SessionId bigint NOT NULL, GameEvent bigint NOT NULL, TableId bigint NOT NULL ); ALTER TABLE public.GameSession OWNER TO postgres; CREATE SEQUENCE GameSession_SessionId_seq START WITH 1 INCREMENT BY 1 NO MAXVALUE NO MINVALUE CACHE 1; ALTER TABLE public.GameSession_SessionId_seq OWNER TO postgres; ALTER SEQUENCE GameSession_SessionId_seq OWNED BY GameSession.SessionId; -- Not sure what this does -- SELECT pg_catalog.setval('GameEvent_Id_seq', 1, true); ALTER TABLE ONLY GameSession ADD CONSTRAINT GameSession_pkey PRIMARY KEY (SessionId); Note that I did not invest this stuff ... I just copied from stuff to create other tables which were already in the project. -- Felipe Monteiro de Carvalho ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] How to insert a record and get the primary key with sqldb?
On Sat, 22 Oct 2011, Felipe Monteiro de Carvalho wrote: On Sat, Oct 22, 2011 at 3:33 PM, michael.vancann...@wisa.be wrote: 2. or sequences, which must be generated manually before the insert (DB2, Oracle, Firebird) using a special API, but which may or may not be generated in an AFTER INSERT trigger. In which case it's impossible to retrieve the sequence value after the insert except by re-reading the record. Indeed, it looks like that Postgres uses this second method, because I did this: SQLText:='INSERT INTO GameSession (GameEvent, TableId) values (:GameEventParam, :TableIdParam);'; SQLGameSession.SQL.Text := SQLText; SQLGameSession.Params.ParamByName('GameEventParam').AsInteger:=lGameEventId; SQLGameSession.Params.ParamByName('TableIdParam').AsInteger:=ARequest.GameId; SQLGameSession.ExecSQL; DBComm.SQLTransaction.Commit; SQLGameSession.Active := True; And I get a message saying that my value for SessionId is missing ... but I thought it would be auto-generated, because I created my table like this: CREATE TABLE GameSession ( SessionId bigint NOT NULL, GameEvent bigint NOT NULL, TableId bigint NOT NULL ); ALTER TABLE public.GameSession OWNER TO postgres; CREATE SEQUENCE GameSession_SessionId_seq START WITH 1 INCREMENT BY 1 NO MAXVALUE NO MINVALUE CACHE 1; ALTER TABLE public.GameSession_SessionId_seq OWNER TO postgres; ALTER SEQUENCE GameSession_SessionId_seq OWNED BY GameSession.SessionId; -- Not sure what this does -- SELECT pg_catalog.setval('GameEvent_Id_seq', 1, true); Sets the initial value of the sequence. ALTER TABLE ONLY GameSession ADD CONSTRAINT GameSession_pkey PRIMARY KEY (SessionId); Note that I did not invest this stuff ... I just copied from stuff to create other tables which were already in the project. You must get a value first, and pass it along to the insert statement. Auto-generation is not possible, since you don't have any link between the sequence and your table. (normally, this is done in the trigger). Michael. ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] How to insert a record and get the primary key with sqldb?
In our previous episode, michael.vancann...@wisa.be said: Ok, now I want to insert a record in my table and I would like to obtain the auto-generated PrimaryKey This is a classic problem, since SQL simply doesn't support this. So all DBs do something else, for postgresql there are sequence objects that can be queried, while other allow to return the id of the autogenerated fields. Afaik sqldb does not abstract this yet. That's because it can't be abstracted correctly. There are 2 incompatible mechanisms. 1. autogenerated fields (mysql, MS SQL server) which must be retrieved after the insert using a special API. 2. or sequences, which must be generated manually before the insert (DB2, Oracle, Firebird) using a special API, but which may or may not be generated in an AFTER INSERT trigger. In which case it's impossible to retrieve the sequence value after the insert except by re-reading the record. I don't know which mechanism postgresql follows. A combination. Autogenerated, but the API call that the value must be obtained from is basically the sequence object. (which also has different operations). Afaik Zeos manages to abstract this for all these dbs by having a sequence object. ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] How to insert a record and get the primary key with sqldb?
On Saturday 22 October 2011 16.20:13 Michael Van Canneyt wrote: Note that I did not invest this stuff ... I just copied from stuff to create other tables which were already in the project. You must get a value first, and pass it along to the insert statement. Auto-generation is not possible, since you don't have any link between the sequence and your table. (normally, this is done in the trigger). BTW, MSEgui has tsequencelink which fetches a sequence value and stores it in the field by posting a inserted record automatically. Works for Firebird and Postgres. Martin ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] How to insert a record and get the primary key with sqldb?
On Sat, 22 Oct 2011, Marco van de Voort wrote: In our previous episode, michael.vancann...@wisa.be said: Ok, now I want to insert a record in my table and I would like to obtain the auto-generated PrimaryKey This is a classic problem, since SQL simply doesn't support this. So all DBs do something else, for postgresql there are sequence objects that can be queried, while other allow to return the id of the autogenerated fields. Afaik sqldb does not abstract this yet. That's because it can't be abstracted correctly. There are 2 incompatible mechanisms. 1. autogenerated fields (mysql, MS SQL server) which must be retrieved after the insert using a special API. 2. or sequences, which must be generated manually before the insert (DB2, Oracle, Firebird) using a special API, but which may or may not be generated in an AFTER INSERT trigger. In which case it's impossible to retrieve the sequence value after the insert except by re-reading the record. I don't know which mechanism postgresql follows. A combination. Autogenerated, but the API call that the value must be obtained from is basically the sequence object. (which also has different operations). Afaik Zeos manages to abstract this for all these dbs by having a sequence object. I fail to see how it can do that. E.g. the mechanism by Martin is just a trick to update a field value after an insert/update. That's a fine/useful mechanism, but not what I'd call 'abstracting'. But never mind. I think the trick is useful, and we should look into getting it in SQLDB. Michael. ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] How to insert a record and get the primary key with sqldb?
On Sat, 22 Oct 2011, Martin Schreiber wrote: On Saturday 22 October 2011 16.20:13 Michael Van Canneyt wrote: Note that I did not invest this stuff ... I just copied from stuff to create other tables which were already in the project. You must get a value first, and pass it along to the insert statement. Auto-generation is not possible, since you don't have any link between the sequence and your table. (normally, this is done in the trigger). BTW, MSEgui has tsequencelink which fetches a sequence value and stores it in the field by posting a inserted record automatically. Works for Firebird and Postgres. Indeed. IBX has a similar feature. One more for the TODO list. Michael. ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-pascal
RE : [fpc-pascal] How to insert a record and get the primary key withsqldb?
Afaik Zeos manages to abstract this for all these dbs by having a sequence object. I fail to see how it can do that. E.g. the mechanism by Martin is just a trick to update a field value after an insert/update. That's a fine/useful mechanism, but not what I'd call 'abstracting'. But never mind. I think the trick is useful, and we should look into getting it in SQLDB. Zeos TZSequence is only supported for Oracle, IB and PostGreSql, ie. the databases using sequences. AFAIK, the use of TZSequence is also mutually exclusive with a trigger that uses that sequence. When using a trigger the RETURNING clause is the solution to use. A very limited abstraction... Ludo ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] How to insert a record and get the primary key with sqldb?
On Sat, Oct 22, 2011 at 11:21 AM, michael.vancann...@wisa.be wrote: DBComm.SQLTransaction.StartTransaction; -- Fails here with transaction already active Correct. The default transaction is made active after connecting. You should call StartTransaction on this transaction only after a commit or rollback. I also found this problem when I migrated from Zeos to SQLdb. Only SQLdb works in this way. IMHO, it not make sense. For automatic transactions, the user can define AutoCommit=True If it is False, I can call StartTransaction BEFORE the Commit. That is the way that all libs work. Marcos Douglas ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] Re: How to insert a record and get the primary key with sqldb?
On Sat, Oct 22, 2011 at 11:35 AM, Inoussa OUEDRAOGO inouss...@gmail.com wrote: Ok, searching some more I see that select scope_identity() could return the generated primary key. But how to get the value? Better use the RETURNING* clause** as it clearly state the column value you are expecting; The scope_identity() may be a source of subtle bugs that are difficult to resolve, for example : what if the table make use of two sequences (yes sometime this is needed) what if the table's insert trigger generates a insert query(or stored procedure) into another table which make use of sequence (*) http://www.postgresql.org/docs/8.3/interactive/sql-insert.html (**) this clause is at least supported by Firebird, MS SQL SERVER, ORACLE Talking about MSSQL Server, the scope_identity() return the ID inside the scope, ie, return the ID from your INSERT instruction, ignoring Triggers, for example. If you use @@IDENTITY then you get the last ID inserted, ie, if you have triggers you do not know which ID belongs which table. Marcos Douglas ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] Re: How to insert a record and get the primary key with sqldb?
ugh, any ideas how I can obtain the next sequence value using sqldb and postgres then? I have never used sequence values before, and while I am googling I only found either answers which are specific for a particular framework (java, djambo, whatever) or people claiming that it should generate the index automatically! o.O Which clearly it is not doing... I couldn't yet get a generic answer using SQL supported by Postgres, or whatever thing which I could reuse in sqldb. thanks, -- Felipe Monteiro de Carvalho -- Felipe Monteiro de Carvalho ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] Re: How to insert a record and get the primary key with sqldb?
On Sat, Oct 22, 2011 at 1:33 PM, Felipe Monteiro de Carvalho felipemonteiro.carva...@gmail.com wrote: ugh, any ideas how I can obtain the next sequence value using sqldb and postgres then? I have never used sequence values before, and while I am googling I only found either answers which are specific for a particular framework (java, djambo, whatever) or people claiming that it should generate the index automatically! o.O Which clearly it is not doing... I couldn't yet get a generic answer using SQL supported by Postgres, or whatever thing which I could reuse in sqldb. You can use: - Stored Procedures (SP): one for each table; - Dynamic SP: pass the generic SQL to the SP and return the scope_identity(); - GUID: Use a column to save a GUID. The real ID can be autoincrement but you do not need it. You can found the register using the GUID. Marcos Douglas ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] Re: How to insert a record and get the primary key with sqldb?
On Sat, 22 Oct 2011, Felipe Monteiro de Carvalho wrote: ugh, any ideas how I can obtain the next sequence value using sqldb and postgres then? I have never used sequence values before, and while I am googling I only found either answers which are specific for a particular framework (java, djambo, whatever) or people claiming that it should generate the index automatically! o.O Which clearly it is not doing... I couldn't yet get a generic answer using SQL supported by Postgres, or whatever thing which I could reuse in sqldb. Just a use a TSQLQuery: With TSQLQuery.Create(Self) do try Database:=MyDatabase; Transaction:=MyTransaction; // Replace sequencename with the correct name of the sequence SQL.Text:='SELECT nextval(''sequencename'')'; Open; TheNewID:=(Fields[0] as TLargeIntField).AsLargeInt; close; finally free; end; That's it. Michael. ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Re: RE : [fpc-pascal] How to insert a record and get the primary key withsqldb?
On Sat, 22 Oct 2011, Ludo Brands wrote: Afaik Zeos manages to abstract this for all these dbs by having a sequence object. I fail to see how it can do that. E.g. the mechanism by Martin is just a trick to update a field value after an insert/update. That's a fine/useful mechanism, but not what I'd call 'abstracting'. But never mind. I think the trick is useful, and we should look into getting it in SQLDB. Zeos TZSequence is only supported for Oracle, IB and PostGreSql, ie. the databases using sequences. AFAIK, the use of TZSequence is also mutually exclusive with a trigger that uses that sequence. When using a trigger the RETURNING clause is the solution to use. A very limited abstraction... ... And mainly the reason I think it is not abstractable... :-) Michael. ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] How to insert a record and get the primary key with sqldb?
On Saturday 22 October 2011 17.23:38 Marcos Douglas wrote: On Sat, Oct 22, 2011 at 11:21 AM, michael.vancann...@wisa.be wrote: DBComm.SQLTransaction.StartTransaction; -- Fails here with transaction already active Correct. The default transaction is made active after connecting. You should call StartTransaction on this transaction only after a commit or rollback. I also found this problem when I migrated from Zeos to SQLdb. Only SQLdb works in this way. IMHO, it not make sense. For automatic transactions, the user can define AutoCommit=True If it is False, I can call StartTransaction BEFORE the Commit. That is the way that all libs work. That means there are different transactions for reading and writing? MSEgui has this option too. But what if reading and writing should be in a single transaction? Martin ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] How to insert a record and get the primary key with sqldb?
On Sat, Oct 22, 2011 at 1:53 PM, Martin Schreiber mse00...@gmail.com wrote: On Saturday 22 October 2011 17.23:38 Marcos Douglas wrote: On Sat, Oct 22, 2011 at 11:21 AM, michael.vancann...@wisa.be wrote: DBComm.SQLTransaction.StartTransaction; -- Fails here with transaction already active Correct. The default transaction is made active after connecting. You should call StartTransaction on this transaction only after a commit or rollback. I also found this problem when I migrated from Zeos to SQLdb. Only SQLdb works in this way. IMHO, it not make sense. For automatic transactions, the user can define AutoCommit=True If it is False, I can call StartTransaction BEFORE the Commit. That is the way that all libs work. That means there are different transactions for reading and writing? MSEgui has this option too. But what if reading and writing should be in a single transaction? I'm talking about transactions for writing. Marcos Douglas ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] Re: How to insert a record and get the primary key with sqldb?
On Saturday 22 October 2011 17.33:11 Felipe Monteiro de Carvalho wrote: ugh, any ideas how I can obtain the next sequence value using sqldb and postgres then? I have never used sequence values before, and while I am googling I only found either answers which are specific for a particular framework (java, djambo, whatever) or people claiming that it should generate the index automatically! o.O Which clearly it is not doing... I couldn't yet get a generic answer using SQL supported by Postgres, or whatever thing which I could reuse in sqldb. thanks, Postgres documenatation is here: http://www.postgresql.org/docs/manuals/ http://www.postgresql.org/docs/8.3/static/functions-sequence.html MSEgui calls getsqlresult() with the statement function tmsepqconnection.readsequence(const sequencename: string): string; begin result:= 'select nextval(''' +sequencename+''') as res;'; end; returns. Instead of the MSEgui getsqlresult() function use a tsqlquery in sqldb. Martin ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Re: RE : [fpc-pascal] How to insert a record and get the primary key withsqldb?
Ok, thanks a lot =) On 10/22/11, Michael Van Canneyt mich...@freepascal.org wrote: ... And mainly the reason I think it is not abstractable... :-) In this case I would suggest to abstract it like this: // ASequenceName - The name of the sequence for usage in Postgres, etc. Ignored for MSSQL, etc. // ARecordValues - The values of the fields, all should be placed in the sequence in which they exist in the table columns. nil is accepted. // Returns the index to the primary key TSQLQuery.InsertNewRecordWithAutoGeneratedPrimaryKey(ASequenceName: string; ARecordValues: array of const): Integer; Then it will ... insert a new record with the record values that you provided and give back the primary key for it. At least that's how I would expect it =D For each database it would simply figure out if it needs to get the sequence number or if it will auto-generate or whatever. -- Felipe Monteiro de Carvalho ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] How to insert a record and get the primary key with sqldb?
On 22/10/2011, Felipe Monteiro de Carvalho wrote: Yet another chapter of my database problems =) As this message thread proves, there are many issues with Auto-inc field, so simply DON'T USE THEM! You have many alternatives, which will save you LOTS of grey hairs. Auto-Inc field are just evil, no matter which RDBMS you use. 1) Use a GUID created at the time you do the Insert. This also means you can do Master/Detail records with no problems at all. 2) If you must use an Integer as a primary key, then simply implement the Ambler High/Low method. Google will give you more information, but in a nutshell it works as follows: You have a next_id table in the database. When you application starts it reads the last used value, books out say the next 10 numbers, and update the Next_ID table. This now means you can insert 10 new records without needing to revisit the Next_ID table, and nobody else will get those 10 numbers. Here is an example implementation as done in tiOPF2 http://tiopf.svn.sourceforge.net/viewvc/tiopf/tiOPF2/Trunk/Options/tiOIDInteger.pas?revision=2087view=markup Hope this helps a bit. -- Regards, - Graeme - ___ fpGUI - a cross-platform Free Pascal GUI toolkit http://fpgui.sourceforge.net ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-pascal
[fpc-pascal] Indy 10 HTTP Server component with FPC
Hi, Is anybody here using the Indy 10 components with FPC? More specifically, the HTTP Server component. My project compiles fine, but when I activate the HTTP Server I get the following error. Socket error # 98. Address already in use. I know that under Linux, if you use a port 1024 you must have root access, so I even tried with port 8080, but no matter what port I use, or even if I execute my app with root privileges, I always get the same error. I downloaded a daily snapshot archive of Indy 10 from their repository a few days ago. I have no idea what revision or version number it is. -- Regards, - Graeme - ___ fpGUI - a cross-platform Free Pascal GUI toolkit http://fpgui.sourceforge.net ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] Indy 10 HTTP Server component with FPC
In our previous episode, Graeme Geldenhuys said: Is anybody here using the Indy 10 components with FPC? More specifically, the HTTP Server component. My project compiles fine, but when I activate the HTTP Server I get the following error. Socket error # 98. Address already in use. I know that under Linux, if you use a port 1024 you must have root access, so I even tried with port 8080, but no matter what port I use, or even if I execute my app with root privileges, I always get the same error. I downloaded a daily snapshot archive of Indy 10 from their repository a few days ago. I have no idea what revision or version number it is. I haven't tried for years, but I can remember some strange problems designtime that went away if you manually added a tidbinding in formcreate. ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-pascal
RE : [fpc-pascal] Re: How to insert a record and get the primary keywith sqldb?
Error: bPreparation of query failed. (PostgreSQL: ERROR: column GameSession_SessionId_seq does not exist LINE 1: prepare prepst2 as SELECT nextval(GameSession_SessionId_se... SQLGameSession.SQL.Text:='SELECT nextval(GameSession_SessionId_seq) as res;'; Nextval takes a regclass as parameter, not an identifier (column). So, use single quotes: SELECT nextval('GameSession_SessionId_seq') as res; Ludo ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Re: RE : [fpc-pascal] Re: How to insert a record and get the primary keywith sqldb?
On Sat, Oct 22, 2011 at 9:38 PM, Ludo Brands ludo.bra...@free.fr wrote: Nextval takes a regclass as parameter, not an identifier (column). So, use single quotes: SELECT nextval('GameSession_SessionId_seq') as res; But Postgres requires double quotes or else it will lowercase the entire identifier and it won't match. It seams that it moves forward if I use both types of quotes! Like this: OPDebugLn('[TGameSessionComm.CreateSessionResponse] Obtaining New Primary Key'); SQLGameSession.SQL.Text:='SELECT nextval(''GameSession_SessionId_seq'') as res;'; SQLGameSession.Open; FSessionId := (SQLGameSession.Fields[0] as TLargeIntField).AsLargeInt; SQLGameSession.Close; But now I get a new error Cannot open a non-select statement o.O Regardless of the final as res; being there or not. -- Felipe Monteiro de Carvalho ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] Indy 10 HTTP Server component with FPC
On 22/10/2011, Marco van de Voort wrote: I haven't tried for years, but I can remember some strange problems designtime that went away if you manually added a tidbinding in formcreate. I'm not using design-time usage at all, everything is done manually via code. I'm creating a TIdHTTPServer instance via code, set the port, one basic event handler, and then when I try to set Active = True, that's when the error pops up. I'll try and debug it some more - hopefully it is something small. If not, I'll have to do some Adapter Pattern magic in tiOPF to get n-tier support going. I used Indy components years ago in Delphi 7, and remember they were quite good. It would be a pity if FPC developers couldn't benefit from them too. I believe you helped them with FPC support some years back moving from Kylix's libc unit to FPC's baseunix. I think I read this somewhere. Anyway, back to debugging Indy some more then. -- Regards, - Graeme - ___ fpGUI - a cross-platform Free Pascal GUI toolkit http://fpgui.sourceforge.net ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] Indy 10 HTTP Server component with FPC
In our previous episode, Graeme Geldenhuys said: designtime that went away if you manually added a tidbinding in formcreate. I'm not using design-time usage at all, everything is done manually via code. I'm creating a TIdHTTPServer instance via code, set the port, one basic event handler, and then when I try to set Active = True, that's when the error pops up. You need to add a tidbinding record to bindings. IIRC that is used to find the interface to bind on. ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-pascal
[fpc-pascal] FPC has multiple HTTP server components
Hi, I was looking through the FCL code and noticed that there seems to be more than one HTTP server component. What is the difference between them, and which one would be the better option as the basis for a HTTP based n-tier application server (for use with tiOPF). I found the recent one Michael van Canneyt committed in fcl-web: fcl-web/src/base/fphttpserver.pp (TFPHttpServer component) I also found one in fcl-net: fcl-net/src/httpsvlt.pp(THTTPServer component) -- Regards, - Graeme - ___ fpGUI - a cross-platform Free Pascal GUI toolkit http://fpgui.sourceforge.net ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-pascal