diff options
| -rw-r--r-- | Jamroot.jam | 0 | ||||
| -rw-r--r-- | project2/Jamfile.jam | 20 | ||||
| -rw-r--r-- | project2/envproc.cpp | 78 | ||||
| -rw-r--r-- | project2/envproc.h | 33 | ||||
| -rw-r--r-- | project2/p2web.cpp | 278 | ||||
| -rw-r--r-- | project2/p2webMain.cpp | 42 | ||||
| -rw-r--r-- | project2/rdbmsDataSource.cpp | 18 | ||||
| -rw-r--r-- | project2/rdbmsDataSource.h | 23 | ||||
| -rw-r--r-- | project2/sourceObject.cpp | 8 | ||||
| -rw-r--r-- | project2/sourceObject.h | 13 | ||||
| -rw-r--r-- | project2/sqlView.cpp | 78 | ||||
| -rw-r--r-- | project2/sqlView.h | 23 | ||||
| -rw-r--r-- | project2/ustring.h | 9 | 
13 files changed, 623 insertions, 0 deletions
diff --git a/Jamroot.jam b/Jamroot.jam new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Jamroot.jam diff --git a/project2/Jamfile.jam b/project2/Jamfile.jam new file mode 100644 index 0000000..7505f92 --- /dev/null +++ b/project2/Jamfile.jam @@ -0,0 +1,20 @@ +alias libxml2 : : : : +	<cflags>"`pkg-config --cflags libxml-2.0`" +	<linkflags>"`pkg-config --libs libxml-2.0`" ; + +lib fcgi : : <name>fcgi ; +lib odbc : : <name>odbc ; + +exe p2web : +	p2webMain.cpp +	sourceObject.cpp +	rdbmsDataSource.cpp +	sqlView.cpp +	envproc.cpp +	libxml2 +	../libmisc +	../libodbcpp : +	<include>../libmisc/ +	<include>../libodbcpp/ +	<library>odbc +	<library>fcgi ; diff --git a/project2/envproc.cpp b/project2/envproc.cpp new file mode 100644 index 0000000..0313c0f --- /dev/null +++ b/project2/envproc.cpp @@ -0,0 +1,78 @@ +#include "envproc.h" +#include "rdbmsDataSource.h" +#include "sqlView.h" +#include <map> +#include <libxml/tree.h> +#include <libxml/xinclude.h> +#include <boost/shared_ptr.hpp> +#include <boost/any.hpp> +#include <boost/foreach.hpp> + +void +EnvironmentProcessor::init() +{ +	elems = regexExtractSet("/([^/?]+)", request_uri.c_str()); +	params = regexExtractMulti("&?([^=]+)=?([^&]*)", query_string.c_str(), 2); +	page = elems.size() > 0 ? elems[0] : "index"; +} + +template <class X, class Y> +void +collectAll(std::map<ustring, Y> & objs, xmlNodePtr node, const ustring & name) +{ +	if (name == node->name) { +		fprintf(stderr, "Found a %s\n", name.c_str()); +		try { +			objs[xmlGetProp(node, BAD_CAST "name")] = Y(new X(node)); +			fprintf(stderr, "Load succeeded\n"); +		} +		catch (const std::exception & e) { +			// Assume the XML node is what we thought it was +			fprintf(stderr, "Load failed (%s)\n", e.what()); +		} +		catch (...) { +			// Assume the XML node is what we thought it was +			fprintf(stderr, "Load failed\n"); +		} +	} +	else { +		for (xmlNodePtr child = node->children; child; child = child->next) { +			collectAll<X, Y>(objs, child, name); +		} +	} +} + +xmlDocPtr +EnvironmentProcessor::process() +{ +	xmlDocPtr doc = xmlNewDoc(BAD_CAST "1.0"); +	xmlDocPtr pageXDoc = xmlReadFile(("present/" + page + ".xml").c_str(), NULL, XML_PARSE_XINCLUDE); +	while (xmlXIncludeProcess(pageXDoc) > 0); +	xmlNodePtr root = xmlDocGetRootElement(pageXDoc); +	// Collect datasources +	RdbmsDataSources rdbmsDataSources; +	collectAll<_RdbmsDataSource>(rdbmsDataSources, root, BAD_CAST "rdbmsdatasource"); +	// Collect views +	SqlViews sqlViews; +	collectAll<_SqlView>(sqlViews, root, BAD_CAST "sqlview"); +	// +	xmlNodePtr root_node = xmlNewNode(NULL, xmlGetProp(root, BAD_CAST "root")); +	try { +		BOOST_FOREACH(SqlViews::value_type s, sqlViews) { +			s.second->execute(rdbmsDataSources, root_node); +		} +	} +	catch (...) { +	} +	xmlDocSetRootElement(doc, root_node); +	char * buf; +	if (asprintf(&buf, "type=\"text/xsl\" href=\"%s\"", +			xmlGetProp(root, BAD_CAST "style")) > 0) { +		xmlAddPrevSibling(root_node, +				xmlNewDocPI(doc, BAD_CAST "xml-stylesheet", BAD_CAST buf)); +	} +	free(buf); +	xmlFreeDoc(pageXDoc); +	return doc; +} + diff --git a/project2/envproc.h b/project2/envproc.h new file mode 100644 index 0000000..64e13c1 --- /dev/null +++ b/project2/envproc.h @@ -0,0 +1,33 @@ +#ifndef ENVPROC_H +#define ENVPROC_H + +#include <string> +#include <libxml/tree.h> +#include "regexex.h" + +class EnvironmentProcessor { +	public: +		template <class getenvFunc> +		EnvironmentProcessor(const getenvFunc & getenv) : +			request_uri(getenv("REQUEST_URI")), +			query_string(getenv("QUERY_STRING")), +			http_host(getenv("HTTP_HOST")), +			request_method(getenv("REQUEST_METHOD")) +		{ +			init(); +		} +		virtual xmlDoc * process(); +	private: +		void init(); + +		std::string request_uri; +		std::string query_string; +		std::string http_host; +		std::string request_method; + +		StringSet elems; +		RegMultiMatch params; +		std::string page; +}; + +#endif diff --git a/project2/p2web.cpp b/project2/p2web.cpp new file mode 100644 index 0000000..3d1b320 --- /dev/null +++ b/project2/p2web.cpp @@ -0,0 +1,278 @@ +#include <stdio.h> +#include <string.h> +#include <map> +#include <stdlib.h> +#include <libxml/tree.h> +#include "connection.h" +#include "selectcommand.h" +#include "column.h" +#include "smartpointer.h" +#include "dsn.h" +#include "xml.h" +#include "regexex.h" + +template <class X> +class Handle : public X, public IsRefCounted { +	public: +		template <class P1> +		Handle(const P1 & p1) : X(p1) +		{ +		} +		Handle() +		{ +		} +}; + +typedef Handle<ODBC::Connection> ConnHandle; +typedef SmartPointer<ConnHandle> ConnHandlePtr; +typedef std::map<int, ConnHandlePtr> ConnectionPool; + +void bindQueryParams(ODBC::Connection & db, ODBC::SelectCommand & sel, int pqid, ODBC::SelectCommand * parent, +		const StringSet & elems, const RegMultiMatch & qs); + +void +addQueryResultsToXml(ODBC::Connection & wdb, ConnectionPool cp, xmlNode * root_node, int dsn, const ODBC::String & sql, +		const ODBC::String & name, const ODBC::String & recordName, int pqid, ODBC::SelectCommand * parent, +		const StringSet & elems, const RegMultiMatch & qs) +{ +	typedef std::map<ODBC::String, xmlNode *> Columns; +	xmlNode * resultXml = xmlNewChild(root_node, NULL, name.c_str(), NULL); +	ODBC::SelectCommand query(*cp[dsn], sql); +	bindQueryParams(wdb, query, pqid, parent, elems, qs); +	while (query.fetch()) { +		Columns columns; +		unsigned int cols = query.columnCount(); +		xmlNode * record = xmlNewChild(resultXml, NULL, recordName.c_str(), NULL); +		for (unsigned int col = 0; col < cols; col += 1) { +			const unsigned char * nameattr = query[col].name.c_str(); +			unsigned char * name, * attr = NULL; +			switch (sscanf((const char *)nameattr, "%a[^_]_%as", &name, &attr))  +			{ +				case 0: +					return; // Make me an exception +					break; +				case 1: +					attr = NULL; +					break; +			} +			char * buf = NULL; +			query[col].writeToBuf(&buf); +			if (buf) { +				if (attr) { +					if (strcmp((const char *)attr, ".") == 0) { +						xmlNewProp(record, name, BAD_CAST buf); +					} +					else { +						Columns::iterator i = columns.find(attr); +						if (i != columns.end()) { +							xmlNewProp(i->second, name, BAD_CAST buf); +						} +					} +				} +				else if (strcmp((const char *)name, "value") == 0) { +					xmlNodeAddContent(record, BAD_CAST buf); +				} +				else { +					columns[name] = xmlNewTextChild(record, NULL, name, BAD_CAST buf); +				} +				free(buf); +			} +			free(name); +			free(attr); +		} +		ODBC::SelectCommand queries(wdb, +				"SELECT d.id AS dsn, q.id AS query, q.sql, q.name, q.recordname, pq.id \ +				FROM dsn d, page_query pq, query q \ +				WHERE pq.parent = ? \ +				AND q.id = pq.query \ +				AND d.id = q.dsn"); +		queries.bindParamI(0, pqid); +		while (queries.fetch()) { +			addQueryResultsToXml(wdb, cp, record, queries["dsn"], +					queries["sql"], queries["name"], queries["recordname"], queries["id"], &query, elems, qs); +		} +	} +} + +void +bindQueryParams(ODBC::Connection & db, ODBC::SelectCommand & sel, int pqid, ODBC::SelectCommand * parent, +		const StringSet & elems, const RegMultiMatch & qs) +{ +	ODBC::SelectCommand params(db, +			"SELECT paramidx, source, key \ +			FROM page_query_params \ +			WHERE pqid = ?"); +	params.bindParamI(0, pqid); +	while (params.fetch()) { +		const char * key = params["key"]; +		const char * src = params["source"]; +		int idx = params["paramidx"]; +		switch (*src) { +			case 'v': // Value +				sel.bindParamS(idx, key); +				break; +			case 'u': // URL token +				sel.bindParamS(idx, elems[atoi(key)]); +				break; +			case 's': // Session variable +				break; +			case 'q': // Query string param +				for(RegMultiMatch::const_iterator u = qs.begin(); u != qs.end(); u++) { +					if ((*u)[0] == key) { +						sel.bindParamS(idx, (*u)[1]); +					} +				} +				break; +			case 'p': // Parent column value +				if (parent) { +					(*parent)[key].rebind(&sel, idx); +				} +				break; +			default: +				; +		} +	} +} + + +int +main(int, char**) +{ +	try { +		std::string request_uri(getenv("REQUEST_URI")); +		std::string query_string(getenv("QUERY_STRING")); +		StringSet elems(regexExtractSet("/([^/?]+)", request_uri.c_str())); +		RegMultiMatch params(regexExtractMulti("&?([^=]+)=?([^&]*)", query_string.c_str(), 2)); +		xmlDoc * doc = xmlNewDoc(BAD_CAST "1.0"); +		xmlNode * root_node = NULL; +		ODBC::String fqdn(getenv("HTTP_HOST")); +		ODBC::DSN main("dbweb", "dbweb", "dbweb"); +		ODBC::Connection db(main); +		int pageId = 0; +		std::string page(elems.size() > 0 ? elems[0] : "index"); +		{ +			ODBC::SelectCommand pageHeaders(db, +					"SELECT p.id, p.name, p.style, p.documentname \ +					FROM site s, domainname dn, page p \ +					WHERE s.id = dn.site  \ +					AND p.pattern = ? \ +					AND dn.fqdn = ? \ +					AND p.site = s.id"); +			pageHeaders.bindParamS(0, page); +			pageHeaders.bindParamS(1, fqdn); +			while (pageHeaders.fetch()) { +				pageId = pageHeaders["id"]; +				root_node = xmlNewNode(NULL, pageHeaders["documentname"]); +				xmlDocSetRootElement(doc, root_node); +				if (!pageHeaders["style"].isNull()) { +					printf("Content-type: text/xml-xslt\r\n"); +					char * buf; +					if (asprintf(&buf, "type=\"text/xsl\" href=\"%s\"", +							pageHeaders["style"].operator const char *()) > 0) { +						xmlAddPrevSibling(root_node, +								xmlNewDocPI(doc, BAD_CAST "xml-stylesheet", BAD_CAST buf)); +					} +					free(buf); +				} +				else { +					printf("Content-type: text/xml\r\n"); +				} +				xmlNewProp(root_node, BAD_CAST "title", pageHeaders["name"]); +			} +		} +		// These were for debug... but why not pass them on? +		xmlNsPtr dbwebns = xmlNewNs(root_node, BAD_CAST "http://dbweb.randomdan.homeip.net/", BAD_CAST "dbweb"); +		xmlNewChild(root_node, dbwebns, BAD_CAST "fqdn", fqdn.c_str()); +		xmlNewChild(root_node, dbwebns, BAD_CAST "requesturi", BAD_CAST request_uri.c_str()); +		// URL elements +		xmlNode * uriElems = xmlNewChild(root_node, dbwebns, BAD_CAST "uriElems", NULL); +		for(StringSet::const_iterator u = elems.begin(); u != elems.end(); u++) { +			xmlNewChild(uriElems, dbwebns, BAD_CAST "uriElem", BAD_CAST u->c_str()); +		} +		// Parameters +		xmlNode * paramsXml = xmlNewChild(root_node, dbwebns, BAD_CAST "params", NULL); +		for(RegMultiMatch::const_iterator u = params.begin(); u != params.end(); u++) { +			xmlNode * param = xmlNewChild(paramsXml, NULL, BAD_CAST "param", BAD_CAST (*u)[1].c_str()); +			xmlNewProp(param, BAD_CAST "name", BAD_CAST (*u)[0].c_str()); +		} +		ConnectionPool cp; +		// Load DSNs +#ifdef DEBUG +		xmlNode * dsnsXml = xmlNewChild(root_node, dbwebns, BAD_CAST "DSNs", NULL); +#endif +		{ +			ODBC::SelectCommand dsns(db, +					"SELECT DISTINCT d.id AS id, d.connectionstring AS connstr \ +					FROM dsn d, page_query pq, query q \ +					WHERE pq.page = ? \ +					AND q.id = pq.query \ +					AND d.id = q.dsn"); +			dsns.bindParamI(0, pageId); +			while (dsns.fetch()) { +				int id = dsns["id"]; +				ODBC::String connstr = dsns["connstr"]; +#ifdef DEBUG +				xmlNode * dsnXml = xmlNewChild(dsnsXml, NULL, BAD_CAST "DSN", NULL); +				xmlNewTextChildf(dsnXml, "id", "%d", id); +				xmlNewTextChildf(dsnXml, "connectionstring", "%s", connstr.c_str()); +#endif +				cp[id] = new ConnHandle(connstr); +			} +		} +		// Exec queries +		{ +			ODBC::SelectCommand queries(db, +					"SELECT d.id AS dsn, q.id AS query, q.sql, q.name, q.recordname, pq.id \ +					FROM dsn d, page_query pq, query q \ +					WHERE pq.page = ? \ +					AND q.id = pq.query \ +					AND d.id = q.dsn \ +					AND pq.parent IS NULL"); +			queries.bindParamI(0, pageId); +#ifdef DEBUG +			xmlNode * queriesXml = xmlNewChild(root_node, dbwebns, BAD_CAST "queries", NULL); +#endif +			while (queries.fetch()) { +#ifdef DEBUG +				int query = queries["query"]; +#endif +				int dsn = queries["dsn"]; +				ODBC::String sql = queries["sql"]; +				ODBC::String name = queries["name"]; +				ODBC::String recordName = queries["recordname"]; +#ifdef DEBUG +				xmlNode * queryXml = xmlNewChild(queriesXml, NULL, BAD_CAST "query", NULL); +				xmlNewTextChildf(queryXml, "query", "%d", query); +				xmlNewTextChildf(queryXml, "name", "%s", name.c_str()); +				xmlNewTextChildf(queryXml, "dsn", "%d", dsn); +				xmlNewTextChildf(queryXml, "sql", "%s", sql.c_str()); +#endif +				addQueryResultsToXml(db, cp, root_node, dsn, sql, name, recordName, queries["id"], NULL, elems, params); +			} +		} +		printf("\r\n"); +		xmlDocFormatDump(stdout, doc, 1); +		xmlFreeDoc(doc); +	} +	catch (std::exception & e) { +		printf("Content-type: text/xml\r\n"); +		printf("\r\n"); +		xmlDoc * doc = xmlNewDoc(BAD_CAST "1.0"); +		xmlNode * root_node = xmlNewNode(NULL, BAD_CAST "error"); +		xmlDocSetRootElement(doc, root_node); +		xmlNewTextChildf(root_node, "what", "%s", e.what()); +		xmlDocFormatDump(stdout, doc, 1); +	} +	catch (...) { +		printf("Content-type: text/xml\r\n"); +		printf("\r\n"); +		xmlDoc * doc = xmlNewDoc(BAD_CAST "1.0"); +		xmlNode * root_node = xmlNewNode(NULL, BAD_CAST "error"); +		xmlNewTextChildf(root_node, "what", "Unknown"); +		xmlNewTextChildf(root_node, "detail", "Exception thrown does not inherit from std::exception"); +		xmlDocSetRootElement(doc, root_node); +		xmlDocFormatDump(stdout, doc, 1); +	} +	return 0; +} + diff --git a/project2/p2webMain.cpp b/project2/p2webMain.cpp new file mode 100644 index 0000000..716495f --- /dev/null +++ b/project2/p2webMain.cpp @@ -0,0 +1,42 @@ +#include <libxml/tree.h> +#include <fcgi_stdio.h> +#include "envproc.h" +#include <boost/bind.hpp> + +int +xmlWrite(void * _out, const char * buf, int len) +{ +	return FCGX_PutStr(buf, len, (FCGX_Stream*)_out); +} + +int main(void) +{ +	FCGX_Stream *in, *_out, *err; +	FCGX_ParamArray envp; + +	while (FCGX_Accept(&in, &_out, &err, &envp) >= 0)  +	{ +		try { +			EnvironmentProcessor ep(boost::bind(FCGX_GetParam, _1, envp)); + +			xmlDoc * doc = ep.process(); + +			FCGX_FPrintF(_out, "Content-type: text/xml-xslt\r\n\r\n");       +			xmlOutputBufferPtr out = xmlOutputBufferCreateIO( +					xmlWrite, NULL, _out, xmlGetCharEncodingHandler(XML_CHAR_ENCODING_UTF8)); +			xmlSaveFileTo(out, doc, NULL); +			xmlFreeDoc(doc); +		} +		catch (const std::exception & e) { +			FCGX_FPrintF(_out, "Content-type: text/plain\r\n\r\n");       +			FCGX_FPrintF(_out, "Kaboom!\r\n\r\n");       +			FCGX_FPrintF(_out, "%s\r\n\r\n", e.what());       +		} +		catch (...) { +			FCGX_FPrintF(_out, "Content-type: text/plain\r\n\r\n");       +			FCGX_FPrintF(_out, "Kaboom!\r\n\r\n");       +			FCGX_FPrintF(_out, "Unknown exception.\r\n\r\n");       +		} +	} +	return 0; +} diff --git a/project2/rdbmsDataSource.cpp b/project2/rdbmsDataSource.cpp new file mode 100644 index 0000000..f4b3b4e --- /dev/null +++ b/project2/rdbmsDataSource.cpp @@ -0,0 +1,18 @@ +#include "rdbmsDataSource.h" +#include "xml.h" + +_RdbmsDataSource::_RdbmsDataSource(xmlNodePtr p) : +	_Project2SourceObject(p), +	masterDsn(xmlGetNodeValue<ustring>(p, BAD_CAST "masterdsn", BAD_CAST "")) +{ +	fprintf(stderr, "Created RDBMS Datasource %s (%s)\n", name.c_str(), masterDsn.c_str()); +} + +_RdbmsDataSource::operator ODBC::Connection &() +{ +	if (!database) { +		database = boost::shared_ptr<ODBC::Connection>(new ODBC::Connection(masterDsn)); +	} +	return *database; +} + diff --git a/project2/rdbmsDataSource.h b/project2/rdbmsDataSource.h new file mode 100644 index 0000000..74ed829 --- /dev/null +++ b/project2/rdbmsDataSource.h @@ -0,0 +1,23 @@ +#ifndef RDBMSDATASOURCE_H +#define RDBMSDATASOURCE_H + +#include <libxml/tree.h> +#include <boost/shared_ptr.hpp> +#include <map> +#include "sourceObject.h" +#include "connection.h" +#include "ustring.h" + +class _RdbmsDataSource : public _Project2SourceObject { +	public: +		_RdbmsDataSource(xmlNodePtr p); +		operator ODBC::Connection &(); +		const ustring masterDsn; +	private: +		boost::shared_ptr<ODBC::Connection> database; +}; +typedef boost::shared_ptr<_RdbmsDataSource> RdbmsDataSource; +typedef std::map<ustring, RdbmsDataSource> RdbmsDataSources; + +#endif + diff --git a/project2/sourceObject.cpp b/project2/sourceObject.cpp new file mode 100644 index 0000000..a441e77 --- /dev/null +++ b/project2/sourceObject.cpp @@ -0,0 +1,8 @@ +#include "sourceObject.h" + +_Project2SourceObject::_Project2SourceObject(xmlNodePtr p) : +	name(xmlGetProp(p, BAD_CAST "name")) +{ +	fprintf(stderr, "Created object %s\n", name.c_str()); +} + diff --git a/project2/sourceObject.h b/project2/sourceObject.h new file mode 100644 index 0000000..d6531ff --- /dev/null +++ b/project2/sourceObject.h @@ -0,0 +1,13 @@ +#ifndef SOURCEOBJECT_H +#define SOURCEOBJECT_H + +#include "ustring.h" +#include <libxml/tree.h> + +class _Project2SourceObject { +	public: +		_Project2SourceObject(xmlNodePtr p); +		const ustring name; +}; + +#endif diff --git a/project2/sqlView.cpp b/project2/sqlView.cpp new file mode 100644 index 0000000..ca1c135 --- /dev/null +++ b/project2/sqlView.cpp @@ -0,0 +1,78 @@ +#include "sqlView.h" +#include "xml.h" +#include "selectcommand.h" +#include "column.h" +#include <string.h> + +_SqlView::_SqlView(xmlNodePtr p) : +	_Project2SourceObject(p), +	sql(xmlGetNodeValue<ustring>(p, BAD_CAST "sql", BAD_CAST "")), +	dataSource(xmlGetProp(p, BAD_CAST "datasource")), +	recordName(xmlGetProp(p, BAD_CAST "recordname")) +{ +} + +void _SqlView::execute(RdbmsDataSources s, xmlNodePtr par) const +{ +	typedef std::map<ODBC::String, xmlNode *> Columns; +	fprintf(stderr, "executing\n"); +	ODBC::SelectCommand query(*s[dataSource], sql); +	xmlNode * set = xmlNewChild(par, NULL, name.c_str(), NULL); +	while (query.fetch()) { +		Columns columns; +		unsigned int cols = query.columnCount(); +		xmlNode * record = xmlNewChild(set, NULL, recordName.c_str(), NULL); +		for (unsigned int col = 0; col < cols; col += 1) { +			const unsigned char * nameattr = query[col].name.c_str(); +			unsigned char * name, * attr = NULL; +			switch (sscanf((const char *)nameattr, "%a[^_]_%as", &name, &attr))  +			{ +				case 0: +					return; // Make me an exception +					break; +				case 1: +					attr = NULL; +					break; +			} +			char * buf = NULL; +			query[col].writeToBuf(&buf); +			if (buf) { +				if (attr) { +					if (strcmp((const char *)attr, ".") == 0) { +						xmlNewProp(record, name, BAD_CAST buf); +					} +					else { +						Columns::iterator i = columns.find(attr); +						if (i != columns.end()) { +							xmlNewProp(i->second, name, BAD_CAST buf); +						} +					} +				} +				else if (strcmp((const char *)name, "value") == 0) { +					xmlNodeAddContent(record, BAD_CAST buf); +				} +				else { +					columns[name] = xmlNewTextChild(record, NULL, name, BAD_CAST buf); +				} +				free(buf); +			} +			free(name); +			free(attr); +		} +		/* +		ODBC::SelectCommand queries(wdb, +				"SELECT d.id AS dsn, q.id AS query, q.sql, q.name, q.recordname, pq.id \ +				FROM dsn d, page_query pq, query q \ +				WHERE pq.parent = ? \ +				AND q.id = pq.query \ +				AND d.id = q.dsn"); +		queries.bindParamI(0, pqid); +		while (queries.fetch()) { +			addQueryResultsToXml(wdb, cp, record, queries["dsn"], +					queries["sql"], queries["name"], queries["recordname"], queries["id"], &query, elems, qs); +		} +		*/ +	} +	fprintf(stderr, "finished\n"); +} + diff --git a/project2/sqlView.h b/project2/sqlView.h new file mode 100644 index 0000000..16812d2 --- /dev/null +++ b/project2/sqlView.h @@ -0,0 +1,23 @@ +#ifndef SQLVIEW_H +#define SQLVIEW_H + +#include <libxml/tree.h> +#include <boost/shared_ptr.hpp> +#include <map> +#include "sourceObject.h" +#include "ustring.h" +#include "rdbmsDataSource.h" + +class _SqlView : public _Project2SourceObject { +	public: +		_SqlView(xmlNodePtr p); +		void execute(RdbmsDataSources s, xmlNodePtr) const; +		const ustring sql; +		const ustring dataSource; +		const ustring recordName; +}; +typedef boost::shared_ptr<_SqlView> SqlView; +typedef std::map<ustring, SqlView> SqlViews; + +#endif + diff --git a/project2/ustring.h b/project2/ustring.h new file mode 100644 index 0000000..cfed0c4 --- /dev/null +++ b/project2/ustring.h @@ -0,0 +1,9 @@ +#ifndef USTRING_H +#define USTRING_H + +#include <string> + +typedef std::basic_string<unsigned char> ustring; + +#endif +  | 
