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 generate_dyn(DsqlCompilerScratch*, dsql_nod*);
|
|
|
|
static void grant_revoke(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 process_role_nm_list(DsqlCompilerScratch*, SSHORT, const dsql_nod*, const dsql_nod*, NOD_TYPE, const dsql_nod*);
|
|
|
|
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
|
|
|
|
|
2009-12-22 16:36:10 +01:00
|
|
|
const NOD_TYPE type = statement->getDdlNode()->nod_type;
|
2006-07-10 05:12:10 +02: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
|
|
|
{
|
2011-05-27 04:05:27 +02:00
|
|
|
if (field->fld_type_of_table.hasData())
|
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,
|
2011-05-27 04:05:27 +02:00
|
|
|
field->fld_type_of_table.c_str());
|
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) <<
|
2011-05-27 04:05:27 +02:00
|
|
|
field->fld_type_of_table);
|
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(),
|
2011-11-27 20:08:06 +01:00
|
|
|
reinterpret_cast<const dsql_str*>(field->fld_sub_type_name)->str_data,
|
2009-12-20 22:01:10 +01:00
|
|
|
"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 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.
|
|
|
|
*
|
|
|
|
**************************************/
|
2009-01-06 06:53:34 +01:00
|
|
|
switch (node->nod_type)
|
|
|
|
{
|
2001-05-23 15:26:42 +02:00
|
|
|
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;
|
|
|
|
|
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 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;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
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
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
}
|