Important: The information in this document is obsolete and should not be used for new development.
Processing Query Results
You can use the low-level functionDBGetItem
to retrieve a single data item returned by a query, or you can use the high-level functionDBGetQueryResults
to retrieve all of the query results at once. If you use theDBGetQueryResults
function, you can then use theDBResultsToText
function to convert the results to ASCII text. TheDBResultsToText
function calls routines called result handlers, which are installed in memory by applications or by system extensions (files containing'INIT'
resources). This section discusses the use of theDBGetItem
andDBGetQueryResults
functions and describes how to write and install a result handler.Getting Query Results
TheDBGetItem
function retrieves a single data item that was returned by a data source in response to a query. When you call theDBGetItem
function, you specify the data type to be retrieved. If you do not know what data type to expect, you can specify thetypeAnyType
constant for thedataType
parameter, and the data server returns the next data item regardless of data type. It also returns information about the data item, including data type and length.If you do not know the length of the next data item, you can specify
NIL
for thebuffer
parameter in theDBGetItem
function, and the data server returns the data type, length, and number of decimal places without retrieving the data item. The next time you call theDBGetItem
function with a nonzero value for the buffer parameter, the function retrieves the data item.If you want to skip a data item, specify the
typeDiscard
constant for thedataType
parameter. Then the next time you call theDBGetItem
function, it retrieves the following data item.You should use the
DBGetItem
function if you want complete control over the retrieval of each item of data. If you want the Data Access Manager to retrieve the data for you, use theDBGetQueryResults
function instead.Table 12-1 shows the data types recognized by the Data Access Manager. You use a constant to specify each data type, as follows:
CONST {data types} typeAnyType = 0; {can be any data type} typeNone = 'none'; {no more data expected} typeBoolean = 'bool'; {Boolean} typeSMInt = 'shor'; {short integer} typeInteger = 'long'; {integer} typeSMFloat = 'sing'; {short floating point} typeFloat = 'doub'; {floating point} typeDate = 'date'; {date} typeTime = 'time'; {time} typeTimeStamp = 'tims'; {date and time} typeChar = 'TEXT'; {character} typeDecimal = 'deci'; {decimal number} typeMoney = 'mone'; {money value} typeVChar = 'vcha'; {variable character} typeVBin = 'vbin'; {variable binary} typeLChar = 'lcha'; {long character} typeLBin = 'lbin'; {long binary} typeDiscard = 'disc'; {discard next data item} typeUnknown = 'unkn'; {result handler for unknown } { data type} typeColBreak = 'colb'; {result handler for column break} typeRowBreak = 'rowb'; {result handler for end of line}The writer of a database extension can define other data types to support specific data sources or data servers.Each data type has a standard definition, shown in Table 12-1. For example, if the
DBGetItem
function returns thetypeInteger
constant for thedataType
parameter, you know that the data item represents an integer value and that a 4-byte buffer is necessary to hold it. Similarly, if you are using theDBSendItem
function to send to the data server a data item that you identify astypeFloat
, the data server expects to receive an 8-byte floating-point value.Notice that some of these data types are defined to have a specific length (referred to as an implied length), and some do not. The
len
parameter of theDBSendItem
andDBGetItem
functions indicates the length of an individual data item. TheDBGetQueryResults
function returns a handle to an array of lengths, decimal places, and flags in thecolInfo
field of the results record. ThetypeAnyType
,typeColBreak
, andtypeRowBreak
constants do not refer to specific data types, and therefore the length specification is not applicable for these constants.
The
DBGetQueryResults
function retrieves all of the data that was returned by a data source in response to a query, unless insufficient memory is available to hold the data, in which case it retrieves as many complete rows of data as possible. TheDBGetQueryResults
function stores the data in a structure called a results record. You must allocate the results record data structure and pass this record to theDBGetQueryResults
function. The Data Access Manager allocates the handles inside the results record. When your application is finished using the results record, you must deallocate both the results record and the handles inside the results record.The results record is defined by the
ResultsRecord
data type.
TYPE ResultsRecord = RECORD numRows: Integer; {number of rows retrieved} numCols: Integer; {number of columns per row} colTypes: ColTypesHandle; {type of data in each column} colData: Handle; {array of data items} colInfo: ColInfoHandle; {info about each data item} END;ThenumRows
field in the results record indicates the total number of rows retrieved. If theDBGetQueryResults
function returns a result code other thanrcDBValue
, then not all of the data actually returned by the data source was retrieved. This could happen, for instance, if the user's computer does not have sufficient memory space to hold all the data. In this case, your application can make more space available (by writing the data in the data record to disk, for example) and then call theDBGetQueryResults
function again to complete retrieval of the data.
The
- Note
- The
DBGetQueryResults
function retrieves whole rows only; if it runs out of space in the middle of a row, it stores the partial row in a private buffer so that the data in the results record ends with the last complete row. Because the last partial row is no longer available from the data server, you cannot start to retrieve data with theDBGetQueryResults
function and then switch to theDBGetItem
function to complete the data retrieval.numCols
field indicates the number of columns in each row of data.The
colTypes
field is a handle to an array of data types, specifying the type of data in each column. The number of elements in the array is equal to the value in thenumCols
field. Table 12-1 beginning on page 12-39 shows the standard data types.The
colData
field is a handle to the data retrieved by theDBGetQueryResults
function.The
colInfo
field is a handle to an array of records of typeDBColInfoRecord
, each of which specifies the length, places, and flags for a data item. There are as many records in the array as there are data items retrieved by theDBGetQueryResults
function. Here is theDBColInfoRecord
type definition:
TYPE DBColInfoRecord = RECORD len: Integer; {length of data item} places: Integer; {places for decimal and } { money data items} flags: Integer; {flags for data item} END;Thelen
field indicates the length of the data item. TheDBGetQueryResults
function returns a value in this field only for those data types that do not have implied lengths; see Table 12-1 beginning on page 12-39.The
places
field indicates the number of decimal places in data items of typestypeMoney
andtypeDecimal
. For all other data types, theplaces
field returns 0.The least significant bit of the
flags
field is set to 1 if the data item is in the last column of the row. The third bit of theflags
field is 1 if the data item isNULL
. You can use the constantskDBLastColFlag
andkDBNullFlag
to test for these flag bits.Converting Query Results to Text
TheDBResultsToText
function provided by the high-level interface converts the data retrieved by theDBGetQueryResults
function into strings of ASCII text. This function makes it easier for you to display retrieved data for the user.For the
DBResultsToText
function to convert data of a specific type to text, either the application or the system software must have a routine called a result handler. With System 7, Apple Computer, Inc., provides system result handlers for the data types listed here. (These data types are described in Table 12-1 beginning on page 12-39.)
Data type Constant Data type Constant Boolean typeBoolean Time typeTime Short integer typeSMInt Date and time typeTimeStamp Integer typeInteger Character typeChar Short floating point typeSMFloat Decimal number typeDecimal Floating point typeFloat Money value typeMoney Date typeDate Variable character typeVChar
In addition to the result handlers for these standard data types, Apple provides the following three system result handlers, which correspond to no specific data type:
- Note
- Apple's system result handler for the variable character (
typeVChar
) data type strips trailing spaces from the character string.
Data type Constant Unknown typeUnknown Column break typeColBreak End of line typeRowBreak The
typeUnknown
result handler processes any data type for which no other result handler is available. TheDBResultsToText
function calls thetypeColBreak
result handler after each item that is not the last item in a row. This result handler does not correspond to any data type, but adds a delimiter character to separate columns of text. The defaulttypeColBreak
result handler inserts a tab character. Similarly, theDBResultsToText
function calls thetypeRowBreak
result handler at the end of each row of data to add a character that separates the rows of text. The defaulttypeRowBreak
result handler inserts a return character. Your application can install your owntypeColBreak
andtypeRowBreak
result handlers to insert whatever characters you wish--or to insert no character at all, if you prefer.You can install result handlers for any data types you know about. When you call the
DBInstallResultHandler
function, you can specify whether the result handler you are installing is a system result handler. A system result handler is available to all applications that use the system. All other result handlers (called application result handlers) are associated with a particular application. TheDBResultsToText
function always uses a result handler for the current application in preference to a system result handler for the same data type. When you install a system result handler for the same data type as an already installed system result handler, the new result handler replaces the old one. Similarly, when you install an application result handler for the same data type as a result handler already installed for the same application, the new result handler replaces the old one for that application.Result handlers are stored in memory. The Data Access Manager installs its system result handlers the first time the Macintosh Operating System loads the Data Access Manager into memory. You must reinstall your own application result handlers each time your application starts up. You can also install your own system result handlers each time your application starts up, or you can provide a system extension (that is, a file with an
'INIT'
resource) that installs system result handlers each time the user starts up the system.Here is a function declaration for a result handler function:
FUNCTION MyResultHandler (dataType: DBType; theLen, thePlaces, theFlags: Integer; theData: Ptr; theText: Handle): OSErr;ThedataType
parameter specifies the data type of the data item that theDBResultsToText
function is passing to the result handler. Table 12-1 beginning on page 12-39 describes the standard data types.The parameters
theLen
andthePlaces
specify the length and number of decimal places of the data item that theDBResultsToText
function wants the result handler to convert to text.The parameter
theFlags
is the value returned for theflags
parameter by theDBGetItem
function. If the least significant bit of this parameter is set to 1, the data item is in the last column of the row. If the third bit of this parameter is set to 1, the data item isNULL
. You can use the constantskDBLastColFlag
andkDBNullFlag
to test for these flag bits.The parameter
theData
is a pointer to the data that the result handler is to convert to text.The parameter
theText
is a handle to the buffer that is to hold the text version of the data. The result handler should use the Memory Manager'sSetHandleSize
function to increase the size of the buffer as necessary to hold the new text, and append the new text to the end of the text already in the buffer. TheSetHandleSize
function is described in the chapter "Memory Manager" in Inside Macintosh: Memory.If the result handler successfully converts the data to text, it should return a result code of 0 (
noErr
).You can use the
DBInstallResultHandler
function to install a result handler and theDBRemoveResultHandler
function to remove an application result handler. You can install and replace system result handlers, but you cannot remove them.The following line of code installs an application result handler. The first parameter (
typeInteger
) specifies the data type that this result handler processes. The second parameter (MyTypeIntegerHandler
) is a pointer to the result handler routine. The last parameter (FALSE
) is a Boolean value specifying that this routine is not a system result handler.
err := DBInstallResultHandler (typeInteger,@MyTypeIntegerHandler,FALSE);Listing 12-6 shows a result handler that converts the integer data type to text.
FUNCTION MyTypeIntegerHandler(datatype: DBType; theLen: Integer; theData: Ptr; theText: Handle): OSErr; VAR theInt: LongInt; theTextLen: LongInt; temp: Str255; atemp1: Ptr; atemp2: LongInt; atemp3: LongInt; BEGIN BlockMove(theData, @theInt, sizeof(theInt)); NumToString(theInt, temp); {convert to text} theTextLen := GetHandleSize(theText); {get current size } { of theText} {size text handle} SetHandleSize(theText, theTextLen + LongInt(LENGTH(temp))); IF (MemError <> noErr) THEN MyTypeIntegerHandler := MemError ELSE BEGIN atemp1 := Ptr(ORD(@temp)); atemp2 := LongInt(theText^) + theTextLen; atemp3 := LongInt(LENGTH(temp)); {use BlockMove to append text} BlockMove(P2CStr(atemp1), Ptr(atemp2), atemp3); MyTypeIntegerHandler := MemError; END; END;