Bug 146471 - Firebird: impossible to delete an external table
Summary: Firebird: impossible to delete an external table
Status: RESOLVED FIXED
Alias: None
Product: LibreOffice
Classification: Unclassified
Component: Base (show other bugs)
Version:
(earliest affected)
7.4.0.0 alpha0+
Hardware: All All
: medium normal
Assignee: Julien Nabet
URL:
Whiteboard: target:7.4.0 target:7.3.0.2
Keywords:
Depends on:
Blocks:
 
Reported: 2021-12-29 11:24 UTC by Julien Nabet
Modified: 2022-01-05 12:33 UTC (History)
0 users

See Also:
Crash report or crash signature:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Julien Nabet 2021-12-29 11:24:41 UTC
Description:
On pc Debian x86-64 with master sources updated today, I can't delete an external table on a odb with Firebird.

Steps to Reproduce:
1. Create a simple file containing:
test1;1
test2;2
2. Launch LO, enable experimental features and restart LO
3. Create a brand new odb file with Firebird embedded
4. Create an external table like this:
CREATE TABLE ext1 EXTERNAL '<filename>' ( field1 char(20), field2 smallint );

in my case, I got a file /tmp/myfile.txt so it would be:
CREATE TABLE ext1 EXTERNAL '/tmp/myfile.txt' ( field1 char(20), field2 smallint);

5. Menu View, "Refresh Tables"
=> a table "EXT1" appears in Tables panel

Now try to remove this new table.


Actual Results:
Nothing happens
On console, we can see:
warn:dbaccess:40302:40302:dbaccess/source/ui/app/AppControllerDnD.cxx:142: DBG_UNHANDLED_EXCEPTION in deleteTables exception: com.sun.star.uno.RuntimeException message: /home/julien/lo/libreoffice/connectivity/source/drivers/firebird/Tables.cxx:59


Expected Results:
Table should be removed


Reproducible: Always


User Profile Reset: No



Additional Info:
Version: 7.4.0.0.alpha0+ / LibreOffice Community
Build ID: 3365e860d44b3396a5c1dd10e3f8db9c5da0ce02
CPU threads: 12; OS: Linux 5.15; UI render: default; VCL: gtk3
Locale: fr-FR (fr_FR.UTF-8); UI: en-US
Calc: threaded
Comment 1 Julien Nabet 2021-12-29 17:16:19 UTC
Some analysis shows that to display tables, ODatabaseMetaData::getTables is called and it goes in the else part of this block:

   1339     // TODO: GLOBAL TEMPORARY, LOCAL TEMPORARY, ALIAS, SYNONYM
   1340     if (!types.hasElements() || (types.getLength() == 1 && types[0].match(wld)))
   1341     {
   1342         // All table types? I.e. includes system tables.
   1343         queryBuf.append("(RDB$RELATION_TYPE = 0 OR RDB$RELATION_TYPE = 1) ");
   1344     }
   1345     else
   1346     {
   1347         queryBuf.append("( (0 = 1) ");
   1348         for (OUString const & t : types)
   1349         {
   1350             if (t == "SYSTEM TABLE")
   1351                 queryBuf.append("OR (RDB$SYSTEM_FLAG = 1 AND RDB$VIEW_BLR IS NULL) ");
   1352             else if (t == "TABLE")
   1353                 queryBuf.append("OR (RDB$SYSTEM_FLAG IS NULL OR RDB$SYSTEM_FLAG = 0 AND RDB$VIEW_BLR IS NULL) ");
   1354             else if (t == "VIEW")
   1355                 queryBuf.append("OR (RDB$SYSTEM_FLAG IS NULL OR RDB$SYSTEM_FLAG = 0 AND RDB$VIEW_BLR IS NOT NULL) ");
   1356             else
   1357                 throw SQLException(); // TODO: implement other types, see above.
   1358         }
   1359         queryBuf.append(") ");
   1360     }

when trying to remove the table, it goes in the if part.
see:
https://opengrok.libreoffice.org/xref/core/connectivity/source/drivers/firebird/DatabaseMetaData.cxx?r=5b20bb65#1347

