Inserting `sql.Nulltime` into Postgres `timestamp with time zone` - database

Let's s say I have struct with a field like:
FinishedAt sql.NullTime `json:"finished_at"`
var out models.Job
err := client.QueryRow(ctx, updateQuery,
&job.FinishedAt,
).Scan(
&out.FinishedAt,
)
Above I use "github.com/jackc/pgx/v4" to work with PG.
There is no error during the update but the field is set to null after the request.
Using &job.FinishedAt.Time as an argument works appropriately but I want to understand why the sql.Nulltime type doesn't work.
Is that just related to how the library works?

Related

Parsing and converting JSON

I have an issue with TJSONObject.ParseJSONValue or TJSONObject.toString
the following code does not display the JSON from Memo1 in Memo2, only an empty "{}":
A:=tJSONObject.Create;
A.ParseJSONValue(Memo1.Lines.Text);
Memo2.Lines.Text:=A.ToString;
What is wrong with it?
ParseJSONValue() is a class function of TJSONObject. It does not modify the TJSONObject that it is called on, like you are expecting. It returns a new TJSONValue, which will point to a TJSONObject if the JSON data represents a JSON object. You are ignoring that return value (and thus leaking it, as you need to call Free on it with you are done using it).
You need to change your code to something more like this:
var A: TJSONValue;
A := TJSONObject.ParseJSONValue(Memo1.Text);
if A <> nil then
try
Memo2.Text := A.ToString;
finally
A.Free;
end;
ParseJSONValue is a FUNCTION so it needs to be
A:=A.ParseJSONValue...
how stupid....

How to insert a document if a filter returns nothing, otherwise replace the document found in mongodb with go?

I am not using the MGO package like in this example, just the active repo from here.
I am having a hard time reading the documentation. Basically, I have a bson.M object that I want to replace the current one, and if that one doesn't exist, insert it.
Currently my code looks like:
updateFilter := bson.D{{"from_symbol", fromSymbol}, {"to_symbol", strings.ToUpper(currency["to_symbol"].(string))}}
// The above seems to be correctly finding the documents I want
// currency is my bson.M object
_, err := collection.ReplaceOne(ctx, updateFilter, currency)
// However this line will not additionally insert if the object is not found, it is replacing fine
I'm sure I could manually run another query looking to see if the document exists, but that seems unnecessary.
Thank you!
EDIT:
It looks like there should be a way to do something with replaceOptions, see the documentation.
upsert := options.ReplaceOptions{Upsert: true}
_, err := collection.ReplaceOne(ctx, updateFilter, currency, upset)
However this gives me the error:
cannot use true (type bool) as type *bool in field value
Use the SetUpsert function:
collection.ReplaceOne(ctx,filter,newDoc,options.Replace().SetUpsert(true))

How to call a function with void return using Firedac FDConnection Component in Delphi XE5?

I recently started using the [ExecSQLScalar]1 and [ExecSQL]2 methods of the FDConnection component in Delphi XE5. It's very handy not to need to build a Dataset object, like FDQuery just for simple queries or executions.
However I had a curious problem when executing a function with void return that has internal validations where it can generate exceptions. I'm using a Postgres database.
CREATE FUNCTION can_be_exception()
RETURNS void AS
$$
BEGIN
RAISE EXCEPTION E'fail';
END;
$$
LANGUAGE plpgsql STABLE;
In delphi, I call the ExecSQLScalar function ...
FDConnection1.ExecSQLScalar('select 1');
FDConnection1.ExecSQLScalar('select can_be_exception()');
On first run, I get the following error:
Project TFDConnectionDEMO.exe raised exception class
EPgNativeException with message '[FireDAC][Phys][PG][libpq] ERROR:
fail'.
On the second run, I get a Violation Access error:
Project TFDConnectionDEMO.exe raised exception class $C0000005 with
message 'access violation at 0x00000000: read of address 0x00000000'.
Apparently the error occurs in the line below in unit FireDAC.Comp.Client
function TFDCustomConnection.ExecSQLScalar(const ASQL: String;
const AParams: array of Variant; const ATypes: array of TFieldType): Variant;
var
oCmd: IFDPhysCommand;
begin
oCmd := BaseCreateSQL;
try
if BasePrepareSQL(oCmd, ASQL, AParams, ATypes) or (FExecSQLTab = nil) then begin
FDFree(FExecSQLTab);
...
ignoring the previous error and trying again, another error is displayed...
Project TZConnectionDEMO.exe raised exception class EFDException with
message '[FireDAC][DatS]-24. Row is not nested'.
Searching, I found no response to this error. I figured my mistake would be to call the bank raise_exception function using the ExecSQLScalar function of the FDConnection component. So I tried using FDConnection.ExecSQL and as I imagined, you can not use this if there is a SELECT clause in the parameter.
Is there a better way to call function with void return using FDConnection.ExecSQL? would a BUG be in the component? or would not it be correct to make that kind of call?
Using ExecSQLScalar is fine in this case. This is certainly a bug (which was already fixed, at least in Delphi 10.2.3). As you've correctly pointed out, the problem is in releasing a table storage object instance held by the FExecSQLTab field by using FDFree procedure.
I don't have Delphi XE5 source code but maybe you can see something like this inside (comments about what happened are added by me):
if BasePrepareSQL(oCmd, ASQL, AParams, ATypes) or (FExecSQLTab = nil) then
begin
FDFree(FExecSQLTab); { ← directly calls destructor if object is not nil }
FExecSQLTab := oCmd.Define; { ← no assignment if command execution raises exception }
end;
Problem was that when a SQL command execution raised exception during storage table definition stage (oCmd.Define), reference to previously destroyed storage table object instance (by FDFree) remained stored in the FExecSQLTab field (as a dangling pointer).
Then when a different command was executed that way, FDFree procedure was called just for that dangling pointer. Hence the access violation.
Way to correct this is replacing line e.g. by:
FDFree(FExecSQLTab);
by:
FDFreeAndNil(FExecSQLTab);
which was done in some later Delphi release.

