LCOV - code coverage report
Current view: top level - libreoffice/connectivity/source/drivers/postgresql - pq_databasemetadata.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 0 809 0.0 %
Date: 2012-12-27 Functions: 0 172 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*************************************************************************
       3             :  *
       4             :  *  Effective License of whole file:
       5             :  *
       6             :  *    This library is free software; you can redistribute it and/or
       7             :  *    modify it under the terms of the GNU Lesser General Public
       8             :  *    License version 2.1, as published by the Free Software Foundation.
       9             :  *
      10             :  *    This library is distributed in the hope that it will be useful,
      11             :  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
      12             :  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13             :  *    Lesser General Public License for more details.
      14             :  *
      15             :  *    You should have received a copy of the GNU Lesser General Public
      16             :  *    License along with this library; if not, write to the Free Software
      17             :  *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
      18             :  *    MA  02111-1307  USA
      19             :  *
      20             :  *  Parts "Copyright by Sun Microsystems, Inc" prior to August 2011:
      21             :  *
      22             :  *    The Contents of this file are made available subject to the terms of
      23             :  *    the GNU Lesser General Public License Version 2.1
      24             :  *
      25             :  *    Copyright: 2000 by Sun Microsystems, Inc.
      26             :  *
      27             :  *    Contributor(s): Joerg Budischewski
      28             :  *
      29             :  *  All parts contributed on or after August 2011:
      30             :  *
      31             :  *    Version: MPL 1.1 / GPLv3+ / LGPLv2.1+
      32             :  *
      33             :  *    The contents of this file are subject to the Mozilla Public License Version
      34             :  *    1.1 (the "License"); you may not use this file except in compliance with
      35             :  *    the License or as specified alternatively below. You may obtain a copy of
      36             :  *    the License at http://www.mozilla.org/MPL/
      37             :  *
      38             :  *    Software distributed under the License is distributed on an "AS IS" basis,
      39             :  *    WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      40             :  *    for the specific language governing rights and limitations under the
      41             :  *    License.
      42             :  *
      43             :  *    Major Contributor(s):
      44             :  *    [ Copyright (C) 2011 Lionel Elie Mamane <lionel@mamane.lu> ]
      45             :  *
      46             :  *    All Rights Reserved.
      47             :  *
      48             :  *    For minor contributions see the git repository.
      49             :  *
      50             :  *    Alternatively, the contents of this file may be used under the terms of
      51             :  *    either the GNU General Public License Version 3 or later (the "GPLv3+"), or
      52             :  *    the GNU Lesser General Public License Version 2.1 or later (the "LGPLv2.1+"),
      53             :  *    in which case the provisions of the GPLv3+ or the LGPLv2.1+ are applicable
      54             :  *    instead of those above.
      55             :  *
      56             :  *   Some portions were adapted from JDBC PostgreSQL driver:
      57             :  *
      58             :  *    Copyright (c) 2004-2008, PostgreSQL Global Development Group
      59             :  *
      60             :  *   Licence of original JDBC driver code:
      61             :  *
      62             :  *    Redistribution and use in source and binary forms, with or without
      63             :  *    modification, are permitted provided that the following conditions are met:
      64             :  *
      65             :  *    1. Redistributions of source code must retain the above copyright notice,
      66             :  *       this list of conditions and the following disclaimer.
      67             :  *    2. Redistributions in binary form must reproduce the above copyright notice,
      68             :  *       this list of conditions and the following disclaimer in the documentation
      69             :  *       and/or other materials provided with the distribution.
      70             :  *    3. Neither the name of the PostgreSQL Global Development Group nor the names
      71             :  *       of its contributors may be used to endorse or promote products derived
      72             :  *       from this software without specific prior written permission.
      73             :  *
      74             :  *    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
      75             :  *    AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      76             :  *    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      77             :  *    ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
      78             :  *    LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
      79             :  *    CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
      80             :  *    SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
      81             :  *    INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
      82             :  *    CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
      83             :  *    ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
      84             :  *    POSSIBILITY OF SUCH DAMAGE.
      85             :  *
      86             :  ************************************************************************/
      87             : 
      88             : #include <algorithm>
      89             : #include "pq_databasemetadata.hxx"
      90             : #include "pq_driver.hxx"
      91             : #include "pq_sequenceresultset.hxx"
      92             : #include "pq_statics.hxx"
      93             : #include "pq_tools.hxx"
      94             : 
      95             : #include <rtl/ustrbuf.hxx>
      96             : 
      97             : #include<com/sun/star/sdbc/TransactionIsolation.hpp>
      98             : #include<com/sun/star/sdbc/ResultSetType.hpp>
      99             : #include<com/sun/star/sdbc/XPreparedStatement.hpp>
     100             : #include<com/sun/star/sdbc/XParameters.hpp>
     101             : #include<com/sun/star/sdbc/DataType.hpp>
     102             : #include<com/sun/star/sdbc/IndexType.hpp>
     103             : #include<com/sun/star/sdbc/ColumnValue.hpp>
     104             : #include<com/sun/star/sdbc/ColumnSearch.hpp>
     105             : #include<com/sun/star/sdbc/KeyRule.hpp>
     106             : #include<com/sun/star/sdbc/Deferrability.hpp>
     107             : 
     108             : using ::osl::MutexGuard;
     109             : 
     110             : using ::rtl::OUString;
     111             : 
     112             : using namespace com::sun::star::sdbc;
     113             : 
     114             : using com::sun::star::uno::RuntimeException;
     115             : using com::sun::star::uno::Sequence;
     116             : 
     117             : using com::sun::star::uno::Reference;
     118             : using com::sun::star::uno::Sequence;
     119             : using com::sun::star::uno::Any;
     120             : using com::sun::star::uno::makeAny;
     121             : using com::sun::star::uno::UNO_QUERY;
     122             : using com::sun::star::uno::UNO_QUERY_THROW;
     123             : 
     124             : namespace pq_sdbc_driver
     125             : {
     126             : typedef
     127             : std::vector
     128             : <
     129             :     com::sun::star::uno::Sequence< com::sun::star::uno::Any >,
     130             :     Allocator< com::sun::star::uno::Sequence< com::sun::star::uno::Any > >
     131             : > SequenceAnyVector;
     132             : 
     133             : 
     134             : #define ASCII_STR(x) OUString( RTL_CONSTASCII_USTRINGPARAM( x ) )
     135             : 
     136             : #define QUOTEME(X)  #X
     137             : #define STRINGIFY(X) QUOTEME(X)
     138             : 
     139             : // These are pre-processor versions of KeyRule.idl declarations
     140             : // These are inherited from JDBC, and thus won't change anytime soon.
     141             : // Having them as pre-processor definitions allows to include them
     142             : // into compile-time strings (through STRINGIFY), which can be passed to ASCII_STR.
     143             : // That is without resorting to horrendeous hacks in template meta-programming.
     144             : #define KEYRULE_CASCADE      0
     145             : #define KEYRULE_RESTRICT     1
     146             : #define KEYRULE_SET_NULL     2
     147             : #define KEYRULE_NO_ACTION    4
     148             : #define KEYRULE_SET_DEFAULT  4
     149             : // Ditto for Deferrability.idl
     150             : #define DEFERRABILITY_INITIALLY_DEFERRED  5
     151             : #define DEFERRABILITY_INITIALLY_IMMEDIATE 6
     152             : #define DEFERRABILITY_NONE                7
     153             : 
     154             : // alphabetically ordered !
     155             : static const int PRIVILEGE_CREATE     = 0x1;
     156             : static const int PRIVILEGE_DELETE     = 0x2;
     157             : static const int PRIVILEGE_EXECUTE    = 0x4;
     158             : static const int PRIVILEGE_INSERT     = 0x8;
     159             : static const int PRIVILEGE_REFERENCES = 0x10;
     160             : static const int PRIVILEGE_RULE       = 0x20;
     161             : static const int PRIVILEGE_SELECT     = 0x40;
     162             : static const int PRIVILEGE_TEMPORARY  = 0x80;
     163             : static const int PRIVILEGE_TRIGGER    = 0x100;
     164             : static const int PRIVILEGE_UPDATE     = 0x200;
     165             : static const int PRIVILEGE_USAGE      = 0x400;
     166             : static const int PRIVILEGE_MAX = PRIVILEGE_USAGE;
     167             : 
     168           0 : void DatabaseMetaData::checkClosed()
     169             :         throw (SQLException, RuntimeException)
     170             : {
     171           0 : }
     172             : 
     173           0 : DatabaseMetaData::DatabaseMetaData(
     174             :     const ::rtl::Reference< RefCountedMutex > & refMutex,
     175             :     const ::com::sun::star::uno::Reference< com::sun::star::sdbc::XConnection >  & origin,
     176             :     ConnectionSettings *pSettings )
     177             :   : m_refMutex( refMutex ),
     178             :     m_pSettings( pSettings ),
     179             :     m_origin( origin ),
     180           0 :     m_getIntSetting_stmt ( m_origin->prepareStatement(ASCII_STR( "SELECT setting FROM pg_catalog.pg_settings WHERE name=?" )) )
     181             : {
     182           0 :     init_getReferences_stmt();
     183           0 :     init_getPrivs_stmt();
     184           0 : }
     185             : 
     186           0 : sal_Bool DatabaseMetaData::allProceduresAreCallable(  ) throw (SQLException, RuntimeException)
     187             : {
     188             :     // TODO
     189           0 :     return sal_False;
     190             : }
     191             : 
     192           0 : sal_Bool DatabaseMetaData::allTablesAreSelectable(  ) throw (SQLException, RuntimeException)
     193             : {
     194           0 :     return sal_True;
     195             : }
     196             : 
     197           0 : OUString DatabaseMetaData::getURL(  ) throw (SQLException, RuntimeException)
     198             : {
     199             :     // TODO
     200             :     // LEM TODO: implement
     201           0 :     return OUString();
     202             : }
     203             : 
     204           0 : OUString DatabaseMetaData::getUserName(  ) throw (SQLException, RuntimeException)
     205             : {
     206           0 :     return m_pSettings->user;
     207             : }
     208             : 
     209           0 : sal_Bool DatabaseMetaData::isReadOnly(  ) throw (SQLException, RuntimeException)
     210             : {
     211           0 :     return sal_False;
     212             : }
     213             : 
     214             : 
     215           0 : sal_Bool DatabaseMetaData::nullsAreSortedHigh(  ) throw (SQLException, RuntimeException)
     216             : {
     217             :     // Whether NULL values are considered, for sorting purposes, LARGER than any other value.
     218             :     // Specification: http://download.oracle.com/javase/6/docs/api/java/sql/DatabaseMetaData.html#nullsAreSortedHigh()
     219             :     // PostgreSQL behaviour: http://www.postgresql.org/docs/9.1/static/queries-order.htlm
     220           0 :     return sal_True;
     221             : }
     222             : 
     223           0 : sal_Bool DatabaseMetaData::nullsAreSortedLow(  ) throw (SQLException, RuntimeException)
     224             : {
     225           0 :     return ! nullsAreSortedHigh();
     226             : }
     227             : 
     228           0 : sal_Bool DatabaseMetaData::nullsAreSortedAtStart(  ) throw (SQLException, RuntimeException)
     229             : {
     230           0 :     return sal_False;
     231             : }
     232             : 
     233           0 : sal_Bool DatabaseMetaData::nullsAreSortedAtEnd(  ) throw (SQLException, RuntimeException)
     234             : {
     235           0 :     return sal_False;
     236             : }
     237             : 
     238           0 : OUString DatabaseMetaData::getDatabaseProductName(  ) throw (SQLException, RuntimeException)
     239             : {
     240           0 :     return ASCII_STR("PostgreSQL");
     241             : }
     242             : 
     243           0 : OUString DatabaseMetaData::getDatabaseProductVersion(  ) throw (SQLException, RuntimeException)
     244             : {
     245           0 :     return rtl::OUString::createFromAscii( PQparameterStatus( m_pSettings->pConnection, "server_version" ) );
     246             : }
     247           0 : OUString DatabaseMetaData::getDriverName(  ) throw (SQLException, RuntimeException)
     248             : {
     249           0 :     return ASCII_STR( "postgresql-sdbc" );
     250             : }
     251             : 
     252           0 : OUString DatabaseMetaData::getDriverVersion(  ) throw (SQLException, RuntimeException)
     253             : {
     254           0 :     return ASCII_STR( PQ_SDBC_DRIVER_VERSION );
     255             : }
     256             : 
     257           0 : sal_Int32 DatabaseMetaData::getDriverMajorVersion(  ) throw (RuntimeException)
     258             : {
     259           0 :     return PQ_SDBC_MAJOR;
     260             : }
     261             : 
     262           0 : sal_Int32 DatabaseMetaData::getDriverMinorVersion(  ) throw (RuntimeException)
     263             : {
     264           0 :     return PQ_SDBC_MINOR;
     265             : }
     266             : 
     267           0 : sal_Bool DatabaseMetaData::usesLocalFiles(  ) throw (SQLException, RuntimeException)
     268             : {
     269             :     // LEM TODO:
     270             :     //           http://wiki.services.openoffice.org/wiki/Documentation/DevGuide/Database/XDatabaseMetaData_Interface
     271             :     //           says "Returns true when the catalog name of the
     272             :     //           database should not appear in the DatasourceBrowser
     273             :     //           of OpenOffice.org API, otherwise false is returned."
     274             :     //           So, hmmm, think about it.
     275           0 :     return sal_False;
     276             : }
     277             : 
     278           0 : sal_Bool DatabaseMetaData::usesLocalFilePerTable(  ) throw (SQLException, RuntimeException)
     279             : {
     280           0 :     return sal_False;
     281             : }
     282             : 
     283           0 : sal_Bool DatabaseMetaData::supportsMixedCaseIdentifiers(  ) throw (SQLException, RuntimeException)
     284             : {
     285           0 :     return sal_False;
     286             : }
     287             : 
     288           0 : sal_Bool DatabaseMetaData::storesUpperCaseIdentifiers(  ) throw (SQLException, RuntimeException)
     289             : {
     290           0 :     return sal_False;
     291             : }
     292             : 
     293           0 : sal_Bool DatabaseMetaData::storesLowerCaseIdentifiers(  ) throw (SQLException, RuntimeException)
     294             : {
     295           0 :     return sal_True;
     296             : }
     297             : 
     298             : 
     299           0 : sal_Bool DatabaseMetaData::storesMixedCaseIdentifiers(  ) throw (SQLException, RuntimeException)
     300             : {
     301           0 :     return sal_False;
     302             : }
     303             : 
     304             : 
     305           0 : sal_Bool DatabaseMetaData::supportsMixedCaseQuotedIdentifiers(  ) throw (SQLException, RuntimeException)
     306             : {
     307           0 :     return sal_True;
     308             : }
     309             : 
     310           0 : sal_Bool DatabaseMetaData::storesUpperCaseQuotedIdentifiers(  ) throw (SQLException, RuntimeException)
     311             : {
     312           0 :     return sal_False;
     313             : }
     314             : 
     315             : 
     316           0 : sal_Bool DatabaseMetaData::storesLowerCaseQuotedIdentifiers(  ) throw (SQLException, RuntimeException)
     317             : {
     318           0 :     return sal_False;
     319             : }
     320             : 
     321             : 
     322           0 : sal_Bool DatabaseMetaData::storesMixedCaseQuotedIdentifiers(  ) throw (SQLException, RuntimeException)
     323             : {
     324           0 :     return sal_False;
     325             : }
     326             : 
     327             : 
     328           0 : OUString DatabaseMetaData::getIdentifierQuoteString(  ) throw (SQLException, RuntimeException)
     329             : {
     330           0 :     return ASCII_STR( "\"" );
     331             : }
     332             : 
     333           0 : OUString DatabaseMetaData::getSQLKeywords(  ) throw (SQLException, RuntimeException)
     334             : {
     335             :     // In Java 6, this is all keywords that are not SQL:2003
     336             :     // In Java 2 v1.4 and as per LibreOffice SDK doc, this is all keywords that are not SQL92
     337             :     // I understand this to mean "reserved keywords" only.
     338             :     // See http://www.postgresql.org/docs/current/static/sql-keywords-appendix.html
     339           0 :     return ASCII_STR(
     340             :         "ANALYSE,"
     341             :         "ANALYZE,"
     342             :         "ARRAY," //SQL:1999
     343             :         "ASYMMETRIC," //SQL:2003
     344             :         "BINARY," //SQL:1999
     345             :         "CONCURRENTLY,"
     346             :         "CURRENT_CATALOG," //SQL:2008
     347             :         "CURRENT_ROLE," //SQL:1999
     348             :         "CURRENT_SCHEMA," //SQL:2008
     349             :         "DO,"
     350             :         "FREEZE,"
     351             :         "ILIKE,"
     352             :         "ISNULL,"
     353             :         "LIMIT," //SQL:1999; non-reserved in SQL:2003
     354             :         "LOCALTIME," //SQL:1999
     355             :         "LOCALTIMESTAMP," //SQL:1999
     356             :         "NOTNULL,"
     357             :         "OFFSET," //SQL:2008
     358             :         "OVER," //SQL:2003
     359             :         "PLACING," //non-reserved in SQL:2003
     360             :         "RETURNING," //non-reserved in SQL:2008
     361             :         "SIMILAR," //SQL:2003
     362             :         "VARIADIC,"
     363             :         "VERBOSE,"
     364             :         "WINDOW" //SQL:2003
     365             :  );
     366             : }
     367           0 : OUString DatabaseMetaData::getNumericFunctions(  ) throw (SQLException, RuntimeException)
     368             : {
     369             :     // See http://www.postgresql.org/docs/9.1/static/functions-math.html
     370             :     // LEM TODO: Err... http://wiki.services.openoffice.org/wiki/Documentation/DevGuide/Database/Support_Scalar_Functions
     371             :     //           says this should be "Open Group CLI" names, not PostgreSQL names.
     372             :     //           Currently this is just a list of supported functions in PostgreSQL, with PostgreSQL names.
     373             :     //           And it is my job to map from Open Group CLI names/syntax to PostgreSQL names/syntax. Where? By parsing the SQL???
     374             :     //           Should look at what the JDBC driver is doing.
     375           0 :     return ASCII_STR(
     376             :         "abs,"
     377             :         "cbrt,"
     378             :         "ceil,"
     379             :         "ceiling,"
     380             :         "degrees,"
     381             :         "div,"
     382             :         "exp,"
     383             :         "floor,"
     384             :         "ln,"
     385             :         "log,"
     386             :         "mod,"
     387             :         "pi,"
     388             :         "power,"
     389             :         "radians,"
     390             :         "random,"
     391             :         "round,"
     392             :         "setseed,"
     393             :         "sign,"
     394             :         "sqrt,"
     395             :         "trunc,"
     396             :         "width_bucket,"
     397             :         "acos,"
     398             :         "asin,"
     399             :         "atan,"
     400             :         "atan2,"
     401             :         "cos,"
     402             :         "cot,"
     403             :         "sin,"
     404             :         "tan"
     405             :  );
     406             : }
     407             : 
     408           0 : OUString DatabaseMetaData::getStringFunctions(  ) throw (SQLException, RuntimeException)
     409             : {
     410             :     // See http://www.postgresql.org/docs/9.1/static/functions-string.html
     411           0 :     return ASCII_STR(
     412             :         "bit_length,"
     413             :         "char_length,"
     414             :         "character_length,"
     415             :         "lower,"
     416             :         "octet_length,"
     417             :         "overlay,"
     418             :         "position,"
     419             :         "substring,"
     420             :         "trim,"
     421             :         "upper,"
     422             :         "ascii,"
     423             :         "btrim,"
     424             :         "chr,"
     425             :         "concat,"
     426             :         "concat_ws,"
     427             :         "convert,"
     428             :         "convert_from,"
     429             :         "convert_to,"
     430             :         "decode,"
     431             :         "encode,"
     432             :         "foramt,"
     433             :         "initcap,"
     434             :         "left,"
     435             :         "length,"
     436             :         "lpad,"
     437             :         "ltrim,"
     438             :         "md5,"
     439             :         "pg_client_encoding,"
     440             :         "quote_ident,"
     441             :         "quote_literal,"
     442             :         "quote_nullable,"
     443             :         "regexp_matches,"
     444             :         "regexp_replace,"
     445             :         "regexp_split_to_array,"
     446             :         "regexp_split_to_table,"
     447             :         "repeat,"
     448             :         "replace,"
     449             :         "reverse,"
     450             :         "right,"
     451             :         "rpad,"
     452             :         "rtrim,"
     453             :         "split_part,"
     454             :         "strpos,"
     455             :         "substr,"
     456             :         "to_ascii,"
     457             :         "to_hex,"
     458             :         "translate"
     459             :  );
     460             : }
     461             : 
     462           0 : OUString DatabaseMetaData::getSystemFunctions(  ) throw (SQLException, RuntimeException)
     463             : {
     464             :     // See http://www.postgresql.org/docs/9.1/static/functions-info.html
     465             :     // and http://www.postgresql.org/docs/9.1/static/functions-admin.html
     466           0 :     return ASCII_STR(
     467             :         "current_catalog,"
     468             :         "current_database,"
     469             :         "current_query,"
     470             :         "current_schema,"
     471             :         "current_schemas,"
     472             :         "current_user,"
     473             :         "inet_client_addr,"
     474             :         "inet_client_port,"
     475             :         "inet_server_addr,"
     476             :         "inet_server_port,"
     477             :         "pg_backend_pid,"
     478             :         "pg_conf_load_time,"
     479             :         "pg_is_other_temp_schema,"
     480             :         "pg_listening_channels,"
     481             :         "pg_my_temp_schema,"
     482             :         "pg_postmaster_start_time,"
     483             :         "session_user,"
     484             :         "user,"
     485             :         "version,"
     486             :         "has_any_column_privilege,"
     487             :         "has_any_column_privilege,"
     488             :         "has_any_column_privilege,"
     489             :         "has_column_privilege,"
     490             :         "has_database_privilege,"
     491             :         "has_foreign_data_wrapper_privilege,"
     492             :         "has_function_privilege,"
     493             :         "has_language_privilege,"
     494             :         "has_schema_privilege,"
     495             :         "has_sequence_privilege,"
     496             :         "has_server_privilege,"
     497             :         "has_table_privilege,"
     498             :         "has_tablespace_privilege,"
     499             :         "pg_has_role,"
     500             :         "pg_collation_is_visible,"
     501             :         "pg_conversion_is_visible,"
     502             :         "pg_function_is_visible,"
     503             :         "pg_opclass_is_visible,"
     504             :         "pg_operator_is_visible,"
     505             :         "pg_table_is_visible,"
     506             :         "pg_ts_config_is_visible,"
     507             :         "pg_ts_dict_is_visible,"
     508             :         "pg_ts_parser_is_visible,"
     509             :         "pg_ts_template_is_visible,"
     510             :         "pg_type_is_visible,"
     511             :         "format_type,"
     512             :         "pg_describe_object,"
     513             :         "pg_get_constraintdef,"
     514             :         "pg_get_expr,"
     515             :         "pg_get_functiondef,"
     516             :         "pg_get_function_arguments,"
     517             :         "pg_get_function_identity_arguments,"
     518             :         "pg_get_function_result,"
     519             :         "pg_get_indexdef,"
     520             :         "pg_get_keywords,"
     521             :         "pg_get_ruledef,"
     522             :         "pg_get_serial_sequence,"
     523             :         "pg_get_triggerdef,"
     524             :         "pg_get_userbyid,"
     525             :         "pg_get_viewdef,"
     526             :         "pg_options_to_table,"
     527             :         "pg_tablespace_databases,"
     528             :         "pg_typeof,"
     529             :         "col_description,"
     530             :         "obj_description,"
     531             :         "shobj_description,"
     532             :         "txid_current,"
     533             :         "txid_current_snapshot,"
     534             :         "txid_snapshot_xip,"
     535             :         "txid_snapshot_xmax,"
     536             :         "txid_snapshot_xmin,"
     537             :         "txid_visible_in_snapshot,"
     538             :         "xmin,"
     539             :         "xmax,"
     540             :         "xip_list,"
     541             :         "current_setting,"
     542             :         "set_config,"
     543             :         "pg_cancel_backend,"
     544             :         "pg_reload_conf,"
     545             :         "pg_rotate_logfile,"
     546             :         "pg_terminate_backend,"
     547             :         "pg_create_restore_point,"
     548             :         "pg_current_xlog_insert_location,"
     549             :         "pg_current_xlog_location,"
     550             :         "pg_start_backup,"
     551             :         "pg_stop_backup,"
     552             :         "pg_switch_xlog,"
     553             :         "pg_xlogfile_name,"
     554             :         "pg_xlogfile_name_offset,"
     555             :         "pg_is_in_recovery,"
     556             :         "pg_last_xlog_receive_location,"
     557             :         "pg_last_xlog_replay_location,"
     558             :         "pg_last_xact_replay_timestamp,"
     559             :         "pg_is_xlog_replay_paused,"
     560             :         "pg_xlog_replay_pause,"
     561             :         "pg_xlog_replay_resume,"
     562             :         "pg_column_size,"
     563             :         "pg_database_size,"
     564             :         "pg_indexes_size,"
     565             :         "pg_relation_size,"
     566             :         "pg_size_pretty,"
     567             :         "pg_table_size,"
     568             :         "pg_tablespace_size,"
     569             :         "pg_tablespace_size,"
     570             :         "pg_total_relation_size,"
     571             :         "pg_relation_filenode,"
     572             :         "pg_relation_filepath,"
     573             :         "pg_ls_dir,"
     574             :         "pg_read_file,"
     575             :         "pg_read_binary_file,"
     576             :         "pg_stat_file,"
     577             :         "pg_advisory_lock,"
     578             :         "pg_advisory_lock_shared,"
     579             :         "pg_advisory_unlock,"
     580             :         "pg_advisory_unlock_all,"
     581             :         "pg_advisory_unlock_shared,"
     582             :         "pg_advisory_xact_lock,"
     583             :         "pg_advisory_xact_lock_shared,"
     584             :         "pg_try_advisory_lock,"
     585             :         "pg_try_advisory_lock_shared,"
     586             :         "pg_try_advisory_xact_lock,"
     587             :         "pg_try_advisory_xact_lock_shared,"
     588             :         "pg_sleep"
     589             :  );
     590             : }
     591           0 : OUString DatabaseMetaData::getTimeDateFunctions(  ) throw (SQLException, RuntimeException)
     592             : {
     593             :     // TODO
     594           0 :     return ASCII_STR(
     595             :         "age,"
     596             :         "age,"
     597             :         "clock_timestamp,"
     598             :         "current_date,"
     599             :         "current_time,"
     600             :         "current_timestamp,"
     601             :         "date_part,"
     602             :         "date_part,"
     603             :         "date_trunc,"
     604             :         "extract,"
     605             :         "extract,"
     606             :         "isfinite,"
     607             :         "isfinite,"
     608             :         "isfinite,"
     609             :         "justify_days,"
     610             :         "justify_hours,"
     611             :         "justify_interval,"
     612             :         "localtime,"
     613             :         "localtimestamp,"
     614             :         "now,"
     615             :         "statement_timestamp,"
     616             :         "timeofday,"
     617             :         "transaction_timestamp,"
     618             :  );
     619             : }
     620           0 : OUString DatabaseMetaData::getSearchStringEscape(  ) throw (SQLException, RuntimeException)
     621             : {
     622           0 :     return ASCII_STR( "\\" );
     623             : }
     624           0 : OUString DatabaseMetaData::getExtraNameCharacters(  ) throw (SQLException, RuntimeException)
     625             : {
     626           0 :     return ASCII_STR( "$" );
     627             : }
     628             : 
     629           0 : sal_Bool DatabaseMetaData::supportsAlterTableWithAddColumn(  ) throw (SQLException, RuntimeException)
     630             : {
     631           0 :     return sal_True;
     632             : }
     633             : 
     634           0 : sal_Bool DatabaseMetaData::supportsAlterTableWithDropColumn(  ) throw (SQLException, RuntimeException)
     635             : {
     636           0 :     return sal_True;
     637             : }
     638             : 
     639           0 : sal_Bool DatabaseMetaData::supportsColumnAliasing(  ) throw (SQLException, RuntimeException)
     640             : {
     641           0 :     return sal_True;
     642             : }
     643             : 
     644           0 : sal_Bool DatabaseMetaData::nullPlusNonNullIsNull(  ) throw (SQLException, RuntimeException)
     645             : {
     646           0 :     return sal_True;
     647             : }
     648             : 
     649           0 : sal_Bool DatabaseMetaData::supportsTypeConversion(  ) throw (SQLException, RuntimeException)
     650             : {
     651             :     // LEM: this is specifically whether the "CONVERT" function is supported
     652             :     //      It seems that in PostgreSQL, that function is only for string encoding, so no.
     653           0 :     return sal_False;
     654             : }
     655             : 
     656           0 : sal_Bool DatabaseMetaData::supportsConvert( sal_Int32 fromType, sal_Int32 toType ) throw (SQLException, RuntimeException)
     657             : {
     658             :     (void) fromType; (void) toType;
     659           0 :     return sal_False;
     660             : }
     661             : 
     662           0 : sal_Bool DatabaseMetaData::supportsTableCorrelationNames(  ) throw (SQLException, RuntimeException)
     663             : {
     664             :     // LEM: A correlation name is "bar" in "SELECT foo FROM qux [AS] bar WHERE ..."
     665           0 :     return sal_True;
     666             : }
     667             : 
     668             : 
     669           0 : sal_Bool DatabaseMetaData::supportsDifferentTableCorrelationNames(  ) throw (SQLException, RuntimeException)
     670             : {
     671           0 :     return sal_False;
     672             : }
     673           0 : sal_Bool DatabaseMetaData::supportsExpressionsInOrderBy(  ) throw (SQLException, RuntimeException)
     674             : {
     675           0 :     return sal_True;
     676             : }
     677             : 
     678           0 : sal_Bool DatabaseMetaData::supportsOrderByUnrelated(  ) throw (SQLException, RuntimeException)
     679             : {
     680           0 :     return sal_True;
     681             : }
     682             : 
     683           0 : sal_Bool DatabaseMetaData::supportsGroupBy(  ) throw (SQLException, RuntimeException)
     684             : {
     685           0 :     return sal_True;
     686             : }
     687             : 
     688           0 : sal_Bool DatabaseMetaData::supportsGroupByUnrelated(  ) throw (SQLException, RuntimeException)
     689             : {
     690           0 :     return sal_True;
     691             : }
     692             : 
     693           0 : sal_Bool DatabaseMetaData::supportsGroupByBeyondSelect(  ) throw (SQLException, RuntimeException)
     694             : {
     695           0 :     return sal_True;
     696             : }
     697             : 
     698           0 : sal_Bool DatabaseMetaData::supportsLikeEscapeClause(  ) throw (SQLException, RuntimeException)
     699             : {
     700           0 :     return sal_True;
     701             : }
     702             : 
     703           0 : sal_Bool DatabaseMetaData::supportsMultipleResultSets(  ) throw (SQLException, RuntimeException)
     704             : {
     705           0 :     return sal_True;
     706             : }
     707             : 
     708           0 : sal_Bool DatabaseMetaData::supportsMultipleTransactions(  ) throw (SQLException, RuntimeException)
     709             : {
     710             :     // Allows multiple transactions open at once (on different connections!)
     711           0 :     return sal_True;
     712             : }
     713             : 
     714           0 : sal_Bool DatabaseMetaData::supportsNonNullableColumns(  ) throw (SQLException, RuntimeException)
     715             : {
     716           0 :     return sal_True;
     717             : }
     718             : 
     719             : 
     720           0 : sal_Bool DatabaseMetaData::supportsMinimumSQLGrammar(  ) throw (SQLException, RuntimeException)
     721             : {
     722           0 :     return sal_True;
     723             : }
     724             : 
     725           0 : sal_Bool DatabaseMetaData::supportsCoreSQLGrammar(  ) throw (SQLException, RuntimeException)
     726             : {
     727             :     // LEM: jdbc driver says not, although the comments in it seem old
     728             :     //      fdo#45249 Base query design won't use any aggregate function
     729             :     //      (except COUNT(*) unless we say yes, so say yes.
     730             :     //      Actually, Base assumes *also* support for aggregate functions "collect, fusion, intersection"
     731             :     //      as soon as supportsCoreSQLGrammar() returns true.
     732             :     //      Those are *not* Core SQL, though. They are in optional feature S271 "Basic multiset support"
     733           0 :     return sal_True;
     734             : }
     735             : 
     736           0 : sal_Bool DatabaseMetaData::supportsExtendedSQLGrammar(  ) throw (SQLException, RuntimeException)
     737             : {
     738           0 :     return sal_False;
     739             : }
     740             : 
     741           0 : sal_Bool DatabaseMetaData::supportsANSI92EntryLevelSQL(  ) throw (SQLException, RuntimeException)
     742             : {
     743           0 :     return sal_True;
     744             : }
     745             : 
     746           0 : sal_Bool DatabaseMetaData::supportsANSI92IntermediateSQL(  ) throw (SQLException, RuntimeException)
     747             : {
     748             :     // LEM: jdbc driver says not, although the comments in it seem old
     749           0 :     return sal_False;
     750             : }
     751             : 
     752           0 : sal_Bool DatabaseMetaData::supportsANSI92FullSQL(  ) throw (SQLException, RuntimeException)
     753             : {
     754             :     // LEM: jdbc driver says not, although the comments in it seem old
     755           0 :     return sal_False;
     756             : }
     757             : 
     758           0 : sal_Bool DatabaseMetaData::supportsIntegrityEnhancementFacility(  ) throw (SQLException, RuntimeException)
     759             : {
     760             :     // LEM: jdbc driver says yes, although comment says they are not sure what this means...
     761           0 :     return sal_True;
     762             : }
     763             : 
     764           0 : sal_Bool DatabaseMetaData::supportsOuterJoins(  ) throw (SQLException, RuntimeException)
     765             : {
     766           0 :     return sal_True;
     767             : }
     768             : 
     769           0 : sal_Bool DatabaseMetaData::supportsFullOuterJoins(  ) throw (SQLException, RuntimeException)
     770             : {
     771           0 :     return sal_True;
     772             : }
     773             : 
     774           0 : sal_Bool DatabaseMetaData::supportsLimitedOuterJoins(  ) throw (SQLException, RuntimeException)
     775             : {
     776           0 :     return sal_True;
     777             : }
     778             : 
     779             : 
     780           0 : OUString DatabaseMetaData::getSchemaTerm(  ) throw (SQLException, RuntimeException)
     781             : {
     782           0 :     return ASCII_STR( "SCHEMA" );
     783             : }
     784             : 
     785           0 : OUString DatabaseMetaData::getProcedureTerm(  ) throw (SQLException, RuntimeException)
     786             : {
     787           0 :     return ASCII_STR( "function" );
     788             : }
     789             : 
     790           0 : OUString DatabaseMetaData::getCatalogTerm(  ) throw (SQLException, RuntimeException)
     791             : {
     792           0 :     return ASCII_STR( "DATABASE" );
     793             : }
     794             : 
     795           0 : sal_Bool DatabaseMetaData::isCatalogAtStart(  ) throw (SQLException, RuntimeException)
     796             : {
     797             : 
     798           0 :     return sal_True;
     799             : }
     800             : 
     801           0 : OUString DatabaseMetaData::getCatalogSeparator(  ) throw (SQLException, RuntimeException)
     802             : {
     803           0 :     return ASCII_STR( "." );
     804             : }
     805             : 
     806           0 : sal_Bool DatabaseMetaData::supportsSchemasInDataManipulation(  ) throw (SQLException, RuntimeException)
     807             : {
     808           0 :     return sal_True;
     809             : }
     810             : 
     811           0 : sal_Bool DatabaseMetaData::supportsSchemasInProcedureCalls(  ) throw (SQLException, RuntimeException)
     812             : {
     813           0 :     return sal_True;
     814             : }
     815             : 
     816           0 : sal_Bool DatabaseMetaData::supportsSchemasInTableDefinitions(  ) throw (SQLException, RuntimeException)
     817             : {
     818           0 :     return sal_True;
     819             : }
     820             : 
     821           0 : sal_Bool DatabaseMetaData::supportsSchemasInIndexDefinitions(  ) throw (SQLException, RuntimeException)
     822             : {
     823           0 :     return sal_True;
     824             : }
     825             : 
     826           0 : sal_Bool DatabaseMetaData::supportsSchemasInPrivilegeDefinitions(  ) throw (SQLException, RuntimeException)
     827             : {
     828           0 :     return sal_True;
     829             : }
     830             : 
     831           0 : sal_Bool DatabaseMetaData::supportsCatalogsInDataManipulation(  ) throw (SQLException, RuntimeException)
     832             : {
     833           0 :     return sal_False;
     834             : }
     835             : 
     836           0 : sal_Bool DatabaseMetaData::supportsCatalogsInProcedureCalls(  ) throw (SQLException, RuntimeException)
     837             : {
     838           0 :     return sal_False;
     839             : }
     840             : 
     841           0 : sal_Bool DatabaseMetaData::supportsCatalogsInTableDefinitions(  ) throw (SQLException, RuntimeException)
     842             : {
     843           0 :     return sal_False;
     844             : }
     845             : 
     846             : 
     847           0 : sal_Bool DatabaseMetaData::supportsCatalogsInIndexDefinitions(  ) throw (SQLException, RuntimeException)
     848             : {
     849           0 :     return sal_False;
     850             : }
     851             : 
     852             : 
     853           0 : sal_Bool DatabaseMetaData::supportsCatalogsInPrivilegeDefinitions(  ) throw (SQLException, RuntimeException)
     854             : {
     855           0 :     return sal_False;
     856             : }
     857             : 
     858             : 
     859             : // LEM TODO: positioned (through cursor) updates and deletes seem
     860             : // to be supported; see {UPDATE,DELETE} /table/ (...) WHERE CURRENT OF /cursor_name/" syntax
     861             : // and http://www.postgresql.org/docs/9.1/static/view-pg-cursors.html
     862             : // http://www.postgresql.org/docs/9.1/static/libpq-example.html actually uses a cursor :)
     863           0 : sal_Bool DatabaseMetaData::supportsPositionedDelete(  ) throw (SQLException, RuntimeException)
     864             : {
     865             :     // LEM: jdbc driver says not, although the comments in it seem old
     866           0 :     return sal_False;
     867             : }
     868             : 
     869           0 : sal_Bool DatabaseMetaData::supportsPositionedUpdate(  ) throw (SQLException, RuntimeException)
     870             : {
     871             :     // LEM: jdbc driver says not, although the comments in it seem old
     872           0 :     return sal_False;
     873             : }
     874             : 
     875             : 
     876           0 : sal_Bool DatabaseMetaData::supportsSelectForUpdate(  ) throw (SQLException, RuntimeException)
     877             : {
     878           0 :     return sal_True;
     879             : }
     880             : 
     881             : 
     882           0 : sal_Bool DatabaseMetaData::supportsStoredProcedures(  ) throw (SQLException, RuntimeException)
     883             : {
     884           0 :     return sal_True;
     885             : }
     886             : 
     887             : 
     888           0 : sal_Bool DatabaseMetaData::supportsSubqueriesInComparisons(  ) throw (SQLException, RuntimeException)
     889             : {
     890           0 :     return sal_True;
     891             : }
     892             : 
     893           0 : sal_Bool DatabaseMetaData::supportsSubqueriesInExists(  ) throw (SQLException, RuntimeException)
     894             : {
     895           0 :     return sal_True;
     896             : }
     897             : 
     898           0 : sal_Bool DatabaseMetaData::supportsSubqueriesInIns(  ) throw (SQLException, RuntimeException)
     899             : {
     900           0 :     return sal_True;
     901             : }
     902             : 
     903           0 : sal_Bool DatabaseMetaData::supportsSubqueriesInQuantifieds(  ) throw (SQLException, RuntimeException)
     904             : {
     905             :     // LEM: jdbc driver says yes, although comment says they don't know what this means...
     906           0 :     return sal_True;
     907             : }
     908             : 
     909           0 : sal_Bool DatabaseMetaData::supportsCorrelatedSubqueries(  ) throw (SQLException, RuntimeException)
     910             : {
     911           0 :     return sal_True;
     912             : }
     913           0 : sal_Bool DatabaseMetaData::supportsUnion(  ) throw (SQLException, RuntimeException)
     914             : {
     915           0 :     return sal_True;
     916             : }
     917             : 
     918           0 : sal_Bool DatabaseMetaData::supportsUnionAll(  ) throw (SQLException, RuntimeException)
     919             : {
     920           0 :     return sal_True;
     921             : }
     922             : 
     923           0 : sal_Bool DatabaseMetaData::supportsOpenCursorsAcrossCommit(  ) throw (SQLException, RuntimeException)
     924             : {
     925           0 :     return sal_False;
     926             : }
     927             : 
     928           0 : sal_Bool DatabaseMetaData::supportsOpenCursorsAcrossRollback(  ) throw (SQLException, RuntimeException)
     929             : {
     930           0 :     return sal_False;
     931             : }
     932             : 
     933           0 : sal_Bool DatabaseMetaData::supportsOpenStatementsAcrossCommit(  ) throw (SQLException, RuntimeException)
     934             : {
     935           0 :     return sal_True;
     936             : }
     937           0 : sal_Bool DatabaseMetaData::supportsOpenStatementsAcrossRollback(  ) throw (SQLException, RuntimeException)
     938             : {
     939           0 :     return sal_True;
     940             : }
     941             : 
     942           0 : sal_Int32 DatabaseMetaData::getMaxBinaryLiteralLength(  ) throw (SQLException, RuntimeException)
     943             : {
     944           0 :     return 0;
     945             : }
     946             : 
     947           0 : sal_Int32 DatabaseMetaData::getMaxCharLiteralLength(  ) throw (SQLException, RuntimeException)
     948             : {
     949           0 :     return 0;
     950             : }
     951             : 
     952             : // Copied / adapted / simplified from JDBC driver
     953           0 : sal_Int32 DatabaseMetaData::getIntSetting(OUString settingName)
     954             :     throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException)
     955             : {
     956           0 :     MutexGuard guard( m_refMutex->mutex );
     957             : 
     958           0 :     Reference< XParameters > params(m_getIntSetting_stmt, UNO_QUERY_THROW );
     959           0 :     params->setString(1, settingName );
     960           0 :     Reference< XResultSet > rs = m_getIntSetting_stmt->executeQuery();
     961           0 :     Reference< XRow > xRow( rs , UNO_QUERY_THROW );
     962           0 :     OSL_VERIFY(rs->next());
     963             :     OSL_ENSURE(rs->isFirst(), "postgresql-sdbc DatabaseMetaData getIntSetting not on first row");
     964             :     OSL_ENSURE(rs->isLast(),  "postgresql-sdbc DatabaseMetaData getIntSetting not on last row");
     965           0 :     return xRow->getInt(1);
     966             : }
     967             : 
     968           0 : sal_Int32 DatabaseMetaData::getMaxNameLength()
     969             :     throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException)
     970             : {
     971           0 :     if ( m_pSettings->maxNameLen == 0)
     972           0 :         m_pSettings->maxNameLen = getIntSetting( ASCII_STR("max_identifier_length") );
     973             :     OSL_ENSURE(m_pSettings->maxNameLen, "postgresql-sdbc: maxNameLen is zero");
     974           0 :     return m_pSettings->maxNameLen;
     975             : }
     976             : 
     977           0 : sal_Int32 DatabaseMetaData::getMaxIndexKeys()
     978             :     throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException)
     979             : {
     980           0 :     if ( m_pSettings->maxIndexKeys == 0)
     981           0 :         m_pSettings->maxIndexKeys = getIntSetting(ASCII_STR("max_index_keys"));
     982             :     OSL_ENSURE(m_pSettings->maxIndexKeys, "postgresql-sdbc: maxIndexKeys is zero");
     983           0 :     return m_pSettings->maxIndexKeys;
     984             : }
     985             : 
     986           0 : sal_Int32 DatabaseMetaData::getMaxColumnNameLength(  ) throw (SQLException, RuntimeException)
     987             : {
     988           0 :     return getMaxNameLength();
     989             : }
     990             : 
     991           0 : sal_Int32 DatabaseMetaData::getMaxColumnsInGroupBy(  ) throw (SQLException, RuntimeException)
     992             : {
     993           0 :     return 0;
     994             : }
     995             : 
     996           0 : sal_Int32 DatabaseMetaData::getMaxColumnsInIndex(  ) throw (SQLException, RuntimeException)
     997             : {
     998           0 :     return getMaxIndexKeys();
     999             : }
    1000             : 
    1001           0 : sal_Int32 DatabaseMetaData::getMaxColumnsInOrderBy(  ) throw (SQLException, RuntimeException)
    1002             : {
    1003           0 :     return 0;
    1004             : }
    1005             : 
    1006           0 : sal_Int32 DatabaseMetaData::getMaxColumnsInSelect(  ) throw (SQLException, RuntimeException)
    1007             : {
    1008           0 :     return 0;
    1009             : }
    1010             : 
    1011           0 : sal_Int32 DatabaseMetaData::getMaxColumnsInTable(  ) throw (SQLException, RuntimeException)
    1012             : {
    1013           0 :     return 1600;
    1014             : }
    1015             : 
    1016           0 : sal_Int32 DatabaseMetaData::getMaxConnections(  ) throw (SQLException, RuntimeException)
    1017             : {
    1018             :     // LEM: The JDBC driver returns an arbitrary 8192; truth is as much as OS / hardware supports
    1019           0 :     return 0;
    1020             : }
    1021             : 
    1022           0 : sal_Int32 DatabaseMetaData::getMaxCursorNameLength(  ) throw (SQLException, RuntimeException) //TODO, don't know
    1023             : {
    1024           0 :     return getMaxNameLength();
    1025             : }
    1026             : 
    1027           0 : sal_Int32 DatabaseMetaData::getMaxIndexLength(  ) throw (SQLException, RuntimeException) //TODO, don't know
    1028             : {
    1029             :     // LEM: that's the index itself, not its name
    1030           0 :     return 0;
    1031             : }
    1032             : 
    1033           0 : sal_Int32 DatabaseMetaData::getMaxSchemaNameLength(  ) throw (SQLException, RuntimeException)
    1034             : {
    1035           0 :     return getMaxNameLength();
    1036             : }
    1037             : 
    1038           0 : sal_Int32 DatabaseMetaData::getMaxProcedureNameLength(  ) throw (SQLException, RuntimeException)
    1039             : {
    1040           0 :     return getMaxNameLength();
    1041             : }
    1042             : 
    1043           0 : sal_Int32 DatabaseMetaData::getMaxCatalogNameLength(  ) throw (SQLException, RuntimeException)
    1044             : {
    1045           0 :     return getMaxNameLength();
    1046             : }
    1047             : 
    1048           0 : sal_Int32 DatabaseMetaData::getMaxRowSize(  ) throw (SQLException, RuntimeException)
    1049             : {
    1050             :     // jdbc driver says 1GB, but http://www.postgresql.org/about/ says 1.6TB
    1051             :     // and that 1GB is the maximum _field_ size
    1052             :     // The row limit does not fit into a sal_Int32
    1053           0 :     return 0;
    1054             : }
    1055             : 
    1056           0 : sal_Bool DatabaseMetaData::doesMaxRowSizeIncludeBlobs(  ) throw (SQLException, RuntimeException)
    1057             : {
    1058             :     // LEM: Err... PostgreSQL basically does not do BLOBs well
    1059             :     //      In any case, BLOBs do not change the maximal row length AFAIK
    1060           0 :     return sal_True;
    1061             : }
    1062             : 
    1063           0 : sal_Int32 DatabaseMetaData::getMaxStatementLength(  ) throw (SQLException, RuntimeException)
    1064             : {
    1065             :     // LEM: actually, that would be 2^sizeof(size_t)-1
    1066             :     //      on the server? on the client (because of libpq)? minimum of the two? not sure
    1067             :     //      Anyway, big, so say unlimited.
    1068           0 :     return 0;
    1069             : }
    1070             : 
    1071           0 : sal_Int32 DatabaseMetaData::getMaxStatements(  ) throw (SQLException, RuntimeException) //TODO, don't know
    1072             : {
    1073           0 :     return 0;
    1074             : }
    1075             : 
    1076           0 : sal_Int32 DatabaseMetaData::getMaxTableNameLength(  ) throw (SQLException, RuntimeException)
    1077             : {
    1078           0 :     return getMaxNameLength();
    1079             : }
    1080             : 
    1081           0 : sal_Int32 DatabaseMetaData::getMaxTablesInSelect(  ) throw (SQLException, RuntimeException)
    1082             : {
    1083           0 :     return 0;
    1084             : }
    1085             : 
    1086           0 : sal_Int32 DatabaseMetaData::getMaxUserNameLength(  ) throw (SQLException, RuntimeException)
    1087             : {
    1088           0 :     return getMaxNameLength();
    1089             : }
    1090             : 
    1091           0 : sal_Int32 DatabaseMetaData::getDefaultTransactionIsolation(  ) throw (SQLException, RuntimeException)
    1092             : {
    1093           0 :     return com::sun::star::sdbc::TransactionIsolation::READ_COMMITTED;
    1094             : }
    1095             : 
    1096           0 : sal_Bool DatabaseMetaData::supportsTransactions(  ) throw (SQLException, RuntimeException)
    1097             : {
    1098           0 :     return sal_True;
    1099             : }
    1100             : 
    1101           0 : sal_Bool DatabaseMetaData::supportsTransactionIsolationLevel( sal_Int32 level ) throw (SQLException, RuntimeException)
    1102             : {
    1103           0 :     if ( level == com::sun::star::sdbc::TransactionIsolation::READ_COMMITTED
    1104             :          || level == com::sun::star::sdbc::TransactionIsolation::SERIALIZABLE
    1105             :          || level == com::sun::star::sdbc::TransactionIsolation::READ_UNCOMMITTED
    1106             :          || level == com::sun::star::sdbc::TransactionIsolation::REPEATABLE_READ)
    1107           0 :         return sal_True;
    1108             :     else
    1109           0 :         return sal_False;
    1110             : }
    1111             : 
    1112           0 : sal_Bool DatabaseMetaData::supportsDataDefinitionAndDataManipulationTransactions(  )
    1113             :     throw (SQLException, RuntimeException)
    1114             : {
    1115           0 :     return sal_True;
    1116             : }
    1117             : 
    1118           0 : sal_Bool DatabaseMetaData::supportsDataManipulationTransactionsOnly(  ) throw (SQLException, RuntimeException)
    1119             : {
    1120           0 :     return sal_False;
    1121             : }
    1122             : 
    1123           0 : sal_Bool DatabaseMetaData::dataDefinitionCausesTransactionCommit(  ) throw (SQLException, RuntimeException)
    1124             : {
    1125           0 :     return sal_False;
    1126             : }
    1127             : 
    1128           0 : sal_Bool DatabaseMetaData::dataDefinitionIgnoredInTransactions(  ) throw (SQLException, RuntimeException)
    1129             : {
    1130           0 :     return sal_False;
    1131             : }
    1132             : 
    1133           0 : ::com::sun::star::uno::Reference< XResultSet > DatabaseMetaData::getProcedures(
    1134             :     const ::com::sun::star::uno::Any& catalog,
    1135             :     const OUString& schemaPattern,
    1136             :     const OUString& procedureNamePattern ) throw (SQLException, RuntimeException)
    1137             : {
    1138             :     (void) catalog; (void) schemaPattern; (void) procedureNamePattern;
    1139             : //        1.  PROCEDURE_CAT string =&gt; procedure catalog (may be NULL )
    1140             : //        2. PROCEDURE_SCHEM string =&gt; procedure schema (may be NULL )
    1141             : //        3. PROCEDURE_NAME string =&gt; procedure name
    1142             : //        4. reserved for future use
    1143             : //        5. reserved for future use
    1144             : //        6. reserved for future use
    1145             : //        7. REMARKS string =&gt; explanatory comment on the procedure
    1146             : //        8. PROCEDURE_TYPE short =&gt; kind of procedure:
    1147             : //               * UNKNOWN - May return a result
    1148             : //               * NO - Does not return a result
    1149             : //               * RETURN - Returns a result
    1150             : 
    1151             : // LEM TODO: implement
    1152             : // LEM TODO: at least fake the columns, even if no row.
    1153           0 :     MutexGuard guard( m_refMutex->mutex );
    1154           0 :     checkClosed();
    1155             :     return new SequenceResultSet(
    1156           0 :         m_refMutex, *this, Sequence< OUString >(), Sequence< Sequence< Any > > (), m_pSettings->tc );
    1157             : }
    1158             : 
    1159           0 : ::com::sun::star::uno::Reference< XResultSet > DatabaseMetaData::getProcedureColumns(
    1160             :     const ::com::sun::star::uno::Any& catalog,
    1161             :     const OUString& schemaPattern,
    1162             :     const OUString& procedureNamePattern,
    1163             :     const OUString& columnNamePattern ) throw (SQLException, RuntimeException)
    1164             : {
    1165             :     (void) catalog; (void) schemaPattern; (void) procedureNamePattern; (void) columnNamePattern;
    1166           0 :     MutexGuard guard( m_refMutex->mutex );
    1167           0 :     checkClosed();
    1168             : // LEM TODO: implement
    1169             : // LEM TODO: at least fake the columns, even if no row.
    1170             :     return new SequenceResultSet(
    1171           0 :         m_refMutex, *this, Sequence< OUString >(), Sequence< Sequence< Any > > (), m_pSettings->tc );
    1172             : }
    1173             : 
    1174           0 : ::com::sun::star::uno::Reference< XResultSet > DatabaseMetaData::getTables(
    1175             :     const ::com::sun::star::uno::Any& catalog,
    1176             :     const OUString& schemaPattern,
    1177             :     const OUString& tableNamePattern,
    1178             :     const ::com::sun::star::uno::Sequence< OUString >& types )
    1179             :     throw (SQLException, RuntimeException)
    1180             : {
    1181             :     (void) catalog; (void) types;
    1182           0 :     Statics &statics = getStatics();
    1183             : 
    1184           0 :     MutexGuard guard( m_refMutex->mutex );
    1185           0 :     checkClosed();
    1186             : 
    1187           0 :     if( isLog( m_pSettings, LogLevel::INFO ) )
    1188             :     {
    1189           0 :         rtl::OUStringBuffer buf( 128 );
    1190           0 :         buf.appendAscii( "DatabaseMetaData::getTables got called with " );
    1191           0 :         buf.append( schemaPattern );
    1192           0 :         buf.appendAscii( "." );
    1193           0 :         buf.append( tableNamePattern );
    1194           0 :         log( m_pSettings, LogLevel::INFO, buf.makeStringAndClear() );
    1195             :     }
    1196             :     // ignore catalog, as a single pq connection does not support multiple catalogs
    1197             : 
    1198             :     // LEM TODO: this does not give the right column names, not the right number of columns, etc.
    1199             :     // Take "inspiration" from JDBC driver
    1200             :     // Ah, this is used to create a XResultSet manually... Try to do it directly in SQL
    1201           0 :     Reference< XPreparedStatement > statement = m_origin->prepareStatement(
    1202             :         ASCII_STR(
    1203             :             "SELECT "
    1204             :             "DISTINCT ON (pg_namespace.nspname, relname ) " // avoid duplicates (pg_settings !)
    1205             :             "pg_namespace.nspname, relname, relkind, pg_description.description "
    1206             :             "FROM pg_namespace, pg_class LEFT JOIN pg_description ON pg_class.oid = pg_description.objoid "
    1207             :             "WHERE relnamespace = pg_namespace.oid "
    1208             :             "AND ( relkind = 'r' OR relkind = 'v') "
    1209             :             "AND pg_namespace.nspname LIKE ? "
    1210             :             "AND relname LIKE ? "
    1211             : //            "ORDER BY pg_namespace.nspname || relname"
    1212           0 :             ) );
    1213             : 
    1214           0 :     Reference< XParameters > parameters( statement, UNO_QUERY_THROW );
    1215           0 :     parameters->setString( 1 , schemaPattern );
    1216           0 :     parameters->setString( 2 , tableNamePattern );
    1217             : 
    1218           0 :     Reference< XResultSet > rs = statement->executeQuery();
    1219           0 :     Reference< XRow > xRow( rs, UNO_QUERY_THROW );
    1220           0 :     SequenceAnyVector vec;
    1221             : 
    1222           0 :     while( rs->next() )
    1223             :     {
    1224           0 :         Sequence< Any > row( 5 );
    1225             : 
    1226           0 :         row[0] <<= m_pSettings->catalog;
    1227           0 :         row[1] <<= xRow->getString( 1 );
    1228           0 :         row[2] <<= xRow->getString( 2 );
    1229           0 :         OUString type = xRow->getString(3);
    1230           0 :         if( 0 == type.compareToAscii( "r" ) )
    1231             :         {
    1232           0 :             if( 0 == xRow->getString(1).compareToAscii( "pg_catalog" ) )
    1233             :             {
    1234           0 :                 row[3] <<= statics.SYSTEM_TABLE;
    1235             :             }
    1236             :             else
    1237             :             {
    1238           0 :                 row[3] <<= statics.TABLE;
    1239             :             }
    1240             :         }
    1241           0 :         else if( 0 == type.compareToAscii( "v" ) )
    1242             :         {
    1243           0 :             row[3] <<= statics.VIEW;
    1244             :         }
    1245             :         else
    1246             :         {
    1247           0 :             row[3] <<= statics.UNKNOWN;
    1248             :         }
    1249           0 :         row[4] <<= xRow->getString(4);
    1250             : 
    1251             :         // no description in postgresql AFAIK
    1252           0 :         vec.push_back( row );
    1253           0 :     }
    1254           0 :     Reference< XCloseable > closeable( statement, UNO_QUERY );
    1255           0 :     if( closeable.is() )
    1256           0 :         closeable->close();
    1257             : 
    1258             :     return new SequenceResultSet(
    1259           0 :         m_refMutex, *this, statics.tablesRowNames, sequence_of_vector(vec), m_pSettings->tc );
    1260             : }
    1261             : 
    1262             : struct SortInternalSchemasLastAndPublicFirst
    1263             : {
    1264           0 :     bool operator () ( const Sequence< Any >  & a, const Sequence< Any >  & b )
    1265             :     {
    1266           0 :         OUString valueA;
    1267           0 :         OUString valueB;
    1268           0 :         a[0] >>= valueA;
    1269           0 :         b[0] >>= valueB;
    1270           0 :         bool ret = false;
    1271           0 :         if( valueA.compareToAscii( RTL_CONSTASCII_STRINGPARAM( "public" ) ) == 0 )
    1272             :         {
    1273           0 :             ret = true;
    1274             :         }
    1275           0 :         else if( valueB.compareToAscii( RTL_CONSTASCII_STRINGPARAM( "public" ) ) == 0 )
    1276             :         {
    1277           0 :             ret = false;
    1278             :         }
    1279           0 :         else if( valueA.matchAsciiL( RTL_CONSTASCII_STRINGPARAM( "pg_" ) ) &&
    1280           0 :             valueB.matchAsciiL( RTL_CONSTASCII_STRINGPARAM( "pg_" ) ) )
    1281             :         {
    1282           0 :             ret = valueA.compareTo( valueB ) < 0; // sorts equal !
    1283             :         }
    1284           0 :         else if( valueA.matchAsciiL( RTL_CONSTASCII_STRINGPARAM( "pg_" ) ))
    1285             :         {
    1286           0 :             ret = false; // sorts last !
    1287             :         }
    1288           0 :         else if( valueB.matchAsciiL( RTL_CONSTASCII_STRINGPARAM( "pg_" ) ) )
    1289             :         {
    1290           0 :             ret = true; // sorts first !
    1291             :         }
    1292             :         else
    1293             :         {
    1294           0 :             ret = (valueA.compareTo( valueB ) < 0);
    1295             :         }
    1296           0 :         return ret;
    1297             :     }
    1298             : };
    1299             : 
    1300           0 : ::com::sun::star::uno::Reference< XResultSet > DatabaseMetaData::getSchemas(  )
    1301             :     throw (SQLException, RuntimeException)
    1302             : {
    1303           0 :     MutexGuard guard( m_refMutex->mutex );
    1304           0 :     checkClosed();
    1305             : 
    1306           0 :     if( isLog( m_pSettings, LogLevel::INFO ) )
    1307             :     {
    1308           0 :         log( m_pSettings, LogLevel::INFO, "DatabaseMetaData::getSchemas() got called" );
    1309             :     }
    1310             :     // <b>TABLE_SCHEM</b> string =&amp;gt; schema name
    1311           0 :     Reference< XStatement > statement = m_origin->createStatement();
    1312           0 :     Reference< XResultSet > rs = statement->executeQuery(
    1313           0 :         ASCII_STR("SELECT nspname from pg_namespace") );
    1314             :     // LEM TODO: look at JDBC driver and consider doing the same
    1315             :     //           in particular, excluding temporary schemas, but maybe better through pg_is_other_temp_schema(oid) OR  == pg_my_temp_schema()
    1316             : 
    1317           0 :     Reference< XRow > xRow( rs, UNO_QUERY_THROW );
    1318           0 :     SequenceAnyVector vec;
    1319           0 :     while( rs->next() )
    1320             :     {
    1321           0 :         Sequence<Any> row(1);
    1322           0 :         row[0] <<= xRow->getString(1);
    1323           0 :         vec.push_back( row );
    1324           0 :     }
    1325             : 
    1326             :     // sort public first, sort internal schemas last, sort rest in alphabetic order
    1327           0 :     std::sort( vec.begin(), vec.end(), SortInternalSchemasLastAndPublicFirst() );
    1328             : 
    1329           0 :     Reference< XCloseable > closeable( statement, UNO_QUERY );
    1330           0 :     if( closeable.is() )
    1331           0 :         closeable->close();
    1332             :     return new SequenceResultSet(
    1333           0 :         m_refMutex, *this, getStatics().schemaNames, sequence_of_vector(vec), m_pSettings->tc );
    1334             : }
    1335             : 
    1336           0 : ::com::sun::star::uno::Reference< XResultSet > DatabaseMetaData::getCatalogs(  )
    1337             :     throw (SQLException, RuntimeException)
    1338             : {
    1339             :     // LEM TODO: return the current catalog like JDBC driver?
    1340             :     //           at least fake the columns, even if no content
    1341           0 :     MutexGuard guard( m_refMutex->mutex );
    1342           0 :     checkClosed();
    1343             :     return new SequenceResultSet(
    1344           0 :         m_refMutex, *this, Sequence< OUString >(), Sequence< Sequence< Any > > (), m_pSettings->tc );
    1345             : }
    1346             : 
    1347           0 : ::com::sun::star::uno::Reference< XResultSet > DatabaseMetaData::getTableTypes(  )
    1348             :     throw (SQLException, RuntimeException)
    1349             : {
    1350             :     // LEM TODO: this can be made dynamic, see JDBC driver
    1351           0 :     MutexGuard guard( m_refMutex->mutex );
    1352           0 :     checkClosed();
    1353             :     return new SequenceResultSet(
    1354           0 :         m_refMutex, *this, getStatics().tableTypeNames, getStatics().tableTypeData,
    1355           0 :         m_pSettings->tc );
    1356             : }
    1357             : 
    1358             : 
    1359             : /** returns the constant from sdbc.DataType
    1360             :  */
    1361           0 : sal_Int32 typeNameToDataType( const OUString &typeName, const OUString &typtype )
    1362             : {
    1363             : //     sal_Int32 ret = com::sun::star::sdbc::DataType::DISTINCT;
    1364             :     // map all unknown types to memo (longvarchar). This allows to show them in
    1365             :     // string representation. Additionally, the edit-table-type-selection-box
    1366             :     // is not so unuseable anymore.
    1367           0 :     sal_Int32 ret = com::sun::star::sdbc::DataType::LONGVARCHAR;
    1368           0 :     if( 0 == typtype.compareToAscii( "b" ) )
    1369             :     {
    1370             :         // as long as the OOo framework does not support arrays,
    1371             :         // the user is better of with interpreting arrays as strings !
    1372             : //         if( typeName.getLength() && '_' == typeName[0] )
    1373             : //         {
    1374             : //             its just a naming convention, but as long as we don't have anything better,
    1375             : //             we take it as granted
    1376             : //             ret = com::sun::star::sdbc::DataType::ARRAY;
    1377             : //         }
    1378             :         // base type
    1379           0 :         Statics &statics = getStatics();
    1380           0 :         BaseTypeMap::iterator ii = statics.baseTypeMap.find( typeName );
    1381           0 :         if( ii != statics.baseTypeMap.end() )
    1382             :         {
    1383           0 :             ret = ii->second;
    1384             :         }
    1385             :     }
    1386           0 :     else if( 0 == typtype.compareToAscii( "c" ) )
    1387             :     {
    1388           0 :         ret = com::sun::star::sdbc::DataType::STRUCT;
    1389             :     }
    1390           0 :     else if( 0 == typtype.compareToAscii( "d" ) )
    1391             :     {
    1392           0 :         ret = com::sun::star::sdbc::DataType::LONGVARCHAR;
    1393             :     }
    1394           0 :     return ret;
    1395             : }
    1396             : 
    1397             : namespace {
    1398           0 : inline bool isSystemColumn( sal_Int16 attnum )
    1399             : {
    1400           0 :     return attnum <= 0;
    1401             : }
    1402             : }
    1403             : 
    1404             : // is not exported by the postgres header
    1405             : const static int PQ_VARHDRSZ = sizeof( sal_Int32 );
    1406             : 
    1407             : // Oh, quelle horreur
    1408             : // LEM TODO: Need to severely rewrite that!
    1409             : // should probably just "do the same" as ODBC or JDBC drivers...
    1410           0 : static void extractPrecisionAndScale(
    1411             :     sal_Int32 dataType, sal_Int32 atttypmod, sal_Int32 *precision, sal_Int32 *scale )
    1412             : {
    1413           0 :     if( atttypmod < PQ_VARHDRSZ )
    1414             :     {
    1415           0 :         *precision = 0;
    1416           0 :         *scale = 0;
    1417             :     }
    1418             :     else
    1419             :     {
    1420           0 :         switch( dataType )
    1421             :         {
    1422             :         case com::sun::star::sdbc::DataType::NUMERIC:
    1423             :         case com::sun::star::sdbc::DataType::DECIMAL:
    1424             :         {
    1425           0 :             *precision = ( ( atttypmod - PQ_VARHDRSZ ) >> 16 ) & 0xffff;
    1426           0 :             *scale = (atttypmod - PQ_VARHDRSZ ) & 0xffff;
    1427           0 :             break;
    1428             :         }
    1429             :         default:
    1430           0 :             *precision = atttypmod - PQ_VARHDRSZ;
    1431           0 :             *scale = 0;
    1432             :         }
    1433             :     }
    1434           0 : }
    1435             : 
    1436           0 : struct DatabaseTypeDescription
    1437             : {
    1438           0 :     DatabaseTypeDescription()
    1439           0 :     {}
    1440           0 :     DatabaseTypeDescription( const OUString &name, const OUString & type ) :
    1441             :         typeName( name ),
    1442           0 :         typeType( type )
    1443           0 :     {}
    1444           0 :     DatabaseTypeDescription( const DatabaseTypeDescription &source ) :
    1445             :         typeName( source.typeName ),
    1446           0 :         typeType( source.typeType )
    1447           0 :     {}
    1448           0 :     DatabaseTypeDescription & operator = ( const DatabaseTypeDescription & source )
    1449             :     {
    1450           0 :         typeName = source.typeName;
    1451           0 :         typeType = source.typeType;
    1452           0 :         return *this;
    1453             :     }
    1454             :     OUString typeName;
    1455             :     OUString typeType;
    1456             : };
    1457             : 
    1458             : typedef ::boost::unordered_map
    1459             : <
    1460             :     sal_Int32,
    1461             :     DatabaseTypeDescription,
    1462             :     ::boost::hash< sal_Int32 >,
    1463             :     ::std::equal_to< sal_Int32 >,
    1464             :     Allocator< ::std::pair< sal_Int32, DatabaseTypeDescription > >
    1465             : > Oid2DatabaseTypeDescriptionMap;
    1466             : 
    1467           0 : static void columnMetaData2DatabaseTypeDescription(
    1468             :     Oid2DatabaseTypeDescriptionMap &oidMap,
    1469             :     const Reference< XResultSet > &rs,
    1470             :     const Reference< XStatement > &stmt )
    1471             : {
    1472           0 :     Reference< XRow > row( rs, UNO_QUERY_THROW );
    1473           0 :     int domains = 0;
    1474           0 :     rtl::OUStringBuffer queryBuf(128);
    1475           0 :     queryBuf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "SELECT oid,typtype,typname FROM pg_TYPE WHERE " ) );
    1476           0 :     while( rs->next() )
    1477             :     {
    1478           0 :         if( row->getString( 9 ) == "d" && oidMap.find( row->getInt( 12 ) ) == oidMap.end() )
    1479             :         {
    1480           0 :             oidMap[row->getInt(12)] = DatabaseTypeDescription();
    1481           0 :             if( domains )
    1482           0 :                 queryBuf.appendAscii( " OR " );
    1483           0 :             queryBuf.appendAscii( "oid = " );
    1484           0 :             queryBuf.append( row->getInt(12 ), 10 );
    1485           0 :             domains ++;
    1486             :         }
    1487             :     }
    1488           0 :     rs->beforeFirst();
    1489             : 
    1490           0 :     if( domains )
    1491             :     {
    1492           0 :         Reference< XResultSet > rsDomain = stmt->executeQuery( queryBuf.makeStringAndClear() );
    1493           0 :         row = Reference< XRow >( rsDomain, UNO_QUERY_THROW );
    1494           0 :         while( rsDomain->next() )
    1495             :         {
    1496           0 :             oidMap[row->getInt(1)] = DatabaseTypeDescription(row->getString(3), row->getString(2) );
    1497             :         }
    1498           0 :         disposeNoThrow( stmt );
    1499           0 :     }
    1500             : 
    1501           0 : }
    1502             : 
    1503             : 
    1504             : 
    1505           0 : ::com::sun::star::uno::Reference< XResultSet > DatabaseMetaData::getColumns(
    1506             :     const ::com::sun::star::uno::Any& catalog,
    1507             :     const OUString& schemaPattern,
    1508             :     const OUString& tableNamePattern,
    1509             :     const OUString& columnNamePattern ) throw (SQLException, RuntimeException)
    1510             : {
    1511             :     (void) catalog;
    1512             :     // LEM TODO: review in comparison with JDBC driver
    1513           0 :     Statics &statics = getStatics();
    1514             : 
    1515             :     // continue !
    1516           0 :     MutexGuard guard( m_refMutex->mutex );
    1517           0 :     checkClosed();
    1518             : 
    1519           0 :     if( isLog( m_pSettings, LogLevel::INFO ) )
    1520             :     {
    1521           0 :         rtl::OUStringBuffer buf( 128 );
    1522           0 :         buf.appendAscii( "DatabaseMetaData::getColumns got called with " );
    1523           0 :         buf.append( schemaPattern );
    1524           0 :         buf.appendAscii( "." );
    1525           0 :         buf.append( tableNamePattern );
    1526           0 :         buf.appendAscii( "." );
    1527           0 :         buf.append( columnNamePattern );
    1528           0 :         log( m_pSettings, LogLevel::INFO, buf.makeStringAndClear() );
    1529             :     }
    1530             : 
    1531             :     // ignore catalog, as a single pq connection
    1532             :     // does not support multiple catalogs anyway
    1533             :     // We don't use information_schema.columns because it contains
    1534             :     // only the columns the current user has any privilege over.
    1535             : 
    1536             :     //  1. TABLE_CAT string => table catalog (may be NULL)
    1537             :     //               => not supported
    1538             :     //  2. TABLE_SCHEM string => table schema (may be NULL)
    1539             :     //               => pg_namespace.nspname
    1540             :     //  3. TABLE_NAME string => table name
    1541             :     //               => pg_class.relname
    1542             :     //  4. COLUMN_NAME string => column name
    1543             :     //               => pg_attribure.attname
    1544             :     //  5. DATA_TYPE short => SQL type from java.sql.Types
    1545             :     //               => pg_type.typname => sdbc.DataType
    1546             :     //  6. TYPE_NAME string => Data source dependent type name, for a UDT the
    1547             :     //                         type name is fully qualified
    1548             :     //               => pg_type.typname
    1549             :     //  7. COLUMN_SIZE long => column size. For char or date types this is
    1550             :     //                         the maximum number of characters, for numeric
    1551             :     //                         or decimal types this is precision.
    1552             :     //               => pg_attribute.atttypmod
    1553             :     //  8. BUFFER_LENGTH is not used.
    1554             :     //               => not used
    1555             :     //  9. DECIMAL_DIGITS long => the number of fractional digits
    1556             :     //               => don't know ! TODO !
    1557             :     //  10. NUM_PREC_RADIX long => Radix (typically either 10 or 2)
    1558             :     //               => TODO ??
    1559             :     //  11. NULLABLE long => is NULL allowed?
    1560             :     //                      NO_NULLS - might not allow NULL values
    1561             :     //                      NULABLE - definitely allows NULL values
    1562             :     //                      NULLABLE_UNKNOWN - nullability unknown
    1563             :     //               => pg_attribute.attnotnull
    1564             :     //  12. REMARKS string => comment describing column (may be NULL )
    1565             :     //               => pg_description.description
    1566             :     //  13. COLUMN_DEF string => default value (may be NULL)
    1567             :     //               => pg_type.typdefault
    1568             :     //  14. SQL_DATA_TYPE long => unused
    1569             :     //               => empty
    1570             :     //  15. SQL_DATETIME_SUB long => unused
    1571             :     //               => empty
    1572             :     //  16. CHAR_OCTET_LENGTH long => for char types the maximum number of
    1573             :     //                                bytes in the column
    1574             :     //               => pg_type.typlen
    1575             :     //  17. ORDINAL_POSITION int => index of column in table (starting at 1)
    1576             :     //                              pg_attribute.attnum
    1577             :     //  18. IS_NULLABLE string => "NO" means column definitely does not allow
    1578             :     //                            NULL values; "YES" means the column might
    1579             :     //                            allow NULL values. An empty string means
    1580             :     //                            nobody knows.
    1581             :     //               => pg_attribute.attnotnull
    1582             : 
    1583           0 :     Reference< XPreparedStatement > statement = m_origin->prepareStatement(
    1584             :         ASCII_STR(
    1585             : 
    1586             :             "SELECT pg_namespace.nspname, "  // 1
    1587             :             "pg_class.relname, "             // 2
    1588             :             "pg_attribute.attname, "         // 3
    1589             :             "pg_type.typname, "              // 4
    1590             :             "pg_attribute.atttypmod, "       // 5
    1591             :             "pg_attribute.attnotnull, "      // 6
    1592             :             "pg_type.typdefault, "           // 7
    1593             :             "pg_type.typtype, "              // 8
    1594             :             "pg_attrdef.adsrc, "             // 9
    1595             :             "pg_description.description, "   // 10
    1596             :             "pg_type.typbasetype, "          // 11
    1597             :             "pg_attribute.attnum "           // 12
    1598             :             "FROM pg_class, "
    1599             :                  "pg_attribute LEFT JOIN pg_attrdef ON pg_attribute.attrelid = pg_attrdef.adrelid AND pg_attribute.attnum = pg_attrdef.adnum "
    1600             :                               "LEFT JOIN pg_description ON pg_attribute.attrelid = pg_description.objoid AND pg_attribute.attnum=pg_description.objsubid,"
    1601             :                  " pg_type, pg_namespace "
    1602             :             "WHERE pg_attribute.attrelid = pg_class.oid "
    1603             :                    "AND pg_attribute.atttypid = pg_type.oid "
    1604             :                    "AND pg_class.relnamespace = pg_namespace.oid "
    1605             :                    "AND NOT pg_attribute.attisdropped "
    1606             :                    "AND pg_namespace.nspname LIKE ? "
    1607             :                    "AND pg_class.relname LIKE ? "
    1608             :                    "AND pg_attribute.attname LIKE ? "
    1609             :             "ORDER BY pg_namespace.nspname, pg_class.relname, pg_attribute.attnum"
    1610           0 :             ) );
    1611             : 
    1612           0 :     Reference< XParameters > parameters( statement, UNO_QUERY_THROW );
    1613           0 :     parameters->setString( 1 , schemaPattern );
    1614           0 :     parameters->setString( 2 , tableNamePattern );
    1615           0 :     parameters->setString( 3 , columnNamePattern );
    1616             : 
    1617           0 :     Reference< XResultSet > rs = statement->executeQuery();
    1618           0 :     Reference< XRow > xRow( rs, UNO_QUERY_THROW );
    1619           0 :     SequenceAnyVector vec;
    1620             : 
    1621           0 :     Oid2DatabaseTypeDescriptionMap domainMap;
    1622           0 :     Reference< XStatement > domainTypeStmt = m_origin->createStatement();
    1623           0 :     columnMetaData2DatabaseTypeDescription( domainMap, rs, domainTypeStmt );
    1624             : 
    1625           0 :     sal_uInt32 colNum(0);
    1626           0 :     OUString sSchema( ASCII_STR("#invalid#") );
    1627           0 :     OUString sTable(  ASCII_STR("#invalid#") );
    1628             : 
    1629           0 :     while( rs->next() )
    1630             :     {
    1631           0 :         if( m_pSettings->showSystemColumns || ! isSystemColumn( xRow->getShort( 12 ) ) )
    1632             :         {
    1633           0 :             OUString sNewSchema( xRow->getString(1) );
    1634           0 :             OUString sNewTable(  xRow->getString(2) );
    1635           0 :             if ( sNewSchema != sSchema || sNewTable != sTable )
    1636             :             {
    1637           0 :                 colNum = 1;
    1638           0 :                 sSchema = sNewSchema;
    1639           0 :                 sTable = sNewTable;
    1640             :             }
    1641             :             else
    1642           0 :                 ++colNum;
    1643             :             sal_Int32 precision, scale, type;
    1644           0 :             Sequence< Any > row( 18 );
    1645           0 :             row[0] <<= m_pSettings->catalog;
    1646           0 :             row[1] <<= sNewSchema;
    1647           0 :             row[2] <<= sNewTable;
    1648           0 :             row[3] <<= xRow->getString(3);
    1649           0 :             if( xRow->getString(8) == "d" )
    1650             :             {
    1651           0 :                 DatabaseTypeDescription desc( domainMap[xRow->getInt(11)] );
    1652           0 :                 type = typeNameToDataType( desc.typeName, desc.typeType );
    1653             :             }
    1654             :             else
    1655             :             {
    1656           0 :                 type = typeNameToDataType( xRow->getString(4), xRow->getString(8) );
    1657             :             }
    1658           0 :             extractPrecisionAndScale( type, xRow->getInt(5) , &precision, &scale );
    1659           0 :             row[4] <<= type;
    1660           0 :             row[5] <<= xRow->getString(4);
    1661           0 :             row[6] <<= precision;
    1662             :             // row[7] BUFFER_LENGTH not used
    1663           0 :             row[8] <<= scale;
    1664             :             // row[9] RADIX TODO
    1665           0 :             if( xRow->getBoolean( 6 ) && ! isSystemColumn(xRow->getInt( 12 )) )
    1666             :             {
    1667           0 :                 row[10] <<= OUString::valueOf(com::sun::star::sdbc::ColumnValue::NO_NULLS);
    1668           0 :                 row[17] <<= statics.NO;
    1669             :             }
    1670             :             else
    1671             :             {
    1672           0 :                 row[10] <<= OUString::valueOf(com::sun::star::sdbc::ColumnValue::NULLABLE);
    1673           0 :                 row[17] <<= statics.YES;
    1674             :             }
    1675             : 
    1676           0 :             row[11] <<= xRow->getString( 10 ); // comment
    1677           0 :             row[12] <<= xRow->getString( 9 ); // COLUMN_DEF = pg_type.typdefault
    1678             :             // row[13] SQL_DATA_TYPE    not used
    1679             :             // row[14] SQL_DATETIME_SUB not used
    1680           0 :             row[15] <<= precision;
    1681           0 :             row[16] <<= colNum ;
    1682             : 
    1683           0 :             vec.push_back( row );
    1684             :         }
    1685             :     }
    1686           0 :     Reference< XCloseable > closeable( statement, UNO_QUERY );
    1687           0 :     if( closeable.is() )
    1688           0 :         closeable->close();
    1689             : 
    1690             :     return new SequenceResultSet(
    1691           0 :         m_refMutex, *this, statics.columnRowNames, sequence_of_vector(vec), m_pSettings->tc );
    1692             : }
    1693             : 
    1694           0 : ::com::sun::star::uno::Reference< XResultSet > DatabaseMetaData::getColumnPrivileges(
    1695             :     const ::com::sun::star::uno::Any& catalog,
    1696             :     const OUString& schema,
    1697             :     const OUString& table,
    1698             :     const OUString& columnNamePattern ) throw (SQLException, RuntimeException)
    1699             : {
    1700             :     (void) catalog;
    1701             : 
    1702           0 :     MutexGuard guard( m_refMutex->mutex );
    1703           0 :     checkClosed();
    1704             : 
    1705           0 :     if( isLog( m_pSettings, LogLevel::INFO ) )
    1706             :     {
    1707           0 :         rtl::OUStringBuffer buf( 128 );
    1708           0 :         buf.appendAscii( "DatabaseMetaData::getColumnPrivileges got called with " );
    1709           0 :         buf.append( schema );
    1710           0 :         buf.appendAscii( "." );
    1711           0 :         buf.append( table );
    1712           0 :         buf.appendAscii( "." );
    1713           0 :         buf.append( columnNamePattern );
    1714           0 :         log( m_pSettings, LogLevel::INFO, buf.makeStringAndClear() );
    1715             :     }
    1716             : 
    1717           0 :     Reference< XParameters > parameters( m_getColumnPrivs_stmt, UNO_QUERY_THROW );
    1718           0 :     parameters->setString( 1 , schema );
    1719           0 :     parameters->setString( 2 , table );
    1720           0 :     parameters->setString( 3 , columnNamePattern );
    1721             : 
    1722           0 :     Reference< XResultSet > rs = m_getColumnPrivs_stmt->executeQuery();
    1723             : 
    1724           0 :     return rs;
    1725             : }
    1726             : 
    1727           0 : ::com::sun::star::uno::Reference< XResultSet > DatabaseMetaData::getTablePrivileges(
    1728             :     const ::com::sun::star::uno::Any& catalog,
    1729             :     const OUString& schemaPattern,
    1730             :     const OUString& tableNamePattern ) throw (SQLException, RuntimeException)
    1731             : {
    1732             :     (void) catalog;
    1733           0 :     MutexGuard guard( m_refMutex->mutex );
    1734           0 :     checkClosed();
    1735             : 
    1736           0 :     if( isLog( m_pSettings, LogLevel::INFO ) )
    1737             :     {
    1738           0 :         rtl::OUStringBuffer buf( 128 );
    1739           0 :         buf.appendAscii( "DatabaseMetaData::getTablePrivileges got called with " );
    1740           0 :         buf.append( schemaPattern );
    1741           0 :         buf.appendAscii( "." );
    1742           0 :         buf.append( tableNamePattern );
    1743           0 :         log( m_pSettings, LogLevel::INFO, buf.makeStringAndClear() );
    1744             :     }
    1745             : 
    1746           0 :     Reference< XParameters > parameters( m_getTablePrivs_stmt, UNO_QUERY_THROW );
    1747           0 :     parameters->setString( 1 , schemaPattern );
    1748           0 :     parameters->setString( 2 , tableNamePattern );
    1749             : 
    1750           0 :     Reference< XResultSet > rs = m_getTablePrivs_stmt->executeQuery();
    1751             : 
    1752           0 :     return rs;
    1753             : }
    1754             : 
    1755           0 : ::com::sun::star::uno::Reference< XResultSet > DatabaseMetaData::getBestRowIdentifier(
    1756             :     const ::com::sun::star::uno::Any& catalog,
    1757             :     const OUString& schema,
    1758             :     const OUString& table,
    1759             :     sal_Int32 scope,
    1760             :     sal_Bool nullable ) throw (SQLException, RuntimeException)
    1761             : {
    1762             :     (void) catalog; (void) schema; (void) table; (void) scope; (void) nullable;
    1763             :     //LEM TODO: implement! See JDBC driver
    1764           0 :     MutexGuard guard( m_refMutex->mutex );
    1765           0 :     checkClosed();
    1766             :     return new SequenceResultSet(
    1767           0 :         m_refMutex, *this, Sequence< OUString >(), Sequence< Sequence< Any > > (), m_pSettings->tc );
    1768             : }
    1769             : 
    1770           0 : ::com::sun::star::uno::Reference< XResultSet > DatabaseMetaData::getVersionColumns(
    1771             :     const ::com::sun::star::uno::Any& catalog,
    1772             :     const OUString& schema,
    1773             :     const OUString& table ) throw (SQLException, RuntimeException)
    1774             : {
    1775             :     (void) catalog; (void) schema; (void) table;
    1776             :     //LEM TODO: implement! See JDBC driver
    1777           0 :     MutexGuard guard( m_refMutex->mutex );
    1778           0 :     checkClosed();
    1779             :     return new SequenceResultSet(
    1780           0 :         m_refMutex, *this, Sequence< OUString >(), Sequence< Sequence< Any > > (), m_pSettings->tc );
    1781             : }
    1782             : 
    1783           0 : ::com::sun::star::uno::Reference< XResultSet > DatabaseMetaData::getPrimaryKeys(
    1784             :     const ::com::sun::star::uno::Any& catalog,
    1785             :     const OUString& schema,
    1786             :     const OUString& table ) throw (SQLException, RuntimeException)
    1787             : {
    1788             :     (void) catalog;
    1789             :     //LEM TODO: review
    1790           0 :     MutexGuard guard( m_refMutex->mutex );
    1791           0 :     checkClosed();
    1792             : 
    1793             : //        1.  TABLE_CAT string =&gt; table catalog (may be NULL )
    1794             : //        2. TABLE_SCHEM string =&gt; table schema (may be NULL )
    1795             : //        3. TABLE_NAME string =&gt; table name
    1796             : //        4. COLUMN_NAME string =&gt; column name
    1797             : //        5. KEY_SEQ short =&gt; sequence number within primary key
    1798             : //        6. PK_NAME string =&gt; primary key name (may be NULL )
    1799             : 
    1800           0 :     if( isLog( m_pSettings, LogLevel::INFO ) )
    1801             :     {
    1802           0 :         rtl::OUStringBuffer buf( 128 );
    1803           0 :         buf.appendAscii( "DatabaseMetaData::getPrimaryKeys got called with " );
    1804           0 :         buf.append( schema );
    1805           0 :         buf.appendAscii( "." );
    1806           0 :         buf.append( table );
    1807           0 :         log( m_pSettings, LogLevel::INFO, buf.makeStringAndClear() );
    1808             :     }
    1809             : 
    1810           0 :     Reference< XPreparedStatement > statement = m_origin->prepareStatement(
    1811             :         ASCII_STR(
    1812             :             "SELECT nmsp.nspname, "
    1813             :                     "cl.relname, "
    1814             :                     "con.conkey, "
    1815             :                     "con.conname, "
    1816             :                     "con.conrelid "
    1817             :             "FROM pg_constraint as con,pg_class as cl, pg_namespace as nmsp "
    1818             :             "WHERE con.connamespace = nmsp.oid AND con.conrelid = cl.oid AND con.contype = 'p' "
    1819           0 :                 "AND nmsp.nspname LIKE ? AND cl.relname LIKE ?" ) );
    1820             : 
    1821           0 :     Reference< XParameters > parameters( statement, UNO_QUERY_THROW );
    1822           0 :     parameters->setString( 1 , schema );
    1823           0 :     parameters->setString( 2 , table );
    1824             : 
    1825           0 :     Reference< XResultSet > rs = statement->executeQuery();
    1826           0 :     Reference< XRow > xRow( rs, UNO_QUERY_THROW );
    1827           0 :     SequenceAnyVector vec;
    1828             : 
    1829           0 :     while( rs->next() )
    1830             :     {
    1831           0 :         Sequence< Any > row( 6 );
    1832           0 :         row[0] <<= m_pSettings->catalog;
    1833           0 :         row[1] <<= xRow->getString(1);  //
    1834           0 :         row[2] <<= xRow->getString(2);
    1835           0 :         OUString array = xRow->getString(3);
    1836           0 :         row[4] <<= xRow->getString(5); // the relid
    1837           0 :         row[5] <<= xRow->getString(4);
    1838             : 
    1839           0 :         int i = 0;
    1840             :         // now retrieve the columns information
    1841             :         // unfortunately, postgresql does not allow array of variable size in
    1842             :         // WHERE clauses (in the default installation), so we have to choose
    1843             :         // this expensive and somewhat ugly way
    1844             :         // annotation: postgresql shouldn't have choosen an array here, instead they
    1845             :         //             should have multiple rows per table
    1846             :         // LEM: to transform an array into several rows, see unnest;
    1847             :         //      it is as simple as "SELECT foo, bar, unnest(qux) FROM ..."
    1848             :         //      where qux is the column that contains an array.
    1849           0 :         while( array[i] && '}' != array[i] )
    1850             :         {
    1851           0 :             i++;
    1852           0 :             int start = i;
    1853           0 :             while( array[i] && array[i] != '}' && array[i] != ',' ) i++;
    1854           0 :             row[3] <<= OUString( &array.getStr()[start], i - start );
    1855           0 :             vec.push_back( row );
    1856             :         }
    1857           0 :     }
    1858             : 
    1859             :     {
    1860           0 :         Reference< XCloseable > closeable( statement, UNO_QUERY );
    1861           0 :         if( closeable.is() )
    1862           0 :             closeable->close();
    1863             :     }
    1864             : 
    1865             : 
    1866           0 :     SequenceAnyVector::iterator ii = vec.begin();
    1867           0 :     OUString lastTableOid;
    1868           0 :     sal_Int32 index = 0;
    1869           0 :     Sequence< Sequence< Any > > ret( vec.size() );
    1870           0 :     int elements = 0;
    1871           0 :     for( ; ii != vec.end() ; ++ ii )
    1872             :     {
    1873             : 
    1874           0 :         Sequence< Any > row = *ii;
    1875           0 :         OUString tableOid;
    1876           0 :         OUString attnum;
    1877             : 
    1878           0 :         row[4] >>= tableOid;
    1879           0 :         row[3] >>= attnum;
    1880           0 :         statement = m_origin->prepareStatement(
    1881             :             ASCII_STR(
    1882             :                 "SELECT att.attname FROM "
    1883             :                 "pg_attribute AS att, pg_class AS cl WHERE "
    1884           0 :                 "att.attrelid = ? AND att.attnum = ?" ));
    1885             : 
    1886           0 :         parameters = Reference< XParameters >( statement, UNO_QUERY_THROW );
    1887           0 :         parameters->setString( 1 , tableOid );
    1888           0 :         parameters->setString( 2 , attnum );
    1889             : 
    1890           0 :         rs = statement->executeQuery();
    1891           0 :         xRow = Reference< XRow >( rs, UNO_QUERY_THROW );
    1892           0 :         if( rs->next() )
    1893             :         {
    1894             :             // column name
    1895           0 :             row[3] <<= xRow->getString( 1 );
    1896           0 :             if( tableOid != lastTableOid )
    1897           0 :                 index = 1;
    1898           0 :             lastTableOid = tableOid;
    1899           0 :             row[4] <<= OUString::valueOf( index );
    1900           0 :             index ++;
    1901             :         }
    1902             :         {
    1903           0 :             Reference< XCloseable > closeable( statement, UNO_QUERY );
    1904           0 :             if( closeable.is() )
    1905           0 :                 closeable->close();
    1906             :         }
    1907           0 :         ret[elements] = row;
    1908           0 :         elements ++;
    1909           0 :     }
    1910             :     return new SequenceResultSet(
    1911           0 :         m_refMutex, *this, getStatics().primaryKeyNames, ret , m_pSettings->tc );
    1912             : }
    1913             : 
    1914             : // Copied / adapted / simplified from JDBC driver
    1915             : #define SQL_CASE_KEYRULE "  WHEN 'c' THEN " STRINGIFY(KEYRULE_CASCADE) \
    1916             :                          "  WHEN 'n' THEN " STRINGIFY(KEYRULE_SET_NULL) \
    1917             :                          "  WHEN 'd' THEN " STRINGIFY(KEYRULE_SET_DEFAULT) \
    1918             :                          "  WHEN 'r' THEN " STRINGIFY(KEYRULE_RESTRICT) \
    1919             :                          "  WHEN 'a' THEN " STRINGIFY(KEYRULE_NO_ACTION) \
    1920             :                          "  ELSE NULL "
    1921             : 
    1922             : #define SQL_GET_REFERENCES \
    1923             :     "WITH con AS (SELECT oid, conname, contype, condeferrable, condeferred, conrelid, confrelid,  confupdtype, confdeltype, generate_subscripts(conkey,1) AS conkeyseq, unnest(conkey) AS conkey , unnest(confkey) AS confkey FROM pg_catalog.pg_constraint) " \
    1924             :     "SELECT NULL::text AS PKTABLE_CAT, pkn.nspname AS PKTABLE_SCHEM, pkc.relname AS PKTABLE_NAME, pka.attname AS PKCOLUMN_NAME, " \
    1925             :     " NULL::text AS FKTABLE_CAT, fkn.nspname AS FKTABLE_SCHEM, fkc.relname AS FKTABLE_NAME, fka.attname AS FKCOLUMN_NAME, " \
    1926             :     " con.conkeyseq AS KEY_SEQ, " \
    1927             :     " CASE con.confupdtype " \
    1928             :     SQL_CASE_KEYRULE \
    1929             :     " END AS UPDATE_RULE, " \
    1930             :     " CASE con.confdeltype " \
    1931             :     SQL_CASE_KEYRULE \
    1932             :     " END AS DELETE_RULE, " \
    1933             :     " con.conname AS FK_NAME, pkic.relname AS PK_NAME, " \
    1934             :     " CASE " \
    1935             :     "  WHEN con.condeferrable AND con.condeferred THEN " STRINGIFY(DEFERRABILITY_INITIALLY_DEFERRED) \
    1936             :     "  WHEN con.condeferrable THEN " STRINGIFY(DEFERRABILITY_INITIALLY_IMMEDIATE) \
    1937             :     "  ELSE " STRINGIFY(DEFERRABILITY_NONE) \
    1938             :     " END AS DEFERRABILITY " \
    1939             :     "FROM " \
    1940             :     " pg_catalog.pg_namespace pkn, pg_catalog.pg_class pkc, pg_catalog.pg_attribute pka, " \
    1941             :     " pg_catalog.pg_namespace fkn, pg_catalog.pg_class fkc, pg_catalog.pg_attribute fka, " \
    1942             :     " con, pg_catalog.pg_depend dep, pg_catalog.pg_class pkic " \
    1943             :     "WHERE pkn.oid = pkc.relnamespace AND pkc.oid = pka.attrelid AND pka.attnum = con.confkey AND con.confrelid = pkc.oid " \
    1944             :     " AND  fkn.oid = fkc.relnamespace AND fkc.oid = fka.attrelid AND fka.attnum = con.conkey  AND con.conrelid  = fkc.oid " \
    1945             :     " AND con.contype = 'f' AND con.oid = dep.objid AND pkic.oid = dep.refobjid AND pkic.relkind = 'i' AND dep.classid = 'pg_constraint'::regclass::oid AND dep.refclassid = 'pg_class'::regclass::oid "
    1946             : 
    1947             : #define SQL_GET_REFERENCES_PSCHEMA " AND pkn.nspname = ? "
    1948             : #define SQL_GET_REFERENCES_PTABLE  " AND pkc.relname = ? "
    1949             : #define SQL_GET_REFERENCES_FSCHEMA " AND fkn.nspname = ? "
    1950             : #define SQL_GET_REFERENCES_FTABLE  " AND fkc.relname = ? "
    1951             : #define SQL_GET_REFERENCES_ORDER_SOME_PTABLE "ORDER BY fkn.nspname, fkc.relname, conkeyseq"
    1952             : #define SQL_GET_REFERENCES_ORDER_NO_PTABLE   "ORDER BY pkn.nspname, pkc.relname, conkeyseq"
    1953             : 
    1954             : #define SQL_GET_REFERENCES_NONE_NONE_NONE_NONE \
    1955             :     SQL_GET_REFERENCES \
    1956             :     SQL_GET_REFERENCES_ORDER_NO_PTABLE
    1957             : 
    1958             : #define SQL_GET_REFERENCES_SOME_NONE_NONE_NONE \
    1959             :     SQL_GET_REFERENCES \
    1960             :     SQL_GET_REFERENCES_PSCHEMA \
    1961             :     SQL_GET_REFERENCES_ORDER_NO_PTABLE
    1962             : 
    1963             : #define SQL_GET_REFERENCES_NONE_SOME_NONE_NONE \
    1964             :     SQL_GET_REFERENCES \
    1965             :     SQL_GET_REFERENCES_PTABLE \
    1966             :     SQL_GET_REFERENCES_ORDER_SOME_PTABLE
    1967             : 
    1968             : #define SQL_GET_REFERENCES_SOME_SOME_NONE_NONE \
    1969             :     SQL_GET_REFERENCES \
    1970             :     SQL_GET_REFERENCES_PSCHEMA \
    1971             :     SQL_GET_REFERENCES_PTABLE \
    1972             :     SQL_GET_REFERENCES_ORDER_SOME_PTABLE
    1973             : 
    1974             : #define SQL_GET_REFERENCES_NONE_NONE_SOME_NONE \
    1975             :     SQL_GET_REFERENCES \
    1976             :     SQL_GET_REFERENCES_FSCHEMA \
    1977             :     SQL_GET_REFERENCES_ORDER_NO_PTABLE
    1978             : 
    1979             : #define SQL_GET_REFERENCES_NONE_NONE_NONE_SOME \
    1980             :     SQL_GET_REFERENCES \
    1981             :     SQL_GET_REFERENCES_FTABLE \
    1982             :     SQL_GET_REFERENCES_ORDER_NO_PTABLE
    1983             : 
    1984             : #define SQL_GET_REFERENCES_NONE_NONE_SOME_SOME \
    1985             :     SQL_GET_REFERENCES \
    1986             :     SQL_GET_REFERENCES_FSCHEMA \
    1987             :     SQL_GET_REFERENCES_FTABLE \
    1988             :     SQL_GET_REFERENCES_ORDER_NO_PTABLE
    1989             : 
    1990             : #define SQL_GET_REFERENCES_SOME_NONE_SOME_NONE \
    1991             :     SQL_GET_REFERENCES \
    1992             :     SQL_GET_REFERENCES_PSCHEMA \
    1993             :     SQL_GET_REFERENCES_FSCHEMA \
    1994             :     SQL_GET_REFERENCES_ORDER_NO_PTABLE
    1995             : 
    1996             : #define SQL_GET_REFERENCES_SOME_NONE_NONE_SOME \
    1997             :     SQL_GET_REFERENCES \
    1998             :     SQL_GET_REFERENCES_PSCHEMA \
    1999             :     SQL_GET_REFERENCES_FTABLE \
    2000             :     SQL_GET_REFERENCES_ORDER_NO_PTABLE
    2001             : 
    2002             : #define SQL_GET_REFERENCES_SOME_NONE_SOME_SOME \
    2003             :     SQL_GET_REFERENCES \
    2004             :     SQL_GET_REFERENCES_PSCHEMA \
    2005             :     SQL_GET_REFERENCES_FSCHEMA \
    2006             :     SQL_GET_REFERENCES_FTABLE \
    2007             :     SQL_GET_REFERENCES_ORDER_NO_PTABLE
    2008             : 
    2009             : #define SQL_GET_REFERENCES_NONE_SOME_SOME_NONE \
    2010             :     SQL_GET_REFERENCES \
    2011             :     SQL_GET_REFERENCES_PTABLE \
    2012             :     SQL_GET_REFERENCES_FSCHEMA \
    2013             :     SQL_GET_REFERENCES_ORDER_SOME_PTABLE
    2014             : 
    2015             : #define SQL_GET_REFERENCES_NONE_SOME_NONE_SOME \
    2016             :     SQL_GET_REFERENCES \
    2017             :     SQL_GET_REFERENCES_PTABLE \
    2018             :     SQL_GET_REFERENCES_FTABLE \
    2019             :     SQL_GET_REFERENCES_ORDER_SOME_PTABLE
    2020             : 
    2021             : #define SQL_GET_REFERENCES_NONE_SOME_SOME_SOME \
    2022             :     SQL_GET_REFERENCES \
    2023             :     SQL_GET_REFERENCES_PTABLE \
    2024             :     SQL_GET_REFERENCES_FSCHEMA \
    2025             :     SQL_GET_REFERENCES_FTABLE \
    2026             :     SQL_GET_REFERENCES_ORDER_SOME_PTABLE
    2027             : 
    2028             : #define SQL_GET_REFERENCES_SOME_SOME_SOME_NONE \
    2029             :     SQL_GET_REFERENCES \
    2030             :     SQL_GET_REFERENCES_PSCHEMA \
    2031             :     SQL_GET_REFERENCES_PTABLE \
    2032             :     SQL_GET_REFERENCES_FSCHEMA \
    2033             :     SQL_GET_REFERENCES_ORDER_SOME_PTABLE
    2034             : 
    2035             : #define SQL_GET_REFERENCES_SOME_SOME_NONE_SOME \
    2036             :     SQL_GET_REFERENCES \
    2037             :     SQL_GET_REFERENCES_PSCHEMA \
    2038             :     SQL_GET_REFERENCES_PTABLE \
    2039             :     SQL_GET_REFERENCES_FTABLE \
    2040             :     SQL_GET_REFERENCES_ORDER_SOME_PTABLE
    2041             : 
    2042             : #define SQL_GET_REFERENCES_SOME_SOME_SOME_SOME \
    2043             :     SQL_GET_REFERENCES \
    2044             :     SQL_GET_REFERENCES_PSCHEMA \
    2045             :     SQL_GET_REFERENCES_PTABLE \
    2046             :     SQL_GET_REFERENCES_FSCHEMA \
    2047             :     SQL_GET_REFERENCES_FTABLE \
    2048             :     SQL_GET_REFERENCES_ORDER_SOME_PTABLE
    2049             : 
    2050           0 : void DatabaseMetaData::init_getReferences_stmt ()
    2051             : {
    2052           0 :     m_getReferences_stmt[0]  = m_origin->prepareStatement(ASCII_STR( SQL_GET_REFERENCES_NONE_NONE_NONE_NONE ));
    2053           0 :     m_getReferences_stmt[1]  = m_origin->prepareStatement(ASCII_STR( SQL_GET_REFERENCES_SOME_NONE_NONE_NONE ));
    2054           0 :     m_getReferences_stmt[2]  = m_origin->prepareStatement(ASCII_STR( SQL_GET_REFERENCES_NONE_SOME_NONE_NONE ));
    2055           0 :     m_getReferences_stmt[3]  = m_origin->prepareStatement(ASCII_STR( SQL_GET_REFERENCES_SOME_SOME_NONE_NONE ));
    2056           0 :     m_getReferences_stmt[4]  = m_origin->prepareStatement(ASCII_STR( SQL_GET_REFERENCES_NONE_NONE_SOME_NONE ));
    2057           0 :     m_getReferences_stmt[5]  = m_origin->prepareStatement(ASCII_STR( SQL_GET_REFERENCES_SOME_NONE_SOME_NONE ));
    2058           0 :     m_getReferences_stmt[6]  = m_origin->prepareStatement(ASCII_STR( SQL_GET_REFERENCES_NONE_SOME_SOME_NONE ));
    2059           0 :     m_getReferences_stmt[7]  = m_origin->prepareStatement(ASCII_STR( SQL_GET_REFERENCES_SOME_SOME_SOME_NONE ));
    2060           0 :     m_getReferences_stmt[8]  = m_origin->prepareStatement(ASCII_STR( SQL_GET_REFERENCES_NONE_NONE_NONE_SOME ));
    2061           0 :     m_getReferences_stmt[9]  = m_origin->prepareStatement(ASCII_STR( SQL_GET_REFERENCES_SOME_NONE_NONE_SOME ));
    2062           0 :     m_getReferences_stmt[10] = m_origin->prepareStatement(ASCII_STR( SQL_GET_REFERENCES_NONE_SOME_NONE_SOME ));
    2063           0 :     m_getReferences_stmt[11] = m_origin->prepareStatement(ASCII_STR( SQL_GET_REFERENCES_SOME_SOME_NONE_SOME ));
    2064           0 :     m_getReferences_stmt[12] = m_origin->prepareStatement(ASCII_STR( SQL_GET_REFERENCES_NONE_NONE_SOME_SOME ));
    2065           0 :     m_getReferences_stmt[13] = m_origin->prepareStatement(ASCII_STR( SQL_GET_REFERENCES_SOME_NONE_SOME_SOME ));
    2066           0 :     m_getReferences_stmt[14] = m_origin->prepareStatement(ASCII_STR( SQL_GET_REFERENCES_NONE_SOME_SOME_SOME ));
    2067           0 :     m_getReferences_stmt[15] = m_origin->prepareStatement(ASCII_STR( SQL_GET_REFERENCES_SOME_SOME_SOME_SOME ));
    2068           0 : }
    2069             : 
    2070           0 : void DatabaseMetaData::init_getPrivs_stmt ()
    2071             : {
    2072           0 :     rtl::OUStringBuffer sSQL(300);
    2073             :     sSQL.append( ASCII_STR(
    2074             :             " SELECT dp.TABLE_CAT, dp.TABLE_SCHEM, dp.TABLE_NAME, dp.GRANTOR, pr.rolname AS GRANTEE, dp.privilege, dp.is_grantable "
    2075             :             " FROM ("
    2076             :             "  SELECT table_catalog AS TABLE_CAT, table_schema AS TABLE_SCHEM, table_name,"
    2077             :             "         grantor, grantee, privilege_type AS PRIVILEGE, is_grantable"
    2078           0 :             "  FROM information_schema.table_privileges") );
    2079           0 :     if ( PQserverVersion( m_pSettings->pConnection ) < 90200 )
    2080             :         // information_schema.table_privileges does not fill in default ACLs when no ACL
    2081             :         // assume default ACL is "owner has all privileges" and add it
    2082             :         sSQL.append( ASCII_STR(
    2083             :             " UNION "
    2084             :             "  SELECT current_database() AS TABLE_CAT, pn.nspname AS TABLE_SCHEM, c.relname AS TABLE_NAME,"
    2085             :             "         ro.rolname AS GRANTOR, rg.rolname AS GRANTEE, p.privilege, 'YES' AS is_grantable"
    2086             :             "  FROM pg_catalog.pg_class c,"
    2087             :             "       (VALUES ('SELECT'), ('INSERT'), ('UPDATE'), ('DELETE'), ('TRUNCATE'), ('REFERENCES'), ('TRIGGER')) p (privilege),"
    2088             :             "       pg_catalog.pg_roles ro,"
    2089             :             "       (  SELECT oid, rolname FROM pg_catalog.pg_roles"
    2090             :             "         UNION ALL"
    2091             :             "          VALUES (0::oid, 'PUBLIC')"
    2092             :             "       ) AS rg (oid, rolname),"
    2093             :             "       pg_catalog.pg_namespace pn"
    2094             :             "  WHERE c.relkind IN ('r', 'v') AND c.relacl IS NULL AND pg_has_role(rg.oid, c.relowner, 'USAGE')"
    2095           0 :             "        AND c.relowner=ro.oid AND c.relnamespace = pn.oid") );
    2096             :     sSQL.append( ASCII_STR(
    2097             :             " ) dp,"
    2098             :             " (SELECT oid, rolname FROM pg_catalog.pg_roles UNION ALL VALUES (0, 'PUBLIC')) pr"
    2099             :             " WHERE table_schem LIKE ? AND table_name LIKE ? AND (dp.grantee = 'PUBLIC' OR pg_has_role(pr.oid, dp.grantee, 'USAGE'))"
    2100           0 :             " ORDER BY table_schem, table_name, privilege" ) );
    2101             : 
    2102           0 :     m_getTablePrivs_stmt = m_origin->prepareStatement( sSQL.makeStringAndClear() );
    2103             : 
    2104             :     sSQL.append( ASCII_STR(
    2105             :             " SELECT dp.TABLE_CAT, dp.TABLE_SCHEM, dp.TABLE_NAME, dp.COLUMN_NAME, dp.GRANTOR, pr.rolname AS GRANTEE, dp.PRIVILEGE, dp.IS_GRANTABLE FROM ("
    2106             :             "  SELECT table_catalog AS TABLE_CAT, table_schema AS TABLE_SCHEM, table_name, column_name,"
    2107             :             "         grantor, grantee, privilege_type AS PRIVILEGE, is_grantable"
    2108           0 :             "  FROM information_schema.column_privileges") );
    2109           0 :     if ( PQserverVersion( m_pSettings->pConnection ) < 90200 )
    2110             :         // information_schema.table_privileges does not fill in default ACLs when no ACL
    2111             :         // assume default ACL is "owner has all privileges" and add it
    2112             :         sSQL.append( ASCII_STR(
    2113             :             " UNION "
    2114             :             "  SELECT current_database() AS TABLE_CAT, pn.nspname AS TABLE_SCHEM, c.relname AS TABLE_NAME, a.attname AS column_name,"
    2115             :             "         ro.rolname AS GRANTOR, rg.rolname AS GRANTEE, p.privilege, 'YES' AS is_grantable"
    2116             :             "  FROM pg_catalog.pg_class c, pg_catalog.pg_attribute a,"
    2117             :             "       (VALUES ('SELECT'), ('INSERT'), ('UPDATE'), ('REFERENCES')) p (privilege),"
    2118             :             "       pg_catalog.pg_roles ro,"
    2119             :             "       (  SELECT oid, rolname FROM pg_catalog.pg_roles"
    2120             :             "         UNION ALL"
    2121             :             "          VALUES (0::oid, 'PUBLIC')"
    2122             :             "       ) AS rg (oid, rolname),"
    2123             :             "       pg_catalog.pg_namespace pn"
    2124             :             "  WHERE c.relkind IN ('r', 'v') AND c.relacl IS NULL AND pg_has_role(rg.oid, c.relowner, 'USAGE')"
    2125           0 :             "        AND c.relowner=ro.oid AND c.relnamespace = pn.oid AND a.attrelid = c.oid AND a.attnum > 0") );
    2126             :     sSQL.append( ASCII_STR(
    2127             :             " ) dp,"
    2128             :             " (SELECT oid, rolname FROM pg_catalog.pg_roles UNION ALL VALUES (0, 'PUBLIC')) pr"
    2129             :             " WHERE table_schem = ? AND table_name = ? AND column_name LIKE ? AND (dp.grantee = 'PUBLIC' OR pg_has_role(pr.oid, dp.grantee, 'USAGE'))"
    2130           0 :             " ORDER BY column_name, privilege" ) );
    2131             : 
    2132           0 :     m_getColumnPrivs_stmt = m_origin->prepareStatement( sSQL.makeStringAndClear() );
    2133           0 : }
    2134             : 
    2135           0 : ::com::sun::star::uno::Reference< XResultSet > DatabaseMetaData::getImportedExportedKeys(
    2136             :     const Any& /* primaryCatalog */,
    2137             :     const OUString& primarySchema,
    2138             :     const OUString& primaryTable,
    2139             :     const Any& /* foreignCatalog */,
    2140             :     const OUString& foreignSchema,
    2141             :     const OUString& foreignTable ) throw (SQLException, RuntimeException)
    2142             : {
    2143           0 :     unsigned int i = 0;
    2144           0 :     if ( ! primarySchema.isEmpty() )
    2145           0 :         i |=  0x01;
    2146           0 :     if ( ! primaryTable.isEmpty() )
    2147           0 :         i |=  0x02;
    2148           0 :     if ( ! foreignSchema.isEmpty() )
    2149           0 :         i |=  0x04;
    2150           0 :     if ( ! foreignTable.isEmpty() )
    2151           0 :         i |=  0x08;
    2152             : 
    2153           0 :     Reference< XPreparedStatement > stmt = m_getReferences_stmt[i];
    2154           0 :     Reference< XParameters > param ( stmt, UNO_QUERY_THROW );
    2155             : 
    2156           0 :     unsigned int j = 1;
    2157           0 :     if ( i & 0x01 )
    2158           0 :         param->setString( j++, primarySchema );
    2159           0 :     if ( i & 0x02 )
    2160           0 :         param->setString( j++, primaryTable  );
    2161           0 :     if ( i & 0x04 )
    2162           0 :         param->setString( j++, foreignSchema );
    2163           0 :     if ( i & 0x08 )
    2164           0 :         param->setString( j++, foreignTable  );
    2165             : 
    2166           0 :     Reference< XResultSet > rs = stmt->executeQuery();
    2167             : 
    2168           0 :     return rs;
    2169             : }
    2170             : 
    2171             : 
    2172           0 : ::com::sun::star::uno::Reference< XResultSet > DatabaseMetaData::getImportedKeys(
    2173             :     const ::com::sun::star::uno::Any& catalog,
    2174             :     const OUString& schema,
    2175             :     const OUString& table ) throw (SQLException, RuntimeException)
    2176             : {
    2177           0 :     return getImportedExportedKeys(Any(), OUString(), OUString(), catalog, schema, table);
    2178             : }
    2179             : 
    2180           0 : ::com::sun::star::uno::Reference< XResultSet > DatabaseMetaData::getExportedKeys(
    2181             :     const ::com::sun::star::uno::Any& catalog,
    2182             :     const OUString& schema,
    2183             :     const OUString& table ) throw (SQLException, RuntimeException)
    2184             : {
    2185           0 :     return getImportedExportedKeys(catalog, schema, table, Any(), OUString(), OUString());
    2186             : }
    2187             : 
    2188           0 : ::com::sun::star::uno::Reference< XResultSet > DatabaseMetaData::getCrossReference(
    2189             :     const ::com::sun::star::uno::Any& primaryCatalog,
    2190             :     const OUString& primarySchema,
    2191             :     const OUString& primaryTable,
    2192             :     const ::com::sun::star::uno::Any& foreignCatalog,
    2193             :     const OUString& foreignSchema,
    2194             :     const OUString& foreignTable ) throw (SQLException, RuntimeException)
    2195             : {
    2196           0 :     return getImportedExportedKeys( primaryCatalog, primarySchema, primaryTable, foreignCatalog, foreignSchema, foreignTable );
    2197             : }
    2198             : 
    2199             : 
    2200             : struct TypeInfoByDataTypeSorter
    2201             : {
    2202           0 :     bool operator () ( const Sequence< Any > & a, const Sequence< Any > & b )
    2203             :     {
    2204           0 :         OUString valueA;
    2205           0 :         OUString valueB;
    2206           0 :         a[1 /*DATA_TYPE*/] >>= valueA;
    2207           0 :         b[1 /*DATA_TYPE*/] >>= valueB;
    2208           0 :         if( valueB.toInt32() == valueA.toInt32() )
    2209             :         {
    2210           0 :             OUString nameA;
    2211           0 :             OUString nameB;
    2212           0 :             a[0 /*TYPE_NAME*/] >>= nameA;
    2213           0 :             b[0 /*TYPE_NAME*/] >>= nameB;
    2214           0 :             if( nameA.compareToAscii( RTL_CONSTASCII_STRINGPARAM( "int4" ) ) == 0 )
    2215           0 :                 return 1;
    2216           0 :             if( nameB.compareToAscii( RTL_CONSTASCII_STRINGPARAM( "int4" ) ) == 0 )
    2217           0 :                 return 0;
    2218           0 :             return nameA.compareTo( nameB ) < 0;
    2219             :         }
    2220             : 
    2221           0 :         return valueA.toInt32() < valueB.toInt32();
    2222             : //         sal_Int32 valueA;
    2223             : //         sal_Int32 valueB;
    2224             : //         a[1 /*DATA_TYPE*/] >>= valueA;
    2225             : //         b[1 /*DATA_TYPE*/] >>= valueB;
    2226             : //         if( valueB == valueA )
    2227             : //         {
    2228             : //             OUString nameA;
    2229             : //             OUString nameB;
    2230             : //             a[0 /*TYPE_NAME*/] >>= nameA;
    2231             : //             b[0 /*TYPE_NAME*/] >>= nameB;
    2232             : //             return nameA.compareTo( nameB ) < 0;
    2233             : //         }
    2234             : 
    2235             : //         return valueA < valueB;
    2236             :     }
    2237             : };
    2238             : 
    2239           0 : static sal_Int32 calcSearchable( sal_Int32 dataType )
    2240             : {
    2241           0 :     sal_Int32 ret = com::sun::star::sdbc::ColumnSearch::FULL;
    2242           0 :     if( com::sun::star::sdbc::DataType::BINARY == dataType ||
    2243             :         com::sun::star::sdbc::DataType::VARBINARY == dataType ||
    2244             :         com::sun::star::sdbc::DataType::LONGVARBINARY == dataType )
    2245           0 :         ret = com::sun::star::sdbc::ColumnSearch::NONE;
    2246             : 
    2247           0 :     return ret;
    2248             : }
    2249             : 
    2250           0 : static sal_Int32 getMaxScale( sal_Int32 dataType )
    2251             : {
    2252             :     // LEM TODO: review, see where used, see JDBC, ...
    2253           0 :     sal_Int32 ret = 0;
    2254           0 :     if( dataType == com::sun::star::sdbc::DataType::NUMERIC )
    2255           0 :         ret = 1000; // see pg-docs DataType/numeric
    2256             : //     else if( dataType == DataType::DOUBLE )
    2257             : //         ret = 308;
    2258             : //     else if( dataType == DataType::FLOAT )
    2259             : //         ret =
    2260           0 :     return ret;
    2261             : }
    2262             : 
    2263             : 
    2264             : struct RawType
    2265             : {
    2266             :     const char * typeName;
    2267             :     const char * createParam;
    2268             :     sal_Int32    sdbcType;
    2269             :     sal_Int32    precision;
    2270             :     sal_Int32    nullable;
    2271             :     bool         caseSensitive;
    2272             :     sal_Int32    searchable;
    2273             : };
    2274             : 
    2275           0 : static void pgTypeInfo2ResultSet(
    2276             :      SequenceAnyVector &vec,
    2277             :      const Reference< XResultSet > &rs )
    2278             : {
    2279             :     static const sal_Int32 TYPE_NAME = 0;  // string Type name
    2280             :     static const sal_Int32 DATA_TYPE = 1;  // short SQL data type from java.sql.Types
    2281             :     static const sal_Int32 PRECISION = 2;  // long maximum precision
    2282             :     static const sal_Int32 CREATE_PARAMS = 5; // string => parameters used in creating the type (may be NULL )
    2283             :     static const sal_Int32 NULLABLE  = 6;  // short ==> can you use NULL for this type?
    2284             :                                            // - NO_NULLS - does not allow NULL values
    2285             :                                            // - NULLABLE - allows NULL values
    2286             :                                            // - NULLABLE_UNKNOWN - nullability unknown
    2287             : 
    2288             :     static const sal_Int32 CASE_SENSITIVE = 7; // boolean==> is it case sensitive
    2289             :     static const sal_Int32 SEARCHABLE = 8;  // short ==>; can you use
    2290             :                                             // "WHERE" based on this type:
    2291             :                                             //   - NONE - No support
    2292             :                                             //   - CHAR - Only supported with WHERE .. LIKE
    2293             :                                             //   - BASIC - Supported except for WHERE .. LIKE
    2294             :                                             //   - FULL - Supported for all WHERE ..
    2295             :     static const sal_Int32 UNSIGNED_ATTRIBUTE = 9; // boolean ==> is it unsigned?
    2296             :     static const sal_Int32 FIXED_PREC_SCALE = 10; // boolean ==> can it be a money value?
    2297             :     static const sal_Int32 AUTO_INCREMENT = 11; // boolean ==> can it be used for
    2298             :                                                 // an auto-increment value?
    2299             :     static const sal_Int32 MINIMUM_SCALE = 13; // short ==> minimum scale supported
    2300             :     static const sal_Int32 MAXIMUM_SCALE = 14; // short ==> maximum scale supported
    2301             :     static const sal_Int32 NUM_PREC_RADIX = 17; // long ==> usually 2 or 10
    2302             : 
    2303             :     /*  not filled so far
    2304             :         3. LITERAL_PREFIX string ==> prefix used to quote a literal
    2305             :                                      (may be <NULL/>)
    2306             :         4, LITERAL_SUFFIX string ==> suffix used to quote a literal
    2307             :                                     (may be <NULL/>)
    2308             :         5. CREATE_PARAMS string ==> parameters used in creating thw type (may be <NULL/>)
    2309             :         12. LOCAL_TYPE_NAME  string ==> localized version of type name (may be <NULL/>)
    2310             :         15, SQL_DATA_TYPE long ==> unused
    2311             :         16. SQL_DATETIME_SUB long ==> unused
    2312             :      */
    2313           0 :     Reference< XRow > xRow( rs, UNO_QUERY_THROW );
    2314           0 :     while( rs->next() )
    2315             :     {
    2316           0 :         Sequence< Any > row(18);
    2317             : 
    2318           0 :         sal_Int32 dataType =typeNameToDataType(xRow->getString(5),xRow->getString(2));
    2319           0 :         sal_Int32 precision = xRow->getString(3).toInt32();
    2320             : 
    2321           0 :         if( dataType == com::sun::star::sdbc::DataType::CHAR  ||
    2322             :             ( dataType == com::sun::star::sdbc::DataType::VARCHAR &&
    2323           0 :               xRow->getString(TYPE_NAME+1).equalsIgnoreAsciiCaseAsciiL(RTL_CONSTASCII_STRINGPARAM("varchar")) ) )
    2324             :         {
    2325             :             // reflect varchar as varchar with upper limit !
    2326             :             //NOTE: the sql spec requires varchar to have an upper limit, however
    2327             :             //      in postgresql the upper limit is optional, no limit means unlimited
    2328             :             //      length (=1GB).
    2329           0 :             precision = 0x40000000; // about 1 GB, see character type docs in postgresql
    2330           0 :             row[CREATE_PARAMS] <<= ASCII_STR( "length" );
    2331             :         }
    2332           0 :         else if( dataType == com::sun::star::sdbc::DataType::NUMERIC )
    2333             :         {
    2334           0 :             precision = 1000;
    2335           0 :             row[CREATE_PARAMS] <<= ASCII_STR( "length, scale" );
    2336             :         }
    2337             : 
    2338           0 :         row[TYPE_NAME] <<= xRow->getString(1);
    2339           0 :         row[DATA_TYPE] <<= OUString::valueOf(dataType);
    2340           0 :         row[PRECISION] <<= OUString::valueOf( precision );
    2341           0 :         sal_Int32 nullable = xRow->getBoolean(4) ?
    2342             :             com::sun::star::sdbc::ColumnValue::NO_NULLS :
    2343           0 :             com::sun::star::sdbc::ColumnValue::NULLABLE;
    2344           0 :         row[NULLABLE] <<= OUString::valueOf(nullable);
    2345           0 :         row[CASE_SENSITIVE] <<= OUString::valueOf((sal_Int32)1);
    2346           0 :         row[SEARCHABLE] <<= OUString::valueOf( calcSearchable( dataType ) );
    2347           0 :         row[UNSIGNED_ATTRIBUTE] <<= ASCII_STR( "0" ); //
    2348           0 :         if( com::sun::star::sdbc::DataType::INTEGER == dataType ||
    2349             :             com::sun::star::sdbc::DataType::BIGINT == dataType )
    2350           0 :             row[AUTO_INCREMENT] <<= ASCII_STR( "1" );     // TODO
    2351             :         else
    2352           0 :             row[AUTO_INCREMENT] <<= ASCII_STR( "0" );     // TODO
    2353           0 :         row[MINIMUM_SCALE] <<= ASCII_STR( "0" );      // TODO: what is this ?
    2354           0 :         row[MAXIMUM_SCALE] <<= OUString::valueOf( getMaxScale( dataType ) );
    2355           0 :         row[NUM_PREC_RADIX] <<= ASCII_STR( "10" );    // TODO: what is this ?
    2356             :         (void)FIXED_PREC_SCALE;
    2357           0 :         vec.push_back( row );
    2358           0 :     }
    2359             : 
    2360           0 : }
    2361             : 
    2362             : 
    2363           0 : ::com::sun::star::uno::Reference< XResultSet > DatabaseMetaData::getTypeInfo(  )
    2364             :     throw (SQLException, RuntimeException)
    2365             : {
    2366             :     // Note: Indexes start at 0 (in the API doc, they start at 1)
    2367           0 :     MutexGuard guard( m_refMutex->mutex );
    2368           0 :     checkClosed();
    2369             : 
    2370           0 :     if( isLog( m_pSettings, LogLevel::INFO ) )
    2371             :     {
    2372           0 :         log( m_pSettings, LogLevel::INFO, "DatabaseMetaData::getTypeInfo() got called" );
    2373             :     }
    2374             : 
    2375           0 :     Reference< XStatement > statement = m_origin->createStatement();
    2376           0 :     Reference< XResultSet > rs = statement->executeQuery(
    2377             :         ASCII_STR(
    2378             :           "SELECT pg_type.typname AS typname," //1
    2379             :           "pg_type.typtype AS typtype,"        //2
    2380             :           "pg_type.typlen AS typlen,"          //3
    2381             :           "pg_type.typnotnull AS typnotnull,"  //4
    2382             :           "pg_type.typname AS typname "        //5
    2383             :           "FROM pg_type "
    2384             :           "WHERE pg_type.typtype = 'b' "
    2385             :           "OR pg_type.typtype = 'p'"
    2386           0 :             ) );
    2387             : 
    2388           0 :     SequenceAnyVector vec;
    2389           0 :     pgTypeInfo2ResultSet( vec, rs );
    2390             : 
    2391             :     // check for domain types
    2392           0 :     rs = statement->executeQuery(
    2393             :      ASCII_STR(
    2394             :         "SELECT t1.typname as typname,"
    2395             :         "t2.typtype AS typtype,"
    2396             :         "t2.typlen AS typlen,"
    2397             :         "t2.typnotnull AS typnotnull,"
    2398             :         "t2.typname as realtypname "
    2399             :         "FROM pg_type as t1 LEFT JOIN pg_type AS t2 ON t1.typbasetype=t2.oid "
    2400           0 :         "WHERE t1.typtype = 'd'" ) );
    2401           0 :     pgTypeInfo2ResultSet( vec, rs );
    2402             : 
    2403           0 :     std::sort( vec.begin(), vec.end(), TypeInfoByDataTypeSorter() );
    2404             : 
    2405             :     return new SequenceResultSet(
    2406             :         m_refMutex,
    2407             :         *this,
    2408           0 :         getStatics().typeinfoColumnNames,
    2409             :         sequence_of_vector(vec),
    2410             :         m_pSettings->tc,
    2411           0 :         &( getStatics().typeInfoMetaData ));
    2412             : }
    2413             : 
    2414             : 
    2415           0 : static sal_Int32 seqContains( const Sequence< sal_Int32 > &seq, sal_Int32 value )
    2416             : {
    2417           0 :     sal_Int32 ret = -1;
    2418           0 :     for( int i = 0; i < seq.getLength(); i ++ )
    2419             :     {
    2420           0 :         if( seq[i] == value )
    2421             :         {
    2422           0 :             ret = i;
    2423           0 :             break;
    2424             :         }
    2425             :     }
    2426           0 :     return ret;
    2427             : }
    2428             : 
    2429           0 : ::com::sun::star::uno::Reference< XResultSet > DatabaseMetaData::getIndexInfo(
    2430             :     const ::com::sun::star::uno::Any& catalog,
    2431             :     const OUString& schema,
    2432             :     const OUString& table,
    2433             :     sal_Bool unique,
    2434             :     sal_Bool approximate ) throw (SQLException, RuntimeException)
    2435             : {
    2436             :     (void) catalog; (void) approximate;
    2437             :     //LEM TODO: review
    2438           0 :     MutexGuard guard( m_refMutex->mutex );
    2439           0 :     checkClosed();
    2440             : 
    2441             :     /*
    2442             :        1. TABLE_CAT string -> table catalog (may be NULL )
    2443             :        2. TABLE_SCHEM string -> table schema (may be NULL )
    2444             :        3. TABLE_NAME string -> table name
    2445             :        4. NON_UNIQUE boolean -> Can index values be non-unique?
    2446             :                                 false when TYPE is tableIndexStatistic
    2447             :        5. INDEX_QUALIFIER string -> index catalog (may be NULL );
    2448             :                                 NULL when TYPE is tableIndexStatistic
    2449             :        6. INDEX_NAME string -> index name; NULL when TYPE is tableIndexStatistic
    2450             :        7. TYPE short -> index type:
    2451             :               * 0 - this identifies table statistics that are returned
    2452             :                     in conjuction with a table's index descriptions
    2453             :               * CLUSTERED - this is a clustered index
    2454             :               * HASHED - this is a hashed index
    2455             :               * OTHER - this is some other style of index
    2456             :        8. ORDINAL_POSITION short -> column sequence number within index;
    2457             :                                     zero when TYPE is tableIndexStatistic
    2458             :        9. COLUMN_NAME string -> column name; NULL when TYPE is tableIndexStatistic
    2459             :       10. ASC_OR_DESC string -> column sort sequence, "A"= ascending,
    2460             :                                 "D" = descending, may be NULL if sort sequence
    2461             :                                 is not supported; NULL when TYPE is tableIndexStatistic
    2462             :       11. CARDINALITY long -> When TYPE is tableIndexStatistic, then this is
    2463             :                               the number of rows in the table; otherwise, it
    2464             :                               is the number of unique values in the index.
    2465             :       12. PAGES long -> When TYPE is tableIndexStatisic then this is
    2466             :                         the number of pages used for the table, otherwise
    2467             :                         it is the number of pages used for the current index.
    2468             :       13. FILTER_CONDITION string -> Filter condition, if any. (may be NULL )
    2469             : 
    2470             :     */
    2471             :     static const sal_Int32 C_SCHEMA = 1;
    2472             :     static const sal_Int32 C_TABLENAME = 2;
    2473             :     static const sal_Int32 C_INDEXNAME = 3;
    2474             :     static const sal_Int32 C_IS_CLUSTERED = 4;
    2475             :     static const sal_Int32 C_IS_UNIQUE = 5;
    2476             :     static const sal_Int32 C_IS_PRIMARY = 6;
    2477             :     static const sal_Int32 C_COLUMNS = 7;
    2478             : 
    2479             :     static const sal_Int32 R_TABLE_SCHEM = 1;
    2480             :     static const sal_Int32 R_TABLE_NAME = 2;
    2481             :     static const sal_Int32 R_NON_UNIQUE = 3;
    2482             :     static const sal_Int32 R_INDEX_NAME = 5;
    2483             :     static const sal_Int32 R_TYPE = 6;
    2484             :     static const sal_Int32 R_ORDINAL_POSITION = 7;
    2485             :     static const sal_Int32 R_COLUMN_NAME = 8;
    2486             : 
    2487           0 :     Reference< XPreparedStatement > stmt = m_origin->prepareStatement(
    2488             :         ASCII_STR(
    2489             :             "SELECT nspname, "          // 1
    2490             :                    "pg_class.relname, " // 2
    2491             :                    "class2.relname, "   // 3
    2492             :                    "indisclustered, "   // 4
    2493             :                    "indisunique, "      // 5
    2494             :                    "indisprimary, "     // 6
    2495             :                    "indkey "            // 7
    2496             :             "FROM pg_index INNER JOIN pg_class ON indrelid = pg_class.oid "
    2497             :                           "INNER JOIN pg_namespace ON pg_class.relnamespace = pg_namespace.oid "
    2498             :                           "INNER JOIN pg_class as class2 ON pg_index.indexrelid = class2.oid "
    2499           0 :             "WHERE nspname = ? AND pg_class.relname = ?" ) );
    2500             : 
    2501           0 :     Reference< XParameters > param ( stmt, UNO_QUERY_THROW );
    2502           0 :     param->setString( 1, schema );
    2503           0 :     param->setString( 2, table );
    2504           0 :     Reference< XResultSet > rs = stmt->executeQuery();
    2505           0 :     Reference< XRow > xRow ( rs, UNO_QUERY_THROW );
    2506             : 
    2507           0 :     SequenceAnyVector vec;
    2508           0 :     while( rs->next() )
    2509             :     {
    2510           0 :         Sequence< sal_Int32 > columns = parseIntArray( xRow->getString(C_COLUMNS) );
    2511           0 :         Reference< XPreparedStatement > columnsStmt = m_origin->prepareStatement(
    2512             :             ASCII_STR(
    2513             :                 "SELECT attnum, attname "
    2514             :                 "FROM pg_attribute "
    2515             :                 "     INNER JOIN pg_class ON attrelid = pg_class.oid "
    2516             :                 "     INNER JOIN pg_namespace ON pg_class.relnamespace=pg_namespace.oid "
    2517           0 :                 "     WHERE pg_namespace.nspname=?  AND pg_class.relname=?" ) );
    2518           0 :         Reference< XParameters > paramColumn ( columnsStmt, UNO_QUERY_THROW );
    2519           0 :         OUString currentSchema = xRow->getString( C_SCHEMA );
    2520           0 :         OUString currentTable = xRow->getString( C_TABLENAME );
    2521           0 :         OUString currentIndexName = xRow->getString( C_INDEXNAME );
    2522           0 :         sal_Bool isNonUnique = ! xRow->getBoolean( C_IS_UNIQUE );
    2523           0 :         sal_Bool isPrimary = xRow->getBoolean( C_IS_PRIMARY );
    2524             :         (void)isPrimary;
    2525           0 :         sal_Int32 indexType =  xRow->getBoolean( C_IS_CLUSTERED ) ?
    2526             :             com::sun::star::sdbc::IndexType::CLUSTERED :
    2527           0 :             com::sun::star::sdbc::IndexType::HASHED;
    2528             : 
    2529           0 :         paramColumn->setString( C_SCHEMA, currentSchema );
    2530           0 :         paramColumn->setString( C_TABLENAME, currentTable );
    2531             : 
    2532           0 :         Reference< XResultSet > rsColumn = columnsStmt->executeQuery();
    2533           0 :         Reference< XRow > rowColumn( rsColumn, UNO_QUERY_THROW );
    2534           0 :         while( rsColumn->next() )
    2535             :         {
    2536           0 :             sal_Int32 pos = seqContains( columns, rowColumn->getInt( 1 ) );
    2537           0 :             if( pos >= 0 && ( ! isNonUnique || !  unique ) )
    2538             :             {
    2539           0 :                 Sequence< Any > result( 13 );
    2540           0 :                 result[R_TABLE_SCHEM] = makeAny(currentSchema);
    2541           0 :                 result[R_TABLE_NAME] = makeAny(currentTable);
    2542           0 :                 result[R_INDEX_NAME] = makeAny(currentIndexName);
    2543           0 :                 result[R_NON_UNIQUE] =
    2544           0 :                     Any( &isNonUnique, getBooleanCppuType() );
    2545           0 :                 result[R_TYPE] = makeAny( indexType );
    2546           0 :                 result[R_COLUMN_NAME] = makeAny( rowColumn->getString(2) );
    2547           0 :                 sal_Int32 nPos = ((sal_Int32)pos+1); // MSVC++ nonsense
    2548           0 :                 result[R_ORDINAL_POSITION] = makeAny( nPos );
    2549           0 :                 vec.push_back( result );
    2550             :             }
    2551             :         }
    2552           0 :     }
    2553             :     return new SequenceResultSet(
    2554           0 :         m_refMutex, *this, getStatics().indexinfoColumnNames,
    2555             :         sequence_of_vector(vec),
    2556           0 :         m_pSettings->tc );
    2557             : }
    2558             : 
    2559           0 : sal_Bool DatabaseMetaData::supportsResultSetType( sal_Int32 setType )
    2560             :     throw (SQLException, RuntimeException)
    2561             : {
    2562           0 :     if ( setType == com::sun::star::sdbc::ResultSetType::SCROLL_SENSITIVE )
    2563           0 :         return sal_False;
    2564             :     else
    2565           0 :         return sal_True;
    2566             : }
    2567             : 
    2568           0 : sal_Bool DatabaseMetaData::supportsResultSetConcurrency(
    2569             :     sal_Int32 setType, sal_Int32 concurrency ) throw (SQLException, RuntimeException)
    2570             : {
    2571             :     (void) concurrency;
    2572           0 :     if ( ! supportsResultSetType( setType ) )
    2573           0 :         return sal_False;
    2574             :     else
    2575           0 :         return sal_True;
    2576             : }
    2577             : 
    2578           0 : sal_Bool DatabaseMetaData::ownUpdatesAreVisible( sal_Int32 /* setType */ ) throw (SQLException, RuntimeException)
    2579             : {
    2580           0 :     return sal_True;
    2581             : }
    2582             : 
    2583           0 : sal_Bool DatabaseMetaData::ownDeletesAreVisible( sal_Int32 /* setType */ ) throw (SQLException, RuntimeException)
    2584             : {
    2585           0 :     return sal_True;
    2586             : }
    2587             : 
    2588           0 : sal_Bool DatabaseMetaData::ownInsertsAreVisible( sal_Int32 /* setType */ ) throw (SQLException, RuntimeException)
    2589             : {
    2590           0 :     return sal_True;
    2591             : }
    2592             : 
    2593           0 : sal_Bool DatabaseMetaData::othersUpdatesAreVisible( sal_Int32 /* setType */ ) throw (SQLException, RuntimeException)
    2594             : {
    2595           0 :     return sal_False;
    2596             : }
    2597             : 
    2598           0 : sal_Bool DatabaseMetaData::othersDeletesAreVisible( sal_Int32 /* setType */ ) throw (SQLException, RuntimeException)
    2599             : {
    2600           0 :     return sal_False;
    2601             : }
    2602             : 
    2603           0 : sal_Bool DatabaseMetaData::othersInsertsAreVisible( sal_Int32 /* setType */ ) throw (SQLException, RuntimeException)
    2604             : {
    2605           0 :     return sal_False;
    2606             : }
    2607             : 
    2608           0 : sal_Bool DatabaseMetaData::updatesAreDetected( sal_Int32 /* setType */ ) throw (SQLException, RuntimeException)
    2609             : {
    2610           0 :     return sal_False;
    2611             : }
    2612             : 
    2613           0 : sal_Bool DatabaseMetaData::deletesAreDetected( sal_Int32 /* setType */ ) throw (SQLException, RuntimeException)
    2614             : {
    2615           0 :     return sal_False;
    2616             : }
    2617           0 : sal_Bool DatabaseMetaData::insertsAreDetected( sal_Int32 /* setType */ ) throw (SQLException, RuntimeException)
    2618             : {
    2619           0 :     return sal_False;
    2620             : }
    2621             : 
    2622           0 : sal_Bool DatabaseMetaData::supportsBatchUpdates(  ) throw (SQLException, RuntimeException)
    2623             : {
    2624           0 :     return sal_True;
    2625             : }
    2626             : 
    2627           0 : ::com::sun::star::uno::Reference< XResultSet > DatabaseMetaData::getUDTs( const ::com::sun::star::uno::Any& catalog, const OUString& schemaPattern, const OUString& typeNamePattern, const ::com::sun::star::uno::Sequence< sal_Int32 >& types ) throw (SQLException, RuntimeException)
    2628             : {
    2629             :     (void) catalog; (void) schemaPattern; (void) typeNamePattern; (void) types;
    2630             :     //LEM TODO: implement! See JDBC driver
    2631           0 :     MutexGuard guard( m_refMutex->mutex );
    2632           0 :     checkClosed();
    2633             :     return new SequenceResultSet(
    2634           0 :         m_refMutex, *this, Sequence< OUString >(), Sequence< Sequence< Any > > (), m_pSettings->tc );
    2635             : }
    2636             : 
    2637           0 : ::com::sun::star::uno::Reference< com::sun::star::sdbc::XConnection > DatabaseMetaData::getConnection()
    2638             :     throw (SQLException, RuntimeException)
    2639             : {
    2640           0 :     return m_origin;
    2641             : }
    2642             : }

Generated by: LCOV version 1.10