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 : : }
|