merge the formfield patch from ooo-build
[ooovba.git] / connectivity / source / drivers / postgresql / pq_tools.cxx
blobc2099b487d49be75dc7770fbcc361b89e804d946
1 #include <rtl/strbuf.hxx>
2 #include <rtl/ustrbuf.hxx>
4 #include <com/sun/star/beans/XPropertySet.hpp>
5 #include <com/sun/star/lang/XComponent.hpp>
7 #include <com/sun/star/sdbc/XRow.hpp>
8 #include <com/sun/star/sdbc/XParameters.hpp>
9 #include <com/sun/star/sdbc/DataType.hpp>
10 #include <com/sun/star/sdbc/KeyRule.hpp>
11 #include <com/sun/star/sdbcx/KeyType.hpp>
12 #include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
14 #include "pq_xcontainer.hxx"
15 #include "pq_tools.hxx"
16 #include "pq_statics.hxx"
18 #include <libpq-fe.h>
19 #include <string.h>
21 using rtl::OUString;
22 using rtl::OUStringBuffer;
24 using com::sun::star::beans::XPropertySet;
26 using com::sun::star::lang::XComponent;
28 using com::sun::star::sdbc::SQLException;
29 using com::sun::star::sdbc::XStatement;
30 using com::sun::star::sdbc::XConnection;
31 using com::sun::star::sdbc::XPreparedStatement;
32 using com::sun::star::sdbc::XParameters;
33 using com::sun::star::sdbc::XResultSet;
34 using com::sun::star::sdbc::XRow;
36 using com::sun::star::sdbcx::XColumnsSupplier;
38 using com::sun::star::uno::UNO_QUERY;
39 using com::sun::star::uno::Reference;
40 using com::sun::star::uno::Sequence;
41 using com::sun::star::uno::XInterface;
42 using com::sun::star::uno::Any;
43 using com::sun::star::uno::makeAny;
45 using com::sun::star::container::XEnumeration;
46 using com::sun::star::container::XEnumerationAccess;
48 namespace pq_sdbc_driver
50 #define ASCII_STR(x) rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( x ) )
52 rtl::OUString date2String( const com::sun::star::util::Date & x )
54 char buffer[64];
55 sprintf( buffer, "%d-%02d-%02d", x.Year, x.Month, x.Day );
56 return OUString::createFromAscii( buffer );
59 com::sun::star::util::Date string2Date( const rtl::OUString &date )
61 // Format: Year-Month-Day
62 com::sun::star::util::Date ret;
64 ret.Year = (sal_Int32) rtl_ustr_toInt32( date.pData->buffer, 10 );
66 int index = date.indexOf( '-' );
67 if( index >= 0 )
69 ret.Month = (sal_Int32)rtl_ustr_toInt32( &(date.pData->buffer[ index+1]), 10 );
70 int start = index;
71 index = date.indexOf( '-', start+1 );
72 if( index >= 0 )
74 ret.Day = (sal_Int32)rtl_ustr_toInt32( &date.pData->buffer[index+1], 10 );
77 return ret;
80 rtl::OUString time2String( const com::sun::star::util::Time & x )
82 char buffer[64];
83 sprintf( buffer, "%02d:%02d:%02d.%02d", x.Hours, x.Minutes, x.Seconds, x.HundredthSeconds );
84 return OUString::createFromAscii( buffer );
89 com::sun::star::util::Time string2Time( const rtl::OUString & time )
91 com::sun::star::util::Time ret;
93 sal_Unicode temp[4];
95 temp[0] = time[0];
96 temp[1] = time[1];
97 temp[2] = 0;
98 ret.Hours = (sal_Int32)rtl_ustr_toInt32( temp , 10 );
100 temp[0] = time[3];
101 temp[1] = time[4];
102 ret.Minutes = (sal_Int32)rtl_ustr_toInt32( temp , 10 );
104 temp[0] = time[6];
105 temp[1] = time[7];
106 ret.Seconds = (sal_Int32)rtl_ustr_toInt32( temp , 10 );
108 if( time.getLength() >9 )
110 ret.HundredthSeconds = (sal_Int32)rtl_ustr_toInt32( &time[9] , 10 );
112 return ret;
118 rtl::OUString dateTime2String( const com::sun::star::util::DateTime & x )
120 char buffer[128];
121 sprintf( buffer, "%d-%02d-%02d %02d:%02d:%02d.%02d",
122 x.Year, x.Month, x.Day,
123 x.Hours, x.Minutes, x.Seconds, x.HundredthSeconds );
124 return OUString::createFromAscii( buffer );
128 com::sun::star::util::DateTime string2DateTime( const rtl::OUString & dateTime )
130 int space = dateTime.indexOf( ' ' );
131 com::sun::star::util::DateTime ret;
133 if( space >= 0 )
135 com::sun::star::util::Date date ( string2Date( OUString( dateTime.getStr(), space ) ) );
136 com::sun::star::util::Time time( string2Time( OUString( dateTime.getStr() + space +1 ) ) );
137 ret.Day = date.Day;
138 ret.Month = date.Month;
139 ret.Year = date.Year;
141 ret.Hours = time.Hours;
142 ret.Minutes = time.Minutes;
143 ret.Seconds = time.Seconds;
144 ret.HundredthSeconds = time.HundredthSeconds;
146 return ret;
149 rtl::OUString concatQualified( const rtl::OUString & a, const rtl::OUString &b)
151 rtl::OUStringBuffer buf( a.getLength() + 2 + b.getLength() );
152 buf.append( a );
153 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "." ) );
154 buf.append( b );
155 return buf.makeStringAndClear();
158 void bufferEscapeConstant( rtl::OUStringBuffer & buf, const rtl::OUString & value, sal_Int32 encoding )
160 rtl::OString y = rtl::OUStringToOString( value, encoding );
161 rtl::OStringBuffer strbuf( y.getLength() * 2 + 2 );
162 int len = PQescapeString( ((char*)strbuf.getStr()), y.getStr() , y.getLength() );
163 strbuf.setLength( len );
164 buf.append( rtl::OStringToOUString( strbuf.makeStringAndClear(), RTL_TEXTENCODING_ASCII_US ) );
167 void bufferQuoteConstant( rtl::OUStringBuffer & buf, const rtl::OUString & value, sal_Int32 encoding )
169 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( " '" ) );
170 bufferEscapeConstant( buf, value, encoding );
171 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "' " ) );
174 void bufferQuoteQualifiedIdentifier(
175 rtl::OUStringBuffer & buf, const rtl::OUString &schema, const rtl::OUString &name)
177 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" \"" ) );
178 buf.append(schema);
179 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\".\"" ) );
180 buf.append( name );
181 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "\" " ) );
184 void bufferQuoteQualifiedIdentifier(
185 rtl::OUStringBuffer & buf,
186 const rtl::OUString &schema,
187 const rtl::OUString &name,
188 const rtl::OUString &col)
190 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" \"" ) );
191 buf.append(schema);
192 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\".\"" ) );
193 buf.append( name );
194 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\".\"" ) );
195 buf.append( col );
196 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "\" " ) );
200 void bufferQuoteIdentifier( rtl::OUStringBuffer & buf, const rtl::OUString &toQuote )
202 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( " \"") );
203 buf.append( toQuote );
204 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "\" " ) );
209 rtl::OUString extractStringProperty(
210 const Reference< XPropertySet > & descriptor, const rtl::OUString &name )
212 rtl::OUString value;
213 descriptor->getPropertyValue( name ) >>= value;
214 return value;
217 sal_Bool extractBoolProperty(
218 const Reference< XPropertySet > & descriptor, const rtl::OUString &name )
220 sal_Bool value = sal_False;
221 descriptor->getPropertyValue( name ) >>= value;
222 return value;
225 sal_Int32 extractIntProperty(
226 const Reference< XPropertySet > & descriptor, const rtl::OUString &name )
228 sal_Int32 ret = 0;
229 descriptor->getPropertyValue( name ) >>= ret;
230 return ret;
233 void disposeObject( const com::sun::star::uno::Reference< com::sun::star::uno::XInterface > & r )
235 Reference< XComponent > comp( r, UNO_QUERY );
236 if( comp.is() )
237 comp->dispose();
240 void disposeNoThrow( const com::sun::star::uno::Reference< com::sun::star::uno::XInterface > & r )
244 disposeObject( r );
246 catch( SQLException & e )
248 // ignore this
253 void rollbackNoThrow( const com::sun::star::uno::Reference< com::sun::star::sdbc::XConnection > & r )
257 Reference< XStatement > stmt = r->createStatement();
258 stmt->executeUpdate( getStatics().ROLLBACK );
261 catch( SQLException & )
263 // ignore this
267 Reference< XConnection > extractConnectionFromStatement( const Reference< XInterface > & stmt )
269 Reference< XConnection > ret;
271 Reference< com::sun::star::sdbc::XStatement > owner( stmt, UNO_QUERY );
272 if( owner.is() )
273 ret = owner->getConnection();
274 else
276 Reference< com::sun::star::sdbc::XPreparedStatement > myowner( stmt, UNO_QUERY );
277 if( myowner.is() )
278 ret = myowner->getConnection();
279 if( ! ret.is() )
280 throw SQLException(
281 ASCII_STR( "PQSDBC: Couldn't retrieve connection from statement" ),
282 Reference< XInterface > () , rtl::OUString(), 0 , com::sun::star::uno::Any() );
285 return ret;
289 DisposeGuard::DisposeGuard( const Reference< XInterface > & r )
290 : d( r )
293 DisposeGuard::~DisposeGuard()
295 disposeNoThrow( d );
298 TransactionGuard::TransactionGuard( const Reference< XStatement > &stmt )
299 : m_stmt( stmt ),
300 m_commited( sal_False )
302 m_stmt->executeUpdate( getStatics().BEGIN );
305 void TransactionGuard::commit()
307 m_stmt->executeUpdate( getStatics().COMMIT );
308 m_commited = sal_True;
311 void TransactionGuard::executeUpdate( const rtl::OUString & sql )
313 m_stmt->executeUpdate( sql );
316 TransactionGuard::~TransactionGuard()
320 if( ! m_commited )
321 m_stmt->executeUpdate( getStatics().ROLLBACK );
323 catch( com::sun::star::uno::Exception & e )
325 // ignore, we are within a dtor
328 disposeNoThrow( m_stmt );
332 bool isWhitespace( sal_Unicode c )
334 return ' ' == c || 9 == c || 10 == c || 13 == c;
337 ::rtl::OUString extractTableFromInsert( const rtl::OUString & sql )
339 rtl::OUString ret;
340 int i = 0;
341 for( ; i < sql.getLength() && isWhitespace(sql[i]) ; i++ );
343 if( 0 == rtl_ustr_ascii_shortenedCompareIgnoreAsciiCase_WithLength(
344 &sql[i], sql.getLength() - i, "insert" , 6 ) )
346 i += 6;
347 for( ; i < sql.getLength() && isWhitespace(sql[i]) ; i++ );
348 if( 0 == rtl_ustr_ascii_shortenedCompareIgnoreAsciiCase_WithLength(
349 &sql[i], sql.getLength() - i, "into" , 4 ) )
351 i +=4;
352 for( ; i < sql.getLength() && isWhitespace(sql[i]) ; i++ );
353 int start = i;
354 bool quote = (sql[i] == '"');
355 for( i++ ; i < sql.getLength() ; i ++ )
357 if( quote && sql[i] == '"' )
359 for( i++ ; i < sql.getLength() && isWhitespace(sql[i]) ; i++ );
360 if( '.' == sql[i] )
362 for( i++ ; i < sql.getLength() && isWhitespace(sql[i]) ; i++ );
363 if( '"' == sql[i] )
365 // the second part of the table name does not use quotes
366 // parse on
367 quote = 0;
370 else
372 // end quoted name, ok
373 break;
376 else
378 if( isWhitespace( sql[i] ) )
380 // found the end of an unquoted name
381 break;
385 ret = rtl::OUString( &sql[start], i - start ).trim();
386 // printf( "pq_statement: parsed table name %s from insert\n" ,
387 // OUStringToOString( ret, RTL_TEXTENCODING_ASCII_US).getStr() );
390 return ret;
394 static bool isOperator( char c )
396 bool ret;
397 switch(c)
399 case '+':
400 case '-':
401 case '*':
402 case '/':
403 case '<':
404 case '>':
405 case '=':
406 case '~':
407 case '!':
408 case '@':
409 case '#':
410 case '%':
411 case '^':
412 case '&':
413 case '|':
414 case '`':
415 case '?':
416 case '$':
417 ret = true;
418 default:
419 ret = false;
421 return ret;
424 void splitSQL( const rtl::OString & sql, OStringVector &vec )
426 int length = sql.getLength();
428 int i = 0;
429 bool singleQuote = false;
430 bool doubleQuote = false;
431 int start = 0;
432 for( ; i < length ; i ++ )
434 char c = sql[i];
435 if( doubleQuote )
437 if( '"' == c )
439 vec.push_back( rtl::OString( &sql[start], i-start+1 ) );
440 start = i + 1;
441 doubleQuote = false;
444 else if( singleQuote )
446 if( '\'' == c && '\'' == sql[i+1] )
448 // two subsequent single quotes within a quoted string
449 // mean a single quote within the string
450 i ++;
452 else if( '\'' == c )
454 vec.push_back( rtl::OString( &sql[start], i - start +1 ) );
455 start = i + 1; // leave single quotes !
456 singleQuote = false;
459 else
461 if( '"' == c )
463 vec.push_back( rtl::OString( &sql[start], i - start ) );
464 doubleQuote = true;
465 start = i;
467 else if( '\'' == c )
469 vec.push_back( rtl::OString( &sql[start], i - start ) );
470 singleQuote = true;
471 start = i;
475 if( start < i )
476 vec.push_back( rtl::OString( &sql[start] , i - start ) );
478 // for( i = 0 ; i < vec.size() ; i ++ )
479 // printf( "%s!" , vec[i].getStr() );
480 // printf( "\n" );
484 void tokenizeSQL( const rtl::OString & sql, OStringVector &vec )
486 int length = sql.getLength();
488 int i = 0;
489 bool singleQuote = false;
490 bool doubleQuote = false;
491 int start = 0;
492 for( ; i < length ; i ++ )
494 char c = sql[i];
495 if( doubleQuote )
497 if( '"' == c )
499 vec.push_back( rtl::OString( &sql[start], i-start ) );
500 start = i + 1;
501 doubleQuote = false;
504 else if( singleQuote )
506 if( '\'' == c )
508 vec.push_back( rtl::OString( &sql[start], i - start +1 ) );
509 start = i + 1; // leave single quotes !
510 singleQuote = false;
513 else
515 if( '"' == c )
517 doubleQuote = true;
518 start = i +1; // skip double quotes !
520 else if( '\'' == c )
522 singleQuote = true;
523 start = i; // leave single quotes
525 else if( isWhitespace( c ) )
527 if( i == start )
528 start ++; // skip additional whitespace
529 else
531 vec.push_back( rtl::OString( &sql[start], i - start ) );
532 start = i +1;
535 else if( ',' == c || isOperator( c ) || '(' == c || ')' == c )
537 if( i - start )
538 vec.push_back( rtl::OString( &sql[start], i - start ) );
539 vec.push_back( rtl::OString( &sql[i], 1 ) );
540 start = i + 1;
542 else if( '.' == c )
544 if( ( i > start && sql[start] >= '0' && sql[start] <= '9' ) ||
545 ( i == start && i > 1 && isWhitespace( sql[i-1] ) ) )
547 // ignore, is a literal
549 else
551 if( i - start )
552 vec.push_back( rtl::OString( &sql[start], i - start ) );
553 vec.push_back( rtl::OString( RTL_CONSTASCII_STRINGPARAM( "." ) ) );
554 start = i + 1;
559 if( start < i )
560 vec.push_back( rtl::OString( &sql[start] , i - start ) );
562 // for( i = 0 ; i < vec.size() ; i ++ )
563 // printf( "%s!" , vec[i].getStr() );
564 // printf( "\n" );
568 void splitConcatenatedIdentifier( const rtl::OUString & source, rtl::OUString *first, rtl::OUString *second)
570 OStringVector vec;
571 tokenizeSQL( rtl::OUStringToOString( source, RTL_TEXTENCODING_UTF8 ), vec );
572 if( vec.size() == 3 )
574 *first = rtl::OStringToOUString( vec[0] , RTL_TEXTENCODING_UTF8 );
575 *second = rtl::OStringToOUString( vec[2], RTL_TEXTENCODING_UTF8 );
579 typedef std::vector< sal_Int32 , Allocator< sal_Int32 > > IntVector;
582 rtl::OUString array2String( const com::sun::star::uno::Sequence< Any > &seq )
584 OUStringBuffer buf(128);
585 int len = seq.getLength();
586 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "{" ) );
587 for( int i = 0 ; i < len ; i ++ )
589 OUString element;
590 seq[i] >>= element;
592 if( i > 0 )
593 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(",") );
594 int strLength = element.getLength();
595 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "\"") );
596 for( int j = 0 ; j < strLength ; j ++ )
598 sal_Unicode c = element[j];
599 if( c == '\\' || c == '"' || c == '{' || c == '}' )
601 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "\\" ) );
603 buf.append( c );
605 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "\"" ) );
607 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "}" ) );
608 return buf.makeStringAndClear();
611 typedef
612 std::vector
614 com::sun::star::uno::Any,
615 Allocator< com::sun::star::uno::Any >
616 > AnyVector;
618 com::sun::star::uno::Sequence< Any > parseArray( const rtl::OUString & str ) throw( SQLException )
620 com::sun::star::uno::Sequence< Any > ret;
622 int len = str.getLength();
623 bool doubleQuote = false;
624 int brackets = 0;
625 int i = 0;
627 OUStringBuffer current;
628 AnyVector elements;
629 bool doubleQuotedValue = false;
630 while( i < len )
632 sal_Unicode c = str[i];
633 sal_Unicode cnext = str[i+1];
634 if( doubleQuote )
636 if( '\\' == c )
638 i ++;
639 current.append( cnext );
641 else if( '"' == c )
643 doubleQuote = false;
644 doubleQuotedValue = true; // signal, that there was an empty element
646 else
648 current.append( c );
651 else if ( '{' == c )
653 brackets ++;
655 else if( '}' == c )
657 brackets --;
658 if( brackets < 0 )
661 OUStringBuffer buf;
662 buf.appendAscii( "error during array parsing, didn't expect a } at position " );
663 buf.append( (sal_Int32) i );
664 buf.appendAscii( " ('" );
665 buf.append( str );
666 buf.appendAscii( "')" );
667 throw SQLException(
668 buf.makeStringAndClear(),
669 Reference< XInterface > (), rtl::OUString(), 1, Any() );
671 if( brackets == 0 )
673 if( current.getLength() > 0 || doubleQuotedValue )
674 elements.push_back( makeAny( current.makeStringAndClear() ) );
676 else
678 current.append( c );
681 else if( '"' == c )
683 // if( current.getLength() != 0 )
684 // {
685 // OUStringBuffer buf;
686 // buf.appendAscii( "error during array parsing, didn't expect a \" at position " );
687 // buf.append( i );
688 // buf.append( " ('" );
689 // buf.append( str );
690 // buf.append( "')" );
691 // throw SDBCException(
692 // buf.makeStringAndClear(),
693 // Reference< XInterface > (), 1, Any() );
694 // }
695 // else
696 // {
697 doubleQuote = true;
698 // }
700 else if( ',' == c && brackets == 1)
702 doubleQuotedValue = false;
703 elements.push_back( makeAny( current.makeStringAndClear() ) );
705 else if( isWhitespace( c ) )
707 // ignore whitespace without quotes
709 else
711 current.append( c );
713 i++;
715 ret = Sequence< Any > ( &elements[0] , elements.size() );
716 return ret;
719 com::sun::star::uno::Sequence< sal_Int32 > parseIntArray( const ::rtl::OUString & str )
721 sal_Int32 start = 0;
722 IntVector vec;
723 // printf( ">%s<\n" , OUStringToOString( str, RTL_TEXTENCODING_UTF8 ).getStr() );
724 for( sal_Int32 i = str.indexOf( ' ' ) ; i != -1 ; i = str.indexOf( ' ', start) )
726 vec.push_back( (sal_Int32)rtl_ustr_toInt32( &str.pData->buffer[start], 10 ) );
727 // printf( "found %d\n" , rtl_ustr_toInt32( &str.pData->buffer[start], 10 ));
728 start = i + 1;
730 vec.push_back( (sal_Int32)rtl_ustr_toInt32( &str.pData->buffer[start], 10 ) );
731 // printf( "found %d\n" , rtl_ustr_toInt32( &str.pData->buffer[start], 10 ));
732 return Sequence< sal_Int32 > ( &vec[0], vec.size() );
735 void fillAttnum2attnameMap(
736 Int2StringMap &map,
737 const Reference< com::sun::star::sdbc::XConnection > &conn,
738 const rtl::OUString &schema,
739 const rtl::OUString &table )
741 Reference< XPreparedStatement > prep = conn->prepareStatement(
742 ASCII_STR( "SELECT attname,attnum "
743 "FROM pg_attribute "
744 "INNER JOIN pg_class ON attrelid = pg_class.oid "
745 "INNER JOIN pg_namespace ON pg_class.relnamespace = pg_namespace.oid "
746 "WHERE relname=? AND nspname=?" ) );
748 Reference< XParameters > paras( prep, UNO_QUERY );
749 paras->setString( 1 , table );
750 paras->setString( 2 , schema );
751 Reference< XResultSet > rs = prep->executeQuery();
753 Reference< XRow > xRow( rs , UNO_QUERY );
754 while( rs->next() )
756 map[ xRow->getInt(2) ] = xRow->getString(1);
760 ::rtl::OString extractSingleTableFromSelect( const OStringVector &vec )
762 rtl::OString ret;
763 int token = 0;
765 if( 0 == rtl_str_shortenedCompareIgnoreAsciiCase_WithLength(
766 vec[0].pData->buffer, vec[0].pData->length, "select" , 6 , 6 ) )
768 for( token = 1; token < vec.size() ; token ++ )
770 if( 0 == rtl_str_shortenedCompareIgnoreAsciiCase_WithLength(
771 vec[token].getStr(), vec[token].getLength(), "from" , 4 , 4 ) )
773 // found from
774 break;
777 token ++;
779 if( token < vec.size() && 0 == rtl_str_shortenedCompareIgnoreAsciiCase_WithLength(
780 vec[token].pData->buffer, vec[token].pData->length, "only " , 4 , 4 ) )
782 token ++;
785 if( token < vec.size() && rtl_str_compare_WithLength(
786 vec[token].getStr(), vec[token].getLength(),
787 RTL_CONSTASCII_STRINGPARAM("(") ) )
789 // it is a table or a function name
790 rtl::OStringBuffer buf(128);
791 if( '"' == vec[token][0] )
792 buf.append( &(vec[token][1]) , vec[token].getLength() -2 );
793 else
794 buf.append( vec[token] );
795 token ++;
797 if( token < vec.size() )
799 if( rtl_str_compare_WithLength(
800 vec[token].getStr(), vec[token].getLength(),
801 RTL_CONSTASCII_STRINGPARAM( "." ) ) == 0 )
803 buf.append( vec[token] );
804 token ++;
805 if( token < vec.size() )
807 if( '"' == vec[token][0] )
808 buf.append( &(vec[token][1]) , vec[token].getLength() -2 );
809 else
810 buf.append( vec[token] );
811 token ++;
816 ret = buf.makeStringAndClear();
817 // now got my table candidate
819 if( token < vec.size() && rtl_str_compare_WithLength(
820 vec[token].getStr(), vec[token].getLength(),
821 RTL_CONSTASCII_STRINGPARAM( "(" ) ) == 0 )
823 // whoops, it is a function
824 ret = rtl::OString();
826 else
828 if( token < vec.size() )
830 if( 0 == rtl_str_shortenedCompareIgnoreAsciiCase_WithLength(
831 vec[token].pData->buffer, vec[token].pData->length, "as" , 2, 2 ) )
833 token += 2; // skip alias
837 if( token < vec.size() )
839 if( rtl_str_compare_WithLength(
840 vec[token].getStr(), vec[token].getLength(),
841 RTL_CONSTASCII_STRINGPARAM( "," ) ) == 0 )
843 // whoops, multiple tables are used
844 ret = rtl::OString();
846 else
848 static const char * forbiddenKeywords[] =
849 { "join", "natural", "outer", "inner", "left", "right", "full" , 0 };
850 for( int i = 0 ; forbiddenKeywords[i] ; i ++ )
852 if( 0 == rtl_str_shortenedCompareIgnoreAsciiCase_WithLength(
853 vec[token].pData->buffer, vec[token].pData->length,
854 forbiddenKeywords[i], strlen(forbiddenKeywords[i]),
855 strlen(forbiddenKeywords[i]) ) )
857 // whoops, it is a join
858 ret = rtl::OString();
866 return ret;
870 com::sun::star::uno::Sequence< sal_Int32 > string2intarray( const ::rtl::OUString & str )
872 com::sun::star::uno::Sequence< sal_Int32 > ret;
873 if( str.getLength() > 1 && '{' == str[0] )
875 std::vector< sal_Int32, Allocator< sal_Int32 > > vec;
876 sal_Int32 start = 0;
879 start ++;
880 vec.push_back( (sal_Int32)rtl_ustr_toInt32( &str[start], 10 ) );
881 start = str.indexOf( ',' , start );
882 } while( start != -1 );
883 ret = com::sun::star::uno::Sequence< sal_Int32 > ( &vec[0] , vec.size() );
885 return ret;
889 Sequence< rtl::OUString > convertMappedIntArray2StringArray(
890 const Int2StringMap &map, const Sequence< sal_Int32 > &intArray )
892 Sequence< ::rtl::OUString > ret( intArray.getLength() );
893 for( int i = 0; i < intArray.getLength() ; i ++ )
895 Int2StringMap::const_iterator ii = map.find( intArray[i] );
896 if( ii != map.end() )
897 ret[i] = ii->second;
899 return ret;
903 ::rtl::OUString sqltype2string( const Reference< XPropertySet > & desc )
905 OUStringBuffer typeName;
906 typeName.append( extractStringProperty( desc, getStatics().TYPE_NAME ) );
907 sal_Int32 precision = extractIntProperty( desc, getStatics().PRECISION );
909 if( precision )
911 switch( extractIntProperty( desc, getStatics().TYPE ) )
913 case com::sun::star::sdbc::DataType::VARBINARY:
914 case com::sun::star::sdbc::DataType::VARCHAR:
915 case com::sun::star::sdbc::DataType::CHAR:
917 typeName.appendAscii( RTL_CONSTASCII_STRINGPARAM( "(" ) );
918 typeName.append( precision );
919 typeName.appendAscii( RTL_CONSTASCII_STRINGPARAM( ")" ) );
920 break;
922 case com::sun::star::sdbc::DataType::DECIMAL:
923 case com::sun::star::sdbc::DataType::NUMERIC:
925 typeName.appendAscii( RTL_CONSTASCII_STRINGPARAM( "(" ) );
926 typeName.append( precision );
927 typeName.appendAscii( RTL_CONSTASCII_STRINGPARAM( "," ) );
928 typeName.append( extractIntProperty( desc, getStatics().SCALE ) );
929 typeName.appendAscii( RTL_CONSTASCII_STRINGPARAM( ")" ) );
930 break;
932 default:
933 ((void)0);
936 return typeName.makeStringAndClear();
942 static void keyType2String( OUStringBuffer & buf, sal_Int32 keyType )
944 if( com::sun::star::sdbc::KeyRule::CASCADE == keyType )
946 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "CASCADE " ) );
948 else if( com::sun::star::sdbc::KeyRule::RESTRICT == keyType )
950 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "RESTRICT " ) );
952 else if( com::sun::star::sdbc::KeyRule::SET_DEFAULT == keyType )
954 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "SET DEFAULT " ) );
956 else if( com::sun::star::sdbc::KeyRule::SET_NULL == keyType )
958 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "SET NULL " ) );
960 else //if( com::sun::star::sdbc::KeyRule::NO_ACTION == keyType )
962 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "NO ACTION " ) );
966 void bufferKey2TableConstraint(
967 OUStringBuffer &buf, const Reference< XPropertySet > &key )
969 Statics &st = getStatics();
970 sal_Int32 type = extractIntProperty( key, st.TYPE );
971 OUString referencedTable = extractStringProperty( key, st.REFERENCED_TABLE );
972 sal_Int32 updateRule = extractIntProperty( key, st.UPDATE_RULE );
973 sal_Int32 deleteRule = extractIntProperty( key, st.DELETE_RULE );
974 bool foreign = false;
975 if( type == com::sun::star::sdbcx::KeyType::UNIQUE )
977 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "UNIQUE( " ) );
979 else if( type == com::sun::star::sdbcx::KeyType::PRIMARY )
981 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "PRIMARY KEY( " ) );
983 else if( type == com::sun::star::sdbcx::KeyType::FOREIGN )
985 foreign = true;
986 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "FOREIGN KEY( " ) );
989 Reference< XColumnsSupplier > columns( key, UNO_QUERY );
990 if( columns.is() )
992 Reference< XEnumerationAccess > colEnumAccess( columns->getColumns(), UNO_QUERY );
993 if( colEnumAccess.is() )
995 Reference< XEnumeration > colEnum = colEnumAccess->createEnumeration();
996 bool first = true;
997 while(colEnum.is() && colEnum->hasMoreElements() )
999 if( first )
1001 first = false;
1003 else
1005 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( ", " ) );
1007 Reference< XPropertySet > keyColumn( colEnum->nextElement(), UNO_QUERY );
1008 bufferQuoteIdentifier(buf, extractStringProperty( keyColumn, st.NAME ) );
1012 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( ") " ));
1014 if( foreign )
1016 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "REFERENCES " ) );
1017 OUString schema;
1018 OUString tableName;
1019 splitConcatenatedIdentifier( referencedTable, &schema, &tableName );
1020 bufferQuoteQualifiedIdentifier(buf , schema, tableName);
1021 if(columns.is() )
1023 Reference< XEnumerationAccess > colEnumAccess( columns->getColumns(), UNO_QUERY);
1024 if( colEnumAccess.is() )
1026 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( " (" ) );
1027 Reference< XEnumeration > colEnum(colEnumAccess->createEnumeration());
1028 bool first = true;
1029 while(colEnum.is() && colEnum->hasMoreElements() )
1031 if( first )
1033 first = false;
1035 else
1037 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( ", " ) );
1039 Reference< XPropertySet > keyColumn( colEnum->nextElement(), UNO_QUERY );
1040 bufferQuoteIdentifier(
1041 buf, extractStringProperty( keyColumn, st.RELATED_COLUMN ) );
1043 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( ") " ) );
1047 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "ON DELETE " ) );
1048 keyType2String( buf, deleteRule );
1049 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( " ON UPDATE " ) );
1050 keyType2String( buf, updateRule );
1055 static bool equalsIgnoreCase( const rtl::OString & str, const char *str2, int length2 )
1057 return 0 == rtl_str_compareIgnoreAsciiCase_WithLength(
1058 str.pData->buffer, str.pData->length, str2, length2 );
1061 void extractNameValuePairsFromInsert( String2StringMap & map, const rtl::OString & lastQuery )
1063 OStringVector vec;
1064 tokenizeSQL( lastQuery, vec );
1066 int nSize = vec.size();
1067 // printf( "1 %d\n", nSize );
1068 if( nSize > 6 &&
1069 equalsIgnoreCase( vec[0] , RTL_CONSTASCII_STRINGPARAM( "insert" ) ) &&
1070 equalsIgnoreCase( vec[1] , RTL_CONSTASCII_STRINGPARAM( "into" ) ) )
1072 int n = 2;
1074 // printf( "1a\n" );
1075 // extract table name
1076 rtl::OString tableName;
1077 if( equalsIgnoreCase( vec[n+1], RTL_CONSTASCII_STRINGPARAM( "." ) ) )
1079 tableName = vec[n];
1080 tableName += vec[n+1];
1081 tableName += vec[n+2];
1082 n +=2;
1084 else
1086 tableName = vec[n];
1089 OStringVector names;
1090 n ++;
1091 if( equalsIgnoreCase( vec[n], RTL_CONSTASCII_STRINGPARAM( "(" ) ) )
1093 // printf( "2\n" );
1094 // extract names
1095 n++;
1096 while( nSize > n && ! equalsIgnoreCase(vec[n] , RTL_CONSTASCII_STRINGPARAM( ")" ) ) )
1098 names.push_back( vec[n] );
1099 if( nSize > n+1 && equalsIgnoreCase( vec[n+1] , RTL_CONSTASCII_STRINGPARAM( "," ) ) )
1101 n ++;
1103 n++;
1105 n++;
1107 // now read the values
1108 if( nSize > n +1 && equalsIgnoreCase( vec[n], RTL_CONSTASCII_STRINGPARAM("VALUES") ) &&
1109 equalsIgnoreCase(vec[n+1], RTL_CONSTASCII_STRINGPARAM( "(" ) ) )
1111 n +=2;
1112 // printf( "3\n" );
1113 for ( int i = 0 ; i < names.size() && nSize > n ; i ++ )
1115 map[names[i]] = vec[n];
1116 if( nSize > n+1 && equalsIgnoreCase( vec[n+1] , RTL_CONSTASCII_STRINGPARAM(",") ) )
1118 n ++;
1120 n++;
1127 rtl::OUString querySingleValue(
1128 const com::sun::star::uno::Reference< com::sun::star::sdbc::XConnection > &connection,
1129 const rtl::OUString &query )
1131 OUString ret;
1132 Reference< XStatement > stmt = connection->createStatement();
1133 DisposeGuard guard( stmt );
1134 Reference< XResultSet > rs = stmt->executeQuery( query );
1135 Reference< XRow > xRow( rs, UNO_QUERY );
1136 if( rs->next() )
1137 ret = xRow->getString( 1 );
1138 return ret;
1142 // copied from connectivity/source/dbtools, can't use the function directly
1143 bool implSetObject( const Reference< XParameters >& _rxParameters,
1144 const sal_Int32 _nColumnIndex, const Any& _rValue)
1146 sal_Bool bSuccessfullyReRouted = sal_True;
1147 switch (_rValue.getValueTypeClass())
1149 case typelib_TypeClass_HYPER:
1151 sal_Int64 nValue = 0;
1152 _rxParameters->setLong( _nColumnIndex, nValue );
1154 break;
1156 case typelib_TypeClass_VOID:
1157 _rxParameters->setNull(_nColumnIndex,com::sun::star::sdbc::DataType::VARCHAR);
1158 break;
1160 case typelib_TypeClass_STRING:
1161 _rxParameters->setString(_nColumnIndex, *(rtl::OUString*)_rValue.getValue());
1162 break;
1164 case typelib_TypeClass_BOOLEAN:
1165 _rxParameters->setBoolean(_nColumnIndex, *(sal_Bool *)_rValue.getValue());
1166 break;
1168 case typelib_TypeClass_BYTE:
1169 _rxParameters->setByte(_nColumnIndex, *(sal_Int8 *)_rValue.getValue());
1170 break;
1172 case typelib_TypeClass_UNSIGNED_SHORT:
1173 case typelib_TypeClass_SHORT:
1174 _rxParameters->setShort(_nColumnIndex, *(sal_Int16*)_rValue.getValue());
1175 break;
1177 case typelib_TypeClass_CHAR:
1178 _rxParameters->setString(_nColumnIndex, ::rtl::OUString((sal_Unicode *)_rValue.getValue(),1));
1179 break;
1181 case typelib_TypeClass_UNSIGNED_LONG:
1182 case typelib_TypeClass_LONG:
1183 _rxParameters->setInt(_nColumnIndex, *(sal_Int32*)_rValue.getValue());
1184 break;
1186 case typelib_TypeClass_FLOAT:
1187 _rxParameters->setFloat(_nColumnIndex, *(float*)_rValue.getValue());
1188 break;
1190 case typelib_TypeClass_DOUBLE:
1191 _rxParameters->setDouble(_nColumnIndex, *(double*)_rValue.getValue());
1192 break;
1194 case typelib_TypeClass_SEQUENCE:
1195 if (_rValue.getValueType() == ::getCppuType((const Sequence< sal_Int8 > *)0))
1197 _rxParameters->setBytes(_nColumnIndex, *(Sequence<sal_Int8>*)_rValue.getValue());
1199 else
1200 bSuccessfullyReRouted = sal_False;
1201 break;
1202 case typelib_TypeClass_STRUCT:
1203 if (_rValue.getValueType() == ::getCppuType((const com::sun::star::util::DateTime*)0))
1204 _rxParameters->setTimestamp(_nColumnIndex, *(com::sun::star::util::DateTime*)_rValue.getValue());
1205 else if (_rValue.getValueType() == ::getCppuType((const com::sun::star::util::Date*)0))
1206 _rxParameters->setDate(_nColumnIndex, *(com::sun::star::util::Date*)_rValue.getValue());
1207 else if (_rValue.getValueType() == ::getCppuType((const com::sun::star::util::Time*)0))
1208 _rxParameters->setTime(_nColumnIndex, *(com::sun::star::util::Time*)_rValue.getValue());
1209 else
1210 bSuccessfullyReRouted = sal_False;
1211 break;
1213 case typelib_TypeClass_INTERFACE:
1215 Reference< com::sun::star::io::XInputStream > xStream;
1216 if (_rValue >>= xStream)
1218 _rValue >>= xStream;
1219 _rxParameters->setBinaryStream(_nColumnIndex, xStream, xStream->available());
1220 break;
1223 // run through
1224 default:
1225 bSuccessfullyReRouted = sal_False;
1229 return bSuccessfullyReRouted;