Subject Re: [firebird-support] Re: Execution plan
Author Ann W. Harrison
frederic.hoornaert wrote:

Look at the isc_dsql_sql_info call, specifically the
isc_info_sql_get_plan option.

The call definition is

ISC_STATUS API_ROUTINE isc_dsql_sql_info(
ISC_STATUS* userStatus,
DsqlHandle *dsqlHandle,
SSHORT itemsLength,
char* items,
SSHORT bufferLength,
char* buffer)

ISC_STATUS is defined in ibase.h - it's a 32-bit integer -
as the return value of the call it is set to zero if
the call succeeds, of a status code indicating the nature
of the failure.

API_ROUTINE is a macro that translates to nothing on most
platforms but allows us to mark exported entry points
where that is necessary when building shared libraries.

ISC_STATUS* is a pointer to an array of 20 ISC_STATUS's

DsqlHandle* is the statement handle returned from an
isc_dsql_prepare call.

itemsLength is the number of info items to be handled by
this call -

items is an array of bytes that list the information requested

bufferLength is the length of the output buffer

buffer is the allocated buffer.


Here's the code from isql.cpp:


static SCHAR plan_info[] = { isc_info_sql_get_plan };

...

if (Plan)
{
/* Bug 7565: A plan larger than plan_buffer will not be displayed */
/* Bug 7565: Note also that the plan must fit into Print_Buffer */

plan_buffer = (SCHAR *) ISQL_ALLOC(PRINT_BUFFER_LENGTH);
memset(plan_buffer, 0, PRINT_BUFFER_LENGTH);

if (isc_dsql_sql_info (isc_status, &Stmt,
sizeof(plan_info), plan_info,
PRINT_BUFFER_LENGTH, plan_buffer))
{
ISQL_errmsg(isc_status);
}
else if (plan_buffer[0] == isc_info_sql_get_plan)
{
l = gds__vax_integer((UCHAR*) plan_buffer + 1, 2);
sprintf(Print_buffer, "%.*s%s", l, plan_buffer + 3, NEWLINE);
ISQL_printf(Diag, Print_buffer);
}

ISQL_FREE(plan_buffer);
}


On successful return, the buffer contains a series of clumplets, one for
each info item requested. This particular call asks for only one info
item - a more generic implementation would replace the

else if (plan_buffer[0] == isc_info_sql_get_plan)

with code that could handle a variety of info requests - or combinations
of them

else while (plan_buffer[0] <> isc_info_end)

switch (plan_buffer[0])
{
case (isc_info_sql_get_plan):
....
case (isc_info_sql_num_variables):
....
}

In any event, each clumplet consists of a 16-bit length, which is
big_endian - the gds__vax_integer routine swaps it to the local
endian state - plus that many bytes of infor. This particular item
returns a string.


Hope this helps.


Ann