/*- * Copyright 2005-2007 Guram Dukashvili * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ //--------------------------------------------------------------------------- #include //--------------------------------------------------------------------------- namespace mycpp { //--------------------------------------------------------------------------- utf8::String tm2Str(const struct tm & tv) { utf8::String s; s.resize(19); sprintf(s.c_str(),"%04d-%02d-%02d %02d:%02d:%02d", tv.tm_year + 1900, tv.tm_mon + 1, tv.tm_mday, tv.tm_hour, tv.tm_min, tv.tm_sec); return s; } //--------------------------------------------------------------------------- utf8::String time2Str(int64_t t) { struct tm tv = ksys::time2tm(t); utf8::String s; s.resize(19); sprintf(s.c_str(), "%04d-%02d-%02d %02d:%02d:%02d", tv.tm_year + 1900, tv.tm_mon + 1, tv.tm_mday, tv.tm_hour, tv.tm_min, tv.tm_sec); return s; } //--------------------------------------------------------------------------- int64_t str2Time(const char * s) { struct tm tv; memset(&tv, 0, sizeof(tv)); sscanf(s, "%04d-%02d-%02d %02d:%02d:%02d", &tv.tm_year, &tv.tm_mon, &tv.tm_mday, &tv.tm_hour, &tv.tm_min, &tv.tm_sec); tv.tm_year -= 1900; tv.tm_mon--; return ksys::tm2Time(tv); } //--------------------------------------------------------------------------- ///////////////////////////////////////////////////////////////////////////// //--------------------------------------------------------------------------- DSQLStatement::DSQLStatement() : handle_(NULL), database_(NULL), sqlTextChanged_(false), prepared_(false), executed_(false), storeResults_(false), #if _MSC_VER #pragma warning(disable:4355) #endif params_(*this), values_(*this) #if _MSC_VER #pragma warning(default:4355) #endif { } //--------------------------------------------------------------------------- DSQLStatement::~DSQLStatement() { detach(); } //--------------------------------------------------------------------------- DSQLStatement & DSQLStatement::attach(Database & database) { if( attached() ) newObjectV1C2(EINVAL, __PRETTY_FUNCTION__)->throwSP(); database.dsqlStatements_.add(this, utf8::ptr2Str(this)); database_ = &database; return *this; } //--------------------------------------------------------------------------- DSQLStatement & DSQLStatement::detach() { if( attached() ){ free(); database_->dsqlStatements_.removeByObject(this); database_ = NULL; prepared_ = false; } return *this; } //--------------------------------------------------------------------------- DSQLStatement & DSQLStatement::allocate() { if( !attached() ) newObjectV1C2(EINVAL, __PRETTY_FUNCTION__)->throwSP(); if( !allocated() ){ handle_ = api.mysql_stmt_init(database_->handle_); if( handle_ == NULL ) database_->exceptionHandler(newObjectV1C2( api.mysql_errno(database_->handle_), api.mysql_error(database_->handle_))); } return *this; } //--------------------------------------------------------------------------- DSQLStatement & DSQLStatement::free() { values_.freeRes(); if( allocated() ){ if( api.mysql_stmt_close(handle_) != 0 && api.mysql_errno(database_->handle_) != CR_SERVER_GONE_ERROR ) database_->exceptionHandler(newObjectV1C2( api.mysql_errno(database_->handle_), api.mysql_error(database_->handle_))); handle_ = NULL; prepared_ = false; } return *this; } //--------------------------------------------------------------------------- utf8::String DSQLStatement::compileSQLParameters() { params_.params_.clear(); params_.indexToParam_.clear(); utf8::String text(sqlText_.unique()); utf8::String::Iterator i(text); while( !i.eos() ){ uintptr_t c = i.getChar(); if( c == ':' ){ utf8::String::Iterator i2(i); while( i2.next() && ((c = i2.getChar()) == '_' || (utf8::getC1Type(c) & (C1_ALPHA | C1_DIGIT)) != 0) ); if( i2 - i > 1 && !(i + 1).isDigit() ){ params_.indexToParam_.add(params_.add(utf8::String(i + 1,i2))); text.replace(i,i2,"?"); } } i.next(); } return text; } //--------------------------------------------------------------------------- DSQLStatement & DSQLStatement::prepare() { allocate(); if( sqlTextChanged_ || !prepared_ ){ utf8::String sql(compileSQLParameters()); if( api.mysql_stmt_prepare(handle_, sql.c_str(), (unsigned long) sql.size()) != 0 ){ if( api.mysql_errno(database_->handle_) != ER_UNSUPPORTED_PS ) database_->exceptionHandler(newObjectV1C2( api.mysql_errno(database_->handle_), api.mysql_error(database_->handle_))); } params_.bind_.resize(api.mysql_stmt_param_count(handle_)); values_.bind_.resize(api.mysql_stmt_field_count(handle_)); values_.clear().valuesIndex_.clear(); sqlTextChanged_ = false; prepared_ = true; } else if( executed_ ){ values_.clear().valuesIndex_.clear(); executed_ = false; } return *this; } //--------------------------------------------------------------------------- DSQLStatement & DSQLStatement::execute() { database_->transaction_->start(); values_.freeRes(); prepare(); if( params_.bind_.count() > 0 ){ params_.bind(); if( api.mysql_stmt_bind_param(handle_,params_.bind_.bind()) != 0 ){ database_->exceptionHandler(newObjectV1C2( api.mysql_errno(database_->handle_), api.mysql_error(database_->handle_) )); } } if( params_.bind_.count() == 0 && values_.bind_.count() == 0 ){ if( api.mysql_query(database_->handle_, compileSQLParameters().c_str()) != 0 ) database_->exceptionHandler(newObjectV1C2( api.mysql_errno(database_->handle_), api.mysql_error(database_->handle_))); } else{ if( api.mysql_stmt_execute(handle_) != 0 ){ database_->exceptionHandler(newObjectV1C2( api.mysql_errno(database_->handle_), api.mysql_error(database_->handle_))); } } executed_ = true; if( values_.bind_.count() > 0 ){ values_.lengths_.resize(values_.bind_.count()); values_.res_ = api.mysql_stmt_result_metadata(handle_); if( api.mysql_errno(database_->handle_) != 0 ) database_->exceptionHandler(newObjectV1C2( api.mysql_errno(database_->handle_), api.mysql_error(database_->handle_))); values_.fields_ = api.mysql_fetch_fields(values_.res_); } /* Now buffer all results to client */ if( storeResults_ ) if( api.mysql_stmt_store_result(handle_) != 0 ) database_->exceptionHandler(newObjectV1C2( api.mysql_errno(database_->handle_), api.mysql_error(database_->handle_))); if( database_->transaction_->startCount_ == 1 && values_.bind_.count() > 0 ) values_.fetchAll(); database_->transaction_->commit(); return *this; } //--------------------------------------------------------------------------- ///////////////////////////////////////////////////////////////////////////// // properties /////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// //--------------------------------------------------------------------------- DSQLStatement & DSQLStatement::sqlText(const utf8::String & sqlText) { sqlText_ = sqlText; sqlTextChanged_ = true; prepared_ = false; return *this; } //--------------------------------------------------------------------------- } // namespace fbcpp //---------------------------------------------------------------------------