Long fields are record fields that may contain a variable number of bytes and can store very large numbers of bytes. The data may be small enough to fit into a single buffer, however it may be too long to store in memory such as long documents or large images.
There are two types of long fields; text and binary fields. Binary fields can contain any kind of data like images, audio files, etc. Because binary fields can contain illegal Prolog characters the data must be transported to and from the DBMS as base64 encoded data. If a long binary field is read the data will be base64 encoded.
How Trinc-Prolog reads long fields can be set with the method putLongFieldReadMode/1. The parameter of this method can be one of the following three constants:
read_complete: the complete long field is read. This is the default option.
read_limited: only a limited number of bytes is read. If the size of the long field is smaller than the number of bytes to read then the complete field is read, else only a part of the field is read. The maximum allowed number of bytes to read can be determined with the method longFieldReadLimit/1.
read_ignore: all long fields are ignored. The long fields are never present in the result set of a SQL command.
The method putLongFieldReadLimit/1 sets the number of bytes that is read if only parts of long fields are read.
Long fields can be written by using SQL commands with parameters. Instead of creating a SQL command with the value(s) of the long field(s) to insert or update a question mark must be used. In the following example a new employee is inserted into the table 'employees', the value for the long text field 'Notes' is not specified.
| insert into employees(Lastname, FirstName, Notes) values (Dubby, Harry, ?) |
To determine if a parameter is connected to a long field the method isParameterLongField/2 can be used. It is necessary to check if a parameter is connected to a long field, before the value is written, because the DBMS must be told the number of bytes that will be written to the long field. The number of bytes to write for a long field can be set with the method putParameterLongFieldSize/2. For binary fields not the size of the base64 encoded data must be specified but the number of bytes before it is encoded (atom_base64/2).
The example below iterates through all the parameters of a prepared SQL command and checks each parameter if it is connected to a long field and if so asks for the number of bytes to write.
| %Iterate from 0 to (Num-1) parameters browseFrame::askParameterValues( Num, Num ). browseFrame::askParameterValues( Pos, Num ) :- %Check if it is a long field, if so then do NOT ask for a value but for the number %of bytes to write _Query<-isParameterLongField(Pos, YesNo), ((YesNo = true) -> (askParameterLength(Pos), !) ; (askParameter(Pos), !) ), !, Pos2 is Pos+1, askParameterValues(Pos2, Num). |
The number of bytes to write is set in the same example with the statement:
| _Query<-putParameterLongFieldSize(Pos, NumBytes) |
When the DBMS needs the data to write then it asks for that by using a callback, this is the onMoreData/4 callback.
Setting the onMoreData/4 callback:
| %Create a query instance and initialise it _Query new_obj query, _Query<-putDatabase(_DB, true), this(T), add_callback(_Query, onMoreData, T, doOnMoreData) |
The onMoreData/4 callback has four parameters: the first is the query instance that wants data, the second is the zero-based parameter index, the third is the type of the field (text or binary) and the last parameter is an empty variable. The value assigned to that last variable will be written to the DBMS if a solution was found for the Prolog goal executing the callback. For binary fields the data must be base64 encoded (atom_base64/2).
The example below responds to the onMoreData/4 event by displaying a modal dialog and asking the user for the data to write. If the field is a binary field then the data is first base64 encoded with the predicate atom_base64/2.
| browseFrame::doOnMoreData( onMoreData(Sender, ParIndex, Type, Value) ) :- Dlg new_obj questionFrame, this(T), (Type == text -> (Str is_string 'Value for long text field (par ' & to_string(ParIndex, true) & '):' ) ; (Str is_string 'Value for long binary field (par ' & to_string(ParIndex, true) & '):') ), Dlg<-createAndInit(T, Str, Result), Dlg<-showModal(_), Dlg<-modalResult(Res), (Res == 0 -> (del_obj Dlg, !, fail) ; (Dlg<-answer(Val), %Get value that the user has entered !, ((Type == text) -> (Value = Val) ; %If binary field then use base64 encoding (atom_base64(Val, Value)) ), del_obj Dlg) ). |