2001-05-23 15:26:42 +02:00
|
|
|
/*
|
|
|
|
* PROGRAM: JRD Access Method
|
2003-11-07 09:06:35 +01:00
|
|
|
* MODULE: ext.cpp
|
2001-05-23 15:26:42 +02:00
|
|
|
* 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"
|
2003-11-11 13:19:20 +01:00
|
|
|
#include "gen/iberror.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"
|
2003-03-23 17:50:54 +01:00
|
|
|
#include "../jrd/os/path_utils.h"
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-04-14 09:23:14 +02:00
|
|
|
namespace {
|
|
|
|
IB_FILE *ext_fopen(const char *filename, const char *mode);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-04-14 09:23:14 +02:00
|
|
|
class ExternalFileDirectoryList : public DirectoryList {
|
2003-05-30 14:17:47 +02:00
|
|
|
const Firebird::PathName GetConfigString(void) const {
|
|
|
|
return Firebird::PathName(Config::getExternalFileAccess());
|
2003-03-23 17:50:54 +01:00
|
|
|
}
|
2003-04-06 17:01:30 +02:00
|
|
|
} iExternalFileDirectoryList;
|
2003-03-23 17:50:54 +01:00
|
|
|
|
2003-04-14 09:23:14 +02:00
|
|
|
IB_FILE *ext_fopen(const char *filename, const char *mode) {
|
2003-04-06 17:01:30 +02:00
|
|
|
if (!iExternalFileDirectoryList.IsPathInList(filename))
|
2003-11-11 13:19:20 +01:00
|
|
|
ERR_post(isc_conf_access_denied,
|
|
|
|
isc_arg_string, "external file",
|
|
|
|
isc_arg_string, ERR_cstring(const_cast <TEXT *>(filename)),
|
|
|
|
isc_arg_end);
|
2003-06-16 17:43:00 +02:00
|
|
|
|
2003-03-23 17:50:54 +01:00
|
|
|
return ib_fopen(filename, mode);
|
|
|
|
}
|
2003-04-14 09:23:14 +02:00
|
|
|
};
|
2003-03-23 17:50:54 +01:00
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
#ifdef WIN_NT
|
|
|
|
#define FOPEN_TYPE "a+b"
|
|
|
|
#define FOPEN_READ_ONLY "rb"
|
2003-11-11 13:19:20 +01:00
|
|
|
#define SYS_ERR isc_arg_win32
|
2001-05-23 15:26:42 +02:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef FOPEN_TYPE
|
|
|
|
#define FOPEN_TYPE "a+"
|
|
|
|
#define FOPEN_READ_ONLY "rb"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef SYS_ERR
|
2003-11-11 13:19:20 +01:00
|
|
|
#define SYS_ERR isc_arg_unix
|
2001-05-23 15:26:42 +02:00
|
|
|
#endif
|
|
|
|
|
|
|
|
|
2003-04-10 08:49:16 +02:00
|
|
|
//static void io_error(EXT, TEXT *, ISC_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);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-01-03 11:59:52 +01:00
|
|
|
EXT EXT_file(jrd_rel* relation, const 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.
|
|
|
|
*
|
|
|
|
**************************************/
|
2003-12-31 06:36:12 +01:00
|
|
|
DBB dbb = GET_DBB;
|
2001-05-23 15:26:42 +02:00
|
|
|
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
|
|
|
|
|
2003-03-23 17:50:54 +01:00
|
|
|
// If file_name has no path part, expand it in ExternalTablesDirs.
|
2003-05-30 14:17:47 +02:00
|
|
|
Firebird::PathName Path, Name;
|
2003-03-23 17:50:54 +01:00
|
|
|
PathUtils::splitLastComponent(Path, Name, file_name);
|
|
|
|
if (Path.length() == 0) { // path component not present in file_name
|
2003-04-06 17:01:30 +02:00
|
|
|
iExternalFileDirectoryList.ExpandFileName(Path, Name, 4);
|
2003-03-23 17:50:54 +01:00
|
|
|
file_name = Path.c_str();
|
|
|
|
}
|
|
|
|
|
2003-12-31 06:36:12 +01:00
|
|
|
ext* file = FB_NEW_RPT(*dbb->dbb_permanent, (strlen(file_name) + 1)) ext();
|
|
|
|
relation->rel_file = file;
|
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;
|
2003-08-28 15:16:03 +02:00
|
|
|
file->ext_ifi = 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)))
|
2003-12-31 06:36:12 +01:00
|
|
|
{
|
2001-05-23 15:26:42 +02:00
|
|
|
ERR_post(isc_io_error,
|
2003-11-11 13:19:20 +01:00
|
|
|
isc_arg_string, "ib_fopen",
|
|
|
|
isc_arg_string,
|
2001-05-23 15:26:42 +02:00
|
|
|
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);
|
2003-12-31 06:36:12 +01:00
|
|
|
}
|
|
|
|
else {
|
2001-05-23 15:26:42 +02:00
|
|
|
file->ext_flags |= EXT_readonly;
|
2003-12-31 06:36:12 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return file;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-01-03 11:59:52 +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.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
if (relation->rel_file) {
|
2003-12-31 06:36:12 +01:00
|
|
|
ext* file = relation->rel_file;
|
2001-05-23 15:26:42 +02:00
|
|
|
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.
|
|
|
|
*
|
|
|
|
**************************************/
|
2003-12-31 06:36:12 +01:00
|
|
|
TDBB tdbb = GET_THREAD_DATA;
|
|
|
|
|
|
|
|
jrd_rel* relation = rsb->rsb_relation;
|
|
|
|
ext* file = relation->rel_file;
|
|
|
|
jrd_req* request = tdbb->tdbb_request;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
if (request->req_flags & req_abort)
|
|
|
|
return FALSE;
|
|
|
|
|
2003-12-31 06:36:12 +01:00
|
|
|
RPB* rpb = &request->req_rpb[rsb->rsb_stream];
|
|
|
|
rec* record = rpb->rpb_record;
|
|
|
|
const fmt* format = record->rec_format;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-12-31 06:36:12 +01:00
|
|
|
const SSHORT offset = (SSHORT) (SLONG) format->fmt_desc[0].dsc_address;
|
|
|
|
UCHAR* p = record->rec_data + offset;
|
|
|
|
SSHORT l = record->rec_length - offset;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
if (file->ext_ifi == 0 ||
|
|
|
|
(ib_fseek((IB_FILE *) file->ext_ifi, rpb->rpb_ext_pos, 0) != 0))
|
2003-12-31 06:36:12 +01:00
|
|
|
{
|
2001-05-23 15:26:42 +02:00
|
|
|
ERR_post(isc_io_error,
|
2003-11-11 13:19:20 +01:00
|
|
|
isc_arg_string, "ib_fseek",
|
|
|
|
isc_arg_string,
|
2001-05-23 15:26:42 +02:00
|
|
|
ERR_cstring(reinterpret_cast < char *>(file->ext_filename)),
|
|
|
|
isc_arg_gds, isc_io_open_err, SYS_ERR, errno, 0);
|
2003-12-31 06:36:12 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
while (l--) {
|
2003-12-31 06:36:12 +01:00
|
|
|
const SSHORT c = ib_getc((IB_FILE *) file->ext_ifi);
|
2001-05-23 15:26:42 +02:00
|
|
|
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 */
|
|
|
|
|
2003-12-31 06:36:12 +01:00
|
|
|
dsc desc;
|
|
|
|
fmt::fmt_desc_const_iterator desc_ptr = format->fmt_desc.begin();
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-12-31 06:36:12 +01:00
|
|
|
SSHORT i = 0;
|
|
|
|
for (vec::iterator itr = relation->rel_fields->begin();
|
|
|
|
i < format->fmt_count; ++i, ++itr, ++desc_ptr)
|
|
|
|
{
|
2004-01-03 11:59:52 +01:00
|
|
|
const jrd_fld* 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;
|
2003-12-31 06:36:12 +01:00
|
|
|
const lit* literal = (LIT) field->fld_missing_value;
|
|
|
|
if (literal) {
|
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.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
|
2003-11-11 13:19:20 +01:00
|
|
|
/* ERR_post (isc_wish_list, isc_arg_interpreted, "EXT_modify: not yet implemented", 0); */
|
2001-05-23 15:26:42 +02:00
|
|
|
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.
|
|
|
|
*
|
|
|
|
**************************************/
|
2003-12-31 06:36:12 +01:00
|
|
|
TDBB tdbb = GET_THREAD_DATA;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-12-31 06:36:12 +01:00
|
|
|
jrd_rel* relation = rsb->rsb_relation;
|
|
|
|
jrd_req* request = tdbb->tdbb_request;
|
|
|
|
RPB* rpb = &request->req_rpb[rsb->rsb_stream];
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-12-31 06:36:12 +01:00
|
|
|
const fmt* format;
|
|
|
|
rec* record = rpb->rpb_record;
|
|
|
|
if (!record || !(format = record->rec_format)) {
|
2001-05-23 15:26:42 +02:00
|
|
|
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).
|
|
|
|
*
|
|
|
|
**************************************/
|
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;
|
|
|
|
*/
|
|
|
|
|
2003-12-31 06:36:12 +01:00
|
|
|
TDBB tdbb = GET_THREAD_DATA;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-12-31 06:36:12 +01:00
|
|
|
CSB csb = opt->opt_csb;
|
|
|
|
csb_repeat* csb_tail = &csb->csb_rpt[stream];
|
|
|
|
jrd_rel* relation = csb_tail->csb_relation;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
/* 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;
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
2003-12-31 06:36:12 +01:00
|
|
|
Rsb* rsb_ = FB_NEW_RPT(*tdbb->tdbb_default,0) Rsb;
|
2001-12-24 03:51:06 +01:00
|
|
|
rsb_->rsb_type = rsb_ext_sequential;
|
2003-12-31 06:36:12 +01:00
|
|
|
const SSHORT size = sizeof(irsb);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
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
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-01-03 11:59:52 +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.
|
|
|
|
*
|
|
|
|
**************************************/
|
2003-12-31 06:36:12 +01:00
|
|
|
jrd_rel* relation = rpb->rpb_relation;
|
|
|
|
ext* file = relation->rel_file;
|
|
|
|
rec* record = rpb->rpb_record;
|
|
|
|
const fmt* format = record->rec_format;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
/* 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) {
|
2003-12-31 06:36:12 +01:00
|
|
|
DBB dbb = GET_DBB;
|
2001-05-23 15:26:42 +02:00
|
|
|
CHECK_DBB(dbb);
|
|
|
|
/* Distinguish error message for a ReadOnly database */
|
|
|
|
if (dbb->dbb_flags & DBB_read_only)
|
|
|
|
ERR_post(isc_read_only_database, 0);
|
2003-12-31 06:36:12 +01:00
|
|
|
else {
|
2001-05-23 15:26:42 +02:00
|
|
|
ERR_post(isc_io_error,
|
2003-11-11 13:19:20 +01:00
|
|
|
isc_arg_string, "insert",
|
|
|
|
isc_arg_string, file->ext_filename,
|
2001-05-23 15:26:42 +02:00
|
|
|
isc_arg_gds, isc_io_write_err,
|
2003-11-11 13:19:20 +01:00
|
|
|
isc_arg_gds, isc_ext_readonly_err, 0);
|
2003-12-31 06:36:12 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
2003-12-31 06:36:12 +01:00
|
|
|
dsc desc;
|
2001-12-24 03:51:06 +01:00
|
|
|
vec::iterator field_ptr = relation->rel_fields->begin();
|
2003-12-31 06:36:12 +01:00
|
|
|
fmt::fmt_desc_const_iterator desc_ptr = format->fmt_desc.begin();
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-12-31 06:36:12 +01:00
|
|
|
for (USHORT i = 0; i < format->fmt_count; i++, field_ptr++, desc_ptr++)
|
2001-12-24 03:51:06 +01:00
|
|
|
{
|
2004-01-03 11:59:52 +01:00
|
|
|
const jrd_fld* 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))
|
|
|
|
{
|
2003-12-31 06:36:12 +01:00
|
|
|
UCHAR* p = record->rec_data + (int) desc_ptr->dsc_address;
|
|
|
|
const lit* literal = (LIT) field->fld_missing_value;
|
|
|
|
if (literal) {
|
2001-05-23 15:26:42 +02:00
|
|
|
desc = *desc_ptr;
|
|
|
|
desc.dsc_address = p;
|
|
|
|
MOV_move(&literal->lit_desc, &desc);
|
|
|
|
}
|
|
|
|
else {
|
2003-12-31 06:36:12 +01:00
|
|
|
USHORT l = desc_ptr->dsc_length;
|
|
|
|
const UCHAR pad = (desc_ptr->dsc_dtype == dtype_text) ? ' ' : 0;
|
|
|
|
do {
|
|
|
|
*p++ = pad;
|
|
|
|
} while (--l);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
}
|
2001-12-24 03:51:06 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-12-31 06:36:12 +01:00
|
|
|
const USHORT offset = (USHORT) (ULONG) format->fmt_desc[0].dsc_address;
|
|
|
|
const UCHAR* p = record->rec_data + offset;
|
|
|
|
USHORT l = record->rec_length - offset;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
if (file->ext_ifi == 0
|
|
|
|
|| (ib_fseek((IB_FILE *) file->ext_ifi, (SLONG) 0, 2) != 0))
|
2003-12-31 06:36:12 +01:00
|
|
|
{
|
2003-11-11 13:19:20 +01:00
|
|
|
ERR_post(isc_io_error, isc_arg_string, "ib_fseek", isc_arg_string,
|
2001-05-23 15:26:42 +02:00
|
|
|
ERR_cstring(reinterpret_cast < char *>(file->ext_filename)),
|
|
|
|
isc_arg_gds, isc_io_open_err, SYS_ERR, errno, 0);
|
2003-12-31 06:36:12 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
for (; l--; ++p)
|
|
|
|
ib_putc(*p, (IB_FILE *) file->ext_ifi);
|
|
|
|
ib_fflush((IB_FILE *) file->ext_ifi);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-01-03 11:59:52 +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.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-01-03 11:59:52 +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.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-01-03 11:59:52 +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.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-01-03 11:59:52 +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.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
}
|
|
|
|
|