/**************************************************************
 * 
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 * 
 *************************************************************/



// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_connectivity.hxx"
#include "connectivity/dbtools.hxx"
#include "connectivity/dbconversion.hxx"
#include "connectivity/dbcharset.hxx"
#include "connectivity/SQLStatementHelper.hxx"
#include <unotools/confignode.hxx>
#include "resource/sharedresources.hxx"
#include "resource/common_res.hrc"
#include <com/sun/star/sdbc/XConnection.hpp>
#include <com/sun/star/sdbc/ColumnValue.hpp>
#include <com/sun/star/sdbc/DataType.hpp>
#include <com/sun/star/sdbc/XRow.hpp>
#include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp>
#include <com/sun/star/sdbcx/XKeysSupplier.hpp>
#include <com/sun/star/sdbc/XDriverAccess.hpp>
#include <com/sun/star/sdbcx/XDataDefinitionSupplier.hpp>
#include <com/sun/star/sdbcx/Privilege.hpp>
#include <com/sun/star/container/XIndexAccess.hpp>
#include <com/sun/star/container/XEnumerationAccess.hpp>
#include <com/sun/star/sdbc/KeyRule.hpp>
#include <com/sun/star/sdbcx/KeyType.hpp>
#include "TConnection.hxx"
#include "connectivity/sdbcx/VColumn.hxx"
#include <com/sun/star/frame/XModel.hpp>
#include <com/sun/star/container/XChild.hpp>

#include <tools/diagnose_ex.h>
#include <unotools/sharedunocomponent.hxx>
#include <comphelper/configurationhelper.hxx>

//.........................................................................
namespace dbtools
{
//.........................................................................
	using namespace ::com::sun::star::uno;
	using namespace ::com::sun::star::beans;
	using namespace ::com::sun::star::sdbc;
	using namespace ::com::sun::star::sdbcx;
	using namespace ::com::sun::star::lang;
	using namespace ::com::sun::star::container;
	using namespace ::com::sun::star::frame;
	using namespace connectivity;
	using namespace comphelper;

::rtl::OUString createStandardColumnPart(const Reference< XPropertySet >& xColProp,const Reference< XConnection>& _xConnection,ISQLStatementHelper* _pHelper,const ::rtl::OUString& _sCreatePattern)
{

	Reference<XDatabaseMetaData> xMetaData = _xConnection->getMetaData();

	::dbtools::OPropertyMap& rPropMap = OMetaConnection::getPropMap();

	::rtl::OUString sTypeName;
	sal_Int32		nDataType	= 0;
	sal_Int32		nPrecision	= 0;
	sal_Int32		nScale		= 0;

	const ::rtl::OUString sQuoteString = xMetaData->getIdentifierQuoteString();
	::rtl::OUStringBuffer aSql = ::dbtools::quoteName(sQuoteString,::comphelper::getString(xColProp->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_NAME))));

	aSql.appendAscii(" ");

	nDataType = nPrecision = nScale = 0;
	sal_Bool bIsAutoIncrement = sal_False;
	xColProp->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_TYPENAME))			>>= sTypeName;
	xColProp->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_TYPE))				>>= nDataType;
	xColProp->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_PRECISION))			>>= nPrecision;
	xColProp->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_SCALE))				>>= nScale;
	xColProp->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_ISAUTOINCREMENT))	>>= bIsAutoIncrement;

	// check if the user enter a specific string to create autoincrement values
	::rtl::OUString sAutoIncrementValue;
	Reference<XPropertySetInfo> xPropInfo = xColProp->getPropertySetInfo();
	if ( xPropInfo.is() && xPropInfo->hasPropertyByName(rPropMap.getNameByIndex(PROPERTY_ID_AUTOINCREMENTCREATION)) )
		xColProp->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_AUTOINCREMENTCREATION)) >>= sAutoIncrementValue;
	// look if we have to use precisions
	sal_Bool bUseLiteral = sal_False;
	::rtl::OUString sPreFix,sPostFix,sCreateParams;
	{
		Reference<XResultSet> xRes = xMetaData->getTypeInfo();
		if(xRes.is())
		{
			Reference<XRow> xRow(xRes,UNO_QUERY);
			while(xRes->next())
			{
				::rtl::OUString sTypeName2Cmp = xRow->getString(1);
				sal_Int32 nType = xRow->getShort(2);
				sPreFix = xRow->getString (4);
				sPostFix = xRow->getString (5);
				sCreateParams = xRow->getString(6);
				// first identical type will be used if typename is empty
				if ( !sTypeName.getLength() && nType == nDataType )
					sTypeName = sTypeName2Cmp;

				if( sTypeName.equalsIgnoreAsciiCase(sTypeName2Cmp) && nType == nDataType && sCreateParams.getLength() && !xRow->wasNull())
				{
					bUseLiteral = sal_True;
					break;
				}
			}
		}
	}

	sal_Int32 nIndex = 0;
	if ( sAutoIncrementValue.getLength() && (nIndex = sTypeName.indexOf(sAutoIncrementValue)) != -1 )
	{
		sTypeName = sTypeName.replaceAt(nIndex,sTypeName.getLength() - nIndex,::rtl::OUString());
	}

	if ( (nPrecision > 0 || nScale > 0) && bUseLiteral )
	{
		sal_Int32 nParenPos = sTypeName.indexOf('(');
		if ( nParenPos == -1 )
		{
			aSql.append(sTypeName);
			aSql.appendAscii("(");
		}
		else
		{
			aSql.append(sTypeName.copy(0,++nParenPos));
		}

        if ( nPrecision > 0 && nDataType != DataType::TIMESTAMP )
        {
		    aSql.append(nPrecision);
            if ( (nScale > 0) || (_sCreatePattern.getLength() && sCreateParams.indexOf(_sCreatePattern) != -1) )
                aSql.appendAscii(",");
        }
		if ( (nScale > 0) || (_sCreatePattern.getLength() && sCreateParams.indexOf(_sCreatePattern) != -1 ) || nDataType == DataType::TIMESTAMP )
			aSql.append(nScale);

        if ( nParenPos == -1 )
			aSql.appendAscii(")");
		else
		{
			nParenPos = sTypeName.indexOf(')',nParenPos);
			aSql.append(sTypeName.copy(nParenPos));
		}
	}
	else
		aSql.append(sTypeName); // simply add the type name

	::rtl::OUString aDefault = ::comphelper::getString(xColProp->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_DEFAULTVALUE)));
	if ( aDefault.getLength() )
    {
		aSql.append(::rtl::OUString::createFromAscii(" DEFAULT ")); 
        aSql.append(sPreFix);
        aSql.append(aDefault);
        aSql.append(sPostFix);
    } // if ( aDefault.getLength() )

	if(::comphelper::getINT32(xColProp->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_ISNULLABLE))) == ColumnValue::NO_NULLS)
		aSql.append(::rtl::OUString::createFromAscii(" NOT NULL"));

	if ( bIsAutoIncrement && sAutoIncrementValue.getLength())
	{
		aSql.appendAscii(" ");
		aSql.append(sAutoIncrementValue);
	}

    if ( _pHelper )
        _pHelper->addComment(xColProp,aSql);

	return aSql.makeStringAndClear();
}
// -----------------------------------------------------------------------------

