Date: prev next · Thread: first prev next last
2012 Archives by date, by thread · List index



getColumns() is a XDatabaseMetadata interface function to get the list
of columns of a table and info on these columns.

The PostgreSQL-SDBC implementation in 3.5.0 has a couple of bugs fixed
by the attached patch.

 - If the table previously had a column that has since been dropped
   (removed), the numbering of the columns has a hole, and in some
   circumstances the dropped column is still shown by getColumns().

   "Still shown" fixed by

+                   "AND NOT pg_attribute.attisdropped "

   which is the boolean in the PostgreSQL internals that says "this
   column has been dropped, don't show it anymore".

   Numbering had a hole was because it was using "attnum", the
   internal PostgreSQL numbering of columns. But this internal
   numbering is not contiguous, as the number of dropped columns are
   *not* recycled. This is fixed by:

   * Removing attnum from the query we send to PostgreSQL.
   * Adapt column numbers (shifted by one) every time a column (after
     attnum) is read.
   * Generate our own numbering and put that in the result.

   Note that "#invalid#" cannot be a table or schema name: character
   '#' is not allowed.


 - Entries were sorted by the concatenation (?) of schema name, table
   name, column name. In rare cases, this could lead to wrong order,
   and is slower anyway. Example:

   library, book, bookID
   library, bookShelf, bookShelfID
   library, book, XID

   is sorted in this order by "concatenation", but in this (correct) order
   when sorting by column:

   library, book, bookID
   library, book, XID
   library, bookShelf, bookShelfID


   "||" is the SQL string concatenation operator.


I don't have a smoking gun fdo# of a "point and click user"-visible
bug of this, partially because our internal code is suspicious about
some of this data... See lcl_sanitizeColumnDescs in
connectivity/source/commontools/TTableHelper.cxx.

But I consider Base also as a programming platform,
user code (scripts) is allowed to call any function in
XDatabaseMetadata with any arguments, and giving a wrong result (data)
back is a bug in itself.

So I'd like to have this all fixed in libreoffice-3-5, too.

-- 
Lionel
From 710d460eb9f30f0ba33b3ea6ac6d43e320144513 Mon Sep 17 00:00:00 2001
From: Lionel Elie Mamane <lionel@mamane.lu>
Date: Wed, 1 Feb 2012 17:18:48 +0100
Subject: [PATCH 2/2] postgres getColumns: skip dropped columns, make
 ORDINAL_POSITION consecutive

---
 .../drivers/postgresql/pq_databasemetadata.cxx     |   58 +++++++++++++-------
 1 files changed, 38 insertions(+), 20 deletions(-)

diff --git a/connectivity/source/drivers/postgresql/pq_databasemetadata.cxx 
b/connectivity/source/drivers/postgresql/pq_databasemetadata.cxx
index f359eaa..b3fedf6 100644
--- a/connectivity/source/drivers/postgresql/pq_databasemetadata.cxx
+++ b/connectivity/source/drivers/postgresql/pq_databasemetadata.cxx
@@ -1530,7 +1532,9 @@ static void columnMetaData2DatabaseTypeDescription(
     }
 
     // ignore catalog, as a single pq connection
-    // does not support multiple catalogs eitherway
+    // does not support multiple catalogs anyway
+    // We don't use information_schema.columns because it contains
+    // only the columns the current user has any privilege over.
 
     //  1. TABLE_CAT string => table catalog (may be NULL)
     //               => not supported
