[fpc-devel] String and UnicodeString and UTF8String
Hi *, In current Delphi is String synonym for base type UnicodeString UTF-16 AFAIU ATM in FPC is String synonym for AnsiString (as in previos versions of Delphi) Are there any plans to change meaning of String type ? (like Delphi to UnicodeString , or UTF8String?) Are there any plans to intorduce implicit conversions between AnsiStrings (ANSI code page) to UTF8Strings (UTF-8 encoded) or something like this ? TIA -Laco. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] String and UnicodeString and UTF8String
AFAIK, in current Delphi (which I don't have) a String is a variable that can contain dynamically coded informations (such as locally coded 8-Bit ANSI, UTF-8, UTF-16, ...) and - of course - know which code it holds. I understand By default, variables declared as type String are *UnicodeString*.**, that String=UnicodeString See: http://docwiki.embarcadero.com/VCL/en/System.UnicodeString and also http://docwiki.embarcadero.com/RADStudio/en/String_Types#UnicodeString Note alse, that AnsiString holds additional informations about character encoding: The AnsiString http://docwiki.embarcadero.com/VCL/en/System.AnsiString structure contains a 32-bit length indicator, a 32-bit reference count, a 16-bit data length indicating the number of bytes per character, and a 16-bit code page. -Laco. If a string is generated by the VCL from a Window API function, the coding will be UTF-16, though, but if you create a string with some other coding it will be automatically re-coded to UTF16 before sending it into a Windows API function. -Michael ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] String and UnicodeString and UTF8String
I think at most two are required for any target: unicodestring (D2009 compatibility), and if really necessary because somehow the unicodestring version causes too much overhead, an ansistring($) version as well. That's only for the classes though, I think most of the base RTL can be simply ansistring($). So if I understand correctly, then UnicodeString and also AnsiString types must be extended that they will hold also information about actual codepage (encoding) of string data they hold. (AFAIK ATM they hold only information about reference count and size and of course data) I am not expert, so I do not understand all aspect/problems which are joined with proper string handling, but some kind of implicit conversions (based on actual encoding of string data) is necessary (ANSI - UTF-8 - UTF-16 - ANSI ... etc.). For example known problem with Euro currency symbol. In Windows is in CurrencyString global variable stored using ANSI codepage, but used in LCL (which expect UTF-8 encoding) without any explicit conversion, what leads to displayng ? instead of € (for example in TDBEdit or TDBGrid) Another problem when displaying character data in data-aware database controls (TDBEdit, TDBGrid). Data-aware controls (LCL) reads data from TField descendatns (FCL) using TField.Text property which returns string (without codepage information is not clear if it is AnsiString or UTF8String or UnicodeString). LCL expect UTF-8 strings, but it is not true in all cases (for example in case of ODBC) -Laco. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] String and UnicodeString and UTF8Stringt
...: the new ansistring type has a hidden element size field (in addition to the reference count, length and codepage), and from what I can see at page 10 of http://edn.embarcadero.com/article/images/38980/Delphi_and_Unicode.pdf, Delphi 2009's unicodestring is simply an ansistring(1200). So it seems, that if we will have any GenericString, with properties reference count, size, character width, codepage, then all other string types can be based on this string type. So other strings will be only any shortcuts, and internaly will use same structure: AnsiString = GenericString(with actual system ANSI code page (0) ... or ... without any explicit codepage ($)) UTF8String = GenericString(with UTF-8 encoding) UnicodeString = GenericString(with UTF-16 encoding) So it seems to me, that there is agreement on adding character width, codepage to internal string record structure and provide conversions where needed, isn't it ? (more or less same approach like in Delphi) Where is not agreement, it is fact what should be default string encoding (AnsiString($) or UTF-8 or UTF-16 or UTF-32) So if I revert to my original question ... is there any agreement on some points related to future of String type ? P.S. I still does not understand, how can things work correctly if LCL expect that all AnsiStrings (String) are UTF8Strings, byt RTL/FCL does not strictly follow this (at least in Windows) ? -Laco. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] String and UnicodeString and UTF8Stringt
Sven Barth wrote / napísal(a): Am 12.01.2011 07:16, schrieb LacaK: P.S. I still does not understand, how can things work correctly if LCL expect that all AnsiStrings (String) are UTF8Strings, byt RTL/FCL does not strictly follow this (at least in Windows) ? LCL uses SysToUTF8 and UTF8ToSys if it uses the RTL (and the FCL). This is often done with wrappers that wrap the RTL method and do the conversion (e.g. FileExistsUTF8, etc.). As I wrote in any of my previous message, AFAIK this is not true in case of fcl-db and Lazarus data-aware components like TDBGrid, TDBEdit ... They use TField.Text: String property to get string conent of field and display them. AFAIU LCL expects, that TField.Text will always return UTF-8 encoded string (because no conversion (SysToUTF8) is done in dbgrids.pas or dbedit.inc) , but this is not true always. So where is error ? 1. Is it wrong expectation by LCL, that TField.Text is always UTF8 string -or- 2. Is it wrong in implementation of TSQLConnectors, which write data into record buffer (of TStringField) and do not convert them always into UTF-8 ? (if data should be always in UTF-8 then it will be good redefine TField.Text property like property Text: UTF8String to be clear, that we always work with UTF-8 strings) -or 3. I missed something ? ;-) -Laco. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] String and UnicodeString and UTF8Stringt
L 2. Is it wrong in implementation of TSQLConnectors, which write data L into record buffer (of TStringField) and do not convert them always into L UTF-8 ? Do you set the CHARSET field in your TSQLConnector to UTF-8 ? not all connectors supports CharSet property. When I look into sources only MySQL and IB support them (SQLite always return UTF-8 encoded ... ODBC, Postgre and Oracle ignore it) Do you define the right code page in each field of your database ? Yes, this is not primary question of database side, but db client library api, which is used by SQLConnector to retrieve data. For example in ODBC we use SQLGetData in LoadField method to retrieve data from odbc interface. And for example in case of MS SQL Server character data are retrieved in current ANSI code page (in Windows of course, may be that for example in *nix data are retrieved in UTF-8 naturaly) . (AFAIK there is no universal way how to explicitly request character encoding from ODBC interface) So it is true, that every sql connector is mandatory write character data in UTF-8 ? or can write in some native format (Ansi, UTF-16) ... but in this case must somewhere write additional info about actual encoding. -Laco. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] Variables declaraction inside code
This was discussed few times here. Later ppl tired from the endless discussions and summarised their ideas on this page: http://wiki.lazarus.freepascal.org/Modernised_Pascal Nice! For me, If I can say is most interested: 1. try ... except ... finally ... end; 2. C style IIF operator: l ? true : false; 3. C style comments: /* ... */ (I have never understood why in Pascal was used (* ... *) ) -Laco. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] String and UnicodeString and UTF8Stringt
Martin Schreiber wrote / napísal(a): On Wednesday, 12. January 2011 09.45:47 LacaK wrote: So where is error ? 1. Is it wrong expectation by LCL, that TField.Text is always UTF8 string -or- 2. Is it wrong in implementation of TSQLConnectors, which write data into record buffer (of TStringField) and do not convert them always into UTF-8 ? (if data should be always in UTF-8 then it will be good redefine TField.Text property like property Text: UTF8String to be clear, that we always work with UTF-8 strings) -or 3. I missed something ? ;-) MSEgui sqldb version converts to UTF-16 from/to system encoding or utf-8 (selectable by option properties) and uses FPC 16bit UnicodeString to store string field values in the dataset, the tmsestringfield returns UnicodeString values. So one can either use utf-8 encoded databaseconnections or connections with the current system encoding. MSEgui uses 16 bit UnicodeString everywhere, the conversion from/to system encoding is done transparently by the FPC unicode/widestring-manager if necessary. This is a solution which works now, no additional complicated and possibly less performant codepage and encoding aware stringtype necessary... Yes, sounds logicaly to me. Then you propose same way for TStringField ? (internaly store as UnicodeString UTF-16 and also TStringField.Text should return UnicodeString instead of String ? ... what will happens in LCL, when visual component will read UTF-16 string, will they be translated into UTF-8 automagicaly?) -Laco. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] String and UnicodeString and UTF8Stringt
L but db client library api, which is used by SQLConnector to L retrieve data. How an UTF8 SQLConnector can retrieve UTF8 data from a field defined as binary ? It cann't . Here I am speaking about TStringField, which is IMHO designed for character data, for binary data is designed TBinaryField L For example in ODBC we use SQLGetData in LoadField L method to retrieve data from odbc interface. And for example in L case of MS SQL Server character data are retrieved in current ANSI L code page (in Windows of course, may be that for example in *nix L data are retrieved in UTF-8 naturaly) . Via ODBC ? L (AFAIK there is no universal way how to explicitly request L character encoding from ODBC interface) But that's a problem of ODBC, but: http://web.datadirect.com/resources/odbc/unicode/unix.html Yes in UNIX world it may be so (I do not know), but in Windows ODBC we have no such possibility AFAIK L So it is true, that every sql connector is mandatory write character L data in UTF-8 ? No. It is mandatory that you send/receive UTF8 to/from GUI LCL elements. As LCL elements are using TStringField.Text property, then this property should return UTF8String, right (not AnsiString in ANSI code page) ? If yes, then also TStringField must store internaly data in any unicode format (to not lose any characters), right ? So it can be UTF-8, UTF-16 or UTF-32 ... in all cases we must allocate space 4*[max.number of characters in field], right ? So in what encoding are string data stored now in TStringField ? -Laco. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] TStringField, String and UnicodeString and UTF8String
Didn't I explain this to you and others a few times? ;-) If so, then please excuse me The database-components itself are encoding-agnostic. This means: encoding in = encoding out. So it is up to the developer what codepage he want to use. So TField.Text can have the encoding _you_ want. So, if you want to work with Lazarus, which uses UTF-8, you have to use UTF-8 encoded strings in your database. So this is answer, which i have looked for: In Lazarus TStringField MUST hold UTF-8 encoded strings. But I guess (I have theory), that in time, when Borland introduced TStringField, the design goal was: TStringField was designed for SBCS (because DataSize=Size+1) string data encoded in system ANSI code page and TWideStringField was designed for DBCS widestring (UTF-16) character data May be, that I was mistaken by this view. (or may be, that there is different approach in Delphi (no agnostic) and different in FPC (agnostic)?) If there is some strange reason why you don't want the strings in your database to be UTF-8 encoded, SQL Server does not support UTF-8 (AFAIK) SQL Server provides non-UNICODE datatypes - char, varchar, text and UNICODE (UCS-2) datatypes - nchar, nvarchar, ntext you have to convert the strings from the encoding your database uses to UTF-8 while reading data from the database. Luckily, you can specify the encoding of strings you want to use for most databases. Not only the encoding in which the strings are stored, but also the encoding which has to be used when you send and retrieve data from the database. And you can set this for each connection made. Ie: you can resolve the problem by changing the connection-string, or by adding some connection-parameter. Yes, it is true for example for MySQL or Firebird ODBC driver, but for SQL Server or PostgreSQL ODBC driver there are no such options (but PostgreSQL ODBC driver exists in ANSI and UNICODE version) SQL Server ODBC driver supports AutoTranslate, see: http://msdn.microsoft.com/en-us/library/ms130822.aspx SQL Server *char*, *varchar*, or *text* data sent to a client SQL_C_CHAR variable is converted from character to Unicode using the server ACP, then converted from Unicode to character using the client ACP. There's also another solution you can find on the forum and other places. You can convert the strings to UTF-8 not only when they are read from the database, but also when they are read from the internal memory. There's a hook for that. Thanks for your patience -Laco. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] TStringField, String and UnicodeString and UTF8String
Joost van der Sluis wrote / nap?sal(a): On Wed, 2011-01-12 at 14:59 +0100, LacaK wrote: No. It is mandatory that you send/receive UTF8 to/from GUI LCL elements. As LCL elements are using TStringField.Text property, then this property should return UTF8String, right (not AnsiString in ANSI code page) ? If yes, then also TStringField must store internaly data in any unicode format (to not lose any characters), right ? So it can be UTF-8, UTF-16 or UTF-32 ... in all cases we must allocate space 4*[max.number of characters in field], right ? So in what encoding are string data stored now in TStringField ? The encoding you've specified. In the connection-string or some other database-server dependent setting. ok. But then there is problem in buffer size allocated for TStringField (ftString), does not ? See please at bug report: http://bugs.freepascal.org/view.php?id=17376 There is described situation with SQLite (TSQLite3Connectin) , which returns UTF-8 strings, so there is no problem in encoding, but problem is in fact, that for char(n),varchar(n) fields is created TStringField with Size=n and in record buffer is also allocated space with Size+1, where n is number of characters (not bytes). So truncation of data occurs, when writting UTF-8 encoded string into record buffer. So IMHO there must be: 1. allocated space in record buffer in size 4*TFieldDef.Size+1 (and so on) or 2. redefine meaning of Size property (as number of bytes not characters) and create fielddefs with Size*4 hm, according to http://docwiki.embarcadero.com/VCL/XE/en/DB.TStringField.Size is Size number of characters but according to http://docwiki.embarcadero.com/VCL/en/DB.TFieldDef.Size is Size number of bytes in underlaying database but TField is created from TFieldDef and TField.Size=TFieldDef.Size ... so isn't it curious ? Not that when you want to use UTF-16 (or 32) you have to use TWideStringFields. So TWideStringField is no-encoding-agnostic field (is it designed to be everytime UTF-16 encoded) ? -Laco. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] TStringField, String and UnicodeString and UTF8String
L Yes in UNIX world it may be so (I do not know), L but in Windows ODBC we have no such possibility AFAIK Quote from Microsoft: The ODBC 3.5 (or higher) Driver Manager supports both ANSI and Unicode versions of all functions that accept pointers to character strings or SQLPOINTER in their arguments. The Unicode functions are implemented as functions (with a suffix of W), not as macros. The ANSI functions (which can be called with or without a suffix of A) are identical to the current ODBC API functions. ODBC 3.5 was launched around 2000-2001. But this approach will require changes in packages/odbc/src/odbcsql.inc like, does not ?: -pointer(SQLGetData) := GetProcedureAddress(ODBCLibraryHandle,'SQLGetData'); +pointer(SQLGetData) := GetProcedureAddress(ODBCLibraryHandle,'SQLGetDataW'); And I do not know how it affect compatibility for example in UNIX or if all ODBC drivers support this functionality. But also in this case we will get UTF-16 widestrings (in Windows) not UTF-8, does not ? -Laco. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] TStringField, String and UnicodeString and UTF8String
Most probably it needs a flag to indicate that the ODBC must work in Unicode, and then dynamic link to *W functions if this flag is set. I think ODBC drivers since 2002+/- should have this set of APIs, but I had never used ODBC in my life... :) It seems, that Driver Manager automaticaly performs conversions on non-unicode driver. See http://web.datadirect.com/resources/odbc/unicode/odbc-driver.html ( and http://web.datadirect.com/resources/odbc/unicode/char-background.html ) If the driver is a non-Unicode driver, it cannot understand W function calls, and the Driver Manager must convert them to ANSI calls before sending them to the driver. Also it seems to me, that when you call ANSI version of ODBC API functions, then you receive data in ANSI encoding. If it is so, then it is always safe use ansitoutf8() (or UTF8Encode()) on receved data. L But also in this case we will get UTF-16 widestrings (in Windows) not L UTF-8, does not ? That's not important, you get unicode in the specified by the API format, then SQLConnector fills information in the expected target format (WideString, UTF8String over AnsiString, Raw bytes...). In Windows we get UTF-16, in Linux/UNIX we get UTF-8 So it is so, that in Windows is widestring=UTF-16 and in Linux/UNIX is widestring=UTF-8 string ? (So there is different meaning of widestring type on different OSeses ? I am only Windows developer, so I have no understanding of others OSeses ;-)) -Laco. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] TStringField, String and UnicodeString and UTF8String
So IMHO there must be: 1. allocated space in record buffer in size 4*TFieldDef.Size+1 2. redefine meaning of Size property (as number of bytes not characters) and create fielddefs with Size*4 Yes, those are the possible solutions. Good thing about the second option, is that a user can do that on his own if he wants to use UTF-8, just create persistent fields with a field size of 4*the amount of characters. I'm not sure if we have to change this. It's a problem the programmer has to deal with, I think... I see here these possible problems/disadvantages: 1. In many cases (dynamic build or ad-hoc queries) is creating persistent fields not very effective (or complicated) 2. allocation of space in record buffer is based on TFieldDef objects (see TCustomBufDataset.GetFieldSize) and TFieldDef object are created by TSQLConnectors in AddFieldDefs method, so setting Size in persistent field does not solve whole problem, because each SQLConnector must set Size also 3. in TStringField is Size used also to determine default DisplayWidth (for TDBGrid) and in Delphi also for setting MaxLength in TDBEdit (so here we can see, that Size is used like max.number of characters rather than bytes) 4. incompatibility of Delphi (if we reclasiffy Size as number of bytes not characters) So I would prefer 1st way (increase buffer size, may be if we will support only BMP then 3*Size+1 will be sufficient) So Size remains as character length hm, according to http://docwiki.embarcadero.com/VCL/XE/en/DB.TStringField.Size is Size number of characters but according to http://docwiki.embarcadero.com/VCL/en/DB.TFieldDef.Size is Size number of bytes in underlaying database Yes, that's indeed the problem. But there's also the .DataSize property, so we could use that. Yes, but DataSize is defined only in TField not in TFieldDef class If we will add DataSize property also for TFieldDef class and overload TFieldDef.Create method with additional parameter DataSize, then SQLConnector would specify both information: character size (for displaying purposes) and byte size (for buffer purposes) Maybe... if the pressure on the bugtracker gets too high, I'll bow and change this. (I think 25% of all existing db bugs are related to this and people who do not understand anything about encodings.) but TField is created from TFieldDef and TField.Size=TFieldDef.Size ... so isn't it curious ? Not that when you want to use UTF-16 (or 32) you have to use TWideStringFields. So TWideStringField is no-encoding-agnostic field (is it designed to be everytime UTF-16 encoded) ? No. It's designed to contain an array of two-bytes records. In fact you can use it to store UCS-2 data, but not UTF-16. Same story as with ansi/UTF-8. Yes I understand now. Laco. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] TStringField, String and UnicodeString and UTF8String
So this is answer, which i have looked for: In Lazarus TStringField MUST hold UTF-8 encoded strings. Not entirely true. You could also choose to bind the fields to some Lazarus-components manually, not using the db-components. IMHO most of gui database applications use controls like TDBGrid or TDBEdit so they should display correct values by default without extra coding (or at least provide some standardized support ... ) (Tedit.Text := convertFunc(StringField.Text)) Or you can add a hook so that the .text property always does a conversion to UTF-8. First option can be used if you use a mediator or view. Second options I woudn't use. Rofl. You mean that Microsoft SQL Server can't handle unicode completely? Completely not, but only UCS-2 (no UTF-8) SQL Server provides non-UNICODE datatypes - char, varchar, text ie: TStringField Yes, but ODBC driver returns data in ANSI codepage (no possibility to force them return UTF-8) This I can fix by patch in TODBCConnection LoadField like this: (so I convert to UTF-8 in connector method, when driver is unable return UTF-8) begin Res:=SQLGetData(ODBCCursor.FSTMTHandle, FieldDef.Index+1, SQL_C_CHAR, buffer, FieldDef.Size, @StrLenOrInd); + if CharSet='ANSI' then //hack for Microsoft SQL Server +StrPLCopy(buffer, UTF8Encode(PChar(buffer)), FieldDef.Size); end; and UNICODE (UCS-2) datatypes - nchar, nvarchar, ntext ie: TWideStringField. Yes, in this case ODBC driver returns data in UCS-2, this data are written into WideString buffer, which seems correct, but in DBGrid are displayed ? instead of characters with diacritical marks (IMHO because widestringmanager in Windows converts WideString to ANSI string , not UTF-8 string). This can be fixed by using OnGetText method of field: aText:=UTF8Encode(Sender.AsString); Which is not user friendly, because requires hacking in user code in every TWideStringField in every TSQLQuery It can be also fixed in fields.inc: function TWideStringField.GetAsString: string; begin +{$IFDEF WINDOWS} + Result := UTF8Encode(GetAsWideString); +{$ELSE} Result := GetAsWideString; +{$ENDIF} end; So what is the expected encoding of data written into TWideStringField ... or is there way how to get correct results id DBGrid without above mentioned workarounds ? SQL Server ODBC driver supports AutoTranslate, see: http://msdn.microsoft.com/en-us/library/ms130822.aspx SQL Server char, varchar, or text data sent to a client SQL_C_CHAR variable is converted from character to Unicode using the server ACP, then converted from Unicode to character using the client ACP. This is what you use when you set the encoding when you connect to the client. The solution to all your problems. As explained three times, in this message alone. In fact it's simple: incoming data=outgoing data. If you need UTF-8 encoding for the outgoing data (direct access to Lazarus controls) you have to select UTF-8 at the input. Yes, but as I wrote such possibility does not exists with Microsoft SQL Server (and also I think Access) (it seems, that Microsoft does not like UTF-8 and prefers UTF-16 (UCS-2)) And, luckily, you can instruct the Database-server which encoding to use when it's communicating with the outer world. So your problem is solved. When it is possiblem then yes. Now, if you also choose UTF-8 as the Database-server field encoding (the encoding the data is stored in) there's no conversion necessary at all. Yes if DB supports UTF-8 -Laco. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] MySQL 5.5 and Connector System
If sb wants in in 2.4.4, I urge you to be quick :-) Does it mean, that you are preparing release 2.4.4 in short time ? If yes, then I would happy, if also bug http://bugs.freepascal.org/view.php?id=16493 with attached patch will be commited. Thanks Laco. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] MySQL 5.5 and Connector System
Done. Revision 16776. Thak you very much. Could I ask how/when are bugs/patch reviewed/commited ? Is there any single person(s) who maintains for example fcl-db or any fpc-developer can apply patches ? Is there any special time when patches are applied or in trunk can be patch applied any time (so if it is applied depends only on free time of developer(s)?) ? I am asking because some (simple) patches are waiting relative long time. For example: http://bugs.freepascal.org/view.php?id=15314 http://bugs.freepascal.org/view.php?id=16924 (patch 1) This is not criticism ;-) Laco. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
[fpc-devel] GetLocaleInfo strange result in Windows 7
Hi *, consider following sample program: var b: array[0..255] of char; begin if getlocaleinfoa(LOCALE_USER_DEFAULT, LOCALE_SSHORTDATE, b, sizeof(b)) 0 then writeln('LOCALE_USER_DEFAULT:',b); if getlocaleinfoa(LOCALE_SYSTEM_DEFAULT, LOCALE_SSHORTDATE, b, sizeof(b)) 0 then writeln('LOCALE_SYSTEM_DEFAULT:',b); if getlocaleinfoa(GetThreadLocale, LOCALE_SSHORTDATE, b, sizeof(b)) 0 then writeln('GetThreadLocale:',b); end; In Windows XP/Vista returns: LOCALE_USER_DEFAULT:d. M. LOCALE_SYSTEM_DEFAULT:d. M. GetThreadLocale:d. M. --IS OK In Windows 7 returns: LOCALE_USER_DEFAULT:d. M. LOCALE_SYSTEM_DEFAULT:d. M. GetThreadLocale:M/d/ --HERE IS PROBLEM So because calls to getlocaleinfo with argument GetThreadLocale is used to initialize DefaultFormatSettings, in Windows 7 are some locale specific global variables (ShortDateFormat, DateSeparator etc.) initialized incorrectly. Has anybody else this experience ? Now I find: http://qc.embarcadero.com/wc/qcmain.aspx?d=80189 http://stackoverflow.com/questions/1767946/getthreadlocale-returns-different-value-than-getuserdefaultlcid So can you fix this problem somewhere in initialization process ? Thanks -Laco. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] GetLocaleInfo strange result in Windows 7
Please file a bugreport, citing the stackoverflow answer. http://bugs.freepascal.org/view.php?id=18574 -Laco. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
[fpc-devel] fcl-db bugs/improvements/patches
Hi *, there are some waiting bugs with patches, which are relative simple and IMHO they can not affect negatively product quality. I summarize them here, for quick review them, so if then they can go into 2.4.4 release: 1. http://bugs.freepascal.org/view.php?id=17188 and http://bugs.freepascal.org/view.php?id=18718 This fix add missing cases so all existing should work as before 2. http://bugs.freepascal.org/view.php?id=18649 This fix adds (or replaces) new datatype BIGINT to SQLite3Connection 3. http://bugs.freepascal.org/view.php?id=18670 This fix adds new datatype NCHAR, NVARCHAR, NCLOB to SQLite3Connection 4. http://bugs.freepascal.org/view.php?id=14944 This fix adds support for transactions in ODBCConnection 5. http://bugs.freepascal.org/view.php?id=16885 This fix adds missing TOracleConnection.RowsAffected method 6. http://bugs.freepascal.org/view.php?id=18699 This fixes Dialect 1 case Thanks -Laco. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] fcl-db bugs/improvements/patches
They all need improvement or a better review or testcases or break backwards compatibility. The BIGINT or NCHAR stuff not, I would think ? I'll have a look. BIGINT leads to a backwards compatibility issue with largeint not being recognized anymore. (not a real problem I think, but it must be documented in user-changes) then we can leave largeint and add bigint this will be safe in all aspects. And largeint can be dropped later (as obsolete, non-standard). And I think to fix this a revision has to be reverted, not committed? Which leads to a new issue: we need to add a test that test for the problem introduced with the revision being reverted. (ie: recognition of fieldtypes when the first record is NULL) yes this problem was revealed, but does not affect fix as I wrote in bug tracker we must always rely on sqlite3_column_decltype() and only when no useful information will be available then use as workaround (or hack) sqlite3_column_type() The nchar stuff doesn't have tests. yes it is true, but they can be added later ... but NCHAR is not supported by all databases so it must be implemented carefully I don't even know if ftWideString and such are working at all. for me it works ... and as TWideStringField is descendant of TStringField (which have tests), there is big chance, that it will work The basic tests for these types have to be added. if some patches are problematic, then leave it for future ... but please comment my list and let me know if I can do something to help. IMHO at least points 4,5,6 are safe. Thanks Laco. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] fcl-db bugs/improvements/patches
Michael can you please look also at this http://bugs.freepascal.org/view.php?id=17510 Thanks Laco. I will look at them today. Michael. On Wed, 16 Feb 2011, LacaK wrote: Hi *, there are some waiting bugs with patches, which are relative simple and IMHO they can not affect negatively product quality. I summarize them here, for quick review them, so if then they can go into 2.4.4 release: 1. http://bugs.freepascal.org/view.php?id=17188 and http://bugs.freepascal.org/view.php?id=18718 This fix add missing cases so all existing should work as before 2. http://bugs.freepascal.org/view.php?id=18649 This fix adds (or replaces) new datatype BIGINT to SQLite3Connection 3. http://bugs.freepascal.org/view.php?id=18670 This fix adds new datatype NCHAR, NVARCHAR, NCLOB to SQLite3Connection 4. http://bugs.freepascal.org/view.php?id=14944 This fix adds support for transactions in ODBCConnection 5. http://bugs.freepascal.org/view.php?id=16885 This fix adds missing TOracleConnection.RowsAffected method 6. http://bugs.freepascal.org/view.php?id=18699 This fixes Dialect 1 case Thanks -Laco. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] fcl-db bugs/improvements/patches
Hi Joost, thanks for reply 4. http://bugs.freepascal.org/view.php?id=14944 This fix adds support for transactions in ODBCConnection Adding transactions so close to a release is not a good idea, imho. It could be added in trunk, though. ok, no objections from me side only to explain: ODBC works by default in auto-commit mode, and this behavior is not affected by fix so all remains as is. only when you supply to TODBCConnection.Params: 'Autocommit=false' or 'AutoCommit=0' you will switch to manual commit. without this all works as before. But first run the testsuite with this patch for at least mysql/mssql and firebird using odbc. ;-) please, no 5. http://bugs.freepascal.org/view.php?id=16885 This fix adds missing TOracleConnection.RowsAffected method A regression-test has to be performed before this can be comitted. (Needs an oracle setup) Why do you think, that this patch can lead to problems, ATM RowsAffected is not implemented, so it always returns -1. So nobody can use / rely on this value. So I think, that provide some (untested) solution is better than nothing ... and we can wait for users feedback (I do not have Oracle instaled, so I can not help, test) 6. http://bugs.freepascal.org/view.php?id=18699 This fixes Dialect 1 case The question in the bug-report has to be answered. answered So even 4,5 and 6 are not that easy. (If they were, they were already applied) ;-) ok Thanks Laco. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] fcl-db bugs/improvements/patches
When I already have start this thread, I would like also point to this bugs (their are both more or less about the same): http://bugs.freepascal.org/view.php?id=14730 http://bugs.freepascal.org/view.php?id=18162 Now I can not primary talk about NULL paramters, but about ukInsert case (in Procedure TCustomSQLQuery.ApplyRecUpdate). There is serious bug in fact, that FInsertQuery is assigned only once (using function InsertRecQuery), when FIRST insert is applied. And InsertRecQuery construct SQL insert but only for NOT NULL values. Example: 1. we have table1 with some 3 columns: col1, col2, col3 2. I Append record and set only 1st column, then Post 3. I ApplyUpdates ... insert is constructed INSERT INTO table1 (col1) VALUES(:col1) 4. I Append second record and fill all 3 columns, then Post 5. I ApplyUpdates ... but no new insert is constructed (because FInsertQry is already assigned), but is used existing from step 3 6. So columns col2 and col3 are never inserted to database Do you see ? Thanks Laco. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
[fpc-devel] TFmtBCDField
Hi Joost, it seems, that you have started applying patch in http://bugs.freepascal.org/view.php?id=18160 or http://bugs.freepascal.org/view.php?id=16924 Great! I have some comments, ideas, please consider them. Because in mean time was enhanced FmtBCD unit you can remove some commented lines in fields.inc 1. VarFMTBcdCreate() should already work, so: 2447-Result := BCDToDouble(bcd)//remove when complete variant support in fmtbcd.pp will be implemented 2448-//Result := VarFMTBcdCreate(bcd) //later invalid variant type cast ? 2448+Result := VarFMTBcdCreate(bcd) 2. VarToBCD() is already implemented, so: 2548procedure TFMTBCDField.SetVarValue(const AValue: Variant); 2549- var E:double; 2550begin 2551- E:=AValue; 2552- SetAsBCD(DoubleToBCD(E));//remove when VarToBCD in fmtbcd.pp will be implemented 2553- //SetAsBCD(VarToBCD(AValue)); 2553+SetAsBCD(VarToBCD(AValue)); 2554end; 3. BCDToStrF there is waiting patch http://bugs.freepascal.org/view.php?id=18388 if applied, then also can be removed comments in procedure TFMTBCDField.GetText 4. Add 3th parameter to TryStrToBCD( const aValue : FmtBCDStringtype; var BCD : tBCD; DecimalSeparator : char = #0) : Boolean; so we can supply directly decimal separator '.' used in SQL and to avoid saving existing, set '.' and then restoring ... http://svn.freepascal.org/cgi-bin/viewvc.cgi/trunk/packages/fcl-db/src/sqldb/sqlite/sqlite3conn.pp?r1=16948r2=16954 (like TryStrToDate, TryStrToTime) or add overloaded TryStrToBCD( const aValue : FmtBCDStringtype; var BCD : tBCD; FormatSettings : TFormatSettings) : Boolean; (like TryStrToFloat) Thanks Laco. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] TFmtBCDField
Hi Joost, thanks! Thinking about TFmtBCDField it seems to me, that also dsparams.inc must be adjusted to support ftFMTBcd ... add AsBCD: TBCD etc. ... at least my test with new TSQLite3Connection shows, that there is missing it (when applyng updates to record) Do you have already finished implementing ftFMTBcd into TSQLite3Connection ? 4. Add 3th parameter to TryStrToBCD( const aValue : FmtBCDStringtype; var BCD : tBCD; DecimalSeparator : char = #0) : Boolean; so we can supply directly decimal separator '.' used in SQL and to avoid saving existing, set '.' and then restoring ... http://svn.freepascal.org/cgi-bin/viewvc.cgi/trunk/packages/fcl-db/src/sqldb/sqlite/sqlite3conn.pp?r1=16948r2=16954 (like TryStrToDate, TryStrToTime) or add overloaded TryStrToBCD( const aValue : FmtBCDStringtype; var BCD : tBCD; FormatSettings : TFormatSettings) : Boolean; (like TryStrToFloat) And could you add a bug-report for this? I think that Marco or MvC should have a look at it and have to decide which design is best and also compatible to Delphi. Then the db-changes can be made. Bug report is here http://bugs.freepascal.org/view.php?id=18807 If this way will be approved, then we can very nice use it (no need to initialize something, store/restore) for example: ... if not TryStrToBCD(bcdstr,bcd,SQLFormatSettings) then ... we must only add into TSQLConnection: property SQLFormatSettings: TFormatSettings read FSQLServerFormatSettings; FSQLServerFormatSetting already exists as private variable Laco. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
[fpc-devel] RFC: TParam.AsBCD vs. AsFMTBCD
Hi, we have in fcl-db TField.AsBCD: TBCD; but we do not have TParam.AsBCD, nor TParam.AsFMTBCD Delphi defines: TParam.AsBCD: Currency ... http://docwiki.embarcadero.com/VCL/XE/en/DB.TParam.AsBCD TParam.AsFMTBCD: TBCD ... http://docwiki.embarcadero.com/VCL/XE/en/DB.TParam.AsFMTBCD But for me sounds more logical and consistent, that TParam.AsBCD will be like TField.AsBCD so result type will be TBCD (TParam.AsBCD: Currency is more like TParam.AsCurrency: Currency) So what way to go ? 1. TParam.AsBCD: TBCD 2. TParam.AsFMTBCD: TBCD Laco. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] RFC: TParam.AsBCD vs. AsFMTBCD
Ok, here is patch for AsFMTBCD: TBCD ... http://bugs.freepascal.org/view.php?id=18809 Please review. It seems, that methods TParam.GetData and SetData are not used at all ... strange ;-) Laco. Well, the Delphi compatible way is usually preferred. It makes no sense to have both .asBCD and asFMTBCD to have the same result type. The same can of course be said about .asBCD and .AsCurrency; But since Delphi compatibility is a goal, I think we should follow them. Borland could perfectly have sufficed with 2 properties (.AsCurrency, AsBCD). For some reason they introduced 3. Michael. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
[fpc-devel] RFC: Procedure TParam.AssignFieldValue
Hi, can anybody look into dsparams.inc at above mentioned method. There are using 5 assigments : DataType := ... 1. because DataType is property it uses SetDataType method 2. SetDataType method try convert existing FValue into new FieldType 3. but later in AssignFieldValue is FValue rewritten by Value:=AValue (or Cleared) So it seems to me that using DataType is unnecessary, I would suggest using FDataType:=... What do you think ? TIA Laco. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
[fpc-devel] TFieldDef.Size vs TField.Size
Hi, I am writting here to discuss bug http://bugs.freepascal.org/view.php?id=17268 (I do not want reopen bug and writte there because I am not sure about my arguments) IMHO root of problem is in different definition of TFieldDef.Size and TField.Size Documentation says, that 1. TFieldDef.Size should be For string and byte fields, *Size* is the number of bytes reserved http://docwiki.embarcadero.com/VCL/en/DB.TFieldDef.Size 2. TField.Size should be the maximum number of characters in the string (for ftString and I guess that also for ftWideString) http://docwiki.embarcadero.com/VCL/en/DB.TField.Size http://docwiki.embarcadero.com/VCL/en/DB.TStringField.Size And now let's go look into fields.inc: 1. Function TFieldDef.CreateField copies Result.Size:=FSize (so TField.Size:=TFieldDef.Size) 2. function TStringField.GetDataSize returns for ftString ... Size+1 3. function TWideStringField.GetDataSize returns for ftWideString ... (Size + 1) * 2 Points 2,3 are clear Size is expected to be number of characters, DataSize number of bytes. But point 1 says, that TFieldDef.Size and TField.Size should be the same And now let's go look into bufdataset.pas: 4. function TCustomBufDataset.GetFieldSize works with TFieldDef and returns number of bytes needed in record buffer case FieldDef.DataType of ftString, ftGuid, ftFixedChar: result := FieldDef.Size + 1; ftFixedWideChar, ftWideString:result := (FieldDef.Size + 1)*2; ... So also here we can see, that FieldDef.Size is expected to be number of characters not bytes. So IMHO logical conclusion will be say, that TFieldDef.Size for string fields has same menaing as Field.Size, so it is number of characters (so documentation is wrong in this case ... also fast test in Delphi shows, that FieldDef.Size=Field.Size=number of characters) Laco. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] TFieldDef.Size vs TField.Size
Hi, I am writting here to discuss bug http://bugs.freepascal.org/view.php?id=17268 (I do not want reopen bug and writte there because I am not sure about my arguments) IMHO root of problem is in different definition of TFieldDef.Size and TField.Size Documentation says, that 1. TFieldDef.Size should be For string and byte fields, *Size* is the number of bytes reserved http://docwiki.embarcadero.com/VCL/en/DB.TFieldDef.Size 2. TField.Size should be the maximum number of characters in the string (for ftString and I guess that also for ftWideString) http://docwiki.embarcadero.com/VCL/en/DB.TField.Size http://docwiki.embarcadero.com/VCL/en/DB.TStringField.Size And now let's go look into fields.inc: 1. Function TFieldDef.CreateField copies Result.Size:=FSize (so TField.Size:=TFieldDef.Size) 2. function TStringField.GetDataSize returns for ftString ... Size+1 3. function TWideStringField.GetDataSize returns for ftWideString ... (Size + 1) * 2 Points 2,3 are clear Size is expected to be number of characters, DataSize number of bytes. But point 1 says, that TFieldDef.Size and TField.Size should be the same And now let's go look into bufdataset.pas: 4. function TCustomBufDataset.GetFieldSize works with TFieldDef and returns number of bytes needed in record buffer case FieldDef.DataType of ftString, ftGuid, ftFixedChar: result := FieldDef.Size + 1; ftFixedWideChar, ftWideString:result := (FieldDef.Size + 1)*2; ... So also here we can see, that FieldDef.Size is expected to be number of characters not bytes. So IMHO logical conclusion will be say, that TFieldDef.Size for string fields has same menaing as Field.Size, so it is number of characters Correct, if you assume 1 char = 1 byte. (so documentation is wrong in this case ... also fast test in Delphi shows, that FieldDef.Size=Field.Size=number of characters) Your story is confusing to me. Where do you see a problem ? See please http://svn.freepascal.org/cgi-bin/viewvc.cgi/trunk/packages/fcl-db/src/sqldb/odbc/odbcconn.pas?r1=16094r2=16988 And look at ftWideString, ftFixedWideChar cases What happens if we have NVARCHAR(20) column on MS SQL Server (uses UCS-2 1char=2bytes): 1. in AddFieldDefs method is created TFieldDef object with Size=20*2 (because FieldSize:=ColumnSize*sizeof(Widechar)) 2. later when TField objects are created in TFieldDef.CreateField method, TWideString object is created with Size=40 (because Size is copied from TFieldDef object) ... and this is wrong, because: 2.1 TWideString.Size should IMO return max.number of characters ... Size is used for example in data-aware controls to limit MaxLength 2.2 TWideStringField.GetDataSize will return 82, which is also wrong (because (40+1)*2) 2.3 in record buffer will be allocated also 82 bytes (because of TCustomBufDataset.GetFieldSize) So IMO correct will be in step 1 FieldSize:=ColumnSize not FieldSize:=ColumnSize*sizeof(WideChar) (like in my original fix in bug report) Note also, that Size is used (also in Delphi) to limit the number of characters in data-aware controls (for ftString, ftWideString), so it must be number of characters in both cases. Do you see an implementation problem or a documentation problem ? Implementation problem at first but also Documentation is confusing, because do not clearly says about menaing of TWideStringField.Size (only indirect guess can be done, that it is inherited from TStringField.Size, so it is number of characters) See, that also other users are confusing by it https://forums.embarcadero.com/thread.jspa?messageID=188792 Note that nowhere in the documentation pages you mention, widestrings are mentioned (which is convenient, since that's where 1 char 1 byte). Yes, but in Delphi6 help is for TWideStringField.DataSize: Inspect DataSize to determine the number of bytes required to store the fields value. Use DataSize to determine the size needed for a buffer when working with the GetData and SetData methods. For wide string fields, DataSize is the value of the Size property plus one (for the trailing NULL character), multiplied by two. So we can estimate, that Size is number of characters, while DataSize=(Size+1)*2 Laco. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] TFieldDef.Size vs TField.Size
Please, be patient. I'm working on it, as you can see in the bug reports and commits. ok, of course I did not know your plans, ideas, thoughts etc. As I said earlier, widestringfields aren't available in fpc yet. Someone wrote some code for it, but it is never properly tested and probably only worked by accident. I did not know that, I was thinking about TWideStringFields as a implemented, supported thing But I don't commit everything in one go, it's work-in-progress. And I need to write tests for everything that I commit. You mixed two things in one patch, so I had to split it into pieces. ok I did some tests with different Delphi versions, with and without unicode. And beside finding some bugs in XE's string-db code I think I know a solution for all problems regarding strings and unicode. But let me thing it out, write tests, write code and test if it works indeed. ok if you can inform about your plans, order of tasks etc. ... it will be welcomed if I can help you, let me know ... for example I have fix for TODBCConnection.SetParameters ... there is missing ftTime and ftWideString,ftWideFixedChar cases ... as revealed by testing with ODBC/MySQL IMHO root of problem is in different definition of TFieldDef.Size and TField.Size Documentation says, that 1. TFieldDef.Size should be For string and byte fields, Size is the number of bytes reserved [?]http://docwiki.embarcadero.com/VCL/en/DB.TFieldDef.Size I don't care what the documentation of others say. It is about how we implemented it and how we document things. ok I've read the documentation and did some tests. The documentation is simply wrong here. The behavior changed with different versions of Delphi, the documentation is never adapted. As I wrote in the bug-report, TFieldDef.Size should contain the number of bytes to hold the string, without the leading 0. why do you think so ? If we do not care about Delphi documentation, it seems to me more consistent, that TFieldDef.Size and TField.Size says about equal things (this is similar story as TField.AsBCD: TBCD and TParam.AsBCD: Currency ... same name, different meaning ... in my opinion something very strange) Note that with the unicode-versions of Delphi have in TFieldDef.Size the amount of characters * 4 in TFieldDef.Size. For WideStrings and normal strings. I'm thinking about adding a property to T(Buf)Dataset in which you can specify if you want to use unicode-length strings, or 'normal' lengths. So that we can add backwards-compatilibity, which Delphi doesn't. would not be better add such property to TSQLConnection class, as IMO all SQLQueries connected to one DB will work with same type of strings. So users can set it once and not for every TCustomSQLQuery object individualy ? 2. TField.Size should be the maximum number of characters in the string (for ftString and I guess that also for ftWideString) [?]http://docwiki.embarcadero.com/VCL/en/DB.TField.Size [?]http://docwiki.embarcadero.com/VCL/en/DB.TStringField.Size That's simply true. Also for widestrings. (tested) And now let's go look into fields.inc: 1. Function TFieldDef.CreateField copies Result.Size:=FSize (so TField.Size:=TFieldDef.Size) 2. function TStringField.GetDataSize returns for ftString ... Size+1 3. function TWideStringField.GetDataSize returns for ftWideString ... (Size + 1) * 2 Those functions have to be adapted, yes. I have the changes here but I need to fine-tune the tests, clean up etc. So also here we can see, that FieldDef.Size is expected to be number of characters not bytes. This was the case in the past. And it didn't lead to problems as widestrings were never used properly. (That's why no-one bothered how it was implemented for widestrings) So IMHO logical conclusion will be say, that TFieldDef.Size for string fields has same menaing as Field.Size, so it is number of characters (so documentation is wrong in this case ... also fast test in Delphi shows, that FieldDef.Size=Field.Size=number of characters) No, our implementation is wrong and we have to adapt our code. That way it is also possible to fix the unicode-problems you've reported. ps: if you want to know what the Delphi-XE-bug is. when using the TClientDataset, for widestrings, TFieldDef.Size is four times the amount of characters (ok), but when you get TWideSTringField.Datasize the answer is two times TfieldDef.Size +2. Yes same as in FPC GetDataSize:=(Size+1)*2 So if you have a wide-string of 40 characters. TFieldDef.Size is 160, but TField.Datasize 322. (obviously wrong) Yes, TField.Size = TFieldDef.Size, TField.DataSize = (TField.Size+1)*2 Laco. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] TFieldDef.Size vs TField.Size
I'm adding some ftTime tests. Did you noticed, that I already posted such tests http://bugs.freepascal.org/view.php?id=18763 ? Then let me know, I send you fix for ftTime for TODBCConnection ... but depends on http://bugs.freepascal.org/view.php?id=18773 All widestring-issues are postponed until I found a way to deal with them, unicode, and have tests to test them. ok but now the TFmtBcd field is finally implemented, please look at http://bugs.freepascal.org/view.php?id=18809 and IMO also this bugs must be solved first to continue with implementing TFmtBcdField into connectors http://bugs.freepascal.org/view.php?id=18388 and http://bugs.freepascal.org/view.php?id=18807 you can add support for that? Now it only works with sqlite, yes, but there is missing support for parameter ftFmtBCD in Procedure TSQLite3Cursor.bindparams maybe you can add it for the other databases that you use? (odbc,mysql?) yes i can do it, but would wait for fixing above mentioned bugs, to not touch code twice if something in fmtbcd unit changes As I wrote in the bug-report, TFieldDef.Size should contain the number of bytes to hold the string, without the leading 0. why do you think so ? If we do not care about Delphi documentation, it seems to me more consistent, that TFieldDef.Size and TField.Size says about equal things It depends on how they are used. I think it is very usefull for a programmer to know the maximum amount of characters. (TField.Size) yes And a programmer should be able to detect how many bytes are reserverd to store it (TFieldDef.Size). yes, but I would preffer introduce new TFieldDef.DataSize property, which will serve for byte length. So we will have TFieldDef.Size, TField.Size=character length and TFieldDef.DataSize, TField.DataSize=byte length Then we will be able use TFieldDef.DataSize instead of TCustomBufDataset.GetFieldSize (we can completely drop this) and all fields stuff will be in one unit fields.inc This is especially important if we are supporting unicode-strings, where both values can differ. yes So when you are getting/setting data from the server, you use TFieldDef.Size, and then you want to check what the maximum amount of characters is, TField.Size. yes, my only objection is, that same name is used for different things, which is confusing, non-intuitive and will/can lead to misunderstandings Note that with the unicode-versions of Delphi have in TFieldDef.Size the amount of characters * 4 in TFieldDef.Size. For WideStrings and normal strings. I'm thinking about adding a property to T(Buf)Dataset in which you can specify if you want to use unicode-length strings, or 'normal' lengths. So that we can add backwards-compatilibity, which Delphi doesn't. would not be better add such property to TSQLConnection class, as IMO all SQLQueries connected to one DB will work with same type of strings. So users can set it once and not for every TCustomSQLQuery object individualy ? Maybe. but I have to think about it better. Because if code in fields.inc depends on it, we have to add the property to TDataset itself. yes I also must think about it more So if you have a wide-string of 40 characters. TFieldDef.Size is 160, but TField.Datasize 322. (obviously wrong) Yes, TField.Size = TFieldDef.Size, TField.DataSize = (TField.Size+1)*2 There are more ways to solve that. And we need to find how the Delphi datasets which do not have this problem do that. One way is: TField.Size := (TFieldDef.Size div 2) if it's a WideString, and div 4 if unicode is enabled. Or the TDataset descendant has to correct the value for WideStrings when creating fields. (How?) hm, we must think about it more Laco. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] TFieldDef.Size vs TField.Size
One way is: TField.Size := (TFieldDef.Size div 2) if it's a WideString, and div 4 if unicode is enabled. Or the TDataset descendant has to correct the value for WideStrings when creating fields. (How?) Very simple/primitive Idea No1: add property DataSize: integer read GetDataSize write FDataSize; into TFieldDef class add next parameter ADataSize to Constructor TFieldDef.Create(AOwner: TFieldDefs; const AName: string; ADataType: TFieldType; ASize: Integer; ARequired: Boolean; AFieldNo: Longint ADataSize: Integer=0); which is used in every TSQLConnection descendant to create fielddefs So connectors can supply ASize=character length and also ADataSize=byte length , which they require to write/read character data into local buffer (each connector should be aware of this information ... i.e. encoding of character data which exchanges with DB engine) If not specified , then default =0 means use ASize+1 for ftString, (ASize+1)*2 for ftWideString ... for backward compatibility, for most others datatypes ignore it (because they are internaly stored in fixed length data structures). Each TSQLConnection has CharSet property and each DB engine supports limited number of connection charsets. So SQLConnection can read CharSet property and determine character width. For example if CharSet='UTF-8' then char_width:=3 (or 4) if CharSet='UCS-2' then char_width:=2 if CharSet='UTF-16' then char_width:=4; So with conjuction with Column size (ASize) can easy compute buffer size (ADataSize) or Constructor TFieldDef.Create(AOwner: TFieldDefs; const AName: string; ADataType: TFieldType; ASize: Integer; ARequired: Boolean; AFieldNo: Longint ACharEncoding: TCharEncoding); TCharEncoding=(cheUnknown, cheAnsi, cheUTF8, cheUTF16); and then ADataSize can be computed inside TFieldDef.Create and stored into FDataSize for later usage.(as I wrote before TFieldDef.GetDataSize will replace TCustomBufDataset.GetFieldSize) Laco. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
[fpc-devel] FmtBCD unit improvements / bugs
Hi, I would like to ask somebody to look at these bug reports: 1. http://bugs.freepascal.org/view.php?id=18388 This bug report contains implementation of missing BcdToStrF function. There is also discussion if FmtBCD unit is localized ... tests under Delphi (6,10) shows, that Delphi *uses* global variables DecimalSeparator (in StrToBCD, BCDToStr, BCDToStrF) and ThousandSeparator (in BCDToStrF). 2. http://bugs.freepascal.org/view.php?id=18807 If fix in bug report (1) will be applied, then I can continue by adding overloaded functions TryStrToBCD, StrToBCD, BCDToStr with next parameter const Format: TFormatSettings (in style of TryStrToFloat etc. and also in Delphi compatible way) and drop global variable DecimalPoint and replace its using by either DefaultFormatSettings (when used function without Format parameter) or supplied Format parameter. So it will be something like this: function TryStrToBCD ( const aValue : FmtBCDStringtype; // --- here is not specified Format, so use DefaultFormatSettings var BCD : tBCD ) : Boolean; begin Result:=TryStrToBCD(aValue, BCD, DefaultFormatSettings); end; function TryStrToBCD ( const aValue : FmtBCDStringtype; var BCD : tBCD; const Format: TFormatSettings ) : Boolean; // --- here is explicitly specified Format, so use it ... //here use Format.DecimalSeparator , Format.ThousandSeparator ... I would like if we make progress in this, because then we can continue with other task related to this. Please let me know if you agree with this direction and if yes, then please apply fix in (1) and then I will prepare fix for (2) Thanks -Laco. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
[fpc-devel] RFC: customvariant handling in variants.pp and fmtbcd.pp
Hi, I would like ask for your opinion in this case. I found, that in this sample program is raised Invalid variant ... var bcd1: TBCD; v,v1: variant; s: string; begin bcd1:=2; v1:=varfmtbcdcreate(bcd1); s:=v1; //assigment from customvariant to string is not handled in sysvartolstr() end; I can fix it by following fixs: 1. fmtbcd_castto.diff ... added case when castto varString is requested ... then do not use cast throught varDouble (to avoid lost of precision), but convert directly from TBCD to string 2. variants.pp ... here we must add handling of customvariants into sysvartolstr ... I created helper function TryCastFromCustomVariant which can be used multiple times (now in sysvartolstr and sysvartoreal) ... I isolate in this function code which is required multiple times. I am not sure if 1. is this optimal approach, or is better to put same code repeatedly in sysvartolstrm sysvartoreal and in future in others sysvarto... ? 2. is the name and place of such function good choosen ? Can somebody look at it, and commit what is good and change what is not good ;-) ? Thanks -Laco. --- f:\tmp\fmtbcd.pp.oldMon Mar 21 07:37:34 2011 +++ f:\tmp\fmtbcd.ppWed Mar 23 10:34:38 2011 @@ -4006,9 +3992,18 @@ begin begin VarDataInit(v); try - v.vType:=varDouble; - v.vDouble:=TFMTBcdVarData(Source.vPointer).BCD; - VarDataCastTo(Dest, v, aVarType); //now cast Double to any requested type + if aVarType = varString then + begin +Dest.vType:=varString; +Dest.vString:=nil; + AnsiString(Dest.vString):=BCDToStr(TFMTBcdVarData(Source.vPointer).BCD); + end + else + begin +v.vType:=varDouble; +v.vDouble:=BCDToDouble(TFMTBcdVarData(Source.vPointer).BCD); +VarDataCastTo(Dest, v, aVarType); //now cast Double to any requested type + end; finally VarDataClear(v); end; --- f:\tmp\variants.pp.ori Thu Dec 2 10:03:42 2010 +++ f:\tmp\variants.pp Wed Mar 23 10:32:52 2011 @@ -602,7 +602,6 @@ begin TVarData(V).vType := varEmpty; end; - procedure sysvarclear(var v : Variant); begin if TVarData(v).vType and varComplexType 0 then @@ -611,6 +610,16 @@ begin TVarData(v).vType := varEmpty; end; +function TryCastFromCustomVariant(const v : Variant; const aVarType: TVarType; out Dest: TVarData):boolean; +var Handler: TCustomVariantType; +begin + Result:=FindCustomVariantType(TVarData(v).vType, Handler); + if Result then + begin +VariantInit(Dest); +Handler.CastTo(dest, TVarData(v), aVarType); + end; +end; function Sysvartoint (const v : Variant) : Integer; begin @@ -661,20 +670,15 @@ end; {$ifndef FPUNONE} function sysvartoreal (const v : Variant) : Extended; -var Handler: TCustomVariantType; -dest: TVarData; +var dest: TVarData; begin if VarType(v) = varNull then if NullStrictConvert then VarCastError(varNull, varDouble) else Result := 0 - else if FindCustomVariantType(TVarData(v).vType, Handler) then - begin -VariantInit(dest); -Handler.CastTo(dest, TVarData(v), varDouble); -Result := dest.vDouble; - end + else if TryCastFromCustomVariant(v, varDouble, dest) then +Result := dest.vDouble else Result := VariantToDouble(TVarData(V)); end; @@ -694,12 +698,15 @@ end; procedure sysvartolstr (var s : AnsiString; const v : Variant); +var dest: TVarData; begin if VarType(v) = varNull then if NullStrictConvert then VarCastError(varNull, varString) else s := NullAsStringValue + else if TryCastFromCustomVariant(v, varString, dest) then +s := AnsiString(dest.vString) else S := VariantToAnsiString(TVarData(V)); end; ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] RFC: customvariant handling in variants.pp and fmtbcd.pp
Hi Sergei, I can fix it by following fixs: 1. fmtbcd_castto.diff ... added case when castto varString is requested ... then do not use cast throught varDouble (to avoid lost of precision), but convert directly from TBCD to string 2. variants.pp ... here we must add handling of customvariants into sysvartolstr ... I created helper function TryCastFromCustomVariant which can be used multiple times (now in sysvartolstr and sysvartoreal) ... I isolate in this function code which is required multiple times. I am not sure if 1. is this optimal approach, or is better to put same code repeatedly in sysvartolstrm sysvartoreal and in future in others sysvarto... ? 2. is the name and place of such function good choosen ? Doing what you propose isn't good. Checking for custom variant type is expensive because it involves locking, therefore custom variant handling should be done *after* the standard types. ok The real problem is that the standard types are currently handled in VarUtils.VariantToX functions, which do not depend on Variants unit and cannot use custom variant stuff. yes The correct solution would be to move the code of VariantToX functions to Variants unit, inlining them to sysvartoX functions. But if you try that, you'll discover very soon that VariantChangeTypeEx (non-Windows implementation in varutils.inc) depends on some of them. This is again not correct, because conversion functions called from VariantChangeTypeEx do not need to handle Pascal-specific types and by-reference variants. But a simplifed portion of conversion functions have to stay in VarUtils unit. This is of course a major rewrite, but I'd stay on it, because with a number of quick-fixes we risk to end up with unmaintainable code. ok I agree, but I think, that this is too dificult for me, so I must wait if somebody will do it. So my questions are: 1. is acceptable apply my patch (or some variation of it) to variants.pp as a temporary solution ? (you can add there hint must be chaged, when ...) 2. fix for fmtbcd.pp does not affect above mentioned problem, so should you commit it (if is correct from your POV) to not forget about it ? Thanks -Laco. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] RFC: customvariant handling in variants.pp and fmtbcd.pp
Hi Sergei, Doing what you propose isn't good. Checking for custom variant type is expensive because it involves locking, therefore custom variant handling should be done *after* the standard types. Both committed in r17170, with some changes: great thanks! In fmtbcd.pp, I used VarDataFromStr method instead of assigning individual fields of TVarData; if I understand things correctly, this method exist precisely for such cases. ok thanks, I have attached minor rearangement, consider them please In variants.pp, I used an individual function, with an out-parameter of type AnsiString. Such approach allows to avoid finalization of the intermediate Variant. ok, thank you very much I have looked again at function FindCustomVariantType and I see there : 3590 Result:=(aVarType=CMinVarType); 3591 if Result then So it seems to me, that for standard variant types is control immediately returned, so no performance problem should exist there with entering critical section and so on. Or I missed something ? Laco. procedure TFMTBcdFactory.CastTo(var Dest: TVarData; const Source: TVarData; const aVarType: TVarType); var v: TVarData; begin if Source.vType=VarType then if aVarType = varString then VarDataFromStr(Dest, BCDToStr(TFMTBcdVarData(Source.vPointer).BCD)) else begin VarDataInit(v); try v.vType:=varDouble; v.vDouble:=BCDToDouble(TFMTBcdVarData(Source.vPointer).BCD); VarDataCastTo(Dest, v, aVarType); //now cast Double to any requested type finally VarDataClear(v); end; end else inherited; end;___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
[fpc-devel] Implementing TFmtBCDField - ftFmtBCD and SQLite
Hi, after doing some test with new implementation of TFmtBCDField for TSQLite3Connection connector I encounter this problem: When you declare in SQLite some column as NUMERIC or DECIMAL then this column will have NUMERIC affinity. CREATE TABLE t (d DECIMAL(30,7)); If you insert in such column any numeric value (quoted or unquoted): INSERT INTO t VALUES('123456789123456789.123456'); SQLite converts such numeric value to 8-byte floating point representation (REAL) or 8-byte integer (INTEGER), so: (lost of precision occurs) SELECT * FROM t; returns 123456789123456784 See: http://www.sqlite.org/datatype3.html#affinity A column with NUMERIC affinity may contain values using all five storage classes. When text data is inserted into a NUMERIC column, the storage class of the text is converted to INTEGER or REAL (in order of preference) if such conversion is lossless and reversible. For conversions between TEXT and REAL storage classes, SQLite considers the conversion to be lossless and reversible if the first 15 significant decimal digits of the number are preserved. If the lossless conversion of TEXT to INTEGER or REAL is not possible then the value is stored using the TEXT storage class. No attempt is made to convert NULL or BLOB values. My original understanding was, that when I store big numbers as TEXT and lossless conversion to REAL can not be done, then value will be stored as TEXT, but in meaning in SQLite lossless is: if the first 15 significant decimal digits of the number are preserved (not all digits only first 15!!!) I have asked about this in sqlite-users mailing list (topic storing big numbers into NUMERIC, DECIMAL columns) and results are: (I attach some of comments from sqlite-users mailing list) A.) if we want preserve precision of BCD values we must store them as BLOBs (using sqlite3_bind_blob()) ... see (1) and (2) in attachment (with optimalization like : if BCDPrecision(...) 15 then use sqlite3_bind_blob(...) else sqlite3_bind_double(...) ) Here my test shows, that if I store value like BLOB I still can do select like: SELECT d+100 FROM t; SELECT sum(d) FROM t; SELECT * FROM t WHERE d12345678912345678; (it seems, that SQLite converts BLOB-TEXT-REAL ...of course precision is lost) B.) does not support numbers (big exact numbers), which are not supported by SQLite (SQLite supports only REAL and INTEGER). ... see (3) So DECIMAL, NUMERIC map to ftFloat if decimal places4 (out of range ftBCD) and map to ftLargeInt if decimal places=0 What do you think, which way to go ? -Laco. (1) Here are two options which will let you get the contents back to the original precision: A) Store the values as BLOBs. B) Store the value as TEXT, but add a non-digit to the beginning of each number value, for example X24395734857634756.92384729847239842398423964294298473927 Both methods will prevent SQLite from trying to see the value as a number. Oh and since nobody seems to have pointed it out yet, SQLite doesn't have a NUMERIC or a DECIMAL column type. The types can be found here: http://www.sqlite.org/datatype3.html Putting INTEGER and REAL together gives you NUMERIC, but there's no way to declare a column of that type, just a value. The page actually rehearses your problem, showing when strings containing numeric values can be converted to a number. -- (2) You can store any big-number representation you like as TEXT or BLOB values. The main issue is that you'll lose syntactic sugar: SQLite3 won't be able to treat those as numeric values, therefore it won't be able to compare numerically nor use arithmetic with such values. -- (3) If your goal is to work with any user database created outside of your FreePascal connector then chances are that user will use the same database outside of your FreePascal connector too. And if use declared column as NUMERIC then he probably will expect numbers to be inserted into that column (especially if the data type inside FreePascal is also some sort of number). User also will probably execute some queries that do some arithmetic operations on values in that column. And they will be really surprised to see that not all the data is numbers there. So you better insert everything as numbers, let SQLite transform everything to REAL and lose precision. And tell your users that it's limitation of SQLite and you cannot do anything with it, only suggest to insert big numbers as text.___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] RFC: customvariant handling in variants.pp and fmtbcd.pp
I have attached minor rearangement, consider them please Will do. It's possible to go even further and completely exclude finalization and try..finally block, because the intermediate Variant is always of type Double, which doesn't need finalization. Thanks! I will look forward for your patch. L. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] Implementing TFmtBCDField - ftFmtBCD and SQLite
Simply said: So Sqlite doesn't support real BCD values. Yes, SQLite does not support them native So we can't support it either for Sqlite. It was my question. We can (if we want) partialy add work-arounds: DECIMAL(x,y) if y=0 then map to ftLargeInt (64bit integer) elseif y=4 then map to ftBCD (as it is now) else map to ftFloat (IMHO better than raising exception) More difficult: Sqlite is not a 'normal' sql-database. It has all kind of strange issues, it's own definitions and options. It is impossible to support all these gimmicks in sqldb. I agree, and most horrible is, that in one column you can have any datatype in different rows (in 1st row character data, in 2nd integer and in 3th real numbers and in 4th blob) Sqlite only has very few data-types (the 'affinities') but to be gentle to our users we do support more, only based on the field-type name. Yes and this is IMO good. If user defines column datatype as numeric or integer or float it can be expected, that also data in that column will be in that format So as long as users can't make tables with numeric fields that support more then 15 numbers, we don't have to support bcd-fields. So map decimal to BCD (not float, it will be invalid for values within the supported precision range). If users want to store numbers with an higher precision, that is simply impossible in sqlite. Yes it is impossible in native way ... but we can help him and do necessary conversion in the background ... question is what user expect, when defines column like DECIMAL(15,7) ? If they want to store their numbers in blob-fields, they can simply define a blob field and do so... Yes but BLOB is mapped to TBlobField and there are no methods like AsFloat, AsBCD, AsFMTBCD ... so user must handle all this in their code ... retrieve value convert them etc. , use TField.OnGetText etc. ... it is doable, but not very confort. So where's the problem? (I see the problem of Sqlite not supporting bcd-fields, Yes it is primary problem but the sqldb-problem? What to do in case when user defines column NUMERIC, DECIAML (x,y) where y4 or x15 ? (I do not like raise exception if there is way how to handle this situation ... and also user IMHO does not expect exception) As I wrote we should at least do: DECIMAL(x,y) if y=0 --- ftLargeInt elseif y=4 --- ftBCD else --- ftFloat (or ftString with Size=x+1 ?) But we can go far (this is relative simple to implement and gives maximum transparency and easy to use): if x 15 or y4 --- ftFmtBCD (and here write as BLOB into SQLite3 database in background) elseif y=0 --- ftLargeInt else --- ftBCD Laco. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] Implementing TFmtBCDField - ftFmtBCD and SQLite
No, map to ftfmtbcd, as it should. That will work fine as long as the values are within the sqlite-range. ok. in reading phase no problem (ATM we read using sqlite3_column_text (so SQLite converts all storage classes (integer,real, blob) to string) and then converting to TBCD ... ok (Well, show me the bug: as it is now, he won't get an exception? Just map to ftmbcd) yes now no exception it is ok as is the user will only get an invalid value when he stores a value outside the sqlite-precision scope. Exactly what he would expect when he uses sqlite. Yes. I can live with this, but do not forget, that ATM there is not implemented writting of ftFmtBCD parameters in Procedure TSQLite3Cursor.bindparams(AParams : TParams); So writting never occurs! So there we must add at least ftFmtBCD case, (behind ftbcd) But If we add this code (excuse me, I must offer it) ;-): //it is only pseudo code ftFmtBCD: begin if P.AsFMTBCD.Precision 15 then //we are out-of-range begin str1:=BCDTOStr(P.AsFMTBCD, SQLFormatSettings); checkerror(sqlite3_bind_blob(fstatement,I,pcharstr(str1), length(str1),@freebindstring)); end else begin do1:=P.AsFloat; checkerror(sqlite3_bind_double(fstatement,I,do1)); end; end; // all. Then all cases will be covered and no additional work around are needed. Laco. P.S.: P.AsFMTBCD: http://bugs.freepascal.org/view.php?id=18809 ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
[fpc-devel] Recent changes to TField.SetData
Hi, This fix http://svn.freepascal.org/cgi-bin/viewvc.cgi/trunk/packages/fcl-db/src/base/fields.inc?r1=17199r2=17220 fixes mising call to TField.Validate (before data are written into record buffer) and adds also call to TField.DataChanged (after data are written) But It seems to me, that DataChanged is now called 2 times First in TDataSet descendants in SetFieldData method (see bufdataset.pas, dbf.pas, paradox.pp, meds.pp) and second in above mentioned place. So it would be good remove this call from TDataSet descendants. For example for bufdataset.pas: 1860 if not (State in [dsCalcFields, dsFilter, dsNewValue]) then 1861 DataEvent(deFieldChange, Ptrint(Field)); Laco. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] Behavior of conversion between vardate variants and string in fpc and delphi
Running this code in Delphi 7 gives the exception below: var V: Variant; D: TDateTime; begin ShortDateFormat := 'dd/mm/'; // the problem occurs regardless of the format option V := '20/04/2011'; D := V; Memo1.Lines.Add('Date: ' + DateToStr(D)); // required to avoid dead code elimination end; raised exception class EVariantTypeCastError with message 'Could not convert variant of type (String) into type (Double)' Can someone check with more recent Delphi if this is still true? In DelphiXE: raised exception class EVariantTypeCastError with message 'Could not convert variant of type (UnicodeString) into type (Double)' Laco. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] Behavior of conversion between vardate variants and string in fpc and delphi
So, what should be done? 1) Be totally compatible with Delphi: convert date to string with hardcoded format and raise exception when doing the conversion back? 2) Use the hardcoded format used to convert from vardate variant to string and vice versa? 3) Use shortdateformat to convert from vardate variant to string and vice versa? Point 3 sounds to me as best and logical. This code in DelphiXE: ShortDateFormat := 'dd#mm#'; // the problem occurs regardless of the format option DateSeparator:='#'; V := '20#04#2011'; v1:=varAsType(V, varDate); D:=v1; Writeln('Date: ' + DateToStr(D)); Outputs: Date: 20#04#2011 So it seems, that DelphiXe also uses ShortDateFormat, DateSeparator Laco. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] Recent changes to TField.SetData
Then please move approprate code at least into TCustomBufDataset.SetFieldData Thanks This code was already there. Should the 'Validate' code be moved there too ? Yes. TDataset descendants are responsible to calling Validate, e.g., zeos call it inside TZAbstractRODataset.SetFieldData. I agree, but I do not like idea, that SAME piece of code must be repeated in many descendants of TDataSet (TCustomBufDataSet, TParadox, TMemDataset, TFixedFormatDataSet, TDbf, TCustomSqliteDataset etc.) So it would be good, if we can put 'validate code' into any new method? and call it once from descendants (be precise only from descendants, which are intended for use in FPC, because components which are also for Delphi must do it in Delphi compatible way and can not use this new method) One of the reasons of letting descendants call it it's too improve granularity so Validate can be called in the middle of the routine, as is in zeos, instead to force the call before the TDataset routine. Yes, but I think, that in many cases can be expected, that 'validate' will be called before any other action, It seems, that TDataSet descendants never call inherited TDataSet.SetFieldData(Field: TField; Buffer: Pointer); (because it is empty method) So if we move 'validate code' there then in 'our' descendants we put only {$IFDEF FPC} inherited; {$ENDIF} at first line. This does not affect existing tdataset descendants, and FPC dataset descendants can be adjusted to benefit from this. (I know, it is not perfect solution ;-) but I very dislike repeat same 'validate' code in X places) --or-- introduce any new method (ValidateFieldData ? ;-))) and let tdatsset descendants use it: {$IFDEF FPC} ValidateFieldData(Field: TField; Buffer: Pointer); {$ENDIF} --or-- some smarter solution ? Laco. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] Recent changes to TField.SetData
--or-- introduce any new method (ValidateFieldData ? ;-))) and let tdatsset descendants use it: {$IFDEF FPC} ValidateFieldData(Field: TField; Buffer: Pointer); {$ENDIF} --or-- some smarter solution ? The whole code, which is repeated (and can be put in one place) is: if not (State in [dsEdit, dsInsert, dsFilter, dsCalcFields]) then begin DatabaseErrorFmt(SNotEditing,[Name],self); exit; end; if (Field.FieldNo0) and not (State in [dsSetKey, dsFilter]) then begin if ReadOnly then DatabaseErrorFmt(SReadOnlyField, [Field.DisplayName], Self); Field.Validate(Buffer); end; Laco. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] Recent changes to TField.SetData
The whole code, which is repeated (and can be put in one place) is: if not (State in [dsEdit, dsInsert, dsFilter, dsCalcFields]) then begin DatabaseErrorFmt(SNotEditing,[Name],self); exit; end; if (Field.FieldNo0) and not (State in [dsSetKey, dsFilter]) then begin if Read OnlythenDatabaseErrorFmtSReadOnlyField,[Field.DisplayName], Self); Field.Validate(Buffer); end; You are right in your dislike. I will create a 'BeforeSetFieldData' in TDataset and put the code in there, and the same for 'AfterSetFieldData' with the OnChange code. OK, Then please do not forget commit necessary changes also in other descendants (not only in TCustomBufDataSet but also in TParadox, TMemDataset, TFixedFormatDataSet, TDbf) to completelly fix 'missing onvalidate call' problem. Thanks I am still thinking about this. I have other solution, which is relative simple , puts base logic into base TField methods (so all TDataSet descendants can benefit from it) and does not negatively affect existing TDataSet descendants and does not require introduce new methods (BeforeSetFieldData, AfterSetFieldData). Let's distributes repeating used code as follows: 1. base checks before into procedure TField.SetData(Buffer: Pointer; NativeFormat : Boolean); 820 begin 821 If Not Assigned(FDataset) then 822 DatabaseErrorFmt(SNoDataset,[FieldName]); if not (State in [dsEdit, dsInsert, dsFilter, dsCalcFields]) then //here should be IMO also dsNewValue DatabaseErrorFmt(SNotEditing,[FDataSet.Name],FDataSet); if ReadOnly and (FieldNo0) and not (FDataSet.State in [dsSetKey, dsFilter]) then DatabaseErrorFmt(SReadOnlyField, [DisplayName], Self); 829 FDataSet.SetFieldData(Self,Buffer, NativeFormat); -- 2. into procedure TField.Validate(Buffer: Pointer); 892 begin if FDataSet.State in [dsSetKey, dsFilter] then Exit; 893 If assigned(OnValidate) Then -- 3. after call into procedure TDataSet.SetFieldData(Field: TField; Buffer: Pointer); begin if not (State in [dsCalcFields, dsFilter, dsNewValue]) then DataEvent(deFieldChange, Ptrint(Field)); end; -- And now all what we must do, is put into method SetFieldData in TDataSet descendants one line: Field.Validate(Buffer); and one line at end: inherited; //calls field change ... this is done by all TDataSet descendants in fcl-db as a last thing It is only draft, so some detils may be changed ... ;-) What do you think ? Laco. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] Recent changes to TField.SetData
Small optimalization use dsWriteModes instead of fixed set: - if not (State in [dsEdit, dsInsert, dsFilter, dsCalcFields]) then //here should be IMO also dsNewValue + if not (FDataSet.State in dsWriteModes) then DatabaseErrorFmt(SNotEditing,[FDataSet.Name],FDataSet); if ReadOnly and (FieldNo0) and not (FDataSet.State in [dsSetKey, dsFilter]) then DatabaseErrorFmt(SReadOnlyField, [DisplayName], Self); 829 FDataSet.SetFieldData(Self,Buffer, NativeFormat); -- Laco. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] Recent changes to TField.SetData
Hi, here are diffs with changes, I hope they will be good for all TDataSet descendants (those specific to FPC and also those which are also for use in Delphi) Code which is general (and is used repeatedly) is placed in TField methods and only small code remains which must be placed into each TDataSet descendant. (I patched only TBufDataSet, but later can be updated also other TDataSet descendants ... remove redundant code and add Field.Validate(...)) Thanks -Laco. The whole code, which is repeated (and can be put in one place) is: if not (State in [dsEdit, dsInsert, dsFilter, dsCalcFields]) then begin DatabaseErrorFmt(SNotEditing,[Name],self); exit; end; if (Field.FieldNo0) and not (State in [dsSetKey, dsFilter]) then begin if Read OnlythenDatabaseErrorFmtSReadOnlyField,[Field.DisplayName], Self); Field.Validate(Buffer); end; You are right in your dislike. I will create a 'BeforeSetFieldData' in TDataset and put the code in there, and the same for 'AfterSetFieldData' with the OnChange code. OK, Then please do not forget commit necessary changes also in other descendants (not only in TCustomBufDataSet but also in TParadox, TMemDataset, TFixedFormatDataSet, TDbf) to completelly fix 'missing onvalidate call' problem. Thanks I am still thinking about this. I have other solution, which is relative simple , puts base logic into base TField methods (so all TDataSet descendants can benefit from it) and does not negatively affect existing TDataSet descendants and does not require introduce new methods (BeforeSetFieldData, AfterSetFieldData). Let's distributes repeating used code as follows: 1. base checks before into procedure TField.SetData(Buffer: Pointer; NativeFormat : Boolean); 820 begin 821 If Not Assigned(FDataset) then 822 DatabaseErrorFmt(SNoDataset,[FieldName]); if not (State in [dsEdit, dsInsert, dsFilter, dsCalcFields]) then //here should be IMO also dsNewValue DatabaseErrorFmt(SNotEditing,[FDataSet.Name],FDataSet); if ReadOnly and (FieldNo0) and not (FDataSet.State in [dsSetKey, dsFilter]) then DatabaseErrorFmt(SReadOnlyField, [DisplayName], Self); 829 FDataSet.SetFieldData(Self,Buffer, NativeFormat); -- 2. into procedure TField.Validate(Buffer: Pointer); 892 begin if FData Set.Statein[dsSetKey,dsFilter]thenExit 893 If assigned(OnValidate) Then -- 3. after call into procedure TDataSet.SetFieldData(Field: TField; Buffer: Pointer); begin if not (State in [dsCalcFields, dsFilter, dsNewValue]) then DataEvent(deFieldChange, Ptrint(Field)); end; -- And now all what we must do, is put into method SetFieldData in TDataSet descendants one line: Field.Validate(Buffer); and one line at end: inherited; //calls field change ... this is done by all TDataSet descendants in fcl-db as a last thing It is only draft, so some detils may be changed ... ;-) What do you think ? Laco. --- bufdataset.pas.ori Sun Feb 20 14:31:16 2011 +++ bufdataset.pas Wed Apr 13 09:07:18 2011 @@ -1830,14 +1830,10 @@ var CurrBuff : pointer; NullMask : pbyte; begin - if not (state in [dsEdit, dsInsert, dsFilter, dsCalcFields]) then -begin -DatabaseErrorFmt(SNotEditing,[Name],self); -exit; -end; CurrBuff := GetCurrentBuffer; - If Field.Fieldno 0 then // If = 0, then calculated field or something + If Field.FieldNo 0 then // If = 0, then calculated field or something begin +Field.Validate(Buffer); NullMask := CurrBuff; inc(CurrBuff,FFieldBufPositions[Field.FieldNo-1]); --- fields.inc.ori Wed Apr 13 08:50:56 2011 +++ fields.inc Wed Apr 13 09:05:04 2011 @@ -820,12 +820,10 @@ procedure TField.SetData(Buffer: Pointer begin If Not Assigned(FDataset) then DatabaseErrorFmt(SNoDataset,[FieldName]); - if (FieldNo0) and not (FDataSet.State in [dsSetKey, dsFilter]) then -begin -if ReadOnly then - DatabaseErrorFmt(SReadOnlyField, [DisplayName], Self); -Validate(Buffer); -end; + if not (FDataSet.State in dsWriteModes) then +DatabaseErrorFmt(SNotEditing,[FDataSet.Name],FDataSet); + if ReadOnly and (FieldNo0) and not (FDataSet.State in [dsSetKey, dsFilter]) then +DatabaseErrorFmt(SReadOnlyField, [DisplayName], Self); FDataSet.SetFieldData(Self,Buffer, NativeFormat); end; @@ -890,7 +888,7 @@ end; procedure TField.Validate(Buffer: Pointer); begin - If assigned(OnValidate) Then + If assigned(OnValidate) and not (FDataSet.State in [dsSetKey,dsFilter]) Then begin FValueBuffer:=Buffer; FValidating:=True; ___ fpc-devel maillist - fpc-devel@lists.freepascal.org
Re: [fpc-devel] RFC: customvariant handling in variants.pp and fmtbcd.pp
Hi Sergei, Sorry for the delay, got stuck with other issues... Applied in r17319. Thank you for the patch! It is ok ;-) Thanks. Could I ask why is there needed VarDataInit ? (only for my interest ;-)) Laco. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] RFC: customvariant handling in variants.pp and fmtbcd.pp
Could I ask why is there needed VarDataInit ? (only for my interest ;-)) A good question. Formally it is not needed, but in general initializing variables before use remains a good idea. Here the TVarData is passed to VarDataCastTo, and after initializing we can be sure that VarDataCastTo won't find garbage in remaining 4 bytes of structure if it accesses them for whatever reason. Thanks for explain Laco. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] Recent changes to TField.SetData
/ Michael, // do you plan do something else with this OnValidate problem ? / I thought I had done everything, or did I (again) forget something ? There is IMHO unresolved original problem which is in fact, that some TDataSet descendants implement call to Field.Validate in descendant's SetFieldData (for example ZEOS in procedure TZAbstractRODataset.SetFieldData) So if we leave call to Validate(Buffer) in TField.SetData ( http://svn.freepascal.org/cgi-bin/viewvc.cgi/trunk/packages/fcl-db/src/base/fields.inc?r1=17199r2=17220 ) Then in case of these TDataSet descendants will Validate called twice. (once in TField.SetData and second in descendant's SetFieldData) Please look at diff's which are attached in my email from 13.4.2011. (There are changes which we must/can do to fix it) Thanks -Laco. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
[fpc-devel] Closing bug reports or not ?
Hi, excuse me for this question ;-) Closing bug report is task for reporter of bug or is not (so leave it resolved and bug will close somebody later?) ? Thanks Laco. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
[fpc-devel] SQLite and ftFmtBCD
Hi Joost (and others also ;-), I comment your question about http://bugs.freepascal.org/view.php?id=18809 here. (because I do not know what comment here and what in bug tracker) I see problem in fact, that AsString returns number formated using locale specific DecimalSeparator. So if FmtBCD param will hold value 123456789,123456789 then this value will be written into SQLite3 database. Which is IMO not very good, becuase SQL standard and also SQLite expects, that numeric values will always have point as decimal separator. So my suggestion is in case of ftFMTBCD param use something like: ftFmtBCD: begin str1:= BCDToStr(P.AsFMTBCD, SQLFormatSettings); //this depend on bug 18807 checkerror(sqlite3_bind_text(fstatement,I,pcharstr(str1), length(str1),@freebindstring)); end; or better: ftFmtBCD: begin if P.AsFMTBCD.Precision 15 then //we are out of REAL range, so we must bind as BLOB begin str1:=BCDTOStr(P.AsFMTBCD, SQLFormatSettings); checkerror(sqlite3_bind_blob(fstatement,I,pcharstr(str1), length(str1), @freebindstring)); end else begin do1=P.AsFloat checkerror(sqlite3_bind_double(fstatement,I,do1)); end; end; about SQLFormatSettings see: http://bugs.freepascal.org/view.php?id=17188 -- Other questions: Isn't it better to use '4' instead of 255/0 as default value for the scale? SQL standard says, that if scale is ommited then scale is 0 ... imho it is better to follow standard Isn't it better to map to a ftInteger/ftLargeInt field when size1=0? Yes IMHO it is better, at least because ftLargeInt (int64) can hold more significant digits (left to decimal point) than ftBCD (currency) But what if user defines NUMERIC(30,0) then we have two options: 1. say sorry SQLite does not support this, so we map to ftLargeInt 2. or map to ftFmtBCD if (scale4) or (precision18) if precision18 then ftFmtBCD else if scale=0 then ftLargeInt else if scale=4 then ftBCD else ftFmtBCD -Laco. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] SQLite and ftFmtBCD
I'll look at this solution. I'm a little bit confused about SQLFormatSettings and why it was implemented as it is now. I'll have to investigate this. IMO for locale independent formatting numeric, date, time values according to sql standard or better: ftFmtBCD: begin if P.AsFMTBCD.Precision 15 then //we are out of REAL range, so we must bind as BLOB begin s tr1=BCDTOStrP.AsFMTBCD,SQLFormatSettings); checkerror(sqlite3_bind_blob(fstatement,I,pcharstr(str1), length(str1), @freebindstring)); end else begin d o1=P.AsFloat checkerror(sqlite3_bind_double(fstatement,I,do1)); end; end; This is wrong. There are some values which can't be written as floats, but have precision15. Yes, then my mystake then we can/must use: ftFmtBCD: begin str1:=BCDTOStr(P.AsFMTBCD,SQLFormatSettings); //bind as BLOB, because when bind as TEXT, SQLite always will convert to REAL or INTEGER, //which can lead to lost of precision checkerror(sqlite3_bind_blob(fstatement,I,pcharstr(str1), length(str1), @freebindstring)); end; But this particular piece of code is used when an invalid value is supplied, like 'DECIMAL(10,A)'. yes, in this case we can default to 4 (but A as scale is in all cases something very strange) The case that the value is omitted is handled elsewhere. ok, in this case we should use 0 Isn't it better to map to a ftInteger/ftLargeInt field when size1=0? Yes IMHO it is better, at least because ftLargeInt (int64) can hold more significant digits (left to decimal point) than ftBCD (currency) But what if user defines NUMERIC(30,0) then we have two options: 1. say sorry SQLite does not support this, so we map to ftLargeInt Nah... 2. or map to ftFmtBCD if (scale4) or (precision18) if precision18 then ftFmtBCD else if scale=0 then ftLargeInt else if scale=4 then ftBCD else ftFmtBCD Can you create a patch which does this? Yes, tomorow I will do it Laco. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] SQLite and ftFmtBCD
or better: ftFmtBCD: begin if P.AsFMTBCD.Precision 15 then //we are out of REAL range, so we must bind as BLOB begin s tr1=BCDTOStrP.AsFMTBCD,SQLFormatSettings); checkerror(sqlite3_bind_blob(fstatement,I,pcharstr(str1), length(str1), @freebindstring)); end else begin d o1=P.AsFloat checkerror(sqlite3_bind_double(fstatement,I,do1)); end; end; This is wrong. There are some values which can't be written as floats, but have precision15. Joost, look at ftBCD, ftCurrency they are also written as floats So if there is it acceptable, then I would say, that also in this case is it acceptable, isn't it ? (I do not say, that it is perfect) Can you create a patch which does this? Patch is attached. DECIMAL - ftBCD (if precision and scale is not supplied, then scale=0) DECIMAL(p) = DECIMAL(p,0) = DECIMAL(p,nonnumeric) - if p=18 then ftLargeInt else ftFmtBCD DECIMAL(p,s) - if s4 or p-s14 then ftFmtBCD (number does not fit into currency) -Laco. --- sqlite3conn.pp.ori Wed May 11 07:22:28 2011 +++ sqlite3conn.pp Wed May 11 08:58:48 2011 @@ -347,11 +347,35 @@ var i : integer; FN,FD : string; ft1 : tfieldtype; - size1 : word; + size1, size2 : integer; ar1 : TStringArray; fi: integer; st: psqlite3_stmt; - + + function ExtractPrecisionAndScale(decltype: string; var precision, scale: integer): boolean; + var p: integer; + begin + p:=pos('(', decltype); + Result:=p0; + if not Result then Exit; + System.Delete(decltype,1,p); + p:=pos(')', decltype); + Result:=p0; + if not Result then Exit; + decltype:=copy(decltype,1,p-1); + p:=pos(',', decltype); + if p=0 then + begin + precision:=StrToIntDef(decltype, precision); + scale:=0; + end + else + begin + precision:=StrToIntDef(copy(decltype,1,p-1), precision); + scale:=StrToIntDef(copy(decltype,p+1,length(decltype)-p), scale); + end; + end; + begin st:=TSQLite3Cursor(cursor).fstatement; for i:= 0 to sqlite3_column_count(st) - 1 do @@ -379,27 +403,19 @@ begin size1:=0; case ft1 of ftString: begin -fi:=pos('(',FD); -if (fi0) then - begin - System.Delete(FD,1,fi); - fi:=pos(')',FD); - size1:=StrToIntDef(trim(copy(FD,1,fi-1)),255); - if size1 dsMaxStringSize then size1 := dsMaxStringSize; - end -else size1 := 255; +size1 := 255; //sql: if length is omitted then length is 1 +size2 := 0; +ExtractPrecisionAndScale(FD, size1, size2); +if size1 dsMaxStringSize then size1 := dsMaxStringSize; end; ftBCD:begin -fi:=pos(',',FD); -if (fi0) then - begin - System.Delete(FD,1,fi); - fi:=pos(')',FD); - size1:=StrToIntDef(trim(copy(FD,1,fi-1)),255); - if size14 then -ft1 := ftFMTBcd; - end -else size1 := 4; +size2 := 18; //sql: if a precision is omitted, then use implementation-defined +size1 := 0; //sql: if a scale is omitted then scale is 0 +ExtractPrecisionAndScale(FD, size2, size1); +if (size2=18) and (size1=0) then + ft1:=ftLargeInt +else if (size2-size114) or (size14) then + ft1:=ftFmtBCD; end; ftUnknown : DatabaseError('Unknown record type: '+FN); end; // Case ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] Bug in IBConnection?
this error message isc_shutdown is throw during isc_attach_database and so it seems, that your database is in shutdown mode (which prevents you attach ... but I do not understand why you can success fuly attach using ssh?) See http://www.firebirdnews.org/?p=234 http://www.destructor.de/firebird/gfix.htm Laco. -database /usr/path_to_database/TEST.IB shutdown $00488EFB $0048A1E1 $00489C98 What can be causing this error? ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
[fpc-devel] TField.OldValue
Hi *, I have 2 questions, which I divide into 2 emails. 1st is about TField.OldValue and Delphi compatibility. Please look at small attached program (for SQLite3). In Delphi (with TClientDataSet and dbExpress) outputs: 1. Field.OnValidate: OldValue=N; Value=N; NewValue=N 2. Field.OnChange: OldValue=O; Value=N; NewValue=N 3. BeforePost: OldValue=O; Value=N; NewValue=N 4. AfterPost: OldValue=O; Value=N; NewValue=N 5. Before ApplyUpdates: OldValue=O; Value=N; NewValue=N 6. After ApplyUpdates: OldValue=N; Value=N; NewValue=N In FPC: 1. Field.OnValidate: OldValue=N; Value=N; NewValue=N 2. Field.OnChange: OldValue=null; Value=N; NewValue=N 3. BeforePost: OldValue=null; Value=N; NewValue=N 4. AfterPost: OldValue=O; Value=N; NewValue=N 5. Before ApplyUpdates: OldValue=O; Value=N; NewValue=N 6. After ApplyUpdates: OldValue=null; Value=N; NewValue=N As you can see, there are differences in 2,3,6, where in FPC OldValue is NULL but in Delphi is it old value. Dou you think, that it is bug ? (at least it makes impossible compare OldValue and Value in BeforePost event handler and take some action when some field changes) TIA L. program testOldValue; {$mode objfpc}{$H+} uses {$IFDEF UNIX}{$IFDEF UseCThreads} cthreads, {$ENDIF}{$ENDIF} Classes, SysUtils, CustApp, db, sqlite3conn, sqldb, variants; type { TtestOldValue } TtestOldValue = class(TCustomApplication) protected procedure DoRun; override; public constructor Create(TheOwner: TComponent); override; destructor Destroy; override; procedure WriteHelp; virtual; private Forder: integer; procedure Show(Msg: string; Field: TField); procedure QfieldValidate(Sender: TField); procedure QfieldChange(Sender: TField); procedure QBeforePost(DataSet: TDataSet); procedure QAfterPost(DataSet: TDataSet); end; { SQLite3Test } procedure TtestOldValue.DoRun; var ErrorMsg: String; Conn: TSQLite3Connection; Tran: TSQLTransaction; s: string; Q: TSQLQuery; begin // quick check parameters ErrorMsg:=CheckOptions('h','help'); if ErrorMsg'' then begin ShowException(Exception.Create(ErrorMsg)); Terminate; Exit; end; // parse parameters if HasOption('h','help') then begin WriteHelp; Terminate; Exit; end; Conn:=TSQlite3Connection.Create(Self); Conn.DatabaseName:='test.db'; Tran:=TSQLTransaction.Create(Self); Tran.DataBase:=Conn; Conn.Open; Conn.ExecuteDirect('CREATE TEMPORARY TABLE t (int_field INTEGER PRIMARY KEY, str_field varchar(1))'); Conn.ExecuteDirect('INSERT INTO t VALUES(1, ''O'')'); Q:=TSQLQuery.Create(Self); Q.Name:='SQLQuery1'; Q.DataBase:=Conn; Q.Transaction:=Tran; Q.BeforePost:=@QBeforePost; Q.AfterPost:=@QAfterPost; Q.SQL.Text:='SELECT * FROM t'; Q.Open; Q.Fields[1].OnValidate:=@QfieldValidate; Q.Fields[1].OnChange :=@QfieldChange; Forder:=1; {Q.AppendRecord([1,'O']); Show('Before ApplyUpdates', Q.Fields[1]); Q.ApplyUpdates; Show('After ApplyUpdates', Q.Fields[1]); Tran.CommitRetaining; } Forder:=1; Q.Edit; Q.Fields[1].Value:='N'; Q.Post; Show('Before ApplyUpdates', Q.Fields[1]); Q.ApplyUpdates; Show('After ApplyUpdates', Q.Fields[1]); Tran.CommitRetaining; Q.Close; Tran.Commit; Conn.Close; Q.Free; Tran.Free; Conn.Free; readln; // stop program loop Terminate; end; constructor TtestOldValue.Create(TheOwner: TComponent); begin inherited Create(TheOwner); StopOnException:=true; end; destructor TtestOldValue.Destroy; begin inherited Destroy; end; procedure TtestOldValue.WriteHelp; begin { add your help code here } writeln('Usage: ',ExeName,' -h'); end; procedure TtestOldValue.Show(Msg: string; Field: TField); function VarToStr2(v:variant):string; begin if VarIsNull(v) then Result:='null' else Result:=VarToStr(v); end; begin writeln( format('%d. %s: OldValue=%s; Value=%s; NewValue=%s', [Forder, Msg, VarToStr2(Field.OldValue), VarToStr2(Field.Value), VarToStr2(Field.NewValue)]) ); { writeln( format('%d. %s: DataSet=%s; Field=%s; OldValue=%s; Value=%s; NewValue=%s', [Forder, Msg, Field.DataSet.Name, Field.FieldName, VarToStr(Field.OldValue), VarToStr(Field.Value), VarToStr(Field.NewValue)]) ); } inc(Forder); end; procedure TtestOldValue.QfieldValidate(Sender: TField); begin Show('Field.OnValidate', Sender); end; procedure TtestOldValue.QfieldChange(Sender: TField); begin Show('Field.OnChange', Sender); end; procedure TtestOldValue.QBeforePost(DataSet: TDataSet); begin Show('BeforePost', DataSet.Fields[1]); end; procedure TtestOldValue.QAfterPost(DataSet: TDataSet); begin Show('AfterPost', DataSet.Fields[1]); end; var Application: TtestOldValue; {$R *.res} begin Application:=TtestOldValue.Create(nil); Application.Run; Application.Free; end. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org
[fpc-devel] Inserting first record
This is second email. Can somebody confirm, that there is Access Violation when we insert (or append) first row into empty dataset ? (or I missed something?) You can use attached program. TIA L. program testOldValue; {$mode objfpc}{$H+} uses {$IFDEF UNIX}{$IFDEF UseCThreads} cthreads, {$ENDIF}{$ENDIF} Classes, SysUtils, CustApp, db, sqlite3conn, sqldb, variants; type { TtestOldValue } TtestOldValue = class(TCustomApplication) protected procedure DoRun; override; public constructor Create(TheOwner: TComponent); override; destructor Destroy; override; procedure WriteHelp; virtual; private Forder: integer; procedure Show(Msg: string; Field: TField); procedure QfieldValidate(Sender: TField); procedure QfieldChange(Sender: TField); procedure QBeforePost(DataSet: TDataSet); procedure QAfterPost(DataSet: TDataSet); end; { SQLite3Test } procedure TtestOldValue.DoRun; var ErrorMsg: String; Conn: TSQLite3Connection; Tran: TSQLTransaction; s: string; Q: TSQLQuery; begin Conn:=TSQlite3Connection.Create(Self); Conn.DatabaseName:='test.db'; Tran:=TSQLTransaction.Create(Self); Tran.DataBase:=Conn; Conn.Open; Conn.ExecuteDirect('CREATE TEMPORARY TABLE t (int_field INTEGER PRIMARY KEY, str_field varchar(1))'); //Conn.ExecuteDirect('INSERT INTO t VALUES(1, ''O'')'); Q:=TSQLQuery.Create(Self); Q.Name:='SQLQuery1'; Q.DataBase:=Conn; Q.Transaction:=Tran; Q.BeforePost:=@QBeforePost; Q.AfterPost:=@QAfterPost; Q.SQL.Text:='SELECT * FROM t'; Q.Open; Q.Fields[1].OnValidate:=@QfieldValidate; Q.Fields[1].OnChange :=@QfieldChange; Forder:=1; Q.InsertRecord([1,'O']); Show('Before ApplyUpdates', Q.Fields[1]); Q.ApplyUpdates; Show('After ApplyUpdates', Q.Fields[1]); Tran.CommitRetaining; Forder:=1; Q.Edit; Q.Fields[1].Value:='N'; Q.Post; Show('Before ApplyUpdates', Q.Fields[1]); Q.ApplyUpdates; Show('After ApplyUpdates', Q.Fields[1]); Tran.CommitRetaining; Q.Close; Tran.Commit; Conn.Close; Q.Free; Tran.Free; Conn.Free; readln; // stop program loop Terminate; end; constructor TtestOldValue.Create(TheOwner: TComponent); begin inherited Create(TheOwner); StopOnException:=true; end; destructor TtestOldValue.Destroy; begin inherited Destroy; end; procedure TtestOldValue.WriteHelp; begin { add your help code here } writeln('Usage: ',ExeName,' -h'); end; procedure TtestOldValue.Show(Msg: string; Field: TField); function VarToStr2(v:variant):string; begin if VarIsNull(v) then Result:='null' else Result:=VarToStr(v); end; begin writeln( format('%d. %s: OldValue=%s; Value=%s; NewValue=%s', [Forder, Msg, VarToStr2(Field.OldValue), VarToStr2(Field.Value), VarToStr2(Field.NewValue)]) ); { writeln( format('%d. %s: DataSet=%s; Field=%s; OldValue=%s; Value=%s; NewValue=%s', [Forder, Msg, Field.DataSet.Name, Field.FieldName, VarToStr(Field.OldValue), VarToStr(Field.Value), VarToStr(Field.NewValue)]) ); } inc(Forder); end; procedure TtestOldValue.QfieldValidate(Sender: TField); begin Show('Field.OnValidate', Sender); end; procedure TtestOldValue.QfieldChange(Sender: TField); begin Show('Field.OnChange', Sender); end; procedure TtestOldValue.QBeforePost(DataSet: TDataSet); begin Show('BeforePost', DataSet.Fields[1]); end; procedure TtestOldValue.QAfterPost(DataSet: TDataSet); begin Show('AfterPost', DataSet.Fields[1]); end; var Application: TtestOldValue; {$R *.res} begin Application:=TtestOldValue.Create(nil); Application.Run; Application.Free; end. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] Inserting first record
This is second email. Can somebody confirm, that there is Access Violation when we insert (or append) first row into empty dataset ? (or I missed something?) You can use attached program. Is the problem only with sqlite ? No, I can reproduce it also for example with MySQL. But exception is somehow connected with printing (accessing) OldValue ... when I ommit query to this property, then no exception occurs So It seems, that there must be fill more conditions: 1. Empty dataset 2. accessing OldValue ... If you can, try my test program with your database. TIA -Laco. Michael. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] Inserting first record
Here is attached debug output with {$DEFINE DSDebug}. It seems, that exception is related to Append/Insert (it does not depend if dataset is empty before or not) followed by accesing OldValue ... Setting current record to0 Post: Browse mode set Active buffer requested. Returning:0 exception at 0045C732: Access violation. SetBufListSize: -1 Freeing buffers :11 SetBufListSize: Final FBufferCount=-1 L. TFieldDef.Create : int_field(1) TFieldDef.Create : str_field(2) Creating fields Count : 2 Def 0 : int_field(1) Def 1 : str_field(2) About to create fieldint_field Creating field int_field TFieldDef.CReateField : Trying to set dataset TFieldDef.CReateField : Result Fieldno : 1 Self : 1 Setting dataset About to create fieldstr_field Creating field str_field TFieldDef.CReateField : Trying to set dataset TFieldDef.CReateField : Result Fieldno : 2 Self : 2 Setting dataset Found field int_field Calling internal open Calling RecalcBufListSize Recalculating buffer list size - check cursor Recalculating buffer list size Setting buffer list size SetBufListSize: 10 Reallocating memory :44 Filling memory :48 Filled memory : Assigning buffers :40 Assigned buffers 0 :40 SetBufListSize: Final FBufferCount=10 Getting next buffers Getting next record(s), need :10 Getting next record. Internal RecordCount : 0 Result getting next record : TRUE Getting next record. Internal RecordCount : 1 Result getting next record : FALSE Result Getting next record(S), GOT :1 Getting previous record(s), need :10 GetPriorRecord: Getting previous record Setting current record to0 Result getting prior record : FALSE SetBufferCount: FActiveRecord=0 FCurrentRecord=-1 FBufferCount= 10 FRecordCount=1 going to insert mode Active buffer requested. Returning:0 Active buffer requested. Returning:0 Active buffer requested. Returning:0 Done with append Active buffer requested. Returning:0 Active buffer requested. Returning:0 1. Field.OnValidate: OldValue=O; Value=O; NewValue=O Active buffer requested. Returning:0 Active buffer requested. Returning:0 Active buffer requested. Returning:0 2. Field.OnChange: OldValue=null; Value=O; NewValue=O Post: checking required fields Active buffer requested. Returning:0 Active buffer requested. Returning:0 Active buffer requested. Returning:0 3. BeforePost: OldValue=null; Value=O; NewValue=O Trying to do Trying : updatecursorpos Setting current record to0 Trying to do it Active buffer requested. Returning:0 Active buffer requested. Returning:0 Active buffer requested. Returning:0 Active buffer requested. Returning:0 Active buffer requested. Returning:0 Post: Internalpost succeeded Resync called Getting next record(s), need :10 Getting next record. Internal RecordCount : 1 Result getting next record : TRUE Getting next record. Internal RecordCount : 2 Result getting next record : FALSE Result Getting next record(S), GOT :1 Getting previous record(s), need :10 GetPriorRecord: Getting previous record Setting current record to0 Result getting prior record : FALSE Setting current record to0 Post: Browse mode set Active buffer requested. Returning:0 exception at 0045C732: Access violation. SetBufListSize: -1 Freeing buffers :11 SetBufListSize: Final FBufferCount=-1 ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] Inserting first record
May be like this ? Thanks. Laco. On Thu, 2011-06-09 at 11:49 +0200, LacaK wrote: Here is attached debug output with {$DEFINE DSDebug}. It seems, that exception is related to Append/Insert (it does not depend if dataset is empty before or not) followed by accesing OldValue Can't you just post the backtrace? Joost. Program received signal SIGSEGV, Segmentation fault. 0x0045c772 in GETFIELDISNULL (NULLMASK=0x0, X=1) at C:/Programy/lazarus/fpc/2.5.1/source/packages/fcl-db/src/base/bufdataset.pas:686 686 result := ord(NullMask[x div 8]) and (1 shl (x mod 8)) 0 (gdb) backtrace #0 0x0045c772 in GETFIELDISNULL (NULLMASK=0x0, X=1) at C:/Programy/lazarus/fpc/2.5.1/source/packages/fcl-db/src/base/bufdataset.pas:686 #1 0x0045f085 in TCUSTOMBUFDATASET__GETFIELDDATA (FIELD=0x6200c4, BUFFER=0x16bdc00, this=error reading variable) at C:/Programy/lazarus/fpc/2.5.1/source/packages/fcl-db/src/base/bufdataset.pas:1797 #2 0x0045efe6 in TCUSTOMBUFDATASET__GETFIELDDATA (FIELD=0x6200c4, BUFFER=0x16bdc00, NATIVEFORMAT=true, this=error reading variable) at C:/Programy/lazarus/fpc/2.5.1/source/packages/fcl-db/src/base/bufdataset.pas:1766 #3 0x00433441 in TFIELD__GETDATA (BUFFER=0x16bdc00, NATIVEFORMAT=true, this=error reading variable) at C:/Programy/lazarus/fpc/2.5.1/source/packages/fcl-db/src/base/fields.inc:566 #4 0x00433389 in TFIELD__GETDATA (BUFFER=0x16bdc00, this=error reading variable) at C:/Programy/lazarus/fpc/2.5.1/source/packages/fcl-db/src/base/fields.inc:551 #5 0x00434c68 in TSTRINGFIELD__GETVALUE (AVALUE=0x0, this=error reading variable) at C:/Programy/lazarus/fpc/2.5.1/source/packages/fcl-db/src/base/fields.inc:1102 #6 0x00434a98 in TSTRINGFIELD__GETASVARIANT (this=error reading variable, result=...) at C:/Programy/lazarus/fpc/2.5.1/source/packages/fcl-db/src/base/fields.inc:1066 #7 0x00433036 in TFIELD__GETOLDVALUE (this=error reading variable, result=...) at C:/Programy/lazarus/fpc/2.5.1/source/packages/fcl-db/src/base/fields.inc:474 #8 0x00401cde in TTESTOLDVALUE__SHOW (MSG=0x46e3c0 'Before ApplyUpdates', FIELD=0x6200c4, this=error reading variable) at testOldValue.pas:128 #9 0x00401840 in TTESTOLDVALUE__DORUN (this=error reading variable) at testOldValue.pas:71 #10 0x0042b124 in CUSTAPP_TCUSTOMAPPLICATION_$__RUN () #11 0x00401f62 in main () at testOldValue.pas:163 ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] Inserting first record
Very similar to my fix, which I did minute ago. We can more cleanup code by removing unneeded parts. Please look at attached patch. Thanks L. PS1: Yes it fixes AV PS2: But still remains OldValue=null problem (see me 1st email) Hi, I committed a possible fix in rev. 17704. Please test. Michael. On Thu, 9 Jun 2011, LacaK wrote: May be like this ? Thanks. Laco. On Thu, 2011-06-09 at 11:49 +0200, LacaK wrote: Here is attached debug output with {$DEFINE DSDebug}. It seems, that exception is related to Append/Insert (it does not depend if dataset is empty before or not) followed by accesing OldValue Can't you just post the backtrace? Joost. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel --- bufdataset.pas.ori Thu Jun 09 13:37:02 2011 +++ bufdataset.pas Thu Jun 09 13:40:18 2011 @@ -1803,29 +1803,18 @@ begin if state = dsOldValue then begin if not GetActiveRecordUpdateBuffer then - begin - // There is no old value available - result := false; - exit; - end; -currbuff := FUpdateBuffer[FCurrentUpdateBuffer].OldValuesBuffer; + Exit; // There is no old value available +CurrBuff := FUpdateBuffer[FCurrentUpdateBuffer].OldValuesBuffer; end else CurrBuff := GetCurrentBuffer; - if not assigned(CurrBuff) then -begin -result := false; -exit; -end; + if not assigned(CurrBuff) then Exit; If Field.Fieldno 0 then // If = 0, then calculated field or something similar begin -if GetFieldIsnull(pbyte(CurrBuff),Field.Fieldno-1) then - begin - result := false; - exit; - end; +if GetFieldIsNull(pbyte(CurrBuff),Field.FieldNo-1) then + Exit; if assigned(buffer) then begin inc(CurrBuff,FFieldBufPositions[Field.FieldNo-1]); ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
[fpc-devel] fcl-db test suite
Hi *, I am now playing with test suite for fcl-db. I encounter, that for every test in testfieldtypes.pas is repeatedly called InitialiseDBConnector in toolsunit.pas (because of procedure TTestFieldTypes.SetUp), which set-ups testValues and create instance of TSQLDBConnector (which creates instance of TSQLConnection and TSQLTransaction etc.) I guess, that to avoid it, there was introduced ref-counting mechanism in: http://svn.freepascal.org/cgi-bin/viewvc.cgi/trunk/packages/fcl-db/tests/toolsunit.pas?r1=15388r2=15387pathrev=15388 But it does not work, because global variable DBConnectorRefCount is incremented in procedure InitialiseDBConnector after test: if DBConnectorRefCount0 then exit; So variable DBConnectorRefCount will never be 1 Joost, Michael what do you think about it ? TIA -Laco. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] divide bcd's
Hi Joost, for me: 100/1=10 --error 10/1=10 100/10=10 1000/1=10 --error 1000/10=10 --error 1000/100=10 100/2=50 1007/5=201.4 -Laco. Hi all, Dividing BCD's doesn't go wel: 100/1=10 100/2=overflow 1007/5=overflow It's all in this function in the FmtBCD unit: procedure BCDDivide ( const Dividend, Divisor : tBCD; var BCDout : tBCD ); I've tried to understand how the code works. I think it tries to implement the algorithm as described here: http://media.digikey.com/PDF/Reference%20Design/Digi-Key%20DDS%20group/DKAN0003A_BCD_Division.pdf But I can't follow. Florian checked in the original code. Did he wrote it himself? It could be that there's just a small problem with an index or something. But I can't find it. Maybe someone else can. If not, I think we should rewrite the whole function. Joost. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] divide bcd's
Hi Joost, try attached patch. For me it works as expected. -Laco. Maybe someone else can. If not, I think we should rewrite the whole function. Joost. --- fmtbcd.pp.ori Mon Jun 20 07:10:16 2011 +++ fmtbcd.pp Mon Jun 20 07:51:26 2011 @@ -2205,8 +2205,6 @@ writeln; bh1[True] := null_.bh; FlipFlop := False; fdset := p 0; - if fdset -then bh.FDig := 0; add := 0; nz := True; while nz do @@ -2284,9 +2282,6 @@ if p 3 then halt; nLDig := 0; ue := 0; dd := Singles[lFDig] DIV ( bh2.Singles[lFDig - p] + 1 ); -{ -dd := 1; -} if dd 1 then dd := 1; { @@ -2316,21 +2311,10 @@ writeln ( 'p=', p, ' dd=', dd, ' lFdig=' end; } end; -sf := False; -nfdig := lfdig; -nldig := lldig; +sf := False; +nFDig := lFDig; +nLDig := lLDig; Inc ( Add, dd ); -if NOT fdset - then begin -bh.FDig := p; -fdset := True; - end; -if bh.LDig p - then begin -bh.LDig := p; -if ( bh.LDig - bh.FDig ) Succ ( MaxFmtBCDFractionSize ) - then nz := False; - end; if sf then nz := False else begin @@ -2346,6 +2330,19 @@ writeln ( 'p=', p, ' dd=', dd, ' lFdig=' end; if Add 0 then begin + +if NOT fdset + then begin +bh.FDig := p; +fdset := True; + end; +if bh.LDig p + then begin +bh.LDig := p; +if ( bh.LDig - bh.FDig ) Succ ( MaxFmtBCDFractionSize ) + then nz := False; + end; + i4 := p; while ( Add 0 ) AND ( i4 = bh.FDig ) do begin program BCDDIV; {$mode objfpc}{$H+} uses {$IFDEF UNIX}{$IFDEF UseCThreads} cthreads, {$ENDIF}{$ENDIF} Classes { you can add units after this },FmtBCD; {$R *.res} var bcd1,bcd2,bcd3:TBCD; begin bcd1:=1000; bcd2:=1000; BCDDivide(bcd1,bcd2,bcd3); writeln(bcdtostr(bcd1), '/', bcdtostr(bcd2), '=', bcdtostr(bcd3)); bcd1:=1000; bcd2:=100; BCDDivide(bcd1,bcd2,bcd3); writeln(bcdtostr(bcd1), '/', bcdtostr(bcd2), '=', bcdtostr(bcd3)); bcd2:=10; BCDDivide(bcd1,bcd2,bcd3); writeln(bcdtostr(bcd1), '/', bcdtostr(bcd2), '=', bcdtostr(bcd3)); bcd2:=1; BCDDivide(bcd1,bcd2,bcd3); writeln(bcdtostr(bcd1), '/', bcdtostr(bcd2), '=', bcdtostr(bcd3)); bcd1:=100; bcd2:=2; BCDDivide(bcd1,bcd2,bcd3); writeln(bcdtostr(bcd1), '/', bcdtostr(bcd2), '=', bcdtostr(bcd3)); bcd1:=1007; bcd2:=5; BCDDivide(bcd1,bcd2,bcd3); writeln(bcdtostr(bcd1), '/', bcdtostr(bcd2), '=', bcdtostr(bcd3)); bcd1:=11000; bcd2:=11; BCDDivide(bcd1,bcd2,bcd3); writeln(bcdtostr(bcd1), '/', bcdtostr(bcd2), '=', bcdtostr(bcd3)); bcd1:=11; bcd2:=11000; BCDDivide(bcd1,bcd2,bcd3); writeln(bcdtostr(bcd1), '/', bcdtostr(bcd2), '=', bcdtostr(bcd3)); bcd1:=11; bcd2:=11; BCDDivide(bcd1,bcd2,bcd3); writeln(bcdtostr(bcd1), '/', bcdtostr(bcd2), '=', bcdtostr(bcd3)); readln; end. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] divide bcd's
To not forget, I have reported it also in bug tracker http://bugs.freepascal.org/view.php?id=19636 -Laco. Hi Joost, try attached patch. For me it works as expected. -Laco. Maybe someone else can. If not, I think we should rewrite the whole function. Joost. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] MySQL 5.1 and Double (trouble)
Andrew Brunner wrote / napísal(a): On Mon, Jul 11, 2011 at 3:02 AM, Mark Morgan Lloyd markmll.fpc-de...@telemetry.co.uk wrote: 1.) Update Value : 40734.825668912039 2.) Actual Value after update : 40734.8256689120 3.) Actual Value on read :40734.825668912003 Does MySQL come with an official program that you can use to run queries manually? What happens when you use it to store and retrieve that number? 1.) is a value declared as double and viewed under GDB. 2.) is a value viewed in table data in MySQL Console App under Linux. 3.) Is the value retrieved from the table by the Application using the Select statement and Fields.FieldByName(field_name).AsFloat() I am still experiencing this issue and seeking alternatives b/c I'm using all 12 digits - and am expecting all 12 digits. Can someone update the (Fields.Data variant as double) with a binary send instead of converting to a string? IMO it will require use in mysqlconn.inc new API prepare family functions introduced in MySQL 5 http://dev.mysql.com/doc/refman/5.0/en/c-api-prepared-statement-function-overview.html In current implementation (backward compatible with older MySQL versions) there is no only problem with sending values, but also retrieved values are strings (see http://dev.mysql.com/doc/refman/5.0/en/mysql-fetch-row.html) -Laco. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] negative TDateTime values and MinDateTime
Jonas Maebe wrote / napísal(a): On 02 Aug 2011, at 13:45, LacaK wrote: What do you think, can we change MinDateTime from -693593.0 to -693594.0; (to accept 01/01/0001 23:59:59.999) http://www.mail-archive.com/fpc-devel@lists.freepascal.org/msg07989.html Thanks, it seems, that Joost in 2007 has falling in same problem as I now, when working on fcl-db test suite. (now I catch this also when working on fcl-db test suite) I guess, that he has wrote tests for dates '01/01/0001' and now I am writting test for datetimes '01/01/0001 00:00:01' to '01/01/0001 23:59:59'. So if this constant can not be changed, then I must write workaround for date '01/01/0001' and do not add time part to this date. L. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] negative TDateTime values and MinDateTime
My favorite is the really natural one: Plank-time count since the Big Bang. Here supposedly we don't need negative values., Good joke! ;-))) (but nobody knows, when it was (how many mld. years ago) and many doubts, that it is real fact) -Laco. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] negative TDateTime values and MinDateTime
Felipe Monteiro de Carvalho wrote / napísal(a): On Wed, Aug 3, 2011 at 6:55 AM, LacaK la...@zoznam.sk wrote: So if this constant can not be changed, then I must write workaround for date '01/01/0001' and do not add time part to this date. The constant was already changed once, and no-one complained in the following years, so my guess is that it could be changed again I think so also. But my hotfix for this moment is skip testing datetimes '0001-01-01' with time portion. As you can view here http://bugs.freepascal.org/view.php?id=19878 in toolsunit.diff SQL standard ofcourse allows datetimes from '0001-01-01 00:00:00' to '0001-01-01 23:59:59' -Laco. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] FPC 2.6.x branched, trunk becomes 2.7.1
Is this branching somehow related to preparation of release some next version of FPC (2.5.x ? or so) ? I am asking because, there are waiting some bugs/features which I would be happy see fixed before any major release. Can I see somewhere on web some planed time schedule or anouncements about next releases ? TIA -Laco. Hello, today I branched branches/fixes_2_6, the basis for a new fixes branch that will become 2.6.0 eventually. After branching I updated the trunk version to 2.7.1, which might need your build and package scripts to be adapted, as well as the symlinks of ppc386 on *nix. Before branching all makefiles were regenerated, so an update will be big. Marco ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] negative TDateTime values and MinDateTime
Felipe Monteiro de Carvalho wrote / napísal(a): On Thu, Aug 4, 2011 at 1:53 PM, Marco van de Voort mar...@stack.nl wrote: I think sacrificing dates from the year 1 to 100 AD to keep old two digit databases working is a small price to pay. But if I understand the situation correctly, dates 1 to 100AD are already supported in FPC and no-one complayned about old databases in the last years since the change made by Joost. Lacak only asked to add 1 more day to our date limit. Exactly so! And MinDateTime is used only in these two conversions functions (to test if result value is MinDateTime): FloatToDateTime and VariantToDate -Laco. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] FPC 2.6.x branched, trunk becomes 2.7.1
I think there will be some RC1 or so in september. Ok, so there is enought time before. Can I post here list of registered bugs (fcl-db), which will be good commit ? (or you are busy with other task and I must be patient and wait ;-)) TIA -Laco. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] FPC 2.6.x branched, trunk becomes 2.7.1
Luiz Americo Pereira Camara wrote / napísal(a): On 4/8/2011 09:21, LacaK wrote: Is this branching somehow related to preparation of release some next version of FPC (2.5.x ? or so) ? I am asking because, there are waiting some bugs/features which I would be happy see fixed before any major release. Me too. Specifically http://bugs.freepascal.org/view.php?id=19313 Tomorrow, i will add a new patch with the tips Lacak cited in the bug report Yes this is one of my three top bugs. Other two are: http://bugs.freepascal.org/view.php?id=14730 http://bugs.freepascal.org/view.php?id=17624 (this fix is IMO trivial) TIA -Laco. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] FPC 2.6.x branched, trunk becomes 2.7.1
Marco van de Voort wrote / napísal(a): (or you are busy with other task and I must be patient and wait ;-)) I only cherry pick the easy db bugs to get some load of Joost. Typically stuff where it is fairly clear what needs to be done, and no major design decisions on fcl-db are taken. (which would be unfair since atm I'm a Delphi/Zeos not FPC/fcl-db user). ok, I understand Currently a bit more active due to holidays but those end tomorrow. ;-) ;-( Though I would work a bit harder for postgres issues, specially the transaction and binary parameter stuff. I might actually need that one day :) One more tip for PostgreSQL http://bugs.freepascal.org/view.php?id=19567 ;-) -Laco. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] FPC 2.6.x branched, trunk becomes 2.7.1
That's why we have snapshots. The main purpose of a release is to have something that is stable and which doesn't break previously working code (except in known cases documented at http://wiki.freepascal.org/User_Changes_Trunk ). Are there published some rules, what breakage is acceptable, what not etc. ? Is it sufficient to only publish it in User_Changes_Trunk or there must be simple way (switch or something) how to restore old behavior ? I am asking, because one my patch already commited can lead to such situation, where old application recompiled with new FPC and accessed old SQLite database in some special cases can behave unexpected (in other word patch is not 100% backward compatible). Thanks -Laco. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] strcopy, strlcopy for PWideChar
Michael Van Canneyt wrote / napísal(a): On Mon, 15 Aug 2011, LacaK wrote: Hi, it seems, that there is ATM no versions of StrCopy, StrLCopy, which works with WideChars (in SysUtils). Can these variants be added ? function StrCopy(Dest: PWideChar; const Source: PWideChar): PWideChar; http://docwiki.embarcadero.com/VCL/en/SysUtils.StrCopy function StrLCopy(Dest: PWideChar; const Source: PWideChar; MaxLen: Cardinal): PWideChar; http://docwiki.embarcadero.com/VCL/en/SysUtils.StrLCopy etc. Or do you not like these wide versions at all ? It's not a matter of liking, I'm afraid. If Delphi has them, we'll have to add them too :-) Can you please add an entry in the bug tracker, so we don't forget ? http://bugs.freepascal.org/view.php?id=19989 Do you think, that it is realistic expect them in 1-2 months ? Thanks -Laco. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] strcopy, strlcopy for PWideChar
Hans-Peter Diettrich wrote / napísal(a): LacaK schrieb: Or do you not like these wide versions at all ? It's not a matter of liking, I'm afraid. If Delphi has them, we'll have to add them too :-) Can you please add an entry in the bug tracker, so we don't forget ? http://bugs.freepascal.org/view.php?id=19989 Do you think, that it is realistic expect them in 1-2 months ? Supply an patch, to speed up the implementation. Ok, I can try prepare patch, but only generic i.e. which uses only Pascal. Processor specific implementations (which use assembler, like it is done for AnsiString versions) I am afraid is too dificult for me ATM ;-) And also decision where to put (in which units) these functions I will leave to somebody more familiar with unit dependencies. But first the Delphi implementations should be explored, since the following looks not okay to me: StrLCopy copies a maximum MaxLen characters from Source to Dest, then adds a null terminator to Dest and returns Dest. The SizeOf standard function (Delphi) or the sizeof operator (C++) can be used to determine the MaxLen parameter. Usually, MaxLen equals SizeOf(Dest)-1. The mix (or equivalence) of character and byte counts obviously is inappropriate for wide versions. Perhaps sizeof should read Length? Yes, I will do it. I expect, that length is in this case character length, so byte length is character length*sizeof(widechar) -Laco. DoDi ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
[fpc-devel] LoadLibrary and FPU control word
Hi, I encounter strange thing. Look at this program please: var LibraryHandle: TLibHandle; cw: word; begin cw:=Get8087CW; writeln('CW before:',cw, ' IntPower:', intpower(10,-6)); LibraryHandle:=LoadLibrary('odbc32.dll'); writeln('CW after:',Get8087CW, ' IntPower:', intpower(10,-6)); Set8087CW(cw); end. Output: CW before:4978 IntPower: 1.E-0006 CW after:4722 IntPower: 2.E-0006 --- Wrong result of IntPower!!! As you can see, LoadLibrary changes FPU control word (from $1372 to $1272, from 64bit precision to 53bit precision). Which leads to wrong result of PowerInt. But it seems, that this happens on *Windows98* only, on Windows XP,Vista it does not happen. Do you have same experience on Windows98? If yes, then I think, that good idea will be use SafeLoadLibrary instead of LoadLibrary (which partialy solves this problem). Next: But this error I have encounter when running fcl-db tests suite with IBConnection, where is PowerInt used. When I change in ibase60.inc LoadLibrary to SafeLoadLibrary problem still exists, because later call to isc_attach_database again changes FPU control word. So I must save CW before call to isc_attach_database and then reset CW to original value. This solves problem. Please look at attached patches . Do you think, that this approach is acceptable or is there any other solution ? BTW: When I look at function SafeLoadLibrary in dynlibs.pas there is used : {$ifdef i386} w:=get8087cw; When I look at function SafeLoadLibrary in SysUtils.inc there is used : {$if defined(cpui386) or defined(cpux86_64)} fpucw:=Get8087CW; Which conditional is correct ? (i386 or cpui386) Looking at http://www.freepascal.org/docs-html/prog/progap7.html#x316-331000G ... I see no i386 ? And what FPUX87 ? Can not be used this ? Thanks -Laco. --- ibase60.inc.ori Sat Feb 19 19:24:38 2011 +++ ibase60.inc Wed Aug 17 08:59:28 2011 @@ -2458,7 +2458,7 @@ begin Result := 0; if (RefCount=0) then begin -IBaseLibraryHandle:=LoadLibrary(LibraryName); +IBaseLibraryHandle:=SafeLoadLibrary(LibraryName); if (IBaseLibraryHandle=nilhandle) then Exit; inc(RefCount); --- ibconnection.pp.ori Tue Aug 09 14:18:46 2011 +++ ibconnection.pp Wed Aug 17 09:23:14 2011 @@ -381,6 +381,9 @@ procedure TIBConnection.ConnectFB; var ADatabaseName: String; DPB: string; +{$if defined(cpui386) or defined(cpux86_64)} + cw: word; +{$endif} begin DPB := chr(isc_dpb_version1); if (UserName '') then @@ -397,10 +400,16 @@ begin FSQLDatabaseHandle := nil; if HostName '' then ADatabaseName := HostName+':'+DatabaseName else ADatabaseName := DatabaseName; +{$if defined(cpui386) or defined(cpux86_64)} + cw:=get8087cw; +{$endif} if isc_attach_database(@FStatus[0], Length(ADatabaseName), @ADatabaseName[1], @FSQLDatabaseHandle, Length(DPB), @DPB[1]) 0 then CheckError('DoInternalConnect', FStatus); +{$if defined(cpui386) or defined(cpux86_64)} + set8087cw(cw); +{$endif} end; function TIBConnection.GetDialect: integer; ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] LoadLibrary and FPU control word
Because of no response I registered it as bug http://bugs.freepascal.org/view.php?id=20011 Can you please look at least at this: Which compiler defines are OK ? i386 or cpui386 My test shows, that i386 is NOT defined (cpui386 IS defined), but then I do not understand how can it work in dynlibs.pas ??? BTW: When I look at function SafeLoadLibrary in dynlibs.pas there is used : {$ifdef i386} w:=get8087cw; When I look at function SafeLoadLibrary in SysUtils.inc there is used : {$if defined(cpui386) or defined(cpux86_64)} fpucw:=Get8087CW; Which conditional is correct ? (i386 or cpui386) Looking at http://www.freepascal.org/docs-html/prog/progap7.html#x316-331000G ... I see no i386 ? And what FPUX87 ? Can not be used this ? Thanks -Laco. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] LoadLibrary and FPU control word
Thank you! Off-topic: It seems, that in my case (in ibase60.inc is used: uses Dynlibs, sysutils,ctypes; ) function SafeLoadLibrary defined in SysUtils hides SafeLoadLibrary used in DynLibs, this is reason, why SafeLoadLibrary worked as expected. So is i386 obsolete ? If yes there are other palaces, where it is used: rtl/linux/system.pp rtl/wince/wininc/defines.inc rtl/wince/wininc/struct.inc rtl/solaris/i386/sighndh.inc rtl/solaris/x86_64/sighndh.inc -Laco. Fixed in r18255. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
[fpc-devel] overloaded SetFieldData/GetFieldData
Hi, I found this it fpc-pascal mailing list archive (I do not read this mailing list, so I do not catch this discussion) Because I think it is worth to continue, I move it into fpc-devel / ... I feel the definition // of SetFieldData/GetFieldData without a length/size parameter // and strings passed as pchar is causing all kind of problems: /I agree/ // 1) TStringField.SetAsString copies the string to a buffer // with size dsMaxStringSize so that datasets that don't figure // out the original length of the string can simply copy the // full Field.TDatasize (TBufDataset, TDbf, TMemDataset,...). /Yes/ // TWideStringField.SetAsString didn't which caused the crash // when the string is shorter than Field.Size. // TCustomSqliteDataset uses a StrNew(PChar(Buffer)); to get the // length of the string but fails sometimes (see 4). // 2) dsMaxStringSize isn't enforced for TStringField. Defining // a Field.size dsMaxStringSize causes a crash in // TStringField.SetAsString. I haven't raised an issue on this, yet. / Yes, it is also reported by fcl-db test suite, see: http://bugs.freepascal.org/view.php?id=19940 / 3) some of the speed advantage of memory based datasets is // offset by moving full Field.Tdatasize bytes in both set and // get fielddata / / 4) pascal strings can contain #0 characters in the string. // When converting to pchar part of these strings is lost. // /Very good point. See also comments in http://bugs.freepascal.org/view.php?id=19930 / // What I propose is: // 1 to create overloaded versions of SetFieldData and // GetFieldData that include a length parameter, to change // TStringField.SetAsString and TWideStringField.SetAsWideString // to use these versions /Or also create procedure TField.SetData(Buffer: Pointer; DataSize : integer=0); which will do some checks like existing TField.SetData(Buffer: Pointer; NativeFormat : Boolean) and call new FDataSet.SetFieldData(Self, Buffer, NativeFormat, DataSize); This new TDataSet.SetFieldData will by default call existing old SetFieldData: procedure TDataSet.SetFieldData(Field: TField; Buffer: Pointer; NativeFormat: Boolean; DataSize:integer); begin SetFieldData(Field, Buffer, NativeFormat); end; So backward compatibilty will be retained. TDataSet descendants, which will want, they will override this new SetFieldData method and will take advantage of them. (in our case TBufDataSet will be adopted ) / and to migrate the different datasets // to use these new versions. This way existing (user) code // using SetFieldData/GetFieldData will still work (and the user // still being responsible for buffer overruns...) and datasets // can correctly save and retrieve strings while improving performance. // 2 change the bufdataset internal storage for ftstring and // ftwidestring fields to include the string length so that // stored strings can be retrieved in full when containing #0 // characters and without having to copy systematically datasize // bytes. / Yes, so ftString will be stored like ftvarBinary, which has first two bytes length and followed by binary string / However this will introduce an incompatible binary // format for TFpcBinaryDatapacketReader. Having a second // FpcBinaryIdent would allow for both formats to co-habitate. // // If need be the discussion can be moved to fpc-devel. /Yes ;-)))/ /And another theme not related to this subjects are Autoincrement fields, which are ATM read-only for all access (BTW see also http://bugs.freepascal.org/view.php?id=17624 ) Here I have idea introduce at some level (TDataSet or TBufDataSet) virtual function (for example GetNextAutoIncValue), which will be called just after append...post (may be in InternalPost if State=dsInsert) And descendants like TSQLQuery will be able override this method and provide their own mechanism for retrieving auto-generated values from SQL databases. Like MySQL: select last_insert_rowid(), PostgreSQL: select lastval(), MSSQL: select @@identity, etc. For other solution (introduce new property RefreshSQL ) read: http://bugs.freepascal.org/view.php?id=16076 ATM auto-increment fields are practicaly useless. Ofcourse this are only very raw ideas ... TIA -Laco. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] strcopy, strlcopy for PWideChar
Florian Klämpfl wrote / napísal(a): Am 16.08.2011 07:06, schrieb LacaK: Hans-Peter Diettrich wrote / napísal(a): LacaK schrieb: Or do you not like these wide versions at all ? It's not a matter of liking, I'm afraid. If Delphi has them, we'll have to add them too :-) Can you please add an entry in the bug tracker, so we don't forget ? http://bugs.freepascal.org/view.php?id=19989 Do you think, that it is realistic expect them in 1-2 months ? Supply an patch, to speed up the implementation. Ok, I can try prepare patch, but only generic i.e. which uses only Pascal. It's the prefered way anyways. First, make a good pascal version, if someone needs it, he can look into creating an assembler one for some cpus. I posted generic pascal versions in bug report http://bugs.freepascal.org/view.php?id=19989#bugnotes Please review (and commit if all ok). Thanks -Laco. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] TField.Validate in FPC 2.6
Joost van der Sluis wrote / napísal(a): On Sat, 2011-09-17 at 10:56 +0200, Michael Van Canneyt wrote: On Sat, 17 Sep 2011, Martin Schreiber wrote: Hi, TField.SetData() in fixes_2_6 calls TField.Validate(). 2.4.4 does not, trunk neither. Strange that 2.6 does this if trunk does not ? What are the plans for the upcoming release? Will FPC 2.6.0 call TField.Validate() in TField.SetData()? It should not. There were some changes regarding this, and I still didn't look at them. I will and decide how to solve this. (I think I'll revert it all) Please look at http://svn.freepascal.org/cgi-bin/viewvc.cgi?view=revrevision=18872 This commit (patch by Luiz Americo) is OK. It was a long time awaited feature, so please do not drop it. Thanks -Laco. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] Major problem with Move and Array of Int64
Did anyone recently do work on BLOB features to MySQL 5.1 connector? there was commited only this http://svn.freepascal.org/cgi-bin/viewvc.cgi/trunk/packages/fcl-db/src/sqldb/mysql/mysqlconn.inc?r1=17417r2=18951 which introduced mapping from MySQL TEXT datatype (character LOB) to TMemoField and BLOB (binary LOB) to TBlobField but I do not think, that this can cause your problems. L. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] Major problem with Move and Array of Int64
And which SQL DBConnector do you use ? TMySQL51Connection ? my app maps this particular field as SQL_LONGVARBINARY or TODBCConnection ? L. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] Major problem with Move and Array of Int64
Martin Schreiber wrote / napísal(a): On Friday 23 September 2011 14.00:07 Sergei Gorelkin wrote: Recently strings behavior was changed, they are now codepage-aware. The compiler can now implicitly convert strings from one encoding to another. To handle non-string data, you should use RawByteString type, or better yet non-string types like (dynamic) array of byte. So TBlobField.Value probably should be changed to array of byte It seems, that Delphi XE does it in this way: Value is of type TBlob and TBlob is byte array http://docwiki.embarcadero.com/VCL/en/DB.TBlobField.Value and there should be a TField.AsByteArray property? Better use compatible AsBytes: http://docwiki.embarcadero.com/VCL/en/DB.TField.AsBytes http://docwiki.embarcadero.com/VCL/en/DB.TBlobField.GetAsBytes -Laco. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] Trunk does not compile on Linux x86-64
Are there available Lazarus snapshots, which are build using current trunk ? If I download Lazarus with FPC 2.7.1 ( for example: ftp://www.hu.freepascal.org/pub/lazarus/snapshots/Lazarus-0.9.31-33000-fpc-2.7.1-20111021-win32.exe ) it seems, that there are not current source files from trunk, but from begining of September ? Thanks -Laco. 2011/10/21 David Welch dwe...@dwelch.com: is there an svn release number that does compile with 2.4.0 that will get me to 2.4.4 or better so that I can compile the trunk? Guaranteed: Compile http://svn.freepascal.org/svn/fpc/tags/release_2_4_2/ with fpc 2.4.0 to get fpc 2.4.2 Compile http://svn.freepascal.org/svn/fpc/tags/release_2_4_4/ with fpc 2.4.2 to get fpc 2.4.4 Compile http://svn.freepascal.org/svn/fpc/trunk with fpc 2.4.4 to get fpc 2.7.1 IIRC, you have a good chance to the first steps in one go: Compile http://svn.freepascal.org/svn/fpc/tags/release_2_4_4/ with fpc 2.4.0 to get fpc 2.4.4 Vincent ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
[fpc-devel] cvarutil: convert variant array of bytes into ansistring ?
Hi, I am now working on fcl-db TBinaryField, which has Value: Variant property. As I understand documentation, this variant should be returned as variant array of bytes. Later when are assigning values of fields into params also this variant array is copied (into TParam). But when I want/need read parameter value as string (binary string) then variant convert error occurs. It is because in cvarutil.inc in Function VariantToAnsiString(const VargSrc : TVarData) is not supported conversion from variant array into string. So my question is if it is acceptable to add there support for converting byte array to string ? Something like attached diff. Please let me know, if this can be accepted/applied ? Thanks -Laco. --- cvarutil.inc.oriThu Apr 07 06:10:54 2011 +++ cvarutil.incFri Oct 21 11:04:44 2011 @@ -1415,7 +1415,12 @@ begin end else { pointer is nil } VariantTypeMismatch(vType, varString); else { array or something like that } - VariantTypeMismatch(vType, varString); + if (vType and varArray = varArray) and Assigned(vArray) then begin +SetLength(Result, vArray^.Bounds[0].ElementCount * vArray^.ElementSize); +Move(vArray^.Data^, Result[1], length(Result)*sizeof(AnsiChar)); + end + else +VariantTypeMismatch(vType, varString); end; {$IFDEF DEBUG_VARUTILS} if __DEBUG_VARUTILS then begin ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
[fpc-devel] Re: cvarutil: convert variant array of bytes into ansistring ?
Hi Sergei, Thank you for your reply. As it is out of my comfort zone, I leave it to up to you (if or when you implement this) TIA -Laco. It has to be done in a different and more complex way, by using VariantChangeTypeEx to convert the variant(array) to varOleString type, then converting latter to ansistring. This way, in Windows the job will be delegated to OS, which is Delphi compatible. For non-Windows, the relevant code ends up in VariantChangeTypeEx (varutils.inc). Also, you'll need to access the variant array with SafeArray* functions, and make checks that it is actually one-dimensional and its element type is eligible for conversion. Sergei Hi, I am now working on fcl-db TBinaryField, which has Value: Variant property. As I understand documentation, this variant should be returned as variant array of bytes. Later when are assigning values of fields into params also this variant array is copied (into TParam). But when I want/need read parameter value as string (binary string) then variant convert error occurs. It is because in cvarutil.inc in Function VariantToAnsiString(const VargSrc : TVarData) is not supported conversion from variant array into string. So my question is if it is acceptable to add there support for converting byte array to string ? Something like attached diff. Please let me know, if this can be accepted/applied ? Thanks -Laco. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] Segmentation fault for Firebird exception inside thread
May be that is is (or not ;-)) related to http://bugs.freepascal.org/view.php?id=17360 -Laco. Hello, this is my first post and I hope this is the correct list for my question. I'm getting a segmentation fault ('violación de segmento' in spanish) when running the code from below on a Linux 64-bit machine (OpenSuse 10.2 64-bits). I'm using FPC 2.2.5, so perhaps the error is already known, but I did not find any solution in the web. I tested the code on Windows 32 bits and Linux 32 bits too, but there everything seems ok. The example is about opening a Firebird connection in a thread. When there is a Firebird exception inside this connection, the application terminates with the segmentation fault. Does anyone know about this error, or can anyone give me a hint, where to look for a solution? This is the example code: code program fbthreadtest; {$IFDEF FPC} {$MODE DELPHI}{$H+} {$ENDIF} {$APPTYPE CONSOLE} uses {$IFDEF UNIX} cthreads, cwstring, {$ENDIF} Classes, IBConnection, sqldb; type TFBThread = class(TThread) private protected procedure Execute; override; public constructor Create; end; constructor TFBThread.Create; begin inherited Create(True); FreeOnTerminate := False; Resume; end; procedure TFBThread.Execute; var db: TIBConnection; tr: TSQLTransaction; q: TSQLQuery; begin db := TIBConnection.Create(nil); try db.DatabaseName := 'localhost:/home/data/Database/ssstst.gdb'; db.LoginPrompt := False; db.HostName := ''; db.UserName := 'SYSDBA'; db.Password := 'masterkey'; db.Connected := TRUE; tr := TSQLTransaction.Create(nil); try tr.DataBase := db; tr.Action := caCommit; tr.Params.Clear; tr.Params.Add('isc_tpb_read_committed'); tr.Params.Add('isc_tpb_rec_version'); tr.Params.Add('isc_tpb_nowait'); db.Transaction := tr; tr.Active := True; q := TSQLQuery.Create(nil); try q.Database:= db; q.Transaction := tr; try Writeln('select...'); // the following line raises an exception because rdb$databases doesn't exist. q.SQL.Text := 'select count(*) from rdb$databases'; q.Prepare; except Writeln('...exception'); end; finally q.Free; end; finally tr.Commit; tr.Free; end; finally db.Connected := False; db.Free; end; end; begin with TFBThread.Create do begin WaitFor; Free; end; end. /code Thanks, Stefan ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] TMSSQLConnection - sqlDB component for accessing MS SQL Server
Hi, let me share same basic info/ideas about TMSSQLConnection : 1. As Marcos wrote it is descendant of sql-db TSQLConnection class and provides native connector for MS SQL Servers and Sybase servers 2. is depends/requires on FreeTDS open-source cross platform DB-Library (alternatively can be used also Microsoft db-library ntwdblib.dll) 3. all what is needed are 2-3 files: - mssqlconn.pp (implementation of TMSSQLConnection and TSybaseConnection) - dblib.pp (interface to FreeTDS db-library ABI dblib.dll on Windows, libsybdb.so on *NIX) - readme.txt (some info for users/developers) 4. according to market share of MS SQL Server and Sybase there may be many users, which will welcome alternative to TODBCConnection 5. there is on http://www.freepascal.org/future.var in Improve the database support Drivers (descendants) for more database types so I understand it as FPC is open for new stuff ;-) 6. if there is any problem please let us know. If you decide to include it into fcl-db then you can place files for example into src/sqldb/mssql folder ;-) TIA -Laco. Hi, As you can see here http://bugs.freepascal.org/view.php?id=17303 the developer known to LacaK developed a new connector for MSSQLServer, descendant of TSQLConnection class, and sent the beta code in 2010-08-30. Some developers discussed the new code here: http://lazarus.freepascal.org/index.php/topic,15135.msg80922.html#msg80922 I'm already using this connector in production without problems. To FPC core team: Could you take a look in that component and think about included this code in SVN to new developers use too, please? Thanks, Marcos Douglas PS: this message was posted in lazarus-list and fpc-pascal, but I was wrong because nobody answer me about YES or NOT. So, I think this is the right list, don't? ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
[fpc-devel] Copy function and dynamic array
Hi *, I found small incompatibility between Delphi and FPC. This code: var a,b: array of byte; begin setlength(a,2); b:=copy(a,2,1); //--HERE Range check error in FPC, Delphi returns empty array end; Delphi documentation says: If Index is larger than the length of S, *Copy* returns an empty string or array. http://docwiki.embarcadero.com/VCL/en/System.Copy Can it be fixed also in FPC? L. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] Copy function and dynamic array
Sergei Gorelkin wrote / napísal(a): 29.02.2012 17:05, Sven Barth пишет: It's not a bug in Delphi if they write it in the documentation. Whether we should copy this behavior is the question (maybe only in Delphi mode). It cannot be fixed for Delphi mode only because a single copy of RTL is used for all compiler modes. The current situation where out of range 'length' parameter is adjusted but 'index' out of range raises exception is simply self-inconsistent. It is also inconsistent with behavior of Copy for strings. Adjusting index will neither cause any buffer overflows nor make code slower, so it should be fixed. Will you do it or should I register bug in bug tracker? Laco. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] Copy function and dynamic array
Sergei Gorelkin wrote / napísal(a): 29.02.2012 18:21, LacaK пишет: It cannot be fixed for Delphi mode only because a single copy of RTL is used for all compiler modes. The current situation where out of range 'length' parameter is adjusted but 'index' out of range raises exception is simply self-inconsistent. It is also inconsistent with behavior of Copy for strings. Adjusting index will neither cause any buffer overflows nor make code slower, so it should be fixed. Will you do it or should I register bug in bug tracker? Please create a Mantis issue, so it won't be forgotten. http://bugs.freepascal.org/view.php?id=21396 TIA -Laco. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] TMSSQLConnection - sqlDB component for accessing MS SQL Server
michael.vancann...@wisa.be wrote / napísal(a): On Thu, 15 Mar 2012, Marcos Douglas wrote: On Mon, Feb 27, 2012 at 9:33 AM, Marcos Douglas m...@delfire.net wrote: On Mon, Feb 27, 2012 at 5:08 AM, michael.vancann...@wisa.be wrote: On Mon, 27 Feb 2012, LacaK wrote: Hi, let me share same basic info/ideas about TMSSQLConnection : 1. As Marcos wrote it is descendant of sql-db TSQLConnection class and provides native connector for MS SQL Servers and Sybase servers 2. is depends/requires on FreeTDS open-source cross platform DB-Library (alternatively can be used also Microsoft db-library ntwdblib.dll) 3. all what is needed are 2-3 files: - mssqlconn.pp (implementation of TMSSQLConnection and TSybaseConnection) - dblib.pp (interface to FreeTDS db-library ABI dblib.dll on Windows, libsybdb.so on *NIX) - readme.txt (some info for users/developers) 4. according to market share of MS SQL Server and Sybase there may be many users, which will welcome alternative to TODBCConnection 5. there is on http://www.freepascal.org/future.var in Improve the database support Drivers (descendants) for more database types so I understand it as FPC is open for new stuff ;-) 6. if there is any problem please let us know. If you decide to include it into fcl-db then you can place files for example into src/sqldb/mssql folder ;-) I will have a look and include both units. And the dream will become true... Thanks Michael. Any chance to merge in fixes_2_6 in short time? Marcos Douglas Hi Michael, Do you have some prediction to include the sources? My apologies, I had totally forgotten; I am buried in work currently. Committed in revision 20522. I didn't commit any examples or tests. Please test if everything works OK. I compiled on Linux 64-bit, I don't have a working FPC/Lazarus 32-bit windows development environment currently. Hi Michael, splitting files into two packages was unavoidable? I would prefer If all 3 files will be in one folder (sqldb/mssql) together (it seems to me simpler and more convenient). (because they are strongly related each to other) Thanks -Laco. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] TMSSQLConnection - sqlDB component for accessing MS SQL Server
Hi Michael, splitting files into two packages was unavoidable? Yes. As you can see for the other databases, we always keep the header imports separate from the components. Standard time-tested practice. Hm, although I am not happy with this, I can do nothing with it ;-) Then I have minor comments: - in packages/dblib/fpmake.pp at line 23: Author put please instead of Lacak2 Ladislav Karrach (as in dblib.pp header) - in packages/fcl-db/src/sqldb/mssql/makefile.fpc at line 2: change IBConnection to MSSQLConnection ;-) And will you apply also diffs to fcl-db tests ? So we can run complete test suite ... Thanks -Laco. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] TMSSQLConnection - sqlDB component for accessing MS SQL Server
No. Anyway, I change the colum names (id,name to col1, col2) The error is: Cannot insert the value NULL into column 'col', table tempdb.dbo.#t... This error has nothing to do with FPC or SQLDB. Your SQL statement is trying to insert NULL in a required field. No Michael, see the example I wrote before. Create table: create table #t (col1 int, col2 varchar(60)) OBS: No column is required. This INSERT works: insert into #t values (1, 'bla bla bla') This INSERT do NOT works: insert into #t (col2) values ('bla bla') Marcos, can you please test with explicitly allowed nulls: create table #t (col1 int NULL, col2 varchar(60) NULL) (MS SQL Server nullability is controled by database setting *ANSI null default* so you can check this setting on your temp database also)* *L.* * ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel