個人2017年終總結(PF項目框架設計心得分享 1.0rc new)

一晃眼又過去了一年,在這一年裏儘管有許多不如意的事,卻阻擋不了我前進的腳步。先用一句話來總結去年一年的狀態,那就是「無休無止的忙碌」。而這樣的忙碌狀態對我來講是不可取的,由於匱乏的忙碌只能讓頭腦處於一種混亂而機械的狀態中。在去年的時間就是工做上的煩心事困擾着我,雖有許多不錯的主意終究由於忙碌而沒有堅持,最後發現這的確是本身犯下的最大錯誤,由於後來不得不花更多時間來彌補。但願個人總結可以幫助到更多的朋友,從錯誤裏汲取經驗教訓。mysql

總結

  所得:在工做中我能涉及到許多我之前認爲十分複雜的領域,結果發現它們並無想象中的困難。從這一點裏我學習到一切看似困難的東西,只是咱們本身膽怯形成的,在沒有嘗試以前就妄下結論是多麼愚蠢啊。以前我在另外一個城市裏就是由於不相信本身,而喪失了許多的機會,若是有了這些機會我事業上恐怕不會現在天這般不順。因此我但願全部在困難面前畏首畏尾的朋友,大家大膽一點放開大家的懷抱,去擁抱那即將靠近的夢想,雖然沒法保證結果多是一次慘痛的失敗。但是你不趁着你還敢夢想的年紀,那麼後面的生活你就只能活在遺憾當中了。git

  所失:忙碌讓個人神經麻木,甚至身體也有點力不從心,這就形成我在本身理想面前放慢了腳步。在此我也但願各位朋友要重視本身的健康,就算工做再怎麼幸苦也不能由於拼命而輕視了它,別將生活的壓力想象的太大。畢竟只有一個無缺的人,才能體會到美好的生活,而工做只不過是爲了生活而服務的。github

 

PF NEW

  雖然本身的確由於時間和身體的緣由,在這個框架上花費的時間少了許多,但是我卻沒有中止我對它的期許,那即是作到真正的簡單易用。爲了作到這個我從2015年開始到如今幾乎花了三年時間修改了兩次結構,而PF框架如今的版本已經到了2.1,其基本的功能和性能獲得了必定的保證。其中過程的艱辛,恐怕沒有幾我的能體會到。sql

  PF改動:plain server(2014)-> plain framework 1(2015-2016) -> plain framework 2(2017) -> plain framework new(2018)數據庫

  我只有一個簡單的年份和版本變化來表示PF框架的蛻變過程,實際上是一場很是不容易的變化。一開始這個還不能稱之框架,那個時候我只是想簡單的應付工做上的事情,爲服務器打造一個穩定的底層庫,即2014年的plain server。接着我發現只爭對服務器來講根本沒法知足個人要求,因而我從新修改告終構讓它可以支持幾乎全部的常見應有。接着說道如今比較穩定的版本PF2,它的改動最大的就是從語法上直接用到了C++11,使得框架自己可以支持更多新特性。然而PF2仍是不能知足我,我將要進行各大一步的調整,在PF2的基礎上我修改了框架的目錄結構,讓它看起來更加清晰易懂。服務器

  PFnew的新特性:快速安裝(框架、插件)、單元測試(框架、應用)、靈活封裝(接口)網絡

  對於如今的PFnew的快速安裝目前只支持UNIX/LINUX的平臺,固然後續會想辦法支持WINDOWS系統。而單元測試則使用了gtest,目的是讓一些問題更能及早的發現,這一點我也會徵求更多的意見,由於我以前雖然接觸過這個框架,只是一直沒有使用,而對這個測試框架來講也不知道它的優缺點。至於靈活封裝就是移除了核心接口中的許多依賴,我將這部分東西移到了插件中,如今的插件中就有如腳本插件(lua)、數據庫插件(odbc)、網絡協議插件(google protobuf),而這些插件能夠根據應用的須要又框架自己提供接口來加載使用。並且若是有人用心的話,可能會在框架裏發現一個有趣的模塊,那就是數據庫的語法封裝部分(DB QUERY BUILDER),會支持大部分的數據庫語法,這樣使得咱們想要隨意切換不一樣數據庫提供了良好的支持,固然這部分仍舊是嘗試階段。並且關於這個語法封裝器,我參考了Laravel(PHP框架)的代碼,有興趣的同仁能夠去了解一下。app

  在這裏貼一段代碼來看看咱們PFnew的數據庫語法的支持以及單元測試示例:框架

