Parcourir la source

MessageField根据select结果进行填充protobuf message

tanghai il y a 14 ans
Parent
commit
15defdda33

+ 8 - 0
Cpp/Platform/Orm/DbHelper.cc

@@ -0,0 +1,8 @@
+// Copyright: All Rights Reserved
+// Author: egametang@gmail.com (tanghai)
+
+#include "Orm/DbHelper.h"
+
+namespace Egametang {
+
+} // namespace Egametang

+ 41 - 0
Cpp/Platform/Orm/DbHelper.h

@@ -0,0 +1,41 @@
+// Copyright: All Rights Reserved
+// Author: egametang@gmail.com (tanghai)
+
+#ifndef ORM_SQLHELPER_H
+#define ORM_SQLHELPER_H
+
+#include <boost/scoped_ptr.hpp>
+#include <cppconn/driver.h>
+#include <cppconn/exception.h>
+#include <cppconn/resultset.h>
+#include <cppconn/statement.h>
+#include <mysql_connection.h>
+#include "Orm/OrmTypedef.h"
+#include "Orm/Query.h"
+
+namespace Egametang {
+
+class DbHelper
+{
+private:
+	boost::scoped_ptr<sql::Driver> driver;
+	boost::scoped_ptr<sql::Connection> connection;
+
+public:
+	DbHelper(std::string url, std::string username, std::string password)
+	{
+		driver.reset(get_driver_instance());
+		connection.reset(driver->connect(url, username, password));
+	}
+	virtual ~DbHelper();
+
+	ResultSetPtr ExecuteQuery(std::string query)
+	{
+		StatementPtr statemet(connection->createStatement());
+		ResultSetPtr resultSet(statemet->executeQuery(query));
+		return resultSet;
+	}
+};
+
+} // namespace Egametang
+#endif // ORM_SQLHELPER_H

+ 8 - 0
Cpp/Platform/Orm/DbHelperTest.cc

@@ -0,0 +1,8 @@
+// Copyright: All Rights Reserved
+// Author: egametang@gmail.com (tanghai)
+
+#include "Orm/DbHelper.h"
+
+namespace Egametang {
+
+} // namespace Egametang

+ 16 - 0
Cpp/Platform/Orm/DbResult.cc

@@ -0,0 +1,16 @@
+// Copyright: All Rights Reserved
+// Author: egametang@gmail.com (tanghai)
+
+#include "DbResult.h"
+
+namespace Egametang {
+
+DbResult::DbResult()
+{
+}
+
+DbResult::~DbResult()
+{
+}
+
+} // namespace Egametang

+ 47 - 0
Cpp/Platform/Orm/DbResult.h

@@ -0,0 +1,47 @@
+// Copyright: All Rights Reserved
+// Author: egametang@gmail.com (tanghai)
+
+#ifndef ORM_DBRESULT_H
+#define ORM_DBRESULT_H
+
+#include <cppconn/resultset.h>
+
+namespace Egametang {
+
+class DbResult
+{
+private:
+	ResultSetPtr resultSet;
+
+public:
+	DbResult(ResultSetPtr resultSet): resultSet(resultSet)
+	{
+	}
+	void All(std::vector<ProtobufMessagePtr>& messages)
+	{
+		while (resultSet->next())
+		{
+
+		}
+	}
+
+	void One(ProtobufMessagePtr message)
+	{
+		if (!resultSet->first())
+		{
+			return;
+		}
+		const google::protobuf::Descriptor* descriptor = message->GetDescriptor();
+		for (int i = 0; i < descriptor->field_count(); ++i)
+		{
+			const google::protobuf::FieldDescriptor* field = descriptor->field(i);
+			MessageField messageField(*message, field);
+			messageField.SetField(resultSet, i);
+		}
+	}
+
+	virtual ~DbResult();
+};
+
+} // namespace Egametang
+#endif // ORM_DBRESULT_H

+ 8 - 0
Cpp/Platform/Orm/DbResultTest.cc

@@ -0,0 +1,8 @@
+// Copyright: All Rights Reserved
+// Author: egametang@gmail.com (tanghai)
+
+#include "DbResult.h"
+
+namespace Egametang {
+
+} // namespace Egametang

+ 203 - 3
Cpp/Platform/Orm/MessageField.cc

@@ -1,3 +1,7 @@
+#include <string>
+#include <iostream>
+#include <boost/algorithm/string.hpp>
+#include <boost/lexical_cast.hpp>
 #include <glog/logging.h>
 #include "Orm/MessageField.h"
 
@@ -14,11 +18,11 @@ MessageField::~MessageField()
 {
 }
 
-std::string MessageField::ValueToString()
+std::string MessageField::GetField()
 {
 	const google::protobuf::Reflection* reflection = message.GetReflection();
 	google::protobuf::FieldDescriptor::Type type = field->type();
-	std::string valueStr = "";
+	std::string valueStr;
 	switch (type)
 	{
 		case google::protobuf::FieldDescriptor::TYPE_BOOL:
@@ -70,7 +74,7 @@ std::string MessageField::ValueToString()
 		case google::protobuf::FieldDescriptor::TYPE_MESSAGE:
 		{
 			google::protobuf::Message& message = reflection->GetMessage(message, field);
-			valueStr = "'" + message.SerializeAsString() + "'";
+			valueStr = message.ShortDebugString();
 			break;
 		}
 		default:
@@ -82,4 +86,200 @@ std::string MessageField::ValueToString()
 	return valueStr;
 }
 
+void MessageField::SetRepeatedField(ResultSetPtr resultSet, int index)
+{
+	const google::protobuf::Reflection* reflection = message.GetReflection();
+	google::protobuf::FieldDescriptor::Type type = field->type();
+
+	// 获取blob string(repeated字段统一存成blob type)
+	std::istream* is = resultSet->getBlob(index);
+	std::ostringstream os;
+	os << is->rdbuf();
+	std::string fieldStr = os.str();
+
+	std::vector<std::string> strVector;
+	boost::split(strVector, fieldStr, boost::is_any_of("\t\t"));
+
+	switch (type)
+	{
+		case google::protobuf::FieldDescriptor::TYPE_BOOL:
+		{
+			for (std::size_t i = 0; i < strVector.size(); ++i)
+			{
+				int intValue = boost::lexical_cast<int>(strVector[i]);
+				bool value = intValue? true : false;
+				reflection->SetRepeatedBool(&message, field, i, value);
+			}
+			break;
+		}
+		case google::protobuf::FieldDescriptor::TYPE_DOUBLE:
+		{
+			for (std::size_t i = 0; i < strVector.size(); ++i)
+			{
+				double value = boost::lexical_cast<double>(strVector[i]);
+				reflection->SetRepeatedDouble(&message, field, i, value);
+			}
+			break;
+		}
+		case google::protobuf::FieldDescriptor::TYPE_INT32:
+		{
+			for (std::size_t i = 0; i < strVector.size(); ++i)
+			{
+				int32 value = boost::lexical_cast<int32>(strVector[i]);
+				reflection->SetRepeatedInt32(&message, field, i, value);
+			}
+			break;
+		}
+		case google::protobuf::FieldDescriptor::TYPE_INT64:
+		{
+			for (std::size_t i = 0; i < strVector.size(); ++i)
+			{
+				int64 value = boost::lexical_cast<int64>(strVector[i]);
+				reflection->SetRepeatedInt64(&message, field, i, value);
+			}
+			break;
+		}
+		case google::protobuf::FieldDescriptor::TYPE_UINT32:
+		{
+			for (std::size_t i = 0; i < strVector.size(); ++i)
+			{
+				uint32 value = boost::lexical_cast<uint32>(strVector[i]);
+				reflection->SetRepeatedUInt32(&message, field, i, value);
+			}
+			break;
+		}
+		case google::protobuf::FieldDescriptor::TYPE_UINT64:
+		{
+			for (std::size_t i = 0; i < strVector.size(); ++i)
+			{
+				uint64 value = boost::lexical_cast<uint64>(strVector[i]);
+				reflection->SetRepeatedUInt64(&message, field, i, value);
+			}
+			break;
+		}
+		case google::protobuf::FieldDescriptor::TYPE_STRING:
+		{
+			for (std::size_t i = 0; i < strVector.size(); ++i)
+			{
+				reflection->SetRepeatedString(&message, field, i, strVector[i]);
+			}
+			break;
+		}
+		case google::protobuf::FieldDescriptor::TYPE_BYTES:
+		{
+			for (std::size_t i = 0; i < strVector.size(); ++i)
+			{
+				reflection->SetRepeatedString(&message, field, i, strVector[i]);
+			}
+			break;
+		}
+		case google::protobuf::FieldDescriptor::TYPE_MESSAGE:
+		{
+			for (std::size_t i = 0; i < strVector.size(); ++i)
+			{
+				google::protobuf::Message* msg =
+						reflection->MutableRepeatedMessage(&message, field, i);
+				google::protobuf::TextFormat::ParseFromString(strVector[i], msg);
+			}
+			break;
+		}
+		default:
+		{
+			LOG(FATAL) << "no such type";
+			break;
+		}
+	}
+}
+
+void MessageField::SetOptionalField(ResultSetPtr resultSet, int index)
+{
+	const google::protobuf::Reflection* reflection = message.GetReflection();
+	google::protobuf::FieldDescriptor::Type type = field->type();
+	switch (type)
+	{
+		case google::protobuf::FieldDescriptor::TYPE_BOOL:
+		{
+			bool value = resultSet->getBoolean(index);
+			reflection->SetBool(&message, field, value);
+			break;
+		}
+		case google::protobuf::FieldDescriptor::TYPE_DOUBLE:
+		{
+			double value = resultSet->getDouble(index);
+			reflection->SetDouble(&message, field, value);
+			break;
+		}
+		case google::protobuf::FieldDescriptor::TYPE_INT32:
+		{
+			int32 value = resultSet->getInt(index);
+			reflection->SetInt32(&message, field, value);
+			break;
+		}
+		case google::protobuf::FieldDescriptor::TYPE_INT64:
+		{
+			int64 value = resultSet->getInt64(index);
+			reflection->SetInt64(&message, field, value);
+			break;
+		}
+		case google::protobuf::FieldDescriptor::TYPE_UINT32:
+		{
+			uint32 value = resultSet->getUInt(index);
+			reflection->SetUInt32(&message, field, value);
+			break;
+		}
+		case google::protobuf::FieldDescriptor::TYPE_UINT64:
+		{
+			uint64 value = resultSet->getUInt64(index);
+			reflection->SetUInt64(&message, field, value);
+			break;
+		}
+		case google::protobuf::FieldDescriptor::TYPE_STRING:
+		{
+			std::string value = resultSet->getString(index);
+			reflection->SetString(&message, field, value);
+			break;
+		}
+		case google::protobuf::FieldDescriptor::TYPE_BYTES:
+		{
+			std::string value = resultSet->getString(index);
+			reflection->SetString(&message, field, value);
+			break;
+		}
+		case google::protobuf::FieldDescriptor::TYPE_MESSAGE:
+		{
+			std::istream* is = resultSet->getBlob(index);
+			std::ostringstream os;
+			os << is->rdbuf();
+			std::string value = os.str();
+
+			google::protobuf::Message* msg =
+					reflection->MutableMessage(&message, field, index);
+			google::protobuf::TextFormat::ParseFromString(value, msg);
+			break;
+		}
+		default:
+		{
+			LOG(FATAL) << "no such type";
+			break;
+		}
+	}
+}
+
+void MessageField::SetField(ResultSetPtr resultSet, int index)
+{
+	if (resultSet->isNull(index))
+	{
+		return;
+	}
+
+	if (field->is_repeated())
+	{
+		SetRepeatedField(resultSet, index);
+	}
+	else
+	{
+		SetOptionalField(resultSet, index);
+	}
+}
+
 } // namespace Egametang

+ 10 - 1
Cpp/Platform/Orm/MessageField.h

@@ -2,6 +2,8 @@
 #define ORM_MESSAGEFIELD_H
 
 #include <string>
+#include <google/protobuf/message.h>
+#include "Orm/OrmTypedef.h"
 
 namespace Egametang {
 
@@ -15,7 +17,14 @@ public:
 	MessageField(const google::protobuf::Message& message,
 			const google::protobuf::FieldDescriptor* field);
 	~MessageField();
-	std::string MessageField::ValueToString();
+
+	std::string GetField();
+	std::string GetRepeatedField();
+	std::string GetOptionalField();
+
+	void SetField(ResultSetPtr resultSet, int index);
+	void SetRepeatedField(ResultSetPtr resultSet, int index);
+	void SetOptionalField(ResultSetPtr resultSet, int index);
 };
 
 } // namespace Egametang

+ 17 - 0
Cpp/Platform/Orm/OrmTypedef.h

@@ -0,0 +1,17 @@
+// Copyright: All Rights Reserved
+// Author: egametang@gmail.com (tanghai)
+
+#ifndef ORM_ORMTYPEDEF_H
+#define ORM_ORMTYPEDEF_H
+
+#include <boost/shared_ptr.hpp>
+#include <cppconn/resultset.h>
+
+namespace Egametang {
+
+typedef boost::shared_ptr<sql::ResultSet> ResultSetPtr;
+typedef boost::shared_ptr<sql::Statement> StatementPtr;
+
+} // namespace Egametang
+
+#endif // ORM_ORMTYPEDEF_H

+ 0 - 106
Cpp/Platform/Orm/Query.cc

@@ -1,106 +0,0 @@
-#include <google/protobuf/descriptor.h>
-#include <glog/logging.h>
-#include "Orm/Query.h"
-
-namespace Egametang {
-
-Query::Query(): distinct(false), where("true"), limit(0), offset(0)
-{
-}
-
-Query::~Query()
-{
-}
-
-Query& Query::Select(Column column)
-{
-	select = column.ToString();
-	return *this;
-}
-
-Query& Query::Distinct(bool value)
-{
-	distinct = value;
-	return *this;
-}
-
-Query& Query::Where(const Expr& expr)
-{
-	where = expr.ToString();
-	return *this;
-}
-
-Query& Query::GroupBy(Column column)
-{
-	groupBy = column.ToString();
-	return *this;
-}
-
-Query& Query::Having(const Expr& having)
-{
-	having = having.ToString();
-	return *this;
-}
-
-Query& Query::OrderBy(Column column, bool ascending)
-{
-	std::string value = column.ToString();
-	if (!ascending)
-	{
-		value += " desc";
-	}
-	orderBy = value;
-	return *this;
-}
-
-Query& Query::Limit(int value)
-{
-	limit = value;
-	return *this;
-}
-
-Query& Query::Offset(int value)
-{
-	offset = value;
-	return *this;
-}
-
-std::string Query::ToString() const
-{
-	std::string sql = "select ";
-	if (!select.empty())
-	{
-		sql += select;
-	}
-	if (distinct)
-	{
-		sql += " distinct";
-	}
-	if (where != "true")
-	{
-		sql += " where " + where;
-	}
-	if (!groupBy.empty())
-	{
-		sql += " group by " + groupBy;
-	}
-	if (!having.empty())
-	{
-		sql += " having " + having;
-	}
-	if (!orderBy.empty())
-	{
-		sql += " order by " + orderBy;
-	}
-	if (limit)
-	{
-		sql += " limit " + boost::lexical_cast<std::string>(limit);
-	}
-	if (offset)
-	{
-		sql += " offset " + boost::lexical_cast<std::string>(offset);
-	}
-	return sql;
-}
-
-} // namespace Egametang

+ 103 - 11
Cpp/Platform/Orm/Query.h

@@ -4,12 +4,14 @@
 #include <string>
 #include <vector>
 #include "Orm/Expr.h"
+#include "Orm/Column.h"
 
 namespace Egametang {
 
+template <typename Table>
 class Query
 {
-	std::string select;
+	std::string columns;
 	bool distinct;
 	std::string where;
 	std::string groupBy;
@@ -21,16 +23,106 @@ class Query
 public:
 	Query();
 	~Query();
-	Query& Select(Column column);
-	Query& Distinct(bool distinct);
-	Query& Where(const Expr& where);
-	Query& GroupBy(Column column);
-	Query& Having(const Expr& having);
-	Query& OrderBy(Column column, bool ascending = true);
-	Query& Limit(int limit);
-	Query& Offset(int offset);
-
-	std::string ToString() const;
+
+	Query(): distinct(false), where("true"), limit(0), offset(0)
+	{
+	}
+
+	~Query()
+	{
+	}
+
+	Query<Table>& Select(Column column)
+	{
+		columns = column.ToString();
+		return *this;
+	}
+
+	Query<Table>& Distinct(bool value)
+	{
+		distinct = value;
+		return *this;
+	}
+
+	Query<Table>& Where(const Expr& expr)
+	{
+		where = expr.ToString();
+		return *this;
+	}
+
+	Query<Table>& GroupBy(Column column)
+	{
+		groupBy = column.ToString();
+		return *this;
+	}
+
+	Query<Table>& Having(const Expr& having)
+	{
+		having = having.ToString();
+		return *this;
+	}
+
+	Query<Table>& OrderBy(Column column, bool ascending)
+	{
+		std::string value = column.ToString();
+		if (!ascending)
+		{
+			value += " desc";
+		}
+		orderBy = value;
+		return *this;
+	}
+
+	Query<Table>& Limit(int value)
+	{
+		limit = value;
+		return *this;
+	}
+
+	Query<Table>& Offset(int value)
+	{
+		offset = value;
+		return *this;
+	}
+
+	std::string ToString() const
+	{
+		std::string sql = "select ";
+		if (!columns.empty())
+		{
+			sql += columns;
+		}
+		if (distinct)
+		{
+			sql += " distinct";
+		}
+		sql += " from " + Table::descriptor()->full_name();
+		if (where != "true")
+		{
+			sql += " where " + where;
+		}
+		if (!groupBy.empty())
+		{
+			sql += " group by " + groupBy;
+		}
+		if (!having.empty())
+		{
+			sql += " having " + having;
+		}
+		if (!orderBy.empty())
+		{
+			sql += " order by " + orderBy;
+		}
+		if (limit)
+		{
+			sql += " limit " + boost::lexical_cast<std::string>(limit);
+		}
+		if (offset)
+		{
+			sql += " offset " + boost::lexical_cast<std::string>(offset);
+		}
+		return sql;
+	}
 };
 
 } // namespace Egametang