::rtl::OUString createStandardCreateStatement(const Reference< XPropertySet >& descriptor,const Reference< XConnection>& _xConnection,ISQLStatementHelper* _pHelper,const ::rtl::OUString& _sCreatePattern)
{
	::rtl::OUStringBuffer aSql	= ::rtl::OUString::createFromAscii("CREATE TABLE ");
	::rtl::OUString sCatalog,sSchema,sTable,sComposedName;

	Reference<XDatabaseMetaData> xMetaData = _xConnection->getMetaData();
	::dbtools::OPropertyMap& rPropMap = OMetaConnection::getPropMap();

	descriptor->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_CATALOGNAME))	>>= sCatalog;
	descriptor->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_SCHEMANAME))	>>= sSchema;
	descriptor->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_NAME))			>>= sTable;

	sComposedName = ::dbtools::composeTableName( xMetaData, sCatalog, sSchema, sTable, sal_True, ::dbtools::eInTableDefinitions );
	if ( !sComposedName.getLength() )
		::dbtools::throwFunctionSequenceException(_xConnection);

	aSql.append(sComposedName);
    aSql.append(::rtl::OUString::createFromAscii(" ("));

	// columns
	Reference<XColumnsSupplier> xColumnSup(descriptor,UNO_QUERY);
	Reference<XIndexAccess> xColumns(xColumnSup->getColumns(),UNO_QUERY);
	// check if there are columns
	if(!xColumns.is() || !xColumns->getCount()) 
		::dbtools::throwFunctionSequenceException(_xConnection);

	Reference< XPropertySet > xColProp;

	sal_Int32 nCount = xColumns->getCount();
	for(sal_Int32 i=0;i<nCount;++i)
	{
		if ( (xColumns->getByIndex(i) >>= xColProp) && xColProp.is() )
		{
			aSql.append(createStandardColumnPart(xColProp,_xConnection,_pHelper,_sCreatePattern));
			aSql.appendAscii(",");
		}
	}
	return aSql.makeStringAndClear();
}
namespace
{
	::rtl::OUString generateColumnNames(const Reference<XIndexAccess>& _xColumns,const Reference<XDatabaseMetaData>& _xMetaData)
	{
		::dbtools::OPropertyMap& rPropMap = OMetaConnection::getPropMap();
		static const ::rtl::OUString sComma(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(",")));
		
		const ::rtl::OUString sQuote(_xMetaData->getIdentifierQuoteString());
		::rtl::OUString sSql = ::rtl::OUString::createFromAscii(" (");
		Reference< XPropertySet > xColProp;

