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

Generated by: LCOV version 1.10