8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-24 12:03:02 +01:00

Merge B1_5_Remote_LazyPort branch into HEAD

This commit is contained in:
hvlad 2006-05-01 22:23:31 +00:00
parent b196cac010
commit f94b8bd641
14 changed files with 836 additions and 194 deletions

View File

@ -1581,6 +1581,14 @@ ISC_STATUS GDS_DSQL_SQL_INFO_CPP( ISC_STATUS* user_status,
const UCHAR* const end_items = items + item_length; const UCHAR* const end_items = items + item_length;
const UCHAR* const end_info = info + info_length; const UCHAR* const end_info = info + info_length;
UCHAR *start_info;
if (*items == isc_info_length) {
start_info = info;
items++;
}
else {
start_info = 0;
}
// CVC: Is it the idea that this pointer remains with its previous value // CVC: Is it the idea that this pointer remains with its previous value
// in the loop or should it be made NULL in each iteration? // in the loop or should it be made NULL in each iteration?
@ -1760,6 +1768,14 @@ ISC_STATUS GDS_DSQL_SQL_INFO_CPP( ISC_STATUS* user_status,
} }
*info++ = isc_info_end; *info++ = isc_info_end;
if (start_info && (end_info - info >= 7))
{
SLONG number = info - start_info;
memmove(start_info + 7, start_info, number);
USHORT length = convert(number, buffer);
put_item(isc_info_length, length, buffer, start_info, end_info);
}
} }
catch(const std::exception& ex) catch(const std::exception& ex)
{ {
@ -3649,6 +3665,7 @@ static USHORT get_plan_info(
SCHAR* plan; SCHAR* plan;
for (int i = 0; i < 2; i++) { for (int i = 0; i < 2; i++) {
const SCHAR* explain = explain_ptr; const SCHAR* explain = explain_ptr;
if (*explain++ != isc_info_access_path) if (*explain++ != isc_info_access_path)
{ {
// CVC: deallocate memory! // CVC: deallocate memory!

View File

@ -61,6 +61,9 @@ struct sqlda_sup
USHORT dasup_blr_length; USHORT dasup_blr_length;
USHORT dasup_blr_buf_len; USHORT dasup_blr_buf_len;
USHORT dasup_msg_buf_len; USHORT dasup_msg_buf_len;
SCHAR* dasup_info_buf;
USHORT dasup_info_len;
} dasup_clauses[2]; } dasup_clauses[2];
USHORT dasup_dialect; // Dialect associated with statement USHORT dasup_dialect; // Dialect associated with statement

View File

@ -77,6 +77,67 @@ static TEXT *DSQL_failures, *DSQL_failures_ptr;
const int DSQL_FAILURE_SPACE = 2048; const int DSQL_FAILURE_SPACE = 2048;
/**
Parse response on isc_info_sql_select or isc_info_sql_bind
request. Return pointer to the next byte after successfully
parsed info or NULL if error is encountered or info is truncated
**/
SCHAR* UTLD_skip_sql_info(SCHAR* info)
{
if (*info != isc_info_sql_select &&
*info != isc_info_sql_bind)
return 0;
info++;
if (*info++ != isc_info_sql_describe_vars)
return 0;
get_numeric_info((const SCHAR**) &info);
// Loop over the variables being described
while (true)
{
SCHAR str[256]; // must be big enough to hold metadata name
SCHAR item = *info++;
switch (item)
{
case isc_info_end:
return info;
case isc_info_truncated:
return 0;
case isc_info_sql_select:
case isc_info_sql_bind:
return --info;
case isc_info_sql_describe_end:
break;
case isc_info_sql_sqlda_seq:
case isc_info_sql_type:
case isc_info_sql_sub_type:
case isc_info_sql_scale:
case isc_info_sql_length:
get_numeric_info((const SCHAR**) &info);
break;
case isc_info_sql_field:
case isc_info_sql_relation:
case isc_info_sql_owner:
case isc_info_sql_alias:
get_string_info((const SCHAR**) &info, str, sizeof(str));
break;
default:
return 0;
}
}
return 0;
}
/** /**

View File

@ -35,6 +35,7 @@ ISC_STATUS UTLD_parse_sql_info(ISC_STATUS*, USHORT, const SCHAR*, XSQLDA*, USHOR
ISC_STATUS UTLD_parse_sqlda(ISC_STATUS*, sqlda_sup* const, USHORT*, USHORT*, ISC_STATUS UTLD_parse_sqlda(ISC_STATUS*, sqlda_sup* const, USHORT*, USHORT*,
USHORT*, USHORT, XSQLDA*, const USHORT); USHORT*, USHORT, XSQLDA*, const USHORT);
void UTLD_save_status_strings(ISC_STATUS*); void UTLD_save_status_strings(ISC_STATUS*);
SCHAR* UTLD_skip_sql_info(SCHAR*);
#endif // DSQL_UTLD_PROTO_H #endif // DSQL_UTLD_PROTO_H

View File

@ -106,6 +106,15 @@ int INF_blob_info(const blb* blob,
const SCHAR* const end_items = items + item_length; const SCHAR* const end_items = items + item_length;
const SCHAR* const end = info + output_length; const SCHAR* const end = info + output_length;
SCHAR* start_info;
if (*items == isc_info_length) {
start_info = info;
items++;
}
else {
start_info = 0;
}
while (items < end_items && *items != isc_info_end) { while (items < end_items && *items != isc_info_end) {
SCHAR item = *items++; SCHAR item = *items++;
@ -142,6 +151,14 @@ int INF_blob_info(const blb* blob,
*info++ = isc_info_end; *info++ = isc_info_end;
if (start_info && (end - info >= 7))
{
SLONG number = info - start_info;
memmove(start_info + 7, start_info, number);
USHORT length = INF_convert(number, buffer);
INF_put_item(isc_info_length, length, buffer, start_info, end);
}
return TRUE; return TRUE;
} }
@ -838,6 +855,16 @@ int INF_request_info(const jrd_req* request,
const SCHAR* const end_items = items + item_length; const SCHAR* const end_items = items + item_length;
const SCHAR* const end = info + output_length; const SCHAR* const end = info + output_length;
SCHAR* start_info;
if (*items == isc_info_length) {
start_info = info;
items++;
}
else {
start_info = 0;
}
SCHAR buffer[256]; SCHAR buffer[256];
memset(buffer, 0, sizeof(buffer)); memset(buffer, 0, sizeof(buffer));
SCHAR* buffer_ptr = buffer; SCHAR* buffer_ptr = buffer;
@ -962,6 +989,14 @@ int INF_request_info(const jrd_req* request,
*info++ = isc_info_end; *info++ = isc_info_end;
if (start_info && (end - info >= 7))
{
SLONG number = info - start_info;
memmove(start_info + 7, start_info, number);
USHORT length = INF_convert(number, buffer);
INF_put_item(isc_info_length, length, buffer, start_info, end);
}
return TRUE; return TRUE;
} }
@ -986,6 +1021,15 @@ int INF_transaction_info(const jrd_tra* transaction,
const SCHAR* const end_items = items + item_length; const SCHAR* const end_items = items + item_length;
const SCHAR* const end = info + output_length; const SCHAR* const end = info + output_length;
SCHAR* start_info;
if (*items == isc_info_length) {
start_info = info;
items++;
}
else {
start_info = 0;
}
while (items < end_items && *items != isc_info_end) { while (items < end_items && *items != isc_info_end) {
SCHAR item = *items++; SCHAR item = *items++;
@ -1059,6 +1103,14 @@ int INF_transaction_info(const jrd_tra* transaction,
*info++ = isc_info_end; *info++ = isc_info_end;
if (start_info && (end - info >= 7))
{
SLONG number = info - start_info;
memmove(start_info + 7, start_info, number);
USHORT length = INF_convert(number, buffer);
INF_put_item(isc_info_length, length, buffer, start_info, end);
}
return TRUE; return TRUE;
} }

View File

@ -33,7 +33,8 @@
#define isc_info_truncated 2 #define isc_info_truncated 2
#define isc_info_error 3 #define isc_info_error 3
#define isc_info_data_not_ready 4 #define isc_info_data_not_ready 4
#define isc_info_flag_end 127 #define isc_info_length 126
#define isc_info_flag_end 127
/******************************/ /******************************/
/* Database information items */ /* Database information items */

View File

@ -829,9 +829,19 @@ ISC_STATUS SVC_query2(Service* service,
/* Process the receive portion of the query now. */ /* Process the receive portion of the query now. */
const SCHAR* const end = info + buffer_length; const SCHAR* const end = info + buffer_length;
items = recv_items; items = recv_items;
const SCHAR* const end_items2 = items + recv_item_length; const SCHAR* const end_items2 = items + recv_item_length;
SCHAR* start_info;
if (*items == isc_info_length) {
start_info = info;
items++;
}
else {
start_info = 0;
}
while (items < end_items2 && *items != isc_info_end) while (items < end_items2 && *items != isc_info_end)
{ {
/* /*
@ -1209,6 +1219,13 @@ ISC_STATUS SVC_query2(Service* service,
if (info < end) if (info < end)
*info = isc_info_end; *info = isc_info_end;
if (start_info && (end - info >= 7))
{
SLONG number = 1 + (info - start_info);
memmove(start_info + 7, start_info, number);
USHORT length = INF_convert(number, buffer);
INF_put_item(isc_info_length, length, buffer, start_info, end);
}
if (!(service->svc_flags & SVC_thd_running)) if (!(service->svc_flags & SVC_thd_running))
{ {

View File

@ -43,6 +43,7 @@
*/ */
#include "firebird.h" #include "firebird.h"
#include "memory_routines.h" // needed for get_long
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -696,6 +697,39 @@ static const SCHAR describe_bind_info[] =
isc_info_sql_describe_end isc_info_sql_describe_end
}; };
static const SCHAR sql_prepare_info2[] =
{
isc_info_sql_stmt_type,
// describe_select_info
isc_info_sql_select,
isc_info_sql_describe_vars,
isc_info_sql_sqlda_seq,
isc_info_sql_type,
isc_info_sql_sub_type,
isc_info_sql_scale,
isc_info_sql_length,
isc_info_sql_field,
isc_info_sql_relation,
isc_info_sql_owner,
isc_info_sql_alias,
isc_info_sql_describe_end,
// describe_bind_info
isc_info_sql_bind,
isc_info_sql_describe_vars,
isc_info_sql_sqlda_seq,
isc_info_sql_type,
isc_info_sql_sub_type,
isc_info_sql_scale,
isc_info_sql_length,
isc_info_sql_field,
isc_info_sql_relation,
isc_info_sql_owner,
isc_info_sql_alias,
isc_info_sql_describe_end
};
ISC_STATUS API_ROUTINE GDS_ATTACH_DATABASE(ISC_STATUS* user_status, ISC_STATUS API_ROUTINE GDS_ATTACH_DATABASE(ISC_STATUS* user_status,
SSHORT file_length, SSHORT file_length,
@ -830,13 +864,28 @@ ISC_STATUS API_ROUTINE GDS_ATTACH_DATABASE(ISC_STATUS* user_status,
if (database) if (database)
{ {
database->db_path = (TEXT*) alloc((SLONG) (length + 1)); database->db_path = (TEXT*) alloc((SLONG) (length + 1));
if (database->db_path)
{
database->db_prepare_buffer =
(SCHAR*) alloc((SLONG) DBB_PREPARE_BUFFER_SIZE);
}
} }
if (!database || !database->db_path) if (!database || !database->db_path || !database->db_prepare_buffer)
{ {
/* No memory. Make a half-hearted to detach and get out. */ /* No memory. Make a half-hearted to detach and get out. */
if (database) if (database)
release_handle(database); {
if (database->db_path) {
free_block(database->db_path);
database->db_path = 0;
}
if (database->db_prepare_buffer) {
free_block(database->db_prepare_buffer);
database->db_prepare_buffer = 0;
}
release_handle(database);
}
CALL(PROC_DETACH, n) (ptr, handle); CALL(PROC_DETACH, n) (ptr, handle);
status[0] = isc_arg_gds; status[0] = isc_arg_gds;
status[1] = isc_virmemexh; status[1] = isc_virmemexh;
@ -1454,15 +1503,30 @@ ISC_STATUS API_ROUTINE GDS_CREATE_DATABASE(ISC_STATUS* user_status,
if (database) if (database)
{ {
database->db_path = (TEXT *) alloc((SLONG) (length + 1)); database->db_path = (TEXT *) alloc((SLONG) (length + 1));
if (database->db_path)
{
database->db_prepare_buffer =
(SCHAR*) alloc((SLONG) DBB_PREPARE_BUFFER_SIZE);
}
} }
if (!database || !database->db_path) if (!database || !database->db_path || !database->db_prepare_buffer)
{ {
/* No memory. Make a half-hearted to drop database. The /* No memory. Make a half-hearted to drop database. The
database was successfully created but the user wouldn't database was successfully created but the user wouldn't
be able to tell. */ be able to tell. */
if (database) if (database)
release_handle(database); {
if (database->db_path) {
free_block(database->db_path);
database->db_path = 0;
}
if (database->db_prepare_buffer) {
free_block(database->db_prepare_buffer);
database->db_prepare_buffer = 0;
}
release_handle(database);
}
CALL(PROC_DROP_DATABASE, n) (ptr, handle); CALL(PROC_DROP_DATABASE, n) (ptr, handle);
status[0] = isc_arg_gds; status[0] = isc_arg_gds;
status[1] = isc_virmemexh; status[1] = isc_virmemexh;
@ -1472,6 +1536,7 @@ ISC_STATUS API_ROUTINE GDS_CREATE_DATABASE(ISC_STATUS* user_status,
fb_assert(database); fb_assert(database);
fb_assert(database->db_path); fb_assert(database->db_path);
fb_assert(database->db_prepare_buffer);
*public_handle = database->public_handle; *public_handle = database->public_handle;
TEXT* p = database->db_path; TEXT* p = database->db_path;
@ -1716,8 +1781,14 @@ ISC_STATUS API_ROUTINE GDS_DETACH(ISC_STATUS * user_status,
/* Release associated request handles */ /* Release associated request handles */
if (dbb->db_path) if (dbb->db_path) {
free_block(dbb->db_path); free_block(dbb->db_path);
dbb->db_path = 0;
}
if (dbb->db_prepare_buffer) {
free_block(dbb->db_prepare_buffer);
dbb->db_prepare_buffer = 0;
}
while (request = dbb->requests) { while (request = dbb->requests) {
dbb->requests = request->next; dbb->requests = request->next;
@ -1846,8 +1917,14 @@ ISC_STATUS API_ROUTINE GDS_DROP_DATABASE(ISC_STATUS * user_status,
/* Release associated request handles */ /* Release associated request handles */
if (dbb->db_path) if (dbb->db_path) {
free_block(dbb->db_path); free_block(dbb->db_path);
dbb->db_path = 0;
}
if (dbb->db_prepare_buffer) {
free_block(dbb->db_prepare_buffer);
dbb->db_prepare_buffer = 0;
}
while (request = dbb->requests) { while (request = dbb->requests) {
dbb->requests = request->next; dbb->requests = request->next;
@ -2050,37 +2127,56 @@ ISC_STATUS API_ROUTINE isc_dsql_describe(ISC_STATUS * user_status,
ISC_STATUS_ARRAY local; ISC_STATUS_ARRAY local;
USHORT buffer_len; USHORT buffer_len;
SCHAR *buffer, local_buffer[512]; SCHAR *buffer, local_buffer[512];
WHY_STMT statement;
GET_STATUS; GET_STATUS;
TRANSLATE_HANDLE(*stmt_handle, statement, HANDLE_statement, isc_bad_stmt_handle);
if (!(buffer = get_sqlda_buffer(local_buffer, sizeof(local_buffer), sqlda, sqlda_sup::dasup_clause &clause =
dialect, &buffer_len))) statement->das->dasup_clauses[DASUP_CLAUSE_select];
{
status[0] = isc_arg_gds;
status[1] = isc_virmemexh;
status[2] = isc_arg_end;
return error2(status, local);
}
if (!GDS_DSQL_SQL_INFO( status, if (clause.dasup_info_len && clause.dasup_info_buf)
stmt_handle,
sizeof(describe_select_info),
describe_select_info,
buffer_len,
buffer))
{ {
iterative_sql_info( status, iterative_sql_info( status,
stmt_handle, stmt_handle,
sizeof(describe_select_info), sizeof(describe_select_info),
describe_select_info, describe_select_info,
buffer_len, clause.dasup_info_len,
buffer, clause.dasup_info_buf,
dialect, dialect,
sqlda); sqlda);
} }
else
{
if (!(buffer = get_sqlda_buffer(local_buffer, sizeof(local_buffer), sqlda,
dialect, &buffer_len)))
{
status[0] = isc_arg_gds;
status[1] = isc_virmemexh;
status[2] = isc_arg_end;
return error2(status, local);
}
if (buffer != local_buffer) { if (!GDS_DSQL_SQL_INFO( status,
free_block(buffer); stmt_handle,
sizeof(describe_select_info),
describe_select_info,
buffer_len,
buffer))
{
iterative_sql_info( status,
stmt_handle,
sizeof(describe_select_info),
describe_select_info,
buffer_len,
buffer,
dialect,
sqlda);
}
if (buffer != local_buffer) {
free_block(buffer);
}
} }
if (status[1]) { if (status[1]) {
@ -2111,37 +2207,56 @@ ISC_STATUS API_ROUTINE isc_dsql_describe_bind(ISC_STATUS * user_status,
ISC_STATUS_ARRAY local; ISC_STATUS_ARRAY local;
USHORT buffer_len; USHORT buffer_len;
SCHAR *buffer, local_buffer[512]; SCHAR *buffer, local_buffer[512];
WHY_STMT statement;
GET_STATUS; GET_STATUS;
TRANSLATE_HANDLE(*stmt_handle, statement, HANDLE_statement, isc_bad_stmt_handle);
if (!(buffer = get_sqlda_buffer(local_buffer, sizeof(local_buffer), sqlda, sqlda_sup::dasup_clause &clause =
dialect, &buffer_len))) statement->das->dasup_clauses[DASUP_CLAUSE_bind];
{
status[0] = isc_arg_gds;
status[1] = isc_virmemexh;
status[2] = isc_arg_end;
return error2(status, local);
}
if (!GDS_DSQL_SQL_INFO( status, if (clause.dasup_info_len && clause.dasup_info_buf)
stmt_handle,
sizeof(describe_bind_info),
describe_bind_info,
buffer_len,
buffer))
{ {
iterative_sql_info( status, iterative_sql_info( status,
stmt_handle, stmt_handle,
sizeof(describe_bind_info), sizeof(describe_select_info),
describe_bind_info, describe_select_info,
buffer_len, clause.dasup_info_len,
buffer, clause.dasup_info_buf,
dialect, dialect,
sqlda); sqlda);
} }
else
{
if (!(buffer = get_sqlda_buffer(local_buffer, sizeof(local_buffer), sqlda,
dialect, &buffer_len)))
{
status[0] = isc_arg_gds;
status[1] = isc_virmemexh;
status[2] = isc_arg_end;
return error2(status, local);
}
if (buffer != local_buffer) { if (!GDS_DSQL_SQL_INFO( status,
free_block(buffer); stmt_handle,
sizeof(describe_bind_info),
describe_bind_info,
buffer_len,
buffer))
{
iterative_sql_info( status,
stmt_handle,
sizeof(describe_bind_info),
describe_bind_info,
buffer_len,
buffer,
dialect,
sqlda);
}
if (buffer != local_buffer) {
free_block(buffer);
}
} }
if (status[1]) { if (status[1]) {
@ -3242,13 +3357,19 @@ ISC_STATUS API_ROUTINE GDS_DSQL_PREPARE(ISC_STATUS* user_status,
ISC_STATUS *status; ISC_STATUS *status;
ISC_STATUS_ARRAY local; ISC_STATUS_ARRAY local;
USHORT buffer_len; USHORT buffer_len;
SCHAR *buffer, local_buffer[BUFFER_MEDIUM]; SCHAR *buffer, *local_buffer;
sqlda_sup* dasup; sqlda_sup* dasup;
GET_STATUS; GET_STATUS;
if (!(buffer = get_sqlda_buffer(local_buffer, sizeof(local_buffer), sqlda, WHY_STMT statement;
dialect, &buffer_len))) TRANSLATE_HANDLE(*stmt_handle, statement, HANDLE_statement, isc_bad_stmt_handle);
WHY_DBB database = statement->parent;
local_buffer = database->db_prepare_buffer;
if (!(buffer = get_sqlda_buffer(local_buffer, DBB_PREPARE_BUFFER_SIZE,
sqlda, dialect, &buffer_len)))
{ {
status[0] = isc_arg_gds; status[0] = isc_arg_gds;
status[1] = isc_virmemexh; status[1] = isc_virmemexh;
@ -3262,27 +3383,93 @@ ISC_STATUS API_ROUTINE GDS_DSQL_PREPARE(ISC_STATUS* user_status,
length, length,
string, string,
dialect, dialect,
sizeof(sql_prepare_info), sizeof(sql_prepare_info2),
sql_prepare_info, sql_prepare_info2,
buffer_len, buffer_len,
buffer)) buffer))
{ {
WHY_STMT statement = WHY_translate_handle(*stmt_handle); // WHY_STMT statement = WHY_translate_handle(*stmt_handle);
release_dsql_support(statement->das); release_dsql_support(statement->das);
if (!(dasup = (sqlda_sup*) alloc((SLONG) sizeof(sqlda_sup)))) { if (!(dasup = (sqlda_sup*) alloc((SLONG) sizeof(sqlda_sup))))
{
statement->requests = 0; statement->requests = 0;
status[0] = isc_arg_gds; status[0] = isc_arg_gds;
status[1] = isc_virmemexh; status[1] = isc_virmemexh;
status[2] = isc_arg_end; status[2] = isc_arg_end;
} }
else { else
{
statement->das = dasup; statement->das = dasup;
dasup->dasup_dialect = dialect; dasup->dasup_dialect = dialect;
SCHAR* p = buffer;
dasup->dasup_stmt_type = 0;
if (*p == isc_info_sql_stmt_type)
{
const USHORT len = gds__vax_integer((UCHAR*)p + 1, 2);
dasup->dasup_stmt_type = gds__vax_integer((UCHAR*)p + 3, len);
p += 3 + len;
}
sqlda_sup::dasup_clause &das_select = dasup->dasup_clauses[DASUP_CLAUSE_select];
sqlda_sup::dasup_clause &das_bind = dasup->dasup_clauses[DASUP_CLAUSE_bind];
das_select.dasup_info_buf = das_bind.dasup_info_buf = 0;
das_select.dasup_info_len = das_bind.dasup_info_len = 0;
if (*p == isc_info_sql_select)
das_select.dasup_info_buf = p;
das_bind.dasup_info_buf = UTLD_skip_sql_info(p);
p = das_select.dasup_info_buf;
if (p)
{
SCHAR* p2 = das_bind.dasup_info_buf;
if (p2)
{
const SLONG len = p2 - p;
p2 = alloc(len + 1);
memmove(p2, p, len);
p2[len] = isc_info_end;
das_select.dasup_info_buf = p2;
das_select.dasup_info_len = len + 1;
}
else
{
das_select.dasup_info_buf = 0;
das_select.dasup_info_len = 0;
}
}
p = das_bind.dasup_info_buf;
if (p)
{
SCHAR* p2 = UTLD_skip_sql_info(p);
if (p2)
{
const SLONG len = p2 - p;
p2 = alloc(len + 1);
memmove(p2, p, len);
p2[len] = isc_info_end;
das_bind.dasup_info_buf = p2;
das_bind.dasup_info_len = len + 1;
}
else
{
das_bind.dasup_info_buf = 0;
das_bind.dasup_info_len = 0;
}
}
iterative_sql_info(status, stmt_handle, sizeof(sql_prepare_info), iterative_sql_info(status, stmt_handle, sizeof(sql_prepare_info),
sql_prepare_info, buffer_len, buffer, dialect, sql_prepare_info, // buffer_len, buffer, dialect,
sqlda); das_select.dasup_info_len,
das_select.dasup_info_buf,
dialect, sqlda);
} }
} }
@ -3441,14 +3628,28 @@ ISC_STATUS API_ROUTINE GDS_DSQL_SQL_INFO(ISC_STATUS* user_status,
buffer_length, buffer); buffer_length, buffer);
else else
#endif #endif
CALL(PROC_DSQL_SQL_INFO, statement->implementation) (status, {
if (( (item_length == 1) && (items[0] == isc_info_sql_stmt_type) ||
(item_length == 2) && (items[0] == isc_info_sql_stmt_type) &&
(items[1] == isc_info_end || items[1] == 0) ) &&
statement->das && statement->das->dasup_stmt_type)
{
*buffer++ = isc_info_sql_stmt_type;
put_short((UCHAR*) buffer, 4);
buffer += 2;
put_long((UCHAR*) buffer, statement->das->dasup_stmt_type);
}
else
{
CALL(PROC_DSQL_SQL_INFO, statement->implementation) (status,
&statement-> &statement->
handle, handle,
item_length, item_length,
items, items,
buffer_length, buffer_length,
buffer); buffer);
}
}
subsystem_exit(); subsystem_exit();
if (status[1]) if (status[1])
@ -5529,6 +5730,9 @@ static SCHAR *get_sqlda_buffer(SCHAR * buffer,
n_variables = ((SQLDA *) sqlda)->sqln; n_variables = ((SQLDA *) sqlda)->sqln;
length = 32 + n_variables * 172; length = 32 + n_variables * 172;
if (length < local_buffer_length)
length = local_buffer_length;
*buffer_length = (USHORT)((length > 65500L) ? 65500L : length); *buffer_length = (USHORT)((length > 65500L) ? 65500L : length);
if (*buffer_length > local_buffer_length) if (*buffer_length > local_buffer_length)
buffer = alloc((SLONG) * buffer_length); buffer = alloc((SLONG) * buffer_length);
@ -5844,13 +6048,17 @@ static void release_dsql_support(sqlda_sup* dasup)
return; return;
} }
/* for C++, add "dasup::" before "dasup_clause" */ /* for C++, add "sqlda_sup::" before "dasup_clause" */
sqlda_sup::dasup_clause* pClauses = dasup->dasup_clauses; sqlda_sup::dasup_clause* pClauses = dasup->dasup_clauses;
why_priv_gds__free_if_set(pClauses[DASUP_CLAUSE_bind].dasup_blr); why_priv_gds__free_if_set(pClauses[DASUP_CLAUSE_bind].dasup_blr);
why_priv_gds__free_if_set(pClauses[DASUP_CLAUSE_select].dasup_blr); why_priv_gds__free_if_set(pClauses[DASUP_CLAUSE_select].dasup_blr);
why_priv_gds__free_if_set(pClauses[DASUP_CLAUSE_bind].dasup_msg); why_priv_gds__free_if_set(pClauses[DASUP_CLAUSE_bind].dasup_msg);
why_priv_gds__free_if_set(pClauses[DASUP_CLAUSE_select].dasup_msg); why_priv_gds__free_if_set(pClauses[DASUP_CLAUSE_select].dasup_msg);
why_priv_gds__free_if_set(pClauses[DASUP_CLAUSE_bind].dasup_info_buf);
why_priv_gds__free_if_set(pClauses[DASUP_CLAUSE_select].dasup_info_buf);
free_block(dasup); free_block(dasup);
} }

View File

@ -63,6 +63,7 @@ struct why_hndl
FB_API_HANDLE* user_handle; FB_API_HANDLE* user_handle;
struct clean* cleanup; struct clean* cleanup;
TEXT* db_path; TEXT* db_path;
SCHAR* db_prepare_buffer;
}; };
typedef why_hndl *WHY_HNDL; typedef why_hndl *WHY_HNDL;
@ -86,4 +87,6 @@ const int HANDLE_TRANSACTION_limbo = 1;
const int HANDLE_BLOB_filter = 2; /* Blob is locally filtered */ const int HANDLE_BLOB_filter = 2; /* Blob is locally filtered */
const int HANDLE_STATEMENT_local = 4; /* Process DSQL statement locally */ const int HANDLE_STATEMENT_local = 4; /* Process DSQL statement locally */
const SLONG DBB_PREPARE_BUFFER_SIZE = 32768; // size of buffer used in isc_dsql_prepare call
#endif // JRD_Y_HANDLE_H #endif // JRD_Y_HANDLE_H

View File

@ -355,7 +355,7 @@ static XDR::xdr_ops inet_ops =
{ {
inet_getlong, inet_getlong,
inet_putlong, inet_putlong,
#ifdef SUPERSERVER #if defined(SUPERSERVER) && !defined(EMBEDDED)
REMOTE_getbytes, REMOTE_getbytes,
#else #else
inet_getbytes, inet_getbytes,
@ -510,7 +510,8 @@ rem_port* INET_analyze(Firebird::PathName& file_name,
static const p_cnct::p_cnct_repeat protocols_to_try1[] = static const p_cnct::p_cnct_repeat protocols_to_try1[] =
{ {
REMOTE_PROTOCOL(PROTOCOL_VERSION8, ptype_rpc, MAX_PTYPE, 1), REMOTE_PROTOCOL(PROTOCOL_VERSION8, ptype_rpc, MAX_PTYPE, 1),
REMOTE_PROTOCOL(PROTOCOL_VERSION10, ptype_rpc, MAX_PTYPE, 2) REMOTE_PROTOCOL(PROTOCOL_VERSION10, ptype_rpc, MAX_PTYPE, 2),
REMOTE_PROTOCOL(PROTOCOL_VERSION10, ptype_rpc, ptype_lazy_send, 3)
#ifdef SCROLLABLE_CURSORS #ifdef SCROLLABLE_CURSORS
, ,
REMOTE_PROTOCOL(PROTOCOL_SCROLLABLE_CURSORS, ptype_rpc, MAX_PTYPE, 3) REMOTE_PROTOCOL(PROTOCOL_SCROLLABLE_CURSORS, ptype_rpc, MAX_PTYPE, 3)
@ -618,6 +619,10 @@ rem_port* INET_analyze(Firebird::PathName& file_name,
port->port_flags |= PORT_no_oob; port->port_flags |= PORT_no_oob;
} }
if (packet->p_acpt.p_acpt_type == ptype_lazy_send) {
port->port_flags |= PORT_lazy;
}
return port; return port;
} }

View File

@ -185,9 +185,7 @@ static ISC_STATUS send_and_receive(RDB, PACKET *, ISC_STATUS *);
static ISC_STATUS send_blob(ISC_STATUS*, RBL, USHORT, const UCHAR*); static ISC_STATUS send_blob(ISC_STATUS*, RBL, USHORT, const UCHAR*);
static void send_cancel_event(RVNT); static void send_cancel_event(RVNT);
static bool send_packet(rem_port*, PACKET *, ISC_STATUS *); static bool send_packet(rem_port*, PACKET *, ISC_STATUS *);
#ifdef NOT_USED_OR_REPLACED
static bool send_partial_packet(rem_port*, PACKET *, ISC_STATUS *); static bool send_partial_packet(rem_port*, PACKET *, ISC_STATUS *);
#endif
#ifdef MULTI_THREAD #ifdef MULTI_THREAD
static void server_death(rem_port*); static void server_death(rem_port*);
#endif #endif
@ -206,6 +204,16 @@ static ULONG remote_event_id = 0;
#define SET_OBJECT(rdb, object, id) REMOTE_set_object (rdb->rdb_port, (struct blk *) object, id) #define SET_OBJECT(rdb, object, id) REMOTE_set_object (rdb->rdb_port, (struct blk *) object, id)
inline bool defer_packet(rem_port* port, const PACKET* packet, ISC_STATUS* status)
{
rem_que_packet p;
p.packet = *packet;
p.sent = false;
port->port_defered_packets->add(p);
return clear_queue(port, status);
}
#define GDS_ATTACH_DATABASE REM_attach_database #define GDS_ATTACH_DATABASE REM_attach_database
#define GDS_BLOB_INFO REM_blob_info #define GDS_BLOB_INFO REM_blob_info
#define GDS_CANCEL_BLOB REM_cancel_blob #define GDS_CANCEL_BLOB REM_cancel_blob
@ -1225,26 +1233,35 @@ ISC_STATUS GDS_DSQL_ALLOCATE(ISC_STATUS* user_status,
if (rdb->rdb_port->port_protocol < PROTOCOL_VERSION7) if (rdb->rdb_port->port_protocol < PROTOCOL_VERSION7)
return unsupported(user_status); return unsupported(user_status);
PACKET* packet = &rdb->rdb_packet; RSR statement;
packet->p_operation = op_allocate_statement; if (rdb->rdb_port->port_flags & PORT_lazy) {
packet->p_rlse.p_rlse_object = rdb->rdb_id; *stmt_handle = statement = (RSR) ALLR_block(type_rsr, 0);
statement->rsr_rdb = rdb;
statement->rsr_id = INVALID_OBJECT;
statement->rsr_flags |= RSR_lazy;
}
else {
PACKET* packet = &rdb->rdb_packet;
packet->p_operation = op_allocate_statement;
packet->p_rlse.p_rlse_object = rdb->rdb_id;
if (send_and_receive(rdb, packet, user_status)) if (send_and_receive(rdb, packet, user_status))
return error(user_status); return error(user_status);
/* Allocate SQL request block */ /* Allocate SQL request block */
statement = (RSR) ALLR_block(type_rsr, 0);
*stmt_handle = statement;
statement->rsr_rdb = rdb;
statement->rsr_id = packet->p_resp.p_resp_object;
/* register the object */
SET_OBJECT(rdb, statement, statement->rsr_id);
}
RSR statement = (RSR) ALLR_block(type_rsr, 0);
*stmt_handle = statement;
statement->rsr_rdb = rdb;
statement->rsr_id = packet->p_resp.p_resp_object;
statement->rsr_next = rdb->rdb_sql_requests; statement->rsr_next = rdb->rdb_sql_requests;
rdb->rdb_sql_requests = statement; rdb->rdb_sql_requests = statement;
/* register the object */
SET_OBJECT(rdb, statement, statement->rsr_id);
} }
catch (const std::exception& ex) catch (const std::exception& ex)
{ {
@ -1988,14 +2005,45 @@ ISC_STATUS GDS_DSQL_FREE(ISC_STATUS * user_status, RSR * stmt_handle, USHORT opt
return unsupported(user_status); return unsupported(user_status);
} }
if (statement->rsr_flags & RSR_lazy) {
if (option == DSQL_drop) {
release_sql_request(statement);
*stmt_handle = NULL;
}
else {
statement->rsr_flags &= ~RSR_fetched;
statement->rsr_rtr = NULL;
if (!clear_queue(rdb->rdb_port, user_status))
return error(user_status);
REMOTE_reset_statement(statement);
}
return return_success(rdb);
}
PACKET* packet = &rdb->rdb_packet; PACKET* packet = &rdb->rdb_packet;
packet->p_operation = op_free_statement; packet->p_operation = op_free_statement;
P_SQLFREE* free_stmt = &packet->p_sqlfree; P_SQLFREE* free_stmt = &packet->p_sqlfree;
free_stmt->p_sqlfree_statement = statement->rsr_id; free_stmt->p_sqlfree_statement = statement->rsr_id;
free_stmt->p_sqlfree_option = option; free_stmt->p_sqlfree_option = option;
if (send_and_receive(rdb, packet, user_status)) { if (rdb->rdb_port->port_flags & PORT_lazy) {
return error(user_status); if (!defer_packet(rdb->rdb_port, packet, user_status))
return error(user_status);
if (option == DSQL_drop) {
packet->p_resp.p_resp_object = INVALID_OBJECT;
}
else {
packet->p_resp.p_resp_object = statement->rsr_id;
}
}
else {
if (send_and_receive(rdb, packet, user_status)) {
return error(user_status);
}
} }
statement->rsr_handle = (FB_API_HANDLE) (IPTR) packet->p_resp.p_resp_object; statement->rsr_handle = (FB_API_HANDLE) (IPTR) packet->p_resp.p_resp_object;
@ -2096,6 +2144,15 @@ ISC_STATUS GDS_DSQL_INSERT(ISC_STATUS * user_status,
/* set up the packet for the other guy... */ /* set up the packet for the other guy... */
PACKET* packet = &rdb->rdb_packet; PACKET* packet = &rdb->rdb_packet;
if (statement->rsr_flags & RSR_lazy) {
packet->p_operation = op_allocate_statement;
packet->p_rlse.p_rlse_object = rdb->rdb_id;
if (!send_partial_packet(rdb->rdb_port, packet, user_status))
return error(user_status);
}
packet->p_operation = op_insert; packet->p_operation = op_insert;
P_SQLDATA* sqldata = &packet->p_sqldata; P_SQLDATA* sqldata = &packet->p_sqldata;
sqldata->p_sqldata_statement = statement->rsr_id; sqldata->p_sqldata_statement = statement->rsr_id;
@ -2110,6 +2167,16 @@ ISC_STATUS GDS_DSQL_INSERT(ISC_STATUS * user_status,
message->msg_address = NULL; message->msg_address = NULL;
if (statement->rsr_flags & RSR_lazy) {
if (!receive_response(rdb, packet))
return error(user_status);
statement->rsr_id = packet->p_resp.p_resp_object;
SET_OBJECT(rdb, statement, statement->rsr_id);
statement->rsr_flags &= ~RSR_lazy;
}
if (!receive_response(rdb, packet)) { if (!receive_response(rdb, packet)) {
return error(user_status); return error(user_status);
} }
@ -2185,6 +2252,15 @@ ISC_STATUS GDS_DSQL_PREPARE(ISC_STATUS * user_status, RTR * rtr_handle, RSR * st
/* set up the packet for the other guy... */ /* set up the packet for the other guy... */
PACKET* packet = &rdb->rdb_packet; PACKET* packet = &rdb->rdb_packet;
if (statement->rsr_flags & RSR_lazy) {
packet->p_operation = op_allocate_statement;
packet->p_rlse.p_rlse_object = rdb->rdb_id;
if (!send_partial_packet(rdb->rdb_port, packet, user_status))
return error(user_status);
}
packet->p_operation = op_prepare_statement; packet->p_operation = op_prepare_statement;
P_SQLST* prepare = &packet->p_sqlst; P_SQLST* prepare = &packet->p_sqlst;
prepare->p_sqlst_transaction = (transaction) ? transaction->rtr_id : 0; prepare->p_sqlst_transaction = (transaction) ? transaction->rtr_id : 0;
@ -2204,6 +2280,16 @@ ISC_STATUS GDS_DSQL_PREPARE(ISC_STATUS * user_status, RTR * rtr_handle, RSR * st
/* Set up for the response packet. */ /* Set up for the response packet. */
if (statement->rsr_flags & RSR_lazy) {
if (!receive_response(rdb, packet))
return error(user_status);
statement->rsr_id = packet->p_resp.p_resp_object;
SET_OBJECT(rdb, statement, statement->rsr_id);
statement->rsr_flags &= ~RSR_lazy;
}
P_RESP* response = &packet->p_resp; P_RESP* response = &packet->p_resp;
CSTRING temp = response->p_resp_data; CSTRING temp = response->p_resp_data;
response->p_resp_data.cstr_allocated = buffer_length; response->p_resp_data.cstr_allocated = buffer_length;
@ -5252,6 +5338,18 @@ static void disconnect( rem_port* port)
RDB rdb = port->port_context; RDB rdb = port->port_context;
if (rdb) { if (rdb) {
PACKET* packet = &rdb->rdb_packet;
// Deliver the pending defered packets
for (rem_que_packet* p = port->port_defered_packets->begin();
p < port->port_defered_packets->end(); p++)
{
if (!p->sent) {
port->send(&p->packet);
}
}
/* BAND-AID: /* BAND-AID:
It seems as if we are disconnecting the port It seems as if we are disconnecting the port
on both the server and client side. For now on both the server and client side. For now
@ -5263,7 +5361,6 @@ static void disconnect( rem_port* port)
*/ */
PACKET* packet = &rdb->rdb_packet;
if (port->port_type != port_pipe) { if (port->port_type != port_pipe) {
packet->p_operation = op_disconnect; packet->p_operation = op_disconnect;
port->send(packet); port->send(packet);
@ -5271,6 +5368,10 @@ static void disconnect( rem_port* port)
REMOTE_free_packet(port, packet); REMOTE_free_packet(port, packet);
} }
// Cleanup the queue
delete port->port_defered_packets;
// Clear context reference for the associated event handler // Clear context reference for the associated event handler
// to avoid SEGV during shutdown // to avoid SEGV during shutdown
@ -5745,6 +5846,9 @@ static bool init(ISC_STATUS* user_status,
RDB rdb = port->port_context; RDB rdb = port->port_context;
PACKET* packet = &rdb->rdb_packet; PACKET* packet = &rdb->rdb_packet;
MemoryPool& pool = *getDefaultMemoryPool();
port->port_defered_packets = FB_NEW(pool) PacketQueue(pool);
/* Make attach packet */ /* Make attach packet */
P_ATCH* attach = &packet->p_atch; P_ATCH* attach = &packet->p_atch;
@ -6104,6 +6208,18 @@ static bool receive_packet_noqueue(rem_port* port,
user_status[1] = isc_net_read_err; user_status[1] = isc_net_read_err;
user_status[2] = isc_arg_end; user_status[2] = isc_arg_end;
// Receive responses for all defered packets that were already sent
while (port->port_defered_packets->getCount())
{
rem_que_packet* p = port->port_defered_packets->begin();
if (!p->sent)
break;
if (!port->receive(packet))
return FALSE;
port->port_defered_packets->remove(p);
}
return (port->receive(packet)); return (port->receive(packet));
} }
@ -6302,7 +6418,20 @@ static bool release_object(RDB rdb,
packet->p_operation = op; packet->p_operation = op;
packet->p_rlse.p_rlse_object = id; packet->p_rlse.p_rlse_object = id;
if (!send_packet(rdb->rdb_port, packet, rdb->rdb_status_vector)) ISC_STATUS* status = rdb->rdb_status_vector;
if (rdb->rdb_port->port_flags & PORT_lazy) {
switch (op) {
case op_close_blob:
case op_cancel_blob:
case op_release:
return defer_packet(rdb->rdb_port, packet, status);
default:
break;
}
}
if (!send_packet(rdb->rdb_port, packet, status))
return false; return false;
return receive_response(rdb, packet); return receive_response(rdb, packet);
@ -6801,10 +6930,21 @@ static bool send_packet(rem_port* port,
user_status[1] = isc_net_write_err; user_status[1] = isc_net_write_err;
user_status[2] = isc_arg_end; user_status[2] = isc_arg_end;
// Send packets that were defered
for (rem_que_packet* p = port->port_defered_packets->begin();
p < port->port_defered_packets->end(); p++)
{
if (!p->sent) {
if (!port->send_partial(&p->packet))
return FALSE;
p->sent = true;
}
}
return (port->send(packet)); return (port->send(packet));
} }
#ifdef NOT_USED_OR_REPLACED
static bool send_partial_packet(rem_port* port, static bool send_partial_packet(rem_port* port,
PACKET* packet, PACKET* packet,
ISC_STATUS* user_status) ISC_STATUS* user_status)
@ -6834,13 +6974,20 @@ static bool send_partial_packet(rem_port* port,
user_status[1] = isc_net_write_err; user_status[1] = isc_net_write_err;
user_status[2] = isc_arg_end; user_status[2] = isc_arg_end;
if (!port->send_partial(packet)) { // Send packets that were defered
return false;
for (rem_que_packet* p = port->port_defered_packets->begin();
p < port->port_defered_packets->end(); p++)
{
if (!p->sent) {
if (!port->send_partial(&p->packet))
return FALSE;
p->sent = true;
}
} }
return true; return (port->send_partial(packet));
} }
#endif
#ifdef MULTI_THREAD #ifdef MULTI_THREAD
static void server_death(rem_port* port) static void server_death(rem_port* port)

View File

@ -142,6 +142,7 @@ const USHORT ptype_page = 1; /* Page server protocol */
const USHORT ptype_rpc = 2; /* Simple remote procedure call */ const USHORT ptype_rpc = 2; /* Simple remote procedure call */
const USHORT ptype_batch_send = 3; /* Batch sends, no asynchrony */ const USHORT ptype_batch_send = 3; /* Batch sends, no asynchrony */
const USHORT ptype_out_of_band = 4; /* Batch sends w/ out of band notification */ const USHORT ptype_out_of_band = 4; /* Batch sends w/ out of band notification */
const USHORT ptype_lazy_send = 5; /* Defered packets delivery */
/* Generic object id */ /* Generic object id */

View File

@ -298,6 +298,7 @@ const USHORT RSR_eof = 2; /* End-of-stream encountered */
const USHORT RSR_blob = 4; /* Statement relates to blob op */ const USHORT RSR_blob = 4; /* Statement relates to blob op */
const USHORT RSR_no_batch = 8; /* Do not batch fetch rows */ const USHORT RSR_no_batch = 8; /* Do not batch fetch rows */
const USHORT RSR_stream_err = 16; /* There is an error pending in the batched rows */ const USHORT RSR_stream_err = 16; /* There is an error pending in the batched rows */
const USHORT RSR_lazy = 32; /* To be allocated at the first reference */
enum blk_t enum blk_t
@ -353,6 +354,18 @@ typedef int HANDLE;
struct p_cnct; struct p_cnct;
struct rmtque; struct rmtque;
/* Queue of defered packets */
struct rem_que_packet
{
PACKET packet;
bool sent;
};
typedef Firebird::Array<rem_que_packet> PacketQueue;
/* Port itself */
class port_interface class port_interface
{ {
public: public:
@ -422,6 +435,8 @@ struct rem_port
USHORT port_iosb[4]; USHORT port_iosb[4];
#endif #endif
void* port_xcc; /* interprocess structure */ void* port_xcc; /* interprocess structure */
PacketQueue* port_defered_packets; /* queue of defered packets */
OBJCT port_last_object_id; /* cached last id */
#ifdef SUPERSERVER #ifdef SUPERSERVER
Firebird::ObjectsArray< Firebird::Array< char > >* port_queue; Firebird::ObjectsArray< Firebird::Array< char > >* port_queue;
size_t port_qoffset; // current packet in the queue size_t port_qoffset; // current packet in the queue
@ -472,7 +487,7 @@ struct rem_port
ISC_STATUS receive_msg(P_DATA*, PACKET*); ISC_STATUS receive_msg(P_DATA*, PACKET*);
ISC_STATUS seek_blob(P_SEEK*, PACKET*); ISC_STATUS seek_blob(P_SEEK*, PACKET*);
ISC_STATUS send_msg(P_DATA*, PACKET*); ISC_STATUS send_msg(P_DATA*, PACKET*);
ISC_STATUS send_response(PACKET*, OBJCT, USHORT, const ISC_STATUS*); ISC_STATUS send_response(PACKET*, OBJCT, USHORT, const ISC_STATUS*, bool);
ISC_STATUS service_attach(P_ATCH*, PACKET*); ISC_STATUS service_attach(P_ATCH*, PACKET*);
ISC_STATUS service_end(P_RLSE*, PACKET*); ISC_STATUS service_end(P_RLSE*, PACKET*);
ISC_STATUS service_start(P_INFO*, PACKET*); ISC_STATUS service_start(P_INFO*, PACKET*);
@ -498,7 +513,8 @@ const USHORT PORT_not_trusted = 256; /* Connection is from an untrusted node */
// This is tested only in wnet.cpp but never set. // This is tested only in wnet.cpp but never set.
//const USHORT PORT_impersonate = 512; // A remote user is being impersonated //const USHORT PORT_impersonate = 512; // A remote user is being impersonated
const USHORT PORT_dummy_pckt_set= 1024; /* A dummy packet interval is set */ const USHORT PORT_dummy_pckt_set= 1024; /* A dummy packet interval is set */
const USHORT PORT_partial_data = 2048; /* Physical packet doesn't contain all API packet */ const USHORT PORT_partial_data = 2048; /* Physical packet doesn't contain all API packet */
const USHORT PORT_lazy = 4096; /* Defered operations are allowed */
/* Misc declarations */ /* Misc declarations */

View File

@ -74,6 +74,10 @@
#define CHECK_HANDLE(blk, cast, type, id, err) \ #define CHECK_HANDLE(blk, cast, type, id, err) \
{ \ { \
if ((port->port_flags & PORT_lazy) && id == INVALID_OBJECT) \
{ \
id = port->port_last_object_id; \
} \
if (id >= port->port_object_vector->vec_count || \ if (id >= port->port_object_vector->vec_count || \
!(blk = (cast) port->port_objects [id]) || \ !(blk = (cast) port->port_objects [id]) || \
((BLK) blk)->blk_type != (UCHAR) type) \ ((BLK) blk)->blk_type != (UCHAR) type) \
@ -81,12 +85,17 @@
status_vector [0] = isc_arg_gds; \ status_vector [0] = isc_arg_gds; \
status_vector [1] = err; \ status_vector [1] = err; \
status_vector [2] = isc_arg_end; \ status_vector [2] = isc_arg_end; \
return port->send_response(sendL, 0, 0, status_vector); \ return port->send_response(send, 0, 0, status_vector, \
false); \
} \ } \
} }
#define CHECK_HANDLE_MEMBER(blk, cast, type, id, err) \ #define CHECK_HANDLE_MEMBER(blk, cast, type, id, err) \
{ \ { \
if ((this->port_flags & PORT_lazy) && id == INVALID_OBJECT) \
{ \
id = this->port_last_object_id; \
} \
if (id >= this->port_object_vector->vec_count || \ if (id >= this->port_object_vector->vec_count || \
!(blk = (cast) this->port_objects [id]) || \ !(blk = (cast) this->port_objects [id]) || \
((BLK) blk)->blk_type != (UCHAR) type) \ ((BLK) blk)->blk_type != (UCHAR) type) \
@ -94,7 +103,8 @@
status_vector [0] = isc_arg_gds; \ status_vector [0] = isc_arg_gds; \
status_vector [1] = err; \ status_vector [1] = err; \
status_vector [2] = isc_arg_end; \ status_vector [2] = isc_arg_end; \
return this->send_response(sendL, 0, 0, status_vector); \ return this->send_response(sendL, 0, 0, status_vector, \
false); \
} \ } \
} }
@ -576,7 +586,7 @@ void SRVR_multi_thread( rem_port* main_port, USHORT flags)
#endif #endif
*/ */
port->send_response(&request->req_send, 0, 0, port->send_response(&request->req_send, 0, 0,
status_vector); status_vector, false);
port->disconnect(&request->req_send, &request->req_receive); port->disconnect(&request->req_send, &request->req_receive);
} }
else { else {
@ -676,7 +686,7 @@ static bool accept_connection(rem_port* port,
weight = protocol->p_cnct_weight; weight = protocol->p_cnct_weight;
version = protocol->p_cnct_version; version = protocol->p_cnct_version;
architecture = protocol->p_cnct_architecture; architecture = protocol->p_cnct_architecture;
type = MIN(protocol->p_cnct_max_type, ptype_out_of_band); type = MIN(protocol->p_cnct_max_type, ptype_lazy_send);
send->p_operation = op_accept; send->p_operation = op_accept;
} }
} }
@ -707,6 +717,9 @@ static bool accept_connection(rem_port* port,
if (type != ptype_out_of_band) if (type != ptype_out_of_band)
port->port_flags |= PORT_no_oob; port->port_flags |= PORT_no_oob;
if (type == ptype_lazy_send)
port->port_flags |= PORT_lazy;
port->send(send); port->send(send);
return true; return true;
@ -731,7 +744,7 @@ static ISC_STATUS allocate_statement( rem_port* port, P_RLSE * allocate, PACKET*
if (bad_db(status_vector, rdb)) if (bad_db(status_vector, rdb))
{ {
return port->send_response(send, 0, 0, status_vector); return port->send_response(send, 0, 0, status_vector, true);
} }
FB_API_HANDLE handle = 0; FB_API_HANDLE handle = 0;
@ -767,7 +780,7 @@ static ISC_STATUS allocate_statement( rem_port* port, P_RLSE * allocate, PACKET*
} }
} }
return port->send_response(send, object, 0, status_vector); return port->send_response(send, object, 0, status_vector, true);
} }
@ -957,7 +970,7 @@ static ISC_STATUS attach_database(
rdb->rdb_handle = handle; rdb->rdb_handle = handle;
} }
return port->send_response(send, 0, 0, status_vector); return port->send_response(send, 0, 0, status_vector, false);
} }
@ -1023,7 +1036,8 @@ static void aux_request( rem_port* port, P_REQ * request, PACKET* send)
} }
port->send_response(send, rdb->rdb_id, port->send_response(send, rdb->rdb_id,
send->p_resp.p_resp_data.cstr_length, status_vector); send->p_resp.p_resp_data.cstr_length,
status_vector, false);
if (status_vector[1]) { if (status_vector[1]) {
/* restore the port status vector */ /* restore the port status vector */
@ -1064,7 +1078,7 @@ static ISC_STATUS cancel_events( rem_port* port, P_EVENT * stuff, PACKET* send)
RDB rdb = port->port_context; RDB rdb = port->port_context;
if (bad_db(status_vector, rdb)) if (bad_db(status_vector, rdb))
{ {
return port->send_response(send, 0, 0, status_vector); return port->send_response(send, 0, 0, status_vector, false);
} }
/* Find the event */ /* Find the event */
@ -1077,7 +1091,7 @@ static ISC_STATUS cancel_events( rem_port* port, P_EVENT * stuff, PACKET* send)
/* If no event found, pretend it was cancelled */ /* If no event found, pretend it was cancelled */
if (!event) if (!event)
return port->send_response(send, 0, 0, status_vector); return port->send_response(send, 0, 0, status_vector, false);
/* cancel the event */ /* cancel the event */
@ -1095,7 +1109,7 @@ static ISC_STATUS cancel_events( rem_port* port, P_EVENT * stuff, PACKET* send)
/* return response */ /* return response */
return port->send_response(send, 0, 0, status_vector); return port->send_response(send, 0, 0, status_vector, false);
} }
@ -1232,7 +1246,7 @@ ISC_STATUS rem_port::compile(P_CMPL* compileL, PACKET* sendL)
RDB rdb = this->port_context; RDB rdb = this->port_context;
if (bad_db(status_vector, rdb)) if (bad_db(status_vector, rdb))
{ {
return this->send_response(sendL, 0, 0, status_vector); return this->send_response(sendL, 0, 0, status_vector, false);
} }
FB_API_HANDLE handle = 0; FB_API_HANDLE handle = 0;
@ -1245,7 +1259,7 @@ ISC_STATUS rem_port::compile(P_CMPL* compileL, PACKET* sendL)
THREAD_ENTER(); THREAD_ENTER();
if (status_vector[1]) if (status_vector[1])
return this->send_response(sendL, 0, 0, status_vector); return this->send_response(sendL, 0, 0, status_vector, false);
/* Parse the request to find the messages */ /* Parse the request to find the messages */
@ -1281,7 +1295,7 @@ ISC_STATUS rem_port::compile(P_CMPL* compileL, PACKET* sendL)
status_vector[0] = isc_arg_gds; status_vector[0] = isc_arg_gds;
status_vector[1] = isc_too_many_handles; status_vector[1] = isc_too_many_handles;
status_vector[2] = isc_arg_end; status_vector[2] = isc_arg_end;
return this->send_response(sendL, 0, 0, status_vector); return this->send_response(sendL, 0, 0, status_vector, false);
} }
while (message) { while (message) {
@ -1300,7 +1314,7 @@ ISC_STATUS rem_port::compile(P_CMPL* compileL, PACKET* sendL)
message = next; message = next;
} }
return this->send_response(sendL, object, 0, status_vector); return this->send_response(sendL, object, 0, status_vector, false);
} }
@ -1328,7 +1342,7 @@ ISC_STATUS rem_port::ddl(P_DDL* ddlL, PACKET* sendL)
RDB rdb = this->port_context; RDB rdb = this->port_context;
if (bad_db(status_vector, rdb)) if (bad_db(status_vector, rdb))
{ {
return this->send_response(sendL, 0, 0, status_vector); return this->send_response(sendL, 0, 0, status_vector, false);
} }
const UCHAR* blr = ddlL->p_ddl_blr.cstr_address; const UCHAR* blr = ddlL->p_ddl_blr.cstr_address;
@ -1339,7 +1353,7 @@ ISC_STATUS rem_port::ddl(P_DDL* ddlL, PACKET* sendL)
blr_length, reinterpret_cast<const char*>(blr)); blr_length, reinterpret_cast<const char*>(blr));
THREAD_ENTER(); THREAD_ENTER();
return this->send_response(sendL, 0, 0, status_vector); return this->send_response(sendL, 0, 0, status_vector, false);
} }
@ -1529,7 +1543,7 @@ void rem_port::drop_database(P_RLSE* release, PACKET* sendL)
RDB rdb = this->port_context; RDB rdb = this->port_context;
if (bad_db(status_vector, rdb)) if (bad_db(status_vector, rdb))
{ {
this->send_response(sendL, 0, 0, status_vector); this->send_response(sendL, 0, 0, status_vector, false);
return; return;
} }
@ -1540,7 +1554,7 @@ void rem_port::drop_database(P_RLSE* release, PACKET* sendL)
if (status_vector[1] if (status_vector[1]
&& (status_vector[1] != isc_drdb_completed_with_errs)) && (status_vector[1] != isc_drdb_completed_with_errs))
{ {
this->send_response(sendL, 0, 0, status_vector); this->send_response(sendL, 0, 0, status_vector, false);
return; return;
} }
@ -1559,7 +1573,7 @@ void rem_port::drop_database(P_RLSE* release, PACKET* sendL)
if (this->port_statement) if (this->port_statement)
release_statement(&this->port_statement); release_statement(&this->port_statement);
this->send_response(sendL, 0, 0, status_vector); this->send_response(sendL, 0, 0, status_vector, false);
} }
@ -1625,7 +1639,7 @@ ISC_STATUS rem_port::end_blob(P_OP operation, P_RLSE * release, PACKET* sendL)
release_blob(blob); release_blob(blob);
} }
return this->send_response(sendL, 0, 0, status_vector); return this->send_response(sendL, 0, 0, status_vector, false);
} }
@ -1646,7 +1660,7 @@ ISC_STATUS rem_port::end_database(P_RLSE * release, PACKET* sendL)
RDB rdb = this->port_context; RDB rdb = this->port_context;
if (bad_db(status_vector, rdb)) if (bad_db(status_vector, rdb))
{ {
return this->send_response(sendL, 0, 0, status_vector); return this->send_response(sendL, 0, 0, status_vector, false);
} }
THREAD_EXIT(); THREAD_EXIT();
@ -1654,7 +1668,7 @@ ISC_STATUS rem_port::end_database(P_RLSE * release, PACKET* sendL)
THREAD_ENTER(); THREAD_ENTER();
if (status_vector[1]) if (status_vector[1])
return this->send_response(sendL, 0, 0, status_vector); return this->send_response(sendL, 0, 0, status_vector, false);
while (rdb->rdb_events) while (rdb->rdb_events)
release_event(rdb->rdb_events); release_event(rdb->rdb_events);
@ -1671,7 +1685,7 @@ ISC_STATUS rem_port::end_database(P_RLSE * release, PACKET* sendL)
if (this->port_statement) if (this->port_statement)
release_statement(&this->port_statement); release_statement(&this->port_statement);
return this->send_response(sendL, 0, 0, status_vector); return this->send_response(sendL, 0, 0, status_vector, false);
} }
@ -1703,7 +1717,7 @@ ISC_STATUS rem_port::end_request(P_RLSE * release, PACKET* sendL)
if (!status_vector[1]) if (!status_vector[1])
release_request(requestL); release_request(requestL);
return this->send_response(sendL, 0, 0, status_vector); return this->send_response(sendL, 0, 0, status_vector, true);
} }
@ -1735,7 +1749,7 @@ ISC_STATUS rem_port::end_statement(P_SQLFREE* free_stmt, PACKET* sendL)
THREAD_ENTER(); THREAD_ENTER();
if (status_vector[1]) if (status_vector[1])
return this->send_response(sendL, 0, 0, status_vector); return this->send_response(sendL, 0, 0, status_vector, true);
if (!statement->rsr_handle) { if (!statement->rsr_handle) {
release_sql_request(statement); release_sql_request(statement);
@ -1750,7 +1764,7 @@ ISC_STATUS rem_port::end_statement(P_SQLFREE* free_stmt, PACKET* sendL)
const USHORT object = (statement) ? statement->rsr_id : INVALID_OBJECT; const USHORT object = (statement) ? statement->rsr_id : INVALID_OBJECT;
return this->send_response(sendL, object, 0, status_vector); return this->send_response(sendL, object, 0, status_vector, true);
} }
@ -1807,7 +1821,7 @@ ISC_STATUS rem_port::end_transaction(P_OP operation, P_RLSE * release, PACKET* s
release_transaction(transaction); release_transaction(transaction);
} }
return this->send_response(sendL, 0, 0, status_vector); return this->send_response(sendL, 0, 0, status_vector, false);
} }
@ -1831,7 +1845,7 @@ ISC_STATUS rem_port::execute_immediate(P_OP op, P_SQLST * exnow, PACKET* sendL)
RDB rdb = this->port_context; RDB rdb = this->port_context;
if (bad_db(status_vector, rdb)) if (bad_db(status_vector, rdb))
{ {
return this->send_response(sendL, 0, 0, status_vector); return this->send_response(sendL, 0, 0, status_vector, false);
} }
/** Do not call CHECK_HANDLE if this is the start of a transaction **/ /** Do not call CHECK_HANDLE if this is the start of a transaction **/
@ -1956,7 +1970,8 @@ ISC_STATUS rem_port::execute_immediate(P_OP op, P_SQLST * exnow, PACKET* sendL)
return this->send_response( sendL, return this->send_response( sendL,
(OBJCT) (transaction ? transaction->rtr_id : 0), (OBJCT) (transaction ? transaction->rtr_id : 0),
0, 0,
status_vector); status_vector,
false);
} }
@ -2072,7 +2087,8 @@ ISC_STATUS rem_port::execute_statement(P_OP op, P_SQLDATA* sqldata, PACKET* send
return this->send_response( sendL, return this->send_response( sendL,
(OBJCT) (transaction ? transaction->rtr_id : 0), (OBJCT) (transaction ? transaction->rtr_id : 0),
0, 0,
status_vector); status_vector,
false);
} }
@ -2159,7 +2175,8 @@ ISC_STATUS rem_port::fetch(P_SQLDATA * sqldata, PACKET* sendL)
{ {
statement->rsr_flags &= ~RSR_stream_err; statement->rsr_flags &= ~RSR_stream_err;
return this->send_response(sendL, 0, 0, return this->send_response(sendL, 0, 0,
statement->rsr_status_vector); statement->rsr_status_vector,
false);
} }
message = statement->rsr_buffer; message = statement->rsr_buffer;
@ -2190,7 +2207,7 @@ ISC_STATUS rem_port::fetch(P_SQLDATA * sqldata, PACKET* sendL)
break; break;
} }
else { else {
return this->send_response(sendL, 0, 0, status_vector); return this->send_response(sendL, 0, 0, status_vector, false);
} }
} }
message->msg_address = message->msg_buffer; message->msg_address = message->msg_buffer;
@ -2343,7 +2360,7 @@ ISC_STATUS rem_port::fetch_blob(P_SQLDATA * sqldata, PACKET* sendL)
message->msg_address = NULL; message->msg_address = NULL;
} }
return this->send_response(sendL, 0, 0, status_vector); return this->send_response(sendL, 0, 0, status_vector, false);
} }
@ -2382,13 +2399,15 @@ OBJCT rem_port::get_id(BLK block)
{ {
if (!*p) { if (!*p) {
*p = block; *p = block;
return (OBJCT) (p - vector->vec_object); this->port_last_object_id = (OBJCT) (p - vector->vec_object);
return this->port_last_object_id;
} }
} }
/* Vector is full -- somebody will need to expand it */ /* Vector is full -- somebody will need to expand it */
return REMOTE_set_object(this, block, (OBJCT) vector->vec_count); return (this->port_last_object_id =
REMOTE_set_object(this, block, (OBJCT) vector->vec_count));
} }
@ -2501,7 +2520,7 @@ ISC_STATUS rem_port::get_segment(P_SGMT* segment, PACKET* sendL)
reinterpret_cast<char*>(buffer)); reinterpret_cast<char*>(buffer));
THREAD_ENTER(); THREAD_ENTER();
const ISC_STATUS status = const ISC_STATUS status =
this->send_response(sendL, blob->rbl_id, length, status_vector); this->send_response(sendL, blob->rbl_id, length, status_vector, false);
#ifdef DEBUG_REMOTE_MEMORY #ifdef DEBUG_REMOTE_MEMORY
printf("get_segment(server) free buffer %x\n", buffer); printf("get_segment(server) free buffer %x\n", buffer);
#endif #endif
@ -2553,7 +2572,8 @@ ISC_STATUS rem_port::get_segment(P_SGMT* segment, PACKET* sendL)
const ISC_STATUS status = this->send_response(sendL, const ISC_STATUS status = this->send_response(sendL,
(OBJCT)state, (OBJCT)state,
(USHORT) (p - buffer), (USHORT) (p - buffer),
status_vector); status_vector,
false);
#ifdef DEBUG_REMOTE_MEMORY #ifdef DEBUG_REMOTE_MEMORY
printf("get_segment(server) free buffer %x\n", buffer); printf("get_segment(server) free buffer %x\n", buffer);
@ -2588,7 +2608,7 @@ ISC_STATUS rem_port::get_slice(P_SLC * stuff, PACKET* sendL)
RDB rdb = this->port_context; RDB rdb = this->port_context;
if (bad_db(status_vector, rdb)) if (bad_db(status_vector, rdb))
{ {
return this->send_response(sendL, 0, 0, status_vector); return this->send_response(sendL, 0, 0, status_vector, false);
} }
CHECK_HANDLE_MEMBER(transaction, CHECK_HANDLE_MEMBER(transaction,
@ -2628,7 +2648,7 @@ ISC_STATUS rem_port::get_slice(P_SLC * stuff, PACKET* sendL)
ISC_STATUS status; ISC_STATUS status;
if (status_vector[1]) if (status_vector[1])
status = this->send_response(sendL, 0, 0, status_vector); status = this->send_response(sendL, 0, 0, status_vector, false);
else { else {
sendL->p_operation = op_slice; sendL->p_operation = op_slice;
response->p_slr_slice.lstr_address = slice; response->p_slr_slice.lstr_address = slice;
@ -2673,28 +2693,60 @@ ISC_STATUS rem_port::info(P_OP op, P_INFO * stuff, PACKET* sendL)
RDB rdb = this->port_context; RDB rdb = this->port_context;
if (bad_db(status_vector, rdb)) if (bad_db(status_vector, rdb))
{ {
return this->send_response(sendL, 0, 0, status_vector); return this->send_response(sendL, 0, 0, status_vector, false);
} }
/* Make sure there is a suitable temporary blob buffer */ /* Make sure there is a suitable temporary blob buffer */
UCHAR* const buffer = ALLR_alloc((SLONG) stuff->p_info_buffer_length); UCHAR* const buffer = ALLR_alloc(stuff->p_info_buffer_length);
memset(buffer, 0, stuff->p_info_buffer_length); memset(buffer, 0, stuff->p_info_buffer_length);
#ifdef DEBUG_REMOTE_MEMORY #ifdef DEBUG_REMOTE_MEMORY
printf("info(server) allocate buffer %x\n", buffer); printf("info(server) allocate buffer %x\n", buffer);
#endif #endif
SCHAR info[1024], *info_buffer;
SSHORT info_len;
UCHAR temp[1024]; UCHAR temp[1024];
UCHAR* temp_buffer; UCHAR* temp_buffer;
if (op == op_info_database && stuff->p_info_buffer_length > sizeof(temp)) { temp_buffer = temp;
temp_buffer = ALLR_alloc((SLONG) stuff->p_info_buffer_length); if (op == op_info_database)
{
info_len = 0;
info_buffer = 0;
if (stuff->p_info_buffer_length > sizeof(temp))
{
temp_buffer = ALLR_alloc((SLONG) stuff->p_info_buffer_length);
#ifdef DEBUG_REMOTE_MEMORY #ifdef DEBUG_REMOTE_MEMORY
printf("info(server) allocate buffer %x\n", temp_buffer); printf("info(server) allocate buffer %x\n", temp_buffer);
#endif #endif
}
} }
else else
temp_buffer = temp; {
// stuff isc_info_length in front of info items buffer
CSTRING* info_string = (op == op_service_info) ?
&stuff->p_info_recv_items : &stuff->p_info_items;
info_len = 1 + info_string->cstr_length;
if (info_len > sizeof(info))
{
info_buffer = (SCHAR*) ALLR_alloc((SLONG) info_len);
#ifdef DEBUG_REMOTE_MEMORY
ib_printf("info(server) allocate buffer %x\n", info_buffer);
#endif
}
else {
info_buffer = info;
}
*info_buffer = isc_info_length;
memmove(info_buffer + 1, info_string->cstr_address, info_len-1);
}
USHORT info_db_len = 0;
switch (op) { switch (op) {
case op_info_blob: case op_info_blob:
CHECK_HANDLE_MEMBER(blob, CHECK_HANDLE_MEMBER(blob,
@ -2704,8 +2756,8 @@ ISC_STATUS rem_port::info(P_OP op, P_INFO * stuff, PACKET* sendL)
isc_bad_segstr_handle); isc_bad_segstr_handle);
THREAD_EXIT(); THREAD_EXIT();
isc_blob_info(status_vector, &blob->rbl_handle, isc_blob_info(status_vector, &blob->rbl_handle,
stuff->p_info_items.cstr_length, info_len,
reinterpret_cast<char*>(stuff->p_info_items.cstr_address), info_buffer,
stuff->p_info_buffer_length, stuff->p_info_buffer_length,
reinterpret_cast<char*>(buffer)); reinterpret_cast<char*>(buffer));
THREAD_ENTER(); THREAD_ENTER();
@ -2720,9 +2772,9 @@ ISC_STATUS rem_port::info(P_OP op, P_INFO * stuff, PACKET* sendL)
reinterpret_cast<char*>(temp_buffer) /*temp*/); reinterpret_cast<char*>(temp_buffer) /*temp*/);
if (!status_vector[1]) { if (!status_vector[1]) {
TEXT version[256]; TEXT version[256];
sprintf(version, "%s/%s", GDS_VERSION, sprintf(version, "%s/%s", GDS_VERSION, this->port_version->str_data);
this->port_version->str_data); info_db_len = MERGE_database_info(temp_buffer /*temp*/,
MERGE_database_info(temp_buffer /*temp*/, buffer, stuff->p_info_buffer_length, buffer, stuff->p_info_buffer_length,
IMPLEMENTATION, 4, 1, IMPLEMENTATION, 4, 1,
reinterpret_cast<const UCHAR*>(version), reinterpret_cast<const UCHAR*>(version),
reinterpret_cast<UCHAR*>(this->port_host->str_data), reinterpret_cast<UCHAR*>(this->port_host->str_data),
@ -2742,8 +2794,8 @@ ISC_STATUS rem_port::info(P_OP op, P_INFO * stuff, PACKET* sendL)
THREAD_EXIT(); THREAD_EXIT();
isc_request_info(status_vector, &requestL->rrq_handle, isc_request_info(status_vector, &requestL->rrq_handle,
stuff->p_info_incarnation, stuff->p_info_incarnation,
stuff->p_info_items.cstr_length, info_len,
reinterpret_cast<const char*>(stuff->p_info_items.cstr_address), info_buffer,
stuff->p_info_buffer_length, stuff->p_info_buffer_length,
reinterpret_cast<char*>(buffer)); reinterpret_cast<char*>(buffer));
THREAD_ENTER(); THREAD_ENTER();
@ -2758,8 +2810,8 @@ ISC_STATUS rem_port::info(P_OP op, P_INFO * stuff, PACKET* sendL)
isc_bad_trans_handle); isc_bad_trans_handle);
THREAD_EXIT(); THREAD_EXIT();
isc_transaction_info(status_vector, &transaction->rtr_handle, isc_transaction_info(status_vector, &transaction->rtr_handle,
stuff->p_info_items.cstr_length, info_len,
reinterpret_cast<const char*>(stuff->p_info_items.cstr_address), info_buffer,
stuff->p_info_buffer_length, stuff->p_info_buffer_length,
reinterpret_cast < char *>(buffer)); reinterpret_cast < char *>(buffer));
THREAD_ENTER(); THREAD_ENTER();
@ -2773,9 +2825,8 @@ ISC_STATUS rem_port::info(P_OP op, P_INFO * stuff, PACKET* sendL)
stuff->p_info_items.cstr_length, stuff->p_info_items.cstr_length,
reinterpret_cast< reinterpret_cast<
const char*>(stuff->p_info_items.cstr_address), const char*>(stuff->p_info_items.cstr_address),
stuff->p_info_recv_items.cstr_length, info_len,
reinterpret_cast< info_buffer,
const char*>(stuff->p_info_recv_items.cstr_address),
stuff->p_info_buffer_length, stuff->p_info_buffer_length,
reinterpret_cast<char*>(buffer)); reinterpret_cast<char*>(buffer));
THREAD_ENTER(); THREAD_ENTER();
@ -2787,12 +2838,13 @@ ISC_STATUS rem_port::info(P_OP op, P_INFO * stuff, PACKET* sendL)
type_rsr, type_rsr,
stuff->p_info_object, stuff->p_info_object,
isc_bad_req_handle); isc_bad_req_handle);
THREAD_EXIT(); THREAD_EXIT();
GDS_DSQL_SQL_INFO(status_vector, GDS_DSQL_SQL_INFO(status_vector,
&statement->rsr_handle, &statement->rsr_handle,
stuff->p_info_items.cstr_length, info_len,
reinterpret_cast< info_buffer,
const char*>(stuff->p_info_items.cstr_address),
stuff->p_info_buffer_length, stuff->p_info_buffer_length,
reinterpret_cast < char *>(buffer)); reinterpret_cast < char *>(buffer));
THREAD_ENTER(); THREAD_ENTER();
@ -2806,12 +2858,34 @@ ISC_STATUS rem_port::info(P_OP op, P_INFO * stuff, PACKET* sendL)
ALLR_free(temp_buffer); ALLR_free(temp_buffer);
} }
if (info_buffer && (info_buffer != info)) {
#ifdef DEBUG_REMOTE_MEMORY
printf ("info(server) free buffer %x\n", info_buffer);
#endif
ALLR_free(info_buffer);
}
/* Send a response that includes the segment. */ /* Send a response that includes the segment. */
sendL->p_resp.p_resp_data.cstr_address = buffer; USHORT response_len =
info_db_len ? info_db_len : stuff->p_info_buffer_length;
SSHORT skip_len = 0;
if (*buffer == isc_info_length)
{
skip_len = gds__vax_integer(buffer + 1, 2);
SLONG val = gds__vax_integer(buffer + 3, skip_len);
skip_len += 3;
if (val && val <= response_len) {
response_len = val;
}
}
sendL->p_resp.p_resp_data.cstr_address = buffer + skip_len;
const ISC_STATUS status = this->send_response(sendL, stuff->p_info_object,
response_len, status_vector, false);
const ISC_STATUS status = this->send_response(sendL, stuff->p_info_object,
stuff->p_info_buffer_length, status_vector);
#ifdef DEBUG_REMOTE_MEMORY #ifdef DEBUG_REMOTE_MEMORY
printf("info(server) free buffer %x\n", buffer); printf("info(server) free buffer %x\n", buffer);
#endif #endif
@ -2864,7 +2938,7 @@ ISC_STATUS rem_port::insert(P_SQLDATA * sqldata, PACKET* sendL)
reinterpret_cast<const char*>(msg)); reinterpret_cast<const char*>(msg));
THREAD_ENTER(); THREAD_ENTER();
return this->send_response(sendL, 0, 0, status_vector); return this->send_response(sendL, 0, 0, status_vector, false);
} }
@ -2921,7 +2995,7 @@ ISC_STATUS rem_port::open_blob(P_OP op, P_BLOB* stuff, PACKET* sendL)
RDB rdb = this->port_context; RDB rdb = this->port_context;
if (bad_db(status_vector, rdb)) if (bad_db(status_vector, rdb))
{ {
return this->send_response(sendL, 0, 0, status_vector); return this->send_response(sendL, 0, 0, status_vector, false);
} }
FB_API_HANDLE handle = 0; FB_API_HANDLE handle = 0;
@ -2976,7 +3050,7 @@ ISC_STATUS rem_port::open_blob(P_OP op, P_BLOB* stuff, PACKET* sendL)
} }
} }
return this->send_response(sendL, object, 0, status_vector); return this->send_response(sendL, object, 0, status_vector, false);
} }
@ -3010,7 +3084,7 @@ ISC_STATUS rem_port::prepare(P_PREP * stuff, PACKET* sendL)
} }
THREAD_ENTER(); THREAD_ENTER();
return this->send_response(sendL, 0, 0, status_vector); return this->send_response(sendL, 0, 0, status_vector, false);
} }
@ -3046,12 +3120,24 @@ ISC_STATUS rem_port::prepare_statement(P_SQLST * prepareL, PACKET* sendL)
isc_bad_req_handle); isc_bad_req_handle);
UCHAR local_buffer[1024]; UCHAR local_buffer[1024];
UCHAR *info, info_buffer[1024];
UCHAR* buffer; UCHAR* buffer;
if (prepareL->p_sqlst_buffer_length > sizeof(local_buffer)) if (prepareL->p_sqlst_buffer_length > sizeof(local_buffer))
buffer = ALLR_alloc((SLONG) prepareL->p_sqlst_buffer_length); buffer = ALLR_alloc((SLONG) prepareL->p_sqlst_buffer_length);
else else
buffer = local_buffer; buffer = local_buffer;
// stuff isc_info_length in front of info items buffer
if (prepareL->p_sqlst_items.cstr_length + 1 > sizeof(info_buffer)) {
info = ALLR_alloc((SLONG) prepareL->p_sqlst_items.cstr_length + 1);
}
else {
info = info_buffer;
}
*info = isc_info_length;
memmove(info + 1, prepareL->p_sqlst_items.cstr_address,
prepareL->p_sqlst_items.cstr_length);
FB_API_HANDLE handle = (transaction) ? transaction->rtr_handle : 0; FB_API_HANDLE handle = (transaction) ? transaction->rtr_handle : 0;
@ -3084,16 +3170,20 @@ ISC_STATUS rem_port::prepare_statement(P_SQLST * prepareL, PACKET* sendL)
reinterpret_cast<const char*>(prepareL->p_sqlst_SQL_str.cstr_address), reinterpret_cast<const char*>(prepareL->p_sqlst_SQL_str.cstr_address),
(USHORT) ((prepareL->p_sqlst_SQL_dialect * 10) + (USHORT) ((prepareL->p_sqlst_SQL_dialect * 10) +
parser_version), parser_version),
prepareL->p_sqlst_items.cstr_length, prepareL->p_sqlst_items.cstr_length + 1,
reinterpret_cast<const char*>(prepareL->p_sqlst_items.cstr_address), reinterpret_cast<const char*> (info),
prepareL->p_sqlst_buffer_length, prepareL->p_sqlst_buffer_length,
reinterpret_cast<char*>(buffer)); reinterpret_cast<char*>(buffer));
THREAD_ENTER(); THREAD_ENTER();
if (info != info_buffer) {
ALLR_free(info);
}
if (status_vector[1]) { if (status_vector[1]) {
if (buffer != local_buffer) if (buffer != local_buffer)
ALLR_free(buffer); ALLR_free(buffer);
return this->send_response(sendL, 0, 0, status_vector); return this->send_response(sendL, 0, 0, status_vector, false);
} }
REMOTE_reset_statement(statement); REMOTE_reset_statement(statement);
@ -3108,13 +3198,26 @@ ISC_STATUS rem_port::prepare_statement(P_SQLST * prepareL, PACKET* sendL)
/* Send a response that includes the info requested. */ /* Send a response that includes the info requested. */
sendL->p_resp.p_resp_data.cstr_address = buffer; USHORT response_len = prepareL->p_sqlst_buffer_length;
SSHORT skip_len = 0;
if (*buffer == isc_info_length)
{
skip_len = gds__vax_integer(buffer + 1, 2);
SLONG val = gds__vax_integer(buffer + 3, skip_len);
skip_len += 3;
if (val && val <= response_len) {
response_len = val;
}
}
sendL->p_resp.p_resp_data.cstr_address = buffer + skip_len;
const ISC_STATUS status = const ISC_STATUS status =
this->send_response(sendL, this->send_response(sendL,
state, state,
prepareL->p_sqlst_buffer_length, response_len,
status_vector); status_vector,
false);
if (buffer != local_buffer) { if (buffer != local_buffer) {
ALLR_free(buffer); ALLR_free(buffer);
@ -3418,7 +3521,7 @@ bool process_packet(rem_port* port,
gds__log_status("unknown, SERVER/process_packet", status_ptr); gds__log_status("unknown, SERVER/process_packet", status_ptr);
/* It would be nice to log an error to the user, instead of just terminating them! */ /* It would be nice to log an error to the user, instead of just terminating them! */
port->send_response(sendL, 0, 0, status_ptr); port->send_response(sendL, 0, 0, status_ptr, false);
port->disconnect(sendL, receive); /* Well, how about this... */ port->disconnect(sendL, receive); /* Well, how about this... */
ThreadData::restoreSpecific(); ThreadData::restoreSpecific();
@ -3462,7 +3565,7 @@ ISC_STATUS rem_port::put_segment(P_OP op, P_SGMT * segment, PACKET* sendL)
isc_put_segment(status_vector, &blob->rbl_handle, length, isc_put_segment(status_vector, &blob->rbl_handle, length,
reinterpret_cast<const char*>(p)); reinterpret_cast<const char*>(p));
THREAD_ENTER(); THREAD_ENTER();
return this->send_response(sendL, 0, 0, status_vector); return this->send_response(sendL, 0, 0, status_vector, false);
} }
/* We've got a batch of segments. This is only slightly more complicated */ /* We've got a batch of segments. This is only slightly more complicated */
@ -3477,11 +3580,11 @@ ISC_STATUS rem_port::put_segment(P_OP op, P_SGMT * segment, PACKET* sendL)
reinterpret_cast<const char*>(p)); reinterpret_cast<const char*>(p));
THREAD_ENTER(); THREAD_ENTER();
if (status_vector[1]) if (status_vector[1])
return this->send_response(sendL, 0, 0, status_vector); return this->send_response(sendL, 0, 0, status_vector, false);
p += length; p += length;
} }
return this->send_response(sendL, 0, 0, status_vector); return this->send_response(sendL, 0, 0, status_vector, false);
} }
@ -3509,7 +3612,7 @@ ISC_STATUS rem_port::put_slice(P_SLC * stuff, PACKET* sendL)
RDB rdb = this->port_context; RDB rdb = this->port_context;
if (bad_db(status_vector, rdb)) if (bad_db(status_vector, rdb))
{ {
return this->send_response(sendL, 0, 0, status_vector); return this->send_response(sendL, 0, 0, status_vector, false);
} }
THREAD_EXIT(); THREAD_EXIT();
@ -3524,7 +3627,7 @@ ISC_STATUS rem_port::put_slice(P_SLC * stuff, PACKET* sendL)
stuff->p_slc_slice.lstr_address); stuff->p_slc_slice.lstr_address);
THREAD_ENTER(); THREAD_ENTER();
return this->send_response(sendL, 0, 0, status_vector); return this->send_response(sendL, 0, 0, status_vector, false);
} }
@ -3544,7 +3647,7 @@ ISC_STATUS rem_port::que_events(P_EVENT * stuff, PACKET* sendL)
RDB rdb = this->port_context; RDB rdb = this->port_context;
if (bad_db(status_vector, rdb)) if (bad_db(status_vector, rdb))
{ {
return this->send_response(sendL, 0, 0, status_vector); return this->send_response(sendL, 0, 0, status_vector, false);
} }
/* Find unused event block or, if necessary, a new one */ /* Find unused event block or, if necessary, a new one */
@ -3592,7 +3695,7 @@ ISC_STATUS rem_port::que_events(P_EVENT * stuff, PACKET* sendL)
event->rvnt_id = 0; event->rvnt_id = 0;
} }
return this->send_response(sendL, (OBJCT) id, 0, status_vector); return this->send_response(sendL, (OBJCT) id, 0, status_vector, false);
} }
@ -3625,7 +3728,7 @@ ISC_STATUS rem_port::receive_after_start( P_DATA* data,
USHORT msg_number; USHORT msg_number;
if (!get_next_msg_no(requestL, level, &msg_number)) { if (!get_next_msg_no(requestL, level, &msg_number)) {
return this->send_response(sendL, 0, 0, status_vector); return this->send_response(sendL, 0, 0, status_vector, false);
} }
sendL->p_operation = op_response_piggyback; sendL->p_operation = op_response_piggyback;
@ -3699,7 +3802,7 @@ ISC_STATUS rem_port::receive_msg(P_DATA * data, PACKET* sendL)
status_vector[0] = isc_arg_gds; status_vector[0] = isc_arg_gds;
status_vector[1] = isc_badmsgnum; status_vector[1] = isc_badmsgnum;
status_vector[2] = isc_arg_end; status_vector[2] = isc_arg_end;
return this->send_response(sendL, 0, 0, status_vector); return this->send_response(sendL, 0, 0, status_vector, false);
} }
rrq::rrq_repeat* tail = requestL->rrq_rpt + msg_number; rrq::rrq_repeat* tail = requestL->rrq_rpt + msg_number;
const rem_fmt* format = tail->rrq_format; const rem_fmt* format = tail->rrq_format;
@ -3751,7 +3854,8 @@ ISC_STATUS rem_port::receive_msg(P_DATA * data, PACKET* sendL)
if (requestL->rrq_status_vector[1]) { if (requestL->rrq_status_vector[1]) {
const ISC_STATUS res = const ISC_STATUS res =
this->send_response(sendL, 0, 0, this->send_response(sendL, 0, 0,
requestL->rrq_status_vector); requestL->rrq_status_vector,
false);
memset(requestL->rrq_status_vector, 0, memset(requestL->rrq_status_vector, 0,
sizeof(requestL->rrq_status_vector)); sizeof(requestL->rrq_status_vector));
return res; return res;
@ -3768,7 +3872,7 @@ ISC_STATUS rem_port::receive_msg(P_DATA * data, PACKET* sendL)
#endif #endif
THREAD_ENTER(); THREAD_ENTER();
if (status_vector[1]) if (status_vector[1])
return this->send_response(sendL, 0, 0, status_vector); return this->send_response(sendL, 0, 0, status_vector, false);
#ifdef SCROLLABLE_CURSORS #ifdef SCROLLABLE_CURSORS
/* set the appropriate flags according to the way we just scrolled /* set the appropriate flags according to the way we just scrolled
@ -4248,7 +4352,7 @@ ISC_STATUS rem_port::seek_blob(P_SEEK * seek, PACKET* sendL)
sendL->p_resp.p_resp_blob_id.bid_number = result; sendL->p_resp.p_resp_blob_id.bid_number = result;
return this->send_response(sendL, 0, 0, status_vector); return this->send_response(sendL, 0, 0, status_vector, false);
} }
@ -4280,7 +4384,7 @@ ISC_STATUS rem_port::send_msg(P_DATA * data, PACKET* sendL)
status_vector[0] = isc_arg_gds; status_vector[0] = isc_arg_gds;
status_vector[1] = isc_badmsgnum; status_vector[1] = isc_badmsgnum;
status_vector[2] = isc_arg_end; status_vector[2] = isc_arg_end;
return this->send_response(sendL, 0, 0, status_vector); return this->send_response(sendL, 0, 0, status_vector, false);
} }
REM_MSG message = requestL->rrq_rpt[number].rrq_message; REM_MSG message = requestL->rrq_rpt[number].rrq_message;
const rem_fmt* format = requestL->rrq_rpt[number].rrq_format; const rem_fmt* format = requestL->rrq_rpt[number].rrq_format;
@ -4292,14 +4396,15 @@ ISC_STATUS rem_port::send_msg(P_DATA * data, PACKET* sendL)
message->msg_address = NULL; message->msg_address = NULL;
return this->send_response(sendL, 0, 0, status_vector); return this->send_response(sendL, 0, 0, status_vector, false);
} }
ISC_STATUS rem_port::send_response( PACKET* sendL, ISC_STATUS rem_port::send_response( PACKET* sendL,
OBJCT object, OBJCT object,
USHORT length, USHORT length,
const ISC_STATUS* status_vector) const ISC_STATUS* status_vector,
bool defer_flag)
{ {
/************************************** /**************************************
* *
@ -4429,7 +4534,12 @@ ISC_STATUS rem_port::send_response( PACKET* sendL,
response->p_resp_status_vector = new_vector; response->p_resp_status_vector = new_vector;
response->p_resp_data.cstr_length = length; response->p_resp_data.cstr_length = length;
this->send(sendL); if ((this->port_flags & PORT_lazy) && defer_flag) {
this->send_partial(sendL);
}
else {
this->send(sendL);
}
return exit_code; return exit_code;
} }
@ -4535,7 +4645,7 @@ ISC_STATUS rem_port::service_attach(P_ATCH* attach, PACKET* sendL)
rdb->rdb_flags |= RDB_service; rdb->rdb_flags |= RDB_service;
} }
return this->send_response(sendL, 0, 0, status_vector); return this->send_response(sendL, 0, 0, status_vector, false);
} }
@ -4556,14 +4666,14 @@ ISC_STATUS rem_port::service_end(P_RLSE * release, PACKET* sendL)
RDB rdb = this->port_context; RDB rdb = this->port_context;
if (bad_service(status_vector, rdb)) if (bad_service(status_vector, rdb))
{ {
return this->send_response(sendL, 0, 0, status_vector); return this->send_response(sendL, 0, 0, status_vector, false);
} }
THREAD_EXIT(); THREAD_EXIT();
isc_service_detach(status_vector, &rdb->rdb_handle); isc_service_detach(status_vector, &rdb->rdb_handle);
THREAD_ENTER(); THREAD_ENTER();
return this->send_response(sendL, 0, 0, status_vector); return this->send_response(sendL, 0, 0, status_vector, false);
} }
@ -4584,7 +4694,7 @@ ISC_STATUS rem_port::service_start(P_INFO * stuff, PACKET* sendL)
RDB rdb = this->port_context; RDB rdb = this->port_context;
if (bad_service(status_vector, rdb)) if (bad_service(status_vector, rdb))
{ {
return this->send_response(sendL, 0, 0, status_vector); return this->send_response(sendL, 0, 0, status_vector, false);
} }
THREAD_EXIT(); THREAD_EXIT();
@ -4596,7 +4706,7 @@ ISC_STATUS rem_port::service_start(P_INFO * stuff, PACKET* sendL)
reinterpret_cast<char*>(stuff->p_info_items.cstr_address)); reinterpret_cast<char*>(stuff->p_info_items.cstr_address));
THREAD_ENTER(); THREAD_ENTER();
return this->send_response(sendL, 0, 0, status_vector); return this->send_response(sendL, 0, 0, status_vector, false);
} }
@ -4628,7 +4738,7 @@ ISC_STATUS rem_port::set_cursor(P_SQLCUR * sqlcur, PACKET* sendL)
sqlcur->p_sqlcur_type); sqlcur->p_sqlcur_type);
THREAD_ENTER(); THREAD_ENTER();
return this->send_response(sendL, 0, 0, status_vector); return this->send_response(sendL, 0, 0, status_vector, false);
} }
@ -4708,7 +4818,7 @@ ISC_STATUS rem_port::start(P_OP operation, P_DATA * data, PACKET* sendL)
return this->receive_after_start(data, sendL, status_vector); return this->receive_after_start(data, sendL, status_vector);
} }
return this->send_response(sendL, 0, 0, status_vector); return this->send_response(sendL, 0, 0, status_vector, false);
} }
@ -4748,7 +4858,7 @@ ISC_STATUS rem_port::start_and_send(P_OP operation,
status_vector[0] = isc_arg_gds; status_vector[0] = isc_arg_gds;
status_vector[1] = isc_badmsgnum; status_vector[1] = isc_badmsgnum;
status_vector[2] = isc_arg_end; status_vector[2] = isc_arg_end;
return this->send_response(sendL, 0, 0, status_vector); return this->send_response(sendL, 0, 0, status_vector, false);
} }
REM_MSG message = requestL->rrq_rpt[number].rrq_message; REM_MSG message = requestL->rrq_rpt[number].rrq_message;
const rem_fmt* format = requestL->rrq_rpt[number].rrq_format; const rem_fmt* format = requestL->rrq_rpt[number].rrq_format;
@ -4769,7 +4879,7 @@ ISC_STATUS rem_port::start_and_send(P_OP operation,
} }
} }
return this->send_response(sendL, 0, 0, status_vector); return this->send_response(sendL, 0, 0, status_vector, false);
} }
@ -4790,7 +4900,7 @@ ISC_STATUS rem_port::start_transaction(P_OP operation, P_STTR * stuff, PACKET* s
RDB rdb = this->port_context; RDB rdb = this->port_context;
if (bad_db(status_vector, rdb)) if (bad_db(status_vector, rdb))
{ {
return this->send_response(sendL, 0, 0, status_vector); return this->send_response(sendL, 0, 0, status_vector, false);
} }
FB_API_HANDLE handle = 0; FB_API_HANDLE handle = 0;
@ -4849,7 +4959,7 @@ ISC_STATUS rem_port::start_transaction(P_OP operation, P_STTR * stuff, PACKET* s
} }
} }
return this->send_response(sendL, object, 0, status_vector); return this->send_response(sendL, object, 0, status_vector, false);
} }
@ -5103,7 +5213,7 @@ ISC_STATUS rem_port::transact_request(P_TRRQ* trrq, PACKET* sendL)
RDB rdb = this->port_context; RDB rdb = this->port_context;
if (bad_db(status_vector, rdb)) if (bad_db(status_vector, rdb))
{ {
return this->send_response(sendL, 0, 0, status_vector); return this->send_response(sendL, 0, 0, status_vector, false);
} }
const UCHAR* blr = trrq->p_trrq_blr.cstr_address; const UCHAR* blr = trrq->p_trrq_blr.cstr_address;
@ -5131,7 +5241,7 @@ ISC_STATUS rem_port::transact_request(P_TRRQ* trrq, PACKET* sendL)
THREAD_ENTER(); THREAD_ENTER();
if (status_vector[1]) if (status_vector[1])
return this->send_response(sendL, 0, 0, status_vector); return this->send_response(sendL, 0, 0, status_vector, false);
P_DATA* data = &sendL->p_data; P_DATA* data = &sendL->p_data;
sendL->p_operation = op_transact_response; sendL->p_operation = op_transact_response;