2001-05-23 15:26:42 +02:00
|
|
|
/*
|
|
|
|
* PROGRAM: Dynamic SQL runtime support
|
2003-11-10 10:16:38 +01:00
|
|
|
* MODULE: user_dsql.cpp
|
2003-01-12 19:16:50 +01:00
|
|
|
* DESCRIPTION: Above the Y-valve entrypoints for DSQL
|
2001-05-23 15:26:42 +02:00
|
|
|
*
|
|
|
|
*
|
|
|
|
* This module contains DSQL related routines that sit on top
|
|
|
|
* of the Y-valve. This includes the original (pre-version 4)
|
|
|
|
* DSQL routines as well as the alternate VMS and Ada entrypoints
|
|
|
|
* of the new DSQL routines. The pre-version 4 entrypoints
|
|
|
|
* retain their "gds__" prefix while the new routines are prefixed
|
|
|
|
* with "isc_dsql_".
|
|
|
|
* The contents of this file are subject to the Interbase Public
|
|
|
|
* License Version 1.0 (the "License"); you may not use this file
|
|
|
|
* except in compliance with the License. You may obtain a copy
|
|
|
|
* of the License at http://www.Inprise.com/IPL.html
|
|
|
|
*
|
|
|
|
* Software distributed under the License is distributed on an
|
|
|
|
* "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express
|
|
|
|
* or implied. See the License for the specific language governing
|
|
|
|
* rights and limitations under the License.
|
|
|
|
*
|
|
|
|
* The Original Code was created by Inprise Corporation
|
|
|
|
* and its predecessors. Portions created by Inprise Corporation are
|
|
|
|
* Copyright (C) Inprise Corporation.
|
|
|
|
*
|
|
|
|
* All Rights Reserved.
|
|
|
|
* Contributor(s): ______________________________________.
|
2002-10-29 03:59:57 +01:00
|
|
|
*
|
|
|
|
* 2002.10.28 Sean Leyne - Code cleanup, removed obsolete "MPEXL" port
|
|
|
|
*
|
2002-10-30 07:40:58 +01:00
|
|
|
* 2002.10.29 Sean Leyne - Removed obsolete "Netware" port
|
|
|
|
*
|
2003-01-12 19:16:50 +01:00
|
|
|
* 2003.01.12 Alex Peshkoff - Code cleanup, bad level of indirection
|
|
|
|
*
|
2001-05-23 15:26:42 +02:00
|
|
|
*/
|
|
|
|
|
2001-07-30 01:43:24 +02:00
|
|
|
#include "firebird.h"
|
2004-04-29 00:00:03 +02:00
|
|
|
#include <stdio.h>
|
2001-05-23 15:26:42 +02:00
|
|
|
#include <stdlib.h>
|
|
|
|
#include "../jrd/common.h"
|
|
|
|
#include <stdarg.h>
|
|
|
|
#include "../dsql/dsql.h"
|
|
|
|
#include "../dsql/chars.h"
|
|
|
|
#include "../dsql/sqlda.h"
|
|
|
|
#include "../jrd/blr.h"
|
2001-07-30 01:43:24 +02:00
|
|
|
#include "gen/iberror.h"
|
2001-05-23 15:26:42 +02:00
|
|
|
#include "../jrd/align.h"
|
|
|
|
#include "../jrd/gds_proto.h"
|
|
|
|
#include "../jrd/why_proto.h"
|
|
|
|
#include "../dsql/user__proto.h"
|
|
|
|
|
|
|
|
#ifdef VMS
|
|
|
|
#include <descrip.h>
|
|
|
|
#endif
|
|
|
|
|
2003-09-28 02:36:28 +02:00
|
|
|
enum name_type {
|
|
|
|
NAME_statement = 1,
|
|
|
|
NAME_cursor = 2
|
|
|
|
};
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2004-05-03 01:06:37 +02:00
|
|
|
typedef FB_API_HANDLE HNDL;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
/* declare a structure which enables us to associate a cursor with a
|
|
|
|
statement and vice versa */
|
|
|
|
|
2003-11-28 07:48:34 +01:00
|
|
|
struct dsql_name; // fwd. decl.
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-11-28 07:48:34 +01:00
|
|
|
struct stmt
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2003-11-28 07:48:34 +01:00
|
|
|
stmt* stmt_next; // next in chain
|
|
|
|
dsql_name* stmt_stmt; // symbol table entry for statement name
|
|
|
|
dsql_name* stmt_cursor; // symbol table entry for cursor name
|
|
|
|
HNDL stmt_handle; // stmt handle returned by dsql_xxx
|
|
|
|
HNDL stmt_db_handle; // database handle for this statement
|
|
|
|
};
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-11-28 07:48:34 +01:00
|
|
|
// declare a structure to hold the cursor and statement names
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-11-28 07:48:34 +01:00
|
|
|
struct dsql_name
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2003-11-28 07:48:34 +01:00
|
|
|
dsql_name* name_next;
|
|
|
|
dsql_name* name_prev;
|
|
|
|
stmt* name_stmt;
|
2001-05-23 15:26:42 +02:00
|
|
|
USHORT name_length;
|
|
|
|
SCHAR name_symbol[1];
|
2003-11-28 07:48:34 +01:00
|
|
|
};
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
|
|
|
|
static void cleanup(void*);
|
2004-05-03 01:06:37 +02:00
|
|
|
static void cleanup_database(FB_API_HANDLE*, void*);
|
2006-05-19 17:17:02 +02:00
|
|
|
static ISC_STATUS error(const Firebird::Exception& ex);
|
2003-04-10 08:32:58 +02:00
|
|
|
static ISC_STATUS error();
|
|
|
|
static void error_post(ISC_STATUS, ...);
|
2003-11-28 07:48:34 +01:00
|
|
|
static dsql_name* lookup_name(const SCHAR*, dsql_name*);
|
|
|
|
static stmt* lookup_stmt(const SCHAR*, dsql_name*, name_type);
|
2004-05-03 01:06:37 +02:00
|
|
|
static void init(FB_API_HANDLE*);
|
2003-11-28 07:48:34 +01:00
|
|
|
static dsql_name* insert_name(const SCHAR*, dsql_name**, stmt*);
|
|
|
|
static USHORT name_length(const SCHAR*);
|
|
|
|
static void remove_name(dsql_name*, dsql_name**);
|
|
|
|
static bool scompare(const SCHAR*, USHORT, const SCHAR*, USHORT);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-11-28 07:48:34 +01:00
|
|
|
// declare the private data
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
#pragma FB_COMPILER_MESSAGE("Dragons ahead. Static data. Not thread safe!")
|
|
|
|
|
2003-11-28 07:48:34 +01:00
|
|
|
static bool init_flag = false; // whether we've been initialized
|
2003-12-03 09:19:24 +01:00
|
|
|
static dsql_err_stblock* UDSQL_error = NULL;
|
2003-11-28 07:48:34 +01:00
|
|
|
static stmt* statements = NULL;
|
|
|
|
static dsql_name* statement_names = NULL;
|
|
|
|
static dsql_name* cursor_names = NULL;
|
2004-02-02 12:02:12 +01:00
|
|
|
static dsql_dbb* databases = NULL;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-04-10 08:32:58 +02:00
|
|
|
static inline void set_global_private_status(ISC_STATUS* user_status, ISC_STATUS* local_status)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
UDSQL_error->dsql_user_status = user_status;
|
|
|
|
UDSQL_error->dsql_status = (user_status) ? user_status : local_status;
|
|
|
|
}
|
|
|
|
|
2003-04-10 08:32:58 +02:00
|
|
|
static inline void INIT_DSQL(ISC_STATUS* user_status, ISC_STATUS* local_status)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
init(0);
|
|
|
|
set_global_private_status(user_status, local_status);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// Close a dynamic SQL cursor.
|
|
|
|
//
|
2003-11-28 07:48:34 +01:00
|
|
|
ISC_STATUS API_ROUTINE isc_embed_dsql_close(ISC_STATUS* user_status, const SCHAR* name)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2003-04-16 12:18:51 +02:00
|
|
|
ISC_STATUS_ARRAY local_status;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2002-04-04 07:35:21 +02:00
|
|
|
INIT_DSQL(user_status, local_status);
|
|
|
|
try
|
|
|
|
{
|
|
|
|
// get the symbol table entry
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-11-28 07:48:34 +01:00
|
|
|
stmt* statement = lookup_stmt(name, cursor_names, NAME_cursor);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2002-04-04 07:35:21 +02:00
|
|
|
return isc_dsql_free_statement( user_status,
|
2002-12-16 16:38:26 +01:00
|
|
|
&statement->stmt_handle,
|
2001-05-23 15:26:42 +02:00
|
|
|
DSQL_close);
|
2002-04-04 07:35:21 +02:00
|
|
|
}
|
2006-05-19 17:17:02 +02:00
|
|
|
catch(const Firebird::Exception& ex)
|
2002-04-04 07:35:21 +02:00
|
|
|
{
|
2004-03-01 04:35:23 +01:00
|
|
|
return error(ex);
|
2002-04-04 07:35:21 +02:00
|
|
|
}
|
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// Declare a cursor for a dynamic request.
|
|
|
|
//
|
2003-04-10 08:32:58 +02:00
|
|
|
ISC_STATUS API_ROUTINE isc_embed_dsql_declare( ISC_STATUS* user_status,
|
2003-11-28 07:48:34 +01:00
|
|
|
const SCHAR* stmt_name,
|
|
|
|
const SCHAR* cursor)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2003-04-16 12:18:51 +02:00
|
|
|
ISC_STATUS_ARRAY local_status;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2002-04-04 07:35:21 +02:00
|
|
|
INIT_DSQL(user_status, local_status);
|
|
|
|
try
|
|
|
|
{
|
|
|
|
// get the symbol table entry
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-11-28 07:48:34 +01:00
|
|
|
stmt* statement = lookup_stmt(stmt_name, statement_names, NAME_statement);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-11-28 07:48:34 +01:00
|
|
|
const ISC_STATUS s =
|
2002-04-04 07:35:21 +02:00
|
|
|
isc_dsql_set_cursor_name(user_status,
|
2002-12-16 16:38:26 +01:00
|
|
|
&statement->stmt_handle,
|
2001-05-23 15:26:42 +02:00
|
|
|
cursor,
|
|
|
|
0);
|
2002-04-04 07:35:21 +02:00
|
|
|
if (s) {
|
|
|
|
return s;
|
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2002-04-04 07:35:21 +02:00
|
|
|
statement->stmt_cursor = insert_name(cursor, &cursor_names, statement);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2002-04-04 07:35:21 +02:00
|
|
|
return s;
|
|
|
|
}
|
2006-05-19 17:17:02 +02:00
|
|
|
catch(const Firebird::Exception& ex)
|
2002-04-04 07:35:21 +02:00
|
|
|
{
|
2004-03-01 04:35:23 +01:00
|
|
|
return error(ex);
|
2002-04-04 07:35:21 +02:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// Describe output parameters for a prepared statement.
|
|
|
|
//
|
2003-04-10 08:32:58 +02:00
|
|
|
ISC_STATUS API_ROUTINE isc_embed_dsql_describe(ISC_STATUS* user_status,
|
2003-11-28 07:48:34 +01:00
|
|
|
const SCHAR* stmt_name,
|
2001-05-23 15:26:42 +02:00
|
|
|
USHORT dialect, XSQLDA* sqlda)
|
|
|
|
{
|
2003-04-16 12:18:51 +02:00
|
|
|
ISC_STATUS_ARRAY local_status;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2002-04-04 07:35:21 +02:00
|
|
|
INIT_DSQL(user_status, local_status);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2002-04-04 07:35:21 +02:00
|
|
|
try
|
|
|
|
{
|
|
|
|
// get the symbol table entry
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-11-28 07:48:34 +01:00
|
|
|
stmt* statement = lookup_stmt(stmt_name, statement_names, NAME_statement);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2002-04-04 07:35:21 +02:00
|
|
|
return isc_dsql_describe(user_status,
|
2002-12-16 16:38:26 +01:00
|
|
|
&statement->stmt_handle,
|
2001-05-23 15:26:42 +02:00
|
|
|
dialect,
|
|
|
|
sqlda);
|
2002-04-04 07:35:21 +02:00
|
|
|
}
|
2006-05-19 17:17:02 +02:00
|
|
|
catch(const Firebird::Exception& ex)
|
2002-04-04 07:35:21 +02:00
|
|
|
{
|
2004-03-01 04:35:23 +01:00
|
|
|
return error(ex);
|
2002-04-04 07:35:21 +02:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// isc_embed_dsql_descr_bind
|
|
|
|
//
|
2003-04-10 08:32:58 +02:00
|
|
|
ISC_STATUS API_ROUTINE isc_embed_dsql_descr_bind( ISC_STATUS* user_status,
|
2003-11-28 07:48:34 +01:00
|
|
|
const SCHAR* stmt_name,
|
2001-05-23 15:26:42 +02:00
|
|
|
USHORT dialect,
|
|
|
|
XSQLDA* sqlda)
|
|
|
|
{
|
|
|
|
return isc_embed_dsql_describe_bind(user_status,
|
|
|
|
stmt_name,
|
|
|
|
dialect,
|
|
|
|
sqlda);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// Describe input parameters for a prepared statement.
|
|
|
|
//
|
2003-04-10 08:32:58 +02:00
|
|
|
ISC_STATUS API_ROUTINE isc_embed_dsql_describe_bind(ISC_STATUS* user_status,
|
2003-11-28 07:48:34 +01:00
|
|
|
const SCHAR* stmt_name,
|
2001-05-23 15:26:42 +02:00
|
|
|
USHORT dialect,
|
|
|
|
XSQLDA* sqlda)
|
|
|
|
{
|
2003-04-16 12:18:51 +02:00
|
|
|
ISC_STATUS_ARRAY local_status;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2002-04-04 07:35:21 +02:00
|
|
|
INIT_DSQL(user_status, local_status);
|
|
|
|
try
|
|
|
|
{
|
|
|
|
// get the symbol table entry
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-11-28 07:48:34 +01:00
|
|
|
stmt* statement = lookup_stmt(stmt_name, statement_names, NAME_statement);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2002-04-04 07:35:21 +02:00
|
|
|
return isc_dsql_describe_bind(user_status,
|
2002-12-16 16:38:26 +01:00
|
|
|
&statement->stmt_handle,
|
2001-05-23 15:26:42 +02:00
|
|
|
dialect,
|
|
|
|
sqlda);
|
2002-04-04 07:35:21 +02:00
|
|
|
}
|
2006-05-19 17:17:02 +02:00
|
|
|
catch(const Firebird::Exception& ex)
|
2002-04-04 07:35:21 +02:00
|
|
|
{
|
2004-03-01 04:35:23 +01:00
|
|
|
return error(ex);
|
2002-04-04 07:35:21 +02:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// Execute a non-SELECT dynamic SQL statement.
|
|
|
|
//
|
2003-04-10 08:32:58 +02:00
|
|
|
ISC_STATUS API_ROUTINE isc_embed_dsql_execute(ISC_STATUS* user_status,
|
2004-05-03 01:06:37 +02:00
|
|
|
FB_API_HANDLE* trans_handle,
|
2003-11-28 07:48:34 +01:00
|
|
|
const SCHAR* stmt_name,
|
2001-05-23 15:26:42 +02:00
|
|
|
USHORT dialect,
|
|
|
|
XSQLDA* sqlda)
|
|
|
|
{
|
|
|
|
return isc_embed_dsql_execute2( user_status,
|
|
|
|
trans_handle,
|
|
|
|
stmt_name,
|
|
|
|
dialect,
|
|
|
|
sqlda,
|
|
|
|
NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// Execute a non-SELECT dynamic SQL statement.
|
|
|
|
//
|
2003-04-10 08:32:58 +02:00
|
|
|
ISC_STATUS API_ROUTINE isc_embed_dsql_execute2(ISC_STATUS* user_status,
|
2004-05-03 01:06:37 +02:00
|
|
|
FB_API_HANDLE* trans_handle,
|
2003-11-28 07:48:34 +01:00
|
|
|
const SCHAR* stmt_name,
|
2001-05-23 15:26:42 +02:00
|
|
|
USHORT dialect,
|
|
|
|
XSQLDA* in_sqlda,
|
|
|
|
XSQLDA* out_sqlda)
|
|
|
|
{
|
2003-04-16 12:18:51 +02:00
|
|
|
ISC_STATUS_ARRAY local_status;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2002-04-04 07:35:21 +02:00
|
|
|
INIT_DSQL(user_status, local_status);
|
|
|
|
try
|
|
|
|
{
|
|
|
|
// get the symbol table entry
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-11-28 07:48:34 +01:00
|
|
|
stmt* statement = lookup_stmt(stmt_name, statement_names, NAME_statement);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2002-04-04 07:35:21 +02:00
|
|
|
return isc_dsql_execute2( user_status,
|
2002-12-16 16:38:26 +01:00
|
|
|
trans_handle,
|
|
|
|
&statement->stmt_handle,
|
2001-05-23 15:26:42 +02:00
|
|
|
dialect,
|
|
|
|
in_sqlda,
|
|
|
|
out_sqlda);
|
2002-04-04 07:35:21 +02:00
|
|
|
}
|
2006-05-19 17:17:02 +02:00
|
|
|
catch(const Firebird::Exception& ex)
|
2002-04-04 07:35:21 +02:00
|
|
|
{
|
2004-03-01 04:35:23 +01:00
|
|
|
return error(ex);
|
2002-04-04 07:35:21 +02:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// isc_embed_dsql_exec_immed
|
|
|
|
//
|
2003-04-10 08:32:58 +02:00
|
|
|
ISC_STATUS API_ROUTINE isc_embed_dsql_exec_immed(ISC_STATUS* user_status,
|
2004-05-03 01:06:37 +02:00
|
|
|
FB_API_HANDLE* db_handle,
|
|
|
|
FB_API_HANDLE* trans_handle,
|
2001-05-23 15:26:42 +02:00
|
|
|
USHORT length,
|
2003-11-28 07:48:34 +01:00
|
|
|
const SCHAR* string,
|
2001-05-23 15:26:42 +02:00
|
|
|
USHORT dialect,
|
|
|
|
XSQLDA* sqlda)
|
|
|
|
{
|
|
|
|
return isc_embed_dsql_execute_immed(user_status,
|
|
|
|
db_handle,
|
|
|
|
trans_handle,
|
|
|
|
length,
|
|
|
|
string,
|
|
|
|
dialect,
|
|
|
|
sqlda);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// Prepare a statement for execution.
|
|
|
|
//
|
2003-04-10 08:32:58 +02:00
|
|
|
ISC_STATUS API_ROUTINE isc_embed_dsql_execute_immed(ISC_STATUS* user_status,
|
2004-05-03 01:06:37 +02:00
|
|
|
FB_API_HANDLE* db_handle,
|
|
|
|
FB_API_HANDLE* trans_handle,
|
2001-05-23 15:26:42 +02:00
|
|
|
USHORT length,
|
2003-11-28 07:48:34 +01:00
|
|
|
const SCHAR* string,
|
2001-05-23 15:26:42 +02:00
|
|
|
USHORT dialect,
|
|
|
|
XSQLDA* sqlda)
|
|
|
|
{
|
|
|
|
return isc_embed_dsql_exec_immed2( user_status,
|
|
|
|
db_handle,
|
|
|
|
trans_handle,
|
|
|
|
length,
|
|
|
|
string,
|
|
|
|
dialect,
|
|
|
|
sqlda,
|
|
|
|
NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// Prepare a statement for execution.
|
|
|
|
//
|
2003-04-10 08:32:58 +02:00
|
|
|
ISC_STATUS API_ROUTINE isc_embed_dsql_exec_immed2( ISC_STATUS* user_status,
|
2004-05-03 01:06:37 +02:00
|
|
|
FB_API_HANDLE* db_handle,
|
|
|
|
FB_API_HANDLE* trans_handle,
|
2001-05-23 15:26:42 +02:00
|
|
|
USHORT length,
|
2003-11-28 07:48:34 +01:00
|
|
|
const SCHAR* string,
|
2001-05-23 15:26:42 +02:00
|
|
|
USHORT dialect,
|
|
|
|
XSQLDA* in_sqlda,
|
|
|
|
XSQLDA* out_sqlda)
|
|
|
|
{
|
|
|
|
return isc_dsql_exec_immed2(user_status,
|
2002-12-16 16:38:26 +01:00
|
|
|
db_handle,
|
|
|
|
trans_handle,
|
2001-05-23 15:26:42 +02:00
|
|
|
length,
|
|
|
|
string,
|
|
|
|
dialect,
|
|
|
|
in_sqlda,
|
|
|
|
out_sqlda);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef VMS
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// An execute immediate for COBOL to call
|
|
|
|
//
|
2003-04-10 08:32:58 +02:00
|
|
|
ISC_STATUS API_ROUTINE isc_embed_dsql_execute_immed_d(ISC_STATUS* user_status,
|
2004-05-03 01:06:37 +02:00
|
|
|
FB_API_HANDLE* db_handle,
|
|
|
|
FB_API_HANDLE* trans_handle,
|
2001-05-23 15:26:42 +02:00
|
|
|
struct dsc$descriptor_s *
|
|
|
|
string, USHORT dialect,
|
|
|
|
XSQLDA* sqlda)
|
|
|
|
{
|
|
|
|
return isc_embed_dsql_exec_immed2_d(user_status,
|
|
|
|
db_handle, trans_handle, string,
|
|
|
|
dialect, sqlda, NULL);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef VMS
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// An execute immediate for COBOL to call
|
|
|
|
//
|
2003-04-10 08:32:58 +02:00
|
|
|
ISC_STATUS API_ROUTINE isc_embed_dsql_exec_immed2_d(ISC_STATUS* user_status,
|
2004-05-03 01:06:37 +02:00
|
|
|
FB_API_HANDLE* db_handle,
|
|
|
|
FB_API_HANDLE* trans_handle,
|
2001-05-23 15:26:42 +02:00
|
|
|
struct dsc$descriptor_s *
|
|
|
|
string, USHORT dialect,
|
|
|
|
XSQLDA* in_sqlda,
|
|
|
|
XSQLDA* out_sqlda)
|
|
|
|
{
|
|
|
|
USHORT len = string->dsc$w_length;
|
|
|
|
|
|
|
|
return isc_embed_dsql_exec_immed2(user_status, db_handle,
|
|
|
|
trans_handle, len,
|
|
|
|
string->dsc$a_pointer, dialect,
|
|
|
|
in_sqlda, out_sqlda);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// Fetch next record from a dynamic SQL cursor
|
|
|
|
//
|
2003-04-10 08:32:58 +02:00
|
|
|
ISC_STATUS API_ROUTINE isc_embed_dsql_fetch(ISC_STATUS* user_status,
|
2003-11-28 07:48:34 +01:00
|
|
|
const SCHAR* cursor_name,
|
2001-05-23 15:26:42 +02:00
|
|
|
USHORT dialect, XSQLDA* sqlda)
|
|
|
|
{
|
2003-04-16 12:18:51 +02:00
|
|
|
ISC_STATUS_ARRAY local_status;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2002-04-04 07:35:21 +02:00
|
|
|
INIT_DSQL(user_status, local_status);
|
|
|
|
try
|
|
|
|
{
|
2003-11-28 07:48:34 +01:00
|
|
|
stmt* statement = lookup_stmt(cursor_name, cursor_names, NAME_cursor);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2002-04-04 07:35:21 +02:00
|
|
|
return isc_dsql_fetch(user_status,
|
2002-12-16 16:38:26 +01:00
|
|
|
&statement->stmt_handle,
|
2001-05-23 15:26:42 +02:00
|
|
|
dialect,
|
|
|
|
sqlda);
|
2002-04-04 07:35:21 +02:00
|
|
|
}
|
2006-05-19 17:17:02 +02:00
|
|
|
catch(const Firebird::Exception& ex)
|
2002-04-04 07:35:21 +02:00
|
|
|
{
|
2004-03-01 04:35:23 +01:00
|
|
|
return error(ex);
|
2002-04-04 07:35:21 +02:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef SCROLLABLE_CURSORS
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// Fetch next record from a dynamic SQL cursor
|
|
|
|
//
|
2003-04-10 08:32:58 +02:00
|
|
|
ISC_STATUS API_ROUTINE isc_embed_dsql_fetch2( ISC_STATUS* user_status,
|
2003-11-28 07:48:34 +01:00
|
|
|
const SCHAR* cursor_name,
|
2001-05-23 15:26:42 +02:00
|
|
|
USHORT dialect,
|
|
|
|
XSQLDA* sqlda,
|
|
|
|
USHORT direction,
|
|
|
|
SLONG offset)
|
|
|
|
{
|
2003-04-16 12:18:51 +02:00
|
|
|
ISC_STATUS_ARRAY local_status;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2002-04-04 07:35:21 +02:00
|
|
|
INIT_DSQL(user_status, local_status);
|
|
|
|
try
|
|
|
|
{
|
|
|
|
// get the symbol table entry
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-11-28 07:48:34 +01:00
|
|
|
stmt* statement = lookup_stmt(cursor_name, cursor_names, NAME_cursor);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2002-04-04 07:35:21 +02:00
|
|
|
return isc_dsql_fetch2( user_status,
|
2001-05-23 15:26:42 +02:00
|
|
|
&statement->stmt_handle,
|
|
|
|
dialect,
|
|
|
|
sqlda,
|
|
|
|
direction,
|
|
|
|
offset);
|
2002-04-04 07:35:21 +02:00
|
|
|
}
|
2006-05-19 17:17:02 +02:00
|
|
|
catch(const Firebird::Exception& ex)
|
2002-04-04 07:35:21 +02:00
|
|
|
{
|
2004-03-01 04:35:23 +01:00
|
|
|
return error(ex);
|
2002-04-04 07:35:21 +02:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// Fetch next record from a dynamic SQL cursor (ADA version)
|
|
|
|
//
|
2003-04-10 08:32:58 +02:00
|
|
|
ISC_STATUS API_ROUTINE isc_embed_dsql_fetch_a( ISC_STATUS* user_status,
|
2001-05-23 15:26:42 +02:00
|
|
|
int* sqlcode,
|
2003-11-28 07:48:34 +01:00
|
|
|
const SCHAR* cursor_name,
|
2001-05-23 15:26:42 +02:00
|
|
|
USHORT dialect,
|
|
|
|
XSQLDA* sqlda)
|
|
|
|
{
|
|
|
|
*sqlcode = 0;
|
|
|
|
|
2003-04-10 08:32:58 +02:00
|
|
|
ISC_STATUS s = isc_embed_dsql_fetch(user_status, cursor_name, dialect, sqlda);
|
2001-05-23 15:26:42 +02:00
|
|
|
if (s == 100) {
|
|
|
|
*sqlcode = 100;
|
|
|
|
}
|
|
|
|
|
2002-11-14 09:33:08 +01:00
|
|
|
return FB_SUCCESS;
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef SCROLLABLE_CURSORS
|
2003-04-10 08:32:58 +02:00
|
|
|
ISC_STATUS API_ROUTINE isc_embed_dsql_fetch2_a(ISC_STATUS* user_status,
|
2001-05-23 15:26:42 +02:00
|
|
|
int *sqlcode,
|
2003-11-28 07:48:34 +01:00
|
|
|
const SCHAR* cursor_name,
|
2001-05-23 15:26:42 +02:00
|
|
|
USHORT dialect,
|
|
|
|
XSQLDA* sqlda,
|
|
|
|
USHORT direction, SLONG offset)
|
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* i s c _ e m b e d _ d s q l _ f e t c h 2 _ a
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Fetch next record from a dynamic SQL cursor (ADA version)
|
|
|
|
*
|
|
|
|
**************************************/
|
2003-04-10 08:32:58 +02:00
|
|
|
ISC_STATUS s;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
*sqlcode = 0;
|
|
|
|
|
|
|
|
s =
|
|
|
|
isc_embed_dsql_fetch2(user_status, cursor_name, dialect, sqlda,
|
|
|
|
direction, offset);
|
|
|
|
if (s == 100)
|
|
|
|
*sqlcode = 100;
|
|
|
|
|
2002-11-14 09:33:08 +01:00
|
|
|
return FB_SUCCESS;
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
2003-04-10 08:32:58 +02:00
|
|
|
ISC_STATUS API_ROUTINE isc_embed_dsql_insert(ISC_STATUS* user_status,
|
2003-11-28 07:48:34 +01:00
|
|
|
const SCHAR* cursor_name,
|
2001-05-23 15:26:42 +02:00
|
|
|
USHORT dialect, XSQLDA* sqlda)
|
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* i s c _ e m b e d _ d s q l _ i n s e r t
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Insert next record into a dynamic SQL cursor
|
|
|
|
*
|
|
|
|
**************************************/
|
2003-04-16 12:18:51 +02:00
|
|
|
ISC_STATUS_ARRAY local_status;
|
2003-11-28 07:48:34 +01:00
|
|
|
stmt* statement;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2002-04-04 07:35:21 +02:00
|
|
|
INIT_DSQL(user_status, local_status);
|
|
|
|
try
|
|
|
|
{
|
2003-11-28 07:48:34 +01:00
|
|
|
// get the symbol table entry
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2002-04-04 07:35:21 +02:00
|
|
|
statement = lookup_stmt(cursor_name, cursor_names, NAME_cursor);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2002-04-04 07:35:21 +02:00
|
|
|
return isc_dsql_insert(user_status,
|
2002-12-16 16:38:26 +01:00
|
|
|
&statement->stmt_handle,
|
2001-05-23 15:26:42 +02:00
|
|
|
dialect,
|
|
|
|
sqlda);
|
2002-04-04 07:35:21 +02:00
|
|
|
}
|
2006-05-19 17:17:02 +02:00
|
|
|
catch(const Firebird::Exception& ex)
|
2002-04-04 07:35:21 +02:00
|
|
|
{
|
2004-03-01 04:35:23 +01:00
|
|
|
return error(ex);
|
2002-04-04 07:35:21 +02:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-11-28 07:48:34 +01:00
|
|
|
void API_ROUTINE isc_embed_dsql_length(const UCHAR* string, USHORT* length)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* i s c _ e m b e d _ d s q l _ l e n g t h
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Determine length of a ';' or null terminated string
|
|
|
|
*
|
|
|
|
**************************************/
|
2003-11-28 07:48:34 +01:00
|
|
|
const UCHAR* p;
|
2001-05-23 15:26:42 +02:00
|
|
|
for (p = string; *p && *p != ';'; p++)
|
|
|
|
if (classes[*p] & CHR_QUOTE) {
|
2003-11-28 07:48:34 +01:00
|
|
|
for (UCHAR prev = 0, quote = *p++; *p == quote || prev == quote;)
|
2001-05-23 15:26:42 +02:00
|
|
|
prev = *p++;
|
|
|
|
p--;
|
|
|
|
}
|
|
|
|
|
|
|
|
*length = p - string + 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-04-10 08:32:58 +02:00
|
|
|
ISC_STATUS API_ROUTINE isc_embed_dsql_open(ISC_STATUS* user_status,
|
2004-05-03 01:06:37 +02:00
|
|
|
FB_API_HANDLE* trans_handle,
|
2003-11-28 07:48:34 +01:00
|
|
|
const SCHAR* cursor_name,
|
2001-05-23 15:26:42 +02:00
|
|
|
USHORT dialect, XSQLDA* sqlda)
|
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* i s c _ e m b e d _ d s q l _ o p e n
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Open a dynamic SQL cursor.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
|
|
|
|
return isc_embed_dsql_open2(user_status, trans_handle, cursor_name,
|
|
|
|
dialect, sqlda, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-04-10 08:32:58 +02:00
|
|
|
ISC_STATUS API_ROUTINE isc_embed_dsql_open2(ISC_STATUS* user_status,
|
2004-05-03 01:06:37 +02:00
|
|
|
FB_API_HANDLE* trans_handle,
|
2003-11-28 07:48:34 +01:00
|
|
|
const SCHAR* cursor_name,
|
2001-05-23 15:26:42 +02:00
|
|
|
USHORT dialect,
|
|
|
|
XSQLDA* in_sqlda, XSQLDA* out_sqlda)
|
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* i s c _ e m b e d _ d s q l _ o p e n 2
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Open a dynamic SQL cursor.
|
|
|
|
*
|
|
|
|
**************************************/
|
2003-04-16 12:18:51 +02:00
|
|
|
ISC_STATUS_ARRAY local_status;
|
2003-11-28 07:48:34 +01:00
|
|
|
stmt* stmt;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2002-04-04 07:35:21 +02:00
|
|
|
INIT_DSQL(user_status, local_status);
|
|
|
|
try
|
|
|
|
{
|
2003-11-28 07:48:34 +01:00
|
|
|
// get the symbol table entry
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2002-04-04 07:35:21 +02:00
|
|
|
stmt = lookup_stmt(cursor_name, cursor_names, NAME_cursor);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2002-04-04 07:35:21 +02:00
|
|
|
return isc_dsql_execute2(user_status,
|
2002-12-16 16:38:26 +01:00
|
|
|
trans_handle,
|
|
|
|
&stmt->stmt_handle,
|
2001-05-23 15:26:42 +02:00
|
|
|
dialect, in_sqlda, out_sqlda);
|
2002-04-04 07:35:21 +02:00
|
|
|
}
|
2006-05-19 17:17:02 +02:00
|
|
|
catch(const Firebird::Exception& ex)
|
2002-04-04 07:35:21 +02:00
|
|
|
{
|
2004-03-01 04:35:23 +01:00
|
|
|
return error(ex);
|
2002-04-04 07:35:21 +02:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-04-10 08:32:58 +02:00
|
|
|
ISC_STATUS API_ROUTINE isc_embed_dsql_prepare(ISC_STATUS* user_status,
|
2004-05-03 01:06:37 +02:00
|
|
|
FB_API_HANDLE* db_handle,
|
|
|
|
FB_API_HANDLE* trans_handle,
|
2003-11-28 07:48:34 +01:00
|
|
|
const SCHAR* stmt_name,
|
2001-05-23 15:26:42 +02:00
|
|
|
USHORT length,
|
2003-11-28 07:48:34 +01:00
|
|
|
const SCHAR* string,
|
2001-05-23 15:26:42 +02:00
|
|
|
USHORT dialect,
|
|
|
|
XSQLDA* sqlda)
|
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* i s c _ e m b e d _ d s q l _ p r e p a r e
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Prepare a statement for execution.
|
|
|
|
*
|
|
|
|
**************************************/
|
2003-04-16 12:18:51 +02:00
|
|
|
ISC_STATUS s;
|
|
|
|
ISC_STATUS_ARRAY local_status, local_status2;
|
2003-11-28 07:48:34 +01:00
|
|
|
stmt* statement;
|
2001-05-23 15:26:42 +02:00
|
|
|
HNDL stmt_handle;
|
|
|
|
|
|
|
|
init(db_handle);
|
|
|
|
set_global_private_status(user_status, local_status);
|
|
|
|
|
2001-12-24 03:51:06 +01:00
|
|
|
try {
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-11-28 07:48:34 +01:00
|
|
|
dsql_name* name = lookup_name(stmt_name, statement_names);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
if (name && name->name_stmt->stmt_db_handle == *db_handle)
|
|
|
|
{
|
|
|
|
/* The statement name already exists for this database.
|
|
|
|
Re-use its statement handle. */
|
|
|
|
|
|
|
|
statement = name->name_stmt;
|
|
|
|
stmt_handle = statement->stmt_handle;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* This is a new statement name for this database.
|
|
|
|
Allocate a statement handle for it. */
|
|
|
|
|
|
|
|
if (name) {
|
|
|
|
isc_embed_dsql_release(user_status, stmt_name);
|
|
|
|
}
|
|
|
|
statement = NULL;
|
2004-05-03 01:06:37 +02:00
|
|
|
stmt_handle = 0;
|
2001-05-23 15:26:42 +02:00
|
|
|
s = isc_dsql_allocate_statement(user_status,
|
2002-12-16 16:38:26 +01:00
|
|
|
db_handle,
|
|
|
|
&stmt_handle);
|
2001-05-23 15:26:42 +02:00
|
|
|
if (s)
|
|
|
|
{
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
s = isc_dsql_prepare(user_status,
|
2002-12-16 16:38:26 +01:00
|
|
|
trans_handle,
|
|
|
|
&stmt_handle,
|
2001-05-23 15:26:42 +02:00
|
|
|
length, string, dialect, sqlda);
|
|
|
|
|
|
|
|
if (s) {
|
2003-11-28 07:48:34 +01:00
|
|
|
// An error occurred. Free any newly allocated statement handle.
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
if (!statement) {
|
|
|
|
isc_dsql_free_statement(local_status2,
|
2002-12-16 16:38:26 +01:00
|
|
|
&stmt_handle,
|
2001-05-23 15:26:42 +02:00
|
|
|
DSQL_drop);
|
|
|
|
}
|
|
|
|
return error();
|
|
|
|
}
|
|
|
|
|
|
|
|
/* If a new statement was allocated, add it to the symbol table and insert it
|
|
|
|
into the list of statements */
|
|
|
|
|
|
|
|
if (!statement)
|
|
|
|
{
|
2003-11-28 07:48:34 +01:00
|
|
|
statement = (stmt*) gds__alloc((SLONG) sizeof(stmt));
|
2004-03-07 08:58:55 +01:00
|
|
|
// FREE: by user calling isc_embed_dsql_release()
|
2003-11-28 07:48:34 +01:00
|
|
|
if (!statement) // NOMEM:
|
2001-05-23 15:26:42 +02:00
|
|
|
error_post(isc_virmemexh, 0);
|
|
|
|
|
|
|
|
#ifdef DEBUG_GDS_ALLOC
|
|
|
|
gds_alloc_flag_unfreed((void *) statement);
|
2003-11-28 07:48:34 +01:00
|
|
|
#endif // DEBUG_GDS_ALLOC
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
statement->stmt_next = statements;
|
|
|
|
statements = statement;
|
|
|
|
|
|
|
|
statement->stmt_db_handle = (HNDL) * db_handle;
|
|
|
|
statement->stmt_stmt =
|
|
|
|
insert_name(stmt_name, &statement_names, statement);
|
|
|
|
}
|
|
|
|
else if (statement->stmt_cursor)
|
|
|
|
remove_name(statement->stmt_cursor, &cursor_names);
|
|
|
|
|
|
|
|
statement->stmt_handle = stmt_handle;
|
|
|
|
statement->stmt_cursor = NULL;
|
|
|
|
|
|
|
|
return s;
|
2001-12-24 03:51:06 +01:00
|
|
|
|
|
|
|
} // try
|
2006-05-19 17:17:02 +02:00
|
|
|
catch (const Firebird::Exception& ex)
|
2001-12-24 03:51:06 +01:00
|
|
|
{
|
2004-03-01 04:35:23 +01:00
|
|
|
return error(ex);
|
2001-12-24 03:51:06 +01:00
|
|
|
}
|
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef VMS
|
2003-04-10 08:32:58 +02:00
|
|
|
ISC_STATUS API_ROUTINE isc_embed_dsql_prepare_d(ISC_STATUS* user_status,
|
2004-05-03 01:06:37 +02:00
|
|
|
FB_API_HANDLE* db_handle,
|
|
|
|
FB_API_HANDLE* trans_handle,
|
2001-05-23 15:26:42 +02:00
|
|
|
SCHAR* stmt_name,
|
|
|
|
struct dsc$descriptor_s * string,
|
|
|
|
USHORT dialect, XSQLDA* sqlda)
|
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* i s c _ e m b e d _ d s q l _ p r e p a r e _ d
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* A prepare for COBOL to call
|
|
|
|
*
|
|
|
|
**************************************/
|
2003-11-28 07:48:34 +01:00
|
|
|
const USHORT len = string->dsc$w_length;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
return isc_embed_dsql_prepare(user_status, db_handle,
|
|
|
|
trans_handle, stmt_name, len,
|
|
|
|
string->dsc$a_pointer, dialect, sqlda);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
2003-04-10 08:32:58 +02:00
|
|
|
ISC_STATUS API_ROUTINE isc_embed_dsql_release(ISC_STATUS* user_status,
|
2003-11-28 07:48:34 +01:00
|
|
|
const SCHAR* stmt_name)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* i s c _ e m b e d _ d s q l _ r e l e a s e
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Release request for a dsql statement
|
|
|
|
*
|
|
|
|
**************************************/
|
2003-04-16 12:18:51 +02:00
|
|
|
ISC_STATUS_ARRAY local_status;
|
2003-11-28 07:48:34 +01:00
|
|
|
stmt** stmt_ptr;
|
|
|
|
stmt* p;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2002-04-04 07:35:21 +02:00
|
|
|
INIT_DSQL(user_status, local_status);
|
|
|
|
try
|
|
|
|
{
|
2003-11-28 07:48:34 +01:00
|
|
|
// If a request already exists under that name, purge it out
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-11-28 07:48:34 +01:00
|
|
|
stmt* statement = lookup_stmt(stmt_name, statement_names, NAME_statement);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-04-10 08:32:58 +02:00
|
|
|
ISC_STATUS s =
|
2002-04-04 07:35:21 +02:00
|
|
|
isc_dsql_free_statement(user_status,
|
2002-12-16 16:38:26 +01:00
|
|
|
&statement->stmt_handle,
|
2001-05-23 15:26:42 +02:00
|
|
|
DSQL_drop);
|
2002-04-04 07:35:21 +02:00
|
|
|
if (s) {
|
|
|
|
return s;
|
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2002-04-04 07:35:21 +02:00
|
|
|
// remove the statement from the symbol tables
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2002-04-04 07:35:21 +02:00
|
|
|
if (statement->stmt_stmt)
|
|
|
|
remove_name(statement->stmt_stmt, &statement_names);
|
|
|
|
if (statement->stmt_cursor)
|
|
|
|
remove_name(statement->stmt_cursor, &cursor_names);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2002-04-04 07:35:21 +02:00
|
|
|
// and remove this statement from the local list
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2002-04-04 07:35:21 +02:00
|
|
|
for (stmt_ptr = &statements; p = *stmt_ptr; stmt_ptr = &p->stmt_next) {
|
|
|
|
if (p == statement) {
|
|
|
|
*stmt_ptr = statement->stmt_next;
|
|
|
|
gds__free(statement);
|
|
|
|
break;
|
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
2002-04-04 07:35:21 +02:00
|
|
|
return s;
|
|
|
|
}
|
2006-05-19 17:17:02 +02:00
|
|
|
catch(const Firebird::Exception& ex)
|
2002-04-04 07:35:21 +02:00
|
|
|
{
|
2004-03-01 04:35:23 +01:00
|
|
|
return error(ex);
|
2002-04-04 07:35:21 +02:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef VMS
|
|
|
|
int API_ROUTINE isc_dsql_execute_immediate_d(
|
2003-04-10 08:32:58 +02:00
|
|
|
ISC_STATUS* user_status,
|
2001-05-23 15:26:42 +02:00
|
|
|
int db_handle,
|
|
|
|
int trans_handle,
|
2003-11-28 07:48:34 +01:00
|
|
|
struct dsc$descriptor_s* string,
|
2001-05-23 15:26:42 +02:00
|
|
|
USHORT dialect, XSQLDA* sqlda)
|
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* i s c _ d s q l _ e x e c u t e _ i m m e d i a t e _ d
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* An execute immediate for COBOL to call
|
|
|
|
*
|
|
|
|
**************************************/
|
2003-11-28 07:48:34 +01:00
|
|
|
const USHORT len = string->dsc$w_length;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
return isc_dsql_execute_immediate(user_status, db_handle, trans_handle,
|
|
|
|
len, string->dsc$a_pointer, dialect,
|
|
|
|
sqlda);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
2003-04-10 08:32:58 +02:00
|
|
|
ISC_STATUS API_ROUTINE isc_dsql_fetch_a(ISC_STATUS* user_status,
|
2003-11-28 07:48:34 +01:00
|
|
|
int* sqlcode,
|
|
|
|
int* stmt_handle,
|
|
|
|
USHORT dialect, int* sqlda)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* i s c _ d s q l _ f e t c h _ a
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Fetch next record from a dynamic SQL cursor (ADA version)
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
*sqlcode = 0;
|
|
|
|
|
2003-11-28 07:48:34 +01:00
|
|
|
const ISC_STATUS s = isc_dsql_fetch( user_status,
|
2004-05-03 01:06:37 +02:00
|
|
|
reinterpret_cast<FB_API_HANDLE*>(stmt_handle),
|
2001-05-23 15:26:42 +02:00
|
|
|
dialect,
|
|
|
|
reinterpret_cast<XSQLDA*>(sqlda));
|
|
|
|
if (s == 100)
|
|
|
|
*sqlcode = 100;
|
|
|
|
|
2002-11-14 09:33:08 +01:00
|
|
|
return FB_SUCCESS;
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef SCROLLABLE_CURSORS
|
2003-04-10 08:32:58 +02:00
|
|
|
ISC_STATUS API_ROUTINE isc_dsql_fetch2_a(ISC_STATUS* user_status,
|
2001-05-23 15:26:42 +02:00
|
|
|
int *sqlcode,
|
|
|
|
int *stmt_handle,
|
|
|
|
USHORT dialect,
|
|
|
|
int *sqlda,
|
|
|
|
USHORT direction, SLONG offset)
|
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* i s c _ d s q l _ f e t c h 2 _ a
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Fetch next record from a dynamic SQL cursor (ADA version)
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
*sqlcode = 0;
|
|
|
|
|
2003-11-28 07:48:34 +01:00
|
|
|
const ISC_STATUS s =
|
2001-05-23 15:26:42 +02:00
|
|
|
isc_dsql_fetch2(user_status, stmt_handle, dialect, sqlda, direction,
|
|
|
|
offset);
|
|
|
|
if (s == 100)
|
|
|
|
*sqlcode = 100;
|
|
|
|
|
2002-11-14 09:33:08 +01:00
|
|
|
return FB_SUCCESS;
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef VMS
|
2003-04-10 08:32:58 +02:00
|
|
|
int API_ROUTINE isc_dsql_prepare_d( ISC_STATUS* user_status,
|
2001-05-23 15:26:42 +02:00
|
|
|
int trans_handle,
|
|
|
|
int stmt_handle,
|
|
|
|
struct dsc$descriptor_s* string,
|
|
|
|
USHORT dialect,
|
|
|
|
XSQLDA* sqlda)
|
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* i s c _ d s q l _ p r e p a r e _ d
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* A prepare for COBOL to call
|
|
|
|
*
|
|
|
|
**************************************/
|
2003-11-28 07:48:34 +01:00
|
|
|
const USHORT len = string->dsc$w_length;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
return isc_dsql_prepare(user_status, trans_handle, stmt_handle,
|
|
|
|
len, string->dsc$a_pointer, dialect, sqlda);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* i s c _ . . .
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* The following routines define the
|
|
|
|
* old isc_ entrypoints.
|
|
|
|
*
|
|
|
|
**************************************/
|
2003-11-28 07:48:34 +01:00
|
|
|
ISC_STATUS API_ROUTINE isc_close(ISC_STATUS* status_vector, const SCHAR* statement_name)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
return isc_embed_dsql_close(status_vector, statement_name);
|
|
|
|
}
|
|
|
|
|
2003-04-10 08:32:58 +02:00
|
|
|
ISC_STATUS API_ROUTINE isc_declare( ISC_STATUS* status_vector,
|
2003-11-28 07:48:34 +01:00
|
|
|
const SCHAR* statement_name,
|
|
|
|
const SCHAR* cursor_name)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
return isc_embed_dsql_declare(status_vector, statement_name, cursor_name);
|
|
|
|
}
|
|
|
|
|
2003-04-10 08:32:58 +02:00
|
|
|
ISC_STATUS API_ROUTINE isc_describe(ISC_STATUS* status_vector,
|
2003-11-28 07:48:34 +01:00
|
|
|
const SCHAR* statement_name, SQLDA* sqlda)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
return isc_embed_dsql_describe(status_vector,
|
|
|
|
statement_name,
|
2004-05-18 18:32:07 +02:00
|
|
|
DIALECT_sqlda,
|
2001-05-23 15:26:42 +02:00
|
|
|
reinterpret_cast<XSQLDA*>(sqlda));
|
|
|
|
}
|
|
|
|
|
2003-04-10 08:32:58 +02:00
|
|
|
ISC_STATUS API_ROUTINE isc_describe_bind(ISC_STATUS* status_vector,
|
2003-11-28 07:48:34 +01:00
|
|
|
const SCHAR* statement_name,
|
2001-05-23 15:26:42 +02:00
|
|
|
SQLDA* sqlda)
|
|
|
|
{
|
|
|
|
return isc_embed_dsql_describe_bind(status_vector,
|
|
|
|
statement_name,
|
2004-05-18 18:32:07 +02:00
|
|
|
DIALECT_sqlda,
|
2001-05-23 15:26:42 +02:00
|
|
|
reinterpret_cast<XSQLDA*>(sqlda));
|
|
|
|
}
|
|
|
|
|
2003-11-28 07:48:34 +01:00
|
|
|
ISC_STATUS API_ROUTINE isc_dsql_finish(HNDL* db_handle)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2003-04-10 08:32:58 +02:00
|
|
|
ISC_STATUS API_ROUTINE isc_execute(ISC_STATUS* status_vector,
|
2004-05-03 01:06:37 +02:00
|
|
|
FB_API_HANDLE* tra_handle,
|
2003-11-28 07:48:34 +01:00
|
|
|
const SCHAR* statement_name, SQLDA* sqlda)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
return isc_embed_dsql_execute(status_vector,
|
2003-01-12 19:16:50 +01:00
|
|
|
tra_handle,
|
2001-05-23 15:26:42 +02:00
|
|
|
statement_name,
|
2004-05-18 18:32:07 +02:00
|
|
|
DIALECT_sqlda,
|
2001-05-23 15:26:42 +02:00
|
|
|
reinterpret_cast<XSQLDA*>(sqlda));
|
|
|
|
}
|
|
|
|
|
2003-04-10 08:32:58 +02:00
|
|
|
ISC_STATUS API_ROUTINE isc_execute_immediate(ISC_STATUS* status_vector,
|
2004-05-03 01:06:37 +02:00
|
|
|
FB_API_HANDLE* db_handle,
|
|
|
|
FB_API_HANDLE* tra_handle,
|
2003-11-28 07:48:34 +01:00
|
|
|
SSHORT* sql_length, const SCHAR* sql)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
return isc_embed_dsql_execute_immed(status_vector,
|
2003-01-12 19:16:50 +01:00
|
|
|
db_handle, tra_handle,
|
2001-05-23 15:26:42 +02:00
|
|
|
(USHORT) ((sql_length) ? *sql_length :
|
|
|
|
0), sql,
|
2004-05-18 18:32:07 +02:00
|
|
|
DIALECT_sqlda, NULL);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef VMS
|
2003-04-10 08:32:58 +02:00
|
|
|
ISC_STATUS API_ROUTINE isc_execute_immediate_d(ISC_STATUS* status_vector,
|
2001-05-23 15:26:42 +02:00
|
|
|
SLONG* db_handle,
|
|
|
|
SLONG* tra_handle,
|
|
|
|
struct dsc$descriptor_s * string)
|
|
|
|
{
|
|
|
|
USHORT len;
|
|
|
|
|
|
|
|
len = string->dsc$w_length;
|
|
|
|
|
|
|
|
return isc_execute_immediate(status_vector,
|
|
|
|
db_handle,
|
|
|
|
tra_handle, &len, string->dsc$a_pointer);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2003-04-10 08:32:58 +02:00
|
|
|
ISC_STATUS API_ROUTINE isc_fetch(ISC_STATUS* status_vector,
|
2003-11-28 07:48:34 +01:00
|
|
|
const SCHAR* cursor_name, SQLDA* sqlda)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
return isc_embed_dsql_fetch(status_vector,
|
|
|
|
cursor_name,
|
2004-05-18 18:32:07 +02:00
|
|
|
DIALECT_sqlda,
|
2001-05-23 15:26:42 +02:00
|
|
|
reinterpret_cast<XSQLDA*>(sqlda));
|
|
|
|
}
|
|
|
|
|
2003-04-10 08:32:58 +02:00
|
|
|
ISC_STATUS API_ROUTINE isc_fetch_a(ISC_STATUS* status_vector,
|
2001-05-23 15:26:42 +02:00
|
|
|
int *sqlcode,
|
2003-11-28 07:48:34 +01:00
|
|
|
const SCHAR* cursor_name, SQLDA* sqlda)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
return isc_embed_dsql_fetch_a(status_vector,
|
|
|
|
sqlcode,
|
|
|
|
cursor_name,
|
2004-05-18 18:32:07 +02:00
|
|
|
DIALECT_sqlda,
|
2001-05-23 15:26:42 +02:00
|
|
|
reinterpret_cast<XSQLDA*>(sqlda));
|
|
|
|
}
|
|
|
|
|
2003-04-10 08:32:58 +02:00
|
|
|
ISC_STATUS API_ROUTINE isc_open(ISC_STATUS* status_vector,
|
2004-05-03 01:06:37 +02:00
|
|
|
FB_API_HANDLE* tra_handle,
|
2003-11-28 07:48:34 +01:00
|
|
|
const SCHAR* cursor_name, SQLDA* sqlda)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
return isc_embed_dsql_open(status_vector,
|
2003-01-12 19:16:50 +01:00
|
|
|
tra_handle,
|
2001-05-23 15:26:42 +02:00
|
|
|
cursor_name,
|
2004-05-18 18:32:07 +02:00
|
|
|
DIALECT_sqlda,
|
2001-05-23 15:26:42 +02:00
|
|
|
reinterpret_cast<XSQLDA*>(sqlda));
|
|
|
|
}
|
|
|
|
|
2003-04-10 08:32:58 +02:00
|
|
|
ISC_STATUS API_ROUTINE isc_prepare( ISC_STATUS* status_vector,
|
2004-05-03 01:06:37 +02:00
|
|
|
FB_API_HANDLE* db_handle,
|
|
|
|
FB_API_HANDLE* tra_handle,
|
2003-11-28 07:48:34 +01:00
|
|
|
const SCHAR* statement_name,
|
2001-05-23 15:26:42 +02:00
|
|
|
SSHORT* sql_length,
|
2003-11-28 07:48:34 +01:00
|
|
|
const SCHAR* sql,
|
2001-05-23 15:26:42 +02:00
|
|
|
SQLDA* sqlda)
|
|
|
|
{
|
|
|
|
return isc_embed_dsql_prepare( status_vector,
|
2003-01-12 19:16:50 +01:00
|
|
|
db_handle,
|
|
|
|
tra_handle,
|
2001-05-23 15:26:42 +02:00
|
|
|
statement_name,
|
|
|
|
(USHORT) ((sql_length) ? *sql_length : 0),
|
|
|
|
sql,
|
2004-05-18 18:32:07 +02:00
|
|
|
DIALECT_sqlda,
|
2001-05-23 15:26:42 +02:00
|
|
|
reinterpret_cast<XSQLDA*>(sqlda));
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef VMS
|
2003-04-10 08:32:58 +02:00
|
|
|
ISC_STATUS API_ROUTINE isc_prepare_d(ISC_STATUS* status_vector,
|
2001-05-23 15:26:42 +02:00
|
|
|
SLONG* db_handle,
|
|
|
|
SLONG* tra_handle,
|
|
|
|
SCHAR* statement_name,
|
|
|
|
struct dsc$descriptor_s * string,
|
|
|
|
SQLDA* sqlda)
|
|
|
|
{
|
|
|
|
USHORT len;
|
|
|
|
|
|
|
|
len = string->dsc$w_length;
|
|
|
|
|
|
|
|
return isc_prepare(status_vector,
|
|
|
|
db_handle,
|
|
|
|
tra_handle,
|
|
|
|
statement_name, &len, string->dsc$a_pointer, sqlda);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2003-04-10 08:32:58 +02:00
|
|
|
ISC_STATUS API_ROUTINE isc_dsql_release(ISC_STATUS* status_vector,
|
2003-11-28 07:48:34 +01:00
|
|
|
const SCHAR* statement_name)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
return isc_embed_dsql_release(status_vector, statement_name);
|
|
|
|
}
|
|
|
|
|
|
|
|
int API_ROUTINE isc_to_sqlda( SQLDA* sqlda,
|
|
|
|
int number,
|
|
|
|
SCHAR* host_var,
|
|
|
|
int host_var_size,
|
|
|
|
SCHAR* name)
|
|
|
|
{
|
2003-11-28 07:48:34 +01:00
|
|
|
// no longer supported
|
2001-05-23 15:26:42 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// gds_...
|
|
|
|
//
|
|
|
|
// The following routines define the gds__ style names for isc_ entrypoints.
|
|
|
|
//
|
|
|
|
// Please note that these names - strictly speaking - are illegal C++
|
|
|
|
// identifiers, and as such should probably be moved into a C file.
|
|
|
|
//
|
|
|
|
|
2003-11-28 07:48:34 +01:00
|
|
|
ISC_STATUS API_ROUTINE gds__close(ISC_STATUS* status_vector, const SCHAR* statement_name)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
return isc_close(status_vector, statement_name);
|
|
|
|
}
|
|
|
|
|
2003-04-10 08:32:58 +02:00
|
|
|
ISC_STATUS API_ROUTINE gds__declare(ISC_STATUS* status_vector,
|
2003-11-28 07:48:34 +01:00
|
|
|
const SCHAR* statement_name,
|
|
|
|
const SCHAR* cursor_name)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
return isc_declare(status_vector, statement_name, cursor_name);
|
|
|
|
}
|
|
|
|
|
2003-04-10 08:32:58 +02:00
|
|
|
ISC_STATUS API_ROUTINE gds__describe( ISC_STATUS* status_vector,
|
2003-11-28 07:48:34 +01:00
|
|
|
const SCHAR* statement_name,
|
2001-05-23 15:26:42 +02:00
|
|
|
SQLDA* sqlda)
|
|
|
|
{
|
|
|
|
return isc_describe(status_vector, statement_name, sqlda);
|
|
|
|
}
|
|
|
|
|
2003-04-10 08:32:58 +02:00
|
|
|
ISC_STATUS API_ROUTINE gds__describe_bind(ISC_STATUS* status_vector,
|
2003-11-28 07:48:34 +01:00
|
|
|
const SCHAR* statement_name,
|
2001-05-23 15:26:42 +02:00
|
|
|
SQLDA* sqlda)
|
|
|
|
{
|
|
|
|
return isc_describe_bind(status_vector, statement_name, sqlda);
|
|
|
|
}
|
|
|
|
|
2003-04-10 08:32:58 +02:00
|
|
|
ISC_STATUS API_ROUTINE gds__dsql_finish(HNDL* db_handle)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
return isc_dsql_finish(db_handle);
|
|
|
|
}
|
|
|
|
|
2003-04-10 08:32:58 +02:00
|
|
|
ISC_STATUS API_ROUTINE gds__execute(ISC_STATUS* status_vector,
|
2004-05-03 01:06:37 +02:00
|
|
|
FB_API_HANDLE* tra_handle,
|
2003-11-28 07:48:34 +01:00
|
|
|
const SCHAR* statement_name,
|
2001-05-23 15:26:42 +02:00
|
|
|
SQLDA* sqlda)
|
|
|
|
{
|
|
|
|
return isc_execute(status_vector, tra_handle, statement_name, sqlda);
|
|
|
|
}
|
|
|
|
|
2003-04-10 08:32:58 +02:00
|
|
|
ISC_STATUS API_ROUTINE gds__execute_immediate(ISC_STATUS* status_vector,
|
2004-05-03 01:06:37 +02:00
|
|
|
FB_API_HANDLE* db_handle,
|
|
|
|
FB_API_HANDLE* tra_handle,
|
2001-05-23 15:26:42 +02:00
|
|
|
SSHORT* sql_length,
|
2003-11-28 07:48:34 +01:00
|
|
|
const SCHAR* sql)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
return isc_execute_immediate( status_vector,
|
|
|
|
db_handle,
|
|
|
|
tra_handle,
|
|
|
|
sql_length,
|
|
|
|
sql);
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef VMS
|
2003-04-10 08:32:58 +02:00
|
|
|
ISC_STATUS API_ROUTINE gds__execute_immediate_d(ISC_STATUS* status_vector,
|
2001-05-23 15:26:42 +02:00
|
|
|
SLONG* db_handle,
|
|
|
|
SLONG* tra_handle,
|
2003-11-28 07:48:34 +01:00
|
|
|
const SCHAR* sql_string)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
return isc_execute_immediate_d(status_vector,
|
|
|
|
db_handle, tra_handle, sql_string);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2003-04-10 08:32:58 +02:00
|
|
|
ISC_STATUS API_ROUTINE gds__fetch(ISC_STATUS* status_vector,
|
2003-11-28 07:48:34 +01:00
|
|
|
const SCHAR* statement_name,
|
2001-05-23 15:26:42 +02:00
|
|
|
SQLDA* sqlda)
|
|
|
|
{
|
|
|
|
return isc_fetch(status_vector, statement_name, sqlda);
|
|
|
|
}
|
|
|
|
|
2003-04-10 08:32:58 +02:00
|
|
|
ISC_STATUS API_ROUTINE gds__fetch_a(ISC_STATUS* status_vector,
|
2001-05-23 15:26:42 +02:00
|
|
|
int* sqlcode,
|
2003-11-28 07:48:34 +01:00
|
|
|
const SCHAR* statement_name,
|
2001-05-23 15:26:42 +02:00
|
|
|
SQLDA* sqlda)
|
|
|
|
{
|
|
|
|
return isc_fetch_a(status_vector, sqlcode, statement_name, sqlda);
|
|
|
|
}
|
|
|
|
|
2003-04-10 08:32:58 +02:00
|
|
|
ISC_STATUS API_ROUTINE gds__open(ISC_STATUS* status_vector,
|
2004-05-03 01:06:37 +02:00
|
|
|
FB_API_HANDLE* tra_handle,
|
2003-11-28 07:48:34 +01:00
|
|
|
const SCHAR* cursor_name,
|
2001-05-23 15:26:42 +02:00
|
|
|
SQLDA* sqlda)
|
|
|
|
{
|
|
|
|
return isc_open(status_vector, tra_handle, cursor_name, sqlda);
|
|
|
|
}
|
|
|
|
|
2003-04-10 08:32:58 +02:00
|
|
|
ISC_STATUS API_ROUTINE gds__prepare(ISC_STATUS* status_vector,
|
2004-05-03 01:06:37 +02:00
|
|
|
FB_API_HANDLE* db_handle,
|
|
|
|
FB_API_HANDLE* tra_handle,
|
2003-11-28 07:48:34 +01:00
|
|
|
const SCHAR* statement_name,
|
2001-05-23 15:26:42 +02:00
|
|
|
SSHORT* sql_length,
|
2003-11-28 07:48:34 +01:00
|
|
|
const SCHAR* sql,
|
2001-05-23 15:26:42 +02:00
|
|
|
SQLDA* sqlda)
|
|
|
|
{
|
|
|
|
return isc_prepare( status_vector,
|
|
|
|
db_handle,
|
|
|
|
tra_handle,
|
|
|
|
statement_name,
|
|
|
|
sql_length,
|
|
|
|
sql,
|
|
|
|
sqlda);
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef VMS
|
2003-04-10 08:32:58 +02:00
|
|
|
ISC_STATUS API_ROUTINE gds__prepare_d(ISC_STATUS* status_vector,
|
2001-05-23 15:26:42 +02:00
|
|
|
SLONG* db_handle,
|
|
|
|
SLONG* tra_handle,
|
|
|
|
SCHAR* statement_name,
|
|
|
|
SLONG* sql_desc, SQLDA* sqlda)
|
|
|
|
{
|
|
|
|
return isc_prepare_d(status_vector,
|
|
|
|
db_handle,
|
|
|
|
tra_handle, statement_name, sql_desc, sqlda);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2003-04-10 08:32:58 +02:00
|
|
|
ISC_STATUS API_ROUTINE gds__to_sqlda(SQLDA* sqlda,
|
2001-05-23 15:26:42 +02:00
|
|
|
int number,
|
|
|
|
SCHAR* host_variable,
|
|
|
|
int host_variable_size,
|
|
|
|
SCHAR* host_variable_name)
|
|
|
|
{
|
|
|
|
return isc_to_sqlda(sqlda,
|
|
|
|
number,
|
|
|
|
host_variable,
|
|
|
|
host_variable_size, host_variable_name);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// Helper functions for cleanup().
|
|
|
|
//
|
2004-05-12 21:23:17 +02:00
|
|
|
static void free_all_databases(dsql_dbb*& databasesL)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2004-05-12 21:23:17 +02:00
|
|
|
while (databasesL) {
|
|
|
|
dsql_dbb* database = databasesL;
|
|
|
|
databasesL = database->dbb_next;
|
2001-05-23 15:26:42 +02:00
|
|
|
gds__free(database);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-05-12 21:23:17 +02:00
|
|
|
static void free_all_statements(stmt*& statementsL)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2004-05-12 21:23:17 +02:00
|
|
|
while (statementsL) {
|
|
|
|
stmt* statement = statementsL;
|
|
|
|
statementsL = statement->stmt_next;
|
2001-05-23 15:26:42 +02:00
|
|
|
gds__free(statement);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-11-28 07:48:34 +01:00
|
|
|
static void free_all_names(dsql_name*& names)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
while (names) {
|
2003-11-28 07:48:34 +01:00
|
|
|
dsql_name* name = names;
|
2001-05-23 15:26:42 +02:00
|
|
|
names = name->name_next;
|
|
|
|
gds__free(name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// Cleanup handler to free all dynamically allocated memory.
|
|
|
|
//
|
|
|
|
static void cleanup(void* arg)
|
|
|
|
{
|
|
|
|
if (!init_flag) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2003-09-04 23:26:15 +02:00
|
|
|
init_flag = false;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
gds__free(UDSQL_error);
|
|
|
|
UDSQL_error = NULL;
|
|
|
|
|
|
|
|
free_all_databases(databases);
|
|
|
|
free_all_statements(statements);
|
|
|
|
free_all_names(statement_names);
|
|
|
|
free_all_names(cursor_names);
|
|
|
|
|
|
|
|
gds__unregister_cleanup(cleanup, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// the cleanup handler called when a database is closed
|
|
|
|
//
|
2004-05-03 01:06:37 +02:00
|
|
|
static void cleanup_database(FB_API_HANDLE* db_handle, void* dummy)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
if (!db_handle || !databases) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// for each of the statements in this database, remove it
|
|
|
|
// from the local list and from the hash table
|
|
|
|
|
2003-11-28 07:48:34 +01:00
|
|
|
stmt** stmt_ptr = &statements;
|
|
|
|
stmt* p;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
while (p = *stmt_ptr)
|
|
|
|
{
|
|
|
|
if (p->stmt_db_handle == *db_handle)
|
|
|
|
{
|
|
|
|
*stmt_ptr = p->stmt_next;
|
|
|
|
if (p->stmt_stmt) {
|
|
|
|
remove_name(p->stmt_stmt, &statement_names);
|
|
|
|
}
|
|
|
|
if (p->stmt_cursor) {
|
|
|
|
remove_name(p->stmt_cursor, &cursor_names);
|
|
|
|
}
|
|
|
|
gds__free(p);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
stmt_ptr = &p->stmt_next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-02-02 12:02:12 +01:00
|
|
|
dsql_dbb* dbb;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2004-02-02 12:02:12 +01:00
|
|
|
for (dsql_dbb** dbb_ptr = &databases; dbb = *dbb_ptr; dbb_ptr = &dbb->dbb_next)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
if (dbb->dbb_database_handle == *db_handle)
|
|
|
|
{
|
|
|
|
*dbb_ptr = dbb->dbb_next;
|
|
|
|
gds__free(dbb);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// An error returned has been trapped. If the user specified
|
|
|
|
// a status vector, return a status code. Otherwise print the
|
|
|
|
// error code(s) and abort.
|
|
|
|
//
|
2006-05-19 17:17:02 +02:00
|
|
|
static ISC_STATUS error(const Firebird::Exception& ex)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
if (UDSQL_error->dsql_user_status) {
|
2004-03-01 04:35:23 +01:00
|
|
|
Firebird::stuff_exception(UDSQL_error->dsql_user_status, ex);
|
2001-05-23 15:26:42 +02:00
|
|
|
return UDSQL_error->dsql_user_status[1];
|
|
|
|
}
|
|
|
|
|
2004-03-01 04:35:23 +01:00
|
|
|
Firebird::stuff_exception(UDSQL_error->dsql_status, ex);
|
2001-05-23 15:26:42 +02:00
|
|
|
gds__print_status(UDSQL_error->dsql_status);
|
|
|
|
|
|
|
|
exit(UDSQL_error->dsql_status[1]);
|
|
|
|
}
|
|
|
|
|
2004-03-07 08:58:55 +01:00
|
|
|
|
2004-03-01 04:35:23 +01:00
|
|
|
static ISC_STATUS error()
|
|
|
|
{
|
|
|
|
if (UDSQL_error->dsql_user_status) {
|
|
|
|
return UDSQL_error->dsql_user_status[1];
|
|
|
|
}
|
|
|
|
|
|
|
|
gds__print_status(UDSQL_error->dsql_status);
|
|
|
|
|
|
|
|
exit(UDSQL_error->dsql_status[1]);
|
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// Post an error sequence to the status vector. Since an error
|
|
|
|
// sequence can, in theory, be arbitrarily lock, pull a cheap
|
|
|
|
// trick to get the address of the argument vector.
|
|
|
|
//
|
|
|
|
// this is a copy of the routine found in err.c with the
|
|
|
|
// exception that it uses a different error block - one which
|
|
|
|
// is local to the V3 DSQL routines...
|
|
|
|
//
|
2003-04-10 08:32:58 +02:00
|
|
|
static void error_post(ISC_STATUS status, ...)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
va_list args;
|
2003-04-10 08:32:58 +02:00
|
|
|
ISC_STATUS* p;
|
2001-05-23 15:26:42 +02:00
|
|
|
int type;
|
|
|
|
|
|
|
|
/* Get the addresses of the argument vector and the status vector, and do
|
|
|
|
word-wise copy. */
|
|
|
|
|
2004-05-24 01:28:06 +02:00
|
|
|
va_start(args, status);
|
2001-05-23 15:26:42 +02:00
|
|
|
p = UDSQL_error->dsql_status;
|
|
|
|
|
2003-11-28 07:48:34 +01:00
|
|
|
// Copy first argument
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-11-11 13:19:20 +01:00
|
|
|
*p++ = isc_arg_gds;
|
2001-05-23 15:26:42 +02:00
|
|
|
*p++ = status;
|
|
|
|
|
2003-11-28 07:48:34 +01:00
|
|
|
// Pick up remaining args
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
while (type = va_arg(args, int))
|
|
|
|
{
|
|
|
|
switch (*p++ = type) {
|
2003-11-11 13:19:20 +01:00
|
|
|
case isc_arg_gds:
|
2003-04-10 08:32:58 +02:00
|
|
|
*p++ = (ISC_STATUS) va_arg(args, ISC_STATUS);
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
2003-11-11 13:19:20 +01:00
|
|
|
case isc_arg_number:
|
2003-04-10 08:32:58 +02:00
|
|
|
*p++ = (ISC_STATUS) va_arg(args, SLONG);
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
2003-11-11 13:19:20 +01:00
|
|
|
case isc_arg_vms:
|
|
|
|
case isc_arg_unix:
|
|
|
|
case isc_arg_win32:
|
2001-05-23 15:26:42 +02:00
|
|
|
*p++ = va_arg(args, int);
|
|
|
|
break;
|
|
|
|
|
2003-11-11 13:19:20 +01:00
|
|
|
case isc_arg_string:
|
|
|
|
case isc_arg_interpreted:
|
2004-03-07 08:58:55 +01:00
|
|
|
*p++ = (ISC_STATUS)(IPTR) va_arg(args, TEXT *);
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
2003-11-11 13:19:20 +01:00
|
|
|
case isc_arg_cstring:
|
2003-04-10 08:32:58 +02:00
|
|
|
*p++ = (ISC_STATUS) va_arg(args, int);
|
2004-03-07 08:58:55 +01:00
|
|
|
*p++ = (ISC_STATUS)(IPTR) va_arg(args, TEXT *);
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-09-25 12:28:09 +02:00
|
|
|
va_end(args);
|
2003-11-11 13:19:20 +01:00
|
|
|
*p = isc_arg_end;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
// Give up whatever we were doing and return to the user.
|
|
|
|
|
2004-03-01 04:35:23 +01:00
|
|
|
Firebird::status_exception::raise(UDSQL_error->dsql_status);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// Initialize dynamic SQL. This is called only once.
|
|
|
|
//
|
2004-05-03 01:06:37 +02:00
|
|
|
static void init(FB_API_HANDLE* db_handle)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
// If we haven't been initialized yet, do it now
|
|
|
|
if (!init_flag)
|
|
|
|
{
|
2003-12-03 09:19:24 +01:00
|
|
|
UDSQL_error = (dsql_err_stblock*) gds__alloc((SLONG) sizeof(dsql_err_stblock));
|
2001-05-23 15:26:42 +02:00
|
|
|
// FREE: by exit cleanup()
|
|
|
|
if (!UDSQL_error) { // NOMEM:
|
|
|
|
return; // Don't set the init_flag
|
|
|
|
}
|
2003-09-04 23:26:15 +02:00
|
|
|
init_flag = true;
|
2001-05-23 15:26:42 +02:00
|
|
|
gds__register_cleanup(cleanup, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!db_handle) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2004-02-02 12:02:12 +01:00
|
|
|
dsql_dbb* dbb;
|
2001-05-23 15:26:42 +02:00
|
|
|
for (dbb = databases; dbb; dbb = dbb->dbb_next) {
|
|
|
|
if (dbb->dbb_database_handle == *db_handle) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-03-05 08:33:22 +01:00
|
|
|
dbb = (dsql_dbb*) gds__alloc((SLONG) sizeof(dsql_dbb));
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
// FREE: by database exit handler cleanup_database()
|
|
|
|
if (!dbb) { // NOMEM
|
|
|
|
return; // Not a great error handler
|
|
|
|
}
|
|
|
|
|
|
|
|
dbb->dbb_next = databases;
|
|
|
|
databases = dbb;
|
|
|
|
dbb->dbb_database_handle = *db_handle;
|
|
|
|
|
2003-04-16 12:18:51 +02:00
|
|
|
ISC_STATUS_ARRAY local_status;
|
2003-11-09 16:38:03 +01:00
|
|
|
isc_database_cleanup(local_status, db_handle, cleanup_database, NULL);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-11-28 07:48:34 +01:00
|
|
|
static dsql_name* insert_name(const TEXT* symbol_name, dsql_name** list_ptr, stmt* stmt)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* i n s e r t _ n a m e
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Add the name to the designated list.
|
|
|
|
*
|
|
|
|
**************************************/
|
2003-11-28 07:48:34 +01:00
|
|
|
USHORT l = name_length(symbol_name);
|
2004-03-07 08:58:55 +01:00
|
|
|
dsql_name* name = (dsql_name*) gds__alloc((SLONG) sizeof(dsql_name) + l);
|
|
|
|
// FREE: by exit handler cleanup() or database_cleanup()
|
2003-11-28 07:48:34 +01:00
|
|
|
if (!name) // NOMEM:
|
2003-11-11 13:19:20 +01:00
|
|
|
error_post(isc_virmemexh, 0);
|
2001-05-23 15:26:42 +02:00
|
|
|
name->name_stmt = stmt;
|
|
|
|
name->name_length = l;
|
2003-11-28 07:48:34 +01:00
|
|
|
TEXT* p = name->name_symbol;
|
2001-05-23 15:26:42 +02:00
|
|
|
while (l--)
|
2003-11-28 07:48:34 +01:00
|
|
|
*p++ = *symbol_name++;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
if (name->name_next = *list_ptr)
|
|
|
|
name->name_next->name_prev = name;
|
|
|
|
*list_ptr = name;
|
|
|
|
name->name_prev = NULL;
|
|
|
|
|
|
|
|
return name;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-11-28 07:48:34 +01:00
|
|
|
static dsql_name* lookup_name(const TEXT* name, dsql_name* list)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* l o o k u p _ n a m e
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Look up the given name in the designated list.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
|
|
|
|
const USHORT l = name_length(name);
|
|
|
|
for (; list; list = list->name_next) {
|
|
|
|
if (scompare(name, l, list->name_symbol, list->name_length)) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return list;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-11-28 07:48:34 +01:00
|
|
|
static stmt* lookup_stmt(const TEXT* name, dsql_name* list, name_type type)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* l o o k u p _ s t m t
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Look up the given statement in the designated list.
|
|
|
|
*
|
|
|
|
**************************************/
|
2003-11-28 07:48:34 +01:00
|
|
|
dsql_name* found = lookup_name(name, list);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-11-28 07:48:34 +01:00
|
|
|
if (found)
|
2001-05-23 15:26:42 +02:00
|
|
|
return found->name_stmt;
|
|
|
|
|
|
|
|
if (type == NAME_statement) {
|
2003-11-11 13:19:20 +01:00
|
|
|
error_post(isc_dsql_error,
|
|
|
|
isc_arg_gds, isc_sqlerr, isc_arg_number, (SLONG) - 518,
|
|
|
|
isc_arg_gds, isc_dsql_request_err, 0);
|
2003-11-28 07:48:34 +01:00
|
|
|
}
|
|
|
|
else {
|
2003-11-11 13:19:20 +01:00
|
|
|
error_post(isc_dsql_error,
|
|
|
|
isc_arg_gds, isc_sqlerr, isc_arg_number, (SLONG) - 504,
|
2004-11-17 15:50:33 +01:00
|
|
|
isc_arg_gds, isc_dsql_cursor_err,
|
|
|
|
isc_arg_gds, isc_dsql_cursor_not_found,
|
|
|
|
isc_arg_string, name, 0);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-11-28 07:48:34 +01:00
|
|
|
static USHORT name_length(const TEXT* name)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* n a m e _ l e n g t h
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Compute length of user supplied name.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
|
2003-11-28 07:48:34 +01:00
|
|
|
// CVC: Beware, another function that stops at the first blank!!!
|
|
|
|
const TEXT* p;
|
2001-05-23 15:26:42 +02:00
|
|
|
for (p = name; *p && *p != ' '; p++);
|
|
|
|
|
|
|
|
return (USHORT) (p - name);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-11-28 07:48:34 +01:00
|
|
|
static void remove_name(dsql_name* name, dsql_name** list_ptr)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* r e m o v e _ n a m e
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Remove a name from the designated list.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
|
|
|
|
if (name->name_next) {
|
|
|
|
name->name_next->name_prev = name->name_prev;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (name->name_prev) {
|
|
|
|
name->name_prev->name_next = name->name_next;
|
2004-01-28 08:50:41 +01:00
|
|
|
}
|
|
|
|
else {
|
2001-05-23 15:26:42 +02:00
|
|
|
*list_ptr = name->name_next;
|
|
|
|
}
|
|
|
|
|
|
|
|
gds__free(name);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-11-28 07:48:34 +01:00
|
|
|
// CVC: It seems I've read at least three versions of this routine.
|
|
|
|
static bool scompare(const SCHAR* string1,
|
2003-09-04 23:26:15 +02:00
|
|
|
USHORT length1,
|
2003-11-28 07:48:34 +01:00
|
|
|
const SCHAR* string2,
|
2003-09-04 23:26:15 +02:00
|
|
|
USHORT length2)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* s c o m p a r e
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Compare two strings case insensitive according to the C locale rules.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
|
|
|
|
if (length1 != length2) {
|
2003-09-04 23:26:15 +02:00
|
|
|
return false;
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
while (length1--)
|
|
|
|
{
|
2003-11-28 07:48:34 +01:00
|
|
|
const SCHAR c1 = *string1++;
|
|
|
|
const SCHAR c2 = *string2++;
|
2001-05-23 15:26:42 +02:00
|
|
|
if (c1 != c2 && UPPER7(c1) != UPPER7(c2))
|
|
|
|
{
|
2003-09-04 23:26:15 +02:00
|
|
|
return false;
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-09-04 23:26:15 +02:00
|
|
|
return true;
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|