2001-05-23 15:26:42 +02:00
|
|
|
/*
|
|
|
|
* PROGRAM: Dynamic SQL runtime support
|
2003-10-05 08:33:56 +02:00
|
|
|
* MODULE: ddl.cpp
|
2001-05-23 15:26:42 +02:00
|
|
|
* DESCRIPTION: Utilities for generating ddl
|
|
|
|
*
|
|
|
|
* 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.5.20 Claudio Valderrama: Stop null pointer that leads to a crash,
|
|
|
|
* caused by incomplete yacc syntax that allows ALTER DOMAIN dom SET;
|
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-12-24 03:51:06 +01:00
|
|
|
* December 2001 Mike Nordell - Attempt to make it C++
|
2002-06-29 08:56:51 +02:00
|
|
|
*
|
|
|
|
* 2001.5.20 Claudio Valderrama: Stop null pointer that leads to a crash,
|
|
|
|
* caused by incomplete yacc syntax that allows ALTER DOMAIN dom SET;
|
|
|
|
* 2001.5.29 Claudio Valderrama: Check for view v/s relation in DROP
|
|
|
|
* command will stop a user that uses DROP VIEW and drops a table by
|
|
|
|
* accident and vice-versa.
|
|
|
|
* 2001.5.30 Claudio Valderrama: alter column should use 1..N for the
|
|
|
|
* position argument since the call comes from SQL DDL.
|
|
|
|
* 2001.6.27 Claudio Valderrama: DDL_resolve_intl_type() was adding 2 to the
|
|
|
|
* length of varchars instead of just checking that len+2<=MAX_COLUMN_SIZE.
|
|
|
|
* It required a minor change to put_field() where it was decremented, too.
|
|
|
|
* 2001.6.27 Claudio Valderrama: Finally stop users from invoking the same option
|
|
|
|
* several times when altering a domain. Specially dangerous with text data types.
|
|
|
|
* Ex: alter domain d type char(5) type varchar(5) default 'x' default 'y';
|
|
|
|
* Bear in mind that if DYN functions are addressed directly, this protection
|
|
|
|
* becomes a moot point.
|
|
|
|
* 2001.6.30 Claudio Valderrama: revert changes from 2001.6.26 because the code
|
|
|
|
* is called from several places and there are more functions, even in metd.c,
|
|
|
|
* playing the same nonsense game with the field's length, so it needs more
|
|
|
|
* careful examination. For now, the new checks in DYN_MOD should catch most anomalies.
|
|
|
|
* 2001.7.3 Claudio Valderrama: fix Firebird Bug #223059 with mismatch between number
|
|
|
|
* of declared fields for a VIEW and effective fields in the SELECT statement.
|
|
|
|
* 2001.07.22 Claudio Valderrama: minor fixes and improvements.
|
|
|
|
* 2001.08.18 Claudio Valderrama: RECREATE PROCEDURE.
|
|
|
|
* 2001.10.01 Claudio Valderrama: modify_privilege() should recognize that a ROLE can
|
|
|
|
* now be made an explicit grantee.
|
2004-11-29 10:09:42 +01:00
|
|
|
* 2001.10.08 Claudio Valderrama: implement fb_sysflag enum values for autogenerated
|
2002-06-29 08:56:51 +02:00
|
|
|
* non-system triggers so DFW can recognize them easily.
|
|
|
|
* 2001.10.26 Claudio Valderrama: added a call to the new METD_drop_function()
|
|
|
|
* in DDL_execute() so the metadata cache for udfs can be refreshed.
|
|
|
|
* 2001.12.06 Claudio Valderrama: DDL_resolve_intl_type should calculate field length
|
2002-08-11 10:04:54 +02:00
|
|
|
* 2002.08.04 Claudio Valderrama: allow declaring and defining variables at the same time
|
|
|
|
* 2002.08.04 Dmitry Yemanov: ALTER VIEW
|
2002-09-01 17:44:45 +02:00
|
|
|
* 2002.08.31 Dmitry Yemanov: allowed user-defined index names for PK/FK/UK constraints
|
|
|
|
* 2002.09.01 Dmitry Yemanov: RECREATE VIEW
|
2002-09-12 21:53:44 +02:00
|
|
|
* 2002.09.12 Nickolay Samofatov: fixed cached metadata errors
|
2005-05-28 00:45:31 +02:00
|
|
|
* 2004.01.16 Vlad Horsun: added support for default parameters and
|
2004-01-16 11:43:21 +01:00
|
|
|
* EXECUTE BLOCK statement
|
2007-04-13 03:37:44 +02:00
|
|
|
* Adriano dos Santos Fernandes
|
2001-05-23 15:26:42 +02:00
|
|
|
*/
|
|
|
|
|
2001-07-30 01:43:24 +02:00
|
|
|
#include "firebird.h"
|
2010-01-10 18:56:57 +01:00
|
|
|
#include "dyn_consts.h"
|
2004-04-29 00:00:03 +02:00
|
|
|
#include <stdio.h>
|
2001-05-23 15:26:42 +02:00
|
|
|
#include <string.h>
|
2007-04-12 17:56:34 +02:00
|
|
|
#include "../jrd/SysFunction.h"
|
2005-06-14 05:16:54 +02:00
|
|
|
#include "../common/classes/MetaName.h"
|
2001-05-23 15:26:42 +02:00
|
|
|
#include "../dsql/dsql.h"
|
2008-02-28 14:48:16 +01:00
|
|
|
#include "../dsql/node.h"
|
2010-10-22 17:00:22 +02:00
|
|
|
#include "../dsql/ExprNodes.h"
|
2003-11-08 00:27:24 +01:00
|
|
|
#include "../jrd/ibase.h"
|
2010-06-20 05:09:25 +02:00
|
|
|
#include "../jrd/Attachment.h"
|
2011-01-30 01:25:46 +01:00
|
|
|
#include "../jrd/RecordSourceNodes.h"
|
2001-05-23 15:26:42 +02:00
|
|
|
#include "../jrd/intl.h"
|
2008-03-01 20:14:46 +01:00
|
|
|
#include "../jrd/intl_classes.h"
|
2008-02-28 14:48:16 +01:00
|
|
|
#include "../jrd/jrd.h"
|
2001-05-23 15:26:42 +02:00
|
|
|
#include "../jrd/flags.h"
|
|
|
|
#include "../jrd/constants.h"
|
|
|
|
#include "../dsql/errd_proto.h"
|
|
|
|
#include "../dsql/ddl_proto.h"
|
|
|
|
#include "../dsql/gen_proto.h"
|
|
|
|
#include "../dsql/make_proto.h"
|
|
|
|
#include "../dsql/metd_proto.h"
|
|
|
|
#include "../dsql/pass1_proto.h"
|
2007-04-12 17:56:34 +02:00
|
|
|
#include "../dsql/utld_proto.h"
|
2008-03-01 20:14:46 +01:00
|
|
|
#include "../jrd/intl_proto.h"
|
2010-04-08 06:13:48 +02:00
|
|
|
#include "../jrd/dyn_proto.h"
|
2008-03-01 20:14:46 +01:00
|
|
|
#include "../jrd/met_proto.h"
|
2004-05-18 00:30:09 +02:00
|
|
|
#include "../jrd/thread_proto.h"
|
2010-10-12 10:02:57 +02:00
|
|
|
#include "../yvalve/gds_proto.h"
|
2008-02-28 14:48:16 +01:00
|
|
|
#include "../jrd/jrd_proto.h"
|
2009-10-21 02:42:38 +02:00
|
|
|
#include "../jrd/vio_proto.h"
|
2010-10-12 10:02:57 +02:00
|
|
|
#include "../yvalve/why_proto.h"
|
2006-08-31 11:06:15 +02:00
|
|
|
#include "../common/utils_proto.h"
|
2008-05-19 15:47:48 +02:00
|
|
|
#include "../dsql/DdlNodes.h"
|
2010-04-15 16:40:27 +02:00
|
|
|
#include "../dsql/DSqlDataTypeUtil.h"
|
2008-08-15 13:21:47 +02:00
|
|
|
#include "../common/StatusArg.h"
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-10-01 00:59:12 +02:00
|
|
|
#ifdef DSQL_DEBUG
|
2010-10-12 10:02:57 +02:00
|
|
|
#include "../common/prett_proto.h"
|
2001-05-23 15:26:42 +02:00
|
|
|
#endif
|
|
|
|
|
2008-02-28 14:48:16 +01:00
|
|
|
using namespace Jrd;
|
|
|
|
using namespace Dsql;
|
2008-08-15 13:21:47 +02:00
|
|
|
using namespace Firebird;
|
2008-02-28 14:48:16 +01:00
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-11-01 11:26:43 +01:00
|
|
|
static void assign_field_length(dsql_fld*, USHORT);
|
2009-12-20 22:01:10 +01:00
|
|
|
static void define_computed(DsqlCompilerScratch*, dsql_nod*, dsql_fld*, dsql_nod*);
|
|
|
|
static void define_database(DsqlCompilerScratch*);
|
|
|
|
static void define_filter(DsqlCompilerScratch*);
|
|
|
|
static SSHORT getBlobFilterSubType(DsqlCompilerScratch* dsqlScratch, const dsql_nod* node);
|
|
|
|
static void define_role(DsqlCompilerScratch*);
|
|
|
|
static void define_index(DsqlCompilerScratch*);
|
|
|
|
static void define_shadow(DsqlCompilerScratch*);
|
|
|
|
static void define_udf(DsqlCompilerScratch*);
|
|
|
|
static void generate_dyn(DsqlCompilerScratch*, dsql_nod*);
|
|
|
|
static void grant_revoke(DsqlCompilerScratch*);
|
|
|
|
static void modify_database(DsqlCompilerScratch*);
|
|
|
|
static void modify_index(DsqlCompilerScratch*);
|
|
|
|
static void modify_privilege(DsqlCompilerScratch* dsqlScratch, NOD_TYPE type, SSHORT option,
|
2008-06-10 12:55:48 +02:00
|
|
|
const UCHAR* privs, const dsql_nod* table,
|
|
|
|
const dsql_nod* user, const dsql_nod* grantor,
|
|
|
|
const dsql_str* field_name);
|
2009-12-20 22:01:10 +01:00
|
|
|
static char modify_privileges(DsqlCompilerScratch*, NOD_TYPE, SSHORT, const dsql_nod*,
|
2008-06-10 12:55:48 +02:00
|
|
|
const dsql_nod*, const dsql_nod*, const dsql_nod*);
|
2009-12-20 22:01:10 +01:00
|
|
|
static void modify_udf(DsqlCompilerScratch*);
|
|
|
|
static void modify_map(DsqlCompilerScratch*);
|
|
|
|
static void process_role_nm_list(DsqlCompilerScratch*, SSHORT, const dsql_nod*, const dsql_nod*, NOD_TYPE, const dsql_nod*);
|
|
|
|
static void put_field(DsqlCompilerScratch*, dsql_fld*, bool);
|
|
|
|
static void set_statistics(DsqlCompilerScratch*);
|
|
|
|
static void define_user(DsqlCompilerScratch*, UCHAR);
|
|
|
|
static void put_grantor(DsqlCompilerScratch* dsqlScratch, const dsql_nod* grantor);
|
2008-10-14 16:07:10 +02:00
|
|
|
static void post_607(const Arg::StatusVector& v);
|
2009-12-20 22:01:10 +01:00
|
|
|
static void put_user_grant(DsqlCompilerScratch* dsqlScratch, const dsql_nod* user);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
|
2003-09-28 02:36:28 +02:00
|
|
|
const int DEFAULT_BLOB_SEGMENT_SIZE = 80; // bytes
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
|
2003-11-01 11:26:43 +01:00
|
|
|
void DDL_execute(dsql_req* request)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* D D L _ e x e c u t e
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Call access method layered service DYN
|
2001-07-10 19:35:13 +02:00
|
|
|
* to interpret dyn string and perform
|
2001-05-23 15:26:42 +02:00
|
|
|
* metadata updates.
|
|
|
|
*
|
|
|
|
**************************************/
|
2008-02-28 14:48:16 +01:00
|
|
|
thread_db* tdbb = JRD_get_thread_data();
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2009-12-21 00:41:48 +01:00
|
|
|
const DsqlCompiledStatement* statement = request->getStatement();
|
2009-12-20 22:01:10 +01:00
|
|
|
|
2003-09-28 23:36:05 +02:00
|
|
|
#ifdef DSQL_DEBUG
|
2009-11-16 10:18:24 +01:00
|
|
|
if (DSQL_debug & 4)
|
|
|
|
{
|
2003-09-28 23:36:05 +02:00
|
|
|
dsql_trace("Output DYN string for DDL:");
|
2010-06-17 03:18:40 +02:00
|
|
|
PRETTY_print_dyn(statement->getDdlData().begin(), gds__trace_printer, NULL, 0);
|
2003-09-28 23:36:05 +02:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
#endif
|
|
|
|
|
2001-12-24 03:51:06 +01:00
|
|
|
// for delete & modify, get rid of the cached relation metadata
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-11-10 10:16:38 +01:00
|
|
|
const dsql_str* string = NULL;
|
2006-07-10 05:12:10 +02:00
|
|
|
SYM_TYPE sym_type;
|
|
|
|
|
2009-12-22 16:36:10 +01:00
|
|
|
const NOD_TYPE type = statement->getDdlNode()->nod_type;
|
2006-07-10 05:12:10 +02:00
|
|
|
|
|
|
|
switch (type)
|
2003-02-12 20:28:13 +01:00
|
|
|
{
|
2006-08-13 08:42:28 +02:00
|
|
|
case nod_del_udf:
|
|
|
|
case nod_mod_udf:
|
|
|
|
// Signal UDF for obsolescence
|
2009-12-22 16:36:10 +01:00
|
|
|
string = (dsql_str*) statement->getDdlNode()->nod_arg[e_udf_name];
|
2006-08-13 08:42:28 +02:00
|
|
|
sym_type = SYM_udf;
|
2010-06-26 04:50:07 +02:00
|
|
|
METD_drop_function(request->getTransaction(), QualifiedName(string->str_data, ""));
|
2003-02-12 20:28:13 +01:00
|
|
|
break;
|
|
|
|
}
|
2002-06-29 08:56:51 +02:00
|
|
|
|
2006-07-10 05:12:10 +02:00
|
|
|
if (string)
|
2008-03-01 20:14:46 +01:00
|
|
|
MET_dsql_cache_release(tdbb, sym_type, string->str_data);
|
2008-03-02 22:16:16 +01:00
|
|
|
|
2010-02-13 21:29:29 +01:00
|
|
|
if (type == nod_class_stmtnode)
|
2008-04-15 04:18:38 +02:00
|
|
|
{
|
2010-07-06 02:49:33 +02:00
|
|
|
fb_utils::init_status(tdbb->tdbb_status_vector); // Do the same as DYN_ddl does.
|
|
|
|
|
2009-10-21 02:42:38 +02:00
|
|
|
// run all statements under savepoint control
|
|
|
|
{ // scope
|
|
|
|
AutoSavePoint savePoint(tdbb, request->req_transaction);
|
|
|
|
|
2010-03-06 20:10:48 +01:00
|
|
|
DdlNode* ddlNode = reinterpret_cast<DdlNode*>(statement->getDdlNode()->nod_arg[0]);
|
2010-09-17 05:15:32 +02:00
|
|
|
ddlNode->executeDdl(tdbb, statement->getDdlScratch(), request->req_transaction);
|
2009-10-21 02:42:38 +02:00
|
|
|
|
|
|
|
savePoint.release(); // everything is ok
|
|
|
|
}
|
2008-04-15 04:18:38 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2010-06-17 03:18:40 +02:00
|
|
|
fb_assert(statement->getDdlData().getCount() <= MAX_ULONG);
|
2010-04-08 06:13:48 +02:00
|
|
|
DYN_ddl(request->req_transaction,
|
2010-06-17 03:18:40 +02:00
|
|
|
statement->getDdlData().getCount(), statement->getDdlData().begin(),
|
2010-04-08 06:13:48 +02:00
|
|
|
*statement->getSqlText());
|
2008-04-15 04:18:38 +02:00
|
|
|
}
|
2010-04-08 06:13:48 +02:00
|
|
|
|
|
|
|
JRD_autocommit_ddl(tdbb, request->req_transaction);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-12-20 22:01:10 +01:00
|
|
|
void DDL_generate(DsqlCompilerScratch* dsqlScratch, dsql_nod* node)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* D D L _ g e n e r a t e
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Generate the DYN string for a
|
|
|
|
* metadata update. Done during the
|
|
|
|
* prepare phase.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
|
2009-12-20 22:01:10 +01:00
|
|
|
if (dsqlScratch->getAttachment()->dbb_read_only)
|
2009-11-16 10:18:24 +01:00
|
|
|
{
|
2008-08-15 13:21:47 +02:00
|
|
|
ERRD_post(Arg::Gds(isc_read_only_database));
|
2001-05-23 15:26:42 +02:00
|
|
|
return;
|
|
|
|
}
|
2005-05-28 00:45:31 +02:00
|
|
|
|
2010-06-20 05:09:25 +02:00
|
|
|
dsqlScratch->getStatement()->setDdlNode(node);
|
|
|
|
|
2010-02-13 21:29:29 +01:00
|
|
|
if (node->nod_type != nod_class_stmtnode)
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(isc_dyn_version_1);
|
2009-10-21 02:42:38 +02:00
|
|
|
|
2009-12-20 22:01:10 +01:00
|
|
|
generate_dyn(dsqlScratch, node);
|
2009-10-21 02:42:38 +02:00
|
|
|
|
2010-02-13 21:29:29 +01:00
|
|
|
if (node->nod_type != nod_class_stmtnode)
|
2010-06-17 03:18:40 +02:00
|
|
|
{
|
|
|
|
dsqlScratch->appendUChar(isc_dyn_eoc);
|
|
|
|
|
|
|
|
// Store DYN data in the statement.
|
2010-06-17 18:06:54 +02:00
|
|
|
dsqlScratch->getStatement()->setDdlData(dsqlScratch->getBlrData());
|
2010-06-17 03:18:40 +02:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-02-12 20:28:13 +01:00
|
|
|
//
|
|
|
|
// Determine whether ids or names should be referenced
|
|
|
|
// when generating blr for fields and relations.
|
|
|
|
//
|
2009-12-20 22:01:10 +01:00
|
|
|
bool DDL_ids(const DsqlCompilerScratch* scratch)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2009-12-22 16:36:10 +01:00
|
|
|
return !scratch->getStatement()->getDdlNode();
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-02-12 20:28:13 +01:00
|
|
|
//
|
|
|
|
// See the next function for description. This is only a
|
2003-10-05 08:33:56 +02:00
|
|
|
// wrapper that sets the last parameter to false to indicate
|
2003-02-12 20:28:13 +01:00
|
|
|
// we are creating a field, not modifying one.
|
|
|
|
//
|
2011-03-06 03:48:34 +01:00
|
|
|
void DDL_resolve_intl_type(DsqlCompilerScratch* dsqlScratch, dsql_fld* field,
|
|
|
|
const MetaName& collation_name)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2009-12-20 22:01:10 +01:00
|
|
|
DDL_resolve_intl_type2(dsqlScratch, field, collation_name, false);
|
2002-06-29 08:56:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-03-06 03:48:34 +01:00
|
|
|
void DDL_resolve_intl_type2(DsqlCompilerScratch* dsqlScratch, dsql_fld* field,
|
|
|
|
const MetaName& collation_name, bool modifying)
|
2002-06-29 08:56:51 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* D D L _ r e s o l v e _ i n t l _ t y p e 2
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Function
|
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
* If the field is defined with a character set or collation,
|
|
|
|
* resolve the names to a subtype now.
|
|
|
|
*
|
|
|
|
* Also resolve the field length & whatnot.
|
|
|
|
*
|
2002-06-29 08:56:51 +02:00
|
|
|
* If the field is being created, it will pick the db-wide charset
|
|
|
|
* and collation if not specified. If the field is being modified,
|
|
|
|
* since we don't allow changes to those attributes, we'll go and
|
|
|
|
* calculate the correct old lenth from the field itself so DYN
|
|
|
|
* can validate the change properly.
|
|
|
|
*
|
2001-05-23 15:26:42 +02:00
|
|
|
* For International text fields, this is a good time to calculate
|
|
|
|
* their actual size - when declared they were declared in
|
|
|
|
* lengths of CHARACTERs, not BYTES.
|
|
|
|
*
|
|
|
|
**************************************/
|
2001-12-24 03:51:06 +01:00
|
|
|
|
2008-01-16 07:52:43 +01:00
|
|
|
if (field->fld_type_of_name.hasData())
|
2006-08-19 04:52:39 +02:00
|
|
|
{
|
2008-01-16 07:52:43 +01:00
|
|
|
if (field->fld_type_of_table)
|
2006-08-19 04:52:39 +02:00
|
|
|
{
|
2009-12-20 22:01:10 +01:00
|
|
|
dsql_rel* relation = METD_get_relation(dsqlScratch->getTransaction(), dsqlScratch,
|
2010-08-02 04:22:26 +02:00
|
|
|
field->fld_type_of_table->str_data);
|
2008-01-16 07:52:43 +01:00
|
|
|
const dsql_fld* fld = NULL;
|
|
|
|
|
|
|
|
if (relation)
|
|
|
|
{
|
2008-08-15 13:21:47 +02:00
|
|
|
const MetaName fieldName(field->fld_type_of_name);
|
2010-06-15 18:07:58 +02:00
|
|
|
|
2008-01-16 07:52:43 +01:00
|
|
|
for (fld = relation->rel_fields; fld; fld = fld->fld_next)
|
|
|
|
{
|
|
|
|
if (fieldName == fld->fld_name)
|
|
|
|
{
|
2009-06-19 17:47:16 +02:00
|
|
|
field->fld_dimensions = fld->fld_dimensions;
|
2008-01-16 07:52:43 +01:00
|
|
|
field->fld_source = fld->fld_source;
|
|
|
|
field->fld_length = fld->fld_length;
|
|
|
|
field->fld_scale = fld->fld_scale;
|
|
|
|
field->fld_sub_type = fld->fld_sub_type;
|
|
|
|
field->fld_character_set_id = fld->fld_character_set_id;
|
|
|
|
field->fld_collation_id = fld->fld_collation_id;
|
|
|
|
field->fld_character_length = fld->fld_character_length;
|
|
|
|
field->fld_flags = fld->fld_flags;
|
|
|
|
field->fld_dtype = fld->fld_dtype;
|
|
|
|
field->fld_seg_length = fld->fld_seg_length;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!fld)
|
|
|
|
{
|
2008-08-16 17:42:38 +02:00
|
|
|
// column @1 does not exist in table/view @2
|
2008-10-14 16:07:10 +02:00
|
|
|
post_607(Arg::Gds(isc_dyn_column_does_not_exist) <<
|
2009-01-06 06:53:34 +01:00
|
|
|
Arg::Str(field->fld_type_of_name) <<
|
|
|
|
Arg::Str(field->fld_type_of_table->str_data));
|
2008-01-16 07:52:43 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2009-12-20 22:01:10 +01:00
|
|
|
if (!METD_get_domain(dsqlScratch->getTransaction(), field, field->fld_type_of_name.c_str()))
|
2008-01-16 07:52:43 +01:00
|
|
|
{
|
2008-08-16 17:42:38 +02:00
|
|
|
// Specified domain or source field does not exist
|
2008-10-14 16:07:10 +02:00
|
|
|
post_607(Arg::Gds(isc_dsql_domain_not_found) << Arg::Str(field->fld_type_of_name));
|
2008-01-16 07:52:43 +01:00
|
|
|
}
|
2006-08-19 04:52:39 +02:00
|
|
|
}
|
2009-06-19 17:47:16 +02:00
|
|
|
|
|
|
|
if (field->fld_dimensions != 0)
|
|
|
|
{
|
|
|
|
ERRD_post(Arg::Gds(isc_wish_list) <<
|
|
|
|
Arg::Gds(isc_random) <<
|
|
|
|
Arg::Str("Usage of domain or TYPE OF COLUMN of array type in PSQL"));
|
|
|
|
}
|
2006-08-19 04:52:39 +02:00
|
|
|
}
|
|
|
|
|
2001-12-24 03:51:06 +01:00
|
|
|
if ((field->fld_dtype > dtype_any_text) && field->fld_dtype != dtype_blob)
|
|
|
|
{
|
2011-03-06 03:48:34 +01:00
|
|
|
if (field->fld_character_set || collation_name.hasData() || field->fld_flags & FLD_national)
|
2001-12-24 03:51:06 +01:00
|
|
|
{
|
2010-06-15 18:07:58 +02:00
|
|
|
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-204) <<
|
|
|
|
Arg::Gds(isc_dsql_datatype_err) << Arg::Gds(isc_collation_requires_text));
|
2001-12-24 03:51:06 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (field->fld_dtype == dtype_blob)
|
|
|
|
{
|
|
|
|
if (field->fld_sub_type_name)
|
|
|
|
{
|
2001-12-24 03:51:06 +01:00
|
|
|
SSHORT blob_sub_type;
|
2009-12-20 22:01:10 +01:00
|
|
|
if (!METD_get_type(dsqlScratch->getTransaction(),
|
|
|
|
reinterpret_cast<const dsql_str*>(field->fld_sub_type_name),
|
|
|
|
"RDB$FIELD_SUB_TYPE", &blob_sub_type))
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2008-11-16 09:36:48 +01:00
|
|
|
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-204) <<
|
|
|
|
Arg::Gds(isc_dsql_datatype_err) <<
|
2009-01-06 06:53:34 +01:00
|
|
|
Arg::Gds(isc_dsql_blob_type_unknown) <<
|
|
|
|
Arg::Str(((dsql_str*) field->fld_sub_type_name)->str_data));
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
field->fld_sub_type = blob_sub_type;
|
|
|
|
}
|
2010-06-15 18:07:58 +02:00
|
|
|
|
2006-06-02 10:44:19 +02:00
|
|
|
if (field->fld_sub_type > isc_blob_text)
|
|
|
|
{
|
2008-08-16 17:42:38 +02:00
|
|
|
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-204) <<
|
|
|
|
Arg::Gds(isc_dsql_datatype_err) <<
|
2008-08-15 13:21:47 +02:00
|
|
|
Arg::Gds(isc_subtype_for_internal_use));
|
2006-06-02 10:44:19 +02:00
|
|
|
}
|
2010-06-15 18:07:58 +02:00
|
|
|
|
2004-04-29 19:48:39 +02:00
|
|
|
if (field->fld_character_set && (field->fld_sub_type == isc_blob_untyped))
|
|
|
|
field->fld_sub_type = isc_blob_text;
|
2010-06-15 18:07:58 +02:00
|
|
|
|
2004-04-29 19:48:39 +02:00
|
|
|
if (field->fld_character_set && (field->fld_sub_type != isc_blob_text))
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2008-08-16 17:42:38 +02:00
|
|
|
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-204) <<
|
|
|
|
Arg::Gds(isc_dsql_datatype_err) <<
|
2008-08-15 13:21:47 +02:00
|
|
|
Arg::Gds(isc_collation_requires_text));
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
2010-06-15 18:07:58 +02:00
|
|
|
|
2011-03-06 03:48:34 +01:00
|
|
|
if (collation_name.hasData() && (field->fld_sub_type != isc_blob_text))
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2008-08-16 17:42:38 +02:00
|
|
|
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-204) <<
|
|
|
|
Arg::Gds(isc_dsql_datatype_err) <<
|
2008-08-15 13:21:47 +02:00
|
|
|
Arg::Gds(isc_collation_requires_text));
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
2010-06-15 18:07:58 +02:00
|
|
|
|
|
|
|
if (field->fld_sub_type != isc_blob_text)
|
2001-05-23 15:26:42 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2011-03-06 03:48:34 +01:00
|
|
|
if (field->fld_character_set_id != 0 && collation_name.isEmpty())
|
2009-11-16 10:18:24 +01:00
|
|
|
{
|
2001-12-24 03:51:06 +01:00
|
|
|
// This field has already been resolved once, and the collation
|
|
|
|
// hasn't changed. Therefore, no need to do it again.
|
2001-05-23 15:26:42 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2002-06-29 08:56:51 +02:00
|
|
|
|
2008-06-03 08:19:21 +02:00
|
|
|
if (modifying)
|
2003-02-12 20:28:13 +01:00
|
|
|
{
|
2009-01-02 07:36:12 +01:00
|
|
|
#ifdef DEV_BUILD
|
2009-12-20 22:01:10 +01:00
|
|
|
const dsql_rel* relation = dsqlScratch->relation;
|
2009-01-02 07:36:12 +01:00
|
|
|
#endif
|
2003-11-01 11:26:43 +01:00
|
|
|
const dsql_fld* afield = field->fld_next;
|
|
|
|
USHORT bpc = 0;
|
2010-06-15 18:07:58 +02:00
|
|
|
|
2009-11-16 10:18:24 +01:00
|
|
|
while (afield)
|
|
|
|
{
|
2008-01-16 07:52:43 +01:00
|
|
|
// The first test is redundant.
|
2009-01-06 06:53:34 +01:00
|
|
|
if (afield != field && afield->fld_relation && afield->fld_name == field->fld_name)
|
2003-10-16 10:51:06 +02:00
|
|
|
{
|
2008-01-16 07:52:43 +01:00
|
|
|
fb_assert(afield->fld_relation == relation || !relation);
|
|
|
|
break;
|
|
|
|
}
|
2010-06-15 18:07:58 +02:00
|
|
|
|
2008-01-16 07:52:43 +01:00
|
|
|
afield = afield->fld_next;
|
|
|
|
}
|
2010-06-15 18:07:58 +02:00
|
|
|
|
2009-11-16 10:18:24 +01:00
|
|
|
if (afield)
|
|
|
|
{
|
2008-01-16 07:52:43 +01:00
|
|
|
field->fld_character_set_id = afield->fld_character_set_id;
|
2009-12-20 22:01:10 +01:00
|
|
|
bpc = METD_get_charset_bpc(dsqlScratch->getTransaction(), field->fld_character_set_id);
|
2008-01-16 07:52:43 +01:00
|
|
|
field->fld_collation_id = afield->fld_collation_id;
|
|
|
|
field->fld_ttype = afield->fld_ttype;
|
2002-06-29 08:56:51 +02:00
|
|
|
|
2010-06-15 18:07:58 +02:00
|
|
|
if (afield->fld_flags & FLD_national)
|
2008-06-03 08:19:21 +02:00
|
|
|
field->fld_flags |= FLD_national;
|
2010-06-15 18:07:58 +02:00
|
|
|
else
|
2008-06-03 08:19:21 +02:00
|
|
|
field->fld_flags &= ~FLD_national;
|
2005-05-28 00:45:31 +02:00
|
|
|
|
2008-06-03 08:19:21 +02:00
|
|
|
assign_field_length (field, bpc);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2002-06-29 08:56:51 +02:00
|
|
|
|
2005-05-28 00:45:31 +02:00
|
|
|
if (!(field->fld_character_set || field->fld_character_set_id || // set if a domain
|
2009-01-06 06:53:34 +01:00
|
|
|
(field->fld_flags & FLD_national)))
|
2001-12-24 03:51:06 +01:00
|
|
|
{
|
|
|
|
// Attach the database default character set, if not otherwise specified
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2010-06-20 05:09:25 +02:00
|
|
|
const dsql_str* dfl_charset = NULL;
|
|
|
|
|
|
|
|
if (dsqlScratch->getStatement()->getDdlNode() ||
|
|
|
|
(dsqlScratch->flags & (
|
|
|
|
DsqlCompilerScratch::FLAG_FUNCTION | DsqlCompilerScratch::FLAG_PROCEDURE |
|
|
|
|
DsqlCompilerScratch::FLAG_TRIGGER)))
|
|
|
|
{
|
|
|
|
dfl_charset = METD_get_default_charset(dsqlScratch->getTransaction());
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
USHORT charSet = dsqlScratch->getAttachment()->dbb_attachment->att_charset;
|
|
|
|
if (charSet != CS_NONE)
|
|
|
|
{
|
|
|
|
MetaName charSetName = METD_get_charset_name(dsqlScratch->getTransaction(), charSet);
|
|
|
|
dfl_charset = MAKE_string(charSetName.c_str(), charSetName.length());
|
|
|
|
}
|
|
|
|
}
|
2010-06-15 18:07:58 +02:00
|
|
|
|
2001-12-24 03:51:06 +01:00
|
|
|
if (dfl_charset)
|
2003-11-01 11:26:43 +01:00
|
|
|
field->fld_character_set = (dsql_nod*) dfl_charset;
|
2001-12-24 03:51:06 +01:00
|
|
|
else
|
|
|
|
{
|
2009-04-18 16:13:26 +02:00
|
|
|
// If field is not specified with NATIONAL, or CHARACTER SET
|
|
|
|
// treat it as a single-byte-per-character field of character set NONE.
|
|
|
|
assign_field_length(field, 1);
|
2008-06-03 08:19:21 +02:00
|
|
|
field->fld_ttype = 0;
|
2010-06-15 18:07:58 +02:00
|
|
|
|
2011-03-06 03:48:34 +01:00
|
|
|
if (collation_name.isEmpty())
|
2001-05-23 15:26:42 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-06-15 18:07:58 +02:00
|
|
|
const char* charset_name = NULL;
|
2001-12-24 03:51:06 +01:00
|
|
|
|
2010-06-15 18:07:58 +02:00
|
|
|
if (field->fld_flags & FLD_national)
|
2003-02-12 20:28:13 +01:00
|
|
|
charset_name = NATIONAL_CHARACTER_SET;
|
2010-06-15 18:07:58 +02:00
|
|
|
else if (field->fld_character_set)
|
2003-11-10 10:16:38 +01:00
|
|
|
charset_name = ((dsql_str*) field->fld_character_set)->str_data;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2009-04-18 16:13:26 +02:00
|
|
|
// Find an intlsym for any specified character set name & collation name
|
2005-06-06 10:30:03 +02:00
|
|
|
const dsql_intlsym* resolved_type = NULL;
|
2005-05-28 00:45:31 +02:00
|
|
|
|
2001-12-24 03:51:06 +01:00
|
|
|
if (charset_name)
|
|
|
|
{
|
2005-06-06 10:30:03 +02:00
|
|
|
const dsql_intlsym* resolved_charset =
|
2009-12-20 22:01:10 +01:00
|
|
|
METD_get_charset(dsqlScratch->getTransaction(), (USHORT) strlen(charset_name), charset_name);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2001-12-24 03:51:06 +01:00
|
|
|
// Error code -204 (IBM's DB2 manual) is close enough
|
2001-05-23 15:26:42 +02:00
|
|
|
if (!resolved_charset)
|
2001-12-24 03:51:06 +01:00
|
|
|
{
|
|
|
|
// specified character set not found
|
2008-08-16 17:42:38 +02:00
|
|
|
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-204) <<
|
|
|
|
Arg::Gds(isc_dsql_datatype_err) <<
|
2008-08-15 13:21:47 +02:00
|
|
|
Arg::Gds(isc_charset_not_found) << Arg::Str(charset_name));
|
2001-12-24 03:51:06 +01:00
|
|
|
}
|
2010-06-15 18:07:58 +02:00
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
field->fld_character_set_id = resolved_charset->intlsym_charset_id;
|
|
|
|
resolved_type = resolved_charset;
|
|
|
|
}
|
|
|
|
|
2011-03-06 03:48:34 +01:00
|
|
|
if (collation_name.hasData())
|
2001-12-24 03:51:06 +01:00
|
|
|
{
|
2009-12-20 22:01:10 +01:00
|
|
|
const dsql_intlsym* resolved_collation = METD_get_collation(dsqlScratch->getTransaction(),
|
2011-03-06 03:48:34 +01:00
|
|
|
collation_name, field->fld_character_set_id);
|
2001-12-24 03:51:06 +01:00
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
if (!resolved_collation)
|
2001-12-24 03:51:06 +01:00
|
|
|
{
|
2008-08-15 13:21:47 +02:00
|
|
|
MetaName charSetName;
|
2005-06-14 05:16:54 +02:00
|
|
|
|
|
|
|
if (charset_name)
|
|
|
|
charSetName = charset_name;
|
|
|
|
else
|
2009-12-20 22:01:10 +01:00
|
|
|
{
|
|
|
|
charSetName = METD_get_charset_name(dsqlScratch->getTransaction(),
|
|
|
|
field->fld_character_set_id);
|
|
|
|
}
|
2005-06-14 05:16:54 +02:00
|
|
|
|
2001-12-24 03:51:06 +01:00
|
|
|
// Specified collation not found
|
2008-08-16 17:42:38 +02:00
|
|
|
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-204) <<
|
|
|
|
Arg::Gds(isc_dsql_datatype_err) <<
|
2011-03-06 03:48:34 +01:00
|
|
|
Arg::Gds(isc_collation_not_found) << collation_name << charSetName);
|
2001-12-24 03:51:06 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2001-12-24 03:51:06 +01:00
|
|
|
// If both specified, must be for same character set
|
|
|
|
// A "literal constant" must be handled (charset as ttype_dynamic)
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
resolved_type = resolved_collation;
|
2010-06-15 18:07:58 +02:00
|
|
|
|
2008-12-31 06:06:08 +01:00
|
|
|
if ((field->fld_character_set_id != resolved_type->intlsym_charset_id) &&
|
|
|
|
(field->fld_character_set_id != ttype_dynamic))
|
2001-12-24 03:51:06 +01:00
|
|
|
{
|
2008-08-16 17:42:38 +02:00
|
|
|
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-204) <<
|
|
|
|
Arg::Gds(isc_dsql_datatype_err) <<
|
2011-03-06 03:48:34 +01:00
|
|
|
Arg::Gds(isc_collation_not_for_charset) << collation_name);
|
2001-12-24 03:51:06 +01:00
|
|
|
}
|
2006-08-19 04:52:39 +02:00
|
|
|
|
|
|
|
field->fld_explicit_collation = true;
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
2008-06-03 08:19:21 +02:00
|
|
|
assign_field_length (field, resolved_type->intlsym_bytes_per_char);
|
2002-06-29 08:56:51 +02:00
|
|
|
|
2010-06-15 18:07:58 +02:00
|
|
|
field->fld_ttype = resolved_type->intlsym_ttype;
|
2002-06-29 08:56:51 +02:00
|
|
|
field->fld_character_set_id = resolved_type->intlsym_charset_id;
|
2010-06-15 18:07:58 +02:00
|
|
|
field->fld_collation_id = resolved_type->intlsym_collate_id;
|
2002-06-29 08:56:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-11-19 05:25:56 +01:00
|
|
|
static void assign_field_length(dsql_fld* field, USHORT bytes_per_char)
|
2002-06-29 08:56:51 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* a s s i g n _ f i e l d _ l e n g t h
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Function
|
|
|
|
* We'll see if the field's length fits in the maximum
|
|
|
|
* allowed field, including charset and space for varchars.
|
|
|
|
* Either we raise an error or assign the field's length.
|
|
|
|
* If the charlen comes as zero, we do nothing, although we
|
|
|
|
* know that DYN, MET and DFW will blindly set field length
|
|
|
|
* to zero if they don't catch charlen or another condition.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
|
2001-12-24 03:51:06 +01:00
|
|
|
if (field->fld_character_length)
|
|
|
|
{
|
2008-11-19 05:25:56 +01:00
|
|
|
ULONG field_length = (ULONG) bytes_per_char * field->fld_character_length;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2001-12-24 03:51:06 +01:00
|
|
|
if (field->fld_dtype == dtype_varying) {
|
2001-05-23 15:26:42 +02:00
|
|
|
field_length += sizeof(USHORT);
|
2001-12-24 03:51:06 +01:00
|
|
|
}
|
2004-04-29 16:51:02 +02:00
|
|
|
if (field_length > MAX_COLUMN_SIZE)
|
2001-12-24 03:51:06 +01:00
|
|
|
{
|
2008-08-16 17:42:38 +02:00
|
|
|
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-204) <<
|
|
|
|
Arg::Gds(isc_dsql_datatype_err) <<
|
2008-08-15 13:21:47 +02:00
|
|
|
Arg::Gds(isc_imp_exc) <<
|
|
|
|
Arg::Gds(isc_field_name) << Arg::Str(field->fld_name));
|
2001-12-24 03:51:06 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
field->fld_length = (USHORT) field_length;
|
2002-06-29 08:56:51 +02:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-12-20 22:01:10 +01:00
|
|
|
static void define_computed(DsqlCompilerScratch* dsqlScratch,
|
2003-11-01 11:26:43 +01:00
|
|
|
dsql_nod* relation_node,
|
|
|
|
dsql_fld* field,
|
|
|
|
dsql_nod* node)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* d e f i n e _ c o m p u t e d
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Function
|
2001-07-10 19:35:13 +02:00
|
|
|
* Create the ddl to define a computed field
|
|
|
|
* or an expression index.
|
2001-05-23 15:26:42 +02:00
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
|
2009-12-20 22:01:10 +01:00
|
|
|
DsqlCompiledStatement* statement = dsqlScratch->getStatement();
|
2009-12-22 16:36:10 +01:00
|
|
|
dsql_nod* const saved_ddl_node = statement->getDdlNode();
|
|
|
|
statement->setDdlNode(node);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2001-12-24 03:51:06 +01:00
|
|
|
// Get the table node & set up correct context
|
2010-07-26 04:37:57 +02:00
|
|
|
DDL_reset_context_stack(dsqlScratch);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-10-16 10:51:06 +02:00
|
|
|
dsc save_desc;
|
2001-12-24 03:51:06 +01:00
|
|
|
// Save the size of the field if it is specified
|
2001-05-23 15:26:42 +02:00
|
|
|
save_desc.dsc_dtype = 0;
|
|
|
|
|
2001-12-24 03:51:06 +01:00
|
|
|
if (field && field->fld_dtype)
|
|
|
|
{
|
2003-11-04 00:59:24 +01:00
|
|
|
fb_assert(field->fld_dtype <= MAX_UCHAR);
|
2001-05-23 15:26:42 +02:00
|
|
|
save_desc.dsc_dtype = (UCHAR) field->fld_dtype;
|
|
|
|
save_desc.dsc_length = field->fld_length;
|
2003-11-04 00:59:24 +01:00
|
|
|
fb_assert(field->fld_scale <= MAX_SCHAR);
|
2001-05-23 15:26:42 +02:00
|
|
|
save_desc.dsc_scale = (SCHAR) field->fld_scale;
|
2005-10-08 08:52:57 +02:00
|
|
|
save_desc.dsc_sub_type = field->fld_sub_type;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
field->fld_dtype = 0;
|
|
|
|
field->fld_length = 0;
|
|
|
|
field->fld_scale = 0;
|
2005-10-08 08:52:57 +02:00
|
|
|
field->fld_sub_type = 0;
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
2009-12-20 22:01:10 +01:00
|
|
|
PASS1_make_context(dsqlScratch, relation_node);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2009-12-20 22:01:10 +01:00
|
|
|
dsql_nod* input = PASS1_node(dsqlScratch, node->nod_arg[e_cmp_expr]);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2007-06-02 21:13:29 +02:00
|
|
|
// try to calculate size of the computed field. The calculated size
|
|
|
|
// may be ignored, but it will catch self references
|
|
|
|
dsc desc;
|
2010-11-01 01:42:12 +01:00
|
|
|
MAKE_desc(dsqlScratch, &desc, input);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2001-12-24 03:51:06 +01:00
|
|
|
// generate the blr expression
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->beginBlr(isc_dyn_fld_computed_blr);
|
2009-12-20 22:01:10 +01:00
|
|
|
GEN_expr(dsqlScratch, input);
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->endBlr();
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2009-11-16 10:18:24 +01:00
|
|
|
if (save_desc.dsc_dtype)
|
|
|
|
{
|
2001-12-24 03:51:06 +01:00
|
|
|
// restore the field size/type overrides
|
|
|
|
field->fld_dtype = save_desc.dsc_dtype;
|
2001-05-23 15:26:42 +02:00
|
|
|
field->fld_length = save_desc.dsc_length;
|
2001-12-24 03:51:06 +01:00
|
|
|
field->fld_scale = save_desc.dsc_scale;
|
2005-10-08 08:52:57 +02:00
|
|
|
if (field->fld_dtype <= dtype_any_text)
|
|
|
|
{
|
|
|
|
field->fld_character_set_id = DSC_GET_CHARSET(&save_desc);
|
|
|
|
field->fld_collation_id= DSC_GET_COLLATE(&save_desc);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
field->fld_sub_type = save_desc.dsc_sub_type;
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
2009-11-16 10:18:24 +01:00
|
|
|
else if (field)
|
|
|
|
{
|
2001-12-24 03:51:06 +01:00
|
|
|
// use size calculated
|
|
|
|
field->fld_dtype = desc.dsc_dtype;
|
2001-05-23 15:26:42 +02:00
|
|
|
field->fld_length = desc.dsc_length;
|
2001-12-24 03:51:06 +01:00
|
|
|
field->fld_scale = desc.dsc_scale;
|
2005-10-08 08:52:57 +02:00
|
|
|
if (field->fld_dtype <= dtype_any_text)
|
|
|
|
{
|
|
|
|
field->fld_character_set_id = DSC_GET_CHARSET(&desc);
|
|
|
|
field->fld_collation_id= DSC_GET_COLLATE(&desc);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
field->fld_sub_type = desc.dsc_sub_type;
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
2009-12-23 01:57:08 +01:00
|
|
|
statement->setType(DsqlCompiledStatement::TYPE_DDL);
|
2009-12-22 16:36:10 +01:00
|
|
|
statement->setDdlNode(saved_ddl_node);
|
2010-07-26 04:37:57 +02:00
|
|
|
DDL_reset_context_stack(dsqlScratch);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2001-12-24 03:51:06 +01:00
|
|
|
// generate the source text
|
2003-11-10 10:16:38 +01:00
|
|
|
const dsql_str* source = (dsql_str*) node->nod_arg[e_cmp_text];
|
2003-11-04 00:59:24 +01:00
|
|
|
fb_assert(source->str_length <= MAX_USHORT);
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendString(isc_dyn_fld_computed_source, source->str_data,
|
|
|
|
(USHORT) source->str_length);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-12-20 22:01:10 +01:00
|
|
|
static void define_database(DsqlCompilerScratch* dsqlScratch)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* d e f i n e _ d a t a b a s e
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Function
|
2001-07-10 19:35:13 +02:00
|
|
|
* Create a database. Assumes that
|
|
|
|
* database is created elsewhere with
|
|
|
|
* initial options. Modify the
|
2001-05-23 15:26:42 +02:00
|
|
|
* database using DYN to add the remaining
|
|
|
|
* options.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
SLONG start = 0;
|
|
|
|
|
2009-12-20 22:01:10 +01:00
|
|
|
DsqlCompiledStatement* statement = dsqlScratch->getStatement();
|
2009-12-22 16:36:10 +01:00
|
|
|
const dsql_nod* ddl_node = statement->getDdlNode();
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(isc_dyn_mod_database);
|
2009-04-18 16:13:26 +02:00
|
|
|
|
2010-06-17 03:18:40 +02:00
|
|
|
// dsqlScratch->appendNumber(isc_dyn_rel_sql_protection, 1);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-11-01 11:26:43 +01:00
|
|
|
const dsql_nod* elements = ddl_node->nod_arg[e_database_initial_desc];
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2009-01-06 06:53:34 +01:00
|
|
|
if (elements)
|
|
|
|
{
|
2003-11-01 11:26:43 +01:00
|
|
|
const dsql_nod* const* ptr = elements->nod_arg;
|
2008-11-19 05:25:56 +01:00
|
|
|
for (const dsql_nod* const* const end = ptr + elements->nod_count; ptr < end; ptr++)
|
2003-10-16 10:51:06 +02:00
|
|
|
{
|
|
|
|
const dsql_nod* element = *ptr;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2005-05-22 05:11:41 +02:00
|
|
|
switch (element->nod_type)
|
|
|
|
{
|
2001-05-23 15:26:42 +02:00
|
|
|
case nod_file_length:
|
2007-10-17 16:35:31 +02:00
|
|
|
start = (IPTR) element->nod_arg[0] + 1;
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2003-11-01 11:26:43 +01:00
|
|
|
}
|
2005-05-28 00:45:31 +02:00
|
|
|
|
2003-11-10 10:16:38 +01:00
|
|
|
const dsql_str* name;
|
|
|
|
const dsql_fil* file;
|
2001-05-23 15:26:42 +02:00
|
|
|
elements = ddl_node->nod_arg[e_database_rem_desc];
|
|
|
|
if (elements)
|
2001-12-24 03:51:06 +01:00
|
|
|
{
|
2003-11-01 11:26:43 +01:00
|
|
|
const dsql_nod* const* ptr = elements->nod_arg;
|
2008-11-19 05:25:56 +01:00
|
|
|
for (const dsql_nod* const* const end = ptr + elements->nod_count; ptr < end; ptr++)
|
2001-12-24 03:51:06 +01:00
|
|
|
{
|
2003-10-16 10:51:06 +02:00
|
|
|
const dsql_nod* element = *ptr;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-11-19 05:25:56 +01:00
|
|
|
switch (element->nod_type)
|
|
|
|
{
|
2003-08-06 18:30:49 +02:00
|
|
|
case nod_difference_file:
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendNullString(isc_dyn_def_difference,
|
2009-01-06 06:53:34 +01:00
|
|
|
((dsql_str*) element->nod_arg[0])->str_data);
|
2003-08-06 18:30:49 +02:00
|
|
|
break;
|
2001-05-23 15:26:42 +02:00
|
|
|
case nod_file_desc:
|
2003-11-10 10:16:38 +01:00
|
|
|
file = (dsql_fil*) element->nod_arg[0];
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendNullString(isc_dyn_def_file, file->fil_name->str_data);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2001-12-24 03:51:06 +01:00
|
|
|
start = MAX(start, file->fil_start);
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendFileStart(start);
|
|
|
|
dsqlScratch->appendFileLength(file->fil_length);
|
|
|
|
dsqlScratch->appendUChar(isc_dyn_end);
|
2001-05-23 15:26:42 +02:00
|
|
|
start += file->fil_length;
|
|
|
|
break;
|
|
|
|
case nod_dfl_charset:
|
2003-11-10 10:16:38 +01:00
|
|
|
name = (dsql_str*) element->nod_arg[0];
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendNullString(isc_dyn_fld_character_set_name, name->str_data);
|
2008-04-15 04:18:38 +02:00
|
|
|
break;
|
|
|
|
case nod_dfl_collate:
|
|
|
|
name = (dsql_str*) element->nod_arg[0];
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendNullString(isc_dyn_fld_collation, name->str_data);
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2001-12-24 03:51:06 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(isc_dyn_end);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-12-20 22:01:10 +01:00
|
|
|
static SSHORT getBlobFilterSubType(DsqlCompilerScratch* dsqlScratch, const dsql_nod* node)
|
2004-09-08 14:01:30 +02:00
|
|
|
{
|
|
|
|
/*******************************************
|
|
|
|
*
|
|
|
|
* g e t B l o b F i l t e r S u b T y p e
|
|
|
|
*
|
|
|
|
*******************************************
|
|
|
|
*
|
|
|
|
* Function
|
2010-10-24 02:26:00 +02:00
|
|
|
* get sub_type value from LiteralNode.
|
2004-09-08 14:01:30 +02:00
|
|
|
*
|
|
|
|
**************************************/
|
2010-10-24 02:26:00 +02:00
|
|
|
const LiteralNode* literal = ExprNode::as<LiteralNode>(node);
|
|
|
|
fb_assert(literal);
|
|
|
|
|
|
|
|
switch (literal->litDesc.dsc_dtype)
|
2004-09-08 14:01:30 +02:00
|
|
|
{
|
|
|
|
case dtype_long:
|
2010-10-24 02:26:00 +02:00
|
|
|
return (SSHORT) literal->getSlong();
|
2004-09-08 14:01:30 +02:00
|
|
|
case dtype_text:
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
fb_assert(false);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// fall thru for dtype_text
|
2009-01-06 06:53:34 +01:00
|
|
|
const dsql_str* type_name = reinterpret_cast<const dsql_str*>(node->nod_arg[0]);
|
2004-09-08 14:01:30 +02:00
|
|
|
SSHORT blob_sub_type;
|
2009-12-20 22:01:10 +01:00
|
|
|
if (!METD_get_type(dsqlScratch->getTransaction(), type_name, "RDB$FIELD_SUB_TYPE", &blob_sub_type))
|
2004-09-08 14:01:30 +02:00
|
|
|
{
|
2008-08-15 13:21:47 +02:00
|
|
|
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-204) <<
|
|
|
|
Arg::Gds(isc_dsql_datatype_err) <<
|
2009-01-06 06:53:34 +01:00
|
|
|
Arg::Gds(isc_dsql_blob_type_unknown) << Arg::Str(type_name->str_data));
|
2004-09-08 14:01:30 +02:00
|
|
|
}
|
|
|
|
return blob_sub_type;
|
|
|
|
}
|
|
|
|
|
2009-12-20 22:01:10 +01:00
|
|
|
static void define_filter(DsqlCompilerScratch* dsqlScratch)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* d e f i n e _ f i l t e r
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Function
|
|
|
|
* define a filter to the database.
|
|
|
|
*
|
|
|
|
**************************************/
|
2009-12-20 22:01:10 +01:00
|
|
|
DsqlCompiledStatement* statement = dsqlScratch->getStatement();
|
2009-12-22 16:36:10 +01:00
|
|
|
const dsql_nod* filter_node = statement->getDdlNode();
|
2003-11-18 08:58:35 +01:00
|
|
|
const dsql_nod* const* ptr = filter_node->nod_arg;
|
2009-12-20 22:01:10 +01:00
|
|
|
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendNullString(isc_dyn_def_filter, ((dsql_str*) (ptr[e_filter_name]))->str_data);
|
|
|
|
dsqlScratch->appendNumber(isc_dyn_filter_in_subtype,
|
2009-12-20 22:01:10 +01:00
|
|
|
getBlobFilterSubType(dsqlScratch, ptr[e_filter_in_type]));
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendNumber(isc_dyn_filter_out_subtype,
|
2009-12-20 22:01:10 +01:00
|
|
|
getBlobFilterSubType(dsqlScratch, ptr[e_filter_out_type]));
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendNullString(isc_dyn_func_entry_point,
|
2009-12-20 22:01:10 +01:00
|
|
|
((dsql_str*) (ptr[e_filter_entry_pt]))->str_data);
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendNullString(isc_dyn_func_module_name,
|
2009-12-20 22:01:10 +01:00
|
|
|
((dsql_str*) (ptr[e_filter_module]))->str_data);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(isc_dyn_end);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-12-20 22:01:10 +01:00
|
|
|
static void define_index(DsqlCompilerScratch* dsqlScratch)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* d e f i n e _ i n d e x
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Function
|
|
|
|
* Generate ddl to create an index.
|
|
|
|
*
|
|
|
|
**************************************/
|
2009-12-20 22:01:10 +01:00
|
|
|
DsqlCompiledStatement* statement = dsqlScratch->getStatement();
|
|
|
|
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(isc_dyn_begin);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2009-12-22 16:36:10 +01:00
|
|
|
const dsql_nod* ddl_node = statement->getDdlNode();
|
2003-11-01 11:26:43 +01:00
|
|
|
dsql_nod* relation_node = (dsql_nod*) ddl_node->nod_arg[e_idx_table];
|
2011-01-30 01:25:46 +01:00
|
|
|
const MetaName& relation_name = ExprNode::as<RelationSourceNode>(relation_node)->dsqlName;
|
2003-11-01 11:26:43 +01:00
|
|
|
dsql_nod* field_list = ddl_node->nod_arg[e_idx_fields];
|
2003-11-10 10:16:38 +01:00
|
|
|
const dsql_str* index_name = (dsql_str*) ddl_node->nod_arg[e_idx_name];
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendNullString(isc_dyn_def_idx, index_name->str_data);
|
2011-01-30 01:25:46 +01:00
|
|
|
dsqlScratch->appendNullString(isc_dyn_rel_name, relation_name.c_str());
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2009-04-18 16:13:26 +02:00
|
|
|
// go through the fields list, making an index segment for each field,
|
|
|
|
// unless we have a computation, in which case generate an expression index
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
if (field_list->nod_type == nod_list)
|
2003-10-16 10:51:06 +02:00
|
|
|
{
|
2003-11-18 08:58:35 +01:00
|
|
|
const dsql_nod* const* ptr = field_list->nod_arg;
|
|
|
|
const dsql_nod* const* const end = ptr + field_list->nod_count;
|
2003-10-16 10:51:06 +02:00
|
|
|
for (; ptr < end; ptr++)
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendNullString(isc_dyn_fld_name, ((dsql_str*) (*ptr)->nod_arg[1])->str_data);
|
2003-10-16 10:51:06 +02:00
|
|
|
}
|
2010-07-26 04:37:57 +02:00
|
|
|
else if (field_list->nod_type == nod_def_computed)
|
|
|
|
define_computed(dsqlScratch, relation_node, NULL, field_list);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2010-07-26 04:37:57 +02:00
|
|
|
// check for a unique index
|
2001-12-24 03:51:06 +01:00
|
|
|
|
2010-07-26 04:37:57 +02:00
|
|
|
if (ddl_node->nod_arg[e_idx_unique]) {
|
|
|
|
dsqlScratch->appendNumber(isc_dyn_idx_unique, 1);
|
|
|
|
}
|
2001-12-24 03:51:06 +01:00
|
|
|
|
2010-07-26 04:37:57 +02:00
|
|
|
if (ddl_node->nod_arg[e_idx_asc_dsc]) {
|
|
|
|
dsqlScratch->appendNumber(isc_dyn_idx_type, 1);
|
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2010-07-26 04:37:57 +02:00
|
|
|
dsqlScratch->appendUChar(isc_dyn_end); // of define index
|
|
|
|
dsqlScratch->appendUChar(isc_dyn_end); // of begin
|
|
|
|
}
|
2010-06-17 03:18:40 +02:00
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2010-07-26 04:37:57 +02:00
|
|
|
// ******************************
|
|
|
|
// d e f i n e _ r o l e
|
|
|
|
// ******************************
|
|
|
|
// Create a SQL role.
|
|
|
|
//
|
|
|
|
static void define_role(DsqlCompilerScratch* dsqlScratch)
|
|
|
|
{
|
|
|
|
DsqlCompiledStatement* statement = dsqlScratch->getStatement();
|
|
|
|
const dsql_str* role_name = (dsql_str*) statement->getDdlNode()->nod_arg[0];
|
2002-06-29 08:56:51 +02:00
|
|
|
|
2010-07-26 04:37:57 +02:00
|
|
|
dsqlScratch->appendNullString(isc_dyn_def_sql_role, role_name->str_data);
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(isc_dyn_end);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2001-12-24 03:51:06 +01:00
|
|
|
//
|
|
|
|
// create a shadow for the database
|
|
|
|
//
|
2009-12-20 22:01:10 +01:00
|
|
|
static void define_shadow(DsqlCompilerScratch* dsqlScratch)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2009-12-20 22:01:10 +01:00
|
|
|
DsqlCompiledStatement* statement = dsqlScratch->getStatement();
|
2009-12-22 16:36:10 +01:00
|
|
|
const dsql_nod* shadow_node = statement->getDdlNode();
|
2009-01-06 06:53:34 +01:00
|
|
|
const dsql_nod* const* ptr = shadow_node->nod_arg;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
if (!ptr[e_shadow_number])
|
2001-12-24 03:51:06 +01:00
|
|
|
{
|
2008-10-14 16:07:10 +02:00
|
|
|
post_607(Arg::Gds(isc_dsql_shadow_number_err));
|
2001-12-24 03:51:06 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendNumber(isc_dyn_def_shadow, (SSHORT)(IPTR) (ptr[e_shadow_number]));
|
|
|
|
dsqlScratch->appendNullString(isc_dyn_def_file, ((dsql_str*) (ptr[e_shadow_name]))->str_data);
|
2010-10-24 02:26:00 +02:00
|
|
|
dsqlScratch->appendNumber(isc_dyn_shadow_man_auto,
|
|
|
|
(SSHORT) ExprNode::as<LiteralNode>(ptr[e_shadow_man_auto])->getSlong());
|
|
|
|
dsqlScratch->appendNumber(isc_dyn_shadow_conditional,
|
|
|
|
(SSHORT) ExprNode::as<LiteralNode>(ptr[e_shadow_conditional])->getSlong());
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendFileStart(0);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2004-01-21 08:18:30 +01:00
|
|
|
SLONG length = (IPTR) ptr[e_shadow_length];
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendFileLength(length);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(isc_dyn_end);
|
2003-11-18 08:58:35 +01:00
|
|
|
const dsql_nod* elements = ptr[e_shadow_sec_files];
|
2001-05-23 15:26:42 +02:00
|
|
|
if (elements)
|
2001-12-24 03:51:06 +01:00
|
|
|
{
|
2003-11-01 11:26:43 +01:00
|
|
|
ptr = elements->nod_arg;
|
2009-01-06 06:53:34 +01:00
|
|
|
for (const dsql_nod* const* const end = ptr + elements->nod_count; ptr < end; ++ptr)
|
2001-12-24 03:51:06 +01:00
|
|
|
{
|
2003-11-18 08:58:35 +01:00
|
|
|
const dsql_nod* element = *ptr;
|
|
|
|
const dsql_fil* file = (dsql_fil*) element->nod_arg[0];
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendNullString(isc_dyn_def_file, file->fil_name->str_data);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
if (!length && !file->fil_start)
|
2001-12-24 03:51:06 +01:00
|
|
|
{
|
2008-08-16 17:42:38 +02:00
|
|
|
// Preceding file did not specify length, so %s must include starting page number
|
2008-10-14 16:07:10 +02:00
|
|
|
post_607(Arg::Gds(isc_dsql_file_length_err) << Arg::Str(file->fil_name->str_data));
|
2001-12-24 03:51:06 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-11-18 08:58:35 +01:00
|
|
|
const SLONG start = file->fil_start;
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendFileStart(start);
|
2001-05-23 15:26:42 +02:00
|
|
|
length = file->fil_length;
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendFileLength(length);
|
|
|
|
dsqlScratch->appendUChar(isc_dyn_end);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
2001-12-24 03:51:06 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(isc_dyn_end);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-12-20 22:01:10 +01:00
|
|
|
static void define_udf(DsqlCompilerScratch* dsqlScratch)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* d e f i n e _ u d f
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Function
|
|
|
|
* define a udf to the database.
|
|
|
|
*
|
|
|
|
**************************************/
|
2009-12-20 22:01:10 +01:00
|
|
|
DsqlCompiledStatement* statement = dsqlScratch->getStatement();
|
2004-08-27 11:24:39 +02:00
|
|
|
SSHORT position, blob_position = -1;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2009-12-22 16:36:10 +01:00
|
|
|
dsql_nod* udf_node = statement->getDdlNode();
|
2009-12-20 22:01:10 +01:00
|
|
|
dsql_nod* arguments = udf_node->nod_arg[e_udf_args];
|
2003-11-01 11:26:43 +01:00
|
|
|
dsql_nod** ptr = udf_node->nod_arg;
|
2003-11-10 10:16:38 +01:00
|
|
|
const char* udf_name = ((dsql_str*) (ptr[e_udf_name]))->str_data;
|
|
|
|
const dsql_str* func_entry_point_name = reinterpret_cast<dsql_str*>(ptr[e_udf_entry_pt]);
|
2009-10-21 02:42:38 +02:00
|
|
|
const dsql_str* func_module_name = reinterpret_cast<dsql_str*>(ptr[e_udf_module]);
|
|
|
|
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendNullString(isc_dyn_def_function, udf_name);
|
|
|
|
dsqlScratch->appendNullString(isc_dyn_func_entry_point, func_entry_point_name->str_data);
|
2009-10-21 02:42:38 +02:00
|
|
|
|
|
|
|
if (func_module_name)
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendNullString(isc_dyn_func_module_name, func_module_name->str_data);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-11-01 11:26:43 +01:00
|
|
|
dsql_nod** ret_val_ptr = ptr[e_udf_return_value]->nod_arg;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-11-01 11:26:43 +01:00
|
|
|
dsql_fld* field = (dsql_fld*) ret_val_ptr[0];
|
2009-11-16 10:18:24 +01:00
|
|
|
if (field)
|
|
|
|
{
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2004-08-27 11:24:39 +02:00
|
|
|
// CVC: This is case of "returns <type> [by value|reference]"
|
2005-05-28 00:45:31 +02:00
|
|
|
// Some data types can not be returned as value
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2010-10-24 02:26:00 +02:00
|
|
|
if (((int) ExprNode::as<LiteralNode>(ret_val_ptr[1])->getSlong() == FUN_value) &&
|
2009-01-06 06:53:34 +01:00
|
|
|
(field->fld_dtype == dtype_text || field->fld_dtype == dtype_varying ||
|
|
|
|
field->fld_dtype == dtype_cstring || field->fld_dtype == dtype_blob ||
|
|
|
|
field->fld_dtype == dtype_timestamp))
|
2001-12-24 03:51:06 +01:00
|
|
|
{
|
2008-10-14 16:07:10 +02:00
|
|
|
// Return mode by value not allowed for this data type
|
|
|
|
post_607(Arg::Gds(isc_return_mode_err));
|
2001-12-24 03:51:06 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2009-04-18 16:13:26 +02:00
|
|
|
// For functions returning a blob, coerce return argument position to
|
|
|
|
// be the last parameter.
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2001-12-24 03:51:06 +01:00
|
|
|
if (field->fld_dtype == dtype_blob)
|
|
|
|
{
|
2009-02-28 12:57:40 +01:00
|
|
|
blob_position = arguments ? arguments->nod_count + 1 : 1;
|
2001-05-23 15:26:42 +02:00
|
|
|
if (blob_position > MAX_UDF_ARGUMENTS)
|
2001-12-24 03:51:06 +01:00
|
|
|
{
|
2008-08-16 17:42:38 +02:00
|
|
|
// External functions can not have more than 10 parameters
|
|
|
|
// Or 9 if the function returns a BLOB
|
2008-10-14 16:07:10 +02:00
|
|
|
post_607(Arg::Gds(isc_extern_func_err));
|
2001-12-24 03:51:06 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendNumber(isc_dyn_func_return_argument, blob_position);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
else
|
2001-12-24 03:51:06 +01:00
|
|
|
{
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendNumber(isc_dyn_func_return_argument, (SSHORT) 0);
|
2001-12-24 03:51:06 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
position = 0;
|
|
|
|
}
|
2009-11-16 10:18:24 +01:00
|
|
|
else
|
|
|
|
{
|
2002-06-29 08:56:51 +02:00
|
|
|
|
2004-08-27 11:24:39 +02:00
|
|
|
// CVC: This is case of "returns parameter <N>"
|
2002-06-29 08:56:51 +02:00
|
|
|
|
2010-10-24 02:26:00 +02:00
|
|
|
position = (SSHORT) ExprNode::as<LiteralNode>(ret_val_ptr[1])->getSlong();
|
2005-05-28 00:45:31 +02:00
|
|
|
// Function modifies an argument whose value is the function return value
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2005-05-22 05:11:41 +02:00
|
|
|
if (!arguments || position > arguments->nod_count || position < 1)
|
|
|
|
{
|
2008-10-27 16:10:45 +01:00
|
|
|
post_607(Arg::Gds(isc_dsql_udf_return_pos_err) << //gds__extern_func_err,
|
|
|
|
Arg::Num(arguments ? arguments->nod_count : 0));
|
2004-08-27 11:24:39 +02:00
|
|
|
// CVC: We should devise new msg "position should be between 1 and #params";
|
|
|
|
// here it is: dsql_udf_return_pos_err
|
2002-06-29 08:56:51 +02:00
|
|
|
|
2004-08-27 11:24:39 +02:00
|
|
|
// External functions can not have more than 10 parameters
|
|
|
|
// Not strictly correct -- return position error
|
|
|
|
}
|
2005-05-28 00:45:31 +02:00
|
|
|
|
2004-08-27 11:24:39 +02:00
|
|
|
// We'll verify that SCALAR_ARRAY can't be used as a return type.
|
|
|
|
// The support for SCALAR_ARRAY is only for input parameters.
|
|
|
|
const dsql_nod* ret_arg = arguments->nod_arg[position - 1];
|
|
|
|
const dsql_nod* const* param_node = ret_arg->nod_arg;
|
2005-05-22 05:11:41 +02:00
|
|
|
if (param_node[e_udf_param_type])
|
|
|
|
{
|
2010-10-24 02:26:00 +02:00
|
|
|
const SSHORT arg_mechanism =
|
|
|
|
(SSHORT) ExprNode::as<LiteralNode>(param_node[e_udf_param_type])->getSlong();
|
|
|
|
|
2008-02-28 14:48:16 +01:00
|
|
|
if (arg_mechanism == FUN_scalar_array)
|
2008-10-27 16:10:45 +01:00
|
|
|
post_607(Arg::Gds(isc_random) << Arg::Str("BY SCALAR_ARRAY can't be used as a return parameter"));
|
2001-12-24 03:51:06 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendNumber(isc_dyn_func_return_argument, position);
|
2001-05-23 15:26:42 +02:00
|
|
|
position = 1;
|
|
|
|
}
|
|
|
|
|
2009-04-18 16:13:26 +02:00
|
|
|
// Now define all the arguments
|
2001-12-24 03:51:06 +01:00
|
|
|
if (!position)
|
|
|
|
{
|
2009-04-18 16:13:26 +02:00
|
|
|
// CVC: This is case of "returns <type> [by value|reference]"
|
2001-12-24 03:51:06 +01:00
|
|
|
if (field->fld_dtype == dtype_blob)
|
|
|
|
{
|
2009-04-18 16:13:26 +02:00
|
|
|
// CVC: I need to test returning blobs by descriptor before allowing the
|
|
|
|
// change there. For now, I ignore the return type specification.
|
2010-10-24 02:26:00 +02:00
|
|
|
const bool free_it = ((SSHORT) ExprNode::as<LiteralNode>(ret_val_ptr[1])->getSlong() < 0);
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendNumber(isc_dyn_def_function_arg, blob_position);
|
|
|
|
dsqlScratch->appendNumber(isc_dyn_func_mechanism,
|
2008-02-28 14:48:16 +01:00
|
|
|
(SSHORT)(SLONG) ((free_it ? -1 : 1) * FUN_blob_struct));
|
2009-04-18 16:13:26 +02:00
|
|
|
// if we have the free_it set then the blob has to be freed on return
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
2001-12-24 03:51:06 +01:00
|
|
|
else
|
|
|
|
{
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendNumber(isc_dyn_def_function_arg, (SSHORT) 0);
|
2010-10-24 02:26:00 +02:00
|
|
|
dsqlScratch->appendNumber(isc_dyn_func_mechanism,
|
|
|
|
(SSHORT) ExprNode::as<LiteralNode>(ret_val_ptr[1])->getSlong());
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendNullString(isc_dyn_function_name, udf_name);
|
2009-12-20 22:01:10 +01:00
|
|
|
DDL_resolve_intl_type(dsqlScratch, field, NULL);
|
|
|
|
put_field(dsqlScratch, field, true);
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(isc_dyn_end);
|
2001-05-23 15:26:42 +02:00
|
|
|
position = 1;
|
|
|
|
}
|
|
|
|
|
2003-11-04 00:59:24 +01:00
|
|
|
fb_assert(position == 1);
|
2002-06-29 08:56:51 +02:00
|
|
|
|
2009-04-18 16:13:26 +02:00
|
|
|
// CVC: This for all params, including the case of "returns parameter <N>"
|
2002-06-29 08:56:51 +02:00
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
if (arguments)
|
2001-12-24 03:51:06 +01:00
|
|
|
{
|
2003-11-18 08:58:35 +01:00
|
|
|
ptr = arguments->nod_arg;
|
|
|
|
for (const dsql_nod* const* const end = ptr + arguments->nod_count;
|
2001-12-24 03:51:06 +01:00
|
|
|
ptr < end; ptr++, position++)
|
|
|
|
{
|
2001-05-23 15:26:42 +02:00
|
|
|
if (position > MAX_UDF_ARGUMENTS)
|
2001-12-24 03:51:06 +01:00
|
|
|
{
|
2008-08-16 17:42:38 +02:00
|
|
|
// External functions can not have more than 10 parameters
|
2008-10-14 16:07:10 +02:00
|
|
|
post_607(Arg::Gds(isc_extern_func_err));
|
2001-12-24 03:51:06 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2009-04-18 16:13:26 +02:00
|
|
|
// field = (dsql_fld*) *ptr;
|
2004-08-27 11:24:39 +02:00
|
|
|
dsql_nod** param_node = (*ptr)->nod_arg;
|
|
|
|
field = (dsql_fld*) param_node[e_udf_param_field];
|
2002-06-29 08:56:51 +02:00
|
|
|
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendNumber(isc_dyn_def_function_arg, position);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2009-11-16 10:18:24 +01:00
|
|
|
if (param_node[e_udf_param_type])
|
|
|
|
{
|
2010-10-24 02:26:00 +02:00
|
|
|
const SSHORT arg_mechanism =
|
|
|
|
(SSHORT) ExprNode::as<LiteralNode>(param_node[e_udf_param_type])->getSlong();
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendNumber(isc_dyn_func_mechanism, arg_mechanism);
|
2004-08-27 11:24:39 +02:00
|
|
|
}
|
|
|
|
else if (field->fld_dtype == dtype_blob) {
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendNumber(isc_dyn_func_mechanism, (SSHORT) FUN_blob_struct);
|
2004-08-27 11:24:39 +02:00
|
|
|
}
|
2002-06-29 08:56:51 +02:00
|
|
|
else {
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendNumber(isc_dyn_func_mechanism, (SSHORT) FUN_reference);
|
2001-12-24 03:51:06 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendNullString(isc_dyn_function_name, udf_name);
|
2009-12-20 22:01:10 +01:00
|
|
|
DDL_resolve_intl_type(dsqlScratch, field, NULL);
|
|
|
|
put_field(dsqlScratch, field, true);
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(isc_dyn_end);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
2001-12-24 03:51:06 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(isc_dyn_end);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-12-20 22:01:10 +01:00
|
|
|
static void generate_dyn(DsqlCompilerScratch* dsqlScratch, dsql_nod* node)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* g e n e r a t e _ d y n
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Switch off the type of node to generate a
|
|
|
|
* DYN string.
|
|
|
|
*
|
|
|
|
**************************************/
|
2003-11-10 10:16:38 +01:00
|
|
|
const dsql_str* string;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2009-01-06 06:53:34 +01:00
|
|
|
switch (node->nod_type)
|
|
|
|
{
|
2001-05-23 15:26:42 +02:00
|
|
|
case nod_def_index:
|
2009-12-20 22:01:10 +01:00
|
|
|
define_index(dsqlScratch);
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case nod_del_index:
|
2003-11-10 10:16:38 +01:00
|
|
|
string = (dsql_str*) node->nod_arg[0];
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendNullString(isc_dyn_delete_idx, string->str_data);
|
|
|
|
dsqlScratch->appendUChar(isc_dyn_end);
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case nod_del_role:
|
2003-11-10 10:16:38 +01:00
|
|
|
string = (dsql_str*) node->nod_arg[0];
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendNullString(isc_dyn_del_sql_role, string->str_data);
|
|
|
|
dsqlScratch->appendUChar(isc_dyn_end);
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case nod_grant:
|
|
|
|
case nod_revoke:
|
2009-12-20 22:01:10 +01:00
|
|
|
grant_revoke(dsqlScratch);
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case nod_def_role:
|
2009-12-20 22:01:10 +01:00
|
|
|
define_role(dsqlScratch);
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case nod_def_filter:
|
2009-12-20 22:01:10 +01:00
|
|
|
define_filter(dsqlScratch);
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case nod_del_generator:
|
2003-11-10 10:16:38 +01:00
|
|
|
string = (dsql_str*) node->nod_arg[0];
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendNullString(isc_dyn_delete_generator, string->str_data);
|
|
|
|
dsqlScratch->appendUChar(isc_dyn_end);
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case nod_del_filter:
|
2003-11-10 10:16:38 +01:00
|
|
|
string = (dsql_str*) node->nod_arg[0];
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendNullString(isc_dyn_delete_filter, string->str_data);
|
|
|
|
dsqlScratch->appendUChar(isc_dyn_end);
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case nod_def_udf:
|
2009-12-20 22:01:10 +01:00
|
|
|
define_udf(dsqlScratch);
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case nod_del_udf:
|
2003-11-10 10:16:38 +01:00
|
|
|
string = (dsql_str*) node->nod_arg[0];
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendNullString(isc_dyn_delete_function, string->str_data);
|
|
|
|
dsqlScratch->appendUChar(isc_dyn_end);
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case nod_def_shadow:
|
2009-12-20 22:01:10 +01:00
|
|
|
define_shadow(dsqlScratch);
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case nod_del_shadow:
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendNumber(isc_dyn_delete_shadow, (SSHORT) (IPTR) node->nod_arg[0]);
|
|
|
|
dsqlScratch->appendUChar(isc_dyn_end);
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case nod_mod_database:
|
2009-12-20 22:01:10 +01:00
|
|
|
modify_database(dsqlScratch);
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case nod_def_database:
|
2009-12-20 22:01:10 +01:00
|
|
|
define_database(dsqlScratch);
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case nod_mod_index:
|
2009-12-20 22:01:10 +01:00
|
|
|
modify_index(dsqlScratch);
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case nod_set_statistics:
|
2009-12-20 22:01:10 +01:00
|
|
|
set_statistics(dsqlScratch);
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
2005-05-28 00:45:31 +02:00
|
|
|
|
2005-05-22 04:42:17 +02:00
|
|
|
case nod_mod_udf:
|
2009-12-20 22:01:10 +01:00
|
|
|
modify_udf(dsqlScratch);
|
2005-05-22 04:42:17 +02:00
|
|
|
break;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-01-16 07:52:43 +01:00
|
|
|
case nod_mod_role:
|
2009-12-20 22:01:10 +01:00
|
|
|
modify_map(dsqlScratch);
|
2008-01-16 07:52:43 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case nod_add_user:
|
2009-12-20 22:01:10 +01:00
|
|
|
define_user(dsqlScratch, isc_dyn_user_add);
|
2008-01-16 07:52:43 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case nod_mod_user:
|
2009-12-20 22:01:10 +01:00
|
|
|
define_user(dsqlScratch, isc_dyn_user_mod);
|
2008-01-16 07:52:43 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case nod_del_user:
|
2009-12-20 22:01:10 +01:00
|
|
|
define_user(dsqlScratch, isc_dyn_user_del);
|
2008-01-16 07:52:43 +01:00
|
|
|
break;
|
|
|
|
|
2005-05-17 09:17:25 +02:00
|
|
|
default: // CVC: Shouldn't we complain here?
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-12-20 22:01:10 +01:00
|
|
|
static void grant_revoke(DsqlCompilerScratch* dsqlScratch)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* g r a n t _ r e v o k e
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Build DYN string for GRANT/REVOKE statements
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
|
2008-11-16 09:36:48 +01:00
|
|
|
const dsql_nod* const* uptr;
|
|
|
|
const dsql_nod* const* uend;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2004-12-03 07:49:01 +01:00
|
|
|
SSHORT option = 0; // no grant/admin option
|
2009-12-20 22:01:10 +01:00
|
|
|
DsqlCompiledStatement* statement = dsqlScratch->getStatement();
|
2009-12-22 16:36:10 +01:00
|
|
|
dsql_nod* ddl_node = statement->getDdlNode();
|
2008-11-16 09:36:48 +01:00
|
|
|
const dsql_nod* privs = ddl_node->nod_arg[e_grant_privs];
|
|
|
|
const dsql_nod* table = ddl_node->nod_arg[e_grant_table];
|
2008-11-14 11:00:45 +01:00
|
|
|
|
2008-11-19 02:04:36 +01:00
|
|
|
if ((ddl_node->nod_type == nod_revoke) && !privs && !table) // ALL ON ALL
|
2008-11-14 11:00:45 +01:00
|
|
|
{
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(isc_dyn_begin);
|
2008-11-16 09:36:48 +01:00
|
|
|
const dsql_nod* users = ddl_node->nod_arg[e_grant_users];
|
2008-11-14 11:00:45 +01:00
|
|
|
uend = users->nod_arg + users->nod_count;
|
|
|
|
for (uptr = users->nod_arg; uptr < uend; ++uptr)
|
|
|
|
{
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(isc_dyn_revoke_all);
|
2009-12-20 22:01:10 +01:00
|
|
|
put_user_grant(dsqlScratch, *uptr);
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(isc_dyn_end);
|
2008-11-14 11:00:45 +01:00
|
|
|
}
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(isc_dyn_end);
|
2008-11-14 11:00:45 +01:00
|
|
|
|
2010-07-26 04:37:57 +02:00
|
|
|
return;
|
2003-01-17 13:40:01 +01:00
|
|
|
}
|
2002-09-01 17:44:45 +02:00
|
|
|
|
2010-07-26 04:37:57 +02:00
|
|
|
bool process_grant_role = false;
|
|
|
|
if (privs->nod_arg[0] != NULL)
|
2002-09-04 14:09:25 +02:00
|
|
|
{
|
2010-07-26 04:37:57 +02:00
|
|
|
if (privs->nod_arg[0]->nod_type == nod_role_name) {
|
|
|
|
process_grant_role = true;
|
|
|
|
}
|
2002-09-04 14:09:25 +02:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2010-07-26 04:37:57 +02:00
|
|
|
dsqlScratch->appendUChar(isc_dyn_begin);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2010-07-26 04:37:57 +02:00
|
|
|
if (!process_grant_role)
|
|
|
|
{
|
|
|
|
const dsql_nod* users = ddl_node->nod_arg[e_grant_users];
|
|
|
|
if (ddl_node->nod_arg[e_grant_grant]) {
|
|
|
|
option = 1; // with grant option
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
2010-07-26 04:37:57 +02:00
|
|
|
uend = users->nod_arg + users->nod_count;
|
|
|
|
for (uptr = users->nod_arg; uptr < uend; ++uptr)
|
2001-12-24 03:51:06 +01:00
|
|
|
{
|
2010-07-26 04:37:57 +02:00
|
|
|
modify_privileges(dsqlScratch, ddl_node->nod_type, option,
|
|
|
|
privs, table, *uptr, ddl_node->nod_arg[e_grant_grantor]);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
}
|
2010-07-26 04:37:57 +02:00
|
|
|
else
|
2001-12-24 03:51:06 +01:00
|
|
|
{
|
2010-07-26 04:37:57 +02:00
|
|
|
const dsql_nod* role_list = ddl_node->nod_arg[0];
|
|
|
|
const dsql_nod* users = ddl_node->nod_arg[1];
|
|
|
|
if (ddl_node->nod_arg[3]) {
|
|
|
|
option = 2; // with admin option
|
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2010-07-26 04:37:57 +02:00
|
|
|
const dsql_nod* const* role_end = role_list->nod_arg + role_list->nod_count;
|
|
|
|
for (const dsql_nod* const* role_ptr = role_list->nod_arg; role_ptr < role_end; ++role_ptr)
|
2001-12-24 03:51:06 +01:00
|
|
|
{
|
2010-07-26 04:37:57 +02:00
|
|
|
uend = users->nod_arg + users->nod_count;
|
|
|
|
for (uptr = users->nod_arg; uptr < uend; ++uptr)
|
|
|
|
{
|
|
|
|
process_role_nm_list(dsqlScratch, option, *uptr, *role_ptr,
|
|
|
|
ddl_node->nod_type, ddl_node->nod_arg[e_grant_grantor]);
|
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
2001-12-24 03:51:06 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(isc_dyn_end);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-12-20 22:01:10 +01:00
|
|
|
static void modify_database( DsqlCompilerScratch* dsqlScratch)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* m o d i f y _ d a t a b a s e
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Function
|
2001-07-10 19:35:13 +02:00
|
|
|
* Modify a database.
|
2001-05-23 15:26:42 +02:00
|
|
|
*
|
|
|
|
**************************************/
|
2009-12-20 22:01:10 +01:00
|
|
|
DsqlCompiledStatement* statement = dsqlScratch->getStatement();
|
2009-12-22 16:36:10 +01:00
|
|
|
const dsql_nod* ddl_node = statement->getDdlNode();
|
2004-01-28 08:50:41 +01:00
|
|
|
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(isc_dyn_mod_database);
|
|
|
|
// dsqlScratch->appendNumber(isc_dyn_rel_sql_protection, 1);
|
2003-09-04 01:52:47 +02:00
|
|
|
bool drop_difference = false;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2004-01-28 08:50:41 +01:00
|
|
|
const dsql_nod* elements = ddl_node->nod_arg[e_adb_all];
|
|
|
|
const dsql_nod* const* end = elements->nod_arg + elements->nod_count;
|
|
|
|
const dsql_nod* const* ptr;
|
2005-05-28 00:45:31 +02:00
|
|
|
|
2001-12-24 03:51:06 +01:00
|
|
|
for (ptr = elements->nod_arg; ptr < end; ptr++)
|
|
|
|
{
|
2004-01-28 08:50:41 +01:00
|
|
|
const dsql_nod* element = *ptr;
|
2005-05-19 09:34:46 +02:00
|
|
|
if (element->nod_type == nod_drop_difference)
|
2003-09-04 01:52:47 +02:00
|
|
|
drop_difference = true;
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
2010-06-22 02:53:35 +02:00
|
|
|
if (drop_difference)
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(isc_dyn_drop_difference);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2004-01-28 08:50:41 +01:00
|
|
|
SLONG start = 0;
|
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
elements = ddl_node->nod_arg[e_adb_all];
|
2001-12-24 03:51:06 +01:00
|
|
|
end = elements->nod_arg + elements->nod_count;
|
|
|
|
for (ptr = elements->nod_arg; ptr < end; ptr++)
|
|
|
|
{
|
2004-01-28 08:50:41 +01:00
|
|
|
const dsql_fil* file;
|
|
|
|
const dsql_nod* element = *ptr;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2009-11-16 10:18:24 +01:00
|
|
|
switch (element->nod_type)
|
|
|
|
{
|
2001-05-23 15:26:42 +02:00
|
|
|
case nod_file_desc:
|
2003-11-10 10:16:38 +01:00
|
|
|
file = (dsql_fil*) element->nod_arg[0];
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendNullString(isc_dyn_def_file, file->fil_name->str_data);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2001-12-24 03:51:06 +01:00
|
|
|
start = MAX(start, file->fil_start);
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendFileStart(start);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendFileLength(file->fil_length);
|
|
|
|
dsqlScratch->appendUChar(isc_dyn_end);
|
2001-05-23 15:26:42 +02:00
|
|
|
start += file->fil_length;
|
|
|
|
break;
|
2003-08-06 18:30:49 +02:00
|
|
|
case nod_difference_file:
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendNullString(isc_dyn_def_difference,
|
2010-06-22 02:53:35 +02:00
|
|
|
((dsql_str*) element->nod_arg[0])->str_data);
|
2003-08-06 18:30:49 +02:00
|
|
|
break;
|
|
|
|
case nod_begin_backup:
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(isc_dyn_begin_backup);
|
2003-08-06 18:30:49 +02:00
|
|
|
break;
|
|
|
|
case nod_end_backup:
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(isc_dyn_end_backup);
|
2003-08-06 18:30:49 +02:00
|
|
|
break;
|
2009-12-07 19:26:50 +01:00
|
|
|
case nod_dfl_charset:
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendNullString(isc_dyn_fld_character_set_name,
|
2009-12-07 19:26:50 +01:00
|
|
|
((dsql_str*) element->nod_arg[0])->str_data);
|
|
|
|
break;
|
2001-05-23 15:26:42 +02:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(isc_dyn_end);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-12-20 22:01:10 +01:00
|
|
|
static void modify_index( DsqlCompilerScratch* dsqlScratch)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* m o d i f y _ i n d e x
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Function
|
|
|
|
* Alter an index (only active or inactive for now)
|
|
|
|
*
|
|
|
|
**************************************/
|
2009-12-20 22:01:10 +01:00
|
|
|
DsqlCompiledStatement* statement = dsqlScratch->getStatement();
|
2009-12-22 16:36:10 +01:00
|
|
|
dsql_nod* ddl_node = statement->getDdlNode();
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-11-01 11:26:43 +01:00
|
|
|
dsql_nod* index_node = ddl_node->nod_arg[e_alt_index];
|
2003-11-10 10:16:38 +01:00
|
|
|
const dsql_str* index_name = (dsql_str*) index_node->nod_arg[e_alt_idx_name];
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendNullString(isc_dyn_mod_idx, index_name->str_data);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2010-06-22 02:53:35 +02:00
|
|
|
if (index_node->nod_type == nod_idx_active)
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendNumber(isc_dyn_idx_inactive, 0);
|
2010-06-22 02:53:35 +02:00
|
|
|
else if (index_node->nod_type == nod_idx_inactive)
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendNumber(isc_dyn_idx_inactive, 1);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(isc_dyn_end);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-12-20 22:01:10 +01:00
|
|
|
static void put_user_grant(DsqlCompilerScratch* dsqlScratch, const dsql_nod* user)
|
2008-11-14 11:00:45 +01:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* p u t _ u s e r _ g r a n t
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Stuff a user/role/obj option in grant/revoke
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
const dsql_str* name = (dsql_str*) user->nod_arg[0];
|
|
|
|
|
2009-01-06 06:53:34 +01:00
|
|
|
switch (user->nod_type)
|
|
|
|
{
|
2008-11-14 11:00:45 +01:00
|
|
|
case nod_user_group: // GRANT priv ON tbl TO GROUP unix_group
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendNullString(isc_dyn_grant_user_group, name->str_data);
|
2008-11-14 11:00:45 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case nod_user_name:
|
2010-06-22 02:53:35 +02:00
|
|
|
if (user->nod_count == 2)
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendNullString(isc_dyn_grant_user_explicit, name->str_data);
|
2010-06-22 02:53:35 +02:00
|
|
|
else
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendNullString(isc_dyn_grant_user, name->str_data);
|
2008-11-14 11:00:45 +01:00
|
|
|
break;
|
|
|
|
|
2009-10-21 02:42:38 +02:00
|
|
|
case nod_package_obj:
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendNullString(isc_dyn_grant_package, name->str_data);
|
2009-10-21 02:42:38 +02:00
|
|
|
break;
|
|
|
|
|
2008-11-14 11:00:45 +01:00
|
|
|
case nod_proc_obj:
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendNullString(isc_dyn_grant_proc, name->str_data);
|
2008-11-14 11:00:45 +01:00
|
|
|
break;
|
|
|
|
|
2009-12-21 18:23:07 +01:00
|
|
|
case nod_func_obj:
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendNullString(isc_dyn_grant_func, name->str_data);
|
2009-12-21 18:23:07 +01:00
|
|
|
break;
|
|
|
|
|
2008-11-14 11:00:45 +01:00
|
|
|
case nod_trig_obj:
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendNullString(isc_dyn_grant_trig, name->str_data);
|
2008-11-14 11:00:45 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case nod_view_obj:
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendNullString(isc_dyn_grant_view, name->str_data);
|
2008-11-14 11:00:45 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case nod_role_name:
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendNullString(isc_dyn_grant_role, name->str_data);
|
2008-11-14 11:00:45 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2009-04-18 16:13:26 +02:00
|
|
|
// CVC: Here we should complain: DYN doesn't check parameters
|
|
|
|
// and it will write trash in rdb$user_privileges. We probably
|
|
|
|
// should complain in most cases when "name" is blank, too.
|
2008-11-14 11:00:45 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-12-20 22:01:10 +01:00
|
|
|
static void modify_privilege(DsqlCompilerScratch* dsqlScratch,
|
2008-06-13 03:42:58 +02:00
|
|
|
NOD_TYPE type,
|
|
|
|
SSHORT option,
|
|
|
|
const UCHAR* privs,
|
|
|
|
const dsql_nod* table,
|
|
|
|
const dsql_nod* user,
|
|
|
|
const dsql_nod* grantor,
|
|
|
|
const dsql_str* field_name)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* m o d i f y _ p r i v i l e g e
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Stuff a single grant/revoke verb and all its options.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
|
2010-06-17 03:18:40 +02:00
|
|
|
if (type == nod_grant)
|
|
|
|
dsqlScratch->appendUChar(isc_dyn_grant);
|
|
|
|
else
|
|
|
|
dsqlScratch->appendUChar(isc_dyn_revoke);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2009-04-18 16:13:26 +02:00
|
|
|
// stuff the privileges string
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-02-12 20:28:13 +01:00
|
|
|
SSHORT priv_count = 0;
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUShort(0);
|
2010-06-22 02:53:35 +02:00
|
|
|
|
2009-11-16 10:18:24 +01:00
|
|
|
for (; *privs; privs++)
|
|
|
|
{
|
2001-05-23 15:26:42 +02:00
|
|
|
priv_count++;
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(*privs);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
2010-06-17 03:18:40 +02:00
|
|
|
UCHAR* dynsave = dsqlScratch->getBlrData().end();
|
2010-06-22 02:53:35 +02:00
|
|
|
for (SSHORT i = priv_count + 2; i; i--)
|
2001-05-23 15:26:42 +02:00
|
|
|
--dynsave;
|
|
|
|
|
|
|
|
*dynsave++ = (UCHAR) priv_count;
|
|
|
|
*dynsave = (UCHAR) (priv_count >> 8);
|
|
|
|
|
2009-12-24 11:42:32 +01:00
|
|
|
UCHAR dynVerb = 0;
|
2011-01-30 01:25:46 +01:00
|
|
|
|
2009-12-24 11:42:32 +01:00
|
|
|
switch (table->nod_type)
|
|
|
|
{
|
|
|
|
case nod_procedure_name:
|
|
|
|
dynVerb = isc_dyn_prc_name;
|
|
|
|
break;
|
|
|
|
case nod_function_name:
|
|
|
|
dynVerb = isc_dyn_fun_name;
|
|
|
|
break;
|
|
|
|
case nod_package_name:
|
|
|
|
dynVerb = isc_dyn_pkg_name;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
dynVerb = isc_dyn_rel_name;
|
|
|
|
}
|
2011-01-30 01:25:46 +01:00
|
|
|
|
|
|
|
const char* name = dynVerb == isc_dyn_rel_name ?
|
|
|
|
ExprNode::as<RelationSourceNode>(table)->dsqlName.c_str() :
|
|
|
|
((dsql_str*) table->nod_arg[0])->str_data;
|
|
|
|
|
|
|
|
dsqlScratch->appendNullString(dynVerb, name);
|
2002-06-29 08:56:51 +02:00
|
|
|
|
2009-12-20 22:01:10 +01:00
|
|
|
put_user_grant(dsqlScratch, user);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2010-06-22 02:53:35 +02:00
|
|
|
if (field_name)
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendNullString(isc_dyn_fld_name, field_name->str_data);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2005-09-10 09:15:24 +02:00
|
|
|
if (option)
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendNumber(isc_dyn_grant_options, option);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2009-12-20 22:01:10 +01:00
|
|
|
put_grantor(dsqlScratch, grantor);
|
2008-06-10 12:55:48 +02:00
|
|
|
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(isc_dyn_end);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2009-12-20 22:01:10 +01:00
|
|
|
static char modify_privileges(DsqlCompilerScratch* dsqlScratch,
|
2008-06-13 03:42:58 +02:00
|
|
|
NOD_TYPE type,
|
|
|
|
SSHORT option,
|
|
|
|
const dsql_nod* privs,
|
|
|
|
const dsql_nod* table,
|
|
|
|
const dsql_nod* user,
|
|
|
|
const dsql_nod* grantor)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* m o d i f y _ p r i v i l e g e s
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
2008-11-16 09:36:48 +01:00
|
|
|
* Return a char indicating the privilege to be modified
|
2001-05-23 15:26:42 +02:00
|
|
|
*
|
|
|
|
**************************************/
|
2003-02-12 20:28:13 +01:00
|
|
|
|
2008-11-16 09:36:48 +01:00
|
|
|
char privileges[10];
|
2004-06-05 11:37:18 +02:00
|
|
|
const char* p = 0;
|
|
|
|
char* q;
|
2003-11-01 11:26:43 +01:00
|
|
|
const dsql_nod* fields;
|
|
|
|
const dsql_nod* const* ptr;
|
|
|
|
const dsql_nod* const* end;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-11-16 09:36:48 +01:00
|
|
|
switch (privs->nod_type)
|
|
|
|
{
|
2001-05-23 15:26:42 +02:00
|
|
|
case nod_all:
|
|
|
|
p = "A";
|
|
|
|
break;
|
|
|
|
|
|
|
|
case nod_select:
|
|
|
|
return 'S';
|
|
|
|
|
|
|
|
case nod_execute:
|
|
|
|
return 'X';
|
|
|
|
|
|
|
|
case nod_insert:
|
|
|
|
return 'I';
|
|
|
|
|
|
|
|
case nod_references:
|
|
|
|
case nod_update:
|
2004-06-05 11:37:18 +02:00
|
|
|
p = (privs->nod_type == nod_references) ? "R" : "U";
|
2003-02-12 20:28:13 +01:00
|
|
|
fields = privs->nod_arg[0];
|
|
|
|
if (!fields) {
|
2001-05-23 15:26:42 +02:00
|
|
|
return *p;
|
2003-02-12 20:28:13 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2009-01-06 06:53:34 +01:00
|
|
|
for (ptr = fields->nod_arg, end = ptr + fields->nod_count; ptr < end; ptr++)
|
2003-02-12 20:28:13 +01:00
|
|
|
{
|
2009-12-20 22:01:10 +01:00
|
|
|
modify_privilege(dsqlScratch, type, option,
|
2008-06-10 12:55:48 +02:00
|
|
|
reinterpret_cast<const UCHAR*>(p), table, user, grantor,
|
2003-11-10 10:16:38 +01:00
|
|
|
reinterpret_cast<dsql_str*>((*ptr)->nod_arg[1]));
|
2003-02-12 20:28:13 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
case nod_delete:
|
|
|
|
return 'D';
|
|
|
|
|
|
|
|
case nod_list:
|
2004-06-05 11:37:18 +02:00
|
|
|
p = q = privileges;
|
2008-11-16 09:36:48 +01:00
|
|
|
for (ptr = privs->nod_arg, end = ptr + privs->nod_count; ptr < end; ptr++)
|
2003-02-12 20:28:13 +01:00
|
|
|
{
|
2009-12-20 22:01:10 +01:00
|
|
|
*q = modify_privileges(dsqlScratch, type, option, *ptr, table, user, grantor);
|
2004-06-05 11:37:18 +02:00
|
|
|
if (*q) {
|
|
|
|
q++;
|
2003-02-12 20:28:13 +01:00
|
|
|
}
|
|
|
|
}
|
2004-06-05 11:37:18 +02:00
|
|
|
*q = 0;
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2009-11-16 10:18:24 +01:00
|
|
|
if (*p)
|
|
|
|
{
|
2009-12-20 22:01:10 +01:00
|
|
|
modify_privilege(dsqlScratch, type, option,
|
2009-01-06 06:53:34 +01:00
|
|
|
reinterpret_cast<const UCHAR*>(p), table, user, grantor, 0);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-05-22 04:42:17 +02:00
|
|
|
// *******************
|
|
|
|
// m o d i f y _ u d f
|
|
|
|
// *******************
|
|
|
|
// Allow the user to change the entry point or module name.
|
|
|
|
// Useful when there are dependencies on the udf, so it cannot be dropped.
|
2009-12-20 22:01:10 +01:00
|
|
|
static void modify_udf(DsqlCompilerScratch* dsqlScratch)
|
2005-05-22 04:42:17 +02:00
|
|
|
{
|
2009-12-20 22:01:10 +01:00
|
|
|
DsqlCompiledStatement* statement = dsqlScratch->getStatement();
|
|
|
|
|
2009-12-22 16:36:10 +01:00
|
|
|
const dsql_nod* node = statement->getDdlNode();
|
2005-05-22 04:42:17 +02:00
|
|
|
fb_assert(node->nod_type == nod_mod_udf);
|
2005-06-11 02:20:22 +02:00
|
|
|
const dsql_str* obj_name = (dsql_str*) node->nod_arg[e_mod_udf_name];
|
2005-05-22 04:42:17 +02:00
|
|
|
|
|
|
|
if (!node->nod_arg[e_mod_udf_entry_pt] && !node->nod_arg[e_mod_udf_module])
|
2009-01-06 06:53:34 +01:00
|
|
|
{
|
2008-08-15 13:21:47 +02:00
|
|
|
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-104) <<
|
|
|
|
// Unexpected end of command
|
2008-11-16 09:36:48 +01:00
|
|
|
Arg::Gds(isc_command_end_err2) << Arg::Num(node->nod_line) <<
|
2008-08-15 13:21:47 +02:00
|
|
|
Arg::Num(node->nod_column + obj_name->str_length));
|
|
|
|
// + strlen("FUNCTION")
|
2009-01-06 06:53:34 +01:00
|
|
|
}
|
2005-05-22 04:42:17 +02:00
|
|
|
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendNullString(isc_dyn_mod_function, obj_name->str_data);
|
2009-10-21 02:42:38 +02:00
|
|
|
|
2005-05-22 04:42:17 +02:00
|
|
|
const dsql_str* entry_point_name = (dsql_str*) node->nod_arg[e_mod_udf_entry_pt];
|
|
|
|
if (entry_point_name)
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendNullString(isc_dyn_func_entry_point, entry_point_name->str_data);
|
2005-05-22 04:42:17 +02:00
|
|
|
|
|
|
|
const dsql_str* module_name = (dsql_str*) node->nod_arg[e_mod_udf_module];
|
|
|
|
if (module_name)
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendNullString(isc_dyn_func_module_name, module_name->str_data);
|
2005-05-28 00:45:31 +02:00
|
|
|
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(isc_dyn_end);
|
2005-05-22 04:42:17 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-01-16 07:52:43 +01:00
|
|
|
// *******************
|
|
|
|
// m o d i f y _ m a p
|
|
|
|
// *******************
|
|
|
|
// Allow the user to establish/drop the mapping between OS security object and the role
|
2009-12-20 22:01:10 +01:00
|
|
|
static void modify_map(DsqlCompilerScratch* dsqlScratch)
|
2008-01-16 07:52:43 +01:00
|
|
|
{
|
2009-12-20 22:01:10 +01:00
|
|
|
DsqlCompiledStatement* statement = dsqlScratch->getStatement();
|
|
|
|
|
2009-12-22 16:36:10 +01:00
|
|
|
const dsql_nod* node = statement->getDdlNode();
|
2008-01-16 07:52:43 +01:00
|
|
|
fb_assert(node->nod_type == nod_mod_role);
|
|
|
|
|
|
|
|
const dsql_str* ds = (dsql_str*) node->nod_arg[e_mod_role_os_name];
|
2008-06-03 08:19:21 +02:00
|
|
|
fb_assert(ds ||
|
2010-10-24 02:26:00 +02:00
|
|
|
ExprNode::as<LiteralNode>(node->nod_arg[e_mod_role_action])->getSlong() == isc_dyn_automap_role ||
|
|
|
|
ExprNode::as<LiteralNode>(node->nod_arg[e_mod_role_action])->getSlong() == isc_dyn_autounmap_role);
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendNullString(isc_dyn_mapping, ds ? ds->str_data : "");
|
2008-01-16 07:52:43 +01:00
|
|
|
|
|
|
|
ds = (dsql_str*) node->nod_arg[e_mod_role_db_name];
|
|
|
|
fb_assert(ds);
|
2010-10-24 02:26:00 +02:00
|
|
|
dsqlScratch->appendNullString(
|
|
|
|
ExprNode::as<LiteralNode>(node->nod_arg[e_mod_role_action])->getSlong(), ds->str_data);
|
2008-01-16 07:52:43 +01:00
|
|
|
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(isc_dyn_end);
|
2008-01-16 07:52:43 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// *********************
|
|
|
|
// d e f i n e _ u s e r
|
|
|
|
// *********************
|
|
|
|
// Support SQL operator create/alter/drop user
|
2009-12-20 22:01:10 +01:00
|
|
|
static void define_user(DsqlCompilerScratch* dsqlScratch, UCHAR op)
|
2008-01-16 07:52:43 +01:00
|
|
|
{
|
2009-12-20 22:01:10 +01:00
|
|
|
DsqlCompiledStatement* statement = dsqlScratch->getStatement();
|
|
|
|
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(isc_dyn_user);
|
2008-01-16 07:52:43 +01:00
|
|
|
|
2009-12-22 16:36:10 +01:00
|
|
|
const dsql_nod* node = statement->getDdlNode();
|
2008-01-16 07:52:43 +01:00
|
|
|
int argCount = 0;
|
|
|
|
|
|
|
|
for (int i = 0; i < node->nod_count; ++i)
|
|
|
|
{
|
|
|
|
const dsql_str* ds = (dsql_str*) node->nod_arg[i];
|
|
|
|
if (! ds)
|
|
|
|
{
|
|
|
|
if (i == e_user_name || (i == e_user_passwd && op == isc_dyn_user_add))
|
|
|
|
{
|
2008-08-15 13:21:47 +02:00
|
|
|
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-104) <<
|
|
|
|
// Unexpected end of command
|
2008-11-16 09:36:48 +01:00
|
|
|
Arg::Gds(isc_command_end_err2) << Arg::Num(node->nod_line) <<
|
2008-08-15 13:21:47 +02:00
|
|
|
Arg::Num(node->nod_column));
|
2008-01-16 07:52:43 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
++argCount;
|
|
|
|
|
2008-12-02 08:09:49 +01:00
|
|
|
switch (i)
|
2008-01-16 07:52:43 +01:00
|
|
|
{
|
|
|
|
case e_user_name:
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendNullString(op, ds->str_data);
|
2008-01-16 07:52:43 +01:00
|
|
|
break;
|
|
|
|
case e_user_passwd:
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendNullString(isc_dyn_user_passwd, ds->str_data);
|
2008-01-16 07:52:43 +01:00
|
|
|
break;
|
|
|
|
case e_user_first:
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendNullString(isc_dyn_user_first, ds->str_data);
|
2008-01-16 07:52:43 +01:00
|
|
|
break;
|
|
|
|
case e_user_middle:
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendNullString(isc_dyn_user_middle, ds->str_data);
|
2008-01-16 07:52:43 +01:00
|
|
|
break;
|
|
|
|
case e_user_last:
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendNullString(isc_dyn_user_last, ds->str_data);
|
2008-01-16 07:52:43 +01:00
|
|
|
break;
|
2009-11-13 20:00:09 +01:00
|
|
|
case e_user_admin:
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendNullString(isc_dyn_user_admin, ds->str_data);
|
2009-11-13 20:00:09 +01:00
|
|
|
break;
|
2008-01-16 07:52:43 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (argCount < 2 && op != isc_dyn_user_del)
|
|
|
|
{
|
2008-08-15 13:21:47 +02:00
|
|
|
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-104) <<
|
|
|
|
// Unexpected end of command
|
2008-11-16 09:36:48 +01:00
|
|
|
Arg::Gds(isc_command_end_err2) << Arg::Num(node->nod_line) <<
|
2008-08-15 13:21:47 +02:00
|
|
|
Arg::Num(node->nod_column));
|
2008-01-16 07:52:43 +01:00
|
|
|
}
|
|
|
|
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(isc_user_end);
|
|
|
|
dsqlScratch->appendUChar(isc_dyn_end);
|
2008-01-16 07:52:43 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-12-20 22:01:10 +01:00
|
|
|
static void process_role_nm_list(DsqlCompilerScratch* dsqlScratch,
|
2008-06-13 03:42:58 +02:00
|
|
|
SSHORT option,
|
2008-11-16 09:36:48 +01:00
|
|
|
const dsql_nod* user_ptr,
|
|
|
|
const dsql_nod* role_ptr,
|
2008-06-13 03:42:58 +02:00
|
|
|
NOD_TYPE type,
|
|
|
|
const dsql_nod* grantor)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* p r o c e s s _ r o l e _ n m _ l i s t
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Build req_blr for grant & revoke role stmt
|
|
|
|
*
|
|
|
|
**************************************/
|
2010-06-22 02:53:35 +02:00
|
|
|
if (type == nod_grant)
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(isc_dyn_grant);
|
2010-06-22 02:53:35 +02:00
|
|
|
else
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(isc_dyn_revoke);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUShort(1);
|
|
|
|
dsqlScratch->appendUChar('M');
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-11-10 10:16:38 +01:00
|
|
|
const dsql_str* role_nm = (dsql_str*) role_ptr->nod_arg[0];
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendNullString(isc_dyn_sql_role_name, role_nm->str_data);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-11-10 10:16:38 +01:00
|
|
|
const dsql_str* user_nm = (dsql_str*) user_ptr->nod_arg[0];
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendNullString(isc_dyn_grant_user, user_nm->str_data);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2001-12-24 03:51:06 +01:00
|
|
|
if (option) {
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendNumber(isc_dyn_grant_admin_options, option);
|
2001-12-24 03:51:06 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2009-12-20 22:01:10 +01:00
|
|
|
put_grantor(dsqlScratch, grantor);
|
2008-06-10 12:55:48 +02:00
|
|
|
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(isc_dyn_end);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-12-20 22:01:10 +01:00
|
|
|
static void put_grantor(DsqlCompilerScratch* dsqlScratch, const dsql_nod* grantor)
|
2008-06-10 12:55:48 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* p u t _ g r a n t o r
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Function
|
|
|
|
* Write out grantor for grant / revoke.
|
|
|
|
*
|
|
|
|
**************************************/
|
2009-11-16 10:18:24 +01:00
|
|
|
if (grantor)
|
|
|
|
{
|
2008-06-10 12:55:48 +02:00
|
|
|
fb_assert(grantor->nod_type == nod_user_name);
|
|
|
|
const dsql_str* name = (const dsql_str*) grantor->nod_arg[0];
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendNullString(isc_dyn_grant_grantor, name->str_data);
|
2008-06-10 12:55:48 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-12-20 22:01:10 +01:00
|
|
|
static void put_field( DsqlCompilerScratch* dsqlScratch, dsql_fld* field, bool udf_flag)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
2001-07-10 19:35:13 +02:00
|
|
|
* p u t _ f i e l d
|
2001-05-23 15:26:42 +02:00
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Function
|
|
|
|
* Emit dyn which describes a field data type.
|
|
|
|
* This field could be a column, a procedure input,
|
|
|
|
* or a procedure output.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
|
2007-01-17 02:19:01 +01:00
|
|
|
if (field->fld_not_nullable)
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendUChar(isc_dyn_fld_not_null);
|
2007-01-17 02:19:01 +01:00
|
|
|
|
2008-01-16 07:52:43 +01:00
|
|
|
if (field->fld_type_of_name.hasData())
|
2006-08-19 04:52:39 +02:00
|
|
|
{
|
2008-01-16 07:52:43 +01:00
|
|
|
if (field->fld_source.hasData())
|
|
|
|
{
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendString(isc_dyn_fld_source, field->fld_source);
|
|
|
|
dsqlScratch->appendString(isc_dyn_fld_name, field->fld_type_of_name);
|
|
|
|
dsqlScratch->appendNullString(isc_dyn_rel_name, field->fld_type_of_table->str_data);
|
2008-01-16 07:52:43 +01:00
|
|
|
}
|
|
|
|
else
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendString(isc_dyn_fld_source, field->fld_type_of_name);
|
2006-08-19 04:52:39 +02:00
|
|
|
|
|
|
|
if (field->fld_explicit_collation)
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendNumber(isc_dyn_fld_collation, field->fld_collation_id);
|
2006-08-19 04:52:39 +02:00
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendNumber(isc_dyn_fld_type, blr_dtypes[field->fld_dtype]);
|
2001-12-24 03:51:06 +01:00
|
|
|
if (field->fld_dtype == dtype_blob)
|
|
|
|
{
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendNumber(isc_dyn_fld_sub_type, field->fld_sub_type);
|
|
|
|
dsqlScratch->appendNumber(isc_dyn_fld_scale, 0);
|
2001-12-24 03:51:06 +01:00
|
|
|
if (!udf_flag)
|
|
|
|
{
|
|
|
|
if (!field->fld_seg_length) {
|
2001-05-23 15:26:42 +02:00
|
|
|
field->fld_seg_length = DEFAULT_BLOB_SEGMENT_SIZE;
|
2001-12-24 03:51:06 +01:00
|
|
|
}
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendNumber(isc_dyn_fld_segment_length, field->fld_seg_length);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
2009-09-19 10:05:14 +02:00
|
|
|
else
|
|
|
|
{
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendNumber(isc_dyn_fld_length, sizeof(ISC_QUAD));
|
2009-09-19 10:05:14 +02:00
|
|
|
}
|
2009-11-16 10:18:24 +01:00
|
|
|
if (field->fld_sub_type == isc_blob_text)
|
|
|
|
{
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendNumber(isc_dyn_fld_character_set, field->fld_character_set_id);
|
|
|
|
dsqlScratch->appendNumber(isc_dyn_fld_collation, field->fld_collation_id);
|
2001-12-24 03:51:06 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
2001-12-24 03:51:06 +01:00
|
|
|
else if (field->fld_dtype <= dtype_any_text)
|
|
|
|
{
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendNumber(isc_dyn_fld_sub_type, field->fld_sub_type);
|
|
|
|
dsqlScratch->appendNumber(isc_dyn_fld_scale, 0);
|
2001-12-24 03:51:06 +01:00
|
|
|
if (field->fld_dtype == dtype_varying)
|
|
|
|
{
|
2008-06-03 08:19:21 +02:00
|
|
|
// CVC: Fix the assertion
|
|
|
|
fb_assert((field->fld_length) <= MAX_SSHORT);
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendNumber(isc_dyn_fld_length,
|
2009-12-20 22:01:10 +01:00
|
|
|
(SSHORT) (field->fld_length - sizeof(USHORT)));
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
else
|
2001-12-24 03:51:06 +01:00
|
|
|
{
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendNumber(isc_dyn_fld_length, field->fld_length);
|
2001-12-24 03:51:06 +01:00
|
|
|
}
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendNumber(isc_dyn_fld_char_length, field->fld_character_length);
|
|
|
|
dsqlScratch->appendNumber(isc_dyn_fld_character_set, field->fld_character_set_id);
|
2005-09-10 09:15:24 +02:00
|
|
|
if (!udf_flag)
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendNumber(isc_dyn_fld_collation, field->fld_collation_id);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
2009-11-16 10:18:24 +01:00
|
|
|
else
|
|
|
|
{
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendNumber(isc_dyn_fld_scale, field->fld_scale);
|
|
|
|
dsqlScratch->appendNumber(isc_dyn_fld_length, field->fld_length);
|
2001-12-24 03:51:06 +01:00
|
|
|
if (DTYPE_IS_EXACT(field->fld_dtype))
|
|
|
|
{
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendNumber(isc_dyn_fld_precision, field->fld_precision);
|
|
|
|
dsqlScratch->appendNumber(isc_dyn_fld_sub_type, field->fld_sub_type);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-07-26 04:37:57 +02:00
|
|
|
void DDL_reset_context_stack(DsqlCompilerScratch* dsqlScratch)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
2010-07-26 04:37:57 +02:00
|
|
|
* D D L _ r e s e t _ c o n t e x t _ s t a c k
|
2001-05-23 15:26:42 +02:00
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Function
|
2001-07-10 19:35:13 +02:00
|
|
|
* Get rid of any predefined contexts created
|
2001-05-23 15:26:42 +02:00
|
|
|
* for a view or trigger definition.
|
2008-09-01 15:18:02 +02:00
|
|
|
* Also reset hidden variables.
|
2001-05-23 15:26:42 +02:00
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
|
2009-12-20 22:01:10 +01:00
|
|
|
dsqlScratch->context->clear();
|
|
|
|
dsqlScratch->contextNumber = 0;
|
|
|
|
dsqlScratch->derivedContextNumber = 0;
|
2008-09-01 15:18:02 +02:00
|
|
|
|
2009-12-20 22:01:10 +01:00
|
|
|
dsqlScratch->hiddenVarsNumber = 0;
|
2011-01-31 15:47:41 +01:00
|
|
|
dsqlScratch->hiddenVariables.clear();
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-12-20 22:01:10 +01:00
|
|
|
static void set_statistics(DsqlCompilerScratch* dsqlScratch)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* s e t _ s t a t i s t i c s
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Function
|
|
|
|
* Alter an index/.. statistics
|
|
|
|
*
|
|
|
|
**************************************/
|
2009-12-20 22:01:10 +01:00
|
|
|
DsqlCompiledStatement* statement = dsqlScratch->getStatement();
|
2009-12-22 16:36:10 +01:00
|
|
|
const dsql_nod* ddl_node = statement->getDdlNode();
|
2003-11-10 10:16:38 +01:00
|
|
|
const dsql_str* index_name = (dsql_str*) ddl_node->nod_arg[e_stat_name];
|
2010-06-17 03:18:40 +02:00
|
|
|
dsqlScratch->appendNullString(isc_dyn_mod_idx, index_name->str_data);
|
|
|
|
dsqlScratch->appendUChar(isc_dyn_idx_statistic);
|
|
|
|
dsqlScratch->appendUChar(isc_dyn_end);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-10-16 04:31:49 +02:00
|
|
|
// post very often used error - avoid code duplication
|
2008-10-14 16:07:10 +02:00
|
|
|
static void post_607(const Arg::StatusVector& v)
|
|
|
|
{
|
|
|
|
Arg::Gds err(isc_sqlerr);
|
|
|
|
err << Arg::Num(-607) << Arg::Gds(isc_dsql_command_err);
|
|
|
|
|
|
|
|
err.append(v);
|
|
|
|
ERRD_post(err);
|
|
|
|
}
|