diff --git a/.changeset/selfish-worms-buy.md b/.changeset/selfish-worms-buy.md new file mode 100644 index 0000000..c0379ad --- /dev/null +++ b/.changeset/selfish-worms-buy.md @@ -0,0 +1,5 @@ +--- +"@journeyapps/react-native-quick-sqlite": patch +--- + +Result object keys are no longer ordered alphabetically, but rather maintain insertion order. The behaviour now matches other libraries. diff --git a/cpp/JSIHelper.cpp b/cpp/JSIHelper.cpp index ac86be4..6fcb149 100644 --- a/cpp/JSIHelper.cpp +++ b/cpp/JSIHelper.cpp @@ -143,40 +143,44 @@ jsi::Value createSequelQueryExecutionResult(jsi::Runtime &rt, SQLiteOPResult sta // Converting row results into objects size_t rowCount = results->size(); jsi::Object rows = jsi::Object(rt); - if (rowCount > 0) + if (rowCount > 0 && metadata != NULL) { auto array = jsi::Array(rt, rowCount); for (int i = 0; i < rowCount; i++) { jsi::Object rowObject = jsi::Object(rt); - auto row = results->at(i); - for (auto const &entry : row) + auto row = results -> at(i); + // Iterate over metadata to maintain column order + for (const auto &column : *metadata) { - std::string columnName = entry.first; - QuickValue value = entry.second; - if (value.dataType == TEXT) + std::string columnName = column.columnName; + auto it = row.find(columnName); + if (it != row.end()) { - // using value.textValue (std::string) directly allows jsi::String to use length property of std::string (allowing strings with NULLs in them like SQLite does) - rowObject.setProperty(rt, columnName.c_str(), jsi::String::createFromUtf8(rt, value.textValue)); - } - else if (value.dataType == INTEGER) - { - rowObject.setProperty(rt, columnName.c_str(), jsi::Value(value.doubleOrIntValue)); - } - else if (value.dataType == DOUBLE) - { - rowObject.setProperty(rt, columnName.c_str(), jsi::Value(value.doubleOrIntValue)); - } - else if (value.dataType == ARRAY_BUFFER) - { - jsi::Function array_buffer_ctor = rt.global().getPropertyAsFunction(rt, "ArrayBuffer"); - jsi::Object o = array_buffer_ctor.callAsConstructor(rt, (int)value.arrayBufferSize).getObject(rt); - jsi::ArrayBuffer buf = o.getArrayBuffer(rt); - // It's a shame we have to copy here: see https://github.com/facebook/hermes/pull/419 and https://github.com/facebook/hermes/issues/564. - memcpy(buf.data(rt), value.arrayBufferValue.get(), value.arrayBufferSize); - rowObject.setProperty(rt, columnName.c_str(), o); - } - else + QuickValue value = it -> second; + if (value.dataType == TEXT) + { + // using value.textValue (std::string) directly allows jsi::String to use length property of std::string (allowing strings with NULLs in them like SQLite does) + rowObject.setProperty(rt, columnName.c_str(), jsi::String::createFromUtf8(rt, value.textValue)); + } else if (value.dataType == INTEGER) + { + rowObject.setProperty(rt, columnName.c_str(), jsi::Value(value.doubleOrIntValue)); + } else if (value.dataType == DOUBLE) + { + rowObject.setProperty(rt, columnName.c_str(), jsi::Value(value.doubleOrIntValue)); + } else if (value.dataType == ARRAY_BUFFER) + { + jsi::Function array_buffer_ctor = rt.global().getPropertyAsFunction(rt, "ArrayBuffer"); + jsi::Object o = array_buffer_ctor.callAsConstructor(rt, (int) value.arrayBufferSize).getObject(rt); + jsi::ArrayBuffer buf = o.getArrayBuffer(rt); + // It's a shame we have to copy here: see https://github.com/facebook/hermes/pull/419 and https://github.com/facebook/hermes/issues/564. + memcpy(buf.data(rt), value.arrayBufferValue.get(), value.arrayBufferSize); + rowObject.setProperty(rt, columnName.c_str(), o); + } else + { + rowObject.setProperty(rt, columnName.c_str(), jsi::Value(nullptr)); + } + } else { rowObject.setProperty(rt, columnName.c_str(), jsi::Value(nullptr)); } @@ -194,7 +198,7 @@ jsi::Value createSequelQueryExecutionResult(jsi::Runtime &rt, SQLiteOPResult sta for (int i = 0; i < column_count; i++) { auto column = metadata->at(i); jsi::Object column_object = jsi::Object(rt); - column_object.setProperty(rt, "columnName", jsi::String::createFromUtf8(rt, column.colunmName.c_str())); + column_object.setProperty(rt, "columnName", jsi::String::createFromUtf8(rt, column.columnName.c_str())); column_object.setProperty(rt, "columnDeclaredType", jsi::String::createFromUtf8(rt, column.columnDeclaredType.c_str())); column_object.setProperty(rt, "columnIndex", jsi::Value(column.columnIndex)); column_array.setValueAtIndex(rt, i, move(column_object)); diff --git a/cpp/JSIHelper.h b/cpp/JSIHelper.h index 9372937..cf84c4d 100644 --- a/cpp/JSIHelper.h +++ b/cpp/JSIHelper.h @@ -91,7 +91,7 @@ struct SequelBatchOperationResult */ struct QuickColumnMetadata { - string colunmName; + string columnName; int columnIndex; string columnDeclaredType; }; diff --git a/cpp/sqliteExecute.cpp b/cpp/sqliteExecute.cpp index 843a41c..3865d57 100644 --- a/cpp/sqliteExecute.cpp +++ b/cpp/sqliteExecute.cpp @@ -139,7 +139,7 @@ sqliteExecuteWithDB(sqlite3 *db, std::string const &query, const char *tp = sqlite3_column_decltype(statement, i); column_declared_type = tp != NULL ? tp : "UNKNOWN"; QuickColumnMetadata meta = { - .colunmName = column_name, + .columnName = column_name, .columnIndex = i, .columnDeclaredType = column_declared_type, };