[Qt-interest] postgres bytea
Diego Schulz
dschulz at gmail.com
Mon May 4 15:15:01 CEST 2009
On Mon, May 4, 2009 at 3:00 AM, Andrew Maclean <a.maclean at cas.edu.au> wrote:
> Has anyone a simple example of how to insert/get data from a bytea field in
> a postgres database. I am using QT4.5 and the documentation talks about
> automatic conversions but I seem to be unable to do this.
>
> I build and installed the postgresql plugin Ok and it returns true for bytea
> and also Unicode.
>
>
>
>
>
> Thanks for any help
>
>
>
>
>
> Andrew
>
>
Hi Andrew,
I've done a small proof of concept a few days ago. Beware that the
code might not be strictly correct, but may give you some ideas. This
is the function:
void
MainWindow::postBlob ()
{
if (connectDatabase ())
{
qDebug ("Connected!");
QSqlDatabase db = QSqlDatabase::database (tr ("default"));
{
QFile file (editInputFile->text ());
if (!file.open (QIODevice::ReadOnly))
{
return;
}
QSqlQuery query = QSqlQuery (db);
QByteArray ba = file.readAll ();
qlonglong len = ba.length ();
QByteArray sha1 =
QCryptographicHash::hash (ba, QCryptographicHash::Sha1);
QVariant sha1blob (sha1.toHex ());
QVariant blob (ba.toBase64 ());
// Using named parameters
/*
query.prepare("INSERT INTO archivo (nombre, rutaorig, descripcion,
tam , hash , blob) "
"VALUES ( :nombre, :rutaorig , :descripcion, :tam , :hash,
E\'\\\\:blob'\' ) ");
query.bindValue(":nombre", QFileInfo(file).fileName());
query.bindValue(":rutaorig", QFileInfo(file).absolutePath() +
QDir::separator());
query.bindValue(":descripcion", editDescription->text() );
query.bindValue(":tam", len);
query.bindValue(":hash", sha1blob.toString());
query.bindValue(":blob", blob );
*/
// Using positional parameters
query.
prepare
("INSERT INTO archivo (nombre, rutaorig, descripcion, tam, hash, blob) "
"VALUES (?,?,?,?,?,?)");
query.addBindValue (QFileInfo (file).fileName ());
query.addBindValue (QFileInfo (file).absolutePath () +
QDir::separator ());
query.addBindValue (editDescription->text ());
query.addBindValue (len);
query.addBindValue (sha1blob.toString ());
query.addBindValue (blob);
query.exec ();
qDebug () << query.lastQuery ();
QSqlError error = query.lastError ();
if (error.type () == QSqlError::NoError)
{
createModel ();
//QMessageBox::information(this,tr("Blob"), tr("Insert ok"),
QMessageBox::Ok);
}
else
{
QMessageBox::critical (this, tr ("Blob"),
tr ("Error inserting:\n\n %1").
arg (error.databaseText ()),
QMessageBox::Ok);
}
}
db = QSqlDatabase::database ();
QSqlDatabase::removeDatabase (tr ("default"));
}
}
------------------------
The file name comes from a QLineEdit component (editInputFile->text ()).
Note that I encoded the blob to base64 (so it is even possible to
store it even in a text field, though i'm not sure if it's desirable
to do this) to avoid warnings from the pg backend.
If you choose to insert blobs encoded in base64, and have the need to
do something with the blobs from the pg backend, you'll need the
decode(text,text)
[http://www.postgresql.org/docs/8.3/interactive/functions-binarystring.html].
For example, to calculate the actual size of a blob you'll do
something like
SELECT blobname, octet_length(decode(blob::text,'base64')) as
blob_size_in_bytes FROM myblobs WHERE id=2 ;
Bear in mind that doing this kind of operations in the postgresql
backend might imply a huge load in some environments. I'd prefer to
decode the blob in the client application.
Just try both methods, inserting the raw blobs, and then encoding in
base64. If you find a way to avoid the warnings from pg server
regarding the use of \E'...' notation, please let me know!
HTH,
diego
ps. excuse my faults writing english, I'm doing the best I can, but
not very fluent _yet_
More information about the Qt-interest-old
mailing list