Пример #1
0
NValue NValue::opDivideDecimals(const NValue lhs, const NValue rhs) const {
    if ((lhs.getValueType() != VALUE_TYPE_DECIMAL) ||
        (rhs.getValueType() != VALUE_TYPE_DECIMAL))
    {
        throw SQLException(SQLException::dynamic_sql_error, "No decimal NValue in decimal subtract");
    }

    if (lhs.isNull() || rhs.isNull()) {
        TTInt retval;
        retval.SetMin();
        return getDecimalValue( retval );
    }

    TTLInt calc;
    calc.FromInt(lhs.getDecimal());
    calc *= NValue::kMaxScaleFactor;
    if (calc.Div(rhs.getDecimal())) {
        char message[4096];
        snprintf( message, 4096, "Attempted to divide %s by %s causing overflow/underflow (or divide by zero)",
                lhs.createStringFromDecimal().c_str(), rhs.createStringFromDecimal().c_str());
        throw SQLException(SQLException::data_exception_numeric_value_out_of_range,
                           message);
    }
    TTInt retval;
    if (retval.FromInt(calc)  || retval > s_maxDecimalValue || retval < s_minDecimalValue) {
        char message[4096];
        snprintf( message, 4096, "Attempted to divide %s by %s causing overflow. Unscaled result was %s",
                lhs.createStringFromDecimal().c_str(), rhs.createStringFromDecimal().c_str(),
                calc.ToString(10).c_str());
        throw SQLException(SQLException::data_exception_numeric_value_out_of_range,
                           message);
    }
    return getDecimalValue(retval);
}
Пример #2
0
static void throwInvalidDistanceDWithin(const std::string& msg)
{
    std::ostringstream oss;
    oss << "Invalid input to DWITHIN function: '" << msg << "'.";
    throw SQLException(SQLException::data_exception_invalid_parameter,
                       oss.str().c_str());
}
Пример #3
0
static void throwInvalidPolygonLongitude(const std::string& input)
{
    std::ostringstream oss;
    oss << "Invalid input to POLYGONFROMTEXT: '" << input << "'";
    oss << ".  Longitude must be in the range [-180,180].";
    throw SQLException(SQLException::data_exception_invalid_parameter,
                       oss.str().c_str());
}
Пример #4
0
static void throwInvalidWktPoly(const std::string& reason)
{
    std::ostringstream oss;
    oss << "Invalid input to POLYGONFROMTEXT: " << reason << ".  ";
    oss << "Expected input of the form 'POLYGON((<lng> <lat>, ...), ...)'";
    throw SQLException(SQLException::data_exception_invalid_parameter,
                       oss.str().c_str());
}
Пример #5
0
static void throwInvalidWktPoint(const std::string& input)
{
    std::ostringstream oss;
    oss << "Invalid input to POINTFROMTEXT: ";
    oss << "'" << input << "', ";
    oss << "expected input of the form 'POINT(<lng> <lat>)'";
    throw SQLException(SQLException::data_exception_invalid_parameter,
                       oss.str().c_str());
}
Пример #6
0
inline static void throwTimestampFormatError(const std::string &str)
{
    char message[4096];
    // No space separator for between the date and time
    snprintf(message, 4096, "Attempted to cast \'%s\' to type %s failed. Supported format: \'YYYY-MM-DD HH:MM:SS.UUUUUU\'"
             "or \'YYYY-MM-DD\'",
             str.c_str(), valueToString(VALUE_TYPE_TIMESTAMP).c_str());
    throw SQLException(SQLException::dynamic_sql_error, message);
}
Пример #7
0
//-----------------
int Statement::executeUpdate(const std::string& sql)
{
	int rc = sqlite3_exec(mhdbc->hdbc, (const char*)sql.c_str(), 0, 0, NULL);
	if( rc !=SQLITE_OK)
	{
		throw SQLException( (const char*)sqlite3_errmsg( mhdbc->hdbc ) );
	}
	return sqlite3_changes(mhdbc->hdbc);
}
Пример #8
0
void SQLCode::buildSQLStatement(SQLVarParms& varParms, SQLStatement& rSqlStatement)
{
	FUNCTION_ENTRY("SQLCode::_ConstructSQLStatement()");
	std::string strSQLKey;
	SQLStatement SQLFormats;
	int nDbType = 0;
	size_t uiTotalSQLSize = 0;	

	try
	{
		size_t uVarCount = varParms.size();
		if (uVarCount < defMINPARAMSIZE)
			TA_THROW(BadParamCount("the PrepareStatement parameter count error"));

		_GetDbTypeAndSQLKey(varParms, strSQLKey);
		_GetSQLFormat(strSQLKey, SQLFormats);
		//_GetSQLID(strSQLKey, rSqlStatement);

		_BuildNormalSQL(varParms, SQLFormats, rSqlStatement);
		_PrintSQL(strSQLKey, rSqlStatement);			
	}
	catch (BadParamCount* e)
	{
		SQLCodeException SQLException(e->what());
		throw SQLException;
	}
	catch (BadIndex* e)
	{
		SQLCodeException SQLException(e->what());
		throw SQLException;
	}
	catch(DbTypeNotSupported* e)
	{
		SQLCodeException SQLException(e->what());
		throw SQLException;
	}
	catch (...)
	{
		SQLCodeException SQLException("Unknown SQLCode exception");
		throw SQLException;
	}

	FUNCTION_EXIT;
}
Пример #9
0
String Query::toSQL() const
{
	if (m_expectedFileds.size() == 0)
		throw SQLException("No fields to query");
	bool selectAll = (m_expectedFileds[0].trim() == "*");

	String where = m_where->toSQL();
	String having = m_having->toSQL();
	StringBuilder sql(128 + where.length() + having.length());

	//String::format("select %s from %s where %s", ...);
	// select *
	sql.append("select ");
	if (m_distinct)
		sql.append("distinct ");
	sql.append(String(",").join(m_expectedFileds));
	// from table
	sql.append(" from ");
	sql.append(table());
	// where
	if (!m_where.equals(CW_NONE)) {
		sql.append(" where ");
		sql.append(where);
	}
	// group-by
	if (m_groupBy.size() > 0) {
		sql.append(" group by ");
		sql.append(String(",").join(m_groupBy));
	}
	// having
	if (!m_having.equals(CW_NONE)) {
		sql.append(" having ");
		sql.append(having);
	}
	// order by
	for (size_t i=0; i<m_orderBy.size(); i++) {
		sql.append(" order by ");
		sql.append(m_orderBy[i].key);
		sql.append(m_orderBy[i].value ? " desc " : "");
	}

	// limit
	if (m_limit > 0) {
		// TODO: add more generic way('limit' is just in mysql/pg)
		sql.append(" limit ");
		sql.append((int)m_limit);

	}
	// offset
	if (m_offset > 0) {
		sql.append(" offset ");
		sql.append((int)m_offset);

	}
	return sql.toString();
}
Пример #10
0
//-----------------------
boost::shared_ptr<ResultSet> Statement::executeQuery( const std::string& sql )
{
	int rc = sqlite3_prepare_v2(mhdbc->hdbc, (const char*)sql.c_str(), strlen((const char*)sql.c_str()) * sizeof(char), &mhstmt->hstmt,NULL);
	if( rc !=SQLITE_OK)
	{
		throw SQLException( (const char*)sqlite3_errmsg( mhdbc->hdbc ) );
	}
	mrset.reset( new ResultSet(mhdbc,mhstmt));
	return mrset;
}
Пример #11
0
/*
 * This code is needed in the limit executor as well as anywhere limit
 * is inlined. Centralize it here.
 */
