Subject | Re: [firebird-support] Re: Execution plan |
---|---|
Author | Ann W. Harrison |
Post date | 2006-01-02T21:10:55Z |
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
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