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 
27 #include <stdio.h>
28 #include <string.h>
29 #include <osl/diagnose.h>
30 #include "odbc/OPreparedStatement.hxx"
31 #include "odbc/OBoundParam.hxx"
32 #include <com/sun/star/sdbc/DataType.hpp>
33 #include "odbc/OTools.hxx"
34 #include "odbc/ODriver.hxx"
35 #include "odbc/OResultSet.hxx"
36 #include "odbc/OResultSetMetaData.hxx"
37 #include <cppuhelper/typeprovider.hxx>
38 #include <comphelper/sequence.hxx>
39 #include <com/sun/star/lang/DisposedException.hpp>
40 #include "connectivity/dbtools.hxx"
41 #include <comphelper/types.hxx>
42 #include "connectivity/FValue.hxx"
43 #include "resource/common_res.hrc"
44 #include "connectivity/sqlparse.hxx"
45 
46 using namespace ::comphelper;
47 using namespace connectivity;
48 using namespace connectivity::odbc;
49 using namespace com::sun::star::uno;
50 using namespace com::sun::star::lang;
51 using namespace com::sun::star::beans;
52 using namespace com::sun::star::sdbc;
53 using namespace com::sun::star::sdbcx;
54 using namespace com::sun::star::container;
55 using namespace com::sun::star::io;
56 using namespace com::sun::star::util;
57 
58 IMPLEMENT_SERVICE_INFO(OPreparedStatement,"com.sun.star.sdbcx.OPreparedStatement","com.sun.star.sdbc.PreparedStatement");
59 
60 
OPreparedStatement(OConnection * _pConnection,const::rtl::OUString & sql)61 OPreparedStatement::OPreparedStatement( OConnection* _pConnection,const ::rtl::OUString& sql)
62 	:OStatement_BASE2(_pConnection)
63     ,numParams(0)
64 	,boundParams(NULL)
65 	,m_bPrepared(sal_False)
66 {
67 	m_sSqlStatement = sql;
68 	try
69 	{
70 		if(_pConnection->isParameterSubstitutionEnabled())
71 		{
72 			OSQLParser aParser(_pConnection->getDriver()->getORB());
73 			::rtl::OUString sErrorMessage;
74 			::rtl::OUString sNewSql;
75             ::std::auto_ptr<OSQLParseNode> pNode( aParser.parseTree(sErrorMessage,sql) );
76 			if ( pNode.get() )
77 			{	// special handling for parameters
78 				OSQLParseNode::substituteParameterNames(pNode.get());
79 				pNode->parseNodeToStr( sNewSql, _pConnection );
80 				m_sSqlStatement = sNewSql;
81 			}
82 		}
83 	}
84 	catch(Exception&)
85 	{
86 	}
87 }
88 // -----------------------------------------------------------------------------
acquire()89 void SAL_CALL OPreparedStatement::acquire() throw()
90 {
91 	OStatement_BASE2::acquire();
92 }
93 // -----------------------------------------------------------------------------
release()94 void SAL_CALL OPreparedStatement::release() throw()
95 {
96 	OStatement_BASE2::release();
97 }
98 // -----------------------------------------------------------------------------
queryInterface(const Type & rType)99 Any SAL_CALL OPreparedStatement::queryInterface( const Type & rType ) throw(RuntimeException)
100 {
101 	Any aRet = OStatement_BASE2::queryInterface(rType);
102 	return aRet.hasValue() ? aRet : OPreparedStatement_BASE::queryInterface(rType);
103 }
104 // -------------------------------------------------------------------------
getTypes()105 ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type > SAL_CALL OPreparedStatement::getTypes(  ) throw(::com::sun::star::uno::RuntimeException)
106 {
107 	return ::comphelper::concatSequences(OPreparedStatement_BASE::getTypes(),OStatement_BASE2::getTypes());
108 }
109 // -------------------------------------------------------------------------
110 
getMetaData()111 Reference< XResultSetMetaData > SAL_CALL OPreparedStatement::getMetaData(  ) throw(SQLException, RuntimeException)
112 {
113 	::osl::MutexGuard aGuard( m_aMutex );
114 	checkDisposed(OStatement_BASE::rBHelper.bDisposed);
115 
116 
117 	prepareStatement();
118 	OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
119 	if(!m_xMetaData.is())
120 		m_xMetaData = new OResultSetMetaData(getOwnConnection(),m_aStatementHandle);
121 	return m_xMetaData;
122 }
123 // -------------------------------------------------------------------------
124 
close()125 void SAL_CALL OPreparedStatement::close(  ) throw(SQLException, RuntimeException)
126 {
127 	::osl::MutexGuard aGuard( m_aMutex );
128 	checkDisposed(OStatement_BASE::rBHelper.bDisposed);
129 
130 
131 	// Close/clear our result set
132 	clearMyResultSet ();
133 
134 	// Reset last warning message
135 
136 	try {
137 		clearWarnings ();
138 		OStatement_BASE2::close();
139 		FreeParams();
140 	}
141 	catch (SQLException &) {
142 		// If we get an error, ignore
143 	}
144 
145 	// Remove this Statement object from the Connection object's
146 	// list
147 }
148 // -------------------------------------------------------------------------
149 
execute()150 sal_Bool SAL_CALL OPreparedStatement::execute(  ) throw(SQLException, RuntimeException)
151 {
152 	::osl::MutexGuard aGuard( m_aMutex );
153 	checkDisposed(OStatement_BASE::rBHelper.bDisposed);
154 
155 
156 	sal_Bool needData = sal_False;
157 
158 	// Reset warnings
159 
160 	clearWarnings ();
161 
162 	// Reset the statement handle, warning and saved Resultset
163 
164 	reset();
165 
166 	// Call SQLExecute
167 	prepareStatement();
168 
169 	OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
170 	try
171 	{
172 		SQLRETURN nReturn = N3SQLExecute(m_aStatementHandle);
173 
174 		OTools::ThrowException(m_pConnection,nReturn,m_aStatementHandle,SQL_HANDLE_STMT,*this);
175 		needData = nReturn == SQL_NEED_DATA;
176 
177 		// Now loop while more data is needed (i.e. a data-at-
178 		// execution parameter was given).  For each parameter
179 		// that needs data, put the data from the input stream.
180 
181 		while (needData) {
182 
183 			// Get the parameter number that requires data
184 
185 			sal_Int32* paramIndex = 0;
186 			nReturn = N3SQLParamData(m_aStatementHandle,(SQLPOINTER*)&paramIndex);
187 
188 			// If the parameter index is -1, there is no
189 			// more data required
190 
191 			if ( !paramIndex || ( *paramIndex == -1 ) )
192 				needData = sal_False;
193 			else
194 			{
195 				// Now we have the proper parameter
196 				// index, get the data from the input
197 				// stream and do a SQLPutData
198 				putParamData (*paramIndex);
199 			}
200 		}
201 
202 	}
203 	catch (const SQLWarning&)
204 	{
205 	}
206 
207 	// Now loop while more data is needed (i.e. a data-at-
208 	// execution parameter was given).  For each parameter
209 	// that needs data, put the data from the input stream.
210 
211 	while (needData) {
212 
213 		// Get the parameter number that requires data
214 
215 		sal_Int32* paramIndex = 0;
216 		N3SQLParamData (m_aStatementHandle,(SQLPOINTER*)&paramIndex);
217 
218 		// If the parameter index is -1, there is no more
219 		// data required
220 
221 		if (*paramIndex == -1) {
222 			needData = sal_False;
223 		}
224 		else {
225 			// Now we have the proper parameter index,
226 			// get the data from the input stream
227 			// and do a SQLPutData
228 			putParamData(*paramIndex);
229 		}
230 	}
231 
232 	// Now determine if there is a result set associated with
233 	// the SQL statement that was executed.  Get the column
234 	// count, and if it is not zero, there is a result set.
235 
236 
237 	return getColumnCount() > 0;
238 }
239 // -------------------------------------------------------------------------
240 
executeUpdate()241 sal_Int32 SAL_CALL OPreparedStatement::executeUpdate(  ) throw(SQLException, RuntimeException)
242 {
243 	::osl::MutexGuard aGuard( m_aMutex );
244 	checkDisposed(OStatement_BASE::rBHelper.bDisposed);
245 
246 	sal_Int32 numRows = -1;
247 
248 	prepareStatement();
249 	// Execute the statement.  If execute returns sal_False, a
250 	// row count exists.
251 
252 	if (!execute())
253 		numRows = getUpdateCount ();
254 	else
255     {
256 		// No update count was produced (a ResultSet was).  Raise
257 		// an exception
258 		m_pConnection->throwGenericSQLException(STR_NO_ROWCOUNT,*this);
259 	}
260 	return numRows;
261 }
262 // -------------------------------------------------------------------------
263 
setString(sal_Int32 parameterIndex,const::rtl::OUString & x)264 void SAL_CALL OPreparedStatement::setString( sal_Int32 parameterIndex, const ::rtl::OUString& x ) throw(SQLException, RuntimeException)
265 {
266 	::rtl::OString aString(::rtl::OUStringToOString(x,getOwnConnection()->getTextEncoding()));
267 	setParameter(parameterIndex,DataType::CHAR,aString.getLength(),(void*)&x);
268 }
269 // -------------------------------------------------------------------------
270 
getConnection()271 Reference< XConnection > SAL_CALL OPreparedStatement::getConnection(  ) throw(SQLException, RuntimeException)
272 {
273 	::osl::MutexGuard aGuard( m_aMutex );
274 	checkDisposed(OStatement_BASE::rBHelper.bDisposed);
275 
276 	return (Reference< XConnection >)m_pConnection;
277 }
278 // -------------------------------------------------------------------------
279 
executeQuery()280 Reference< XResultSet > SAL_CALL OPreparedStatement::executeQuery(  ) throw(SQLException, RuntimeException)
281 {
282 	::osl::MutexGuard aGuard( m_aMutex );
283 	checkDisposed(OStatement_BASE::rBHelper.bDisposed);
284 
285 	Reference< XResultSet > rs = NULL;
286 
287 	prepareStatement();
288 
289 	if (execute())
290 		rs = getResultSet(sal_False);
291 	else
292     {
293 		// No ResultSet was produced.  Raise an exception
294         m_pConnection->throwGenericSQLException(STR_NO_RESULTSET,*this);
295 	}
296 	return rs;
297 }
298 // -------------------------------------------------------------------------
299 
setBoolean(sal_Int32 parameterIndex,sal_Bool x)300 void SAL_CALL OPreparedStatement::setBoolean( sal_Int32 parameterIndex, sal_Bool x ) throw(SQLException, RuntimeException)
301 {
302 	::osl::MutexGuard aGuard( m_aMutex );
303 	checkDisposed(OStatement_BASE::rBHelper.bDisposed);
304 
305 
306 	sal_Int32 value = 0;
307 
308 	// If the parameter is sal_True, set the value to 1
309 	if (x) {
310 		value = 1;
311 	}
312 
313 	// Set the parameter as if it were an integer
314 	setInt (parameterIndex, value);
315 }
316 // -------------------------------------------------------------------------
setParameter(sal_Int32 parameterIndex,sal_Int32 _nType,sal_Int32 _nSize,void * _pData)317 void OPreparedStatement::setParameter(sal_Int32 parameterIndex,sal_Int32 _nType,sal_Int32 _nSize,void* _pData)
318 {
319 	::osl::MutexGuard aGuard( m_aMutex );
320 	checkDisposed(OStatement_BASE::rBHelper.bDisposed);
321 
322 	prepareStatement();
323 	// Allocate a buffer to be used in binding.  This will be
324 		// a 'permanent' buffer that the bridge will fill in with
325 		// the bound data in native format.
326 
327 
328 	checkParameterIndex(parameterIndex);
329 	sal_Int32 nRealSize = _nSize;
330 	SQLSMALLINT fSqlType = static_cast<SQLSMALLINT>(OTools::jdbcTypeToOdbc(_nType));
331 	switch(fSqlType)
332 	{
333 		case SQL_CHAR:
334 		case SQL_VARCHAR:
335 		case SQL_DECIMAL:
336 		case SQL_NUMERIC:
337 			++nRealSize;
338 			break;
339 		case SQL_BINARY:
340 		case SQL_VARBINARY:
341 			nRealSize=1;    //dummy buffer, binary data isn't copied
342 			break;
343 		default:
344 			break;
345 	}
346 
347 	sal_Int8* bindBuf = allocBindBuf(parameterIndex, nRealSize);
348 
349 	OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
350 	OTools::bindParameter(	m_pConnection,
351 							m_aStatementHandle,
352 							parameterIndex,
353 							bindBuf,
354 							getLengthBuf(parameterIndex),
355 							fSqlType,
356 							sal_False,
357 							m_pConnection->useOldDateFormat(),
358 							_pData,
359 							(Reference <XInterface>)*this,
360 							getOwnConnection()->getTextEncoding());
361 }
362 // -----------------------------------------------------------------------------
setByte(sal_Int32 parameterIndex,sal_Int8 x)363 void SAL_CALL OPreparedStatement::setByte( sal_Int32 parameterIndex, sal_Int8 x ) throw(SQLException, RuntimeException)
364 {
365 	setParameter(parameterIndex,DataType::TINYINT,sizeof(sal_Int8),&x);
366 }
367 // -------------------------------------------------------------------------
368 
setDate(sal_Int32 parameterIndex,const Date & aData)369 void SAL_CALL OPreparedStatement::setDate( sal_Int32 parameterIndex, const Date& aData ) throw(SQLException, RuntimeException)
370 {
371 	DATE_STRUCT x = OTools::DateToOdbcDate(aData);
372 	setParameter(parameterIndex,DataType::DATE,sizeof(DATE_STRUCT),&x);
373 }
374 // -------------------------------------------------------------------------
375 
376 
setTime(sal_Int32 parameterIndex,const Time & aVal)377 void SAL_CALL OPreparedStatement::setTime( sal_Int32 parameterIndex, const Time& aVal ) throw(SQLException, RuntimeException)
378 {
379 	TIME_STRUCT x = OTools::TimeToOdbcTime(aVal);
380 	setParameter(parameterIndex,DataType::TIME,sizeof(TIME_STRUCT),&x);
381 }
382 // -------------------------------------------------------------------------
383 
setTimestamp(sal_Int32 parameterIndex,const DateTime & aVal)384 void SAL_CALL OPreparedStatement::setTimestamp( sal_Int32 parameterIndex, const DateTime& aVal ) throw(SQLException, RuntimeException)
385 {
386 	TIMESTAMP_STRUCT x = OTools::DateTimeToTimestamp(aVal);
387 	setParameter(parameterIndex,DataType::TIMESTAMP,sizeof(TIMESTAMP_STRUCT),&x);
388 }
389 // -------------------------------------------------------------------------
390 
setDouble(sal_Int32 parameterIndex,double x)391 void SAL_CALL OPreparedStatement::setDouble( sal_Int32 parameterIndex, double x ) throw(SQLException, RuntimeException)
392 {
393 	setParameter(parameterIndex,DataType::DOUBLE,sizeof(double),&x);
394 }
395 
396 // -------------------------------------------------------------------------
397 
setFloat(sal_Int32 parameterIndex,float x)398 void SAL_CALL OPreparedStatement::setFloat( sal_Int32 parameterIndex, float x ) throw(SQLException, RuntimeException)
399 {
400 	setParameter(parameterIndex,DataType::FLOAT,sizeof(float),&x);
401 }
402 // -------------------------------------------------------------------------
403 
setInt(sal_Int32 parameterIndex,sal_Int32 x)404 void SAL_CALL OPreparedStatement::setInt( sal_Int32 parameterIndex, sal_Int32 x ) throw(SQLException, RuntimeException)
405 {
406 	setParameter(parameterIndex,DataType::INTEGER,sizeof(sal_Int32),&x);
407 }
408 // -------------------------------------------------------------------------
409 
setLong(sal_Int32 parameterIndex,sal_Int64 x)410 void SAL_CALL OPreparedStatement::setLong( sal_Int32 parameterIndex, sal_Int64 x ) throw(SQLException, RuntimeException)
411 {
412 	try
413 	{
414 		setParameter(parameterIndex,DataType::BIGINT,sizeof(sal_Int64),&x);
415 	}
416 	catch(SQLException&)
417 	{
418 		setString(parameterIndex,ORowSetValue(x));
419 	}
420 }
421 // -------------------------------------------------------------------------
422 
setNull(sal_Int32 parameterIndex,sal_Int32 sqlType)423 void SAL_CALL OPreparedStatement::setNull( sal_Int32 parameterIndex, sal_Int32 sqlType ) throw(SQLException, RuntimeException)
424 {
425 	::osl::MutexGuard aGuard( m_aMutex );
426 	checkDisposed(OStatement_BASE::rBHelper.bDisposed);
427 
428 
429 	prepareStatement();
430 	// Get the buffer needed for the length
431 	checkParameterIndex(parameterIndex);
432 
433 	sal_Int8* lenBuf = getLengthBuf (parameterIndex);
434 	*(SQLLEN*)lenBuf = SQL_NULL_DATA;
435 
436 
437 	SQLLEN prec = 0;
438 	SQLULEN nColumnSize = 0;
439 	if (sqlType == SQL_CHAR || sqlType == SQL_VARCHAR || sqlType == SQL_LONGVARCHAR)
440 	{
441 		prec = 1;
442 		nColumnSize = 1;
443 	}
444 
445 	SQLSMALLINT fCType = 0;
446 	SQLSMALLINT fSqlType = 0;
447 
448 	SQLSMALLINT nDecimalDigits = 0;
449 	OTools::getBindTypes(	sal_False,
450 							m_pConnection->useOldDateFormat(),
451                             (SQLSMALLINT)sqlType,
452 							fCType,
453 							fSqlType);
454 
455 	SQLRETURN nReturn = N3SQLBindParameter(	m_aStatementHandle,
456 											(SQLUSMALLINT)parameterIndex,
457 											(SQLSMALLINT)SQL_PARAM_INPUT,
458 											fCType,
459 											fSqlType,
460 											nColumnSize,
461 											nDecimalDigits,
462 											NULL,
463 											prec,
464 											(SQLLEN*)lenBuf
465 											);
466 	OTools::ThrowException(m_pConnection,nReturn,m_aStatementHandle,SQL_HANDLE_STMT,*this);
467 }
468 // -------------------------------------------------------------------------
469 
setClob(sal_Int32 parameterIndex,const Reference<XClob> & x)470 void SAL_CALL OPreparedStatement::setClob( sal_Int32 parameterIndex, const Reference< XClob >& x ) throw(SQLException, RuntimeException)
471 {
472 	if ( x.is() )
473 		setStream(parameterIndex, x->getCharacterStream(), (SQLLEN)x->length(), DataType::LONGVARCHAR);
474 }
475 // -------------------------------------------------------------------------
476 
setBlob(sal_Int32 parameterIndex,const Reference<XBlob> & x)477 void SAL_CALL OPreparedStatement::setBlob( sal_Int32 parameterIndex, const Reference< XBlob >& x ) throw(SQLException, RuntimeException)
478 {
479     if ( x.is() )
480 		setStream(parameterIndex, x->getBinaryStream(), (SQLLEN)x->length(), DataType::LONGVARCHAR);
481 }
482 // -------------------------------------------------------------------------
483 
setArray(sal_Int32,const Reference<XArray> &)484 void SAL_CALL OPreparedStatement::setArray( sal_Int32 /*parameterIndex*/, const Reference< XArray >& /*x*/ ) throw(SQLException, RuntimeException)
485 {
486     ::dbtools::throwFunctionNotSupportedException( "XParameters::setArray", *this );
487 }
488 // -------------------------------------------------------------------------
489 
setRef(sal_Int32,const Reference<XRef> &)490 void SAL_CALL OPreparedStatement::setRef( sal_Int32 /*parameterIndex*/, const Reference< XRef >& /*x*/ ) throw(SQLException, RuntimeException)
491 {
492     ::dbtools::throwFunctionNotSupportedException( "XParameters::setRef", *this );
493 }
494 // -------------------------------------------------------------------------
setDecimal(sal_Int32 parameterIndex,const::rtl::OUString & x)495 void OPreparedStatement::setDecimal( sal_Int32 parameterIndex, const ::rtl::OUString& x )
496 {
497 	::rtl::OString aString(::rtl::OUStringToOString(x,getOwnConnection()->getTextEncoding()));
498 	setParameter(parameterIndex,DataType::DECIMAL,aString.getLength(),(void*)&x);
499 }
500 // -------------------------------------------------------------------------
setObjectWithInfo(sal_Int32 parameterIndex,const Any & x,sal_Int32 sqlType,sal_Int32 scale)501 void SAL_CALL OPreparedStatement::setObjectWithInfo( sal_Int32 parameterIndex, const Any& x, sal_Int32 sqlType, sal_Int32 scale ) throw(SQLException, RuntimeException)
502 {
503 	checkDisposed(OStatement_BASE::rBHelper.bDisposed);
504 	::osl::MutexGuard aGuard( m_aMutex );
505 
506 	prepareStatement();
507 	// For each known SQL Type, call the appropriate
508 		// set routine
509 
510 	switch (sqlType)
511 	{
512 		case DataType::VARCHAR:
513 		case DataType::LONGVARCHAR:
514 			if(x.hasValue())
515 			{
516 				::rtl::OUString sStr;
517 				x >>= sStr;
518 				::rtl::OString aString(::rtl::OUStringToOString(sStr,getOwnConnection()->getTextEncoding()));
519 				setParameter(parameterIndex,sqlType,aString.getLength(),&aString);
520 			}
521 			else
522 				setNull(parameterIndex,sqlType);
523 			break;
524         case DataType::DECIMAL:
525             {
526                 ORowSetValue aValue;
527                 aValue.fill(x);
528                 setDecimal(parameterIndex,aValue);
529             }
530             break;
531         case DataType::NUMERIC:
532             {
533                 ORowSetValue aValue;
534                 aValue.fill(x);
535                 setString(parameterIndex,aValue);
536             }
537             break;
538 		default:
539 			::dbtools::setObjectWithInfo(this,parameterIndex,x,sqlType,scale);
540 		}
541 }
542 // -------------------------------------------------------------------------
543 
setObjectNull(sal_Int32 parameterIndex,sal_Int32 sqlType,const::rtl::OUString &)544 void SAL_CALL OPreparedStatement::setObjectNull( sal_Int32 parameterIndex, sal_Int32 sqlType, const ::rtl::OUString& /*typeName*/ ) throw(SQLException, RuntimeException)
545 {
546 	::osl::MutexGuard aGuard( m_aMutex );
547 	checkDisposed(OStatement_BASE::rBHelper.bDisposed);
548 
549 	setNull(parameterIndex,sqlType);
550 }
551 // -------------------------------------------------------------------------
552 
setObject(sal_Int32 parameterIndex,const Any & x)553 void SAL_CALL OPreparedStatement::setObject( sal_Int32 parameterIndex, const Any& x ) throw(SQLException, RuntimeException)
554 {
555 	if (!::dbtools::implSetObject(this, parameterIndex, x))
556 	{	// there is no other setXXX call which can handle the value in x
557 		throw SQLException();
558 	}
559 }
560 // -------------------------------------------------------------------------
561 
setShort(sal_Int32 parameterIndex,sal_Int16 x)562 void SAL_CALL OPreparedStatement::setShort( sal_Int32 parameterIndex, sal_Int16 x ) throw(SQLException, RuntimeException)
563 {
564 	setParameter(parameterIndex,DataType::SMALLINT,sizeof(sal_Int16),&x);
565 }
566 // -------------------------------------------------------------------------
567 
setBytes(sal_Int32 parameterIndex,const Sequence<sal_Int8> & x)568 void SAL_CALL OPreparedStatement::setBytes( sal_Int32 parameterIndex, const Sequence< sal_Int8 >& x ) throw(SQLException, RuntimeException)
569 {
570 	setParameter(parameterIndex,DataType::BINARY,x.getLength(),(void*)&x);
571 	boundParams[parameterIndex-1].setSequence(x); // this assures that the sequence stays alive
572 }
573 // -------------------------------------------------------------------------
574 
575 
setCharacterStream(sal_Int32 parameterIndex,const Reference<::com::sun::star::io::XInputStream> & x,sal_Int32 length)576 void SAL_CALL OPreparedStatement::setCharacterStream( sal_Int32 parameterIndex, const Reference< ::com::sun::star::io::XInputStream >& x, sal_Int32 length ) throw(SQLException, RuntimeException)
577 {
578 	setStream(parameterIndex, x, length, DataType::LONGVARCHAR);
579 }
580 // -------------------------------------------------------------------------
581 
setBinaryStream(sal_Int32 parameterIndex,const Reference<::com::sun::star::io::XInputStream> & x,sal_Int32 length)582 void SAL_CALL OPreparedStatement::setBinaryStream( sal_Int32 parameterIndex, const Reference< ::com::sun::star::io::XInputStream >& x, sal_Int32 length ) throw(SQLException, RuntimeException)
583 {
584 	setStream(parameterIndex, x, length, DataType::LONGVARBINARY);
585 }
586 // -------------------------------------------------------------------------
587 
clearParameters()588 void SAL_CALL OPreparedStatement::clearParameters(  ) throw(SQLException, RuntimeException)
589 {
590 	prepareStatement();
591 	OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
592 	SQLRETURN nRet = N3SQLFreeStmt (m_aStatementHandle, SQL_RESET_PARAMS);
593 	nRet = N3SQLFreeStmt (m_aStatementHandle, SQL_UNBIND);
594 }
595 // -------------------------------------------------------------------------
clearBatch()596 void SAL_CALL OPreparedStatement::clearBatch(  ) throw(SQLException, RuntimeException)
597 {
598 	//	clearParameters(  );
599 	//	m_aBatchList.erase();
600 }
601 // -------------------------------------------------------------------------
602 
addBatch()603 void SAL_CALL OPreparedStatement::addBatch( ) throw(SQLException, RuntimeException)
604 {
605 }
606 // -------------------------------------------------------------------------
607 
executeBatch()608 Sequence< sal_Int32 > SAL_CALL OPreparedStatement::executeBatch(  ) throw(SQLException, RuntimeException)
609 {
610 	return Sequence< sal_Int32 > ();
611 }
612 // -------------------------------------------------------------------------
613 
614 //====================================================================
615 // methods
616 //====================================================================
617 
618 //--------------------------------------------------------------------
619 // initBoundParam
620 // Initialize the bound parameter objects
621 //--------------------------------------------------------------------
622 
initBoundParam()623 void OPreparedStatement::initBoundParam () throw(SQLException)
624 {
625 	OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
626 	// Get the number of parameters
627 	numParams = 0;
628 	N3SQLNumParams (m_aStatementHandle,&numParams);
629 
630 	// There are parameter markers, allocate the bound
631 	// parameter objects
632 
633 	if (numParams > 0)
634 	{
635 		// Allocate an array of bound parameter objects
636 
637 		boundParams = new OBoundParam[numParams];
638 
639 		// Allocate and initialize each bound parameter
640 
641 		for (sal_Int32 i = 0; i < numParams; i++)
642 		{
643 			boundParams[i] = OBoundParam();
644 			boundParams[i].initialize ();
645 		}
646 	}
647 }
648 // -------------------------------------------------------------------------
649 
650 //--------------------------------------------------------------------
651 // allocBindBuf
652 // Allocate storage for the permanent data buffer for the bound
653 // parameter.
654 //--------------------------------------------------------------------
655 
allocBindBuf(sal_Int32 index,sal_Int32 bufLen)656 sal_Int8* OPreparedStatement::allocBindBuf(	sal_Int32 index,sal_Int32 bufLen)
657 {
658 	sal_Int8* b = NULL;
659 
660 	// Sanity check the parameter number
661 
662 	if ((index >= 1) &&
663 		(index <= numParams) && bufLen > 0 )
664 	{
665 		b = boundParams[index - 1].allocBindDataBuffer(bufLen);
666 	}
667 
668 	return b;
669 }
670 // -------------------------------------------------------------------------
671 
672 //--------------------------------------------------------------------
673 // getDataBuf
674 // Gets the data buffer for the given parameter index
675 //--------------------------------------------------------------------
676 
getDataBuf(sal_Int32 index)677 sal_Int8* OPreparedStatement::getDataBuf (sal_Int32 index)
678 {
679 	sal_Int8* b = NULL;
680 
681 	// Sanity check the parameter number
682 
683 	if ((index >= 1) &&
684 		(index <= numParams))
685 	{
686 		b = boundParams[index - 1].getBindDataBuffer ();
687 	}
688 
689 	return b;
690 }
691 // -------------------------------------------------------------------------
692 
693 //--------------------------------------------------------------------
694 // getLengthBuf
695 // Gets the length buffer for the given parameter index
696 //--------------------------------------------------------------------
697 
getLengthBuf(sal_Int32 index)698 sal_Int8* OPreparedStatement::getLengthBuf (sal_Int32 index)
699 {
700 	sal_Int8* b = NULL;
701 
702 	// Sanity check the parameter number
703 
704 	if ((index >= 1) &&
705 		(index <= numParams))
706 	{
707 		b = boundParams[index - 1].getBindLengthBuffer ();
708 	}
709 
710 	return b;
711 }
712 // -------------------------------------------------------------------------
713 
714 //--------------------------------------------------------------------
715 // getParamLength
716 // Returns the length of the given parameter number.  When each
717 // parameter was bound, a 4-sal_Int8 buffer was given to hold the
718 // length (stored in native format).  Get the buffer, convert the
719 // buffer from native format, and return it.  If the length is -1,
720 // the column is considered to be NULL.
721 //--------------------------------------------------------------------
722 
getParamLength(sal_Int32 index)723 sal_Int32 OPreparedStatement::getParamLength (	sal_Int32 index)
724 {
725 	sal_Int32 paramLen = SQL_NULL_DATA;
726 
727 	// Sanity check the parameter number
728 
729 	if ((index >= 1) &&
730 		(index <= numParams)) {
731 
732 		// Now get the length of the parameter from the
733 		// bound param array.  -1 is returned if it is NULL.
734 		long n = 0;
735 		memcpy (&n, boundParams[index -1].getBindLengthBuffer (), sizeof (n));
736 		paramLen = n;
737 	}
738 	return paramLen;
739 }
740 // -------------------------------------------------------------------------
741 
742 //--------------------------------------------------------------------
743 // putParamData
744 // Puts parameter data from a previously bound input stream.  The
745 // input stream was bound using SQL_LEN_DATA_AT_EXEC.
746 //--------------------------------------------------------------------
747 
putParamData(sal_Int32 index)748 void OPreparedStatement::putParamData (sal_Int32 index) throw(SQLException)
749 {
750 	// Sanity check the parameter index
751 	if ((index < 1) ||
752 		(index > numParams))
753 	{
754 		return;
755 	}
756 
757 	// We'll transfer up to MAX_PUT_DATA_LENGTH at a time
758     Sequence< sal_Int8 > buf( MAX_PUT_DATA_LENGTH );
759 
760 	// Get the information about the input stream
761 
762 	Reference< XInputStream> inputStream =	boundParams[index - 1].getInputStream ();
763 	if ( !inputStream.is() )
764 	{
765         ::connectivity::SharedResources aResources;
766         const ::rtl::OUString sError( aResources.getResourceString(STR_NO_INPUTSTREAM));
767 		throw SQLException (sError,	*this,::rtl::OUString(),0,Any());
768 	}
769 
770 	sal_Int32 maxBytesLeft = boundParams[index - 1].getInputStreamLen ();
771 
772 	// Loop while more data from the input stream
773     sal_Int32 haveRead = 0;
774 	try
775 	{
776 
777 		do
778 		{
779             sal_Int32 toReadThisRound = ::std::min( MAX_PUT_DATA_LENGTH, maxBytesLeft );
780 
781 			// Read some data from the input stream
782 			haveRead = inputStream->readBytes( buf, toReadThisRound );
783             OSL_ENSURE( haveRead == buf.getLength(), "OPreparedStatement::putParamData: inconsistency!" );
784 
785             if ( !haveRead )
786                 // no more data in the stream - the given stream length was a maximum which could not be
787                 // fulfilled by the stream
788                 break;
789 
790 		    // Put the data
791             OSL_ENSURE( m_aStatementHandle, "OPreparedStatement::putParamData: StatementHandle is null!" );
792 		    N3SQLPutData ( m_aStatementHandle, buf.getArray(), buf.getLength() );
793 
794 			// decrement the number of bytes still needed
795 			maxBytesLeft -= haveRead;
796 		}
797         while ( maxBytesLeft > 0 );
798 	}
799 	catch (const IOException& ex)
800 	{
801 
802 		// If an I/O exception was generated, turn
803 		// it into a SQLException
804 
805 		throw SQLException(ex.Message,*this,::rtl::OUString(),0,Any());
806 	}
807 }
808 // -------------------------------------------------------------------------
809 //--------------------------------------------------------------------
810 // getPrecision
811 // Given a SQL type, return the maximum precision for the column.
812 // Returns -1 if not known
813 //--------------------------------------------------------------------
814 
getPrecision(sal_Int32 sqlType)815 sal_Int32 OPreparedStatement::getPrecision ( sal_Int32 sqlType)
816 {
817 	::osl::MutexGuard aGuard( m_aMutex );
818 	checkDisposed(OStatement_BASE::rBHelper.bDisposed);
819 
820 	sal_Int32 prec = -1;
821     const TTypeInfoVector& rTypeInfo = m_pConnection->getTypeInfo();
822     if ( !rTypeInfo.empty() )
823     {
824         m_pConnection->buildTypeInfo();
825     }
826 
827 	if ( !rTypeInfo.empty() )
828 	{
829 		OTypeInfo aInfo;
830 		aInfo.nType = (sal_Int16)sqlType;
831 		TTypeInfoVector::const_iterator aIter = ::std::find(rTypeInfo.begin(),rTypeInfo.end(),aInfo);
832 		if(aIter != rTypeInfo.end())
833 			prec = (*aIter).nPrecision;
834 	}
835 	return prec;
836 }
837 
838 //--------------------------------------------------------------------
839 // setStream
840 // Sets an input stream as a parameter, using the given SQL type
841 //--------------------------------------------------------------------
842 
setStream(sal_Int32 ParameterIndex,const Reference<XInputStream> & x,SQLLEN length,sal_Int32 SQLtype)843 void OPreparedStatement::setStream(
844 									sal_Int32 ParameterIndex,
845 									const Reference< XInputStream>& x,
846 									SQLLEN length,
847 									sal_Int32 SQLtype)
848 									throw(SQLException)
849 {
850 	::osl::MutexGuard aGuard( m_aMutex );
851 	checkDisposed(OStatement_BASE::rBHelper.bDisposed);
852 
853 
854 	prepareStatement();
855 
856 	checkParameterIndex(ParameterIndex);
857 	// Get the buffer needed for the length
858 
859 	sal_Int8* lenBuf = getLengthBuf(ParameterIndex);
860 
861 	// Allocate a new buffer for the parameter data.  This buffer
862 	// will be returned by SQLParamData (it is set to the parameter
863 	// number, a 4-sal_Int8 integer)
864 
865 	sal_Int8* dataBuf = allocBindBuf (ParameterIndex, 4);
866 
867     // Bind the parameter with SQL_LEN_DATA_AT_EXEC
868 	SQLSMALLINT   Ctype = SQL_C_CHAR;
869 	SQLLEN	atExec = SQL_LEN_DATA_AT_EXEC (length);
870 	memcpy (dataBuf, &ParameterIndex, sizeof(ParameterIndex));
871 	memcpy (lenBuf, &atExec, sizeof (atExec));
872 
873 	if ((SQLtype == SQL_BINARY) || (SQLtype == SQL_VARBINARY) || (SQLtype == SQL_LONGVARBINARY))
874 		Ctype = SQL_C_BINARY;
875 
876 
877 	OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
878 	N3SQLBindParameter(m_aStatementHandle,
879 						(SQLUSMALLINT)ParameterIndex,
880 						(SQLUSMALLINT)SQL_PARAM_INPUT,
881 						Ctype,
882 						(SQLSMALLINT)SQLtype,
883 						(SQLULEN)length,
884 						0,
885 						dataBuf,
886 						sizeof(ParameterIndex),
887 						(SQLLEN*)lenBuf);
888 
889 	// Save the input stream
890 	boundParams[ParameterIndex - 1].setInputStream (x, length);
891 }
892 // -------------------------------------------------------------------------
893 
894 // -------------------------------------------------------------------------
895 
FreeParams()896 void OPreparedStatement::FreeParams()
897 {
898     numParams = 0;
899 	delete [] boundParams;
900 	boundParams = NULL;
901 }
902 // -------------------------------------------------------------------------
setFastPropertyValue_NoBroadcast(sal_Int32 nHandle,const Any & rValue)903 void OPreparedStatement::setFastPropertyValue_NoBroadcast(sal_Int32 nHandle,const Any& rValue) throw (Exception)
904 {
905 	try
906 	{
907 		switch(nHandle)
908 		{
909 			case PROPERTY_ID_RESULTSETCONCURRENCY:
910 				if(!isPrepared())
911 					setResultSetConcurrency(comphelper::getINT32(rValue));
912 				break;
913 			case PROPERTY_ID_RESULTSETTYPE:
914 				if(!isPrepared())
915 					setResultSetType(comphelper::getINT32(rValue));
916 				break;
917 			case PROPERTY_ID_FETCHDIRECTION:
918 				if(!isPrepared())
919 					setFetchDirection(comphelper::getINT32(rValue));
920 				break;
921 			case PROPERTY_ID_USEBOOKMARKS:
922 				if(!isPrepared())
923 					setUsingBookmarks(comphelper::getBOOL(rValue));
924 				break;
925 			default:
926 				OStatement_Base::setFastPropertyValue_NoBroadcast(nHandle,rValue);
927 		}
928 	}
929 	catch(const SQLException&)
930 	{
931 		//	throw Exception(e.Message,*this);
932 	}
933 }
934 // -----------------------------------------------------------------------------
prepareStatement()935 void OPreparedStatement::prepareStatement()
936 {
937 	if(!isPrepared())
938 	{
939 		OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
940 		::rtl::OString aSql(::rtl::OUStringToOString(m_sSqlStatement,getOwnConnection()->getTextEncoding()));
941 		SQLRETURN nReturn = N3SQLPrepare(m_aStatementHandle,(SDB_ODBC_CHAR *) aSql.getStr(),aSql.getLength());
942 		OTools::ThrowException(m_pConnection,nReturn,m_aStatementHandle,SQL_HANDLE_STMT,*this);
943         m_bPrepared = sal_True;
944 		initBoundParam();
945 	}
946 }
947 // -----------------------------------------------------------------------------
checkParameterIndex(sal_Int32 _parameterIndex)948 void OPreparedStatement::checkParameterIndex(sal_Int32 _parameterIndex)
949 {
950 	if(	!_parameterIndex || _parameterIndex > numParams)
951 	{
952         ::connectivity::SharedResources aResources;
953         const ::rtl::OUString sError( aResources.getResourceStringWithSubstitution(STR_WRONG_PARAM_INDEX,
954             "$pos$", ::rtl::OUString::valueOf(_parameterIndex),
955             "$count$", ::rtl::OUString::valueOf((sal_Int32)numParams)
956             ));
957         SQLException aNext(sError,*this, ::rtl::OUString(),0,Any());
958 
959         ::dbtools::throwInvalidIndexException(*this,makeAny(aNext));
960 	}
961 }
962 // -----------------------------------------------------------------------------
createResulSet()963 OResultSet* OPreparedStatement::createResulSet()
964 {
965     OResultSet* pReturn = new OResultSet(m_aStatementHandle,this);
966     pReturn->setMetaData(getMetaData());
967 	return pReturn;
968 }
969 // -----------------------------------------------------------------------------
970