View Issue Details
ID | Project | Category | View Status | Date Submitted | Last Update |
---|---|---|---|---|---|
0004159 | JEDI VCL | 00 JVCL Components | public | 2007-06-19 23:28 | 2008-10-29 06:20 |
Reporter | Oleg | Assigned To | obones | ||
Priority | normal | Severity | minor | Reproducibility | always |
Status | resolved | Resolution | unable to reproduce | ||
Product Version | 3.30 | ||||
Target Version | Fixed in Version | ||||
Summary | 0004159: TJvAppDBStorage does not allow to use section with empty name (i.e. to store data in "root" section of storage) | ||||
Description | For TJvAppDBStorage in methods Read.../Write... if empty line specified for name of "section" (i.e. parameter "Path" does not contains characters '\' at all, or contains only one character '\' and at the very first poition of string), then TJvAppDBStorage component does not find (not capable to read) data from such "section". It is because TJvAppDBStorage (TJvCustomAppDBStorage) uses method DataSet.Locate(';some_key') to find the corresponding database record (for section='', key='some_key') - but it is a wrong way to search for record, which containing NULL in one of fields. (though, TJvAppDBStorage successfully writes data to such a "section" - thereafter this data cannot be read). The problem solved by the following changes in file "JvAppDBStorage.pas": -------------------------------- function TJvCustomAppDBStorage.SectionExists(const Path: string; RestorePosition: Boolean): Boolean; ..... Result := DataSource.DataSet.Locate(SectionField, Path, [loCaseInsensitive]); replaced with if (Path = '') then Result := DataSource.DataSet.Locate(SectionField, Variants.Null(), [loCaseInsensitive]) else Result := DataSource.DataSet.Locate(SectionField, Path, [loCaseInsensitive]); function TJvCustomAppDBStorage.ValueExists(const Section, Key: string; RestorePosition: Boolean): Boolean; ..... Result := DataSource.DataSet.Locate(Format('%s;%s', [SectionField, KeyField]), VarArrayOf([Section, Key]), [loCaseInsensitive]); replaced with if (Section = '') then Result := DataSource.DataSet.Locate(Format('%s;%s', [SectionField, KeyField]), VarArrayOf([Variants.Null(), Key]), [loCaseInsensitive]) else Result := DataSource.DataSet.Locate(Format('%s;%s', [SectionField, KeyField]), VarArrayOf([Section, Key]), [loCaseInsensitive]); | ||||
Additional Information | It is represented correct that empty line can be specified for section name - it is implied that data stored in current ("root") section of storage. For example, component TJvAppRegistryStorage correctly reads and writes data in "root" (current) section (section with empty name). Also it seems that name of a key always should be nonempty (though, for example, registry has a "default" value - which can be used for data with an empty name of key). | ||||
Tags | No tags attached. | ||||
|
Isn't this because your database automatically converts an empty string to 'NULL'? I seem to remember some databases that make no difference between NULL and an empty string, and some others do. I'm asking because your patch does not include the change to the WriteValue so that an empty string is changed to a NULL value. |
|
It is really that in my case "empty" and "NULL" strings are equivalent (when using Oracle + ODAC components). Patch described by me is tested and enough (for use section with empty name) only in this case. If NULL and empty-strings are not equivalent (at database-fields level) - i do not exclude, that still any completions can be demanded. After superficial acquaintance with TJvCustomAppDBStorage.WriteValue I have found that possibly ---------------------------------- FSectionLink.Field.AsString := Section; *** need to be replaced with *** if(Section.IsEmpty()) FSectionLink.Field.Clear() else FSectionLink.Field.AsString := Section; ---------------------------------- hmmm... But now I am not assured, that all changes (described by me in this issue) will be enough. Considering the last patch - possibly it will be enough for use a NULL field value for section with empty name. But if it required to use for section with empty name a field with empty string (instead of NULL) the code should be remained in its present state. Probably, for different cases (databases ...or database access components?) will be better to specify obviously necessity of use of empty strings or NULL (for example, through any additional property in TJvCustomAppDBStorage/TJvAppDBStorage); certainly if such check cannot be performed automatically (programmatically). |
|
Is there other components or functions in which the designated problem (equivalence "empty string" and NULL) also matters? How the problem is solved in that cases? Is it will be good such decision - add additional property like: EmptyStrAsNull: Boolean, "interpret empty lines as NULL"? If I correctly understand, the designated problem can appear in any JVCL + Oracle application, irrespective of used database access components (including BDE) - because "empty string" and NULL are considered identical at a database layer. |
|
Could you create a small sample using your odac components. I will have a look for it and your fix. Greetings Jens |
|
Oleg, can you act on Jens' request? |
|
Any news? |
|
No answers, we cannot do anything. |
Date Modified | Username | Field | Change |
---|---|---|---|
2007-06-19 23:28 | Oleg | New Issue | |
2007-06-20 03:24 | obones | Note Added: 0013494 | |
2007-06-20 03:24 | obones | Status | new => feedback |
2007-06-20 05:49 | Oleg | Note Added: 0013498 | |
2007-06-20 05:51 | Oleg | Note Edited: 0013498 | |
2007-06-20 05:52 | Oleg | Note Edited: 0013498 | |
2007-08-03 03:54 | Oleg | Note Added: 0013608 | |
2007-08-06 14:09 | jfudickar | Note Added: 0013615 | |
2007-10-12 07:15 | obones | Note Added: 0013925 | |
2008-02-21 06:30 | obones | Note Added: 0014247 | |
2008-10-29 06:19 | obones | Status | feedback => resolved |
2008-10-29 06:19 | obones | Resolution | open => unable to reproduce |
2008-10-29 06:19 | obones | Assigned To | => obones |
2008-10-29 06:19 | obones | Note Added: 0014927 |