		sal_Int32 nColCount  = _xColumns->getCount();
		for(sal_Int32 i=0;i<nColCount;++i)
		{
			if ( (_xColumns->getByIndex(i) >>= xColProp) && xColProp.is() )
				sSql += ::dbtools::quoteName(sQuote,::comphelper::getString(xColProp->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_NAME))))
						+ sComma;
		}

		if ( nColCount )
			sSql = sSql.replaceAt(sSql.getLength()-1,1,::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(")")));
		return sSql;
	}
}
// -----------------------------------------------------------------------------
::rtl::OUString createStandardKeyStatement(const Reference< XPropertySet >& descriptor,const Reference< XConnection>& _xConnection)
{
	Reference<XDatabaseMetaData> xMetaData = _xConnection->getMetaData();
	::dbtools::OPropertyMap& rPropMap = OMetaConnection::getPropMap();

	::rtl::OUStringBuffer aSql;
	// keys
	Reference<XKeysSupplier> xKeySup(descriptor,UNO_QUERY);
	Reference<XIndexAccess> xKeys = xKeySup->getKeys();
	if ( xKeys.is() )
	{
		Reference< XPropertySet > xColProp;
		Reference<XIndexAccess> xColumns;
		Reference<XColumnsSupplier> xColumnSup;
		::rtl::OUString sCatalog,sSchema,sTable,sComposedName;
		sal_Bool bPKey = sal_False;
		for(sal_Int32 i=0;i<xKeys->getCount();++i)
		{
			if ( (xKeys->getByIndex(i) >>= xColProp) && xColProp.is() )
			{

				sal_Int32 nKeyType		= ::comphelper::getINT32(xColProp->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_TYPE)));

				if ( nKeyType == KeyType::PRIMARY )
				{
					if(bPKey)
						::dbtools::throwFunctionSequenceException(_xConnection);

					bPKey = sal_True;
					xColumnSup = Reference<XColumnsSupplier>(xColProp,UNO_QUERY);
					xColumns = Reference<XIndexAccess>(xColumnSup->getColumns(),UNO_QUERY);
					if(!xColumns.is() || !xColumns->getCount())
						::dbtools::throwFunctionSequenceException(_xConnection);

					const ::rtl::OUString sQuote	 = xMetaData->getIdentifierQuoteString();
					aSql.append(::rtl::OUString::createFromAscii(" PRIMARY KEY "));
					aSql.append(generateColumnNames(xColumns,xMetaData));
				}
				else if(nKeyType == KeyType::UNIQUE)
				{
					xColumnSup = Reference<XColumnsSupplier>(xColProp,UNO_QUERY);
					xColumns = Reference<XIndexAccess>(xColumnSup->getColumns(),UNO_QUERY);
					if(!xColumns.is() || !xColumns->getCount())
						::dbtools::throwFunctionSequenceException(_xConnection);

					const ::rtl::OUString sQuote	 = xMetaData->getIdentifierQuoteString();
					aSql.append(::rtl::OUString::createFromAscii(" UNIQUE "));
					aSql.append(generateColumnNames(xColumns,xMetaData));
				}
				else if(nKeyType == KeyType::FOREIGN)
				{
					sal_Int32 nDeleteRule	= getINT32(xColProp->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_DELETERULE)));

					xColumnSup = Reference<XColumnsSupplier>(xColProp,UNO_QUERY);
					xColumns = Reference<XIndexAccess>(xColumnSup->getColumns(),UNO_QUERY);
					if(!xColumns.is() || !xColumns->getCount())
						::dbtools::throwFunctionSequenceException(_xConnection);

					aSql.append(::rtl::OUString::createFromAscii(" FOREIGN KEY "));
					::rtl::OUString sRefTable = getString(xColProp->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_REFERENCEDTABLE)));
					::dbtools::qualifiedNameComponents(xMetaData,
														sRefTable,
														sCatalog, 
														sSchema, 
														sTable,
														::dbtools::eInDataManipulation);
					sComposedName = ::dbtools::composeTableName( xMetaData, sCatalog, sSchema, sTable, sal_True, ::dbtools::eInTableDefinitions );
					

					if ( !sComposedName.getLength() )
						::dbtools::throwFunctionSequenceException(_xConnection);

					aSql.append(generateColumnNames(xColumns,xMetaData));

					switch(nDeleteRule)
					{
						case KeyRule::CASCADE:
							aSql.append(::rtl::OUString::createFromAscii(" ON DELETE CASCADE "));
							break;
						case KeyRule::RESTRICT:
							aSql.append(::rtl::OUString::createFromAscii(" ON DELETE RESTRICT "));
							break;
						case KeyRule::SET_NULL:
							aSql.append(::rtl::OUString::createFromAscii(" ON DELETE SET NULL "));
							break;
						case KeyRule::SET_DEFAULT:
							aSql.append(::rtl::OUString::createFromAscii(" ON DELETE SET DEFAULT "));
							break;
						default:
							;
					}
				}
			}
		}
	}

	if ( aSql.getLength() )
	{
		if ( aSql.charAt(aSql.getLength()-1) == ',' )
			aSql.setCharAt(aSql.getLength()-1,')');
		else
			aSql.appendAscii(")");
	}

	return aSql.makeStringAndClear();

}
// -----------------------------------------------------------------------------
::rtl::OUString createSqlCreateTableStatement(	const Reference< XPropertySet >& descriptor,
												const Reference< XConnection>& _xConnection,
                                                ISQLStatementHelper* _pHelper,
                                                const ::rtl::OUString& _sCreatePattern)
{
	::rtl::OUString aSql = ::dbtools::createStandardCreateStatement(descriptor,_xConnection,_pHelper,_sCreatePattern);
	const ::rtl::OUString sKeyStmt = ::dbtools::createStandardKeyStatement(descriptor,_xConnection);
	if ( sKeyStmt.getLength() )
		aSql += sKeyStmt;
	else
	{
		if ( aSql.lastIndexOf(',') == (aSql.getLength()-1) )
			aSql = aSql.replaceAt(aSql.getLength()-1,1,::rtl::OUString::createFromAscii(")"));
		else
			aSql += ::rtl::OUString::createFromAscii(")");
	}
	return aSql;
}
namespace 
{
	Reference<XPropertySet> lcl_createSDBCXColumn(const Reference<XNameAccess>& _xPrimaryKeyColumns,
										  const Reference<XConnection>& _xConnection,
										  const Any& _aCatalog,
										  const ::rtl::OUString& _aSchema,
										  const ::rtl::OUString& _aTable,
										  const ::rtl::OUString& _rQueryName,
										  const ::rtl::OUString& _rName,
										  sal_Bool _bCase,
										  sal_Bool _bQueryForInfo,
										  sal_Bool _bIsAutoIncrement,
										  sal_Bool _bIsCurrency,
										  sal_Int32 _nDataType)
	{
		Reference<XPropertySet> xProp;
		Reference<XDatabaseMetaData> xMetaData = _xConnection->getMetaData();
		Reference< XResultSet > xResult = xMetaData->getColumns(_aCatalog, _aSchema, _aTable, _rQueryName);

		if ( xResult.is() )
		{
			UStringMixEqual aMixCompare(_bCase);
			Reference< XRow > xRow(xResult,UNO_QUERY);
			while( xResult->next() )
			{
				if ( aMixCompare(xRow->getString(4),_rName) )
				{
					sal_Int32		nField5	= xRow->getInt(5);
					::rtl::OUString aField6 = xRow->getString(6);
					sal_Int32		nField7 = xRow->getInt(7)
								,	nField9 = xRow->getInt(9)
								,	nField11= xRow->getInt(11);
					::rtl::OUString sField12 = xRow->getString(12),
                                    sField13 = xRow->getString(13);
					::comphelper::disposeComponent(xRow);

					sal_Bool bAutoIncrement = _bIsAutoIncrement
							,bIsCurrency	= _bIsCurrency;
					if ( _bQueryForInfo )
					{
						const ::rtl::OUString sQuote = xMetaData->getIdentifierQuoteString();
						::rtl::OUString sQuotedName  = ::dbtools::quoteName(sQuote,_rName);
						::rtl::OUString sComposedName;
						sComposedName = composeTableNameForSelect(_xConnection, getString( _aCatalog ), _aSchema, _aTable );

						ColumnInformationMap aInfo(_bCase);
						collectColumnInformation(_xConnection,sComposedName,sQuotedName,aInfo);
						ColumnInformationMap::iterator aIter = aInfo.begin();
						if ( aIter != aInfo.end() )
						{
							bAutoIncrement	= aIter->second.first.first;
							bIsCurrency		= aIter->second.first.second;
							if ( DataType::OTHER == nField5 )
								nField5		= aIter->second.second;
						}
					}
					else if ( DataType::OTHER == nField5 )
						nField5 = _nDataType;
					
					if ( nField11 != ColumnValue::NO_NULLS )
					{
						try
						{
                            if ( _xPrimaryKeyColumns.is() )
                            {
                                if ( _xPrimaryKeyColumns->hasByName(_rName) )
                                    nField11 = ColumnValue::NO_NULLS;
                                
                            }
                            else
                            {
							    Reference< XResultSet > xPKeys = xMetaData->getPrimaryKeys( _aCatalog, _aSchema, _aTable );
                                Reference< XRow > xPKeyRow( xPKeys, UNO_QUERY_THROW );
                                while( xPKeys->next() ) // there can be only one primary key
							    {
                                    ::rtl::OUString sKeyColumn = xPKeyRow->getString(4);
								    if ( aMixCompare(_rName,sKeyColumn) )
								    {
									    nField11 = ColumnValue::NO_NULLS;
									    break;
								    }
							    }
							}
                        }
						catch(SQLException&)
						{
                            OSL_ENSURE( false, "lcl_createSDBCXColumn: caught an exception!" );
						}
					}

					connectivity::sdbcx::OColumn* pRet = new connectivity::sdbcx::OColumn(_rName,
												aField6,
												sField13,
                                                sField12,
												nField11,
												nField7,
												nField9,
												nField5,
												bAutoIncrement,
												sal_False,
												bIsCurrency,
												_bCase);

					xProp = pRet;
					break;
				}
			}
		}

		return xProp;
	}
	//------------------------------------------------------------------
	Reference< XModel> lcl_getXModel(const Reference< XInterface>& _xIface)
	{
		Reference< XInterface > xParent = _xIface;
		Reference< XModel > xModel(xParent,UNO_QUERY);;
		while( xParent.is() && !xModel.is() )
		{
			Reference<XChild> xChild(xParent,UNO_QUERY);
			xParent.set(xChild.is() ? xChild->getParent() : Reference< XInterface >(),UNO_QUERY);
			xModel.set(xParent,UNO_QUERY);
		}
		return xModel;
	}
}
// -----------------------------------------------------------------------------
Reference<XPropertySet> createSDBCXColumn(const Reference<XPropertySet>& _xTable,
										  const Reference<XConnection>& _xConnection,
										  const ::rtl::OUString& _rName,
										  sal_Bool _bCase,
										  sal_Bool _bQueryForInfo,
										  sal_Bool _bIsAutoIncrement,
										  sal_Bool _bIsCurrency,
										  sal_Int32 _nDataType)
{
	Reference<XPropertySet> xProp;
	OSL_ENSURE(_xTable.is(),"Table is NULL!");
	if ( !_xTable.is() )
		return xProp;

	::dbtools::OPropertyMap& rPropMap = OMetaConnection::getPropMap();
	Reference<XDatabaseMetaData> xMetaData = _xConnection->getMetaData();
	Any aCatalog;
	aCatalog = _xTable->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_CATALOGNAME));

	::rtl::OUString aSchema, aTable;
	_xTable->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_SCHEMANAME))	>>= aSchema;
	_xTable->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_NAME))		>>= aTable;
  
    Reference<XNameAccess> xPrimaryKeyColumns = getPrimaryKeyColumns_throw(_xTable);

	xProp = lcl_createSDBCXColumn(xPrimaryKeyColumns,_xConnection,aCatalog, aSchema, aTable, _rName,_rName,_bCase,_bQueryForInfo,_bIsAutoIncrement,_bIsCurrency,_nDataType);
	if ( !xProp.is() )
	{
		xProp = lcl_createSDBCXColumn(xPrimaryKeyColumns,_xConnection,aCatalog, aSchema, aTable, ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("%")),_rName,_bCase,_bQueryForInfo,_bIsAutoIncrement,_bIsCurrency,_nDataType);
		if ( !xProp.is() )
			xProp = new connectivity::sdbcx::OColumn(_rName,
												::rtl::OUString(),::rtl::OUString(),::rtl::OUString(),
												ColumnValue::NULLABLE_UNKNOWN,
												0,
												0,
												DataType::VARCHAR,
												_bIsAutoIncrement,
												sal_False,
												_bIsCurrency,
												_bCase);

	}

	return xProp;
}

