[tinysql] [Fwd: tinySQL and locking?]
Thomas Siedschlag
thomas.siedschlag@x-cellent.com
Tue, 23 Mar 2004 14:05:22 +0100
Hi,
thank you for your answers.
> the DBF-type field is a combined field:
>
> bit 0-2 describe the DBase-Version used
> bit 3 indicates whether the memo-field is used
> bit 4-6 are reserved for SQL (no clue what that part of the specs
> really means)
> bit 7 also indicates that the file is a dBaseIII with memos
>
> Source:
> http://www.dbase.com/KnowledgeBase/int/db7_file_fmt.htm
>
I don't understand the reserved bits for the SQL support too. But I was
wondering, why doesn't exist a DBF-type in tinySQL for a normal DBase4
version (without SQL and memos), and therefore I expect a DBF-type field
with 0x04h.
I wrote some test programs with tinySQL and I found two possible bugs.
Maybe soemone have time to reproduce this.
1. Delete Statement
If I execute a delete statement on a DBF file, then the affected rows
shouldn't deleted physical, but should marked with an asterisk to
indicate a deletion. But I found a 0x00h 0x2Ah instead of a simple 0x2Ah
at the affected positions. You can find in the dbfFileTable.java
public void deleteRow(int row) throws tinySQLException
{
if (row >= getRowCount())
throw new tinySQLException("Row is >= rowcount");
try
{
deletedRows[row] = ROW_DELETED;
ftbl.seek(calcRowPos(row));
ftbl.writeChar(RECORD_IS_DELETED);
}
catch (IOException ioe)
{
throw new tinySQLException("Unable to delete record " + row);
}
}
The RandomAccesFile.writeChar() writes a two-byte value! You should
better use RandomAccesFile.writeByte().
2. Select with Where
I have a select statement something like that
SELECT * FROM person WHERE surname='xxxxx'
If I execute this, I was wondering, why I got no results, although in
the DBF-file records exist, which match the 'where' clause.
I think the bug is in the WhereClause.java.
public boolean isMatch(tsRow matchRow) throws tinySQLException
{
boolean reevaluate = false;
if (tableColumns.size() > 0)
{
/**
* fill cache on start needed
*/
if (cache == null)
{
cache = new Object[tableColumns.size()];
cachePos = new int[tableColumns.size()];
int size = cache.length;
for (int i = 0; i < size; i++)
{
tsColumn col = (tsColumn) tableColumns.elementAt(i);
int idx = matchRow.findColumn(col.getPhysicalName());
cachePos[i] = idx;
cache[i] = matchRow.get(idx);
}
reevaluate = true;
}
else
{
int size = cache.length;
for (int i = 0; i < size; i++)
{
int idx = cachePos[i];
Object myObject = cache[i];
Object rowObject = matchRow.get(i);
// --> Bug: should be: Object rowObject = matchRow.get(idx);
// O1 and O2 should be the same type, so try an equals
if (rowObject != null)
{
if (myObject != null)
{
if ((rowObject != myObject) &&
(rowObject.equals(myObject) == false))
{
cache[i] = rowObject;
reevaluate = true;
}
}
else
{
cache[i] = rowObject;
reevaluate = true;
}
}
}
}
}
else
{
if (!evaluatedOnce)
{
reevaluate = true;
}
}
if (reevaluate)
{
evaluatedOnce = true;
Boolean b =
ParserUtils.convertToBoolean(expression.evaluate(matchRow));
lastReturnValue = b.booleanValue();
}
return lastReturnValue;
}
In isMatch() the cache column is compared with a potential wrong column
value of tha actual row. This may lead to wrong results, because the
cache compare matchs, although the actual row would return a different
result as the 'lastReturnValue'.
Regards
--
Thomas Siedschlag
x-cellent technologies GmbH
Rosenkavalierplatz 5
81925 Muenchen
Germany
e-mail thomas.siedschlag@x-cellent.com
http://www.x-cellent.com