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"
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
)
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( '-' );
69 ret
.Month
= (sal_Int32
)rtl_ustr_toInt32( &(date
.pData
->buffer
[ index
+1]), 10 );
71 index
= date
.indexOf( '-', start
+1 );
74 ret
.Day
= (sal_Int32
)rtl_ustr_toInt32( &date
.pData
->buffer
[index
+1], 10 );
80 rtl::OUString
time2String( const com::sun::star::util::Time
& x
)
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
;
98 ret
.Hours
= (sal_Int32
)rtl_ustr_toInt32( temp
, 10 );
102 ret
.Minutes
= (sal_Int32
)rtl_ustr_toInt32( temp
, 10 );
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 );
118 rtl::OUString
dateTime2String( const com::sun::star::util::DateTime
& x
)
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
;
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 ) ) );
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
;
149 rtl::OUString
concatQualified( const rtl::OUString
& a
, const rtl::OUString
&b
)
151 rtl::OUStringBuffer
buf( a
.getLength() + 2 + b
.getLength() );
153 buf
.appendAscii( RTL_CONSTASCII_STRINGPARAM( "." ) );
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(" \"" ) );
179 buf
.appendAscii( RTL_CONSTASCII_STRINGPARAM("\".\"" ) );
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(" \"" ) );
192 buf
.appendAscii( RTL_CONSTASCII_STRINGPARAM("\".\"" ) );
194 buf
.appendAscii( RTL_CONSTASCII_STRINGPARAM("\".\"" ) );
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
)
213 descriptor
->getPropertyValue( name
) >>= 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
;
225 sal_Int32
extractIntProperty(
226 const Reference
< XPropertySet
> & descriptor
, const rtl::OUString
&name
)
229 descriptor
->getPropertyValue( name
) >>= ret
;
233 void disposeObject( const com::sun::star::uno::Reference
< com::sun::star::uno::XInterface
> & r
)
235 Reference
< XComponent
> comp( r
, UNO_QUERY
);
240 void disposeNoThrow( const com::sun::star::uno::Reference
< com::sun::star::uno::XInterface
> & r
)
246 catch( SQLException
& e
)
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
& )
267 Reference
< XConnection
> extractConnectionFromStatement( const Reference
< XInterface
> & stmt
)
269 Reference
< XConnection
> ret
;
271 Reference
< com::sun::star::sdbc::XStatement
> owner( stmt
, UNO_QUERY
);
273 ret
= owner
->getConnection();
276 Reference
< com::sun::star::sdbc::XPreparedStatement
> myowner( stmt
, UNO_QUERY
);
278 ret
= myowner
->getConnection();
281 ASCII_STR( "PQSDBC: Couldn't retrieve connection from statement" ),
282 Reference
< XInterface
> () , rtl::OUString(), 0 , com::sun::star::uno::Any() );
289 DisposeGuard::DisposeGuard( const Reference
< XInterface
> & r
)
293 DisposeGuard::~DisposeGuard()
298 TransactionGuard::TransactionGuard( const Reference
< XStatement
> &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()
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
)
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 ) )
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 ) )
352 for( ; i
< sql
.getLength() && isWhitespace(sql
[i
]) ; 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
++ );
362 for( i
++ ; i
< sql
.getLength() && isWhitespace(sql
[i
]) ; i
++ );
365 // the second part of the table name does not use quotes
372 // end quoted name, ok
378 if( isWhitespace( sql
[i
] ) )
380 // found the end of an unquoted name
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() );
394 static bool isOperator( char c
)
424 void splitSQL( const rtl::OString
& sql
, OStringVector
&vec
)
426 int length
= sql
.getLength();
429 bool singleQuote
= false;
430 bool doubleQuote
= false;
432 for( ; i
< length
; i
++ )
439 vec
.push_back( rtl::OString( &sql
[start
], i
-start
+1 ) );
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
454 vec
.push_back( rtl::OString( &sql
[start
], i
- start
+1 ) );
455 start
= i
+ 1; // leave single quotes !
463 vec
.push_back( rtl::OString( &sql
[start
], i
- start
) );
469 vec
.push_back( rtl::OString( &sql
[start
], i
- start
) );
476 vec
.push_back( rtl::OString( &sql
[start
] , i
- start
) );
478 // for( i = 0 ; i < vec.size() ; i ++ )
479 // printf( "%s!" , vec[i].getStr() );
484 void tokenizeSQL( const rtl::OString
& sql
, OStringVector
&vec
)
486 int length
= sql
.getLength();
489 bool singleQuote
= false;
490 bool doubleQuote
= false;
492 for( ; i
< length
; i
++ )
499 vec
.push_back( rtl::OString( &sql
[start
], i
-start
) );
504 else if( singleQuote
)
508 vec
.push_back( rtl::OString( &sql
[start
], i
- start
+1 ) );
509 start
= i
+ 1; // leave single quotes !
518 start
= i
+1; // skip double quotes !
523 start
= i
; // leave single quotes
525 else if( isWhitespace( c
) )
528 start
++; // skip additional whitespace
531 vec
.push_back( rtl::OString( &sql
[start
], i
- start
) );
535 else if( ',' == c
|| isOperator( c
) || '(' == c
|| ')' == c
)
538 vec
.push_back( rtl::OString( &sql
[start
], i
- start
) );
539 vec
.push_back( rtl::OString( &sql
[i
], 1 ) );
544 if( ( i
> start
&& sql
[start
] >= '0' && sql
[start
] <= '9' ) ||
545 ( i
== start
&& i
> 1 && isWhitespace( sql
[i
-1] ) ) )
547 // ignore, is a literal
552 vec
.push_back( rtl::OString( &sql
[start
], i
- start
) );
553 vec
.push_back( rtl::OString( RTL_CONSTASCII_STRINGPARAM( "." ) ) );
560 vec
.push_back( rtl::OString( &sql
[start
] , i
- start
) );
562 // for( i = 0 ; i < vec.size() ; i ++ )
563 // printf( "%s!" , vec[i].getStr() );
568 void splitConcatenatedIdentifier( const rtl::OUString
& source
, rtl::OUString
*first
, rtl::OUString
*second
)
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
++ )
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( "\\" ) );
605 buf
.appendAscii( RTL_CONSTASCII_STRINGPARAM( "\"" ) );
607 buf
.appendAscii( RTL_CONSTASCII_STRINGPARAM( "}" ) );
608 return buf
.makeStringAndClear();
614 com::sun::star::uno::Any
,
615 Allocator
< com::sun::star::uno::Any
>
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;
627 OUStringBuffer current
;
629 bool doubleQuotedValue
= false;
632 sal_Unicode c
= str
[i
];
633 sal_Unicode cnext
= str
[i
+1];
639 current
.append( cnext
);
644 doubleQuotedValue
= true; // signal, that there was an empty element
662 buf
.appendAscii( "error during array parsing, didn't expect a } at position " );
663 buf
.append( (sal_Int32
) i
);
664 buf
.appendAscii( " ('" );
666 buf
.appendAscii( "')" );
668 buf
.makeStringAndClear(),
669 Reference
< XInterface
> (), rtl::OUString(), 1, Any() );
673 if( current
.getLength() > 0 || doubleQuotedValue
)
674 elements
.push_back( makeAny( current
.makeStringAndClear() ) );
683 // if( current.getLength() != 0 )
685 // OUStringBuffer buf;
686 // buf.appendAscii( "error during array parsing, didn't expect a \" at position " );
688 // buf.append( " ('" );
689 // buf.append( str );
690 // buf.append( "')" );
691 // throw SDBCException(
692 // buf.makeStringAndClear(),
693 // Reference< XInterface > (), 1, Any() );
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
715 ret
= Sequence
< Any
> ( &elements
[0] , elements
.size() );
719 com::sun::star::uno::Sequence
< sal_Int32
> parseIntArray( const ::rtl::OUString
& str
)
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 ));
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(
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 "
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
);
756 map
[ xRow
->getInt(2) ] = xRow
->getString(1);
760 ::rtl::OString
extractSingleTableFromSelect( const OStringVector
&vec
)
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 ) )
779 if( token
< vec
.size() && 0 == rtl_str_shortenedCompareIgnoreAsciiCase_WithLength(
780 vec
[token
].pData
->buffer
, vec
[token
].pData
->length
, "only " , 4 , 4 ) )
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 );
794 buf
.append( vec
[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
] );
805 if( token
< vec
.size() )
807 if( '"' == vec
[token
][0] )
808 buf
.append( &(vec
[token
][1]) , vec
[token
].getLength() -2 );
810 buf
.append( vec
[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();
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();
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();
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
;
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() );
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() )
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
);
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( ")" ) );
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( ")" ) );
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
)
986 buf
.appendAscii( RTL_CONSTASCII_STRINGPARAM( "FOREIGN KEY( " ) );
989 Reference
< XColumnsSupplier
> columns( key
, UNO_QUERY
);
992 Reference
< XEnumerationAccess
> colEnumAccess( columns
->getColumns(), UNO_QUERY
);
993 if( colEnumAccess
.is() )
995 Reference
< XEnumeration
> colEnum
= colEnumAccess
->createEnumeration();
997 while(colEnum
.is() && colEnum
->hasMoreElements() )
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( ") " ));
1016 buf
.appendAscii( RTL_CONSTASCII_STRINGPARAM( "REFERENCES " ) );
1019 splitConcatenatedIdentifier( referencedTable
, &schema
, &tableName
);
1020 bufferQuoteQualifiedIdentifier(buf
, schema
, tableName
);
1023 Reference
< XEnumerationAccess
> colEnumAccess( columns
->getColumns(), UNO_QUERY
);
1024 if( colEnumAccess
.is() )
1026 buf
.appendAscii( RTL_CONSTASCII_STRINGPARAM( " (" ) );
1027 Reference
< XEnumeration
> colEnum(colEnumAccess
->createEnumeration());
1029 while(colEnum
.is() && colEnum
->hasMoreElements() )
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
)
1064 tokenizeSQL( lastQuery
, vec
);
1066 int nSize
= vec
.size();
1067 // printf( "1 %d\n", nSize );
1069 equalsIgnoreCase( vec
[0] , RTL_CONSTASCII_STRINGPARAM( "insert" ) ) &&
1070 equalsIgnoreCase( vec
[1] , RTL_CONSTASCII_STRINGPARAM( "into" ) ) )
1074 // printf( "1a\n" );
1075 // extract table name
1076 rtl::OString tableName
;
1077 if( equalsIgnoreCase( vec
[n
+1], RTL_CONSTASCII_STRINGPARAM( "." ) ) )
1080 tableName
+= vec
[n
+1];
1081 tableName
+= vec
[n
+2];
1089 OStringVector names
;
1091 if( equalsIgnoreCase( vec
[n
], RTL_CONSTASCII_STRINGPARAM( "(" ) ) )
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( "," ) ) )
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( "(" ) ) )
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(",") ) )
1127 rtl::OUString
querySingleValue(
1128 const com::sun::star::uno::Reference
< com::sun::star::sdbc::XConnection
> &connection
,
1129 const rtl::OUString
&query
)
1132 Reference
< XStatement
> stmt
= connection
->createStatement();
1133 DisposeGuard
guard( stmt
);
1134 Reference
< XResultSet
> rs
= stmt
->executeQuery( query
);
1135 Reference
< XRow
> xRow( rs
, UNO_QUERY
);
1137 ret
= xRow
->getString( 1 );
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
);
1156 case typelib_TypeClass_VOID
:
1157 _rxParameters
->setNull(_nColumnIndex
,com::sun::star::sdbc::DataType::VARCHAR
);
1160 case typelib_TypeClass_STRING
:
1161 _rxParameters
->setString(_nColumnIndex
, *(rtl::OUString
*)_rValue
.getValue());
1164 case typelib_TypeClass_BOOLEAN
:
1165 _rxParameters
->setBoolean(_nColumnIndex
, *(sal_Bool
*)_rValue
.getValue());
1168 case typelib_TypeClass_BYTE
:
1169 _rxParameters
->setByte(_nColumnIndex
, *(sal_Int8
*)_rValue
.getValue());
1172 case typelib_TypeClass_UNSIGNED_SHORT
:
1173 case typelib_TypeClass_SHORT
:
1174 _rxParameters
->setShort(_nColumnIndex
, *(sal_Int16
*)_rValue
.getValue());
1177 case typelib_TypeClass_CHAR
:
1178 _rxParameters
->setString(_nColumnIndex
, ::rtl::OUString((sal_Unicode
*)_rValue
.getValue(),1));
1181 case typelib_TypeClass_UNSIGNED_LONG
:
1182 case typelib_TypeClass_LONG
:
1183 _rxParameters
->setInt(_nColumnIndex
, *(sal_Int32
*)_rValue
.getValue());
1186 case typelib_TypeClass_FLOAT
:
1187 _rxParameters
->setFloat(_nColumnIndex
, *(float*)_rValue
.getValue());
1190 case typelib_TypeClass_DOUBLE
:
1191 _rxParameters
->setDouble(_nColumnIndex
, *(double*)_rValue
.getValue());
1194 case typelib_TypeClass_SEQUENCE
:
1195 if (_rValue
.getValueType() == ::getCppuType((const Sequence
< sal_Int8
> *)0))
1197 _rxParameters
->setBytes(_nColumnIndex
, *(Sequence
<sal_Int8
>*)_rValue
.getValue());
1200 bSuccessfullyReRouted
= sal_False
;
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());
1210 bSuccessfullyReRouted
= sal_False
;
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());
1225 bSuccessfullyReRouted
= sal_False
;
1229 return bSuccessfullyReRouted
;