// -----------------------------------------------------------------------------
bool getBooleanDataSourceSetting( const Reference< XConnection >& _rxConnection, const sal_Char* _pAsciiSettingName )
{
    bool bValue( false );
    try
    {
		Reference< XPropertySet> xDataSourceProperties( findDataSource( _rxConnection ), UNO_QUERY );
        OSL_ENSURE( xDataSourceProperties.is(), "::dbtools::getBooleanDataSourceSetting: somebody is using this with a non-SDB-level connection!" );
		if ( xDataSourceProperties.is() )
		{
			Reference< XPropertySet > xSettings(
			    xDataSourceProperties->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Settings") ) ),
                UNO_QUERY_THROW
            );
            OSL_VERIFY( xSettings->getPropertyValue( ::rtl::OUString::createFromAscii( _pAsciiSettingName ) ) >>= bValue );
		}
    }
    catch( const Exception& )
    {
    	DBG_UNHANDLED_EXCEPTION();
    }
    return bValue;
}
// -------------------------------------------------------------------------
bool getDataSourceSetting( const Reference< XInterface >& _xChild, const ::rtl::OUString& _sAsciiSettingsName,
    Any& /* [out] */ _rSettingsValue )
{
    bool bIsPresent = false;
    try
    {
        const Reference< XPropertySet> xDataSourceProperties( findDataSource( _xChild ), UNO_QUERY );
        if ( !xDataSourceProperties.is() )
            return false;

        const Reference< XPropertySet > xSettings(
			    xDataSourceProperties->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Settings") ) ),
                UNO_QUERY_THROW
            );

        _rSettingsValue = xSettings->getPropertyValue( _sAsciiSettingsName );
        bIsPresent = true;
    }
    catch( const Exception& )
    {
	    bIsPresent = false;
    }
    return bIsPresent;
}
// -------------------------------------------------------------------------
bool getDataSourceSetting( const Reference< XInterface >& _rxDataSource, const sal_Char* _pAsciiSettingsName,
    Any& /* [out] */ _rSettingsValue )
{
    ::rtl::OUString sAsciiSettingsName = ::rtl::OUString::createFromAscii(_pAsciiSettingsName);
    return getDataSourceSetting( _rxDataSource, sAsciiSettingsName,_rSettingsValue );
}
// -----------------------------------------------------------------------------
sal_Bool isDataSourcePropertyEnabled(const Reference<XInterface>& _xProp,const ::rtl::OUString& _sProperty,sal_Bool _bDefault)
{
	sal_Bool bEnabled = _bDefault;
	try
	{
		Reference< XPropertySet> xProp(findDataSource(_xProp),UNO_QUERY);
		if ( xProp.is() )
		{
			Sequence< PropertyValue > aInfo;
			xProp->getPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Info"))) >>= aInfo;
			const PropertyValue* pValue =::std::find_if(aInfo.getConstArray(),
												aInfo.getConstArray() + aInfo.getLength(),
												::std::bind2nd(TPropertyValueEqualFunctor(),_sProperty));
			if ( pValue && pValue != (aInfo.getConstArray() + aInfo.getLength()) )
				pValue->Value >>= bEnabled;
		}
	}
	catch(SQLException&)
	{
        DBG_UNHANDLED_EXCEPTION();
	}
	return bEnabled;
}
// -----------------------------------------------------------------------------
Reference< XTablesSupplier> getDataDefinitionByURLAndConnection(
			const ::rtl::OUString& _rsUrl,
			const Reference< XConnection>& _xConnection,
			const Reference< XMultiServiceFactory>& _rxFactory)
{
	Reference< XTablesSupplier> xTablesSup;
    try
    {
	    Reference< XDriverAccess> xManager(
            _rxFactory->createInstance( ::rtl::OUString::createFromAscii("com.sun.star.sdbc.DriverManager") ),
            UNO_QUERY_THROW );
	    Reference< XDataDefinitionSupplier > xSupp( xManager->getDriverByURL( _rsUrl ), UNO_QUERY );
    	
	    if ( xSupp.is() )
        {
		    xTablesSup = xSupp->getDataDefinitionByConnection( _xConnection );
            OSL_ENSURE(xTablesSup.is(),"No table supplier!");
        }
    }
    catch( const Exception& )
    {
    	DBG_UNHANDLED_EXCEPTION();
    }
	return xTablesSup;
}

