LCOV - code coverage report
Current view: top level - connectivity/source/drivers/postgresql - pq_tools.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 0 626 0.0 %
Date: 2012-08-25 Functions: 0 49 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 0 -

           Branch data     Line data    Source code
       1                 :            : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2                 :            : /*************************************************************************
       3                 :            :  *
       4                 :            :  *  Effective License of whole file:
       5                 :            :  *
       6                 :            :  *    This library is free software; you can redistribute it and/or
       7                 :            :  *    modify it under the terms of the GNU Lesser General Public
       8                 :            :  *    License version 2.1, as published by the Free Software Foundation.
       9                 :            :  *
      10                 :            :  *    This library is distributed in the hope that it will be useful,
      11                 :            :  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
      12                 :            :  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13                 :            :  *    Lesser General Public License for more details.
      14                 :            :  *
      15                 :            :  *    You should have received a copy of the GNU Lesser General Public
      16                 :            :  *    License along with this library; if not, write to the Free Software
      17                 :            :  *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
      18                 :            :  *    MA  02111-1307  USA
      19                 :            :  *
      20                 :            :  *  Parts "Copyright by Sun Microsystems, Inc" prior to August 2011:
      21                 :            :  *
      22                 :            :  *    The Contents of this file are made available subject to the terms of
      23                 :            :  *    the GNU Lesser General Public License Version 2.1
      24                 :            :  *
      25                 :            :  *    Copyright: 2000 by Sun Microsystems, Inc.
      26                 :            :  *
      27                 :            :  *    Contributor(s): Joerg Budischewski
      28                 :            :  *
      29                 :            :  *  All parts contributed on or after August 2011:
      30                 :            :  *
      31                 :            :  *    Version: MPL 1.1 / GPLv3+ / LGPLv2.1+
      32                 :            :  *
      33                 :            :  *    The contents of this file are subject to the Mozilla Public License Version
      34                 :            :  *    1.1 (the "License"); you may not use this file except in compliance with
      35                 :            :  *    the License or as specified alternatively below. You may obtain a copy of
      36                 :            :  *    the License at http://www.mozilla.org/MPL/
      37                 :            :  *
      38                 :            :  *    Software distributed under the License is distributed on an "AS IS" basis,
      39                 :            :  *    WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      40                 :            :  *    for the specific language governing rights and limitations under the
      41                 :            :  *    License.
      42                 :            :  *
      43                 :            :  *    Major Contributor(s):
      44                 :            :  *    [ Copyright (C) 2011 Lionel Elie Mamane <lionel@mamane.lu> ]
      45                 :            :  *
      46                 :            :  *    All Rights Reserved.
      47                 :            :  *
      48                 :            :  *    For minor contributions see the git repository.
      49                 :            :  *
      50                 :            :  *    Alternatively, the contents of this file may be used under the terms of
      51                 :            :  *    either the GNU General Public License Version 3 or later (the "GPLv3+"), or
      52                 :            :  *    the GNU Lesser General Public License Version 2.1 or later (the "LGPLv2.1+"),
      53                 :            :  *    in which case the provisions of the GPLv3+ or the LGPLv2.1+ are applicable
      54                 :            :  *    instead of those above.
      55                 :            :  *
      56                 :            :  ************************************************************************/
      57                 :            : 
      58                 :            : #include <rtl/strbuf.hxx>
      59                 :            : #include <rtl/ustrbuf.hxx>
      60                 :            : 
      61                 :            : #include <com/sun/star/beans/XPropertySet.hpp>
      62                 :            : #include <com/sun/star/lang/XComponent.hpp>
      63                 :            : 
      64                 :            : #include <com/sun/star/sdbc/XRow.hpp>
      65                 :            : #include <com/sun/star/sdbc/XParameters.hpp>
      66                 :            : #include <com/sun/star/sdbc/DataType.hpp>
      67                 :            : #include <com/sun/star/sdbc/KeyRule.hpp>
      68                 :            : #include <com/sun/star/sdbcx/KeyType.hpp>
      69                 :            : #include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
      70                 :            : 
      71                 :            : #include "pq_xcontainer.hxx"
      72                 :            : #include "pq_tools.hxx"
      73                 :            : #include "pq_statics.hxx"
      74                 :            : 
      75                 :            : #include <libpq-fe.h>
      76                 :            : #include <string.h>
      77                 :            : 
      78                 :            : using rtl::OUString;
      79                 :            : using rtl::OUStringBuffer;
      80                 :            : 
      81                 :            : using com::sun::star::beans::XPropertySet;
      82                 :            : 
      83                 :            : using com::sun::star::lang::XComponent;
      84                 :            : 
      85                 :            : using com::sun::star::sdbc::SQLException;
      86                 :            : using com::sun::star::sdbc::XStatement;
      87                 :            : using com::sun::star::sdbc::XConnection;
      88                 :            : using com::sun::star::sdbc::XPreparedStatement;
      89                 :            : using com::sun::star::sdbc::XParameters;
      90                 :            : using com::sun::star::sdbc::XResultSet;
      91                 :            : using com::sun::star::sdbc::XRow;
      92                 :            : 
      93                 :            : using com::sun::star::sdbcx::XColumnsSupplier;
      94                 :            : 
      95                 :            : using com::sun::star::uno::RuntimeException;
      96                 :            : using com::sun::star::uno::UNO_QUERY;
      97                 :            : using com::sun::star::uno::UNO_QUERY_THROW;
      98                 :            : using com::sun::star::uno::Reference;
      99                 :            : using com::sun::star::uno::Sequence;
     100                 :            : using com::sun::star::uno::XInterface;
     101                 :            : using com::sun::star::uno::Any;
     102                 :            : using com::sun::star::uno::makeAny;
     103                 :            : 
     104                 :            : using com::sun::star::container::XEnumeration;
     105                 :            : using com::sun::star::container::XEnumerationAccess;
     106                 :            : 
     107                 :            : namespace pq_sdbc_driver
     108                 :            : {
     109                 :            : #define ASCII_STR(x) rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( x ) )
     110                 :            : 
     111                 :          0 : rtl::OUString date2String( const com::sun::star::util::Date & x )
     112                 :            : {
     113                 :            :     char buffer[64];
     114                 :          0 :     sprintf( buffer, "%d-%02d-%02d", x.Year, x.Month, x.Day );
     115                 :          0 :     return OUString::createFromAscii( buffer );
     116                 :            : }
     117                 :            : 
     118                 :          0 : com::sun::star::util::Date string2Date( const  rtl::OUString &date )
     119                 :            : {
     120                 :            :     // Format: Year-Month-Day
     121                 :          0 :     com::sun::star::util::Date ret;
     122                 :            : 
     123                 :          0 :     ret.Year = (sal_Int32) rtl_ustr_toInt32( date.pData->buffer, 10 );
     124                 :            : 
     125                 :          0 :     int index = date.indexOf( '-' );
     126                 :          0 :     if( index >= 0 )
     127                 :            :     {
     128                 :          0 :         ret.Month = (sal_Int32)rtl_ustr_toInt32( &(date.pData->buffer[ index+1]), 10 );
     129                 :          0 :         int start = index;
     130                 :          0 :         index = date.indexOf( '-', start+1 );
     131                 :          0 :         if( index >= 0 )
     132                 :            :         {
     133                 :          0 :             ret.Day = (sal_Int32)rtl_ustr_toInt32( &date.pData->buffer[index+1], 10 );
     134                 :            :         }
     135                 :            :     }
     136                 :          0 :     return ret;
     137                 :            : }
     138                 :            : 
     139                 :          0 : rtl::OUString time2String( const com::sun::star::util::Time & x )
     140                 :            : {
     141                 :            :     char buffer[64];
     142                 :          0 :     sprintf( buffer, "%02d:%02d:%02d.%02d", x.Hours, x.Minutes, x.Seconds, x.HundredthSeconds );
     143                 :          0 :     return OUString::createFromAscii( buffer );
     144                 :            : 
     145                 :            : }
     146                 :            : 
     147                 :            : 
     148                 :          0 : com::sun::star::util::Time string2Time( const rtl::OUString & time )
     149                 :            : {
     150                 :          0 :     com::sun::star::util::Time ret;
     151                 :            : 
     152                 :            :     sal_Unicode temp[4];
     153                 :            : 
     154                 :          0 :     temp[0] = time[0];
     155                 :          0 :     temp[1] = time[1];
     156                 :          0 :     temp[2] = 0;
     157                 :          0 :     ret.Hours = (sal_Int32)rtl_ustr_toInt32( temp , 10 );
     158                 :            : 
     159                 :          0 :     temp[0] = time[3];
     160                 :          0 :     temp[1] = time[4];
     161                 :          0 :     ret.Minutes = (sal_Int32)rtl_ustr_toInt32( temp , 10 );
     162                 :            : 
     163                 :          0 :     temp[0] = time[6];
     164                 :          0 :     temp[1] = time[7];
     165                 :          0 :     ret.Seconds = (sal_Int32)rtl_ustr_toInt32( temp , 10 );
     166                 :            : 
     167                 :          0 :     if( time.getLength() >9 )
     168                 :            :     {
     169                 :          0 :         ret.HundredthSeconds = (sal_Int32)rtl_ustr_toInt32( &time.getStr()[9] , 10 );
     170                 :            :     }
     171                 :          0 :     return ret;
     172                 :            : 
     173                 :            : }
     174                 :            : 
     175                 :            : 
     176                 :            : 
     177                 :          0 : rtl::OUString dateTime2String( const com::sun::star::util::DateTime & x )
     178                 :            : {
     179                 :            :     char buffer[128];
     180                 :            :     sprintf( buffer, "%d-%02d-%02d %02d:%02d:%02d.%02d",
     181                 :            :              x.Year, x.Month, x.Day,
     182                 :          0 :              x.Hours, x.Minutes, x.Seconds, x.HundredthSeconds );
     183                 :          0 :     return OUString::createFromAscii( buffer );
     184                 :            : 
     185                 :            : }
     186                 :            : 
     187                 :          0 : com::sun::star::util::DateTime string2DateTime( const rtl::OUString & dateTime )
     188                 :            : {
     189                 :          0 :     int space = dateTime.indexOf( ' ' );
     190                 :          0 :     com::sun::star::util::DateTime ret;
     191                 :            : 
     192                 :          0 :     if( space >= 0 )
     193                 :            :     {
     194                 :          0 :         com::sun::star::util::Date date ( string2Date( OUString( dateTime.getStr(), space ) ) );
     195                 :          0 :         com::sun::star::util::Time time( string2Time( OUString( dateTime.getStr() + space +1 ) ) );
     196                 :          0 :         ret.Day = date.Day;
     197                 :          0 :         ret.Month = date.Month;
     198                 :          0 :         ret.Year = date.Year;
     199                 :            : 
     200                 :          0 :         ret.Hours = time.Hours;
     201                 :          0 :         ret.Minutes = time.Minutes;
     202                 :          0 :         ret.Seconds = time.Seconds;
     203                 :          0 :         ret.HundredthSeconds = time.HundredthSeconds;
     204                 :            :     }
     205                 :          0 :     return ret;
     206                 :            : }
     207                 :            : 
     208                 :          0 : rtl::OUString concatQualified( const rtl::OUString & a, const rtl::OUString &b)
     209                 :            : {
     210                 :          0 :     rtl::OUStringBuffer buf( a.getLength() + 2 + b.getLength() );
     211                 :          0 :     buf.append( a );
     212                 :          0 :     buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "." ) );
     213                 :          0 :     buf.append( b );
     214                 :          0 :     return buf.makeStringAndClear();
     215                 :            : }
     216                 :            : 
     217                 :          0 : static inline rtl::OString iOUStringToOString( const rtl::OUString str, ConnectionSettings *settings) {
     218                 :            :     OSL_ENSURE(settings, "pgsql-sdbc: OUStringToOString got NULL settings");
     219                 :          0 :     return rtl::OUStringToOString( str, settings->encoding );
     220                 :            : }
     221                 :            : 
     222                 :          0 : rtl::OString OUStringToOString( const rtl::OUString str, ConnectionSettings *settings) {
     223                 :          0 :     return iOUStringToOString( str, settings );
     224                 :            : }
     225                 :            : 
     226                 :          0 : void bufferEscapeConstant( rtl::OUStringBuffer & buf, const rtl::OUString & value, ConnectionSettings *settings )
     227                 :            : {
     228                 :            : 
     229                 :          0 :     rtl::OString y = iOUStringToOString( value, settings );
     230                 :          0 :     rtl::OStringBuffer strbuf( y.getLength() * 2 + 2 );
     231                 :            :     int error;
     232                 :          0 :     int len = PQescapeStringConn(settings->pConnection, ((char*)strbuf.getStr()), y.getStr() , y.getLength(), &error );
     233                 :          0 :     if ( error )
     234                 :            :     {
     235                 :          0 :         char *errstr = PQerrorMessage(settings->pConnection);
     236                 :            :         // As of PostgreSQL 9.1, the only possible errors "involve invalid multibyte encoding"
     237                 :            :         // According to https://www2.opengroup.org/ogsys/jsp/publications/PublicationDetails.jsp?publicationid=11216
     238                 :            :         // (X/Open SQL CLI, March 1995, ISBN: 1-85912-081-4, X/Open Document Number: C451)
     239                 :            :         // 22018 is for "Invalid character value" and seems to be the best match.
     240                 :            :         // We have no good XInterface Reference to pass here, so just give NULL
     241                 :          0 :         throw SQLException(OUString(errstr, strlen(errstr), settings->encoding),
     242                 :            :                            NULL,
     243                 :            :                            OUString(RTL_CONSTASCII_USTRINGPARAM("22018")),
     244                 :            :                            -1,
     245                 :          0 :                            Any());
     246                 :            :     }
     247                 :          0 :     strbuf.setLength( len );
     248                 :            :     // Previously here RTL_TEXTENCODING_ASCII_US; as we set the PostgreSQL client_encoding to UTF8,
     249                 :            :     // we get UTF8 here, too. I'm not sure why it worked well before...
     250                 :          0 :     buf.append( rtl::OStringToOUString( strbuf.makeStringAndClear(), RTL_TEXTENCODING_UTF8 ) );
     251                 :          0 : }
     252                 :            : 
     253                 :          0 : static inline void ibufferQuoteConstant( rtl::OUStringBuffer & buf, const rtl::OUString & value, ConnectionSettings *settings )
     254                 :            : {
     255                 :          0 :     buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "'" ) );
     256                 :          0 :     bufferEscapeConstant( buf, value, settings );
     257                 :          0 :     buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "'" ) );
     258                 :          0 : }
     259                 :            : 
     260                 :          0 : void bufferQuoteConstant( rtl::OUStringBuffer & buf, const rtl::OUString & value, ConnectionSettings *settings )
     261                 :            : {
     262                 :          0 :     return ibufferQuoteConstant( buf, value, settings );
     263                 :            : }
     264                 :            : 
     265                 :          0 : void bufferQuoteAnyConstant( rtl::OUStringBuffer & buf, const Any &val, ConnectionSettings *settings )
     266                 :            : {
     267                 :          0 :     if( val.hasValue() )
     268                 :            :     {
     269                 :          0 :         OUString str;
     270                 :          0 :         val >>= str;
     271                 :          0 :         bufferQuoteConstant( buf, str, settings );
     272                 :            :     }
     273                 :            :     else
     274                 :          0 :         buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "NULL" ) );
     275                 :          0 : }
     276                 :            : 
     277                 :          0 : static inline void ibufferQuoteIdentifier( rtl::OUStringBuffer & buf, const rtl::OUString &toQuote, ConnectionSettings *settings )
     278                 :            : {
     279                 :            :     OSL_ENSURE(settings, "pgsql-sdbc: bufferQuoteIdentifier got NULL settings");
     280                 :            : 
     281                 :          0 :     rtl::OString y = iOUStringToOString( toQuote, settings );
     282                 :          0 :     char *cstr = PQescapeIdentifier(settings->pConnection, y.getStr(), y.getLength());
     283                 :          0 :     if ( cstr == NULL )
     284                 :            :     {
     285                 :          0 :         char *errstr = PQerrorMessage(settings->pConnection);
     286                 :            :         // Implementation-defined SQLACCESS error
     287                 :          0 :         throw SQLException(OUString(errstr, strlen(errstr), settings->encoding),
     288                 :            :                            NULL,
     289                 :            :                            OUString(RTL_CONSTASCII_USTRINGPARAM("22018")),
     290                 :            :                            -1,
     291                 :          0 :                            Any());
     292                 :            :     }
     293                 :          0 :     buf.append( rtl::OStringToOUString( cstr, RTL_TEXTENCODING_UTF8 ) );
     294                 :          0 :     PQfreemem( cstr );
     295                 :          0 : }
     296                 :            : 
     297                 :          0 : void bufferQuoteIdentifier( rtl::OUStringBuffer & buf, const rtl::OUString &toQuote, ConnectionSettings *settings )
     298                 :            : {
     299                 :          0 :     return ibufferQuoteIdentifier(buf, toQuote, settings);
     300                 :            : }
     301                 :            : 
     302                 :            : 
     303                 :          0 : void bufferQuoteQualifiedIdentifier(
     304                 :            :     rtl::OUStringBuffer & buf, const rtl::OUString &schema, const rtl::OUString &table, ConnectionSettings *settings )
     305                 :            : {
     306                 :          0 :     ibufferQuoteIdentifier(buf, schema, settings);
     307                 :          0 :     buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "." ) );
     308                 :          0 :     ibufferQuoteIdentifier(buf, table, settings);
     309                 :          0 : }
     310                 :            : 
     311                 :          0 : void bufferQuoteQualifiedIdentifier(
     312                 :            :     rtl::OUStringBuffer & buf,
     313                 :            :     const rtl::OUString &schema,
     314                 :            :     const rtl::OUString &table,
     315                 :            :     const rtl::OUString &col,
     316                 :            :     ConnectionSettings *settings)
     317                 :            : {
     318                 :          0 :     ibufferQuoteIdentifier(buf, schema, settings);
     319                 :          0 :     buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "." ) );
     320                 :          0 :     ibufferQuoteIdentifier(buf, table, settings);
     321                 :          0 :     buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "." ) );
     322                 :          0 :     ibufferQuoteIdentifier(buf, col, settings);
     323                 :          0 : }
     324                 :            : 
     325                 :            : 
     326                 :          0 : rtl::OUString extractStringProperty(
     327                 :            :     const Reference< XPropertySet > & descriptor, const rtl::OUString &name )
     328                 :            : {
     329                 :          0 :     rtl::OUString value;
     330                 :          0 :     descriptor->getPropertyValue( name ) >>= value;
     331                 :          0 :     return value;
     332                 :            : }
     333                 :            : 
     334                 :          0 : sal_Bool extractBoolProperty(
     335                 :            :     const Reference< XPropertySet > & descriptor, const rtl::OUString &name )
     336                 :            : {
     337                 :          0 :     sal_Bool value = sal_False;
     338                 :          0 :     descriptor->getPropertyValue( name ) >>= value;
     339                 :          0 :     return value;
     340                 :            : }
     341                 :            : 
     342                 :          0 : sal_Int32 extractIntProperty(
     343                 :            :     const Reference< XPropertySet > & descriptor, const rtl::OUString &name )
     344                 :            : {
     345                 :          0 :     sal_Int32 ret = 0;
     346                 :          0 :     descriptor->getPropertyValue( name ) >>= ret;
     347                 :          0 :     return ret;
     348                 :            : }
     349                 :            : 
     350                 :          0 : void disposeObject( const com::sun::star::uno::Reference< com::sun::star::uno::XInterface > & r )
     351                 :            : {
     352                 :          0 :     Reference< XComponent > comp( r, UNO_QUERY );
     353                 :          0 :     if( comp.is() )
     354                 :          0 :         comp->dispose();
     355                 :          0 : }
     356                 :            : 
     357                 :          0 : void disposeNoThrow( const com::sun::star::uno::Reference< com::sun::star::uno::XInterface > & r )
     358                 :            : {
     359                 :            :     try
     360                 :            :     {
     361                 :          0 :         disposeObject( r );
     362                 :            :     }
     363                 :          0 :     catch( SQLException & )
     364                 :            :     {
     365                 :            :         // ignore this
     366                 :            :     }
     367                 :            : 
     368                 :          0 : }
     369                 :            : 
     370                 :          0 : Reference< XConnection > extractConnectionFromStatement( const Reference< XInterface > & stmt )
     371                 :            : {
     372                 :          0 :     Reference< XConnection > ret;
     373                 :            : 
     374                 :          0 :     Reference< com::sun::star::sdbc::XStatement > owner( stmt, UNO_QUERY );
     375                 :          0 :     if( owner.is() )
     376                 :          0 :         ret = owner->getConnection();
     377                 :            :     else
     378                 :            :     {
     379                 :          0 :         Reference< com::sun::star::sdbc::XPreparedStatement > myowner( stmt, UNO_QUERY );
     380                 :          0 :         if( myowner.is() )
     381                 :          0 :             ret = myowner->getConnection();
     382                 :          0 :         if( ! ret.is() )
     383                 :            :             throw SQLException(
     384                 :            :                 ASCII_STR( "PQSDBC: Couldn't retrieve connection from statement" ),
     385                 :          0 :                 Reference< XInterface > () , rtl::OUString(), 0 , com::sun::star::uno::Any()  );
     386                 :            :     }
     387                 :            : 
     388                 :          0 :     return ret;
     389                 :            : 
     390                 :            : }
     391                 :            : 
     392                 :          0 : DisposeGuard::DisposeGuard( const Reference< XInterface > & r )
     393                 :          0 :     : d( r )
     394                 :          0 : {}
     395                 :            : 
     396                 :          0 : DisposeGuard::~DisposeGuard()
     397                 :            : {
     398                 :          0 :     disposeNoThrow( d );
     399                 :          0 : }
     400                 :            : 
     401                 :          0 : TransactionGuard::TransactionGuard( const Reference< XStatement > &stmt )
     402                 :            :     : m_stmt( stmt ),
     403                 :          0 :       m_commited( sal_False )
     404                 :            : {
     405                 :          0 :     m_stmt->executeUpdate( getStatics().BEGIN );
     406                 :          0 : }
     407                 :            : 
     408                 :          0 : void TransactionGuard::commit()
     409                 :            : {
     410                 :          0 :     m_stmt->executeUpdate( getStatics().COMMIT );
     411                 :          0 :     m_commited = sal_True;
     412                 :          0 : }
     413                 :            : 
     414                 :          0 : void TransactionGuard::executeUpdate( const rtl::OUString & sql )
     415                 :            : {
     416                 :          0 :     m_stmt->executeUpdate( sql );
     417                 :          0 : }
     418                 :            : 
     419                 :          0 : TransactionGuard::~TransactionGuard()
     420                 :            : {
     421                 :            :     try
     422                 :            :     {
     423                 :          0 :         if( ! m_commited )
     424                 :          0 :             m_stmt->executeUpdate( getStatics().ROLLBACK );
     425                 :            :     }
     426                 :          0 :     catch( com::sun::star::uno::Exception & )
     427                 :            :     {
     428                 :            :         // ignore, we are within a dtor
     429                 :            :     }
     430                 :            : 
     431                 :          0 :     disposeNoThrow( m_stmt );
     432                 :          0 : }
     433                 :            : 
     434                 :            : 
     435                 :          0 : bool isWhitespace( sal_Unicode c )
     436                 :            : {
     437                 :          0 :     return ' ' == c || 9 == c || 10 == c || 13 == c;
     438                 :            : }
     439                 :            : 
     440                 :          0 : ::rtl::OUString extractTableFromInsert( const rtl::OUString & sql )
     441                 :            : {
     442                 :          0 :     rtl::OUString ret;
     443                 :          0 :     int i = 0;
     444                 :          0 :     for( ; i < sql.getLength() && isWhitespace(sql[i])  ; i++ );
     445                 :            : 
     446                 :          0 :     if( 0 == rtl_ustr_ascii_shortenedCompareIgnoreAsciiCase_WithLength(
     447                 :          0 :             &sql.getStr()[i], sql.getLength() - i, "insert" , 6 ) )
     448                 :            :     {
     449                 :          0 :         i += 6;
     450                 :          0 :         for( ; i < sql.getLength() && isWhitespace(sql[i]) ; i++ );
     451                 :          0 :         if( 0 == rtl_ustr_ascii_shortenedCompareIgnoreAsciiCase_WithLength(
     452                 :          0 :             &sql.getStr()[i], sql.getLength() - i, "into" , 4 ) )
     453                 :            :         {
     454                 :          0 :             i +=4;
     455                 :          0 :             for( ; i < sql.getLength() && isWhitespace(sql[i]) ; i++ );
     456                 :          0 :             int start = i;
     457                 :          0 :             bool quote = (sql[i] == '"');
     458                 :          0 :             for( i++ ; i < sql.getLength() ; i ++ )
     459                 :            :             {
     460                 :          0 :                 if( quote && sql[i] == '"' )
     461                 :            :                 {
     462                 :          0 :                     for( i++ ; i < sql.getLength() && isWhitespace(sql[i]) ; i++ );
     463                 :          0 :                     if( '.' == sql[i] )
     464                 :            :                     {
     465                 :          0 :                         for( i++ ; i < sql.getLength() && isWhitespace(sql[i]) ; i++ );
     466                 :          0 :                         if( '"' == sql[i] )
     467                 :            :                         {
     468                 :            :                             // the second part of the table name does not use quotes
     469                 :            :                             // parse on
     470                 :          0 :                             quote = 0;
     471                 :            :                         }
     472                 :            :                     }
     473                 :            :                     else
     474                 :            :                     {
     475                 :            :                         // end quoted name, ok
     476                 :          0 :                         break;
     477                 :            :                     }
     478                 :            :                 }
     479                 :            :                 else
     480                 :            :                 {
     481                 :          0 :                     if( isWhitespace( sql[i] ) )
     482                 :            :                     {
     483                 :            :                         // found the end of an unquoted name
     484                 :          0 :                         break;
     485                 :            :                     }
     486                 :            :                 }
     487                 :            :             }
     488                 :          0 :             ret = rtl::OUString( &sql.getStr()[start], i - start ).trim();
     489                 :            : //             printf( "pq_statement: parsed table name %s from insert\n" ,
     490                 :            : //                     OUStringToOString( ret, RTL_TEXTENCODING_ASCII_US).getStr() );
     491                 :            :         }
     492                 :            :     }
     493                 :          0 :     return ret;
     494                 :            : }
     495                 :            : 
     496                 :            : 
     497                 :          0 : static bool isOperator( char c )
     498                 :            : {
     499                 :            :     bool ret;
     500                 :          0 :     switch(c)
     501                 :            :     {
     502                 :            :     case '+':
     503                 :            :     case '-':
     504                 :            :     case '*':
     505                 :            :     case '/':
     506                 :            :     case '<':
     507                 :            :     case '>':
     508                 :            :     case '=':
     509                 :            :     case '~':
     510                 :            :     case '!':
     511                 :            :     case '@':
     512                 :            :     case '#':
     513                 :            :     case '%':
     514                 :            :     case '^':
     515                 :            :     case '&':
     516                 :            :     case '|':
     517                 :            :     case '`':
     518                 :            :     case '?':
     519                 :            :     case '$':
     520                 :          0 :         ret = true;
     521                 :          0 :         break;
     522                 :            :     default:
     523                 :          0 :         ret = false;
     524                 :            :     }
     525                 :          0 :     return ret;
     526                 :            : }
     527                 :            : 
     528                 :          0 : void splitSQL( const rtl::OString & sql, OStringVector &vec )
     529                 :            : {
     530                 :          0 :     int length = sql.getLength();
     531                 :            : 
     532                 :          0 :     int i = 0;
     533                 :          0 :     bool singleQuote = false;
     534                 :          0 :     bool doubleQuote = false;
     535                 :          0 :     int start = 0;
     536                 :          0 :     for( ; i < length ; i ++ )
     537                 :            :     {
     538                 :          0 :         char c = sql[i];
     539                 :          0 :         if( doubleQuote  )
     540                 :            :         {
     541                 :          0 :             if( '"' == c )
     542                 :            :             {
     543                 :          0 :                 vec.push_back( rtl::OString( &sql.getStr()[start], i-start+1  ) );
     544                 :          0 :                 start = i + 1;
     545                 :          0 :                 doubleQuote = false;
     546                 :            :             }
     547                 :            :         }
     548                 :          0 :         else if( singleQuote )
     549                 :            :         {
     550                 :          0 :             if( '\'' == c && '\'' == sql[i+1] )
     551                 :            :             {
     552                 :            :                 // two subsequent single quotes within a quoted string
     553                 :            :                 // mean a single quote within the string
     554                 :          0 :                 i ++;
     555                 :            :             }
     556                 :          0 :             else if( '\'' == c )
     557                 :            :             {
     558                 :          0 :                 vec.push_back( rtl::OString( &sql.getStr()[start], i - start +1 ) );
     559                 :          0 :                 start = i + 1; // leave single quotes !
     560                 :          0 :                 singleQuote = false;
     561                 :            :             }
     562                 :            :         }
     563                 :            :         else
     564                 :            :         {
     565                 :          0 :             if( '"' == c )
     566                 :            :             {
     567                 :          0 :                 vec.push_back( rtl::OString( &sql.getStr()[start], i - start ) );
     568                 :          0 :                 doubleQuote = true;
     569                 :          0 :                 start = i;
     570                 :            :             }
     571                 :          0 :             else if( '\'' == c )
     572                 :            :             {
     573                 :          0 :                 vec.push_back( rtl::OString( &sql.getStr()[start], i - start ) );
     574                 :          0 :                 singleQuote = true;
     575                 :          0 :                 start = i;
     576                 :            :             }
     577                 :            :         }
     578                 :            :     }
     579                 :          0 :     if( start < i )
     580                 :          0 :         vec.push_back( rtl::OString( &sql.getStr()[start] , i - start ) );
     581                 :            : 
     582                 :            : //     for( i = 0 ; i < vec.size() ; i ++ )
     583                 :            : //         printf( "%s!" , vec[i].getStr() );
     584                 :            : //     printf( "\n" );
     585                 :            : 
     586                 :          0 : }
     587                 :            : 
     588                 :          0 : void tokenizeSQL( const rtl::OString & sql, OStringVector &vec  )
     589                 :            : {
     590                 :          0 :     int length = sql.getLength();
     591                 :            : 
     592                 :          0 :     int i = 0;
     593                 :          0 :     bool singleQuote = false;
     594                 :          0 :     bool doubleQuote = false;
     595                 :          0 :     int start = 0;
     596                 :          0 :     for( ; i < length ; i ++ )
     597                 :            :     {
     598                 :          0 :         char c = sql[i];
     599                 :          0 :         if( doubleQuote  )
     600                 :            :         {
     601                 :          0 :             if( '"' == c )
     602                 :            :             {
     603                 :          0 :                 vec.push_back( rtl::OString( &sql.getStr()[start], i-start  ) );
     604                 :          0 :                 start = i + 1;
     605                 :          0 :                 doubleQuote = false;
     606                 :            :             }
     607                 :            :         }
     608                 :          0 :         else if( singleQuote )
     609                 :            :         {
     610                 :          0 :             if( '\'' == c )
     611                 :            :             {
     612                 :          0 :                 vec.push_back( rtl::OString( &sql.getStr()[start], i - start +1 ) );
     613                 :          0 :                 start = i + 1; // leave single quotes !
     614                 :          0 :                 singleQuote = false;
     615                 :            :             }
     616                 :            :         }
     617                 :            :         else
     618                 :            :         {
     619                 :          0 :             if( '"' == c )
     620                 :            :             {
     621                 :          0 :                 doubleQuote = true;
     622                 :          0 :                 start = i +1; // skip double quotes !
     623                 :            :             }
     624                 :          0 :             else if( '\'' == c )
     625                 :            :             {
     626                 :          0 :                 singleQuote = true;
     627                 :          0 :                 start = i; // leave single quotes
     628                 :            :             }
     629                 :          0 :             else if( isWhitespace( c ) )
     630                 :            :             {
     631                 :          0 :                 if( i == start )
     632                 :          0 :                     start ++;   // skip additional whitespace
     633                 :            :                 else
     634                 :            :                 {
     635                 :          0 :                     vec.push_back( rtl::OString( &sql.getStr()[start], i - start  ) );
     636                 :          0 :                     start = i +1;
     637                 :            :                 }
     638                 :            :             }
     639                 :          0 :             else if( ',' == c || isOperator( c ) || '(' == c || ')' == c )
     640                 :            :             {
     641                 :          0 :                 if( i - start )
     642                 :          0 :                     vec.push_back( rtl::OString( &sql.getStr()[start], i - start ) );
     643                 :          0 :                 vec.push_back( rtl::OString( &sql.getStr()[i], 1 ) );
     644                 :          0 :                 start = i + 1;
     645                 :            :             }
     646                 :          0 :             else if( '.' == c )
     647                 :            :             {
     648                 :          0 :                 if( ( i > start && sql[start] >= '0' && sql[start] <= '9' ) ||
     649                 :          0 :                     ( i == start && i > 1 && isWhitespace( sql[i-1] ) ) )
     650                 :            :                 {
     651                 :            :                     // ignore, is a literal
     652                 :            :                 }
     653                 :            :                 else
     654                 :            :                 {
     655                 :          0 :                     if( i - start )
     656                 :          0 :                         vec.push_back( rtl::OString( &sql.getStr()[start], i - start ) );
     657                 :          0 :                     vec.push_back( rtl::OString( RTL_CONSTASCII_STRINGPARAM( "." ) ) );
     658                 :          0 :                     start = i + 1;
     659                 :            :                 }
     660                 :            :             }
     661                 :            :         }
     662                 :            :     }
     663                 :          0 :     if( start < i )
     664                 :          0 :         vec.push_back( rtl::OString( &sql.getStr()[start] , i - start ) );
     665                 :            : 
     666                 :            : //     for( i = 0 ; i < vec.size() ; i ++ )
     667                 :            : //         printf( "%s!" , vec[i].getStr() );
     668                 :            : //     printf( "\n" );
     669                 :          0 : }
     670                 :            : 
     671                 :            : 
     672                 :          0 : void splitConcatenatedIdentifier( const rtl::OUString & source, rtl::OUString *first, rtl::OUString *second)
     673                 :            : {
     674                 :          0 :     OStringVector vec;
     675                 :          0 :     tokenizeSQL( rtl::OUStringToOString( source, RTL_TEXTENCODING_UTF8 ), vec );
     676                 :          0 :     if( vec.size() == 3 )
     677                 :            :     {
     678                 :          0 :         *first = rtl::OStringToOUString( vec[0] , RTL_TEXTENCODING_UTF8 );
     679                 :          0 :         *second = rtl::OStringToOUString( vec[2], RTL_TEXTENCODING_UTF8 );
     680                 :          0 :     }
     681                 :          0 : }
     682                 :            : 
     683                 :            : typedef std::vector< sal_Int32 , Allocator< sal_Int32 > > IntVector;
     684                 :            : 
     685                 :            : 
     686                 :          0 : rtl::OUString array2String( const com::sun::star::uno::Sequence< Any > &seq )
     687                 :            : {
     688                 :          0 :     OUStringBuffer buf(128);
     689                 :          0 :     int len = seq.getLength();
     690                 :          0 :     buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "{" ) );
     691                 :          0 :     for( int i = 0 ; i < len ; i ++ )
     692                 :            :     {
     693                 :          0 :         OUString element;
     694                 :          0 :         seq[i] >>= element;
     695                 :            : 
     696                 :          0 :         if( i > 0 )
     697                 :          0 :             buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(",") );
     698                 :          0 :         int strLength = element.getLength();
     699                 :          0 :         buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "\"") );
     700                 :          0 :         for( int j = 0 ; j < strLength ; j ++ )
     701                 :            :         {
     702                 :          0 :             sal_Unicode c = element[j];
     703                 :          0 :             if( c == '\\' || c == '"' || c == '{' || c == '}' )
     704                 :            :             {
     705                 :          0 :                 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "\\" ) );
     706                 :            :             }
     707                 :          0 :             buf.append( c );
     708                 :            :         }
     709                 :          0 :         buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "\"" ) );
     710                 :          0 :     }
     711                 :          0 :     buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "}" ) );
     712                 :          0 :     return buf.makeStringAndClear();
     713                 :            : }
     714                 :            : 
     715                 :            : typedef
     716                 :            : std::vector
     717                 :            : <
     718                 :            :     com::sun::star::uno::Any,
     719                 :            :     Allocator< com::sun::star::uno::Any >
     720                 :            : > AnyVector;
     721                 :            : 
     722                 :          0 : com::sun::star::uno::Sequence< Any > parseArray( const rtl::OUString & str ) throw( SQLException )
     723                 :            : {
     724                 :          0 :     com::sun::star::uno::Sequence< Any > ret;
     725                 :            : 
     726                 :          0 :     int len = str.getLength();
     727                 :          0 :     bool doubleQuote = false;
     728                 :          0 :     int brackets = 0;
     729                 :          0 :     int i = 0;
     730                 :            : 
     731                 :          0 :     OUStringBuffer current;
     732                 :          0 :     AnyVector elements;
     733                 :          0 :     bool doubleQuotedValue = false;
     734                 :          0 :     while( i < len )
     735                 :            :     {
     736                 :          0 :         sal_Unicode c = str[i];
     737                 :          0 :         sal_Unicode cnext = str[i+1];
     738                 :          0 :         if( doubleQuote )
     739                 :            :         {
     740                 :          0 :             if( '\\' == c )
     741                 :            :             {
     742                 :          0 :                 i ++;
     743                 :          0 :                 current.append( cnext );
     744                 :            :             }
     745                 :          0 :             else if( '"' == c )
     746                 :            :             {
     747                 :          0 :                 doubleQuote = false;
     748                 :          0 :                 doubleQuotedValue = true; // signal, that there was an empty element
     749                 :            :             }
     750                 :            :             else
     751                 :            :             {
     752                 :          0 :                 current.append( c );
     753                 :            :             }
     754                 :            :         }
     755                 :          0 :         else if ( '{' == c )
     756                 :            :         {
     757                 :          0 :             brackets ++;
     758                 :            :         }
     759                 :          0 :         else if( '}' == c )
     760                 :            :         {
     761                 :          0 :             brackets --;
     762                 :          0 :             if( brackets < 0 )
     763                 :            :             {
     764                 :            : 
     765                 :          0 :                 OUStringBuffer buf;
     766                 :          0 :                 buf.appendAscii( "error during array parsing, didn't expect a } at position " );
     767                 :          0 :                 buf.append( (sal_Int32) i );
     768                 :          0 :                 buf.appendAscii( " ('" );
     769                 :          0 :                 buf.append( str );
     770                 :          0 :                 buf.appendAscii( "')" );
     771                 :            :                 throw SQLException(
     772                 :            :                     buf.makeStringAndClear(),
     773                 :          0 :                     Reference< XInterface > (), rtl::OUString(), 1, Any() );
     774                 :            :             }
     775                 :          0 :             if( brackets == 0 )
     776                 :            :             {
     777                 :          0 :                 if( current.getLength() > 0 || doubleQuotedValue )
     778                 :          0 :                     elements.push_back( makeAny( current.makeStringAndClear() ) );
     779                 :            :             }
     780                 :            :             else
     781                 :            :             {
     782                 :          0 :                 current.append( c );
     783                 :            :             }
     784                 :            :         }
     785                 :          0 :         else if( '"' == c )
     786                 :            :         {
     787                 :            : //                 if( current.getLength() != 0 )
     788                 :            : //                 {
     789                 :            : //                     OUStringBuffer buf;
     790                 :            : //                     buf.appendAscii( "error during array parsing, didn't expect a \" at position " );
     791                 :            : //                     buf.append( i );
     792                 :            : //                     buf.append( " ('" );
     793                 :            : //                     buf.append( str );
     794                 :            : //                     buf.append( "')" );
     795                 :            : //                     throw SDBCException(
     796                 :            : //                         buf.makeStringAndClear(),
     797                 :            : //                         Reference< XInterface > (), 1, Any() );
     798                 :            : //                 }
     799                 :            : //                 else
     800                 :            : //                 {
     801                 :          0 :             doubleQuote = true;
     802                 :            : //                 }
     803                 :            :         }
     804                 :          0 :         else if( ',' == c && brackets == 1)
     805                 :            :         {
     806                 :          0 :             doubleQuotedValue = false;
     807                 :          0 :             elements.push_back( makeAny( current.makeStringAndClear() ) );
     808                 :            :         }
     809                 :          0 :         else if( isWhitespace( c ) )
     810                 :            :         {
     811                 :            :             // ignore whitespace without quotes
     812                 :            :         }
     813                 :            :         else
     814                 :            :         {
     815                 :          0 :             current.append( c );
     816                 :            :         }
     817                 :          0 :         i++;
     818                 :            :     }
     819                 :          0 :     return sequence_of_vector(elements);
     820                 :            : }
     821                 :            : 
     822                 :          0 : com::sun::star::uno::Sequence< sal_Int32 > parseIntArray( const ::rtl::OUString & str )
     823                 :            : {
     824                 :          0 :     sal_Int32 start = 0;
     825                 :          0 :     IntVector vec;
     826                 :            : //     printf( ">%s<\n" , OUStringToOString( str, RTL_TEXTENCODING_UTF8 ).getStr() );
     827                 :          0 :     for( sal_Int32 i = str.indexOf( ' ' ) ; i != -1 ; i = str.indexOf( ' ', start) )
     828                 :            :     {
     829                 :          0 :         vec.push_back( (sal_Int32)rtl_ustr_toInt32( &str.pData->buffer[start], 10 ) );
     830                 :            : //         printf( "found %d\n" , rtl_ustr_toInt32( &str.pData->buffer[start], 10 ));
     831                 :          0 :         start = i + 1;
     832                 :            :     }
     833                 :          0 :     vec.push_back( (sal_Int32)rtl_ustr_toInt32( &str.pData->buffer[start], 10 ) );
     834                 :            : //     printf( "found %d\n" , rtl_ustr_toInt32( &str.pData->buffer[start], 10 ));
     835                 :          0 :     return sequence_of_vector(vec);
     836                 :            : }
     837                 :            : 
     838                 :          0 : void fillAttnum2attnameMap(
     839                 :            :     Int2StringMap &map,
     840                 :            :     const Reference< com::sun::star::sdbc::XConnection > &conn,
     841                 :            :     const rtl::OUString &schema,
     842                 :            :     const rtl::OUString &table )
     843                 :            : {
     844                 :          0 :     Reference< XPreparedStatement > prep = conn->prepareStatement(
     845                 :            :         ASCII_STR( "SELECT attname,attnum "
     846                 :            :                    "FROM pg_attribute "
     847                 :            :                          "INNER JOIN pg_class ON attrelid = pg_class.oid "
     848                 :            :                          "INNER JOIN pg_namespace ON pg_class.relnamespace = pg_namespace.oid "
     849                 :          0 :                    "WHERE relname=? AND nspname=?" ) );
     850                 :            : 
     851                 :          0 :     Reference< XParameters > paras( prep, UNO_QUERY_THROW );
     852                 :          0 :     paras->setString( 1 , table );
     853                 :          0 :     paras->setString( 2 , schema );
     854                 :          0 :     Reference< XResultSet > rs = prep->executeQuery();
     855                 :            : 
     856                 :          0 :     Reference< XRow > xRow( rs , UNO_QUERY_THROW );
     857                 :          0 :     while( rs->next() )
     858                 :            :     {
     859                 :          0 :         map[ xRow->getInt(2) ] = xRow->getString(1);
     860                 :          0 :     }
     861                 :          0 : }
     862                 :            : 
     863                 :          0 : ::rtl::OString extractSingleTableFromSelect( const OStringVector &vec )
     864                 :            : {
     865                 :          0 :     rtl::OString ret;
     866                 :            : 
     867                 :          0 :     if( 0 == rtl_str_shortenedCompareIgnoreAsciiCase_WithLength(
     868                 :          0 :             vec[0].pData->buffer, vec[0].pData->length, "select" , 6 , 6 ) )
     869                 :            :     {
     870                 :          0 :         size_t token = 0;
     871                 :            : 
     872                 :          0 :         for( token = 1; token < vec.size() ; token ++ )
     873                 :            :         {
     874                 :          0 :             if( 0 == rtl_str_shortenedCompareIgnoreAsciiCase_WithLength(
     875                 :          0 :                     vec[token].getStr(), vec[token].getLength(), "from" , 4 , 4 ) )
     876                 :            :             {
     877                 :            :                 // found from
     878                 :          0 :                 break;
     879                 :            :             }
     880                 :            :         }
     881                 :          0 :         token ++;
     882                 :            : 
     883                 :          0 :         if( token < vec.size() && 0 == rtl_str_shortenedCompareIgnoreAsciiCase_WithLength(
     884                 :          0 :                 vec[token].pData->buffer, vec[token].pData->length, "only " , 4 , 4 ) )
     885                 :            :         {
     886                 :          0 :             token ++;
     887                 :            :         }
     888                 :            : 
     889                 :          0 :         if( token < vec.size() && rtl_str_compare_WithLength(
     890                 :          0 :                 vec[token].getStr(), vec[token].getLength(),
     891                 :          0 :                 RTL_CONSTASCII_STRINGPARAM("(") ) )
     892                 :            :         {
     893                 :            :             // it is a table or a function name
     894                 :          0 :             rtl::OStringBuffer buf(128);
     895                 :          0 :             if( '"' == vec[token][0] )
     896                 :          0 :                 buf.append( &(vec[token].getStr()[1]) , vec[token].getLength() -2 );
     897                 :            :             else
     898                 :          0 :                 buf.append( vec[token] );
     899                 :          0 :             token ++;
     900                 :            : 
     901                 :          0 :             if( token < vec.size() )
     902                 :            :             {
     903                 :          0 :                 if( rtl_str_compare_WithLength(
     904                 :          0 :                         vec[token].getStr(), vec[token].getLength(),
     905                 :          0 :                         RTL_CONSTASCII_STRINGPARAM( "." ) ) == 0 )
     906                 :            :                 {
     907                 :          0 :                     buf.append( vec[token] );
     908                 :          0 :                     token ++;
     909                 :          0 :                     if( token < vec.size() )
     910                 :            :                     {
     911                 :          0 :                         if( '"' == vec[token][0] )
     912                 :          0 :                             buf.append( &(vec[token].getStr()[1]) , vec[token].getLength() -2 );
     913                 :            :                         else
     914                 :          0 :                             buf.append( vec[token] );
     915                 :          0 :                         token ++;
     916                 :            :                     }
     917                 :            :                 }
     918                 :            :             }
     919                 :            : 
     920                 :          0 :             ret = buf.makeStringAndClear();
     921                 :            :             // now got my table candidate
     922                 :            : 
     923                 :          0 :             if( token < vec.size() && rtl_str_compare_WithLength(
     924                 :          0 :                     vec[token].getStr(), vec[token].getLength(),
     925                 :          0 :                     RTL_CONSTASCII_STRINGPARAM( "(" ) ) == 0 )
     926                 :            :             {
     927                 :            :                 // whoops, it is a function
     928                 :          0 :                 ret = rtl::OString();
     929                 :            :             }
     930                 :            :             else
     931                 :            :             {
     932                 :          0 :                 if( token < vec.size() )
     933                 :            :                 {
     934                 :          0 :                     if( 0 == rtl_str_shortenedCompareIgnoreAsciiCase_WithLength(
     935                 :          0 :                             vec[token].pData->buffer, vec[token].pData->length, "as" , 2, 2 ) )
     936                 :            :                     {
     937                 :          0 :                         token += 2; // skip alias
     938                 :            :                     }
     939                 :            :                 }
     940                 :            : 
     941                 :          0 :                 if( token < vec.size() )
     942                 :            :                 {
     943                 :          0 :                     if( rtl_str_compare_WithLength(
     944                 :          0 :                             vec[token].getStr(), vec[token].getLength(),
     945                 :          0 :                             RTL_CONSTASCII_STRINGPARAM( "," ) ) == 0 )
     946                 :            :                     {
     947                 :            :                         // whoops, multiple tables are used
     948                 :          0 :                         ret = rtl::OString();
     949                 :            :                     }
     950                 :            :                     else
     951                 :            :                     {
     952                 :            :                         static const char * forbiddenKeywords[] =
     953                 :            :                             { "join", "natural", "outer", "inner", "left", "right", "full" , 0 };
     954                 :          0 :                         for( int i = 0 ; forbiddenKeywords[i] ; i ++ )
     955                 :            :                         {
     956                 :          0 :                             if( 0 == rtl_str_shortenedCompareIgnoreAsciiCase_WithLength(
     957                 :          0 :                                  vec[token].pData->buffer, vec[token].pData->length,
     958                 :          0 :                                  forbiddenKeywords[i], strlen(forbiddenKeywords[i]),
     959                 :          0 :                                  strlen(forbiddenKeywords[i]) ) )
     960                 :            :                             {
     961                 :            :                                 // whoops, it is a join
     962                 :          0 :                                 ret = rtl::OString();
     963                 :            :                             }
     964                 :            :                         }
     965                 :            :                     }
     966                 :            :                 }
     967                 :          0 :             }
     968                 :            :         }
     969                 :            :     }
     970                 :          0 :     return ret;
     971                 :            : 
     972                 :            : }
     973                 :            : 
     974                 :          0 : com::sun::star::uno::Sequence< sal_Int32 > string2intarray( const ::rtl::OUString & str )
     975                 :            : {
     976                 :          0 :     com::sun::star::uno::Sequence< sal_Int32 > ret;
     977                 :          0 :     const sal_Int32 strlen = str.getLength();
     978                 :          0 :     if( str.getLength() > 1 )
     979                 :            :     {
     980                 :          0 :         sal_Int32 start = 0;
     981                 :          0 :         while ( iswspace( str.iterateCodePoints(&start) ) )
     982                 :          0 :             if ( start == strlen)
     983                 :            :                 return ret;
     984                 :          0 :         if ( str.iterateCodePoints(&start) != L'{' )
     985                 :            :             return ret;
     986                 :          0 :         while ( iswspace( str.iterateCodePoints(&start) ) )
     987                 :          0 :             if ( start == strlen)
     988                 :            :                 return ret;
     989                 :          0 :         if ( str.iterateCodePoints(&start, 0) == L'}' )
     990                 :            :             return ret;
     991                 :            : 
     992                 :          0 :         std::vector< sal_Int32, Allocator< sal_Int32 > > vec;
     993                 :          0 :         do
     994                 :            :         {
     995                 :          0 :             ::rtl::OUString digits;
     996                 :            :             sal_Int32 c;
     997                 :          0 :             while ( isdigit( c = str.iterateCodePoints(&start) ) )
     998                 :            :             {
     999                 :          0 :                 if ( start == strlen)
    1000                 :            :                     return ret;
    1001                 :          0 :                 digits += OUString(c);
    1002                 :            :             }
    1003                 :          0 :             vec.push_back( digits.toInt32() );
    1004                 :          0 :             while ( iswspace( str.iterateCodePoints(&start) ) )
    1005                 :          0 :                 if ( start == strlen)
    1006                 :            :                     return ret;
    1007                 :          0 :             if ( str.iterateCodePoints(&start, 0) == L'}' )
    1008                 :            :                 break;
    1009                 :          0 :             if ( str.iterateCodePoints(&start) != L',' )
    1010                 :            :                 return ret;
    1011                 :          0 :             if ( start == strlen)
    1012                 :          0 :                 return ret;
    1013                 :            :         } while( true );
    1014                 :            :         // vec is guaranteed non-empty
    1015                 :          0 :         ret = com::sun::star::uno::Sequence< sal_Int32 > ( &vec[0] , vec.size() );
    1016                 :            :     }
    1017                 :          0 :     return ret;
    1018                 :            : }
    1019                 :            : 
    1020                 :            : 
    1021                 :          0 : Sequence< rtl::OUString > convertMappedIntArray2StringArray(
    1022                 :            :     const Int2StringMap &map, const Sequence< sal_Int32 > &intArray )
    1023                 :            : {
    1024                 :          0 :     Sequence< ::rtl::OUString > ret( intArray.getLength() );
    1025                 :          0 :     for( int i = 0; i < intArray.getLength() ; i ++ )
    1026                 :            :     {
    1027                 :          0 :         Int2StringMap::const_iterator ii = map.find( intArray[i] );
    1028                 :          0 :         if( ii != map.end() )
    1029                 :          0 :             ret[i] = ii->second;
    1030                 :            :     }
    1031                 :          0 :     return ret;
    1032                 :            : }
    1033                 :            : 
    1034                 :            : 
    1035                 :          0 : ::rtl::OUString sqltype2string( const Reference< XPropertySet > & desc )
    1036                 :            : {
    1037                 :          0 :     OUStringBuffer typeName;
    1038                 :          0 :     typeName.append( extractStringProperty( desc, getStatics().TYPE_NAME ) );
    1039                 :          0 :     sal_Int32 precision = extractIntProperty( desc, getStatics().PRECISION );
    1040                 :            : 
    1041                 :          0 :     if( precision )
    1042                 :            :     {
    1043                 :          0 :         switch( extractIntProperty( desc, getStatics().TYPE ) )
    1044                 :            :         {
    1045                 :            :         case com::sun::star::sdbc::DataType::VARBINARY:
    1046                 :            :         case com::sun::star::sdbc::DataType::VARCHAR:
    1047                 :            :         case com::sun::star::sdbc::DataType::CHAR:
    1048                 :            :         {
    1049                 :          0 :             typeName.appendAscii( RTL_CONSTASCII_STRINGPARAM( "(" ) );
    1050                 :          0 :             typeName.append( precision );
    1051                 :          0 :             typeName.appendAscii( RTL_CONSTASCII_STRINGPARAM( ")" ) );
    1052                 :          0 :             break;
    1053                 :            :         }
    1054                 :            :         case com::sun::star::sdbc::DataType::DECIMAL:
    1055                 :            :         case com::sun::star::sdbc::DataType::NUMERIC:
    1056                 :            :         {
    1057                 :          0 :             typeName.appendAscii( RTL_CONSTASCII_STRINGPARAM( "(" ) );
    1058                 :          0 :             typeName.append( precision );
    1059                 :          0 :             typeName.appendAscii( RTL_CONSTASCII_STRINGPARAM( "," ) );
    1060                 :          0 :             typeName.append( extractIntProperty( desc, getStatics().SCALE ) );
    1061                 :          0 :             typeName.appendAscii( RTL_CONSTASCII_STRINGPARAM( ")" ) );
    1062                 :          0 :             break;
    1063                 :            :         }
    1064                 :            :         default:
    1065                 :            :             ((void)0);
    1066                 :            :         }
    1067                 :            :     }
    1068                 :          0 :     return typeName.makeStringAndClear();
    1069                 :            : }
    1070                 :            : 
    1071                 :            : 
    1072                 :            : 
    1073                 :            : 
    1074                 :          0 : static void keyType2String( OUStringBuffer & buf, sal_Int32 keyType )
    1075                 :            : {
    1076                 :          0 :     if( com::sun::star::sdbc::KeyRule::CASCADE == keyType )
    1077                 :            :     {
    1078                 :          0 :         buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "CASCADE " ) );
    1079                 :            :     }
    1080                 :          0 :     else if( com::sun::star::sdbc::KeyRule::RESTRICT  == keyType )
    1081                 :            :     {
    1082                 :          0 :         buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "RESTRICT " ) );
    1083                 :            :     }
    1084                 :          0 :     else if( com::sun::star::sdbc::KeyRule::SET_DEFAULT  == keyType )
    1085                 :            :     {
    1086                 :          0 :         buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "SET DEFAULT " ) );
    1087                 :            :     }
    1088                 :          0 :     else if( com::sun::star::sdbc::KeyRule::SET_NULL  == keyType )
    1089                 :            :     {
    1090                 :          0 :         buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "SET NULL " ) );
    1091                 :            :     }
    1092                 :            :     else //if( com::sun::star::sdbc::KeyRule::NO_ACTION == keyType )
    1093                 :            :     {
    1094                 :          0 :         buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "NO ACTION " ) );
    1095                 :            :     }
    1096                 :          0 : }
    1097                 :            : 
    1098                 :          0 : void bufferKey2TableConstraint(
    1099                 :            :     OUStringBuffer &buf, const Reference< XPropertySet > &key, ConnectionSettings *settings )
    1100                 :            : {
    1101                 :          0 :     Statics &st = getStatics();
    1102                 :          0 :     sal_Int32 type = extractIntProperty( key, st.TYPE );
    1103                 :          0 :     OUString referencedTable = extractStringProperty( key, st.REFERENCED_TABLE );
    1104                 :          0 :     sal_Int32 updateRule = extractIntProperty( key, st.UPDATE_RULE );
    1105                 :          0 :     sal_Int32 deleteRule = extractIntProperty( key, st.DELETE_RULE );
    1106                 :          0 :     bool foreign = false;
    1107                 :          0 :     if( type == com::sun::star::sdbcx::KeyType::UNIQUE )
    1108                 :            :     {
    1109                 :          0 :         buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "UNIQUE( " ) );
    1110                 :            :     }
    1111                 :          0 :     else if( type == com::sun::star::sdbcx::KeyType::PRIMARY )
    1112                 :            :     {
    1113                 :          0 :         buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "PRIMARY KEY( " ) );
    1114                 :            :     }
    1115                 :          0 :     else if( type == com::sun::star::sdbcx::KeyType::FOREIGN )
    1116                 :            :     {
    1117                 :          0 :         foreign = true;
    1118                 :          0 :         buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "FOREIGN KEY( " ) );
    1119                 :            :     }
    1120                 :            : 
    1121                 :          0 :     Reference< XColumnsSupplier > columns( key, UNO_QUERY );
    1122                 :          0 :     if( columns.is() )
    1123                 :            :     {
    1124                 :          0 :         Reference< XEnumerationAccess > colEnumAccess( columns->getColumns(), UNO_QUERY );
    1125                 :          0 :         if( colEnumAccess.is() )
    1126                 :            :         {
    1127                 :          0 :             Reference< XEnumeration > colEnum = colEnumAccess->createEnumeration();
    1128                 :          0 :             bool first = true;
    1129                 :          0 :             while(colEnum.is() && colEnum->hasMoreElements() )
    1130                 :            :             {
    1131                 :          0 :                 if( first )
    1132                 :            :                 {
    1133                 :          0 :                     first = false;
    1134                 :            :                 }
    1135                 :            :                 else
    1136                 :            :                 {
    1137                 :          0 :                     buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( ", " ) );
    1138                 :            :                 }
    1139                 :          0 :                 Reference< XPropertySet > keyColumn( colEnum->nextElement(), UNO_QUERY_THROW );
    1140                 :          0 :                 bufferQuoteIdentifier(buf, extractStringProperty( keyColumn, st.NAME ), settings );
    1141                 :          0 :             }
    1142                 :          0 :         }
    1143                 :            :     }
    1144                 :          0 :     buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( ") " ));
    1145                 :            : 
    1146                 :          0 :     if( foreign )
    1147                 :            :     {
    1148                 :          0 :         buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "REFERENCES " ) );
    1149                 :          0 :         OUString schema;
    1150                 :          0 :         OUString tableName;
    1151                 :          0 :         splitConcatenatedIdentifier( referencedTable, &schema, &tableName );
    1152                 :          0 :         bufferQuoteQualifiedIdentifier(buf , schema, tableName, settings );
    1153                 :          0 :         if(columns.is() )
    1154                 :            :         {
    1155                 :          0 :             Reference< XEnumerationAccess > colEnumAccess( columns->getColumns(), UNO_QUERY);
    1156                 :          0 :             if( colEnumAccess.is() )
    1157                 :            :             {
    1158                 :          0 :                 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( " (" ) );
    1159                 :          0 :                 Reference< XEnumeration > colEnum(colEnumAccess->createEnumeration());
    1160                 :          0 :                 bool first = true;
    1161                 :          0 :                 while(colEnum.is() && colEnum->hasMoreElements() )
    1162                 :            :                 {
    1163                 :          0 :                     if( first )
    1164                 :            :                     {
    1165                 :          0 :                         first = false;
    1166                 :            :                     }
    1167                 :            :                     else
    1168                 :            :                     {
    1169                 :          0 :                         buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( ", " ) );
    1170                 :            :                     }
    1171                 :          0 :                     Reference< XPropertySet > keyColumn( colEnum->nextElement(), UNO_QUERY_THROW );
    1172                 :            :                     bufferQuoteIdentifier(
    1173                 :          0 :                                           buf, extractStringProperty( keyColumn, st.RELATED_COLUMN ), settings );
    1174                 :          0 :                 }
    1175                 :          0 :                 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( ") " ) );
    1176                 :          0 :             }
    1177                 :            :         }
    1178                 :            : 
    1179                 :          0 :         buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "ON DELETE " ) );
    1180                 :          0 :         keyType2String( buf, deleteRule );
    1181                 :          0 :         buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( " ON UPDATE " ) );
    1182                 :          0 :         keyType2String( buf, updateRule );
    1183                 :          0 :     }
    1184                 :            : 
    1185                 :          0 : }
    1186                 :            : 
    1187                 :          0 : static bool equalsIgnoreCase( const rtl::OString & str, const char *str2, int length2 )
    1188                 :            : {
    1189                 :            :     return 0 == rtl_str_compareIgnoreAsciiCase_WithLength(
    1190                 :          0 :         str.pData->buffer, str.pData->length, str2, length2 );
    1191                 :            : }
    1192                 :            : 
    1193                 :          0 : void extractNameValuePairsFromInsert( String2StringMap & map, const rtl::OString & lastQuery )
    1194                 :            : {
    1195                 :          0 :     OStringVector vec;
    1196                 :          0 :     tokenizeSQL( lastQuery, vec  );
    1197                 :            : 
    1198                 :          0 :     int nSize = vec.size();
    1199                 :            : //     printf( "1 %d\n", nSize );
    1200                 :          0 :     if( nSize > 6  &&
    1201                 :          0 :         equalsIgnoreCase( vec[0] , RTL_CONSTASCII_STRINGPARAM( "insert" ) ) &&
    1202                 :          0 :         equalsIgnoreCase( vec[1] , RTL_CONSTASCII_STRINGPARAM( "into" ) ) )
    1203                 :            :     {
    1204                 :          0 :         int n = 2;
    1205                 :            : 
    1206                 :            : //         printf( "1a\n" );
    1207                 :            :         // extract table name
    1208                 :          0 :         rtl::OString tableName;
    1209                 :          0 :         if( equalsIgnoreCase( vec[n+1], RTL_CONSTASCII_STRINGPARAM( "." ) ) )
    1210                 :            :         {
    1211                 :          0 :             tableName = vec[n];
    1212                 :          0 :             tableName += vec[n+1];
    1213                 :          0 :             tableName += vec[n+2];
    1214                 :          0 :             n +=2;
    1215                 :            :         }
    1216                 :            :         else
    1217                 :            :         {
    1218                 :          0 :             tableName = vec[n];
    1219                 :            :         }
    1220                 :            : 
    1221                 :          0 :         OStringVector names;
    1222                 :          0 :         n ++;
    1223                 :          0 :         if( equalsIgnoreCase( vec[n], RTL_CONSTASCII_STRINGPARAM( "(" ) ) )
    1224                 :            :         {
    1225                 :            : //             printf( "2\n" );
    1226                 :            :             // extract names
    1227                 :          0 :             n++;
    1228                 :          0 :             while( nSize > n && ! equalsIgnoreCase(vec[n] , RTL_CONSTASCII_STRINGPARAM( ")" ) ) )
    1229                 :            :             {
    1230                 :          0 :                 names.push_back( vec[n] );
    1231                 :          0 :                 if( nSize > n+1 && equalsIgnoreCase( vec[n+1] , RTL_CONSTASCII_STRINGPARAM( "," ) ) )
    1232                 :            :                 {
    1233                 :          0 :                     n ++;
    1234                 :            :                 }
    1235                 :          0 :                 n++;
    1236                 :            :             }
    1237                 :          0 :             n++;
    1238                 :            : 
    1239                 :            :             // now read the values
    1240                 :          0 :             if( nSize > n +1 && equalsIgnoreCase( vec[n], RTL_CONSTASCII_STRINGPARAM("VALUES") ) &&
    1241                 :          0 :                 equalsIgnoreCase(vec[n+1], RTL_CONSTASCII_STRINGPARAM( "(" ) ) )
    1242                 :            :             {
    1243                 :          0 :                 n +=2;
    1244                 :            : //                 printf( "3\n" );
    1245                 :          0 :                 for ( OStringVector::size_type i = 0 ; i < names.size() && nSize > n ; i ++ )
    1246                 :            :                 {
    1247                 :          0 :                     map[names[i]] = vec[n];
    1248                 :          0 :                     if( nSize > n+1 && equalsIgnoreCase( vec[n+1] , RTL_CONSTASCII_STRINGPARAM(",") ) )
    1249                 :            :                     {
    1250                 :          0 :                         n ++;
    1251                 :            :                     }
    1252                 :          0 :                     n++;
    1253                 :            :                 }
    1254                 :            :             }
    1255                 :          0 :         }
    1256                 :          0 :     }
    1257                 :          0 : }
    1258                 :            : 
    1259                 :          0 : rtl::OUString querySingleValue(
    1260                 :            :     const com::sun::star::uno::Reference< com::sun::star::sdbc::XConnection > &connection,
    1261                 :            :     const rtl::OUString &query )
    1262                 :            : {
    1263                 :          0 :     OUString ret;
    1264                 :          0 :     Reference< XStatement > stmt = connection->createStatement();
    1265                 :          0 :     DisposeGuard guard( stmt );
    1266                 :          0 :     Reference< XResultSet > rs = stmt->executeQuery( query );
    1267                 :          0 :     Reference< XRow > xRow( rs, UNO_QUERY );
    1268                 :          0 :     if( rs->next() )
    1269                 :          0 :         ret = xRow->getString( 1 );
    1270                 :          0 :     return ret;
    1271                 :            : }
    1272                 :            : 
    1273                 :            : 
    1274                 :            : // copied from connectivity/source/dbtools, can't use the function directly
    1275                 :          0 : bool implSetObject(     const Reference< XParameters >& _rxParameters,
    1276                 :            :                         const sal_Int32 _nColumnIndex, const Any& _rValue)
    1277                 :            : {
    1278                 :          0 :     sal_Bool bSuccessfullyReRouted = sal_True;
    1279                 :          0 :     switch (_rValue.getValueTypeClass())
    1280                 :            :     {
    1281                 :            :         case typelib_TypeClass_HYPER:
    1282                 :            :         {
    1283                 :          0 :             sal_Int64 nValue = 0;
    1284                 :          0 :             _rxParameters->setLong( _nColumnIndex, nValue );
    1285                 :            :         }
    1286                 :          0 :         break;
    1287                 :            : 
    1288                 :            :         case typelib_TypeClass_VOID:
    1289                 :          0 :             _rxParameters->setNull(_nColumnIndex,com::sun::star::sdbc::DataType::VARCHAR);
    1290                 :          0 :             break;
    1291                 :            : 
    1292                 :            :         case typelib_TypeClass_STRING:
    1293                 :          0 :             _rxParameters->setString(_nColumnIndex, *(rtl::OUString*)_rValue.getValue());
    1294                 :          0 :             break;
    1295                 :            : 
    1296                 :            :         case typelib_TypeClass_BOOLEAN:
    1297                 :          0 :             _rxParameters->setBoolean(_nColumnIndex, *(sal_Bool *)_rValue.getValue());
    1298                 :          0 :             break;
    1299                 :            : 
    1300                 :            :         case typelib_TypeClass_BYTE:
    1301                 :          0 :             _rxParameters->setByte(_nColumnIndex, *(sal_Int8 *)_rValue.getValue());
    1302                 :          0 :             break;
    1303                 :            : 
    1304                 :            :         case typelib_TypeClass_UNSIGNED_SHORT:
    1305                 :            :         case typelib_TypeClass_SHORT:
    1306                 :          0 :             _rxParameters->setShort(_nColumnIndex, *(sal_Int16*)_rValue.getValue());
    1307                 :          0 :             break;
    1308                 :            : 
    1309                 :            :         case typelib_TypeClass_CHAR:
    1310                 :          0 :             _rxParameters->setString(_nColumnIndex, ::rtl::OUString((sal_Unicode *)_rValue.getValue(),1));
    1311                 :          0 :             break;
    1312                 :            : 
    1313                 :            :         case typelib_TypeClass_UNSIGNED_LONG:
    1314                 :            :         case typelib_TypeClass_LONG:
    1315                 :          0 :             _rxParameters->setInt(_nColumnIndex, *(sal_Int32*)_rValue.getValue());
    1316                 :          0 :             break;
    1317                 :            : 
    1318                 :            :         case typelib_TypeClass_FLOAT:
    1319                 :          0 :             _rxParameters->setFloat(_nColumnIndex, *(float*)_rValue.getValue());
    1320                 :          0 :             break;
    1321                 :            : 
    1322                 :            :         case typelib_TypeClass_DOUBLE:
    1323                 :          0 :             _rxParameters->setDouble(_nColumnIndex, *(double*)_rValue.getValue());
    1324                 :          0 :             break;
    1325                 :            : 
    1326                 :            :         case typelib_TypeClass_SEQUENCE:
    1327                 :          0 :             if (_rValue.getValueType() == ::getCppuType((const Sequence< sal_Int8 > *)0))
    1328                 :            :             {
    1329                 :          0 :                 _rxParameters->setBytes(_nColumnIndex, *(Sequence<sal_Int8>*)_rValue.getValue());
    1330                 :            :             }
    1331                 :            :             else
    1332                 :          0 :                 bSuccessfullyReRouted = sal_False;
    1333                 :          0 :             break;
    1334                 :            :         case typelib_TypeClass_STRUCT:
    1335                 :          0 :             if (_rValue.getValueType() == ::getCppuType((const com::sun::star::util::DateTime*)0))
    1336                 :          0 :                 _rxParameters->setTimestamp(_nColumnIndex, *(com::sun::star::util::DateTime*)_rValue.getValue());
    1337                 :          0 :             else if (_rValue.getValueType() == ::getCppuType((const com::sun::star::util::Date*)0))
    1338                 :          0 :                 _rxParameters->setDate(_nColumnIndex, *(com::sun::star::util::Date*)_rValue.getValue());
    1339                 :          0 :             else if (_rValue.getValueType() == ::getCppuType((const com::sun::star::util::Time*)0))
    1340                 :          0 :                 _rxParameters->setTime(_nColumnIndex, *(com::sun::star::util::Time*)_rValue.getValue());
    1341                 :            :             else
    1342                 :          0 :                 bSuccessfullyReRouted = sal_False;
    1343                 :          0 :             break;
    1344                 :            : 
    1345                 :            :         case typelib_TypeClass_INTERFACE:
    1346                 :            :         {
    1347                 :          0 :             Reference< com::sun::star::io::XInputStream >  xStream;
    1348                 :          0 :             if (_rValue >>= xStream)
    1349                 :            :             {
    1350                 :          0 :                 _rValue >>= xStream;
    1351                 :          0 :                 _rxParameters->setBinaryStream(_nColumnIndex, xStream, xStream->available());
    1352                 :            :                 break;
    1353                 :          0 :             }
    1354                 :            :         }
    1355                 :            :             // run through
    1356                 :            :         default:
    1357                 :          0 :             bSuccessfullyReRouted = sal_False;
    1358                 :            : 
    1359                 :            :     }
    1360                 :            : 
    1361                 :          0 :     return bSuccessfullyReRouted;
    1362                 :            : }
    1363                 :            : 
    1364                 :            : }

Generated by: LCOV version 1.10