#include "gtest/gtest.h"
#include "pf/engine/kernel.h"
#include "pf/db/query/grammars/grammar.h"
#include "pf/db/query/grammars/mysql_grammar.h"
#include "pf/db/connection.h"
#include "pf/db/query/builder.h"
#include "pf/support/helpers.h"

enum {
  kDBTypeODBC = 1,
};

using namespace pf_db::query;
using namespace pf_basic::type;

class DBQueryBuilder : public testing::Test {

 public:
   static void SetUpTestCase() {
     
     GLOBALS["log.print"] = false; //First forbid the log print.

     GLOBALS["default.db.open"] = true;
     GLOBALS["default.db.type"] = kDBTypeODBC;
     GLOBALS["default.db.name"] = "pf_test";
     GLOBALS["default.db.user"] = "root";
     GLOBALS["default.db.password"] = "mysql";

     engine_.add_libraryload("pf_plugin_odbc", {kDBTypeODBC});

     engine_.init();

     auto connection = new pf_db::Connection(engine_.get_db());
     unique_move(pf_db::Connection, connection, connection_);
     auto builder = new Builder(connection_.get(), nullptr);
     unique_move(Builder, builder, builder_);
     
     auto mysql_grammar = new grammars::MysqlGrammar();
     unique_move(grammars::Grammar, mysql_grammar, mysql_grammar_);
     auto mysql_builder = new Builder(connection_.get(), mysql_grammar_.get());
     unique_move(Builder, mysql_builder, mysql_builder_);
   }

   static void TearDownTestCase() {
     //std::cout << "TearDownTestCase" << std::endl;
   }

 public:
   virtual void SetUp() {
     builder_->clear();
     mysql_builder_->clear();
   }
   virtual void TearDown() {
   }

 protected:
   static pf_engine::Kernel engine_;
   static std::unique_ptr<pf_db::Connection> connection_;
   static std::unique_ptr<grammars::Grammar> mysql_grammar_;
   static std::unique_ptr<Builder> builder_;
   static std::unique_ptr<Builder> mysql_builder_;

};

pf_engine::Kernel DBQueryBuilder::engine_;
std::unique_ptr<pf_db::Connection> DBQueryBuilder::connection_{nullptr};
std::unique_ptr<Builder> DBQueryBuilder::builder_{nullptr};
std::unique_ptr<Builder> DBQueryBuilder::mysql_builder_{nullptr};
std::unique_ptr<grammars::Grammar> DBQueryBuilder::mysql_grammar_{nullptr};

TEST_F(DBQueryBuilder, construct) {
  Builder object(nullptr, nullptr);
  pf_db::Connection connection(engine_.get_db());
  Builder builder_test1(&connection, nullptr);
  grammars::Grammar grammar;
  Builder builder_test2(&connection, &grammar);
}

TEST_F(DBQueryBuilder, testBasicSelect) {
  builder_->select({"*"}).from("users");
  ASSERT_STREQ("select * from \"users\"", builder_->to_sql().c_str());
}

TEST_F(DBQueryBuilder, testBasicSelectWithGetColumns) {
  builder_->from("users").get();
  ASSERT_TRUE(builder_->columns_.empty());
  
  ASSERT_STREQ("select * from \"users\"", builder_->to_sql().c_str());
  ASSERT_TRUE(builder_->columns_.empty());
}

TEST_F(DBQueryBuilder, testBasicSelectUseWritePdo) {

}

TEST_F(DBQueryBuilder, testBasicTableWrappingProtectsQuotationMarks) {
  builder_->select({"*"}).from("some\"table");
  ASSERT_STREQ("select * from \"some\"\"table\"", builder_->to_sql().c_str());
}

TEST_F(DBQueryBuilder, testAliasWrappingAsWholeConstant) {
  builder_->select({"x.y as foo.bar"}).from("baz");
  ASSERT_STREQ("select \"x\".\"y\" as \"foo.bar\" from \"baz\"", 
               builder_->to_sql().c_str());
}

TEST_F(DBQueryBuilder, testAliasWrappingWithSpacesInDatabaseName) {
  builder_->select({"w x.y.z as foo.bar"}).from("baz");
  ASSERT_STREQ("select \"w x\".\"y\".\"z\" as \"foo.bar\" from \"baz\"",
               builder_->to_sql().c_str());
}

TEST_F(DBQueryBuilder, testAddingSelects) {
  builder_->select({"foo"}).
            add_select({"bar"}).add_select({"baz", "boom"}).from("users");
  ASSERT_STREQ("select \"foo\", \"bar\", \"baz\", \"boom\" from \"users\"",
               builder_->to_sql().c_str());
}

TEST_F(DBQueryBuilder, testBasicSelectWithPrefix) {
  builder_->get_grammar()->set_table_prefix("prefix_");
  builder_->select({"*"}).from("users");
  ASSERT_STREQ("select * from \"prefix_users\"",
               builder_->to_sql().c_str());
}

TEST_F(DBQueryBuilder, testBasicSelectDistinct) {
  builder_->distinct().select({"foo", "bar"}).from("users");
  ASSERT_STREQ("select distinct \"foo\", \"bar\" from \"users\"",
               builder_->to_sql().c_str());
}

TEST_F(DBQueryBuilder, testBasicAlias) {
  builder_->select({"foo as bar"}).from("users");
  ASSERT_STREQ("select \"foo\" as \"bar\" from \"users\"",
               builder_->to_sql().c_str());
}

TEST_F(DBQueryBuilder, testAliasWithPrefix) {
  builder_->get_grammar()->set_table_prefix("prefix_");
  builder_->select({"*"}).from("users as people");
  ASSERT_STREQ("select * from \"prefix_users\" as \"prefix_people\"",
               builder_->to_sql().c_str());
}

TEST_F(DBQueryBuilder, testJoinAliasesWithPrefix) {
  builder_->get_grammar()->set_table_prefix("prefix_");
  builder_->select({"*"}).from("services").join(
      "translations AS t", "t.item_id", "=", "services.id");
   ASSERT_STREQ(
       "select * from \"prefix_services\" inner join \"prefix_translations\" \
as \"prefix_t\" on \"prefix_t\".\"item_id\" = \"prefix_services\".\"id\"",
       builder_->to_sql().c_str());
}

TEST_F(DBQueryBuilder, testBasicTableWrapping) {
  builder_->select({"*"}).from("public.users");
  ASSERT_STREQ("select * from \"public\".\"users\"",
               builder_->to_sql().c_str());
}

TEST_F(DBQueryBuilder, testWhenCallback) {
  auto callback = [](Builder *query, const variable_t &condition) {
    ASSERT_TRUE(condition.get<bool>());
    query->where("id", "=", 1);
  };
  builder_->select({"*"}).from("users").when(true, callback).where("email", "foo");
  ASSERT_STREQ("select * from \"users\" where \"id\" = ? and \"email\" = ?",
               builder_->to_sql().c_str());

  builder_->clear();
  builder_->select({"*"}).from("users").when(false, callback).where("email", "foo");
  ASSERT_STREQ("select * from \"users\" where \"email\" = ?",
               builder_->to_sql().c_str());
}

TEST_F(DBQueryBuilder, testWhenCallbackWithReturn) {

}

void assertEquals(
    const variable_array_t &a, const variable_array_t &b, int32_t line = -1) {
  if (line != -1)
    std::cout << "assertEquals: " << line << std::endl;
  ASSERT_TRUE(a.size() == b.size());
  for (size_t i = 0; i < a.size(); ++i)
    ASSERT_STREQ(a[i].data.c_str(), b[i].data.c_str());
}

TEST_F(DBQueryBuilder, testWhenCallbackWithDefault) {
  auto callback = [](Builder *query, const variable_t &condition) {
    ASSERT_STREQ(condition.c_str(), "truthy");
    query->where("id", "=", 1);
  };
  auto def = [](Builder *query, const variable_t &condition) {
    ASSERT_TRUE(condition == 0);
    query->where("id", "=", 2);
  };

  builder_->select({"*"}).
            from("users").when("truthy", callback, def).where("email", "foo");
  ASSERT_STREQ("select * from \"users\" where \"id\" = ? and \"email\" = ?",
               builder_->to_sql().c_str());

  assertEquals({1, "foo"}, builder_->get_bindings(), __LINE__);

  builder_->clear();

  builder_->select({"*"}).
            from("users").when(0, callback, def).where("email", "foo");
  ASSERT_STREQ("select * from \"users\" where \"id\" = ? and \"email\" = ?",
               builder_->to_sql().c_str());

  assertEquals({2, "foo"}, builder_->get_bindings(), __LINE__);
}

TEST_F(DBQueryBuilder, testUnlessCallback) {
  auto callback = [](Builder *query, const variable_t &condition) {
    ASSERT_FALSE(condition.get<bool>());
    query->where("id", "=", 1);
  };

  builder_->select({"*"}).
            from("users").unless(false, callback).where("email", "foo");
  ASSERT_STREQ("select * from \"users\" where \"id\" = ? and \"email\" = ?",
               builder_->to_sql().c_str());


  builder_->clear();
  builder_->select({"*"}).
            from("users").unless(true, callback).where("email", "foo");
  ASSERT_STREQ("select * from \"users\" where \"email\" = ?",
               builder_->to_sql().c_str());

}

TEST_F(DBQueryBuilder, testUnlessCallbackWithReturn) {

}

TEST_F(DBQueryBuilder, testUnlessCallbackWithDefault) {
  auto callback = [](Builder *query, const variable_t &condition) {
    ASSERT_TRUE(condition == 0);
    query->where("id", "=", 1);
  };
  auto def = [](Builder *query, const variable_t &condition) {
    ASSERT_STREQ(condition.c_str(), "truthy");
    query->where("id", "=", 2);
  };

  builder_->select({"*"}).
            from("users").unless(0, callback, def).where("email", "foo");
  ASSERT_STREQ("select * from \"users\" where \"id\" = ? and \"email\" = ?",
               builder_->to_sql().c_str());

  assertEquals({1, "foo"}, builder_->get_bindings(), __LINE__);

  builder_->clear();

  builder_->select({"*"}).
            from("users").unless("truthy", callback, def).where("email", "foo");
  ASSERT_STREQ("select * from \"users\" where \"id\" = ? and \"email\" = ?",
               builder_->to_sql().c_str());

  assertEquals({2, "foo"}, builder_->get_bindings(), __LINE__);
}

TEST_F(DBQueryBuilder, testTapCallback) {
  auto callback = [](Builder *query) {
    query->where("id", "=", 1);
  };

  builder_->select({"*"}).from("users").tap(callback).where("email", "foo"); 
  ASSERT_STREQ("select * from \"users\" where \"id\" = ? and \"email\" = ?",
               builder_->to_sql().c_str());
}

TEST_F(DBQueryBuilder, testBasicWheres) {
  builder_->select({"*"}).from("users").where("id", "=", 1);
  ASSERT_STREQ("select * from \"users\" where \"id\" = ?",
               builder_->to_sql().c_str());
  assertEquals({1}, builder_->get_bindings());
}

TEST_F(DBQueryBuilder, testMySqlWrappingProtectsQuotationMarks) {
/**
  builder_->select({"*"}).from("some`table");
  ASSERT_STREQ("select * from `some``table`",
               builder_->to_sql().c_str());
**/
}

TEST_F(DBQueryBuilder, testDateBasedWheresAcceptsTwoArguments) {
  auto builder = mysql_builder_.get();
  builder->select({"*"}).from("users").where_date("created_at", "1");
  ASSERT_STREQ("select * from `users` where date(`created_at`) = ?",
               builder->to_sql().c_str());

  builder->clear();
  builder->select({"*"}).from("users").where_day("created_at", "1");
  ASSERT_STREQ("select * from `users` where day(`created_at`) = ?",
               builder->to_sql().c_str());

  builder->clear();
  builder->select({"*"}).from("users").where_month("created_at", "1");
  ASSERT_STREQ("select * from `users` where month(`created_at`) = ?",
               builder->to_sql().c_str());

  builder->clear();
  builder->select({"*"}).from("users").where_year("created_at", "1");
  ASSERT_STREQ("select * from `users` where year(`created_at`) = ?",
               builder->to_sql().c_str());
}