// -----------------------------------------------------------------------------
sal_Int32 getTablePrivileges(const Reference< XDatabaseMetaData>& _xMetaData,
							 const ::rtl::OUString& _sCatalog,
							 const ::rtl::OUString& _sSchema,
							 const ::rtl::OUString& _sTable)
{
	OSL_ENSURE(_xMetaData.is(),"Invalid metadata!");
	sal_Int32 nPrivileges = 0;
	try
	{
		Any aVal;
		if(_sCatalog.getLength())
			aVal <<= _sCatalog;
		Reference< XResultSet > xPrivileges = _xMetaData->getTablePrivileges(aVal, _sSchema, _sTable);
		Reference< XRow > xCurrentRow(xPrivileges, UNO_QUERY);

		if ( xCurrentRow.is() )
		{
			::rtl::OUString sUserWorkingFor = _xMetaData->getUserName();
			static const ::rtl::OUString sSELECT	= ::rtl::OUString::createFromAscii("SELECT");
			static const ::rtl::OUString sINSERT	= ::rtl::OUString::createFromAscii("INSERT");
			static const ::rtl::OUString sUPDATE	= ::rtl::OUString::createFromAscii("UPDATE");
			static const ::rtl::OUString sDELETE	= ::rtl::OUString::createFromAscii("DELETE");
			static const ::rtl::OUString sREAD		= ::rtl::OUString::createFromAscii("READ");
			static const ::rtl::OUString sCREATE	= ::rtl::OUString::createFromAscii("CREATE");
			static const ::rtl::OUString sALTER		= ::rtl::OUString::createFromAscii("ALTER");
			static const ::rtl::OUString sREFERENCE = ::rtl::OUString::createFromAscii("REFERENCE");
			static const ::rtl::OUString sDROP		= ::rtl::OUString::createFromAscii("DROP");
			// after creation the set is positioned before the first record, per definitionem
#ifdef DBG_UTIL
			Reference< XResultSetMetaDataSupplier > xSup(xPrivileges,UNO_QUERY);
			if ( xSup.is() )
			{
				Reference< XResultSetMetaData > xRsMetaData = xSup->getMetaData();
				if ( xRsMetaData.is() )
				{
					sal_Int32 nCount = xRsMetaData->getColumnCount();
					for (sal_Int32 i=1; i<=nCount; ++i)
					{
						::rtl::OUString sColumnName = xRsMetaData->getColumnName(i);
					}
				}
			}
#endif

			::rtl::OUString sPrivilege, sGrantee;
			while ( xPrivileges->next() )
			{
#ifdef DBG_UTIL
				::rtl::OUString sCat, sSchema, sName, sGrantor, sGrantable;
				sCat		= xCurrentRow->getString(1);
				sSchema		= xCurrentRow->getString(2);
				sName		= xCurrentRow->getString(3);
				sGrantor	= xCurrentRow->getString(4);
#endif
				sGrantee	= xCurrentRow->getString(5);
				sPrivilege	= xCurrentRow->getString(6);
#ifdef DBG_UTIL
				sGrantable	= xCurrentRow->getString(7);
#endif

				if (!sUserWorkingFor.equalsIgnoreAsciiCase(sGrantee))
					continue;

				if (sPrivilege.equalsIgnoreAsciiCase(sSELECT))
					nPrivileges |= Privilege::SELECT;
				else if (sPrivilege.equalsIgnoreAsciiCase(sINSERT))
					nPrivileges |= Privilege::INSERT;
				else if (sPrivilege.equalsIgnoreAsciiCase(sUPDATE))
					nPrivileges |= Privilege::UPDATE;
				else if (sPrivilege.equalsIgnoreAsciiCase(sDELETE))
					nPrivileges |= Privilege::DELETE;
				else if (sPrivilege.equalsIgnoreAsciiCase(sREAD))
					nPrivileges |= Privilege::READ;
				else if (sPrivilege.equalsIgnoreAsciiCase(sCREATE))
					nPrivileges |= Privilege::CREATE;
				else if (sPrivilege.equalsIgnoreAsciiCase(sALTER))
					nPrivileges |= Privilege::ALTER;
				else if (sPrivilege.equalsIgnoreAsciiCase(sREFERENCE))
					nPrivileges |= Privilege::REFERENCE;
				else if (sPrivilege.equalsIgnoreAsciiCase(sDROP))
					nPrivileges |= Privilege::DROP;
			}
		}
		disposeComponent(xPrivileges);
	}
	catch(const SQLException& e)
	{
		static ::rtl::OUString sNotSupportedState = ::rtl::OUString::createFromAscii("IM001");
		// some drivers don't support any privileges so we assume that we are allowed to do all we want :-)
		if(e.SQLState == sNotSupportedState)
			nPrivileges |=	Privilege::DROP			| 
							Privilege::REFERENCE	| 
							Privilege::ALTER		|
							Privilege::CREATE		|
							Privilege::READ			|
							Privilege::DELETE		|
							Privilege::UPDATE		|
							Privilege::INSERT		|
							Privilege::SELECT;
		else
			OSL_ENSURE(0,"Could not collect the privileges !");
	}
	return nPrivileges;
}
// -----------------------------------------------------------------------------
// we need some more information about the column
void collectColumnInformation(const Reference< XConnection>& _xConnection,
							  const ::rtl::OUString& _sComposedName,
							  const ::rtl::OUString& _rName,
							  ColumnInformationMap& _rInfo)
{
	static ::rtl::OUString STR_WHERE = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" WHERE "));

	::rtl::OUString sSelect = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("SELECT "));
	sSelect += _rName;
	sSelect += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" FROM "));
	sSelect += _sComposedName;
	sSelect += STR_WHERE;
	sSelect += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("0 = 1"));

	try
	{
        ::utl::SharedUNOComponent< XStatement > xStmt( _xConnection->createStatement() );
        Reference< XPropertySet > xStatementProps( xStmt, UNO_QUERY_THROW );
        xStatementProps->setPropertyValue( OMetaConnection::getPropMap().getNameByIndex( PROPERTY_ID_ESCAPEPROCESSING ), makeAny( (sal_Bool)sal_False ) );
		Reference< XResultSet > xResult( xStmt->executeQuery( sSelect ), UNO_QUERY_THROW );
        Reference< XResultSetMetaDataSupplier > xSuppMeta( xResult, UNO_QUERY_THROW );
		Reference< XResultSetMetaData > xMeta( xSuppMeta->getMetaData(), UNO_QUERY_THROW );

        sal_Int32 nCount = xMeta->getColumnCount();
        OSL_ENSURE( nCount != 0, "::dbtools::collectColumnInformation: result set has empty (column-less) meta data!" );
		for (sal_Int32 i=1; i <= nCount ; ++i)
		{
			_rInfo.insert(ColumnInformationMap::value_type(xMeta->getColumnName(i),
				ColumnInformation(TBoolPair(xMeta->isAutoIncrement(i),xMeta->isCurrency(i)),xMeta->getColumnType(i))));
		}
	}
    catch( const Exception& )
    {
    	DBG_UNHANDLED_EXCEPTION();
    }
}

