Copilot commented on code in PR #266:
URL: https://github.com/apache/fluss-rust/pull/266#discussion_r2776722986


##########
bindings/cpp/src/lib.rs:
##########
@@ -618,6 +622,12 @@ impl Table {
                 self.table_info.clone(),
             );
 
+            let all_columns = self.table_info.get_schema().columns();
+            let projected_columns: Vec<_> = column_indices
+                .iter()
+                .map(|&i| all_columns[i].clone())
+                .collect();

Review Comment:
   `projected_columns` is built via direct indexing (`all_columns[i]`), which 
will panic on an out-of-range projection index coming from the C++ API. Because 
this runs inside the FFI boundary, a panic will abort the process rather than 
returning a clean error. Please validate indices (e.g., use `get()` and return 
a `Result` error) before building `projected_columns`.
   ```suggestion
                   .map(|&i| {
                       all_columns
                           .get(i)
                           .cloned()
                           .ok_or_else(|| {
                               format!(
                                   "Invalid column index {i}: schema has {} 
columns",
                                   all_columns.len()
                               )
                           })
                   })
                   .collect::<Result<_, String>>()?;
   ```



##########
bindings/cpp/src/table.cpp:
##########
@@ -22,12 +22,45 @@
 #include "ffi_converter.hpp"
 #include "rust/cxx.h"
 #include <arrow/c/bridge.h>
+#include <ctime>
 // todo:  bindings/cpp/BUILD.bazel still doesn’t declare Arrow include/link 
dependencies.
 // In environments where Bazel does not already have Arrow available, this 
will fail at compile/link time.
 #include <arrow/record_batch.h>
 
 namespace fluss {
 
+static constexpr int kSecondsPerDay = 24 * 60 * 60;
+
+Date Date::FromYMD(int year, int month, int day) {
+    std::tm tm{};
+    tm.tm_year = year - 1900;
+    tm.tm_mon = month - 1;
+    tm.tm_mday = day;
+    std::time_t epoch_seconds = timegm(&tm);
+    return {static_cast<int32_t>(epoch_seconds / kSecondsPerDay)};
+}
+
+int Date::Year() const {
+    std::time_t epoch_seconds = static_cast<std::time_t>(days_since_epoch) * 
kSecondsPerDay;
+    std::tm tm{};
+    gmtime_r(&epoch_seconds, &tm);
+    return tm.tm_year + 1900;
+}
+
+int Date::Month() const {
+    std::time_t epoch_seconds = static_cast<std::time_t>(days_since_epoch) * 
kSecondsPerDay;
+    std::tm tm{};
+    gmtime_r(&epoch_seconds, &tm);
+    return tm.tm_mon + 1;
+}
+
+int Date::Day() const {
+    std::time_t epoch_seconds = static_cast<std::time_t>(days_since_epoch) * 
kSecondsPerDay;
+    std::tm tm{};
+    gmtime_r(&epoch_seconds, &tm);

Review Comment:
   `timegm` and `gmtime_r` are non-standard/POSIX APIs and are not available on 
all platforms (notably Windows) and may require feature macros on some libc 
implementations. This can make the C++ bindings fail to compile outside POSIX 
environments. Consider replacing with a portable YMD<->days-since-epoch 
conversion (pure arithmetic), or provide platform-specific implementations 
(e.g., `_mkgmtime`/`gmtime_s` on Windows and `timegm`/`gmtime_r` on POSIX) 
behind `#ifdef`s.
   ```suggestion
   // Portable wrappers for converting between UTC calendar dates and epoch 
seconds.
   static std::time_t timegm_utc(std::tm* tm) {
   #if defined(_WIN32)
       // _mkgmtime interprets the tm structure as UTC and returns time_t 
seconds since epoch.
       return _mkgmtime(tm);
   #else
       return ::timegm(tm);
   #endif
   }
   
   static std::tm gmtime_utc(std::time_t epoch_seconds) {
       std::tm tm{};
   #if defined(_WIN32)
       // gmtime_s has (tm*, time_t*) parameter order on Windows.
       gmtime_s(&tm, &epoch_seconds);
   #else
       ::gmtime_r(&epoch_seconds, &tm);
   #endif
       return tm;
   }
   
   Date Date::FromYMD(int year, int month, int day) {
       std::tm tm{};
       tm.tm_year = year - 1900;
       tm.tm_mon = month - 1;
       tm.tm_mday = day;
       std::time_t epoch_seconds = timegm_utc(&tm);
       return {static_cast<int32_t>(epoch_seconds / kSecondsPerDay)};
   }
   
   int Date::Year() const {
       std::time_t epoch_seconds = static_cast<std::time_t>(days_since_epoch) * 
kSecondsPerDay;
       std::tm tm = gmtime_utc(epoch_seconds);
       return tm.tm_year + 1900;
   }
   
   int Date::Month() const {
       std::time_t epoch_seconds = static_cast<std::time_t>(days_since_epoch) * 
kSecondsPerDay;
       std::tm tm = gmtime_utc(epoch_seconds);
       return tm.tm_mon + 1;
   }
   
   int Date::Day() const {
       std::time_t epoch_seconds = static_cast<std::time_t>(days_since_epoch) * 
kSecondsPerDay;
       std::tm tm = gmtime_utc(epoch_seconds);
   ```



##########
bindings/cpp/src/lib.rs:
##########
@@ -665,6 +677,12 @@ impl Table {
                 self.table_info.clone(),
             );
 
+            let all_columns = self.table_info.get_schema().columns();
+            let projected_columns: Vec<_> = column_indices
+                .iter()
+                .map(|&i| all_columns[i].clone())
+                .collect();

Review Comment:
   Same issue as above: `projected_columns` is constructed with 
`all_columns[i]` before calling `.project(...)`, so invalid indices can 
panic/abort across FFI. Please bounds-check `column_indices` and return an 
error instead of panicking.



-- 
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.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to