1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_connectivity.hxx"
26 #include <cppuhelper/typeprovider.hxx>
27 #include "adabas/BConnection.hxx"
28 #include "adabas/BDriver.hxx"
29 #include "adabas/BCatalog.hxx"
30 #include "odbc/OFunctions.hxx"
31 #include "odbc/OTools.hxx"
32 #ifndef _CONNECTIVITY_ODBC_ODATABASEMETADATA_HXX_
33 #include "adabas/BDatabaseMetaData.hxx"
34 #endif
35 #include "adabas/BStatement.hxx"
36 #include "adabas/BPreparedStatement.hxx"
37 #include <com/sun/star/lang/DisposedException.hpp>
38 #include <connectivity/dbcharset.hxx>
39 #include "connectivity/sqliterator.hxx"
40 #include <connectivity/sqlparse.hxx>
41 
42 #include <string.h>
43 
44 using namespace connectivity::adabas;
45 using namespace connectivity;
46 using namespace ::com::sun::star::uno;
47 using namespace ::com::sun::star::beans;
48 using namespace ::com::sun::star::sdbcx;
49 using namespace ::com::sun::star::sdbc;
50 using namespace ::com::sun::star::container;
51 using namespace ::com::sun::star::lang;
52 
53 
54 //------------------------------------------------------------------------------
55 namespace starlang	= ::com::sun::star::lang;
56 // --------------------------------------------------------------------------------
OAdabasConnection(const SQLHANDLE _pDriverHandle,connectivity::odbc::ODBCDriver * _pDriver)57 OAdabasConnection::OAdabasConnection(const SQLHANDLE _pDriverHandle, connectivity::odbc::ODBCDriver*        _pDriver)
58                                                  : OConnection_BASE2(_pDriverHandle,_pDriver)
59 {
60 	m_bUseOldDateFormat = sal_True;
61 }
62 //-----------------------------------------------------------------------------
Construct(const::rtl::OUString & url,const Sequence<PropertyValue> & info)63 SQLRETURN OAdabasConnection::Construct( const ::rtl::OUString& url,const Sequence< PropertyValue >& info) throw(SQLException)
64 {
65 	::osl::MutexGuard aGuard( m_aMutex );
66 
67 	m_aConnectionHandle  = SQL_NULL_HANDLE;
68 	setURL(url);
69 	setConnectionInfo(info);
70 
71 	// Connection allozieren
72 	N3SQLAllocHandle(SQL_HANDLE_DBC,m_pDriverHandleCopy,&m_aConnectionHandle);
73 	if(m_aConnectionHandle == SQL_NULL_HANDLE)
74 		throw SQLException();
75 
76 	const PropertyValue *pBegin	= info.getConstArray();
77 	const PropertyValue *pEnd	= pBegin + info.getLength();
78 	::rtl::OUString sHostName;
79 
80 	sal_Int32 nLen = url.indexOf(':');
81 	nLen = url.indexOf(':',nLen+1);
82 	::rtl::OUString aDSN(url.copy(nLen+1)),aUID,aPWD;
83 	sal_Int32 nTimeout = 20;
84 	for(;pBegin != pEnd;++pBegin)
85 	{
86 		if ( !pBegin->Name.compareToAscii("Timeout") )
87 			pBegin->Value >>= nTimeout;
88 		else if(!pBegin->Name.compareToAscii("user"))
89 			pBegin->Value >>= aUID;
90 		else if(!pBegin->Name.compareToAscii("password"))
91 			pBegin->Value >>= aPWD;
92 		else if(!pBegin->Name.compareToAscii("HostName"))
93 			pBegin->Value >>= sHostName;
94 		else if(0 == pBegin->Name.compareToAscii("CharSet"))
95 		{
96 			::rtl::OUString sIanaName;
97 			OSL_VERIFY( pBegin->Value >>= sIanaName );
98 
99 			::dbtools::OCharsetMap aLookupIanaName;
100 			::dbtools::OCharsetMap::const_iterator aLookup = aLookupIanaName.find(sIanaName, ::dbtools::OCharsetMap::IANA());
101 			if (aLookup != aLookupIanaName.end())
102 				m_nTextEncoding = (*aLookup).getEncoding();
103 			else
104 				m_nTextEncoding = RTL_TEXTENCODING_DONTKNOW;
105 			if(m_nTextEncoding == RTL_TEXTENCODING_DONTKNOW)
106 				m_nTextEncoding = osl_getThreadTextEncoding();
107 		}
108 	}
109 	m_sUser = aUID;
110 
111 	if( !sHostName.isEmpty() )
112 		aDSN = sHostName + ::rtl::OUString::createFromAscii(":") + aDSN;
113 	SQLRETURN nSQLRETURN = openConnectionWithAuth(aDSN,nTimeout, aUID,aPWD);
114 
115 	return nSQLRETURN;
116 }
117 //-----------------------------------------------------------------------------
openConnectionWithAuth(const::rtl::OUString & aConnectStr,sal_Int32 nTimeOut,const::rtl::OUString & _uid,const::rtl::OUString & _pwd)118 SQLRETURN OAdabasConnection::openConnectionWithAuth(const ::rtl::OUString& aConnectStr,sal_Int32 nTimeOut, const ::rtl::OUString& _uid,const ::rtl::OUString& _pwd)
119 {
120 	if (m_aConnectionHandle == SQL_NULL_HANDLE)
121 		return -1;
122 
123 	SQLRETURN nSQLRETURN = 0;
124 	SDB_ODBC_CHAR szDSN[4096];
125 	SDB_ODBC_CHAR szUID[20];
126 	SDB_ODBC_CHAR szPWD[20];
127 
128 	memset(szDSN,'\0',4096);
129 	memset(szUID,'\0',20);
130 	memset(szPWD,'\0',20);
131 
132 	::rtl::OString aConStr(::rtl::OUStringToOString(aConnectStr,getTextEncoding()));
133 	::rtl::OString aUID(::rtl::OUStringToOString(_uid,getTextEncoding()));
134 	::rtl::OString aPWD(::rtl::OUStringToOString(_pwd,getTextEncoding()));
135 	memcpy(szDSN, (SDB_ODBC_CHAR*) aConStr.getStr(), ::std::min<sal_Int32>((sal_Int32)2048,aConStr.getLength()));
136 	memcpy(szUID, (SDB_ODBC_CHAR*) aUID.getStr(), ::std::min<sal_Int32>((sal_Int32)20,aUID.getLength()));
137 	memcpy(szPWD, (SDB_ODBC_CHAR*) aPWD.getStr(), ::std::min<sal_Int32>((sal_Int32)20,aPWD.getLength()));
138 
139 
140 
141 	N3SQLSetConnectAttr(m_aConnectionHandle,SQL_ATTR_LOGIN_TIMEOUT,(SQLPOINTER)nTimeOut,SQL_IS_INTEGER);
142 	// Verbindung aufbauen
143 
144 	nSQLRETURN = N3SQLConnect(m_aConnectionHandle,
145 					  szDSN,
146 					  (SQLSMALLINT) ::std::min<sal_Int32>((sal_Int32)2048,aConStr.getLength()),
147 					  szUID,
148 					  (SQLSMALLINT) ::std::min<sal_Int32>((sal_Int32)20,aUID.getLength()),
149 					  szPWD,
150 					  (SQLSMALLINT) ::std::min<sal_Int32>((sal_Int32)20,aPWD.getLength()));
151 	if (nSQLRETURN == SQL_ERROR || nSQLRETURN == SQL_NO_DATA)
152 		return nSQLRETURN;
153 
154 	m_bClosed = sal_False;
155 
156 	// autocoomit ist immer default
157 
158 	N3SQLSetConnectAttr(m_aConnectionHandle,SQL_ATTR_AUTOCOMMIT,(SQLPOINTER)SQL_AUTOCOMMIT_ON,SQL_IS_INTEGER);
159 
160 	return nSQLRETURN;
161 }
162 
163 //------------------------------------------------------------------------------
disposing()164 void OAdabasConnection::disposing()
165 {
166 	::osl::MutexGuard aGuard(m_aMutex);
167 
168 	Reference< XTablesSupplier > xTableSupplier(m_xCatalog);
169     ::comphelper::disposeComponent(xTableSupplier);
170 
171 	m_xCatalog = WeakReference< XTablesSupplier >();
172 
173     OConnection_BASE2::disposing();
174 }
175 //------------------------------------------------------------------------------
createCatalog()176 Reference< XTablesSupplier > OAdabasConnection::createCatalog()
177 {
178 	::osl::MutexGuard aGuard( m_aMutex );
179 	Reference< XTablesSupplier > xTab = m_xCatalog;
180 	if(!xTab.is())
181 	{
182 		xTab = new OAdabasCatalog(m_aConnectionHandle,this);
183 		m_xCatalog = xTab;
184 	}
185 	return xTab;
186 }
187 // --------------------------------------------------------------------------------
getMetaData()188 Reference< XDatabaseMetaData > SAL_CALL OAdabasConnection::getMetaData(  ) throw(SQLException, RuntimeException)
189 {
190 	::osl::MutexGuard aGuard( m_aMutex );
191 	checkDisposed(OConnection_BASE2::rBHelper.bDisposed);
192 
193 
194 	Reference< XDatabaseMetaData > xMetaData = m_xMetaData;
195 	if(!xMetaData.is())
196 	{
197 		xMetaData = new OAdabasDatabaseMetaData(m_aConnectionHandle,this);
198 		m_xMetaData = xMetaData;
199 	}
200 
201 	return xMetaData;
202 }
203 // --------------------------------------------------------------------------------
createStatement()204 Reference< XStatement > SAL_CALL OAdabasConnection::createStatement(  ) throw(SQLException, RuntimeException)
205 {
206 	::osl::MutexGuard aGuard( m_aMutex );
207 	checkDisposed(OConnection_BASE2::rBHelper.bDisposed);
208 
209 	Reference< XStatement > xReturn = new OAdabasStatement(this);
210 	m_aStatements.push_back(WeakReferenceHelper(xReturn));
211 	return xReturn;
212 }
213 // --------------------------------------------------------------------------------
prepareStatement(const::rtl::OUString & sql)214 Reference< XPreparedStatement > SAL_CALL OAdabasConnection::prepareStatement( const ::rtl::OUString& sql ) throw(SQLException, RuntimeException)
215 {
216 	::osl::MutexGuard aGuard( m_aMutex );
217 	checkDisposed(OConnection_BASE2::rBHelper.bDisposed);
218 
219 	Reference< XPreparedStatement > xReturn = new OAdabasPreparedStatement(this,sql);
220 	m_aStatements.push_back(WeakReferenceHelper(xReturn));
221 	return xReturn;
222 }
223 // -----------------------------------------------------------------------------
getSomething(const::com::sun::star::uno::Sequence<sal_Int8> & rId)224 sal_Int64 SAL_CALL OAdabasConnection::getSomething( const ::com::sun::star::uno::Sequence< sal_Int8 >& rId ) throw (::com::sun::star::uno::RuntimeException)
225 {
226 	return (rId.getLength() == 16 && 0 == rtl_compareMemory(getUnoTunnelImplementationId().getConstArray(),  rId.getConstArray(), 16 ) )
227 				? reinterpret_cast< sal_Int64 >( this )
228 				: OConnection_BASE2::getSomething(rId);
229 }
230 // -----------------------------------------------------------------------------
getUnoTunnelImplementationId()231 Sequence< sal_Int8 > OAdabasConnection::getUnoTunnelImplementationId()
232 {
233 	static ::cppu::OImplementationId * pId = 0;
234 	if (! pId)
235 	{
236 		::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
237 		if (! pId)
238 		{
239 			static ::cppu::OImplementationId aId;
240 			pId = &aId;
241 		}
242 	}
243 	return pId->getImplementationId();
244 }
245 // -----------------------------------------------------------------------------
cloneConnection()246 ::connectivity::odbc::OConnection* OAdabasConnection::cloneConnection()
247 {
248 	return new OAdabasConnection(m_pDriverHandleCopy,m_pDriver);
249 }
250 // -----------------------------------------------------------------------------
createSelectColumns(const::rtl::OUString & _rSql)251 ::vos::ORef<OSQLColumns> OAdabasConnection::createSelectColumns(const ::rtl::OUString& _rSql)
252 {
253 	::vos::ORef<OSQLColumns> aRet;
254 	OSQLParser aParser(getDriver()->getORB());
255 	::rtl::OUString sErrorMessage;
256 	OSQLParseNode* pNode = aParser.parseTree(sErrorMessage,_rSql);
257 	if(pNode)
258 	{
259 		Reference< XTablesSupplier> xCata = createCatalog();
260 		OSQLParseTreeIterator aParseIter(this, xCata->getTables(),
261 										aParser, pNode);
262 		aParseIter.traverseAll();
263 		aRet = aParseIter.getSelectColumns();
264 	}
265 	return aRet;
266 }
267 // -----------------------------------------------------------------------------
268 
269 
270 
271