void
LimitPlanNode::getLimitAndOffsetByReference(const NValueArray &params, int &limit, int &offset)
{
    limit = getLimit();
    offset = getOffset();

    // Limit and offset parameters strictly integers. Can't limit <?=varchar>.
    // Converting the loop counter to NValue's doesn't make it cleaner -
    // and probably makes it slower. Would have to initialize an nvalue for
    // each loop iteration.
    if (getLimitParamIdx() != -1) {
        limit = ValuePeeker::peekInteger(params[getLimitParamIdx()]);
        if (limit < 0) {
            throw SQLException(SQLException::data_exception_invalid_parameter,
                               "Negative parameter to LIMIT");
        }

    }
    if (getOffsetParamIdx() != -1) {
        offset = ValuePeeker::peekInteger(params[getOffsetParamIdx()]);
        if (offset < 0) {
            throw SQLException(SQLException::data_exception_invalid_parameter,
                               "Negative parameter to LIMIT OFFSET");
        }
    }

    // If the limit expression is not null, we need to evaluate it and assign
    // the result to limit, offset must be 0
    if (limitExpression != NULL) {
        // The expression should be an operator expression with either constant
        // value expression or parameter value expression as children
        limitExpression->substitute(params);
        limit = ValuePeeker::peekAsInteger(limitExpression->eval(NULL, NULL));
        assert(offset == 0);
    }
}
/* {{{ MySQL_PreparedResultSetMetaData::getColumnDisplaySize -I- */
unsigned int
MySQL_PreparedResultSetMetaData::getColumnDisplaySize(unsigned int columnIndex)
{
	CPP_ENTER("MySQL_PreparedResultSetMetaData::getColumnDisplaySize");
	CPP_INFO_FMT("this=%p", this);
	checkColumnIndex(columnIndex);
	const MYSQL_FIELD * const field = getFieldMeta(columnIndex);
	const sql::mysql::util::OUR_CHARSET * const cs = sql::mysql::util::find_charset(field->charsetnr);
	if (!cs) {
		std::ostringstream msg("Server sent uknown charsetnr (");
		msg << field->charsetnr << ") . Please report";
		throw SQLException(msg.str());
	}
	int ret = field->length / cs->char_maxlen;
	CPP_INFO_FMT("column=%u display_size=%d", columnIndex, ret);
	return ret;
}
Пример #13
0
Connection * Database::getConnection() throw (SQLException)
{
    if (dbConnection == NULL)
    {
        driver = get_driver_instance();
        if (driver != NULL)
        {
            dbConnection = driver ->connect(hostname, username, password);
            dbConnection ->setSchema(schema);
        }
        else
        {
            throw SQLException("Unable to find a driver");
        }
    }
    return dbConnection;
}
/* {{{ MySQL_PreparedResultSetMetaData::isCaseSensitive -I- */
bool
MySQL_PreparedResultSetMetaData::isCaseSensitive(unsigned int columnIndex)
{
	CPP_ENTER("MySQL_PreparedResultSetMetaData::isCaseSensitive");
	CPP_INFO_FMT("this=%p", this);
	checkColumnIndex(columnIndex);
	const MYSQL_FIELD * const field = getFieldMeta(columnIndex);
	if (field->flags & NUM_FLAG || field->type == MYSQL_TYPE_NEWDECIMAL || field->type == MYSQL_TYPE_DECIMAL) {
		return false;
	}
	const sql::mysql::util::OUR_CHARSET * const cs = sql::mysql::util::find_charset(field->charsetnr);
	if (!cs) {
		std::ostringstream msg("Server sent uknown charsetnr (");
		msg << field->charsetnr << ") . Please report";
		throw SQLException(msg.str());
	}
	return NULL == strstr(cs->collation, "_ci");
}
Пример #15
0
std::shared_ptr<Connection>  Database::getConnection(std::string user,std::string password)
{
   LOG_DEBUG(std::string(__FILE__) + " " + std::to_string(__LINE__));
   std::lock_guard<std::mutex> lock(g_i_mutex);
   SQLHENV   henv;
   SQLHDBC   hdbc;
   SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv);
   SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (void *) SQL_OV_ODBC3, 0);
   SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc);
   SQLRETURN ret; 
   SQLCHAR outstr[1024];
   SQLSMALLINT outstrlen;
   std::string dsnname;
   dsnname += "DSN=" + dsnentry_ + ";UID=" + user + ";PWD=" + password;
   LOG_DEBUG(std::string("ODBCSYSINI :") + std::string(getenv("ODBCSYSINI")));
   LOG_DEBUG(std::string("ODBCINI:") + std::string(getenv("ODBCINI")));
   LOG_DEBUG(std::string("TNS_ADMIN:") + std::string(getenv("TNS_ADMIN")));
   LOG_DEBUG(dsnname);
   ret = SQLDriverConnect(hdbc, NULL, (SQLCHAR*)dsnname.c_str(), SQL_NTS,outstr, sizeof(outstr), &outstrlen,SQL_DRIVER_COMPLETE);
   LOG_DEBUG(std::string(__FILE__) + " " + std::to_string(__LINE__));
   if (SQL_SUCCEEDED(ret)) 
   {
      if (ret == SQL_SUCCESS_WITH_INFO) 
      {
         LOG_DEBUG("SQLDriverConnect");
         ODBCError err;
         LOG_DEBUG(err("SQLDriverConnect", hdbc, SQL_HANDLE_DBC));
      }
      std::shared_ptr<Connection> cnx(new Connection(user,password,henv,hdbc));
      cnx->setProvider(provider_);
      cnx->setSchema(schema_);
      LOG_DEBUG(std::string("Provider set for connection : ") + DBPROVIDERS[provider_]);
      return move(cnx);
   } 
   else  
   {
      ODBCError err;
      std::string message = err("SQLDriverConnect", hdbc, SQL_HANDLE_DBC) + "\nDSN : " + dsnentry_ + "\nDatabase user : " + user;
      throw SQLException(message);
   }
}
Пример #16
0
  // returns the actual ODBC cursor type this datasource would
  // use for a given ResultSet type
