2001-05-23 15:26:42 +02:00
|
|
|
/*
|
|
|
|
* PROGRAM: JRD Access Method
|
|
|
|
* MODULE: ext.c
|
|
|
|
* DESCRIPTION: External file access
|
|
|
|
*
|
|
|
|
* 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): ______________________________________.
|
2001-08-08 04:01:26 +02:00
|
|
|
*
|
2002-06-30 11:58:20 +02:00
|
|
|
* 26-Sept-2001 Paul Beach - Windows External File Directory Config. Parameter
|
|
|
|
*
|
2001-07-10 19:35:13 +02:00
|
|
|
* 2001.07.06 Sean Leyne - Code Cleanup, removed "#ifdef READONLY_DATABASE"
|
|
|
|
* conditionals, as the engine now fully supports
|
|
|
|
* readonly databases.
|
2001-08-08 04:01:26 +02:00
|
|
|
*
|
|
|
|
* 2001.08.07 Sean Leyne - Code Cleanup, removed "#ifdef READONLY_DATABASE"
|
|
|
|
* conditionals, second attempt
|
2002-10-30 07:40:58 +01:00
|
|
|
*
|
|
|
|
* 2002.10.29 Sean Leyne - Removed obsolete "Netware" port
|
|
|
|
*
|
2001-05-23 15:26:42 +02:00
|
|
|
*/
|
|
|
|
|
2001-07-29 19:42:23 +02:00
|
|
|
#include "firebird.h"
|
2001-05-23 15:26:42 +02:00
|
|
|
#include "../jrd/ib_stdio.h"
|
|
|
|
#include <errno.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include "../jrd/jrd.h"
|
|
|
|
#include "../jrd/req.h"
|
|
|
|
#include "../jrd/val.h"
|
|
|
|
#include "../jrd/exe.h"
|
|
|
|
#include "../jrd/rse.h"
|
|
|
|
#include "../jrd/ext.h"
|
|
|
|
#include "../jrd/tra.h"
|
2001-07-29 19:42:23 +02:00
|
|
|
#include "gen/codes.h"
|
2001-05-23 15:26:42 +02:00
|
|
|
#include "../jrd/all_proto.h"
|
|
|
|
#include "../jrd/err_proto.h"
|
|
|
|
#include "../jrd/ext_proto.h"
|
|
|
|
#include "../jrd/gds_proto.h"
|
|
|
|
#include "../jrd/met_proto.h"
|
|
|
|
#include "../jrd/mov_proto.h"
|
|
|
|
#include "../jrd/thd_proto.h"
|
|
|
|
#include "../jrd/vio_proto.h"
|
2002-06-30 11:58:20 +02:00
|
|
|
#include "../jrd/dls_proto.h"
|
2003-03-15 21:20:41 +01:00
|
|
|
#include "../common/config/config.h"
|
|
|
|
#include "../common/config/dir_list.h"
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-03-15 21:20:41 +01:00
|
|
|
static IB_FILE *ext_fopen(const char *filename, const char *mode);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
extern "C" {
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef WIN_NT
|
2002-06-30 11:58:20 +02:00
|
|
|
#include <windows.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <io.h>
|
2001-05-23 15:26:42 +02:00
|
|
|
#define FOPEN_TYPE "a+b"
|
|
|
|
#define FOPEN_READ_ONLY "rb"
|
|
|
|
#define SYS_ERR gds_arg_win32
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef FOPEN_TYPE
|
|
|
|
#define FOPEN_TYPE "a+"
|
|
|
|
#define FOPEN_READ_ONLY "rb"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef SYS_ERR
|
|
|
|
#define SYS_ERR gds_arg_unix
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
2003-03-01 20:11:57 +01:00
|
|
|
//static void io_error(EXT, TEXT *, STATUS, SLONG);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
void EXT_close(RSB rsb)
|
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* E X T _ c l o s e
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Close a record stream for an external file.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void EXT_erase(RPB * rpb, int *transaction)
|
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* E X T _ e r a s e
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Update an external file.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
|
|
|
|
ERR_post(isc_ext_file_delete, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-11-17 01:13:59 +01:00
|
|
|
EXT EXT_file(JRD_REL relation, TEXT * file_name, SLONG * description)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* E X T _ f i l e
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Create a file block for external file access.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
DBB dbb;
|
|
|
|
EXT file;
|
|
|
|
|
|
|
|
dbb = GET_DBB;
|
|
|
|
CHECK_DBB(dbb);
|
|
|
|
|
|
|
|
/* if we already have a external file associated with this relation just
|
|
|
|
* return the file structure */
|
|
|
|
if (relation->rel_file) {
|
|
|
|
EXT_fini(relation);
|
|
|
|
}
|
2002-06-30 11:58:20 +02:00
|
|
|
|
|
|
|
#ifdef WIN_NT
|
|
|
|
/* Default number of file handles stdio.h on Windows is 512, use this
|
|
|
|
call to increase and set to the maximum */
|
|
|
|
_setmaxstdio(2048);
|
|
|
|
#endif
|
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
relation->rel_file = file =
|
2002-09-25 19:12:16 +02:00
|
|
|
FB_NEW_RPT(*dbb->dbb_permanent, (strlen(file_name) + 1)) ext();
|
2001-12-24 03:51:06 +01:00
|
|
|
strcpy(reinterpret_cast<char*>(file->ext_filename), file_name);
|
2001-05-23 15:26:42 +02:00
|
|
|
file->ext_flags = 0;
|
|
|
|
file->ext_ifi = (int *) NULL;
|
2002-06-30 11:58:20 +02:00
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
/* If the database is updateable, then try opening the external files in
|
|
|
|
* RW mode. If the DB is ReadOnly, then open the external files only in
|
|
|
|
* ReadOnly mode, thus being consistent.
|
|
|
|
*/
|
|
|
|
if (!(dbb->dbb_flags & DBB_read_only))
|
2003-03-15 21:20:41 +01:00
|
|
|
file->ext_ifi = (int *) ext_fopen(file_name, FOPEN_TYPE);
|
2001-05-23 15:26:42 +02:00
|
|
|
if (!(file->ext_ifi))
|
|
|
|
{
|
|
|
|
/* could not open the file as read write attempt as read only */
|
2003-03-15 21:20:41 +01:00
|
|
|
if (!(file->ext_ifi = (int *) ext_fopen(file_name, FOPEN_READ_ONLY)))
|
2001-05-23 15:26:42 +02:00
|
|
|
ERR_post(isc_io_error,
|
|
|
|
gds_arg_string, "ib_fopen",
|
|
|
|
gds_arg_string,
|
|
|
|
ERR_cstring(reinterpret_cast <
|
2002-06-30 11:58:20 +02:00
|
|
|
char *>(file->ext_filename)),
|
|
|
|
isc_arg_gds, isc_io_open_err, SYS_ERR, errno, 0);
|
2001-05-23 15:26:42 +02:00
|
|
|
else
|
|
|
|
file->ext_flags |= EXT_readonly;
|
|
|
|
}
|
|
|
|
|
|
|
|
return file;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-11-17 01:13:59 +01:00
|
|
|
void EXT_fini(JRD_REL relation)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* E X T _ f i n i
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Close the file associated with a relation.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
EXT file;
|
|
|
|
|
|
|
|
if (relation->rel_file) {
|
|
|
|
file = relation->rel_file;
|
|
|
|
if (file->ext_ifi)
|
|
|
|
ib_fclose((IB_FILE *) file->ext_ifi);
|
|
|
|
/* before zeroing out the rel_file we need to deallocate the memory */
|
2001-12-24 03:51:06 +01:00
|
|
|
delete relation->rel_file;
|
2001-05-23 15:26:42 +02:00
|
|
|
relation->rel_file = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int EXT_get(RSB rsb)
|
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* E X T _ g e t
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Get a record from an external file.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
TDBB tdbb;
|
2002-11-17 01:13:59 +01:00
|
|
|
JRD_REQ request;
|
|
|
|
JRD_REL relation;
|
2001-05-23 15:26:42 +02:00
|
|
|
EXT file;
|
|
|
|
RPB *rpb;
|
|
|
|
REC record;
|
|
|
|
FMT format;
|
|
|
|
LIT literal;
|
2002-11-30 18:45:02 +01:00
|
|
|
JRD_FLD field;
|
2001-12-24 03:51:06 +01:00
|
|
|
DSC desc;
|
2001-05-23 15:26:42 +02:00
|
|
|
SSHORT c, l, offset, i;
|
|
|
|
UCHAR *p;
|
2001-12-24 03:51:06 +01:00
|
|
|
vec::iterator itr;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
tdbb = GET_THREAD_DATA;
|
|
|
|
|
|
|
|
relation = rsb->rsb_relation;
|
|
|
|
file = relation->rel_file;
|
|
|
|
request = tdbb->tdbb_request;
|
|
|
|
|
|
|
|
if (request->req_flags & req_abort)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
rpb = &request->req_rpb[rsb->rsb_stream];
|
|
|
|
record = rpb->rpb_record;
|
|
|
|
format = record->rec_format;
|
|
|
|
|
|
|
|
offset = (SSHORT) format->fmt_desc[0].dsc_address;
|
|
|
|
p = record->rec_data + offset;
|
|
|
|
l = record->rec_length - offset;
|
|
|
|
|
|
|
|
if (file->ext_ifi == 0 ||
|
|
|
|
(ib_fseek((IB_FILE *) file->ext_ifi, rpb->rpb_ext_pos, 0) != 0))
|
|
|
|
ERR_post(isc_io_error,
|
|
|
|
gds_arg_string, "ib_fseek",
|
|
|
|
gds_arg_string,
|
|
|
|
ERR_cstring(reinterpret_cast < char *>(file->ext_filename)),
|
|
|
|
isc_arg_gds, isc_io_open_err, SYS_ERR, errno, 0);
|
|
|
|
|
|
|
|
while (l--) {
|
|
|
|
c = ib_getc((IB_FILE *) file->ext_ifi);
|
|
|
|
if (c == EOF)
|
|
|
|
return FALSE;
|
|
|
|
*p++ = c;
|
|
|
|
}
|
|
|
|
rpb->rpb_ext_pos = ib_ftell((IB_FILE *) file->ext_ifi);
|
|
|
|
|
|
|
|
/* Loop thru fields setting missing fields to either blanks/zeros
|
|
|
|
or the missing value */
|
|
|
|
|
2001-12-24 03:51:06 +01:00
|
|
|
fmt::fmt_desc_iterator desc_ptr = format->fmt_desc.begin();
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2001-12-24 03:51:06 +01:00
|
|
|
for (i = 0, itr = relation->rel_fields->begin();
|
2002-04-04 09:10:40 +02:00
|
|
|
i < format->fmt_count; ++i, ++itr, ++desc_ptr) {
|
2002-11-30 18:45:02 +01:00
|
|
|
field = (JRD_FLD) (*itr);
|
2001-05-23 15:26:42 +02:00
|
|
|
SET_NULL(record, i);
|
2002-04-04 09:10:40 +02:00
|
|
|
if (!desc_ptr->dsc_length || !field)
|
2001-05-23 15:26:42 +02:00
|
|
|
continue;
|
2001-12-24 03:51:06 +01:00
|
|
|
if ( (literal = (LIT) field->fld_missing_value) ) {
|
2001-05-23 15:26:42 +02:00
|
|
|
desc = *desc_ptr;
|
|
|
|
desc.dsc_address = record->rec_data + (int) desc.dsc_address;
|
|
|
|
if (!MOV_compare(&literal->lit_desc, &desc))
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
CLEAR_NULL(record, i);
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void EXT_modify(RPB * old_rpb, RPB * new_rpb, int *transaction)
|
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* E X T _ m o d i f y
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Update an external file.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
|
|
|
|
/* ERR_post (gds_wish_list, gds_arg_interpreted, "EXT_modify: not yet implemented", 0); */
|
|
|
|
ERR_post(isc_ext_file_modify, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void EXT_open(RSB rsb)
|
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* E X T _ o p e n
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Open a record stream for an external file.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
TDBB tdbb;
|
2002-11-17 01:13:59 +01:00
|
|
|
JRD_REL relation;
|
|
|
|
JRD_REQ request;
|
2001-05-23 15:26:42 +02:00
|
|
|
RPB *rpb;
|
|
|
|
REC record;
|
|
|
|
FMT format;
|
|
|
|
|
|
|
|
tdbb = GET_THREAD_DATA;
|
|
|
|
|
|
|
|
relation = rsb->rsb_relation;
|
|
|
|
request = tdbb->tdbb_request;
|
|
|
|
rpb = &request->req_rpb[rsb->rsb_stream];
|
|
|
|
|
|
|
|
if (!(record = rpb->rpb_record) || !(format = record->rec_format)) {
|
|
|
|
format = MET_current(tdbb, relation);
|
|
|
|
VIO_record(tdbb, rpb, format, request->req_pool);
|
|
|
|
}
|
|
|
|
|
|
|
|
rpb->rpb_ext_pos = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-02-10 14:28:35 +01:00
|
|
|
RSB EXT_optimize(OPT opt, SSHORT stream, JRD_NOD * sort_ptr)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* E X T _ o p t i m i z e
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Compile and optimize a record selection expression into a
|
|
|
|
* set of record source blocks (rsb's).
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
TDBB tdbb;
|
2003-02-10 14:28:35 +01:00
|
|
|
CSB csb;
|
2002-11-17 01:13:59 +01:00
|
|
|
JRD_REL relation;
|
2001-12-24 03:51:06 +01:00
|
|
|
RSB rsb_;
|
2001-07-10 19:35:13 +02:00
|
|
|
/* all these are un refrenced due to the code commented below
|
2002-11-11 20:42:47 +01:00
|
|
|
JRD_NOD node, inversion;
|
2003-02-10 14:28:35 +01:00
|
|
|
opt::opt_repeat *tail, *opt_end;
|
2001-05-23 15:26:42 +02:00
|
|
|
SSHORT i, size;
|
|
|
|
*/
|
|
|
|
SSHORT size;
|
|
|
|
csb_repeat *csb_tail;
|
|
|
|
|
|
|
|
tdbb = GET_THREAD_DATA;
|
|
|
|
|
|
|
|
csb = opt->opt_csb;
|
|
|
|
csb_tail = &csb->csb_rpt[stream];
|
|
|
|
relation = csb_tail->csb_relation;
|
|
|
|
|
|
|
|
/* Time to find inversions. For each index on the relation
|
|
|
|
match all unused booleans against the index looking for upper
|
|
|
|
and lower bounds that can be computed by the index. When
|
|
|
|
all unused conjunctions are exhausted, see if there is enough
|
|
|
|
information for an index retrieval. If so, build up and
|
|
|
|
inversion component of the boolean. */
|
|
|
|
|
|
|
|
/*
|
|
|
|
inversion = NULL;
|
|
|
|
opt_end = opt->opt_rpt + opt->opt_count;
|
|
|
|
|
|
|
|
if (opt->opt_count)
|
|
|
|
for (i = 0; i < csb_tail->csb_indices; i++)
|
|
|
|
{
|
|
|
|
clear_bounds (opt, idx);
|
|
|
|
for (tail = opt->opt_rpt; tail < opt_end; tail++)
|
|
|
|
{
|
|
|
|
node = tail->opt_conjunct;
|
2001-07-10 19:35:13 +02:00
|
|
|
if (!(tail->opt_flags & opt_used) &&
|
2001-05-23 15:26:42 +02:00
|
|
|
computable (csb, node, -1))
|
|
|
|
match (opt, stream, node, idx);
|
|
|
|
if (node->nod_type == nod_starts)
|
2001-07-10 19:35:13 +02:00
|
|
|
compose (&inversion,
|
2001-05-23 15:26:42 +02:00
|
|
|
make_starts (opt, node, stream, idx), nod_bit_and);
|
|
|
|
}
|
2001-07-10 19:35:13 +02:00
|
|
|
compose (&inversion, make_index (opt, relation, idx),
|
2001-05-23 15:26:42 +02:00
|
|
|
nod_bit_and);
|
|
|
|
idx = idx->idx_rpt + idx->idx_count;
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
2002-09-25 19:12:16 +02:00
|
|
|
rsb_ = FB_NEW_RPT(*tdbb->tdbb_default,0) Rsb;
|
2001-12-24 03:51:06 +01:00
|
|
|
rsb_->rsb_type = rsb_ext_sequential;
|
2001-05-23 15:26:42 +02:00
|
|
|
size = sizeof(struct irsb);
|
|
|
|
|
2001-12-24 03:51:06 +01:00
|
|
|
rsb_->rsb_stream = stream;
|
|
|
|
rsb_->rsb_relation = relation;
|
|
|
|
rsb_->rsb_impure = csb->csb_impure;
|
2001-05-23 15:26:42 +02:00
|
|
|
csb->csb_impure += size;
|
|
|
|
|
2001-12-24 03:51:06 +01:00
|
|
|
return rsb_;
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-11-17 01:13:59 +01:00
|
|
|
void EXT_ready(JRD_REL relation)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* E X T _ r e a d y
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Open an external file.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void EXT_store(RPB * rpb, int *transaction)
|
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* E X T _ s t o r e
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Update an external file.
|
|
|
|
*
|
|
|
|
**************************************/
|
2002-11-17 01:13:59 +01:00
|
|
|
JRD_REL relation;
|
2001-05-23 15:26:42 +02:00
|
|
|
REC record;
|
|
|
|
FMT format;
|
|
|
|
EXT file;
|
2002-11-30 18:45:02 +01:00
|
|
|
JRD_FLD field;
|
2001-05-23 15:26:42 +02:00
|
|
|
LIT literal;
|
2001-12-24 03:51:06 +01:00
|
|
|
DSC desc;
|
2001-05-23 15:26:42 +02:00
|
|
|
UCHAR *p;
|
|
|
|
USHORT i, l, offset;
|
|
|
|
|
|
|
|
relation = rpb->rpb_relation;
|
|
|
|
file = relation->rel_file;
|
|
|
|
record = rpb->rpb_record;
|
|
|
|
format = record->rec_format;
|
|
|
|
|
|
|
|
/* Loop thru fields setting missing fields to either blanks/zeros
|
|
|
|
or the missing value */
|
|
|
|
|
2001-07-10 19:35:13 +02:00
|
|
|
/* check if file is read only if read only then
|
2001-05-23 15:26:42 +02:00
|
|
|
post error we cannot write to this file */
|
|
|
|
if (file->ext_flags & EXT_readonly) {
|
|
|
|
DBB dbb;
|
|
|
|
|
|
|
|
dbb = GET_DBB;
|
|
|
|
CHECK_DBB(dbb);
|
|
|
|
/* Distinguish error message for a ReadOnly database */
|
|
|
|
if (dbb->dbb_flags & DBB_read_only)
|
|
|
|
ERR_post(isc_read_only_database, 0);
|
|
|
|
else
|
|
|
|
ERR_post(isc_io_error,
|
|
|
|
gds_arg_string, "insert",
|
|
|
|
gds_arg_string, file->ext_filename,
|
|
|
|
isc_arg_gds, isc_io_write_err,
|
2001-07-29 19:42:23 +02:00
|
|
|
gds_arg_gds, gds_ext_readonly_err, 0);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
2001-12-24 03:51:06 +01:00
|
|
|
vec::iterator field_ptr = relation->rel_fields->begin();
|
|
|
|
fmt::fmt_desc_iterator desc_ptr = format->fmt_desc.begin();
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
for (i = 0; i < format->fmt_count; i++, field_ptr++, desc_ptr++)
|
2001-12-24 03:51:06 +01:00
|
|
|
{
|
2002-11-30 18:45:02 +01:00
|
|
|
field = (JRD_FLD)*field_ptr;
|
2001-12-24 03:51:06 +01:00
|
|
|
if (field &&
|
2001-05-23 15:26:42 +02:00
|
|
|
!field->fld_computation &&
|
2001-12-24 03:51:06 +01:00
|
|
|
desc_ptr->dsc_length &&
|
|
|
|
TEST_NULL(record, i))
|
|
|
|
{
|
2001-05-23 15:26:42 +02:00
|
|
|
p = record->rec_data + (int) desc_ptr->dsc_address;
|
2001-12-24 03:51:06 +01:00
|
|
|
if ( (literal = (LIT) field->fld_missing_value) ) {
|
2001-05-23 15:26:42 +02:00
|
|
|
desc = *desc_ptr;
|
|
|
|
desc.dsc_address = p;
|
|
|
|
MOV_move(&literal->lit_desc, &desc);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
l = desc_ptr->dsc_length;
|
|
|
|
offset = (desc_ptr->dsc_dtype == dtype_text) ? ' ' : 0;
|
|
|
|
do
|
|
|
|
*p++ = offset;
|
|
|
|
while (--l);
|
|
|
|
}
|
|
|
|
}
|
2001-12-24 03:51:06 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
offset = (USHORT) format->fmt_desc[0].dsc_address;
|
|
|
|
p = record->rec_data + offset;
|
|
|
|
l = record->rec_length - offset;
|
|
|
|
|
|
|
|
if (file->ext_ifi == 0
|
|
|
|
|| (ib_fseek((IB_FILE *) file->ext_ifi, (SLONG) 0, 2) != 0))
|
|
|
|
ERR_post(isc_io_error, gds_arg_string, "ib_fseek", gds_arg_string,
|
|
|
|
ERR_cstring(reinterpret_cast < char *>(file->ext_filename)),
|
|
|
|
isc_arg_gds, isc_io_open_err, SYS_ERR, errno, 0);
|
|
|
|
for (; l--; ++p)
|
|
|
|
ib_putc(*p, (IB_FILE *) file->ext_ifi);
|
|
|
|
ib_fflush((IB_FILE *) file->ext_ifi);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-11-17 01:13:59 +01:00
|
|
|
void EXT_trans_commit(JRD_TRA transaction)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* E X T _ t r a n s _ c o m m i t
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Checkin at transaction commit time.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-11-17 01:13:59 +01:00
|
|
|
void EXT_trans_prepare(JRD_TRA transaction)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* E X T _ t r a n s _ p r e p a r e
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Checkin at transaction prepare time.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-11-17 01:13:59 +01:00
|
|
|
void EXT_trans_rollback(JRD_TRA transaction)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* E X T _ t r a n s _ r o l l b a c k
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Checkin at transaction rollback time.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-11-17 01:13:59 +01:00
|
|
|
void EXT_trans_start(JRD_TRA transaction)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* E X T _ t r a n s _ s t a r t
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Checkin at start transaction time.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2001-07-29 19:42:23 +02:00
|
|
|
} // extern "C"
|
2003-03-15 21:20:41 +01:00
|
|
|
|
|
|
|
class ExternalFilesDirectoryList : public DirectoryList {
|
|
|
|
virtual const Firebird::string GetConfigString(void) {
|
2003-03-17 19:03:38 +01:00
|
|
|
return Firebird::string(Config::getExternalTablesDirs());
|
2003-03-15 21:20:41 +01:00
|
|
|
}
|
|
|
|
};
|
|
|
|
static ExternalFilesDirectoryList iExternalFilesDirectoryList;
|
|
|
|
|
|
|
|
static IB_FILE *ext_fopen(const char *filename, const char *mode) {
|
|
|
|
if (! iExternalFilesDirectoryList.IsPathInList(filename))
|
|
|
|
return 0;
|
|
|
|
return ib_fopen(filename, mode);
|
|
|
|
}
|