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