// -----------------------------------------------------------------------------
bool isEmbeddedInDatabase( const Reference< XInterface >& _rxComponent, Reference< XConnection >& _rxActualConnection )
{
    bool bIsEmbedded = false;
	try
	{
		Reference< XModel > xModel = lcl_getXModel( _rxComponent );
    	
		if ( xModel.is() )
		{
			Sequence< PropertyValue > aArgs = xModel->getArgs();
			const PropertyValue* pIter = aArgs.getConstArray();
			const PropertyValue* pEnd  = pIter + aArgs.getLength();
			for(;pIter != pEnd;++pIter)
			{
				if ( pIter->Name.equalsAscii("ComponentData") )
				{
					Sequence<PropertyValue> aDocumentContext;
					pIter->Value >>= aDocumentContext;
					const PropertyValue* pContextIter = aDocumentContext.getConstArray();
					const PropertyValue* pContextEnd  = pContextIter + aDocumentContext.getLength();
					for(;pContextIter != pContextEnd;++pContextIter)
					{
						if (  pContextIter->Name.equalsAscii( "ActiveConnection" )
                        && ( pContextIter->Value >>= _rxActualConnection )
                        )
						{
                            bIsEmbedded = true;
							break;
						}
					}
					break;
				}
			}
		}
	}
	catch(Exception&)
	{
		// not intereseted in 
	}
    return bIsEmbedded;
}
// -----------------------------------------------------------------------------
namespace
{
    ::rtl::OUString lcl_getEncodingName( rtl_TextEncoding _eEncoding )
    {
        ::rtl::OUString sEncodingName;

        OCharsetMap aCharsets;
        OCharsetMap::CharsetIterator aEncodingPos = aCharsets.find( _eEncoding );
        OSL_ENSURE( aEncodingPos != aCharsets.end(), "lcl_getEncodingName: *which* encoding?" );
        if ( aEncodingPos != aCharsets.end() )
            sEncodingName = (*aEncodingPos).getIanaName();

        return sEncodingName;
    }
}

