Click here to Skip to main content
15,885,216 members
Articles / Web Development / HTML

A C++ Embedded Web Server

Rate me:
Please Sign up or sign in to vote.
4.76/5 (47 votes)
23 Jun 2014BSD7 min read 449.1K   8.5K   209  
Give a C++ application its own web page
/*
  SQLiteDatabase.cpp - CSQLiteDatabase implementation, a wrapper for the SQLite database
*/

#include "StdAfx.h"
#include ".\sqlitedatabase.h"

///
///  Access a SQLite database.
///
/// \param[in] dbfname database filename, null terminated char string

CSQLiteDatabase::CSQLiteDatabase(const wchar_t * dbfname )
{
	// remember the dtabase filename
	myDBFName = dbfname;
	// open the database
	Open();
	// allocate room for pointers to 10,000 values returned from a query
//	myRows = new string[ 10000 ];
	// clear the error
	myError = 0;
}
/*****************************************************************
  CSQLiteDatabase destructor.
*/
CSQLiteDatabase::~CSQLiteDatabase(void)
{
	Close();
//	delete[] myRows;
	myRows.clear();
}
/*****************************************************************
  Open.

  This opens, creating if neccessary, a UTF-16 database

*/
void CSQLiteDatabase::Open()
{
	int rc = sqlite3_open16(myDBFName.c_str(), &db);
	if( rc ) {
		printf("Cannot open database %s",myDBFName);
		exit(1);
	}
}
/*****************************************************************
  Close.
*/
void CSQLiteDatabase::Close()
{
	sqlite3_close(db);

}
/*****************************************************************
  callback - called by sqlite for each row returned by a query

  In:
  myRows - pointer to CString array to store the results
  argc - number of columns
  argv - pointer to string array containing results
  azColName - pointer to array of column names

  Notes:
  Assumes that the column count is always constant for each query
  Will not store more than 1000 values
  RowCount must be zeroed before each query

*/
int CSQLiteDatabase::RowCount;
int CSQLiteDatabase::callback(void *myRows, int argc, char **argv, char **azColName)
{
	for(int kcol=0; kcol<argc; kcol++){
		if( ! argv[kcol] ) {
			// a "null" value - we will just return an empty string
			((vector<string> *) myRows)->push_back(string(""));
		} else {
			((vector<string> *) myRows)->push_back(string( argv[kcol] ));
		}

	}
	RowCount++;

	return 0;
}
/**
  Apply SQL query to database.

 \param[in] sQ SQL query string

 \return 
  the number of rows returned by the query.  
  -1 indicates an error
  -2 too many rows

  The data returned by the query, if any, will be in myRows
  To access the second column in the third row
  myRows[ 2 * cols + 1 ]

*/
int CSQLiteDatabase::Query( string & sQ )
{
	RowCount = 0;
	myRows.clear();
	int rc = sqlite3_exec(db, sQ.c_str(), callback, &myRows, &myError);
	if( rc!=SQLITE_OK ){
		if( rc==SQLITE_ABORT ) {
			myError = "Too many rows returned";
			return -2;
		}
		return -1;
	}
	myLastID = (int)sqlite3_last_insert_rowid( db );

	myRowCount = RowCount;
	return myRowCount;

}
/** ***************************************************************
	Enable speed optimization.

When synchronous is FULL (2), the SQLite database engine will pause at critical moments to make sure that data has actually been written to the disk surface before continuing. 
This ensures that if the operating system crashes or if there is a power failure, the database will be uncorrupted after rebooting. 
FULL synchronous is very safe, but it is also slow. When synchronous is NORMAL, the SQLite database engine will still pause at the most critical moments, 
but less often than in FULL mode. There is a very small (though non-zero) chance that a power failure at just the wrong time could corrupt the database in NORMAL mode. 
But in practice, you are more likely to suffer a catastrophic disk failure or some other unrecoverable hardware fault. 
With synchronous OFF (0), SQLite continues without pausing as soon as it has handed data off to the operating system. 
If the application running SQLite crashes, the data will be safe,
but the database might become corrupted if the operating system crashes or the computer loses power before that data has been written to the disk surface. 
On the other hand, some operations are as much as 50 or more times faster with synchronous OFF.

In SQLite version 2, the default value is NORMAL. For version 3, the default was changed to FULL.



*/
void CSQLiteDatabase::setFast()
{
	Query("PRAGMA synchronous = OFF;");
}

/**

  Submit unicode query, retrieve unicode data.

  @param[in] q  unicode query
  @return  number of rows retrieved, -1 for error

  the row data is stored in CSQLiteDatabase::myRows16

*/
int CSQLiteDatabase::Query16( wstring const & q )
{
	myError = 0;
	// submit query - just one
	void const * tail = 0;
	sqlite3_stmt * st = 0;
	if( sqlite3_prepare16_v2( db, q.c_str(), -1, &st, &tail ) != SQLITE_OK ) {
		// error in query - provide human readable msg
		int nErrMsg = 1 + (int)strlen(sqlite3_errmsg(db));
		myError = (char*)sqlite3_malloc(nErrMsg);
		if( myError ){
			memcpy((void*)myError, sqlite3_errmsg(db), nErrMsg);
		} else {
			myError = "out of memory";
		}
		return -1;
	}
	int col_count = sqlite3_column_count( st );

	// loop over rows returned
	myRowCount = 0;
	myRows16.clear();
	while( sqlite3_step( st ) == SQLITE_ROW ) {
		myRowCount++;
		// loop over columns
		for( int kcol = 0; kcol < col_count; kcol++ ) {
			if( sqlite3_column_type( st, kcol ) == SQLITE_NULL )
				myRows16.push_back( wstring(L""));
			else
				myRows16.push_back( wstring( ( wchar_t * )sqlite3_column_text16(st, kcol)) );
		}
	}

	// clean up
	sqlite3_finalize( st );
	myLastID = (int)sqlite3_last_insert_rowid( db );
	return myRowCount;
}


/**************************************************************************

//   Designed and coded by James Bremner, Raven's Point Consulting,
//   james@ravenspoint.com

  This file is under cvs version control

  If it has been released, the release name will be here: $Name: tip $

  Below is more detailed information describing the precise version

  $Header: C:\Documents and Settings\james\My Documents\code\webem\kenai/src/sqlite/SQLiteDatabase.cpp,v 380e7e273298 2008/09/09 21:28:57 james $

*/



By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The BSD License


Written By
Founder Raven's Point Consulting
Canada Canada
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions