tanghai 14 лет назад
Родитель
Сommit
50d809589f

+ 1 - 0
Cpp/Platform/Base/Typedef.h

@@ -3,6 +3,7 @@
 #include <boost/cstdint.hpp>
 #include <boost/shared_ptr.hpp>
 #include <google/protobuf/service.h>
+#include <google/protobuf/message.h>
 
 namespace Egametang {
 

+ 1 - 0
Cpp/Platform/CMakeLists.txt

@@ -1,3 +1,4 @@
 ADD_SUBDIRECTORY(Python)
 ADD_SUBDIRECTORY(Thread)
 ADD_SUBDIRECTORY(Rpc)
+ADD_SUBDIRECTORY(Orm)

+ 9 - 0
Cpp/Platform/Orm/CMakeLists.txt

@@ -0,0 +1,9 @@
+SET(OrmSrc 
+	Column.cc
+	DbHelper.cc
+	DbResult.cc
+	Expr.cc
+	MessageField.cc
+)
+
+ADD_LIBRARY(Orm ${OrmSrc})

+ 2 - 2
Cpp/Platform/Orm/Column.cc

@@ -10,9 +10,9 @@ Column::~Column()
 {
 }
 
-Column& Column::operator()(std::string& column)
+Column& Column::operator()(std::string& name)
 {
-	columnStr = columnStr + ", " + column;
+	columnStr = columnStr + ", " + name;
 	return *this;
 }
 

+ 1 - 1
Cpp/Platform/Orm/Column.h

@@ -14,7 +14,7 @@ private:
 public:
 	Column(const std::string name);
 	~Column();
-	Column& operator()(std::string& column);
+	Column& operator()(std::string& name);
 	std::string ToString() const;
 
 	template <typename T>

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

@@ -5,4 +5,15 @@
 
 namespace Egametang {
 
+DbHelper::DbHelper(std::string url, std::string username, std::string password):
+		driver(NULL)
+{
+	driver = get_driver_instance();
+	connection.reset(driver->connect(url, username, password));
+}
+
+DbHelper::~DbHelper()
+{
+}
+
 } // namespace Egametang

+ 5 - 8
Cpp/Platform/Orm/DbHelper.h

@@ -18,21 +18,18 @@ namespace Egametang {
 class DbHelper
 {
 private:
-	boost::scoped_ptr<sql::Driver> driver;
+	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));
-	}
+	DbHelper(std::string url, std::string username, std::string password);
 	virtual ~DbHelper();
 
-	ResultSetPtr ExecuteQuery(std::string query)
+	template <typename Table>
+	ResultSetPtr ExecuteQuery(Query<Table>& query)
 	{
 		StatementPtr statemet(connection->createStatement());
-		ResultSetPtr resultSet(statemet->executeQuery(query));
+		ResultSetPtr resultSet(statemet->executeQuery(query.ToString()));
 		return resultSet;
 	}
 };

+ 39 - 3
Cpp/Platform/Orm/DbResult.cc

@@ -1,16 +1,52 @@
 // Copyright: All Rights Reserved
 // Author: egametang@gmail.com (tanghai)
 
-#include "DbResult.h"
+#include <google/protobuf/descriptor.h>
+#include "Orm/DbResult.h"
+#include "Orm/MessageField.h"
 
 namespace Egametang {
 
-DbResult::DbResult()
+DbResult::DbResult(ResultSetPtr resultSet): resultSet(resultSet)
 {
 }
 
-DbResult::~DbResult()
+void DbResult::FillMessage(ProtobufMessagePtr message)
 {
+	const google::protobuf::Descriptor* descriptor = message->GetDescriptor();
+	for (int i = 0; i < descriptor->field_count(); ++i)
+	{
+		if (resultSet->isNull(i))
+		{
+			continue;
+		}
+		const google::protobuf::FieldDescriptor* field = descriptor->field(i);
+		MessageField messageField(*message, field);
+		messageField.SetField(resultSet);
+	}
+}
+
+void DbResult::All(std::vector<ProtobufMessagePtr>& messages)
+{
+	for (int i = 0; resultSet->next(); ++i)
+	{
+		ProtobufMessagePtr message = messages[i];
+		FillMessage(message);
+	}
+}
+
+void DbResult::One(ProtobufMessagePtr message)
+{
+	if (!resultSet->first())
+	{
+		return;
+	}
+	FillMessage(message);
+}
+
+std::size_t DbResult::Count()
+{
+	return resultSet->rowsCount();
 }
 
 } // namespace Egametang

+ 12 - 26
Cpp/Platform/Orm/DbResult.h

@@ -4,7 +4,10 @@
 #ifndef ORM_DBRESULT_H
 #define ORM_DBRESULT_H
 
+#include <vector>
 #include <cppconn/resultset.h>
+#include "Base/Typedef.h"
+#include "Orm/OrmTypedef.h"
 
 namespace Egametang {
 
@@ -13,34 +16,17 @@ 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);
-		}
-	}
+	void FillMessage(ProtobufMessagePtr message);
 
+public:
+	DbResult(ResultSetPtr resultSet);
 	virtual ~DbResult();
+
+	void All(std::vector<ProtobufMessagePtr>& messages);
+
+	void One(ProtobufMessagePtr message);
+
+	std::size_t Count();
 };
 
 } // namespace Egametang

+ 4 - 2
Cpp/Platform/Orm/Expr.cc

@@ -1,6 +1,8 @@
 // Copyright: All Rights Reserved
 // Author: egametang@gmail.com (tanghai)
 
+#include <boost/lexical_cast.hpp>
+#include "Orm/Column.h"
 #include "Orm/Expr.h"
 
 namespace Egametang {
@@ -9,14 +11,14 @@ Expr::~Expr()
 {
 }
 
-std::string Expr::ToString()
+std::string Expr::ToString() const
 {
 	return exprStr;
 }
 
 Not::Not(const Expr& expr)
 {
-	exprStr = "not (" + expr + ") ";
+	exprStr = "not (" + expr.ToString() + ") ";
 }
 
 And::And(const Expr& left, const Expr& right)

+ 6 - 2
Cpp/Platform/Orm/Expr.h

@@ -4,6 +4,8 @@
 #ifndef ORM_EXPRESSION_H
 #define ORM_EXPRESSION_H
 
+#include <string>
+
 namespace Egametang {
 
 class Expr
@@ -13,7 +15,7 @@ protected:
 
 public:
 	virtual ~Expr();
-	virtual std::string ToString();
+	virtual std::string ToString() const;
 };
 
 class Not: public Expr
@@ -34,10 +36,12 @@ public:
 	Or(const Expr& left, const Expr& right);
 };
 
+class Column;
+
 // > < >= <= != like
 class Oper: public Expr
 {
-protected:
+public:
 	Oper(const Column& left, const std::string& op, const std::string& right);
 	Oper(const Column& left, const std::string& op, const Column& right);
 	Oper(const Column& left, const std::string& op, int right);

+ 132 - 15
Cpp/Platform/Orm/MessageField.cc

@@ -3,13 +3,16 @@
 #include <boost/algorithm/string.hpp>
 #include <boost/lexical_cast.hpp>
 #include <glog/logging.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/text_format.h>
+#include "Base/Typedef.h"
 #include "Orm/MessageField.h"
 
 namespace Egametang {
 
 MessageField::MessageField(
-		const google::protobuf::Message& message,
-		const google::protobuf::FieldDescriptor* field):
+		google::protobuf::Message& message,
+		google::protobuf::FieldDescriptor* field):
 	message(message), field(field)
 {
 }
@@ -19,6 +22,123 @@ MessageField::~MessageField()
 }
 
 std::string MessageField::GetField()
+{
+	std::string valueStr;
+	if (field->is_repeated())
+	{
+		valueStr = GetRepeatedField();
+	}
+	else
+	{
+		valueStr = GetOptionalField();
+	}
+	return valueStr;
+}
+
+std::string MessageField::GetRepeatedField()
+{
+	const google::protobuf::Reflection* reflection = message.GetReflection();
+	google::protobuf::FieldDescriptor::Type type = field->type();
+	std::string valueStr;
+	switch (type)
+	{
+		case google::protobuf::FieldDescriptor::TYPE_BOOL:
+		{
+			for (int i = 0; i < reflection->FieldSize(message, field); ++i)
+			{
+				bool value = reflection->GetBool(message, field);
+				valueStr += value? "1\t" : "0\t";
+			}
+			break;
+		}
+		case google::protobuf::FieldDescriptor::TYPE_DOUBLE:
+		{
+			for (int i = 0; i < reflection->FieldSize(message, field); ++i)
+			{
+				double value = reflection->GetDouble(message, field);
+				valueStr += boost::lexical_cast<std::string>(value) + "\t";
+			}
+			break;
+		}
+		case google::protobuf::FieldDescriptor::TYPE_INT32:
+		{
+			for (int i = 0; i < reflection->FieldSize(message, field); ++i)
+			{
+				int32 value = reflection->GetInt32(message, field);
+				valueStr += boost::lexical_cast<std::string>(value) + "\t";
+			}
+			break;
+		}
+		case google::protobuf::FieldDescriptor::TYPE_INT64:
+		{
+			for (int i = 0; i < reflection->FieldSize(message, field); ++i)
+			{
+				int64 value = reflection->GetInt64(message, field);
+				valueStr += boost::lexical_cast<std::string>(value) + "\t";
+			}
+			break;
+		}
+		case google::protobuf::FieldDescriptor::TYPE_UINT32:
+		{
+			for (int i = 0; i < reflection->FieldSize(message, field); ++i)
+			{
+				int64 value = reflection->GetInt64(message, field);
+				valueStr += boost::lexical_cast<std::string>(value) + "\t";
+			}
+			break;
+		}
+		case google::protobuf::FieldDescriptor::TYPE_UINT64:
+		{
+			for (int i = 0; i < reflection->FieldSize(message, field); ++i)
+			{
+				int64 value = reflection->GetInt64(message, field);
+				valueStr += boost::lexical_cast<std::string>(value) + "\t";
+			}
+			break;
+		}
+		case google::protobuf::FieldDescriptor::TYPE_STRING:
+		{
+			valueStr += "'";
+			for (int i = 0; i < reflection->FieldSize(message, field); ++i)
+			{
+				int64 value = reflection->GetInt64(message, field);
+				valueStr += reflection->GetString(message, field) + "\t";
+			}
+			valueStr += "'";
+			break;
+		}
+		case google::protobuf::FieldDescriptor::TYPE_BYTES:
+		{
+			valueStr += "'";
+			for (int i = 0; i < reflection->FieldSize(message, field); ++i)
+			{
+				int64 value = reflection->GetInt64(message, field);
+				valueStr += reflection->GetString(message, field) + "\t";
+			}
+			valueStr += "'";
+			break;
+		}
+		case google::protobuf::FieldDescriptor::TYPE_MESSAGE:
+		{
+			valueStr += "'";
+			for (int i = 0; i < reflection->FieldSize(message, field); ++i)
+			{
+				const google::protobuf::Message& message = reflection->GetMessage(message, field);
+				valueStr += message.ShortDebugString() + "\t";
+			}
+			valueStr += "'";
+			break;
+		}
+		default:
+		{
+			LOG(FATAL) << "no such type";
+			break;
+		}
+	}
+	return valueStr;
+}
+
+std::string MessageField::GetOptionalField()
 {
 	const google::protobuf::Reflection* reflection = message.GetReflection();
 	google::protobuf::FieldDescriptor::Type type = field->type();
@@ -73,7 +193,7 @@ std::string MessageField::GetField()
 		}
 		case google::protobuf::FieldDescriptor::TYPE_MESSAGE:
 		{
-			google::protobuf::Message& message = reflection->GetMessage(message, field);
+			const google::protobuf::Message& message = reflection->GetMessage(message, field);
 			valueStr = message.ShortDebugString();
 			break;
 		}
