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

Generated by: LCOV version 1.10