Error about sending an image into bytea column in postgresql db with libpq library

I'm coding in C and using Libpq library of Postgresql and I would like to store a PNG image into the database in "bytea" type. I have been searching on the net for hours and couldn't find a good example to handle this work, so wanted to write here and ask for your help.
I have 12 params to bind and one of them is PNG image. The rest are char*, and no problem with them.
Below is what I have tried so far. (I'm writing the necessary part of code):
PGresult *res;
PGconn *conn;
const char *paramValues[12];
int paramLengths[12];
int paramFormats[12];
const char* imageFrame=frameImageArray.data();// frameImageArray.data is const char*.
int imageSize=frameImageArray.size();
paramFormats[11]=1;
paramLengths[11]=imageSize;
paramValues[11]= imageFrame;
// insertplate is a function on db
res = PQexecParams(conn,
"SELECT insertplate($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12)",
12, // param number
NULL, // oid param type
paramValues, // param values
paramLengths, // param lengths
paramFormats, // params format, 1 for binary
1); //1 for binary result
It is compiled with no problem but when it comes to store the image to db on runtime, the classical runtime error occures :
"Unhandled exception at 0x6d3dc220 in ..._debug.exe: 0xC0000005: Access violation reading location 0x000000007f91e508."
Seems something about memory handling.
Whatever I tried, I couldn't make it run and I'm not able to see my error. Do I have to use Oids for sending binary data to db with PQexecParams? Or something else I'm missing ? I really appreciate if someone help me with this.
Thanks in advance.
Edit: I just realised that if I use Insert statement, it works well, but this function doesn't. Normally it works. Weird.
I finally find the error.
//paramFormats[0]=0;
//paramFormats[1]=0;
//paramFormats[2]=0;
//paramFormats[3]=0;
//paramFormats[4]=0;
//paramFormats[5]=0;
//paramFormats[6]=0;
//paramFormats[7]=0;
//paramFormats[8]=0;
//paramFormats[9]=0;
//paramFormats[10]=0;
//paramFormats[11]=1;
It is possible to leave the "parameter format" as NULL, but I wanted to set only "paramFormats[11]" as seen above. I have set the others to 0 as well and it worked. I didn't expect something like this.

Go's runtime library document out of date?

So, I'm working on parsing a POST using GO. What I want is the body of the post, so I try the following (r is of type *http.Request in this context):
var body io.Reader
var d []byte
body = r.Body.Reader
body.Read( d)
However, this results in a compilation error:
Compile error: <file>:44:
r.Body.Reader undefined (type io.ReadCloser has no field or method Reader)
Odd. I could have sworn that it was defined in the docs... Ah! here it is.
Now, I'm fairly new to Go, but this smells a little odd -- what have I screwed up?
From your link, the doc for a ReadCloser is:
type ReadCloser interface {
Reader
Closer
}
What this is telling you, is that a ReadCloser interface is composed of a Reader and a Closer functionality. It IS both. That means the ReadCloser takes on those interface definitions. They are not actually members, the way you are accessing them.
A Reader is:
type Reader interface {
Read(p []byte) (n int, err error)
}
So that means you should be accessing Read like this:
body = r.Body
body.Read(d)
The way interfaces are defined in Go documents, it looked like it was a "has-a" relationship. It's actually an "is-a" relationship, so the following code does what I want:
var d []byte
r.Body.Read(d)

Resources