@@ -1561,9 +1565,7 @@ static void columnMetaData2DatabaseTypeDescription(
     //                      NULLABLE_UNKNOWN - nullability unknown
     //               => pg_attribute.attnotnull
     //  12. REMARKS string => comment describing column (may be NULL )
-    //               => Don't know, there does not seem to exist something like
-    //                  that in postgres
-    //               LEM TODO: comments exist, find how to retrieve them easily
+    //               => pg_description.description
     //  13. COLUMN_DEF string => default value (may be NULL)
     //               => pg_type.typdefault
     //  14. SQL_DATA_TYPE long => unused
@@ -1591,11 +1593,10 @@ static void columnMetaData2DatabaseTypeDescription(
             "pg_attribute.atttypmod, "       // 5
             "pg_attribute.attnotnull, "      // 6
             "pg_type.typdefault, "           // 7
-            "pg_attribute.attnum, "          // 8
-            "pg_type.typtype, "              // 9
-            "pg_attrdef.adsrc, "             // 10
-            "pg_description.description, "    // 11
-            "pg_type.typbasetype "           // 12
+            "pg_type.typtype, "              // 8
+            "pg_attrdef.adsrc, "             // 9
+            "pg_description.description, "   // 10
+            "pg_type.typbasetype "           // 11
             "FROM pg_class, "
                  "pg_attribute LEFT JOIN pg_attrdef ON pg_attribute.attrelid = pg_attrdef.adrelid 
AND pg_attribute.attnum = pg_attrdef.adnum "
                               "LEFT JOIN pg_description ON pg_attribute.attrelid = 
pg_description.objoid AND pg_attribute.attnum=pg_description.objsubid,"
@@ -1603,10 +1604,11 @@ static void columnMetaData2DatabaseTypeDescription(
             "WHERE pg_attribute.attrelid = pg_class.oid "
                    "AND pg_attribute.atttypid = pg_type.oid "
                    "AND pg_class.relnamespace = pg_namespace.oid "
+                   "AND NOT pg_attribute.attisdropped "
                    "AND pg_namespace.nspname LIKE ? "
                    "AND pg_class.relname LIKE ? "
                    "AND pg_attribute.attname LIKE ? "
-            "ORDER BY pg_namespace.nspname || pg_class.relname || pg_attribute.attnum"
+            "ORDER BY pg_namespace.nspname, pg_class.relname, pg_attribute.attnum"
             ) );
 
     Reference< XParameters > parameters( statement, UNO_QUERY_THROW );
@@ -1632,31 +1634,47 @@ static void columnMetaData2DatabaseTypeDescription(
     Reference< XStatement > domainTypeStmt = m_origin->createStatement();
     columnMetaData2DatabaseTypeDescription( domainMap, rs, domainTypeStmt );
 
+    unsigned int colNum;
+    OUString sSchema( ASCII_STR("#invalid#") );
+    OUString sTable(  ASCII_STR("#invalid#") );
+
     while( rs->next() )
     {
         OUString columnName = xRow->getString(3);
         if( m_pSettings->showSystemColumns || ! isSystemColumn( columnName ) )
         {
+            OUString sNewSchema( xRow->getString(1) );
+            OUString sNewTable(  xRow->getString(2) );
+            if ( sNewSchema != sSchema || sNewTable != sTable )
+            {
+                colNum = 1;
+                sSchema = sNewSchema;
+                sTable = sNewTable;
+            }
+            else
+                ++colNum;
             sal_Int32 precision, scale, type;
             Sequence< Any > row( 18 );
             row[0] <<= m_pSettings->catalog;
-            row[1] <<= xRow->getString(1);  //
-            row[2] <<= xRow->getString(2);
+            row[1] <<= sNewSchema;
+            row[2] <<= sNewTable;
             row[3] <<= columnName;
-            if( xRow->getString(9).equalsAscii( "d" ) )
+            if( xRow->getString(8).equalsAscii( "d" ) )
             {
-                DatabaseTypeDescription desc( domainMap[xRow->getInt(12)] );
+                DatabaseTypeDescription desc( domainMap[xRow->getInt(11)] );
                 type = typeNameToDataType( desc.typeName, desc.typeType );
             }
             else
             {
-                type = typeNameToDataType( xRow->getString(4), xRow->getString(9) );
+                type = typeNameToDataType( xRow->getString(4), xRow->getString(8) );
             }
             extractPrecisionAndScale( type, xRow->getInt(5) , &precision, &scale );
             row[4] <<= type;
             row[5] <<= xRow->getString(4);
             row[6] <<= precision;
+            // row[7] BUFFER_LENGTH not used
             row[8] <<= scale;
+            // row[9] RADIX TODO
             if( xRow->getBoolean( 6 ) && ! isSystemColumn(xRow->getString(3)) )
             {
                 row[10] <<= OUString::valueOf(com::sun::star::sdbc::ColumnValue::NO_NULLS);
@@ -1668,13 +1686,13 @@ static void columnMetaData2DatabaseTypeDescription(
                 row[17] <<= statics.YES;
             }
 
-            row[11] <<= xRow->getString( 11 ); // comment
-            row[12] <<= xRow->getString(10); // COLUMN_DEF = pg_type.typdefault
+            row[11] <<= xRow->getString( 10 ); // comment
+            row[12] <<= xRow->getString( 9 ); // COLUMN_DEF = pg_type.typdefault
+            // row[13] SQL_DATA_TYPE    not used
+            // row[14] SQL_DATETIME_SUB not used
             row[15] <<= precision;
-            row[16] <<= xRow->getString(8) ;
+            row[16] <<= colNum ;
 
-            // no description in postgresql AFAIK
             vec.push_back( row );
         }
     }
-- 
1.7.7.3


Context


Privacy Policy | Impressum (Legal Info) | Copyright information: Unless otherwise specified, all text and images on this website are licensed under the Creative Commons Attribution-Share Alike 3.0 License. This does not include the source code of LibreOffice, which is licensed under the Mozilla Public License (MPLv2). "LibreOffice" and "The Document Foundation" are registered trademarks of their corresponding registered owners or are in actual use as trademarks in one or more countries. Their respective logos and icons are also subject to international copyright laws. Use thereof is explained in our trademark policy.