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

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*************************************************************************
       3             :  *
       4             :  *  Effective License of whole file:
       5             :  *
       6             :  *    This library is free software; you can redistribute it and/or
       7             :  *    modify it under the terms of the GNU Lesser General Public
       8             :  *    License version 2.1, as published by the Free Software Foundation.
       9             :  *
      10             :  *    This library is distributed in the hope that it will be useful,
      11             :  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
      12             :  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13             :  *    Lesser General Public License for more details.
      14             :  *
      15             :  *    You should have received a copy of the GNU Lesser General Public
      16             :  *    License along with this library; if not, write to the Free Software
      17             :  *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
      18             :  *    MA  02111-1307  USA
      19             :  *
      20             :  *  Parts "Copyright by Sun Microsystems, Inc" prior to August 2011:
      21             :  *
      22             :  *    The Contents of this file are made available subject to the terms of
      23             :  *    the GNU Lesser General Public License Version 2.1
      24             :  *
      25             :  *    Copyright: 2000 by Sun Microsystems, Inc.
      26             :  *
      27             :  *    Contributor(s): Joerg Budischewski
      28             :  *
      29             :  *  All parts contributed on or after August 2011:
      30             :  *
      31             :  *    Version: MPL 1.1 / GPLv3+ / LGPLv2.1+
      32             :  *
      33             :  *    The contents of this file are subject to the Mozilla Public License Version
      34             :  *    1.1 (the "License"); you may not use this file except in compliance with
      35             :  *    the License or as specified alternatively below. You may obtain a copy of
      36             :  *    the License at http://www.mozilla.org/MPL/
      37             :  *
      38             :  *    Software distributed under the License is distributed on an "AS IS" basis,
      39             :  *    WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      40             :  *    for the specific language governing rights and limitations under the
      41             :  *    License.
      42             :  *
      43             :  *    Major Contributor(s):
      44             :  *    [ Copyright (C) 2011 Lionel Elie Mamane <lionel@mamane.lu> ]
      45             :  *
      46             :  *    All Rights Reserved.
      47             :  *
      48             :  *    For minor contributions see the git repository.
      49             :  *
      50             :  *    Alternatively, the contents of this file may be used under the terms of
      51             :  *    either the GNU General Public License Version 3 or later (the "GPLv3+"), or
      52             :  *    the GNU Lesser General Public License Version 2.1 or later (the "LGPLv2.1+"),
      53             :  *    in which case the provisions of the GPLv3+ or the LGPLv2.1+ are applicable
      54             :  *    instead of those above.
      55             :  *
      56             :  ************************************************************************/
      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