void SQLiteStatementImpl::compileImplImpl()
{
	if (_pStmt) return;

	std::string statement(toString());
	if (statement.empty())
		throw InvalidSQLStatementException("Empty statements are illegal");

	sqlite3_stmt* pStmt = 0;
	const char* pSql = statement.c_str(); // The SQL to be executed
	int rc = SQLITE_OK;
	const char* pLeftover = 0;
	bool queryFound = false;

	while (rc == SQLITE_OK && !pStmt && !queryFound)
	{
		rc = sqlite3_prepare_v2(_pDB, pSql, -1, &pStmt, &pLeftover);
		if (rc != SQLITE_OK)
		{
			if (pStmt) 
			{
				sqlite3_finalize(pStmt);
			}
			pStmt = 0;
			Utility::throwException(rc, statement);
		}
		else if (rc == SQLITE_OK && pStmt)
		{
			queryFound = true;
		}
		else if (rc == SQLITE_OK && !pStmt) // comment/whitespace ignore
		{
			pSql = pLeftover;
			if (std::strlen(pSql) == 0)
			{
				// empty statement or an conditional statement! like CREATE IF NOT EXISTS
				// this is valid
				queryFound = true;
			}
		}
	}

	clear();
	_pStmt = pStmt;

	// prepare binding
	_pBinder = new Binder(_pStmt);
	_pExtractor = new Extractor(_pStmt);

	int colCount = sqlite3_column_count(_pStmt);

	for (int i = 0; i < colCount; ++i)
	{
		MetaColumn mc(i, sqlite3_column_name(_pStmt, i), Utility::getColumnType(_pStmt, i));
		_columns.push_back(mc);
	}
}
Beispiel #2
0
void Utility::throwException(int rc, const std::string& addErrMsg)
{
	switch (rc)
	{
	case SQLITE_OK:
		break;
	case SQLITE_ERROR:
		throw InvalidSQLStatementException(std::string("SQL error or missing database"), addErrMsg);
	case SQLITE_INTERNAL:
		throw InternalDBErrorException(std::string("An internal logic error in SQLite"), addErrMsg);
	case SQLITE_PERM:
		throw DBAccessDeniedException(std::string("Access permission denied"), addErrMsg);
	case SQLITE_ABORT:
		throw ExecutionAbortedException(std::string("Callback routine requested an abort"), addErrMsg);
	case SQLITE_BUSY:
		throw DBLockedException(std::string("The database file is locked"), addErrMsg);
	case SQLITE_LOCKED:
		throw TableLockedException(std::string("A table in the database is locked"), addErrMsg);
	case SQLITE_NOMEM:
		throw NoMemoryException(std::string("A malloc() failed"), addErrMsg);
	case SQLITE_READONLY:
		throw ReadOnlyException(std::string("Attempt to write a readonly database"), addErrMsg);
	case SQLITE_INTERRUPT:
		throw InterruptException(std::string("Operation terminated by sqlite_interrupt()"), addErrMsg);
	case SQLITE_IOERR:
		throw IOErrorException(std::string("Some kind of disk I/O error occurred"), addErrMsg);
	case SQLITE_CORRUPT:
		throw CorruptImageException(std::string("The database disk image is malformed"), addErrMsg);
	case SQLITE_NOTFOUND:
		throw TableNotFoundException(std::string("Table or record not found"), addErrMsg);
	case SQLITE_FULL:
		throw DatabaseFullException(std::string("Insertion failed because database is full"), addErrMsg);
	case SQLITE_CANTOPEN:
		throw CantOpenDBFileException(std::string("Unable to open the database file"), addErrMsg);
	case SQLITE_PROTOCOL:
		throw LockProtocolException(std::string("Database lock protocol error"), addErrMsg);
	case SQLITE_EMPTY:
		throw InternalDBErrorException(std::string("(Internal Only) Database table is empty"), addErrMsg);
	case SQLITE_SCHEMA:
		throw SchemaDiffersException(std::string("The database schema changed"), addErrMsg);
	case SQLITE_TOOBIG:
		throw RowTooBigException(std::string("Too much data for one row of a table"), addErrMsg);
	case SQLITE_CONSTRAINT:
		throw ConstraintViolationException(std::string("Abort due to constraint violation"), addErrMsg);
	case SQLITE_MISMATCH:
		throw DataTypeMismatchException(std::string("Data type mismatch"), addErrMsg);
	case SQLITE_MISUSE:
		throw InvalidLibraryUseException(std::string("Library used incorrectly"), addErrMsg);
	case SQLITE_NOLFS:
		throw OSFeaturesMissingException(std::string("Uses OS features not supported on host"), addErrMsg);
	case SQLITE_AUTH:
		throw AuthorizationDeniedException(std::string("Authorization denied"), addErrMsg);
	case SQLITE_FORMAT:
		throw CorruptImageException(std::string("Auxiliary database format error"), addErrMsg);
	case SQLITE_NOTADB:
		throw CorruptImageException(std::string("File opened that is not a database file"), addErrMsg);
	case SQLITE_RANGE:
		throw InvalidSQLStatementException(std::string("Bind Parameter out of range (Access of invalid position 0? bind starts with 1!)"), addErrMsg);
	case SQLITE_ROW:
		break; // sqlite_step() has another row ready
	case SQLITE_DONE:
		break; // sqlite_step() has finished executing
	default:
		throw SQLiteException(std::string("Unknown error code: ") + Poco::NumberFormatter::format(rc), addErrMsg);
	}
}
void SQLiteStatementImpl::compileImpl()
{
	if (!_pLeftover)
	{
		_bindBegin = bindings().begin();
	}

	std::string statement(toString());

	sqlite3_stmt* pStmt = 0;
	const char* pSql = _pLeftover ? _pLeftover->c_str() : statement.c_str();

	if (0 == std::strlen(pSql))
		throw InvalidSQLStatementException("Empty statements are illegal");

	int rc = SQLITE_OK;
	const char* pLeftover = 0;
	bool queryFound = false;

	do
	{
		rc = sqlite3_prepare_v2(_pDB, pSql, -1, &pStmt, &pLeftover);
		if (rc != SQLITE_OK)
		{
			if (pStmt) sqlite3_finalize(pStmt);
			pStmt = 0;
			std::string errMsg = sqlite3_errmsg(_pDB);
			Utility::throwException(_pDB, rc, errMsg);
		}
		else if (rc == SQLITE_OK && pStmt)
		{
			queryFound = true;
		}
		else if (rc == SQLITE_OK && !pStmt) // comment/whitespace ignore
		{
			pSql = pLeftover;
			if (std::strlen(pSql) == 0)
			{
				// empty statement or an conditional statement! like CREATE IF NOT EXISTS
				// this is valid
				queryFound = true;
			}
		}
	} while (rc == SQLITE_OK && !pStmt && !queryFound);

	//Finalization call in clear() invalidates the pointer, so the value is remembered here.
	//For last statement in a batch (or a single statement), pLeftover == "", so the next call
	// to compileImpl() shall return false immediately when there are no more statements left.
	std::string leftOver(pLeftover);
	trimInPlace(leftOver);
	clear();
	_pStmt = pStmt;
	if (!leftOver.empty())
	{
		_pLeftover = new std::string(leftOver);
		_canCompile = true;
	}
	else _canCompile = false;

	_pBinder = new Binder(_pStmt);
	_pExtractor = new Extractor(_pStmt);

	if (SQLITE_DONE == _nextResponse && _isExtracted)
	{
		//if this is not the first compile and there has already been extraction
		//during previous step, switch to the next set if there is one provided
		if (hasMoreDataSets())
		{
			activateNextDataSet();
			_isExtracted = false;
		}
	}

	int colCount = sqlite3_column_count(_pStmt);

	if (colCount)
	{
		std::size_t curDataSet = currentDataSet();
		if (curDataSet >= _columns.size()) _columns.resize(curDataSet + 1);
		for (int i = 0; i < colCount; ++i)
		{
			MetaColumn mc(i, sqlite3_column_name(_pStmt, i), Utility::getColumnType(_pStmt, i));
				_columns[curDataSet].push_back(mc);
		}
	}
}
Beispiel #4
0
void Utility::throwException(int rc, const std::string& addErrMsg)
{
    switch (rc)
    {
    case SQLITE_OK:
        break;
    case SQLITE_ERROR:
        throw InvalidSQLStatementException(addErrMsg);
    case SQLITE_INTERNAL:
        throw InternalDBErrorException(addErrMsg);
    case SQLITE_PERM:
        throw DBAccessDeniedException(addErrMsg);
    case SQLITE_ABORT:
        throw ExecutionAbortedException(addErrMsg);
    case SQLITE_BUSY:
        throw DBLockedException(addErrMsg);
    case SQLITE_LOCKED:
    case SQLITE_LOCKED_SHAREDCACHE:
        throw TableLockedException(addErrMsg);
    case SQLITE_NOMEM:
        throw NoMemoryException(addErrMsg);
    case SQLITE_READONLY:
        throw ReadOnlyException(addErrMsg);
    case SQLITE_INTERRUPT:
        throw InterruptException(addErrMsg);
    case SQLITE_IOERR:
        throw IOErrorException(addErrMsg);
    case SQLITE_CORRUPT:
        throw CorruptImageException(addErrMsg);
    case SQLITE_NOTFOUND:
        throw TableNotFoundException(addErrMsg);
    case SQLITE_FULL:
        throw DatabaseFullException(addErrMsg);
    case SQLITE_CANTOPEN:
        throw CantOpenDBFileException(addErrMsg);
    case SQLITE_PROTOCOL:
        throw LockProtocolException(addErrMsg);
    case SQLITE_EMPTY:
        throw InternalDBErrorException(addErrMsg);
    case SQLITE_SCHEMA:
        throw SchemaDiffersException(addErrMsg);
    case SQLITE_TOOBIG:
        throw RowTooBigException(addErrMsg);
    case SQLITE_CONSTRAINT:
        throw ConstraintViolationException(addErrMsg);
    case SQLITE_MISMATCH:
        throw DataTypeMismatchException(addErrMsg);
    case SQLITE_MISUSE:
        throw InvalidLibraryUseException(addErrMsg);
    case SQLITE_NOLFS:
        throw OSFeaturesMissingException(addErrMsg);
    case SQLITE_AUTH:
        throw AuthorizationDeniedException(addErrMsg);
    case SQLITE_FORMAT:
        throw CorruptImageException(addErrMsg);
    case SQLITE_NOTADB:
        throw CorruptImageException(addErrMsg);
    case SQLITE_RANGE:
        throw InvalidSQLStatementException(std::string("Bind parameter out of range (Access of invalid position 0? Bind starts with 1!)"), addErrMsg);
    case SQLITE_ROW:
        break; // sqlite_step() has another row ready
    case SQLITE_DONE:
        break; // sqlite_step() has finished executing
    default:
        throw SQLiteException(std::string("Unknown error code: ") + Poco::NumberFormatter::format(rc), addErrMsg);
    }
}