inline int getODBCCursorTypeFor(int rsType, const DriverInfo* di)
{
  int r;
  switch(rsType) {
  case ResultSet::TYPE_FORWARD_ONLY:
    r=SQL_CURSOR_FORWARD_ONLY;
    break;
  case ResultSet::TYPE_SCROLL_INSENSITIVE:
    r=SQL_CURSOR_STATIC;
    break;
  case ResultSet::TYPE_SCROLL_SENSITIVE:
    if(di->getCursorMask()&SQL_SO_DYNAMIC) {
      r=SQL_CURSOR_DYNAMIC;
    } else {
      r=SQL_CURSOR_KEYSET_DRIVEN;
    }
    break;
  default:
    throw SQLException(ODBCXX_STRING_CONST("[libodbc++]: Invalid ResultSet type ")+intToString(rsType), ODBCXX_STRING_CONST("S1009"));
  }

  return r;
}
/* {{{ MySQL_Connection::init() -I- */
void MySQL_Connection::init(ConnectOptionsMap & properties)
{
	CPP_ENTER_WL(intern->logger, "MySQL_Connection::init");

	intern->is_valid = true;

	MySQL_Uri uri;

	sql::SQLString userName;
	sql::SQLString password;
	sql::SQLString defaultCharset("utf8");
	sql::SQLString characterSetResults("utf8");

	sql::SQLString sslKey, sslCert, sslCA, sslCAPath, sslCipher, postInit;
	bool ssl_used = false;
	int flags = CLIENT_MULTI_RESULTS;

	const int * p_i;
	const bool * p_b;
	const sql::SQLString * p_s;
	bool opt_reconnect = false;
	bool opt_reconnect_value = false;
	bool client_doesnt_support_exp_pwd = false;


	/* Values set in properties individually should have priority over those
	   we restore from Uri */
	sql::ConnectOptionsMap::const_iterator it = properties.find("hostName");

	if (it != properties.end())	{
		if ((p_s = boost::get< sql::SQLString >(&it->second))) {
            /* Parsing uri prior to processing all parameters, so indivudually
               specified parameters precede over those in the uri */
			parseUri(*p_s, uri);
		} else {
			throw sql::InvalidArgumentException("No string value passed for hostName");
		}
	}

#define PROCESS_CONN_OPTION(option_type, options_map) process_connection_option< option_type >(it, options_map, sizeof(options_map)/sizeof(String2IntMap), proxy)

	for (it = properties.begin(); it != properties.end(); ++it) {
		if (!it->first.compare("userName")) {
			if ((p_s = boost::get< sql::SQLString >(&it->second))) {
				userName = *p_s;
			} else {
				throw sql::InvalidArgumentException("No string value passed for userName");
			}
		} else if (!it->first.compare("password")) {
			if ((p_s = boost::get< sql::SQLString >(&it->second))) {
				password = *p_s;
			} else {
				throw sql::InvalidArgumentException("No string value passed for password");
			}
		} else if (!it->first.compare("port")) {
			if ((p_i = boost::get< int >(&it->second))) {
				uri.setPort(static_cast<unsigned int>(*p_i));
			} else {
				throw sql::InvalidArgumentException("No long long value passed for port");
			}
		} else if (!it->first.compare("socket")) {
			if ((p_s = boost::get< sql::SQLString >(&it->second))) {
				uri.setSocket(*p_s);
			} else {
				throw sql::InvalidArgumentException("No string value passed for socket");
			}
		} else if (!it->first.compare("pipe")) {
			if ((p_s = boost::get< sql::SQLString >(&it->second))) {
				uri.setPipe(*p_s);
			} else {
				throw sql::InvalidArgumentException("No string value passed for pipe");
			}
		} else if (!it->first.compare("schema")) {
			if ((p_s = boost::get< sql::SQLString >(&it->second))) {
				uri.setSchema(*p_s);
			} else {
				throw sql::InvalidArgumentException("No string value passed for schema");
			}
		} else if (!it->first.compare("characterSetResults")) {
			if ((p_s = boost::get< sql::SQLString >(&it->second))) {
				characterSetResults = *p_s;
			} else {
				throw sql::InvalidArgumentException("No string value passed for characterSetResults");
			}
		} else if (!it->first.compare("sslKey")) {
			if ((p_s = boost::get< sql::SQLString >(&it->second))) {
				sslKey = *p_s;
			} else {
				throw sql::InvalidArgumentException("No string value passed for sslKey");
			}
			ssl_used = true;
		} else if (!it->first.compare("sslCert")) {
			if ((p_s = boost::get< sql::SQLString >(&it->second))) {
				sslCert = *p_s;
			} else {
				throw sql::InvalidArgumentException("No string value passed for sslCert");
			}
			ssl_used = true;
		} else if (!it->first.compare("sslCA")) {
			if ((p_s = boost::get< sql::SQLString >(&it->second))) {
				sslCA = *p_s;
			} else {
				throw sql::InvalidArgumentException("No string value passed for sslCA");
			}
			ssl_used = true;
		} else if (!it->first.compare("sslCAPath")) {
			if ((p_s = boost::get< sql::SQLString >(&it->second))) {
				sslCAPath = *p_s;
			} else {
				throw sql::InvalidArgumentException("No string value passed for sslCAPath");
			}
			ssl_used = true;
		} else if (!it->first.compare("sslCipher")) {
			if ((p_s = boost::get< sql::SQLString >(&it->second))) {
				sslCipher = *p_s;
			} else {
				throw sql::InvalidArgumentException("No string value passed for sslCipher");
			}
			ssl_used = true;
		} else if (!it->first.compare("defaultStatementResultType")) {
			if (!(p_i = boost::get< int >(&it->second))) {
				throw sql::InvalidArgumentException("No long long value passed for defaultStatementResultType");
			}
			do {
				if (static_cast< int >(sql::ResultSet::TYPE_FORWARD_ONLY) == *p_i) break;
				if (static_cast< int >(sql::ResultSet::TYPE_SCROLL_INSENSITIVE) == *p_i) break;
				if (static_cast< int >(sql::ResultSet::TYPE_SCROLL_SENSITIVE) == *p_i) {
					std::ostringstream msg;
					msg << "Invalid value " << *p_i <<
						" for option defaultStatementResultType. TYPE_SCROLL_SENSITIVE is not supported";
					throw sql::InvalidArgumentException(msg.str());
				}
				std::ostringstream msg;
				msg << "Invalid value (" << *p_i << " for option defaultStatementResultType";
				throw sql::InvalidArgumentException(msg.str());
			} while (0);
			intern->defaultStatementResultType = static_cast< sql::ResultSet::enum_type >(*p_i);
		/* The connector is not ready for unbuffered as we need to refetch */
		} else if (!it->first.compare("defaultPreparedStatementResultType")) {
#if WE_SUPPORT_USE_RESULT_WITH_PS
			if (!(p_i = boost::get< int >(&it->second))) {
				throw sql::InvalidArgumentException("No long long value passed for defaultPreparedStatementResultType");
			}
			do {
				if (static_cast< int >(sql::ResultSet::TYPE_FORWARD_ONLY) == *p_i) break;
				if (static_cast< int >(sql::ResultSet::TYPE_SCROLL_INSENSITIVE) == *p_i) break;
				if (static_cast< int >(sql::ResultSet::TYPE_SCROLL_SENSITIVE) == *p_i) {
					std::ostringstream msg;
					msg << "Invalid value " << *p_i <<
						" for option defaultPreparedStatementResultType. TYPE_SCROLL_SENSITIVE is not supported";
					throw sql::InvalidArgumentException(msg.str());
				}
				std::ostringstream msg;
				msg << "Invalid value (" << *p_i << " for option defaultPreparedStatementResultType";
				throw sql::InvalidArgumentException(msg.str());
			} while (0);
			intern->defaultPreparedStatementResultType = static_cast< sql::ResultSet::enum_type >(*p_i);
#else
			throw SQLException("defaultPreparedStatementResultType parameter still not implemented");

#endif
		} else if (!it->first.compare("metadataUseInfoSchema")) {
			if ((p_b = boost::get<bool>(&it->second))) {
				intern->metadata_use_info_schema = *p_b;
			} else {
				throw sql::InvalidArgumentException("No bool value passed for metadataUseInfoSchema");
			}
		} else if (!it->first.compare("OPT_RECONNECT")) {
			if (!(p_b = boost::get<bool>(&it->second))) {
				throw sql::InvalidArgumentException("No bool value passed for OPT_RECONNECT");
			}
			opt_reconnect = true;
			opt_reconnect_value = *p_b;
		} else if (!it->first.compare("OPT_CHARSET_NAME")) {
			if (!(p_s = boost::get< sql::SQLString >(&it->second))) {
				throw sql::InvalidArgumentException("No SQLString value passed for OPT_CHARSET_NAME");
			}
			defaultCharset = *p_s;
		} else if (!it->first.compare("OPT_NAMED_PIPE")) {
			/* Not sure it is really needed */
			uri.setProtocol(NativeAPI::PROTOCOL_PIPE);
		} else if (!it->first.compare("OPT_CAN_HANDLE_EXPIRED_PASSWORDS")) {
			/* We need to know client version at runtime */
			long client_ver= proxy->get_client_version();
			if (proxy->get_client_version() < 50610) {
				// TODO: I think we should throw a warning here
				/* We only need this flag set if application has said it supports expired
				   password mode */
				client_doesnt_support_exp_pwd= true;
			} else {
				if (!(p_b = boost::get< bool >(&it->second))) {
					throw sql::InvalidArgumentException("No bool value passed for "
														"OPT_CAN_HANDLE_EXPIRED_PASSWORDS");
				}
				/* We do not care here about server version */
				proxy->options(MYSQL_OPT_CAN_HANDLE_EXPIRED_PASSWORDS, (const char*)p_b);
			}
		} else if (!it->first.compare("postInit")) {
			if ((p_s = boost::get< sql::SQLString >(&it->second))) {
				postInit= *p_s;
			} else {
				throw sql::InvalidArgumentException("No string value passed for postInit");
			}

		/* If you need to add new integer connection option that should result in
		   calling mysql_optiong - add its mapping to the intOptions array
		 */
		} else if (PROCESS_CONN_OPTION(int, intOptions)) {
			// Nothing to do here

		/* For boolean coonection option - add mapping to booleanOptions array */
		} else if (PROCESS_CONN_OPTION(bool, booleanOptions)) {
			// Nothing to do here

		/* For string coonection option - add mapping to stringOptions array */
		} else if (PROCESS_CONN_OPTION(sql::SQLString, stringOptions)) {
			// Nothing to do here
		} else if (read_connection_flag(it, flags)) {
			// Nothing to do here
		} else {
			// TODO: Shouldn't we really create a warning here? as soon as we are able to
			//       create a warning
		}
        
	} /* End of cycle on connection options map */

#undef PROCESS_CONNSTR_OPTION

	/* libmysql shouldn't think it is too smart */
	if (tcpProtocol(uri) && !uri.Host().compare(util::LOCALHOST)) {
		uri.setHost("127.0.0.1");
	}

// Throwing in case of wrong protocol
#ifdef _WIN32
	if (uri.Protocol() == NativeAPI::PROTOCOL_SOCKET) {
		throw sql::InvalidArgumentException("Invalid for this platform protocol requested(MYSQL_PROTOCOL_SOCKET)");
	}
#else
	if (uri.Protocol() == NativeAPI::PROTOCOL_PIPE) {
		throw sql::InvalidArgumentException("Invalid for this platform protocol requested(MYSQL_PROTOCOL_PIPE)");
	}
#endif

	proxy->use_protocol(uri.Protocol());

	{
		const char tmp_bool = 1;
		proxy->options(MYSQL_SECURE_AUTH, &tmp_bool);
	}

	proxy->options(MYSQL_SET_CHARSET_NAME, defaultCharset.c_str());

	if (ssl_used) {
		/* According to the docs, always returns 0 */
		proxy->ssl_set(sslKey.c_str(), sslCert.c_str(), sslCA.c_str(), sslCAPath.c_str(), sslCipher.c_str());
	}
	CPP_INFO_FMT("hostName=%s", uri.Host().c_str());
	CPP_INFO_FMT("user=%s", userName.c_str());
	CPP_INFO_FMT("port=%d", uri.Port());
	CPP_INFO_FMT("schema=%s", uri.Schema().c_str());
	CPP_INFO_FMT("socket/pipe=%s", uri.SocketOrPipe().c_str());
	if (!proxy->connect(uri.Host(),
						userName,
						password,
						uri.Schema() /* schema */,
						uri.Port(),
						uri.SocketOrPipe() /*socket or named pipe */,
						flags))
	{
		CPP_ERR_FMT("Couldn't connect : %d", proxy->errNo());
		CPP_ERR_FMT("Couldn't connect : (%s)", proxy->sqlstate().c_str());
		CPP_ERR_FMT("Couldn't connect : %s", proxy->error().c_str());
		CPP_ERR_FMT("Couldn't connect : %d:(%s) %s", proxy->errNo(), proxy->sqlstate().c_str(), proxy->error().c_str());

		/* If error is "Password has expired" and application supports it while 
		   mysql client lib does not */
		std::string error_message;
		int native_error= proxy->errNo();

		if (native_error == ER_MUST_CHANGE_PASSWORD_LOGIN
			&& client_doesnt_support_exp_pwd) {

			native_error= deCL_CANT_HANDLE_EXP_PWD;
			error_message= "Your password has expired, but your instance of"
				" Connector/C++ is not linked against mysql client library that"
				" allows to reset it. To resolve this you either need to change"
				" the password with mysql client that is capable to do that,"
				" or rebuild your instance of Connector/C++ against mysql client"
				" library that supports resetting of an expired password.";
		} else {
			error_message= proxy->error();
		}

		sql::SQLException e(error_message, proxy->sqlstate(), native_error);
		proxy.reset();
		throw e;
	}

	if (opt_reconnect) {
		proxy->options(MYSQL_OPT_RECONNECT, (const char *) &opt_reconnect_value);
	}

	setAutoCommit(true);
	setTransactionIsolation(sql::TRANSACTION_REPEATABLE_READ);
	// Different Values means we have to set different result set encoding
	if (characterSetResults.compare(defaultCharset)) {
		setSessionVariable("character_set_results", characterSetResults.length() ? characterSetResults:"NULL");
	}
	intern->meta.reset(new MySQL_ConnectionMetaData(service.get(), proxy, intern->logger));

	if (postInit.length() > 0) {
		service->executeUpdate(postInit);
	}
}
void SQLAdvancedDeleteCommand::commit()
{
	SQLDatabase sql = getSQLConnection();

	QList<QMap<QString, QString> > colInfo = SQLListColumns(sql, tableName);

	QString nameCode("");
	QString valueCode("");

	unsigned int nc = 0;

	for (QList<QMap<QString, QString> >::iterator it = colInfo.begin() ; it != colInfo.end() ; it++) {
		QMap<QString, QString> col = *it;
		if (nc != 0)
			nameCode += ",";

		nameCode += col["name"];
		nc++;
	}


	QString query = QString("SELECT %1 FROM %2 WHERE %3")
			.arg(nameCode)
			.arg(tableName)
			.arg(whereClause);

	SQLResult res = sql.sendQuery(query);

	if (!res.isValid()) {
		throw SQLException("Error storing SQL result", __FILE__, __LINE__);
	}

	unsigned int numRemoved = 0;

	bool first = true;
	while (res.nextRecord()) {
		if (!first)
			valueCode +=",";

		valueCode += "(";

		for (unsigned int i = 0 ; i < nc ; i++) {
			if (i != 0) {
				valueCode += ",";
			}

			valueCode += QString("'%1'").arg(sql.escapeString(res.getString(i)));
		}

		valueCode += ")";

		first = false;
		numRemoved++;
	}

	if (numRemoved != 0) {
		revertQuery = QString("INSERT INTO %1 (%2) VALUES %3")
				.arg(tableName)
				.arg(nameCode)
				.arg(valueCode);

		query = QString("DELETE FROM %1 WHERE %2")
				.arg(tableName)
				.arg(whereClause);

		sql.sendQuery(query);
	} else {
		revertQuery = QString();
	}
}
Пример #19
0
/*
 * Avoid scaling both sides if possible. E.g, don't turn dec * 2 into
 * (dec * 2*kMaxScale*E-12). Then the result of simple multiplication
 * is a*b*E-24 and have to further multiply to get back to the assumed
 * E-12, which can overflow unnecessarily at the middle step.
 */