@@ -86,19 +206,20 @@ std::string MessageField::GetField()
 	return valueStr;
 }
 
-void MessageField::SetRepeatedField(ResultSetPtr resultSet, int index)
+void MessageField::SetRepeatedField(ResultSetPtr resultSet)
 {
 	const google::protobuf::Reflection* reflection = message.GetReflection();
 	google::protobuf::FieldDescriptor::Type type = field->type();
 
 	// 获取blob string(repeated字段统一存成blob type)
+	int index = field->index();
 	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"));
+	boost::split(strVector, fieldStr, boost::is_any_of("\t"));
 
 	switch (type)
 	{
@@ -191,10 +312,11 @@ void MessageField::SetRepeatedField(ResultSetPtr resultSet, int index)
 	}
 }
 
-void MessageField::SetOptionalField(ResultSetPtr resultSet, int index)
+void MessageField::SetOptionalField(ResultSetPtr resultSet)
 {
 	const google::protobuf::Reflection* reflection = message.GetReflection();
 	google::protobuf::FieldDescriptor::Type type = field->type();
+	int index = field->index();
 	switch (type)
 	{
 		case google::protobuf::FieldDescriptor::TYPE_BOOL:
@@ -253,7 +375,7 @@ void MessageField::SetOptionalField(ResultSetPtr resultSet, int index)
 			std::string value = os.str();
 
 			google::protobuf::Message* msg =
-					reflection->MutableMessage(&message, field, index);
+					reflection->MutableMessage(&message, field);
 			google::protobuf::TextFormat::ParseFromString(value, msg);
 			break;
 		}
@@ -265,20 +387,15 @@ void MessageField::SetOptionalField(ResultSetPtr resultSet, int index)
 	}
 }
 
-void MessageField::SetField(ResultSetPtr resultSet, int index)
+void MessageField::SetField(ResultSetPtr resultSet)
 {
-	if (resultSet->isNull(index))
-	{
-		return;
-	}
-
 	if (field->is_repeated())
 	{
-		SetRepeatedField(resultSet, index);
+		SetRepeatedField(resultSet);
 	}
 	else
 	{
-		SetOptionalField(resultSet, index);
+		SetOptionalField(resultSet);
 	}
 }
 

+ 11 - 9
Cpp/Platform/Orm/MessageField.h

@@ -10,21 +10,23 @@ namespace Egametang {
 class MessageField
 {
 private:
-	const google::protobuf::Message& message;
-	const google::protobuf::FieldDescriptor* field;
+	google::protobuf::Message& message;
+	google::protobuf::FieldDescriptor* field;
+
+	std::string GetRepeatedField();
+	std::string GetOptionalField();
+
+	void SetRepeatedField(ResultSetPtr resultSet);
+	void SetOptionalField(ResultSetPtr resultSet);
 
 public:
-	MessageField(const google::protobuf::Message& message,
-			const google::protobuf::FieldDescriptor* field);
+	MessageField(google::protobuf::Message& message,
+			google::protobuf::FieldDescriptor* field);
 	~MessageField();
 
 	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);
+	void SetField(ResultSetPtr resultSet);
 };
 
 } // namespace Egametang

+ 1 - 3
Cpp/Platform/Orm/Query.h

@@ -3,6 +3,7 @@
 
 #include <string>
 #include <vector>
+#include <boost/lexical_cast.hpp>
 #include "Orm/Expr.h"
 #include "Orm/Column.h"
 
@@ -21,9 +22,6 @@ class Query
 	int offset;
 
 public:
-	Query();
-	~Query();
-
 	Query(): distinct(false), where("true"), limit(0), offset(0)
 	{
 	}