// -----------------------------------------------------------------------------
sal_Int32 DBTypeConversion::convertUnicodeString( const ::rtl::OUString& _rSource, ::rtl::OString& _rDest, rtl_TextEncoding _eEncoding ) SAL_THROW((com::sun::star::sdbc::SQLException))
{
    if ( !rtl_convertUStringToString( &_rDest.pData, _rSource.getStr(), _rSource.getLength(),
            _eEncoding,
            RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR |
            RTL_UNICODETOTEXT_FLAGS_UNDEFINED_REPLACE |
            RTL_UNICODETOTEXT_FLAGS_PRIVATE_MAPTO0 |
            RTL_UNICODETOTEXT_FLAGS_NOCOMPOSITE )
        )
    {
        SharedResources aResources;
        ::rtl::OUString sMessage = aResources.getResourceStringWithSubstitution( STR_CANNOT_CONVERT_STRING,
            "$string$", _rSource,
            "$charset$",  lcl_getEncodingName( _eEncoding )
        );
        
        throw SQLException(
            sMessage,
            NULL,
            ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "22018" ) ),
            22018,
            Any()
        );
    }

    return _rDest.getLength();
}

// -----------------------------------------------------------------------------
sal_Int32 DBTypeConversion::convertUnicodeStringToLength( const ::rtl::OUString& _rSource, ::rtl::OString&  _rDest,
   sal_Int32 _nMaxLen, rtl_TextEncoding _eEncoding ) SAL_THROW((SQLException))
{
    sal_Int32 nLen = convertUnicodeString( _rSource, _rDest, _eEncoding );
    if ( nLen > _nMaxLen )
    {
        SharedResources aResources;
        ::rtl::OUString sMessage = aResources.getResourceStringWithSubstitution( STR_STRING_LENGTH_EXCEEDED,
            "$string$", _rSource,
            "$maxlen$", ::rtl::OUString::valueOf( _nMaxLen ),
            "$charset$", lcl_getEncodingName( _eEncoding )
        );

        throw SQLException(
            sMessage,
            NULL,
            ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "22001" ) ),
            22001,
            Any()
        );
    }

   return nLen;
}
::rtl::OUString lcl_getReportEngines()
{
	static ::rtl::OUString s_sNodeName(RTL_CONSTASCII_USTRINGPARAM("org.openoffice.Office.DataAccess/ReportEngines"));
	return s_sNodeName;
}
// -----------------------------------------------------------------------------
::rtl::OUString lcl_getDefaultReportEngine()
{
	static ::rtl::OUString s_sNodeName(RTL_CONSTASCII_USTRINGPARAM("DefaultReportEngine"));
	return s_sNodeName;
}
// -----------------------------------------------------------------------------
::rtl::OUString lcl_getReportEngineNames()
{
	static ::rtl::OUString s_sNodeName(RTL_CONSTASCII_USTRINGPARAM("ReportEngineNames"));
	return s_sNodeName;
}
// -----------------------------------------------------------------------------
::rtl::OUString getDefaultReportEngineServiceName(const Reference< XMultiServiceFactory >& _rxORB)
{
	::utl::OConfigurationTreeRoot aReportEngines = ::utl::OConfigurationTreeRoot::createWithServiceFactory(
		_rxORB, lcl_getReportEngines(), -1, ::utl::OConfigurationTreeRoot::CM_READONLY);

	if ( aReportEngines.isValid() )
	{
		::rtl::OUString sDefaultReportEngineName;
		aReportEngines.getNodeValue(lcl_getDefaultReportEngine()) >>= sDefaultReportEngineName;
        if ( sDefaultReportEngineName.getLength() )
        {
		    ::utl::OConfigurationNode aReportEngineNames = aReportEngines.openNode(lcl_getReportEngineNames());
		    if ( aReportEngineNames.isValid() )
		    {
			    ::utl::OConfigurationNode aReportEngine = aReportEngineNames.openNode(sDefaultReportEngineName);
			    if ( aReportEngine.isValid() )
			    {
                    ::rtl::OUString sRet;
		            const static ::rtl::OUString s_sService(RTL_CONSTASCII_USTRINGPARAM("ServiceName"));
		            aReportEngine.getNodeValue(s_sService) >>= sRet;
				    return sRet;
			    }
		    }
        }
    	else
        	return ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.report.pentaho.SOReportJobFactory"));
	}
    else
        return ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.report.pentaho.SOReportJobFactory"));
	return ::rtl::OUString();
}
// -----------------------------------------------------------------------------
//.........................................................................
}	// namespace dbtools
//.........................................................................