TEST_F(DBQueryBuilder, testWhereDayMySql) {
  auto builder = mysql_builder_.get();
  builder->select({"*"}).from("users").where_day("created_at", "=", 1);
  ASSERT_STREQ("select * from `users` where day(`created_at`) = ?",
               builder->to_sql().c_str());
  assertEquals({1}, builder->get_bindings());
}

TEST_F(DBQueryBuilder, testWhereMonthMySql) {
  auto builder = mysql_builder_.get();
  builder->select({"*"}).from("users").where_month("created_at", "=", 5);
  ASSERT_STREQ("select * from `users` where month(`created_at`) = ?",
               builder->to_sql().c_str());
  assertEquals({5}, builder->get_bindings());
}

TEST_F(DBQueryBuilder, testWhereYearMySql) {
  auto builder = mysql_builder_.get();
  builder->select({"*"}).from("users").where_year("created_at", "=", 2018);
  ASSERT_STREQ("select * from `users` where year(`created_at`) = ?",
               builder->to_sql().c_str());
  assertEquals({2018}, builder->get_bindings());
}

TEST_F(DBQueryBuilder, testWhereTimeMySql) {
  auto builder = mysql_builder_.get();
  builder->select({"*"}).from("users").where_time("created_at", "=", "22:00");
  ASSERT_STREQ("select * from `users` where time(`created_at`) = ?",
               builder->to_sql().c_str());
  assertEquals({"22:00"}, builder->get_bindings());
}

TEST_F(DBQueryBuilder, testWhereDatePostgres) {

}

TEST_F(DBQueryBuilder, testWhereDayPostgres) {

}

TEST_F(DBQueryBuilder, testWhereMonthPostgres) {

}

TEST_F(DBQueryBuilder, testWhereYearPostgres) {

}

TEST_F(DBQueryBuilder, testWhereDaySqlite) {

}

TEST_F(DBQueryBuilder, testWhereMonthSqlite) {

}

TEST_F(DBQueryBuilder, testWhereYearSqlite) {

}

TEST_F(DBQueryBuilder, testWhereDaySqlServer) {

}

TEST_F(DBQueryBuilder, testWhereMonthSqlServer) {

}

TEST_F(DBQueryBuilder, testWhereYearSqlServer) {

}

TEST_F(DBQueryBuilder, testWhereBetweens) {
  builder_->select({"*"}).from("users").where_between("id", {1, 2});
  ASSERT_STREQ("select * from \"users\" where \"id\" between ? and ?",
               builder_->to_sql().c_str());
  assertEquals({1, 2}, builder_->get_bindings());

  builder_->clear();
  builder_->select({"*"}).from("users").where_notbetween("id", {1, 2});
  ASSERT_STREQ("select * from \"users\" where \"id\" not between ? and ?",
               builder_->to_sql().c_str());
  assertEquals({1, 2}, builder_->get_bindings());
}

TEST_F(DBQueryBuilder, testBasicOrWheres) {
  builder_->select({"*"}).
            from("users").where("id", "=", 1).or_where("email", "=", "foo");
  ASSERT_STREQ("select * from \"users\" where \"id\" = ? or \"email\" = ?",
               builder_->to_sql().c_str());
  assertEquals({1, "foo"}, builder_->get_bindings());
}

TEST_F(DBQueryBuilder, testRawWheres) {
  builder_->select({"*"}).
            from("users").where_raw("id = ? or email = ?", {1, "foo"});
  ASSERT_STREQ("select * from \"users\" where id = ? or email = ?",
               builder_->to_sql().c_str());
  assertEquals({1, "foo"}, builder_->get_bindings());
}

TEST_F(DBQueryBuilder, testRawOrWheres) {
  builder_->select({"*"}).
            from("users").where("id", "=", 1).or_where_raw("email = ?", {"foo"});
  ASSERT_STREQ("select * from \"users\" where \"id\" = ? or email = ?",
               builder_->to_sql().c_str());
  assertEquals({1, "foo"}, builder_->get_bindings());
}

  PFnew地址

  https://github.com/viticm/plainless

相關文章
相關標籤/搜索