Author | Topic: Re: DbInfo() return value complementation - The attachment | |
---|---|---|
Andreas Gehrs-Pahl View the complete thread for this message in: | Re: DbInfo() return value complementation - The attachment on Tue, 29 Nov 2016 04:57:02 -0500 Carlos, >Here is the attachment where I made in it changes according to the >Andreas advise and I think that is the right way to know if the charset >is ANSI without to know in advance which one DBE opened the file. First a clarification. The DBFDBO_ANSI define constant was introduced with Xbase++ version 1.90.322, and the corresponding DBFDBE_ANSI define constant was introduced with version 1.90.331. Contrary to the documentation, using DbInfo(DBFDBO_ANSI) will always return a numeric value, either Zero (0) or One (1), rather than a logical value of FALSE (.f.) or TRUE (.t.), and it has worked that way since this feature was introduced in 2005/2006. The FOXDBO_CODEPAGE define constant was added in Xbase++ version 2.00.720, so it is only a few months old! In earlier versions, you would have to use low-level file functions to check the database header manually. Also, normal (non-VFP) database files do NOT contain any indicator for the used Character Set (OEM or ANSI), as they (should) ALWAYS contain only OEM characters. It is therefore meaningless to use DbInfo(DBFDBO_ANSI) the way you do in your code. Xbase++ allows you to treat the data in database files as ANSI characters, though, which basically means you can enable and disable the implicit OEM/ ANSI conversion of the DBFDBE, by setting the DBFDBE_ANSI define constant to either TRUE (.t.) or FALSE (.f.) -- the default is FALSE -- before opening a database, using this: DbeInfo(COMPONENT_DATA, DBFDBE_ANSI, lValue). You can then check the current setting of a database (or its DBO) using the DbInfo(DBFDBO_ANSI) function, which (strangely) will return either Zero (0) or One (1), instead of the expected and documented logical return value. If the database is treated as containing ANSI characters, the return value is One (1), otherwise it is Zero (0), which is the default. This basically enables or disables the implicit character set conversions when reading or writing data with the DBFDBE for that database, depending on the current/active (thread-specific) Set CharSet setting. If both are set to OEM or both are set to ANSI, no conversion is done, otherwise the implicit OEM to ANSI and ANSI to OEM conversion is done when reading or writing data. So, DbInfo(DBFDBO_ANSI) is a temporary setting, which is based on the actual DBFDBE setting at the time the database was opened. It is not something inherent to a database. So the way you try to use it in your program is not sensible at all. Unless you use DbeInfo(COMPONENT_DATA, DBFDBE_ANSI, .t.) before you open a database with the DBFDBE, the return value will always be Zero. As there is no such settings for the Order Components -- neither the NTXDBE nor the CDXDBE can be configures like this -- the index will always be based on the default setting of the DBE, which is OEM for NTX files and ANSI for CDX files. >Please is it right? No, it isn't, even though it kind of works by accident. If you want this to work correctly, you need to do something like this: In line 26 you should test which DBE was used, and then use the appropriate define constant: if left(f0002->(DbInfo(DBO_DBENAME)), 3) == "DBF" xReturned := f0002->(DbInfo(DBFDBO_ANSI)) elseif left(f0002->(DbInfo(DBO_DBENAME)), 3) == "FOX" xReturned := f0002->(DbInfo(FOXDBO_CODEPAGE)) endif You should never rely on the (coincidental) fact that the values of the two define constants DBFDBO_ANSI and FOXDBO_CODEPAGE are the same, as they could actually change in future versions of Xbase++. That's one of the reasons why those define constants were created; so you don't need to use a meaningless hard-coded numeric value (of 1007). Also, it always makes much more sense to determine which DBE is actually responsible for the DBO, before doing any further queries with define constants that depend on the used DBE. Finally, it makes much more sense to overload the DbeSys() procedure and load, create, and configure only those DBEs that you want to use, rather than what you do in lines 8 - 19 of your code and your LoadDbe() function. Andreas Andreas Gehrs-Pahl Absolute Software, LLC phone: (989) 723-9927 email: Andreas@AbsoluteSoftwareLLC.com web: http://www.AbsoluteSoftwareLLC.com [F]: https://www.facebook.com/AbsoluteSoftwareLLC |