Apparently, the Rust Postgres library doesn't allow the datatype u64 to be stored in QuestDB. So I am trying to sneak it in bypassing it as a String to the prepared statement:
INSERT INTO table_x VALUES ($1,cast($2 as LONG))
However, this is resulting in an error for me too, when I pass a String for $2:
Error { kind: ToSql(1), cause: Some(WrongType { postgres: Numeric, rust: "&alloc::string::String" }) }
Does anyone have an idea how to solve this?
The following works okay with as:
use postgres::{Client, NoTls, Error};
fn main() -> Result<(), Error> {
let mut client = Client::connect("postgresql://admin:quest#localhost:8812/qdb", NoTls)?;
// Basic query
client.batch_execute(
"CREATE TABLE IF NOT EXISTS rust (name STRING, value long);",
)?;
// Parameterized query
let name = "abc";
let uval: u64 = 9223372036854773000;
let val = uval as i64;
client.execute(
"INSERT INTO rust (name, value) VALUES ($1,$2)",
&[&name, &val],
)?;
println!("import finished");
Ok(())
}
Note the difference with i64 and u64 is the following:
i64 is +/- 9223372036854775808
u64 unsigned int is 0-18446744073709551615
The data type in QuestDB for long is 64 bit signed int (i64) so
if you have values over 9223372036854775808, you will need different handling.
edit for more information, see the following resources:
Data types in QuestDB
Rust postgres types
Rust i64 primitive type
Rust u64 primitive type
Related
I have following problem:
I have iOS application with C++ core. Data is bridged through C++<->ObjCpp<->ObjC chain, data structures are later imported in swift from ObjC.
I have optional<vector<optional>> in one of my structures and there is problem with importing it. Vector is converted to NSList, which is populated by data. Because there can't be nil in NSList, I add NSNull to it. If vector isn't optional - I can work with it in Swift, though it isn't very convenient.
let arr = struct.myArray as NSArray
var swift_arr: [UUID?] = []
for val in arr {
if val is NSNull {
swift_arr.append( nil )
} else if val is NSUUID {
swift_arr.append( val as? UUID )
} else {
fatalError()
}
}
But if array is optional - there is big problem, because when I try to bind optional value, Swift tries to convert it to [UUID?] from NSArray, and when there is NSNull among NSUUIDs, it crashes, because NSNull cannot be converted to UUID.
Is there any proper way to handle such arrays?
I'd like to make a POC of using leveldb in order to store key-value table of different data types in protobuf format.
So far I was able to open the database file, and I also saw the get function with the following signature :
virtual Status Get(const ReadOptions& options, const Slice& key, std::string* value)=0
I understand that the value is actually refers to a binary string like vector and not regular alphanumeric string, so I guess it can fit for multi type primitives like string, uint, enum) but how can it support struct/class that represent protobuf layout in c++ ?
So this is my proto file that I'd like to store in the leveldb:
message agentStatus {
string ip = 1;
uint32 port = 2;
string url = 3;
google.protobuf.Timestamp last_seen = 4;
google.protobuf.Timestamp last_keepalive = 5;
bool status = 6;
}
and this is my current POC code. How can I use the get method to access any of the variables from the table above ?
#include <leveldb/db.h>
void main () {
std::string db_file_path = "/tmp/data.db";
leveldb::DB* db;
leveldb::Status status;
leveldb::Options options;
options.create_if_missing = false;
status_ = leveldb::DB::Open(options, db_file_path, &db);
if (!status_.ok()) {
throw std::logic_error("unable to open db");
}
Thanks !
You need to serialize the protobuf message into a binary string, i.e. SerilaizeToString, and use the Put method to write the binary string to LevelDB with a key.
Then you can use the Get method to retrieve the binary value with the given key, and parse the binary string to a protobuf message, i.e. ParseFromString.
Finally, you can get fields of the message.
I'm trying to verify an IP address in Rust, but I can't find a solution casting a str into a u8 that doesn't involve using nightly Rust:
use std::net::{IpAddr, Ipv4Addr};
fn verify_address(address: String) -> bool {
let v: Vec<&str> = address.split('.').collect();
let v_u8: Vec<u8> = v.iter().map(|c| *c.to_owned() as u8).collect();
let addr = IpAddr::V4(Ipv4Addr::new(v_u8[0], v_u8[1], v_u8[2], v_u8[3]));
//.expect("ERR: Error parsing IPv4 address!");
if !addr.is_ipv4() {
return false;
}
return true;
}
error[E0605]: non-primitive cast: `str` as `u8`
--> src/lib.rs:6:42
|
6 | let v_u8: Vec<u8> = v.iter().map(|c| *c.to_owned() as u8).collect();
| ^^^^^^^^^^^^^^^^^^^
|
= note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
Please reread the chapter about error handling. You do not need all this:
use std::net::Ipv4Addr;
fn main() {
let ip = "127.0.0.1".parse::<Ipv4Addr>();
match ip {
Ok(ip) => println!("valid"),
Err(e) => println!("invalid"),
}
}
About your question, you can use primitive cast for... primitive types only. You must use From and Into, or parse if you convert a &str into another type.
I have a table having real datatype column in sql server.
CREATE TABLE Table_1(f_int int, f_string nchar(10), f_real real);
INSERT INTO Table_1 (f_int, f_string, f_real) VALUES (42000000, 'myString2', 40003.16);
when i execute select f_real from Table_1; using ODBC API(From c++ application)
I get value 40003.160156250000 instead of 40003.16
I have binded the result column like below.
struct ColValInfo
{
ColValInfo(){
pValue = NULL;
}
SQLPOINTER pValue;
SQLINTEGER StrLen_or_Ind;
};
ColValInfo* m_pColValInfo;
m_pColValInfo = new ColValInfo[numColumns];
m_pColValInfo[0].pValue = (SQLPOINTER) new char[50];
SQLBindCol(hstmt, 1, SQL_C_DOUBLE, m_pColValInfo[0].pValue,
siz, &(m_pColValInfo[0].StrLen_or_Ind));
Note : SQLPOINTER is a typedef of void * and SQLINTEGER is typedef of long.
I am getting data by doing below
double data = *(double *)m_pColValInfo[0].pValue;
I am using odbc driver 13 for communicating with database. As driver takes care of converting data from sql type to native type which is specified in SQLBindCol ODBC call, i want to know how i am getting 40003.160156250000 when i have 40003.16 in my database.
I have changed precision and scale of the data base column to decimal(16,2), to see if that makes any difference, i see no difference it makes.
Could some please let me know where the conversion is going wrong.
I am trying to generate a metadata for the LLVM IR i have generated. I want to generate a metadata of the form :
!nvvm.annotations = !{!0}
!0 = metadata !{void ()* #foo, metadata !"kernel", i32 1}
Where foo is a function in my LLVM IR. Right now I am only able to generate a metadata of the form:
!nvvm.annotations = !{!0}
!0 = !{!"kernel"}
I used the following code for the above metadata generation.
char metaDataArgument[512];
sprintf(metaDataArgument, "%s", pipelineKernelName);
llvm::NamedMDNode *nvvmMetadataNode = LLVMModule->getOrInsertNamedMetadata("nvvm.annotations");
llvm::MDNode *MDNOdeNVVM = llvm::MDNode::get(*context, llvm::MDString::get(*context, "kernel"));
nvvmMetadataNode->addOperand(MDNOdeNVVM);
Could someone tell me how to modify the above code to generate metadata of the required form
Your metadata will be a tuple with 3 elements.
The first one is a global value, which is wrapped when insert in the metadata hierarchy as "ValueAsMetadata" (we can use the Constant subclass since GlobalValues are constant).
The second is a MDString, you got this one.
The last one is wrapped as a ConstantAsMetadata.
This should look approximately like the follow:
SmallVector<Metadata *, 32> Ops; // Tuple operands
GlobalValue *Foo = Mod.getNamedValue("foo");
if (!Foo) report_fatal_error("Expected foo..");
Ops.push_back(llvm::ValueAsMetadata::getConstant(Foo));
Ops.push_back(llvm::MDString::get(*context, "kernel"));
// get constant i32 1
Type *I32Ty = Type::getInt32Ty(*context);
Contant *One = ConstantInt::get(I32Ty, 1);
Ops.push_back(llvm::ValueAsMetadata::getConstant(One));
auto *Node = MDTuple::get(Context, Ops);