NValue NValue::opMultiplyDecimals(const NValue &lhs, const NValue &rhs) const {
    if ((lhs.getValueType() != VALUE_TYPE_DECIMAL) &&
        (rhs.getValueType() != VALUE_TYPE_DECIMAL))
    {
        throw SQLException(SQLException::dynamic_sql_error, "Non-decimal NValue in decimal multiply");
    }

    if (lhs.isNull() || rhs.isNull()) {
        TTInt retval;
        retval.SetMin();
        return getDecimalValue( retval );
    }

    if ((lhs.getValueType() == VALUE_TYPE_DECIMAL) &&
        (rhs.getValueType() == VALUE_TYPE_DECIMAL))
    {
        TTLInt calc;
        calc.FromInt(lhs.getDecimal());
        calc *= rhs.getDecimal();
        calc /= NValue::kMaxScaleFactor;
        TTInt retval;
        if (retval.FromInt(calc)  || retval > s_maxDecimalValue || retval < s_minDecimalValue) {
            char message[4096];
            snprintf(message, 4096, "Attempted to multiply %s by %s causing overflow/underflow. Unscaled result was %s",
                    lhs.createStringFromDecimal().c_str(), rhs.createStringFromDecimal().c_str(),
                    calc.ToString(10).c_str());
            throw SQLException(SQLException::data_exception_numeric_value_out_of_range,
                               message);
        }
        return getDecimalValue(retval);
    } else if  (lhs.getValueType() != VALUE_TYPE_DECIMAL)
    {
        TTLInt calc;
        calc.FromInt(rhs.getDecimal());
        calc *= lhs.castAsDecimalAndGetValue();
        calc /= NValue::kMaxScaleFactor;
        TTInt retval;
        if (retval.FromInt(calc)  || retval > s_maxDecimalValue || retval < s_minDecimalValue) {
            char message[4096];
            snprintf(message, 4096, "Attempted to multiply %s by %s causing overflow/underflow. Unscaled result was %s",
                    lhs.createStringFromDecimal().c_str(), rhs.createStringFromDecimal().c_str(),
                    calc.ToString(10).c_str());
            throw SQLException(SQLException::data_exception_numeric_value_out_of_range,
                               message);
        }
        return getDecimalValue(retval);
    }
    else
    {
        TTLInt calc;
        calc.FromInt(lhs.getDecimal());
        calc *= rhs.castAsDecimalAndGetValue();
        calc /= NValue::kMaxScaleFactor;
        TTInt retval;
        if (retval.FromInt(calc)  || retval > s_maxDecimalValue || retval < s_minDecimalValue) {
            char message[4096];
            snprintf(message, 4096, "Attempted to multiply %s by %s causing overflow/underflow. Unscaled result was %s",
                    lhs.createStringFromDecimal().c_str(), rhs.createStringFromDecimal().c_str(),
                    calc.ToString(10).c_str());
            throw SQLException(SQLException::data_exception_numeric_value_out_of_range,
                               message);
        }
        return getDecimalValue(retval);
   }
}
Пример #20
0
/**
 *   Set a decimal value from a serialized representation
 *   This function does not handle scientific notation string, Java planner should convert that to plan string first.
 */
