23 #include <utf8_codecvt.hpp>
26 void ASql::MySQL::Connection::connect(
const char* host,
const char* user,
const char* passwd,
const char* db,
unsigned int port,
const char* unix_socket,
unsigned long client_flag,
const char*
const charset)
30 for(
unsigned int i=0; i<
threads(); ++i)
38 for(
unsigned int i=0; i<
threads(); ++i)
43 if(!mysql_real_connect(&
m_connection[i], host, user, passwd, db, port, unix_socket, client_flag))
70 for(
unsigned int i=0; i<threads(); ++i)
72 mysql_stmt_close(foundRowsStatement[i]);
73 mysql_close(&m_connection[i]);
80 if(mysql_stmt_bind_param(foundRowsStatement[thread], 0))
81 throw Error(foundRowsStatement[thread]);
83 if(mysql_stmt_execute(foundRowsStatement[thread]))
84 throw Error(foundRowsStatement[thread]);
86 foundRowsBinding[thread].buffer = rows;
87 if(mysql_stmt_bind_result(foundRowsStatement[thread], &foundRowsBinding[thread]))
88 throw Error(foundRowsStatement[thread]);
90 if(mysql_stmt_fetch(foundRowsStatement[thread]))
91 throw Error(foundRowsStatement[thread]);
92 mysql_stmt_free_result(foundRowsStatement[thread]);
93 mysql_stmt_reset(foundRowsStatement[thread]);
101 for(
unsigned int i=0; i<connection.threads(); ++i)
102 mysql_stmt_close(stmt[i]);
103 m_initialized =
false;
106 const char* realQueryString = queryString;
107 size_t realQueryLength = queryLength;
108 boost::scoped_array<char> buffer;
110 if(customPlaceholders)
112 buffer.reset(
new char[queryLength]);
113 std::memset(buffer.get(), 0, queryLength);
114 realQueryString = buffer.get();
118 size_t intBufferSize=0;
119 std::memset(intBuffer, 0,
sizeof(intBuffer));
120 bool inPlaceholder =
false;
122 for(
const char* it=queryString; it != queryString+queryLength; ++it)
124 if(inPlaceholder &&
'0' <= *it && *it <=
'9' && intBufferSize <
sizeof(intBuffer)-1)
126 intBuffer[intBufferSize++] = *it;
132 paramOrder.push_back(
std::atoi(intBuffer));
135 std::memset(intBuffer, 0,
sizeof(intBuffer));
136 inPlaceholder =
false;
139 if(*it ==
'?') inPlaceholder =
true;
141 buffer[realQueryLength++] = *it;
144 if(inPlaceholder) paramOrder.push_back(
std::atoi(intBuffer));
147 for(
unsigned int i=0; i<connection.threads(); ++i)
150 stmt[i]=mysql_stmt_init(&connection.connection(i));
152 throw Error(&connection.connection(i));
154 if(mysql_stmt_prepare(stmt[i], realQueryString, realQueryLength))
155 throw Error(stmt[i]);
157 if(parameterSet) buildBindings(stmt[i], *parameterSet, paramsConversions[i], paramsBindings[i], paramOrder.size()?¶mOrder:0);
158 if(resultSet) buildBindings(stmt[i], *resultSet, resultsConversions[i], resultsBindings[i]);
161 m_initialized =
true;
168 bindBindings(*const_cast<Data::Set*>(parameters), paramsConversions[thread], paramsBindings[thread], paramOrder.size()?¶mOrder:0);
169 for(Data::Conversions::iterator it=paramsConversions[thread].begin(); it!=paramsConversions[thread].end(); ++it)
170 if(!(paramsBindings[thread][it->first].is_null && *paramsBindings[thread][it->first].is_null)) it->second->convertParam();
171 if(mysql_stmt_bind_param(stmt[thread], paramsBindings[thread].
get())!=0)
throw Error(stmt[thread]);
174 if(mysql_stmt_execute(stmt[thread])!=0)
throw Error(stmt[thread]);
179 bindBindings(row, resultsConversions[thread], resultsBindings[thread]);
180 if(mysql_stmt_bind_result(stmt[thread], resultsBindings[thread].
get())!=0)
throw Error(stmt[thread]);
181 switch (mysql_stmt_fetch(stmt[thread]))
184 throw Error(stmt[thread]);
188 for(Data::Conversions::iterator it=resultsConversions[thread].begin(); it!=resultsConversions[thread].end(); ++it)
189 if(!(resultsBindings[thread][it->first].is_null && *resultsBindings[thread][it->first].is_null)) it->second->convertResult();
196 if(*m_stop[thread])
goto end;
197 executeParameters(parameters, thread);
206 bindBindings(row, resultsConversions[thread], resultsBindings[thread]);
207 if(!executeResult(row, thread))
219 if(*m_stop[thread])
goto end;
220 if(rows) connection.getFoundRows(rows, thread);
224 if(*m_stop[thread])
goto end;
225 if(rows) *rows = mysql_stmt_affected_rows(stmt[thread]);
226 if(*m_stop[thread])
goto end;
227 if(insertId) *insertId = mysql_stmt_insert_id(stmt[thread]);
232 connection.rollback(thread);
234 connection.commit(thread);
235 mysql_stmt_free_result(stmt[thread]);
236 mysql_stmt_reset(stmt[thread]);
242 if(*m_stop[thread])
goto end;
243 executeParameters(parameters, thread);
244 if(*m_stop[thread])
goto end;
245 retval=executeResult(results, thread);
248 connection.rollback(thread);
250 connection.commit(thread);
251 mysql_stmt_free_result(stmt[thread]);
252 mysql_stmt_reset(stmt[thread]);
263 if(*m_stop[thread])
break;
264 executeParameters(
set, thread);
265 if(*m_stop[thread])
break;
266 if(rows) *rows += mysql_stmt_affected_rows(stmt[thread]);
269 connection.rollback(thread);
271 connection.commit(thread);
272 mysql_stmt_free_result(stmt[thread]);
273 mysql_stmt_reset(stmt[thread]);
278 using namespace Data;
282 const int bindSize=order?order->size():
set.numberOfSqlElements();
283 if(!bindSize)
return;
284 bindings.reset(
new MYSQL_BIND[bindSize]);
286 std::memset(bindings.get(), 0,
sizeof(MYSQL_BIND)*bindSize);
288 for(
int i=0; i<bindSize; ++i)
290 const unsigned char index = order?(*order)[i]:i;
300 bindings[i].is_unsigned=1;
309 bindings[i].buffer_type=MYSQL_TYPE_TINY;
315 bindings[i].buffer_type=MYSQL_TYPE_SHORT;
321 bindings[i].buffer_type=MYSQL_TYPE_LONG;
327 bindings[i].buffer_type=MYSQL_TYPE_LONGLONG;
333 bindings[i].buffer_type=MYSQL_TYPE_FLOAT;
339 bindings[i].buffer_type=MYSQL_TYPE_DOUBLE;
346 bindings[i].
buffer = &conv->internal;
347 bindings[i].buffer_type = MYSQL_TYPE_DATE;
348 conversions[i].reset(conv);
355 bindings[i].
buffer = &conv->internal;
356 bindings[i].buffer_type = MYSQL_TYPE_DATETIME;
357 conversions[i].reset(conv);
364 bindings[i].
buffer = &conv->internal;
365 bindings[i].buffer_type = MYSQL_TYPE_TIME;
366 conversions[i].reset(conv);
375 conversions[i].reset(conv);
384 conversions[i].reset(conv);
394 conversions[i].reset(conv);
401 bindings[i].buffer_length = element.
size;
402 bindings[i].buffer_type = element.
type==
CHAR?MYSQL_TYPE_STRING:MYSQL_TYPE_BLOB;
417 const int bindSize=order?order->size():
set.numberOfSqlElements();
418 for(
int i=0; i<bindSize; ++i)
420 const unsigned char index = order?(*order)[i]:i;
429 Data::Conversions::iterator it=conversions.find(i);
430 if(it==conversions.end())
431 bindings[i].buffer=element.
data;
434 it->second->external=element.
data;
435 bindings[i].buffer=it->second->getPointer();
444 *(boost::posix_time::ptime*)external=boost::posix_time::ptime(boost::gregorian::date(
internal.year,
internal.month,
internal.day), boost::posix_time::time_duration(
internal.hour,
internal.minute,
internal.second));
448 *(boost::posix_time::ptime*)external==boost::posix_time::not_a_date_time;
454 std::memset(&
internal, 0,
sizeof(MYSQL_TIME));
455 internal.year = ((boost::posix_time::ptime*)external)->date().year();
456 internal.month = ((boost::posix_time::ptime*)external)->date().month();
457 internal.day = ((boost::posix_time::ptime*)external)->date().day();
458 internal.hour = ((boost::posix_time::ptime*)external)->time_of_day().hours();
459 internal.minute = ((boost::posix_time::ptime*)external)->time_of_day().minutes();
460 internal.second = ((boost::posix_time::ptime*)external)->time_of_day().seconds();
467 *(boost::gregorian::date*)external=boost::gregorian::date(
internal.year,
internal.month,
internal.day);
471 *(boost::gregorian::date*)external==boost::gregorian::date(boost::gregorian::not_a_date_time);
477 std::memset(&
internal, 0,
sizeof(MYSQL_TIME));
478 internal.year = ((boost::gregorian::date*)external)->year();
479 internal.month = ((boost::gregorian::date*)external)->month();
480 internal.day = ((boost::gregorian::date*)external)->day();
485 *(boost::posix_time::time_duration*)external = boost::posix_time::time_duration(
internal.neg?
internal.hour*-1:
internal.hour,
internal.minute,
internal.second);
490 std::memset(&
internal, 0,
sizeof(MYSQL_TIME));
491 internal.hour = std::abs(((boost::posix_time::time_duration*)external)->hours());
492 internal.minute = std::abs(((boost::posix_time::time_duration*)external)->minutes());
493 internal.second = std::abs(((boost::posix_time::time_duration*)external)->seconds());
494 internal.neg = ((boost::posix_time::time_duration*)external)->hours() < 0 ? 1:0;
501 if(data.size() != length) data.resize(length);
506 std::memset(&bind, 0,
sizeof(bind));
507 bind.buffer=&data[0];
508 bind.buffer_length=length;
510 bind.buffer_type=bufferType;
511 if(mysql_stmt_fetch_column(statement, &bind, column, 0)!=0)
throw Error(statement);
519 T& data = *(T*)external;
521 length = data.size();
522 if(length) buffer = &data[0];
528 std::vector<char>& conversionBuffer = inputBuffer;
532 std::wstring& output = *(std::wstring*)external;
533 output.resize(conversionBuffer.size());
535 if(conversionBuffer.size())
539 mbstate_t conversionState = mbstate_t();
540 if(std::use_facet<std::codecvt<wchar_t, char, mbstate_t> >(std::locale(std::locale::classic(),
new utf8CodeCvt::utf8_codecvt_facet)).in(conversionState, (
const char*)&conversionBuffer.front(), (
const char*)&conversionBuffer.front() + conversionBuffer.size(), tmp, &output[0], &output[0] + output.size(), it)!=std::codecvt_base::ok)
542 output.resize(it-&output[0]);
543 conversionBuffer.clear();
551 wstring& data = *(wstring*)external;
553 inputBuffer.resize(data.size()*
sizeof(wchar_t));
555 if(inputBuffer.size())
559 mbstate_t conversionState = mbstate_t();
560 if(use_facet<codecvt<wchar_t, char, mbstate_t> >(locale(locale::classic(),
new utf8CodeCvt::utf8_codecvt_facet)).out(conversionState, (
const wchar_t*)&data[0], (
const wchar_t*)&data[0] + data.size(), tmp, &inputBuffer.front(), &inputBuffer.front() + inputBuffer.size(), it)!=codecvt_base::ok)
throw ASql::Error(
CodeConversionErrorMsg, -1);
561 inputBuffer.resize(it-&inputBuffer[0]);
564 buffer=&inputBuffer.front();
565 length = inputBuffer.size();
587 for(
unsigned int i=0; i<connection.threads(); ++i)
588 mysql_stmt_close(stmt[i]);