41#include <rtl/strbuf.hxx>
42#include <rtl/ustrbuf.hxx>
45#include <com/sun/star/beans/XPropertySet.hpp>
46#include <com/sun/star/container/XEnumerationAccess.hpp>
47#include <com/sun/star/lang/XComponent.hpp>
48#include <com/sun/star/sdbc/SQLException.hpp>
49#include <com/sun/star/sdbc/XRow.hpp>
50#include <com/sun/star/sdbc/XParameters.hpp>
51#include <com/sun/star/sdbc/DataType.hpp>
52#include <com/sun/star/sdbc/KeyRule.hpp>
53#include <com/sun/star/sdbcx/KeyType.hpp>
54#include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
65using com::sun::star::lang::XComponent;
67using com::sun::star::sdbc::SQLException;
68using com::sun::star::sdbc::XStatement;
69using com::sun::star::sdbc::XConnection;
70using com::sun::star::sdbc::XPreparedStatement;
71using com::sun::star::sdbc::XParameters;
72using com::sun::star::sdbc::XResultSet;
73using com::sun::star::sdbc::XRow;
75using com::sun::star::sdbcx::XColumnsSupplier;
77using com::sun::star::uno::UNO_QUERY;
78using com::sun::star::uno::UNO_QUERY_THROW;
81using com::sun::star::uno::XInterface;
82using com::sun::star::uno::Any;
84using com::sun::star::container::XEnumeration;
85using com::sun::star::container::XEnumerationAccess;
92 return OUString::Concat(
a) +
"." + b;
96 OSL_ENSURE(settings,
"pgsql-sdbc: OUStringToOString got NULL settings");
108 OStringBuffer strbuf(
y.getLength() * 2 + 2 );
110 int len = PQescapeStringConn(settings->
pConnection,
const_cast<char*
>(strbuf.getStr()),
y.getStr() ,
y.getLength(), &error );
113 char *errstr = PQerrorMessage(settings->
pConnection);
125 strbuf.setLength( len );
128 buf.append( OStringToOUString( strbuf, RTL_TEXTENCODING_UTF8 ) );
152 buf.append(
"NULL" );
157 OSL_ENSURE(settings,
"pgsql-sdbc: bufferQuoteIdentifier got NULL settings");
160 char *cstr = PQescapeIdentifier(settings->
pConnection,
y.getStr(),
y.getLength());
161 if ( cstr ==
nullptr )
163 char *errstr = PQerrorMessage(settings->
pConnection);
171 buf.append( OStringToOUString( cstr, RTL_TEXTENCODING_UTF8 ) );
182 OUStringBuffer & buf, std::u16string_view schema, std::u16string_view table,
ConnectionSettings *settings )
190 OUStringBuffer & buf,
191 std::u16string_view schema,
192 std::u16string_view table,
193 std::u16string_view col,
208 descriptor->getPropertyValue(
name ) >>=
value;
216 descriptor->getPropertyValue(
name ) >>=
value;
224 descriptor->getPropertyValue(
name ) >>= ret;
241 catch( SQLException & )
254 ret = owner->getConnection();
259 ret = myowner->getConnection();
262 "PQSDBC: Couldn't retrieve connection from statement",
274DisposeGuard::~DisposeGuard()
304 catch( css::uno::Exception & )
315 return ' ' == c || 9 == c || 10 == c || 13 == c;
333 bool quote = (
sql[
i] ==
'"');
334 for(
i++ ;
i <
sql.size() ;
i ++ )
336 if( quote &&
sql[
i] ==
'"' )
409 bool singleQuote =
false;
410 bool doubleQuote =
false;
424 else if( singleQuote )
426 if(
'\'' == c && (
i+1) <
length &&
'\'' ==
sql[
i+1] )
469 bool singleQuote =
false;
470 bool doubleQuote =
false;
484 else if( singleQuote )
515 else if(
',' == c ||
isOperator( c ) ||
'(' == c ||
')' == c )
519 vec.push_back( OString( &
sql.getStr()[
i], 1 ) );
533 vec.push_back( OString(
"." ) );
550 std::vector< OString > vec;
556 *second = OStringToOUString( vec[0], RTL_TEXTENCODING_UTF8 );
559 *
first = OStringToOUString( vec[0], RTL_TEXTENCODING_UTF8 );
560 *second = OStringToOUString( vec[2], RTL_TEXTENCODING_UTF8 );
564 "pq_tools::splitConcatenatedIdentifier unexpected number of tokens in identifier: "
571 OUStringBuffer buf(128);
572 int len = seq.getLength();
574 for(
int i = 0 ;
i < len ;
i ++ )
581 int strLength = element.getLength();
583 for(
int j = 0 ; j < strLength ; j ++ )
586 if( c ==
'\\' || c ==
'"' || c ==
'{' || c ==
'}' )
595 return buf.makeStringAndClear();
601 size_t len = str.size();
602 bool doubleQuote =
false;
606 OUStringBuffer current;
607 std::vector<Any> elements;
608 bool doubleQuotedValue =
false;
618 current.append( cnext );
623 doubleQuotedValue =
true;
640 "error during array parsing, didn't expect a } at position "
641 + OUString::number(
i) +
" ('" + str +
"')",
646 if( !current.isEmpty() || doubleQuotedValue )
647 elements.push_back(
Any( current.makeStringAndClear() ) );
673 else if(
',' == c && brackets == 1)
675 doubleQuotedValue =
false;
676 elements.push_back(
Any( current.makeStringAndClear() ) );
694 std::vector<sal_Int32> vec;
696 for( sal_Int32
i = str.indexOf(
' ' ) ;
i != -1 ;
i = str.indexOf(
' ',
start) )
698 vec.push_back( rtl_ustr_toInt32( &str.pData->buffer[
start], 10 ) );
702 vec.push_back( rtl_ustr_toInt32( &str.pData->buffer[
start], 10 ) );
710 const OUString &schema,
711 const OUString &table )
714 "SELECT attname,attnum "
716 "INNER JOIN pg_class ON attrelid = pg_class.oid "
717 "INNER JOIN pg_namespace ON pg_class.relnamespace = pg_namespace.oid "
718 "WHERE relname=? AND nspname=?" );
721 paras->setString( 1 ,
table );
722 paras->setString( 2 , schema );
728 map[ xRow->getInt(2) ] = xRow->getString(1);
736 if( 0 == rtl_str_shortenedCompareIgnoreAsciiCase_WithLength(
737 vec[0].
pData->buffer, vec[0].pData->length,
"select" , 6 , 6 ) )
741 for( token = 1; token < vec.size() ; token ++ )
743 if( 0 == rtl_str_shortenedCompareIgnoreAsciiCase_WithLength(
744 vec[token].getStr(), vec[token].
getLength(),
"from" , 4 , 4 ) )
752 if( token < vec.size() && 0 == rtl_str_shortenedCompareIgnoreAsciiCase_WithLength(
753 vec[token].
pData->buffer, vec[token].pData->length,
"only " , 4 , 4 ) )
758 if( token < vec.size() && vec[token] !=
"(" )
761 OStringBuffer buf(128);
762 if(
'"' == vec[token][0] )
763 buf.append( &(vec[token].getStr()[1]) , vec[token].
getLength() -2 );
765 buf.append( vec[token] );
768 if( token < vec.size() )
770 if( vec[token] ==
"." )
772 buf.append( vec[token] );
774 if( token < vec.size() )
776 if(
'"' == vec[token][0] )
777 buf.append( &(vec[token].getStr()[1]) , vec[token].
getLength() -2 );
779 buf.append( vec[token] );
785 ret = buf.makeStringAndClear();
788 if( token < vec.size() && vec[token] ==
"(" )
795 if( token < vec.size() )
797 if( 0 == rtl_str_shortenedCompareIgnoreAsciiCase_WithLength(
798 vec[token].
pData->buffer, vec[token].pData->length,
"as" , 2, 2 ) )
804 if( token < vec.size() )
806 if( vec[token] ==
"," )
813 static const char * forbiddenKeywords[] =
814 {
"join",
"natural",
"outer",
"inner",
"left",
"right",
"full" ,
nullptr };
815 for(
int i = 0 ; forbiddenKeywords[
i] ;
i ++ )
817 size_t nKeywordLen = strlen(forbiddenKeywords[
i]);
818 if( 0 == rtl_str_shortenedCompareIgnoreAsciiCase_WithLength(
819 vec[token].
pData->buffer, vec[token].pData->length,
820 forbiddenKeywords[
i], nKeywordLen,
838 return (PQserverVersion( settings->
pConnection ) < 80000)?
839 OUString(
"pg_attrdef.adsrc"):
840 OUString(
"pg_get_expr(pg_attrdef.adbin, pg_attrdef.adrelid, true)");
845 css::uno::Sequence< sal_Int32 > ret;
846 const sal_Int32 strlen = str.getLength();
847 if( str.getLength() > 1 )
853 c = str.iterateCodePoints(&
start);
856 if (
start == strlen)
863 c = str.iterateCodePoints(&
start);
866 if (
start == strlen)
872 std::vector< sal_Int32 > vec;
875 OUStringBuffer digits;
880 if (
start == strlen)
882 c=str.iterateCodePoints(&
start);
888 if (
start == strlen)
890 digits.append(OUString(&c, 1));
891 c = str.iterateCodePoints(&
start);
898 if (
start == strlen)
900 c = str.iterateCodePoints(&
start);
904 if ( str.iterateCodePoints(&
start) != L
',' )
906 if (
start == strlen)
910 assert(vec.size() > 0);
911 ret = css::uno::Sequence< sal_Int32 > ( vec.data() , vec.size() );
921 auto retRange = asNonConstRange(ret);
922 for(
int i = 0;
i < intArray.getLength() ;
i ++ )
924 Int2StringMap::const_iterator ii =
map.find( intArray[
i] );
925 if( ii !=
map.end() )
926 retRange[
i] = ii->second;
942 case css::sdbc::DataType::VARBINARY:
943 case css::sdbc::DataType::VARCHAR:
944 case css::sdbc::DataType::CHAR:
949 case css::sdbc::DataType::DECIMAL:
950 case css::sdbc::DataType::NUMERIC:
963 return typeName.makeStringAndClear();
969 if( css::sdbc::KeyRule::CASCADE == keyType )
971 buf.append(
"CASCADE " );
973 else if( css::sdbc::KeyRule::RESTRICT == keyType )
975 buf.append(
"RESTRICT " );
977 else if( css::sdbc::KeyRule::SET_DEFAULT == keyType )
979 buf.append(
"SET DEFAULT " );
981 else if( css::sdbc::KeyRule::SET_NULL == keyType )
983 buf.append(
"SET NULL " );
987 buf.append(
"NO ACTION " );
999 bool foreign =
false;
1000 if(
type == css::sdbcx::KeyType::UNIQUE )
1002 buf.append(
"UNIQUE( " );
1004 else if(
type == css::sdbcx::KeyType::PRIMARY )
1006 buf.append(
"PRIMARY KEY( " );
1008 else if(
type == css::sdbcx::KeyType::FOREIGN )
1011 buf.append(
"FOREIGN KEY( " );
1018 if( colEnumAccess.is() )
1022 while(colEnum.is() && colEnum->hasMoreElements() )
1042 buf.append(
"REFERENCES " );
1050 if( colEnumAccess.is() )
1055 while(colEnum.is() && colEnum->hasMoreElements() )
1073 buf.append(
"ON DELETE " );
1075 buf.append(
" ON UPDATE " );
1082 std::vector< OString > vec;
1085 int nSize = vec.size();
1105 std::vector< OString> names;
1111 names.push_back( vec[
n] );
1127 for (
auto&
name : names)
1142 const css::uno::Reference< css::sdbc::XConnection > &connection,
1143 const OUString &query )
1151 ret = xRow->getString( 1 );
1158 const sal_Int32 _nColumnIndex,
const Any& _rValue)
1160 bool bSuccessfullyReRouted =
true;
1161 switch (_rValue.getValueTypeClass())
1163 case css::uno::TypeClass_HYPER:
1165 _rxParameters->setLong( _nColumnIndex, sal_Int64(0) );
1169 case css::uno::TypeClass_VOID:
1170 _rxParameters->setNull(_nColumnIndex,css::sdbc::DataType::VARCHAR);
1173 case css::uno::TypeClass_STRING:
1174 _rxParameters->setString(_nColumnIndex, *o3tl::forceAccess<OUString>(_rValue));
1177 case css::uno::TypeClass_BOOLEAN:
1178 _rxParameters->setBoolean(_nColumnIndex, *o3tl::forceAccess<bool>(_rValue));
1181 case css::uno::TypeClass_BYTE:
1182 _rxParameters->setByte(_nColumnIndex, *o3tl::forceAccess<sal_Int8>(_rValue));
1185 case css::uno::TypeClass_UNSIGNED_SHORT:
1186 case css::uno::TypeClass_SHORT:
1187 _rxParameters->setShort(_nColumnIndex, *o3tl::forceAccess<sal_Int16>(_rValue));
1190 case css::uno::TypeClass_CHAR:
1191 _rxParameters->setString(_nColumnIndex, OUString(*o3tl::forceAccess<sal_Unicode>(_rValue)));
1194 case css::uno::TypeClass_UNSIGNED_LONG:
1195 case css::uno::TypeClass_LONG:
1196 _rxParameters->setInt(_nColumnIndex, *o3tl::forceAccess<sal_Int32>(_rValue));
1199 case css::uno::TypeClass_FLOAT:
1200 _rxParameters->setFloat(_nColumnIndex, *o3tl::forceAccess<float>(_rValue));
1203 case css::uno::TypeClass_DOUBLE:
1204 _rxParameters->setDouble(_nColumnIndex, *o3tl::forceAccess<double>(_rValue));
1207 case css::uno::TypeClass_SEQUENCE:
1210 _rxParameters->setBytes(_nColumnIndex, *s);
1213 bSuccessfullyReRouted =
false;
1215 case css::uno::TypeClass_STRUCT:
1216 if (
auto s1 = o3tl::tryAccess<css::util::DateTime>(_rValue))
1217 _rxParameters->setTimestamp(_nColumnIndex, *s1);
1218 else if (
auto s2 = o3tl::tryAccess<css::util::Date>(_rValue))
1219 _rxParameters->setDate(_nColumnIndex, *s2);
1220 else if (
auto s3 = o3tl::tryAccess<css::util::Time>(_rValue))
1221 _rxParameters->setTime(_nColumnIndex, *s3);
1223 bSuccessfullyReRouted =
false;
1226 case css::uno::TypeClass_INTERFACE:
1232 _rxParameters->setBinaryStream(_nColumnIndex,
xStream,
xStream->available());
1238 bSuccessfullyReRouted =
false;
1242 return bSuccessfullyReRouted;
DisposeGuard(const css::uno::Reference< css::uno::XInterface > &r)
css::uno::Reference< css::sdbc::XStatement > m_stmt
void executeUpdate(const OUString &sql)
#define SAL_WARN(area, stream)
std::unique_ptr< sal_Int32[]> pData
RttiCompleteObjectLocator col
double getLength(const B2DPolygon &rCandidate)
class SAL_NO_VTABLE XPropertySet
constexpr OUStringLiteral first
std::basic_string_view< charT, traits > trim(std::basic_string_view< charT, traits > str)
bool equalsIgnoreAsciiCase(std::u16string_view s1, std::u16string_view s2)
sal_Int32 toInt32(std::u16string_view str, sal_Int16 radix=10)
bool matchIgnoreAsciiCase(std::u16string_view s1, std::u16string_view s2, sal_Int32 fromIndex=0)
std::enable_if<!(detail::IsDerivedReference< T >::value||detail::IsUnoSequenceType< T >::value||std::is_base_of< css::uno::XInterface, T >::value), typenamedetail::Optional< T >::type >::type tryAccess(css::uno::Any const &any)
OString extractSingleTableFromSelect(const std::vector< OString > &vec)
bool implSetObject(const Reference< XParameters > &_rxParameters, const sal_Int32 _nColumnIndex, const Any &_rValue)
void bufferQuoteConstant(OUStringBuffer &buf, std::u16string_view value, ConnectionSettings *settings)
static void ibufferQuoteIdentifier(OUStringBuffer &buf, std::u16string_view toQuote, ConnectionSettings *settings)
static OString iOUStringToOString(std::u16string_view str, ConnectionSettings const *settings)
bool isWhitespace(sal_Unicode c)
void bufferQuoteQualifiedIdentifier(OUStringBuffer &buf, std::u16string_view schema, std::u16string_view table, ConnectionSettings *settings)
OUString extractTableFromInsert(std::u16string_view sql)
OUString concatQualified(std::u16string_view a, std::u16string_view b)
OUString array2String(const css::uno::Sequence< Any > &seq)
sal_Int32 extractIntProperty(const Reference< XPropertySet > &descriptor, const OUString &name)
css::uno::Sequence< sal_Int32 > string2intarray(const OUString &str)
std::vector< sal_Int32 > parseIntArray(const OUString &str)
OUString sqltype2string(const Reference< XPropertySet > &desc)
void tokenizeSQL(const OString &sql, std::vector< OString > &vec)
void bufferQuoteAnyConstant(OUStringBuffer &buf, const Any &val, ConnectionSettings *settings)
void extractNameValuePairsFromInsert(String2StringMap &map, const OString &lastQuery)
OUString querySingleValue(const css::uno::Reference< css::sdbc::XConnection > &connection, const OUString &query)
OUString extractStringProperty(const Reference< XPropertySet > &descriptor, const OUString &name)
static bool isOperator(char c)
std::unordered_map< OString, OString > String2StringMap
static void ibufferQuoteConstant(OUStringBuffer &buf, std::u16string_view value, ConnectionSettings *settings)
void splitConcatenatedIdentifier(std::u16string_view source, OUString *first, OUString *second)
void disposeNoThrow(const css::uno::Reference< css::uno::XInterface > &r)
OString OUStringToOString(std::u16string_view str, ConnectionSettings const *settings)
OUString getColExprForDefaultSettingVal(ConnectionSettings const *settings)
Sequence< OUString > convertMappedIntArray2StringArray(const Int2StringMap &map, const Sequence< sal_Int32 > &intArray)
Reference< XConnection > extractConnectionFromStatement(const Reference< XInterface > &stmt)
void bufferQuoteIdentifier(OUStringBuffer &buf, std::u16string_view toQuote, ConnectionSettings *settings)
void bufferEscapeConstant(OUStringBuffer &buf, std::u16string_view value, ConnectionSettings *settings)
void splitSQL(const OString &sql, std::vector< OString > &vec)
std::unordered_map< sal_Int32, OUString > Int2StringMap
static void keyType2String(OUStringBuffer &buf, sal_Int32 keyType)
void bufferKey2TableConstraint(OUStringBuffer &buf, const Reference< XPropertySet > &key, ConnectionSettings *settings)
bool extractBoolProperty(const Reference< XPropertySet > &descriptor, const OUString &name)
void disposeObject(const css::uno::Reference< css::uno::XInterface > &r)
std::vector< Any > parseArray(std::u16string_view str)
void fillAttnum2attnameMap(Int2StringMap &map, const Reference< css::sdbc::XConnection > &conn, const OUString &schema, const OUString &table)
store_handle_type *SAL_CALL query(OStoreObject *pHandle, store_handle_type *)
std::map< OUString, rtl::Reference< Entity > > map
static const rtl_TextEncoding encoding
OUString REFERENCED_TABLE