void NValue::createDecimalFromString(const std::string &txt) {
    if (txt.length() == 0) {
        throw SQLException(SQLException::volt_decimal_serialization_error,
                                       "Empty string provided");
    }
    bool setSign = false;
    if (txt[0] == '-') {
        setSign = true;
    }

    /**
     * Check for invalid characters
     */
    for (int ii = (setSign ? 1 : 0); ii < static_cast<int>(txt.size()); ii++) {
        if ((txt[ii] < '0' || txt[ii] > '9') && txt[ii] != '.') {
            char message[4096];
            snprintf(message, 4096, "Invalid characters in decimal string: %s",
                     txt.c_str());
            throw SQLException(SQLException::volt_decimal_serialization_error,
                               message);
        }
    }

    std::size_t separatorPos = txt.find( '.', 0);
    if (separatorPos == std::string::npos) {
        const std::string wholeString = txt.substr( setSign ? 1 : 0, txt.size());
        const std::size_t wholeStringSize = wholeString.size();
        if (wholeStringSize > 26) {
            throw SQLException(SQLException::volt_decimal_serialization_error,
                               "Maximum precision exceeded. Maximum of 26 digits to the left of the decimal point");
        }
        TTInt whole(wholeString);
        if (setSign) {
            whole.SetSign();
        }
        whole *= kMaxScaleFactor;
        getDecimal() = whole;
        return;
    }

    if (txt.find( '.', separatorPos + 1) != std::string::npos) {
        throw SQLException(SQLException::volt_decimal_serialization_error,
                           "Too many decimal points");
    }

    // This is set to 1 if we carry in the scale.
    int carryScale = 0;
    // This is set to 1 if we carry from the scale to the whole.
    int carryWhole = 0;

    // Start with the fractional part.  We need to
    // see if we need to carry from it first.
    std::string fractionalString = txt.substr( separatorPos + 1, txt.size() - (separatorPos + 1));
    // remove trailing zeros
    while (fractionalString.size() > 0 && fractionalString[fractionalString.size() - 1] == '0')
        fractionalString.erase(fractionalString.size() - 1, 1);
    //
    // If the scale is too large, then we will round
    // the number to the nearest 10**-12, and to the
    // furthest from zero if the number is equidistant
    // from the next highest and lowest.  This is the
    // definition of the Java rounding mode HALF_UP.
    //
    // At some point we will read a rounding mode from the
    // Java side at Engine configuration time, or something
    // like that, and have a whole flurry of rounding modes
    // here.  However, for now we have just the one.
    //
    if (fractionalString.size() > kMaxDecScale) {
        carryScale = ('5' <= fractionalString[kMaxDecScale]) ? 1 : 0;
        fractionalString = fractionalString.substr(0, kMaxDecScale);
    } else {
        while(fractionalString.size() < NValue::kMaxDecScale) {
            fractionalString.push_back('0');
        }
    }
    TTInt fractional(fractionalString);

    // If we decided to carry above, then do it here.
    // The fractional string is set up so that it represents
    // 1.0e-12 * units.
    fractional += carryScale;
    if (TTInt((uint64_t)kMaxScaleFactor) <= fractional) {
        // We know fractional was < kMaxScaleFactor before
        // we rounded, since fractional is 12 digits and
        // kMaxScaleFactor is 13.  So, if carrying makes
        // the fractional number too big, it must be eactly
        // too big.  That is to say, the rounded fractional
        // number number has become zero, and we need to
        // carry to the whole number.
        fractional = 0;
        carryWhole = 1;
    }

    // Process the whole number string.
    const std::string wholeString = txt.substr( setSign ? 1 : 0, separatorPos - (setSign ? 1 : 0));
    // We will check for oversize numbers below, so don't waste time
    // doing it now.
    TTInt whole(wholeString);
    whole += carryWhole;
    if (oversizeWholeDecimal(whole)) {
        throw SQLException(SQLException::volt_decimal_serialization_error,
                           "Maximum precision exceeded. Maximum of 26 digits to the left of the decimal point");
    }
    whole *= kMaxScaleFactor;
    whole += fractional;

    if (setSign) {
        whole.SetSign();
    }

    getDecimal() = whole;
}
Пример #21
0
/**
 *   Set a decimal value from a serialized representation
 *   This function does not handle scientific notation string, Java planner should convert that to plan string first.
 */