Now investigating about RDB$RELATION_TYPE = 0 OR RDB$RELATION_TYPE = 1, these values come from src/jrd/constants.h
    214 // relation types
    215 
    216 enum rel_t {
    217         rel_persistent = 0,
    218         rel_view = 1,
    219         rel_external = 2,
    220         rel_virtual = 3,
    221         rel_global_temp_preserve = 4,
    222         rel_global_temp_delete = 5
    223 };
so we retrieve rel_persistent (for "regular" tables and views)
but we need rel_external.

=> 
diff --git a/connectivity/source/drivers/firebird/DatabaseMetaData.cxx b/connectivity/source/drivers/firebird/DatabaseMetaData.cxx
index f63468f0813f..c8356a32a82b 100644
--- a/connectivity/source/drivers/firebird/DatabaseMetaData.cxx
+++ b/connectivity/source/drivers/firebird/DatabaseMetaData.cxx
@@ -1339,8 +1339,10 @@ uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getTables(
     // TODO: GLOBAL TEMPORARY, LOCAL TEMPORARY, ALIAS, SYNONYM
     if (!types.hasElements() || (types.getLength() == 1 && types[0].match(wld)))
     {
+        // from Firebird: src/jrd/constants.h
+        // rel_persistent = 0, rel_view = 1, rel_external = 2
         // All table types? I.e. includes system tables.
-        queryBuf.append("(RDB$RELATION_TYPE = 0 OR RDB$RELATION_TYPE = 1) ");
+        queryBuf.append("(RDB$RELATION_TYPE = 0 OR RDB$RELATION_TYPE = 1 OR RDB$RELATION_TYPE = 2) ");
     }
     else
     {

After this first change, we got now a popup error when trying to delete the table:
irebird_sdbc error:
*Dynamic SQL Error
*SQL error code = -104
*Token unknown - line 1, column 6
*"EXT1"
caused by
'isc_dsql_prepare'
 /home/julien/lo/libreoffice/connectivity/source/drivers/firebird/Util.cxx:68
The pb is again in the function ODatabaseMetaData::getTables some lines below when trying to retrieve the value of sTableType:
1397              OUString sTableType;
1398
1399              if (nSystemFlag == 1)
1400              {
1401                  sTableType = "SYSTEM TABLE";
1402              }
1403              else if (aIsView)
1404              {
1405                  sTableType = "VIEW";
1406              }
1407              else
1408              {
1409                  if (nTableType == 0)
1410                      sTableType = "TABLE";
1411              }
Since nTableType = 2, sTableType stays empty and some debugging shows that the DROP command generated is incomplete.
Comment 2 Commit Notification 2021-12-30 12:21:45 UTC
Julien Nabet committed a patch related to this issue.
It has been pushed to "master":

https://git.libreoffice.org/core/commit/13de0ade50bec34be612ba4a3196c2efd9ce3b4e

tdf#146471: Firebird: impossible to delete an external table

It will be available in 7.4.0.

The patch should be included in the daily builds available at
https://dev-builds.libreoffice.org/daily/ in the next 24-48 hours. More
information about daily builds can be found at:
https://wiki.documentfoundation.org/Testing_Daily_Builds

Affected users are encouraged to test the fix and report feedback.
Comment 3 Julien Nabet 2021-12-30 12:28:38 UTC
Backport for 7.3 waiting for review here:
https://gerrit.libreoffice.org/c/core/+/127584
Comment 4 Commit Notification 2022-01-05 12:33:18 UTC
Julien Nabet committed a patch related to this issue.
It has been pushed to "libreoffice-7-3":

https://git.libreoffice.org/core/commit/d12094654d83f28b292200367939ca7e6144732b

tdf#146471: Firebird: impossible to delete an external table

It will be available in 7.3.0.2.

The patch should be included in the daily builds available at
https://dev-builds.libreoffice.org/daily/ in the next 24-48 hours. More
information about daily builds can be found at:
https://wiki.documentfoundation.org/Testing_Daily_Builds

Affected users are encouraged to test the fix and report feedback.