arpadboda commented on a change in pull request #656: MINIFI-1013 Used soci 
library.
URL: https://github.com/apache/nifi-minifi-cpp/pull/656#discussion_r358504317
 
 

 ##########
 File path: extensions/sql/data/JSONSQLWriter.cpp
 ##########
 @@ -21,78 +21,132 @@
 #include "rapidjson/stringbuffer.h"
 #include "rapidjson/prettywriter.h"
 #include "Exception.h"
+#include "Utils.h"
+
 namespace org {
 namespace apache {
 namespace nifi {
 namespace minifi {
 namespace sql {
 
-JSONSQLWriter::JSONSQLWriter(const soci::rowset<soci::row> &rowset, 
std::ostream *out)
-    : SQLWriter(rowset), json_payload(rapidjson::kArrayType), 
output_stream(out){
+JSONSQLWriter::JSONSQLWriter(const soci::rowset<soci::row> &rowset, 
std::ostream *out, MaxCollector* pMaxCollector)
+  : SQLWriter(rowset), json_payload_(rapidjson::kArrayType), 
output_stream_(out), pMaxCollector_(pMaxCollector) {
 }
 
 JSONSQLWriter::~JSONSQLWriter() {
 }
 
-bool JSONSQLWriter::addRow(const soci::row &row) {
-  rapidjson::Document::AllocatorType &alloc = json_payload.GetAllocator();
+bool JSONSQLWriter::addRow(const soci::row &row, size_t rowCount) {
+  rapidjson::Document::AllocatorType &alloc = json_payload_.GetAllocator();
   rapidjson::Value rowobj(rapidjson::kObjectType);
+
+  // 'countColumnsInMaxCollector' is used to check that all columns in 
maxCollector are in row columns.
+  // It is checked here since don't know if it is possible in 'soci' to get 
coulmns info of a select statements without executing query.
+  int countColumnsInMaxCollector = 0;
+
   for (std::size_t i = 0; i != row.size(); ++i) {
     const soci::column_properties & props = row.get_properties(i);
 
+    const auto& columnName = utils::toLower(props.get_name());
+
+    if (pMaxCollector_ && rowCount == 0 && 
pMaxCollector_->hasColumn(columnName)) {
+      countColumnsInMaxCollector++;
+    }
+
     rapidjson::Value name;
     name.SetString(props.get_name().c_str(), props.get_name().length(), alloc);
 
     rapidjson::Value valueVal;
-    switch (const auto dataType = props.get_data_type()) {
-      case soci::data_type::dt_string: {
-        std::string str = std::string(row.get<std::string>(i));
-        valueVal.SetString(str.c_str(), str.length(), alloc);
-      }
-      break;
-      case soci::data_type::dt_double:
-        valueVal.SetDouble(row.get<double>(i));
-      break;
-      case soci::data_type::dt_integer:
-        valueVal.SetInt(row.get<int>(i));
-      break;
-      case soci::data_type::dt_long_long: {
-        int64_t i64val = row.get<long long>(i);
-        valueVal.SetInt64(i64val);
-      }
-      break;
-      case soci::data_type::dt_unsigned_long_long: {
-        uint64_t u64val = row.get<unsigned long long>(i);
-        valueVal.SetUint64(u64val);
-      }
-      break;
-      case soci::data_type::dt_date: {
-        std::tm when = row.get<std::tm>(i);
-        std::string str = std::string(asctime(&when));
-        // asctime adds '\n' in the end.
-        if (str[str.size() - 1] == '\n') {
-          str.resize(str.size() - 1);
+
+    if (row.get_indicator(i) == soci::i_null) {
+      std::string null = "NULL";
+      valueVal.SetString(null.c_str(), null.length(), alloc);
+    } else {
+      switch (const auto dataType = props.get_data_type()) {
+        case soci::data_type::dt_string: {
+          auto value = std::string(row.get<std::string>(i));
+          if (pMaxCollector_) {
+            pMaxCollector_->updateMaxValue(columnName, '\'' + value + '\'');
+          }
+          valueVal.SetString(value.c_str(), value.length(), alloc);
+        }
+        break;
+        case soci::data_type::dt_double: {
+          auto value = row.get<double>(i);
+          if (pMaxCollector_) {
+            pMaxCollector_->updateMaxValue(columnName, value);
+          }
+          valueVal.SetDouble(value);
+        }
+        break;
+        case soci::data_type::dt_integer: {
+          auto value = row.get<int>(i);
+          if (pMaxCollector_) {
+            pMaxCollector_->updateMaxValue(columnName, value);
+          }
+          valueVal.SetInt(value);
+        }
+        break;
+        case soci::data_type::dt_long_long: {
+          auto value = row.get<long long>(i);
+          if (pMaxCollector_) {
+            pMaxCollector_->updateMaxValue(columnName, value);
+          }
+          valueVal.SetInt64(value);
+        }
+        break;
+        case soci::data_type::dt_unsigned_long_long: {
+          auto value = row.get<unsigned long long>(i);
+          if (pMaxCollector_) {
+            pMaxCollector_->updateMaxValue(columnName, value);
+          }
+          valueVal.SetUint64(value);
+        }
+        break;
+        case soci::data_type::dt_date: {
+          // It looks like design bug in soci - for `dt_date`, it returns 
std::tm, which doesn't have mmilliseconds, but DB 'datetime' has milliseconds.
+          // Don't know if it is possible to get a string representation for 
'dt_date' type.
+          // The problem for maxCollector, if milliseconds value is not stored 
as a maximum, then when running query with 'select ... datetimeColumn > 
maxValue', 
+          // it will be always at least one record since DB has milliseconds 
"maxValue.milliseconds".
+          // For a workaround in the string representation for 'dt_date', add 
'999' for maxCollector (won't work for cases where time precision is important).
+          std::tm when = row.get<std::tm>(i);
+
+          char strWhen[128];
+          std::strftime(strWhen, sizeof(strWhen), "%Y-%m-%d %H:%M:%S", &when);
 
 Review comment:
   I think the return value should be checked here. In case it's 0, the data in 
array (strWhen) is undefined. 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
[email protected]


With regards,
Apache Git Services

Reply via email to