void NValue::createDecimalFromString(const std::string &txt) {
    if (txt.length() == 0) {
        throw SQLException(SQLException::volt_decimal_serialization_error,
                                       "Empty string provided");
    }
    bool setSign = false;
    if (txt[0] == '-') {
        setSign = true;
    }

    /**
     * Check for invalid characters
     */
    for (int ii = (setSign ? 1 : 0); ii < static_cast<int>(txt.size()); ii++) {
        if ((txt[ii] < '0' || txt[ii] > '9') && txt[ii] != '.') {
            char message[4096];
            snprintf(message, 4096, "Invalid characters in decimal string: %s",
                     txt.c_str());
            throw SQLException(SQLException::volt_decimal_serialization_error,
                               message);
        }
    }

    std::size_t separatorPos = txt.find( '.', 0);
    if (separatorPos == std::string::npos) {
        const std::string wholeString = txt.substr( setSign ? 1 : 0, txt.size());
        const std::size_t wholeStringSize = wholeString.size();
        if (wholeStringSize > 26) {
            throw SQLException(SQLException::volt_decimal_serialization_error,
                               "Maximum precision exceeded. Maximum of 26 digits to the left of the decimal point");
        }
        TTInt whole(wholeString);
        if (setSign) {
            whole.SetSign();
        }
        whole *= kMaxScaleFactor;
        getDecimal() = whole;
        return;
    }

    if (txt.find( '.', separatorPos + 1) != std::string::npos) {
        throw SQLException(SQLException::volt_decimal_serialization_error,
                           "Too many decimal points");
    }

    const std::string wholeString = txt.substr( setSign ? 1 : 0, separatorPos - (setSign ? 1 : 0));
    const std::size_t wholeStringSize = wholeString.size();
    if (wholeStringSize > 26) {
        throw SQLException(SQLException::volt_decimal_serialization_error,
                           "Maximum precision exceeded. Maximum of 26 digits to the left of the decimal point");
    }
    TTInt whole(wholeString);
    std::string fractionalString = txt.substr( separatorPos + 1, txt.size() - (separatorPos + 1));
    // remove trailing zeros
    while (fractionalString.size() > 0 && fractionalString[fractionalString.size() - 1] == '0')
        fractionalString.erase(fractionalString.size() - 1, 1);
    // check if too many decimal places
    if (fractionalString.size() > 12) {
        throw SQLException(SQLException::volt_decimal_serialization_error,
                           "Maximum scale exceeded. Maximum of 12 digits to the right of the decimal point");
    }
    while(fractionalString.size() < NValue::kMaxDecScale) {
        fractionalString.push_back('0');
    }
    TTInt fractional(fractionalString);

    whole *= kMaxScaleFactor;
    whole += fractional;

    if (setSign) {
        whole.SetSign();
    }

    getDecimal() = whole;
}