Page 1 of 1

Postgres BYTEA and RETURNING problem

Posted: Mon Jun 10, 2013 4:05 pm
by infratec
Hi,

INSERT a file in a BYTEA field: no problem.
Use an INSERT with RETURNING in DatabaseQuery(): no problem.

If I use an INSERT with a BYTEA field (SetDatabaseBlob() in front) and RETURNING, I get a DatabaseError():
'There is no parameter $1'

Is this a limitation of Postgres or is it a bug in PB handling of DatabaseQuery() :?:

Code: Select all

#WithReturning = #True
#WithBYTEA = #True

EnableExplicit

UsePostgreSQLDatabase()


Procedure StoreDataFromFile(DB.i, Table$, Filename$)
 
  Protected Result.i, File.i, Size.i, *Buffer, SQL$
 
 
  File = ReadFile(#PB_Any, Filename$)
  If File
    Size = Lof(File)
    Debug "FileSize: " + Str(Size)
    *Buffer = AllocateMemory(Size)
    If *Buffer
      If ReadData(File, *Buffer, Size) = Size        
        
        SetDatabaseBlob(DB, 0, *Buffer, Size)
CompilerIf #WithReturning = #False
        SQL$ = "INSERT INTO " + Table$ + " (filename, filesize, filedata) VALUES (E'" + ReplaceString(Filename$, "\", "\\") + "'," + Str(Size) + ", $1)"
        Debug "(Update) " + SQL$
        If DatabaseUpdate(DB, SQL$)
CompilerElse
  CompilerIf #WithBYTEA = #False
        SQL$ = "INSERT INTO " + Table$ + " (filename, filesize) VALUES (E'" + ReplaceString(Filename$, "\", "\\") + "'," + Str(Size) + ") RETURNING id"
  CompilerElse
        SQL$ = "INSERT INTO " + Table$ + " (filename, filesize, filedata) VALUES (E'" + ReplaceString(Filename$, "\", "\\") + "'," + Str(Size) + ", $1) RETURNING id"
  CompilerEndIf
        Debug "(Query) " + SQL$
        If DatabaseQuery(DB, SQL$)
          If NextDatabaseRow(DB)
            Debug "Returnvalue: " + Str(GetDatabaseLong(DB, 0))
          EndIf
          FinishDatabaseQuery(DB)
CompilerEndIf
          Result = #True
        Else
          Debug DatabaseError()
        EndIf
      EndIf
      FreeMemory(*Buffer)
    EndIf
    CloseFile(File)
  EndIf
 
  ProcedureReturn Result
 
EndProcedure




Procedure RestoreDataToFile(DB.i, Table$, Filename$="")
 
  Protected Result.i, File.i, Size.q, *Buffer
 
 
  If DatabaseQuery(DB, "SELECT filename, filesize, filedata FROM " + Table$)
    If NextDatabaseRow(DB)
      If Filename$ = ""
        Filename$ = GetDatabaseString(DB, 0)
      EndIf
     
      Size = GetDatabaseLong(DB, 1) ;/ Get size of the blob
      *Buffer = AllocateMemory(Size)
      If *Buffer
       
        Debug "Columnsize: " + Str(DatabaseColumnSize(DB, 2))
       
        GetDatabaseBlob(DB, 2, *Buffer, Size)
        File = CreateFile(#PB_Any, Filename$)
        If File
          If WriteData(File, *Buffer, Size) = Size
            Result = #True
          EndIf
          CloseFile(File)
        EndIf
        FreeMemory(*Buffer)
      EndIf
    EndIf
    FinishDatabaseQuery(DB)
  EndIf
 
  ProcedureReturn Result
 
EndProcedure



Define DB.i, Table$, Filename$

DB = OpenDatabase(#PB_Any, "host=xxx.xxx.xxx.xxx port=5432", "yyy", "zzz")
If DB
 
  Table$ = "datatest"
 
  If DatabaseUpdate(DB, "CREATE TEMP TABLE " + Table$ + " (id SERIAL, filename TEXT, filesize INTEGER, filedata BYTEA)")
   
    Filename$ = OpenFileRequester("Choose a file", "", "*.*", 0)
    If Filename$
     
      If StoreDataFromFile(DB, Table$, Filename$)
        RestoreDataToFile(DB, Table$, Filename$ + "." + GetExtensionPart(Filename$))
      EndIf
     
    EndIf
   
  EndIf
  CloseDatabase(DB)
Else
  MessageRequester("Error", "Was not able to connect.")
EndIf
You can change the 2 flags at he beginning to see what happens.
Oh, you need top adjust the OpenDatabase() line.

Bernd

Re: Postgres BYTEA and RETURNING problem

Posted: Mon Jun 10, 2013 7:39 pm
by Fred
What is the version of your Postgresql server ? The PB lib used was old and doesn't support HEX encoding for BYTEA (which is now default on 9.x servers). I have upgraded the client lib for the next version to 9.2.4.

Re: Postgres BYTEA and RETURNING problem

Posted: Mon Jun 10, 2013 9:49 pm
by infratec
Hi Fred,

we still use a debian 6.0.7 with Postgresql 8.4.17.
So it should not be a problem of the lib.

Bernd

Re: Postgres BYTEA and RETURNING problem

Posted: Tue Jun 11, 2013 3:19 am
by RichAlgeni
Have you tried doing the same Insert using the PSQL shell? Make sure it works there first. If it does, it is a PureBasic issue.

I always make sure it works correctly in PSQL first, then code it into my program.

Re: Postgres BYTEA and RETURNING problem

Posted: Tue Jun 11, 2013 9:55 am
by infratec
@RichAlgeni
A test with psql is not possible in this case.
All ways (that I found) to insert a binary file in a table field are totally different to that what PB does.

@Fred
I just checked it with Wireshark:
If DatabaseUpdate() is used there is an additional Parameter field in the packet.
If DatabaseQuery() is used this field is missing and also the binary data is not transmitted,
only the plain INSERT command is in the packet.

As workaround I have to use now an additional SELECT to get the id of the last inserted record.

Bernd

Re: Postgres BYTEA and RETURNING problem

Posted: Sat Nov 02, 2013 2:08 pm
by sput
same problem....

Can anyone give me a working code ? ... to save and load pictures

Postegre 9.3

Re: Postgres BYTEA and RETURNING problem

Posted: Wed Mar 25, 2015 12:25 am
by Jagermeister
Based off these attempts, I had an idea to convert say a JPEG to quads (like bin2data output) and INSERT as text. Being that the characters would be 0-9, A-F, I needn't worry about escape characters. How would I decode that from a query returned as string?

UPDATE: Nevermind. http://www.purebasic.fr/english/viewtop ... ecode+jpeg