Exemplo n.º 1
0
MetaName Jrd::Attachment::nameToUserCharSet(thread_db* tdbb, const MetaName& name)
{
	if (att_charset == CS_METADATA || att_charset == CS_NONE)
		return name;

	UCHAR buffer[MAX_SQL_IDENTIFIER_SIZE];
	ULONG len = INTL_convert_bytes(tdbb, att_charset, buffer, MAX_SQL_IDENTIFIER_LEN,
		CS_METADATA, (const BYTE*) name.c_str(), name.length(), ERR_post);
	buffer[len] = '\0';

	return MetaName((const char*) buffer);
}
Exemplo n.º 2
0
void RecordSource::printInversion(thread_db* tdbb, const InversionNode* inversion,
                                  string& plan, bool detailed, unsigned level, bool navigation)
{
    if (detailed)
        plan += printIndent(++level);

    switch (inversion->type)
    {
    case InversionNode::TYPE_AND:
        if (detailed)
            plan += "Bitmap And";
        printInversion(tdbb, inversion->node1, plan, detailed, level);
        printInversion(tdbb, inversion->node2, plan, detailed, level);
        break;

    case InversionNode::TYPE_OR:
    case InversionNode::TYPE_IN:
        if (detailed)
            plan += "Bitmap Or";
        printInversion(tdbb, inversion->node1, plan, detailed, level);
        printInversion(tdbb, inversion->node2, plan, detailed, level);
        break;

    case InversionNode::TYPE_DBKEY:
        if (detailed)
            plan += "DBKEY";
        break;

    case InversionNode::TYPE_INDEX:
    {
        MetaName indexName;
        MET_lookup_index(tdbb, indexName, inversion->retrieval->irb_relation->rel_name,
                         (USHORT) (inversion->retrieval->irb_index + 1));

        if (detailed)
        {
            if (!navigation)
                plan += "Bitmap" + printIndent(++level);

            plan += "Index \"" + printName(tdbb, indexName.c_str()) + "\" Scan";
        }
        else
        {
            plan += (plan.hasData() ? ", " : "") + printName(tdbb, indexName.c_str());
        }
    }
    break;

    default:
        fb_assert(false);
    }
}
Exemplo n.º 3
0
void TraceSvcJrd::startSession(TraceSession& session, bool interactive)
{
	if (!TraceManager::pluginsCount())
	{
		m_svc.printf(false, "Can not start trace session. There are no trace plugins loaded\n");
		return;
	}

	ConfigStorage* storage = TraceManager::getStorage();

	{	// scope
		StorageGuard guard(storage);

		session.ses_auth = m_authBlock;
		session.ses_user = m_user;
		MetaName role = m_role;
		UserId::makeRoleName(role, SQL_DIALECT_V6);
		session.ses_role = role.c_str();

		session.ses_flags = trs_active;
		if (m_admin) {
			session.ses_flags |= trs_admin;
		}

		if (interactive)
		{
			Guid guid;
			GenerateGuid(&guid);

			char* buff = session.ses_logfile.getBuffer(GUID_BUFF_SIZE);
			GuidToString(buff, &guid);

			session.ses_logfile.insert(0, "fb_trace.");
		}

		storage->addSession(session);
		m_chg_number = storage->getChangeNumber();
	}

	m_svc.started();
	m_svc.printf(false, "Trace session ID %ld started\n", session.ses_id);

	if (interactive)
	{
		readSession(session);
		{
			StorageGuard guard(storage);
			storage->removeSession(session.ses_id);
		}
	}
}
Exemplo n.º 4
0
bool InternalConnection::isSameDatabase(thread_db* tdbb, const PathName& dbName,
		const MetaName& user, const string& pwd,
		const MetaName& role) const
{
	if (m_isCurrent)
	{
		const UserId* attUser = m_attachment->getHandle()->att_user;
		return ((user.isEmpty() || user == attUser->getUserName()) &&
				pwd.isEmpty() &&
				(role.isEmpty() || role == attUser->getSqlRole()));
	}

	return Connection::isSameDatabase(tdbb, dbName, user, pwd, role);
}
Exemplo n.º 5
0
void InternalConnection::attach(thread_db* tdbb, const PathName& dbName,
		const MetaName& user, const string& pwd,
		const MetaName& role)
{
	fb_assert(!m_attachment);
	Database* dbb = tdbb->getDatabase();
	fb_assert(dbName.isEmpty() || dbName == dbb->dbb_database_name.c_str());

	// Don't wrap raised errors. This is needed for backward compatibility.
	setWrapErrors(false);

	Jrd::Attachment* attachment = tdbb->getAttachment();
	if ((user.isEmpty() || user == attachment->att_user->getUserName()) &&
		pwd.isEmpty() &&
		(role.isEmpty() || role == attachment->att_user->getSqlRole()))
	{
		m_isCurrent = true;
		m_attachment = attachment->getInterface();
	}
	else
	{
		m_isCurrent = false;
		m_dbName = dbb->dbb_database_name.c_str();
		generateDPB(tdbb, m_dpb, user, pwd, role);

		// Avoid change of m_dpb by validatePassword() below
		ClumpletWriter newDpb(m_dpb);
		validatePassword(tdbb, m_dbName, newDpb);

		FbLocalStatus status;
		{
			EngineCallbackGuard guard(tdbb, *this, FB_FUNCTION);
			RefPtr<JProvider> jInstance(JProvider::getInstance());
			jInstance->setDbCryptCallback(&status, tdbb->getAttachment()->att_crypt_callback);
			m_attachment.assignRefNoIncr(jInstance->attachDatabase(&status, m_dbName.c_str(),
				newDpb.getBufferLength(), newDpb.getBuffer()));
		}

		if (status->getState() & IStatus::STATE_ERRORS)
			raise(&status, tdbb, "JProvider::attach");
	}

	m_sqlDialect = (m_attachment->getHandle()->att_database->dbb_flags & DBB_DB_SQL_dialect_3) ?
					SQL_DIALECT_V6 : SQL_DIALECT_V5;
}
Exemplo n.º 6
0
void PAR_dependency(thread_db* tdbb, CompilerScratch* csb, StreamType stream, SSHORT id,
	const MetaName& field_name)
{
/**************************************
 *
 *	P A R _ d e p e n d e n c y
 *
 **************************************
 *
 * Functional description
 *	Register a field, relation, procedure or exception reference
 *	as a dependency.
 *
 **************************************/
	SET_TDBB(tdbb);

	CompilerScratch::Dependency dependency(0);

	if (csb->csb_rpt[stream].csb_relation)
	{
		dependency.relation = csb->csb_rpt[stream].csb_relation;
		// How do I determine reliably this is a view?
		// At this time, rel_view_rse is still null.
		//if (is_view)
		//	dependency.objType = obj_view;
		//else
			dependency.objType = obj_relation;
	}
	else if (csb->csb_rpt[stream].csb_procedure)
	{
		if (csb->csb_rpt[stream].csb_procedure->isSubRoutine())
			return;

		dependency.procedure = csb->csb_rpt[stream].csb_procedure;
		dependency.objType = obj_procedure;
	}

	if (field_name.length() > 0)
		dependency.subName = FB_NEW_POOL(*tdbb->getDefaultPool()) MetaName(*tdbb->getDefaultPool(), field_name);
	else if (id >= 0)
		dependency.subNumber = id;

	csb->csb_dependencies.push(dependency);
}
Exemplo n.º 7
0
void Applier::setSequence(thread_db* tdbb, const MetaName& genName, SINT64 value)
{
	const auto attachment = tdbb->getAttachment();

	auto gen_id = attachment->att_generators.lookup(genName);

	if (gen_id < 0)
	{
		gen_id = MET_lookup_generator(tdbb, genName);

		if (gen_id < 0)
			raiseError("Generator %s is not found", genName.c_str());

		attachment->att_generators.store(gen_id, genName);
	}

	if (DPM_gen_id(tdbb, gen_id, false, 0) < value)
		DPM_gen_id(tdbb, gen_id, true, value);
}
Exemplo n.º 8
0
bool checkCreateDatabaseGrant(const MetaName& userName, const MetaName& trustedRole,
	const MetaName& sqlRole, const char* securityDb)
{
	if (userName == SYSDBA_USER_NAME)
		return true;

	RefPtr<IAttachment> att;
	RefPtr<ITransaction> tra;
	if (!openDb(securityDb, att, tra))
		return false;

	FbLocalStatus st;
	MetaName role(sqlRole);
	if (role.hasData())
	{
		const UCHAR info[] = { isc_info_db_sql_dialect, isc_info_end };
		UCHAR buffer[BUFFER_TINY];
		att->getInfo(&st, sizeof(info), info, sizeof(buffer), buffer);
		check("IAttachment::getInfo", &st);

		int dialect = SQL_DIALECT_V5;		// reasonable default
		const UCHAR* p = buffer;
		while (*p != isc_info_end && *p != isc_info_truncated && p < buffer + sizeof(buffer))
		{
			const UCHAR item = (UCHAR) *p++;
			const USHORT length = gds__vax_integer(p, sizeof(USHORT));
			p += sizeof(USHORT);

			switch (item)
			{
			case isc_info_db_sql_dialect:
				dialect = gds__vax_integer(p, length);
				break;
			}

			p += length;
		}

		JRD_make_role_name(role, dialect);

		// We need to check is admin role granted to userName in security DB
		const char* sql = "select count(*) from RDB$USER_PRIVILEGES "
			"where RDB$USER = ? and RDB$RELATION_NAME = ? and RDB$PRIVILEGE = 'M'";

		Message prm;
		Field<Varying> u(prm, MAX_SQL_IDENTIFIER_LEN);
		Field<Varying> r(prm, MAX_SQL_IDENTIFIER_LEN);
		u = userName.c_str();
		r = role.c_str();

		Message result;
		Field<ISC_INT64> cnt(result);

		att->execute(&st, tra, 0, sql, SQL_DIALECT_V6, prm.getMetadata(), prm.getBuffer(),
			result.getMetadata(), result.getBuffer());

		if (st->getState() & IStatus::STATE_ERRORS)
		{
			// isc_dsql_relation_err when exec SQL - i.e. table RDB$USER_PRIVILEGES
			// is missing due to non-FB security DB
			if (!fb_utils::containsErrorCode(st->getErrors(), isc_dsql_relation_err))
				check("IAttachment::execute", &st);

			role = "";
		}
		else if (cnt == 0)
			role = "";
	}
	else
		role = trustedRole;

	if (role == ADMIN_ROLE)
		return true;

	Message gr;
	Field<ISC_SHORT> uType(gr);
	Field<Varying> u(gr, MAX_SQL_IDENTIFIER_LEN);
	Field<ISC_SHORT> rType(gr);
	Field<Varying> r(gr, MAX_SQL_IDENTIFIER_LEN);
	uType = obj_user;
	u = userName.c_str();
	rType = role.hasData() ? obj_sql_role : 255;
	r = role.c_str();

	Message result;
	Field<ISC_INT64> cnt(result);

	att->execute(&st, tra, 0,
		"select count(*) from RDB$DB_CREATORS"
		" where (RDB$USER_TYPE = ? and RDB$USER = ?) or (RDB$USER_TYPE = ? and RDB$USER = ?)",
		SQL_DIALECT_V6, gr.getMetadata(), gr.getBuffer(), result.getMetadata(), result.getBuffer());
	if (st->getState() & IStatus::STATE_ERRORS)
	{
		if (fb_utils::containsErrorCode(st->getErrors(), isc_dsql_relation_err))
		{
			// isc_dsql_relation_err when exec SQL - i.e. table RDB$DB_CREATORS
			// is missing due to non-FB3 security DB
			return false;
		}
		check("IAttachment::execute", &st);
	}

	return cnt > 0;
}
Exemplo n.º 9
0
Str::Str(const MetaName& text) throw() :
    Base(isc_arg_string, (ISC_STATUS)(IPTR) text.c_str()) { }
Exemplo n.º 10
0
void Applier::deleteRecord(thread_db* tdbb, TraNumber traNum,
						   const MetaName& relName,
						   ULONG length, const UCHAR* data)
{
	jrd_tra* transaction = NULL;
	if (!m_txnMap.get(traNum, transaction))
		raiseError("Transaction %" SQUADFORMAT" is not found", traNum);

	LocalThreadContext context(tdbb, transaction, m_request);

	TRA_attach_request(transaction, m_request);

	const auto relation = MET_lookup_relation(tdbb, relName);
	if (!relation)
		raiseError("Table %s is not found", relName.c_str());

	if (!(relation->rel_flags & REL_scanned))
		MET_scan_relation(tdbb, relation);

	const auto format = findFormat(tdbb, relation, length);

	record_param rpb;
	rpb.rpb_relation = relation;

	rpb.rpb_record = m_record;
	const auto record = m_record =
		VIO_record(tdbb, &rpb, format, m_request->req_pool);

	rpb.rpb_format_number = format->fmt_version;
	rpb.rpb_address = record->getData();
	rpb.rpb_length = length;
	record->copyDataFrom(data);

	index_desc idx;
	const bool indexed = lookupRecord(tdbb, relation, record, m_bitmap, idx);

	bool found = false;
	AutoPtr<Record> cleanup;

	if (m_bitmap->getFirst())
	{
		record_param tempRpb = rpb;
		tempRpb.rpb_record = NULL;

		do {
			tempRpb.rpb_number.setValue(m_bitmap->current());

			if (VIO_get(tdbb, &tempRpb, transaction, m_request->req_pool) &&
				(!indexed || compareKey(tdbb, relation, idx, record, tempRpb.rpb_record)))
			{
				if (found)
					raiseError("Record in table %s is ambiguously identified using the primary/unique key", relName.c_str());

				rpb = tempRpb;
				found = true;
			}
		} while (m_bitmap->getNext());

		cleanup = tempRpb.rpb_record;
	}

	if (found)
	{
		doDelete(tdbb, &rpb, transaction);
	}
	else
	{
#ifdef RESOLVE_CONFLICTS
		logWarning("Record being deleted from table %s does not exist, ignoring", relName.c_str());
#else
		raiseError("Record in table %s cannot be located via the primary/unique key", relName.c_str());
#endif
	}
}
Exemplo n.º 11
0
void Applier::updateRecord(thread_db* tdbb, TraNumber traNum,
						   const MetaName& relName,
						   ULONG orgLength, const UCHAR* orgData,
						   ULONG newLength, const UCHAR* newData)
{
	jrd_tra* transaction = NULL;
	if (!m_txnMap.get(traNum, transaction))
		raiseError("Transaction %" SQUADFORMAT" is not found", traNum);

	LocalThreadContext context(tdbb, transaction, m_request);

	TRA_attach_request(transaction, m_request);

	const auto relation = MET_lookup_relation(tdbb, relName);
	if (!relation)
		raiseError("Table %s is not found", relName.c_str());

	if (!(relation->rel_flags & REL_scanned))
		MET_scan_relation(tdbb, relation);

	const auto orgFormat = findFormat(tdbb, relation, orgLength);

	record_param orgRpb;
	orgRpb.rpb_relation = relation;

	orgRpb.rpb_record = m_record;
	const auto orgRecord = m_record =
		VIO_record(tdbb, &orgRpb, orgFormat, m_request->req_pool);

	orgRpb.rpb_format_number = orgFormat->fmt_version;
	orgRpb.rpb_address = orgRecord->getData();
	orgRpb.rpb_length = orgLength;
	orgRecord->copyDataFrom(orgData);

	BlobList sourceBlobs(getPool());
	sourceBlobs.resize(orgFormat->fmt_count);
	for (USHORT id = 0; id < orgFormat->fmt_count; id++)
	{
		dsc desc;
		if (DTYPE_IS_BLOB(orgFormat->fmt_desc[id].dsc_dtype) &&
			EVL_field(NULL, orgRecord, id, &desc))
		{
			const auto source = (bid*) desc.dsc_address;

			if (!source->isEmpty())
				sourceBlobs[id] = *source;
		}
	}

	index_desc idx;
	const auto indexed = lookupRecord(tdbb, relation, orgRecord, m_bitmap, idx);

	bool found = false;
	AutoPtr<Record> cleanup;

	if (m_bitmap->getFirst())
	{
		record_param tempRpb = orgRpb;
		tempRpb.rpb_record = NULL;

		do {
			tempRpb.rpb_number.setValue(m_bitmap->current());

			if (VIO_get(tdbb, &tempRpb, transaction, m_request->req_pool) &&
				(!indexed || compareKey(tdbb, relation, idx, orgRecord, tempRpb.rpb_record)))
			{
				if (found)
					raiseError("Record in table %s is ambiguously identified using the primary/unique key", relName.c_str());

				orgRpb = tempRpb;
				found = true;
			}
		} while (m_bitmap->getNext());

		cleanup = tempRpb.rpb_record;
	}

	const auto newFormat = findFormat(tdbb, relation, newLength);

	record_param newRpb;
	newRpb.rpb_relation = relation;

	newRpb.rpb_record = NULL;
	AutoPtr<Record> newRecord(VIO_record(tdbb, &newRpb, newFormat, m_request->req_pool));

	newRpb.rpb_format_number = newFormat->fmt_version;
	newRpb.rpb_address = newRecord->getData();
	newRpb.rpb_length = newLength;
	newRecord->copyDataFrom(newData);

	if (found)
	{
		doUpdate(tdbb, &orgRpb, &newRpb, transaction, &sourceBlobs);
	}
	else
	{
#ifdef RESOLVE_CONFLICTS
		logWarning("Record being updated in table %s does not exist, inserting instead", relName.c_str());
		doInsert(tdbb, &newRpb, transaction);
#else
		raiseError("Record in table %s cannot be located via the primary/unique key", relName.c_str());
#endif
	}
}
Exemplo n.º 12
0
void Applier::insertRecord(thread_db* tdbb, TraNumber traNum,
						   const MetaName& relName,
						   ULONG length, const UCHAR* data)
{
	jrd_tra* transaction = NULL;
	if (!m_txnMap.get(traNum, transaction))
		raiseError("Transaction %" SQUADFORMAT" is not found", traNum);

	LocalThreadContext context(tdbb, transaction, m_request);

	TRA_attach_request(transaction, m_request);

	const auto relation = MET_lookup_relation(tdbb, relName);
	if (!relation)
		raiseError("Table %s is not found", relName.c_str());

	if (!(relation->rel_flags & REL_scanned))
		MET_scan_relation(tdbb, relation);

	const auto format = findFormat(tdbb, relation, length);

	record_param rpb;
	rpb.rpb_relation = relation;

	rpb.rpb_record = m_record;
	const auto record = m_record =
		VIO_record(tdbb, &rpb, format, m_request->req_pool);

	rpb.rpb_format_number = format->fmt_version;
	rpb.rpb_address = record->getData();
	rpb.rpb_length = length;
	record->copyDataFrom(data);

	try
	{
		doInsert(tdbb, &rpb, transaction);
		return;
	}
	catch (const status_exception& ex)
	{
		// Uniqueness violation is handled below, other exceptions are re-thrown
		if (ex.value()[1] != isc_unique_key_violation &&
			ex.value()[1] != isc_no_dup)
		{
			throw;
		}

		fb_utils::init_status(tdbb->tdbb_status_vector);
	}

	bool found = false;

#ifdef RESOLVE_CONFLICTS
	index_desc idx;
	const auto indexed = lookupRecord(tdbb, relation, record, m_bitmap, idx);

	AutoPtr<Record> cleanup;

	if (m_bitmap->getFirst())
	{
		record_param tempRpb = rpb;
		tempRpb.rpb_record = NULL;

		do {
			tempRpb.rpb_number.setValue(m_bitmap->current());

			if (VIO_get(tdbb, &tempRpb, transaction, m_request->req_pool) &&
				(!indexed || compareKey(tdbb, relation, idx, record, tempRpb.rpb_record)))
			{
				if (found)
					raiseError("Record in table %s is ambiguously identified using the primary/unique key", relName.c_str());

				rpb = tempRpb;
				found = true;
			}
		} while (m_bitmap->getNext());

		cleanup = tempRpb.rpb_record;
	}
#endif

	if (found)
	{
		logWarning("Record being inserted into table %s already exists, updating instead", relName.c_str());

		record_param newRpb;
		newRpb.rpb_relation = relation;

		newRpb.rpb_record = NULL;
		AutoPtr<Record> newRecord(VIO_record(tdbb, &newRpb, format, m_request->req_pool));

		newRpb.rpb_format_number = format->fmt_version;
		newRpb.rpb_address = newRecord->getData();
		newRpb.rpb_length = length;
		newRecord->copyDataFrom(data);

		doUpdate(tdbb, &rpb, &newRpb, transaction, NULL);
	}
	else
	{
		doInsert(tdbb, &rpb, transaction); // second (paranoid) attempt
	}
}
Exemplo n.º 13
0
bool checkCreateDatabaseGrant(const MetaName& userName, const MetaName& trustedRole,
	const MetaName& sqlRole, const char* securityDb)
{
	if (userName == DBA_USER_NAME)
		return true;

	RefPtr<IAttachment> att;
	RefPtr<ITransaction> tra;
	bool hasDb = openDb(securityDb, att, tra);

	FbLocalStatus st;
	MetaName role(sqlRole);
	if (hasDb && role.hasData())
	{
		const UCHAR info[] = { isc_info_db_sql_dialect, isc_info_end };
		UCHAR buffer[BUFFER_TINY];
		att->getInfo(&st, sizeof(info), info, sizeof(buffer), buffer);
		check("IAttachment::getInfo", &st);

		int dialect = SQL_DIALECT_V5;		// reasonable default
		const UCHAR* p = buffer;
		while (*p != isc_info_end && *p != isc_info_truncated && p < buffer + sizeof(buffer))
		{
			const UCHAR item = (UCHAR) *p++;
			const USHORT length = gds__vax_integer(p, sizeof(USHORT));
			p += sizeof(USHORT);

			switch (item)
			{
			case isc_info_db_sql_dialect:
				dialect = gds__vax_integer(p, length);
				break;
			}

			p += length;
		}

		UserId::makeRoleName(role, dialect);

		// We need to check is role granted to userName in security DB
		const char* sql = "select count(*) from RDB$USER_PRIVILEGES "
			"where RDB$USER = ? and RDB$RELATION_NAME = ? and RDB$PRIVILEGE = 'M'";

		Message prm;
		Field<Varying> u(prm, MAX_SQL_IDENTIFIER_LEN);
		Field<Varying> r(prm, MAX_SQL_IDENTIFIER_LEN);
		u = userName.c_str();
		r = role.c_str();

		Message result;
		Field<ISC_INT64> cnt(result);

		att->execute(&st, tra, 0, sql, SQL_DIALECT_V6, prm.getMetadata(), prm.getBuffer(),
			result.getMetadata(), result.getBuffer());

		if (st->getState() & IStatus::STATE_ERRORS)
		{
			// isc_dsql_relation_err when exec SQL - i.e. table RDB$USER_PRIVILEGES
			// is missing due to non-FB security DB
			if (!fb_utils::containsErrorCode(st->getErrors(), isc_dsql_relation_err))
				check("IAttachment::execute", &st);

			role = "";
		}
		else if (cnt == 0)
			role = "";
	}
	else
		role = trustedRole;

	if (role == ADMIN_ROLE)
		return true;

	if (!hasDb)
		return false;

	// check db creators table
	Message gr;
	Field<ISC_SHORT> uType(gr);
	Field<Varying> u(gr, MAX_SQL_IDENTIFIER_LEN);
	Field<ISC_SHORT> rType(gr);
	Field<Varying> r(gr, MAX_SQL_IDENTIFIER_LEN);
	uType = obj_user;
	u = userName.c_str();
	rType = role.hasData() ? obj_sql_role : 255;
	r = role.c_str();

	Message result;
	Field<ISC_INT64> cnt(result);

	att->execute(&st, tra, 0,
		"select count(*) from RDB$DB_CREATORS"
		" where (RDB$USER_TYPE = ? and RDB$USER = ?) or (RDB$USER_TYPE = ? and RDB$USER = ?)",
		SQL_DIALECT_V6, gr.getMetadata(), gr.getBuffer(), result.getMetadata(), result.getBuffer());
	if (st->getState() & IStatus::STATE_ERRORS)
	{
		if (fb_utils::containsErrorCode(st->getErrors(), isc_dsql_relation_err))
		{
			// isc_dsql_relation_err when exec SQL - i.e. table RDB$DB_CREATORS
			// is missing due to non-FB3 security DB
			return false;
		}
		check("IAttachment::execute", &st);
	}

	if (cnt > 0)
		return true;

	if (!role.hasData())
		role = "NONE";

	Message par2;
	Field<ISC_SHORT> uType2(par2);
	Field<Varying> u2(par2, MAX_SQL_IDENTIFIER_LEN);
	Field<Varying> r2(par2, MAX_SQL_IDENTIFIER_LEN);
	uType2 = obj_user;
	u2 = userName.c_str();
	r2 = role.c_str();

	Message res2;
	Field<Text> priv(res2, 8);

	const char* sql =
		"with recursive role_tree as ( "
		"   select rdb$relation_name as nm, 0 as ur from rdb$user_privileges "
		"       where rdb$privilege = 'M' and rdb$field_name = 'D' and rdb$user_type = ? and rdb$user = ? "
		"   union all "
		"   select rdb$role_name as nm, 1 as ur from rdb$roles "
		"       where rdb$role_name = ? "
		"   union all "
		"   select p.rdb$relation_name as nm, t.ur from rdb$user_privileges p "
		"       join role_tree t on t.nm = p.rdb$user "
		"       where p.rdb$privilege = 'M' and (p.rdb$field_name = 'D' or t.ur = 1)) "
		"select r.rdb$system_privileges "
		"   from role_tree t join rdb$roles r on t.nm = r.rdb$role_name ";
	RefPtr<IResultSet> rs(REF_NO_INCR, att->openCursor(&st, tra, 0, sql,
		SQL_DIALECT_V6, par2.getMetadata(), par2.getBuffer(), res2.getMetadata(), NULL, 0));
	check("IAttachment::execute", &st);

	UserId::Privileges privileges, wrk;

	while (rs->fetchNext(&st, res2.getBuffer()) == IStatus::RESULT_OK)
	{
		wrk.load(&priv);
		privileges |= wrk;
	}

	check("IResultSet::fetchNext", &st);

	return wrk.test(CREATE_DATABASE);
}
Exemplo n.º 14
0
void RecordSource::printInversion(thread_db* tdbb, const InversionNode* inversion,
								  string& plan, bool detailed, unsigned level, bool navigation)
{
	if (detailed)
		plan += printIndent(++level);

	switch (inversion->type)
	{
	case InversionNode::TYPE_AND:
		if (detailed)
			plan += "Bitmap And";
		printInversion(tdbb, inversion->node1, plan, detailed, level);
		printInversion(tdbb, inversion->node2, plan, detailed, level);
		break;

	case InversionNode::TYPE_OR:
	case InversionNode::TYPE_IN:
		if (detailed)
			plan += "Bitmap Or";
		printInversion(tdbb, inversion->node1, plan, detailed, level);
		printInversion(tdbb, inversion->node2, plan, detailed, level);
		break;

	case InversionNode::TYPE_DBKEY:
		if (detailed)
			plan += "DBKEY";
		break;

	case InversionNode::TYPE_INDEX:
		{
			const IndexRetrieval* const retrieval = inversion->retrieval;
			const jrd_rel* const relation = retrieval->irb_relation;

			MetaName indexName;
			if (retrieval->irb_name && retrieval->irb_name->hasData())
				indexName = *retrieval->irb_name;
			else
				indexName.printf("<index id %d>", retrieval->irb_index + 1);

			if (detailed)
			{
				if (!navigation)
					plan += "Bitmap" + printIndent(++level);

				const index_desc& idx = retrieval->irb_desc;
				const bool uniqueIdx = (idx.idx_flags & idx_unique);
				const USHORT segCount = idx.idx_count;

				const USHORT minSegs = MIN(retrieval->irb_lower_count, retrieval->irb_upper_count);
				const USHORT maxSegs = MAX(retrieval->irb_lower_count, retrieval->irb_upper_count);

				const bool equality = (retrieval->irb_generic & irb_equality);
				const bool partial = (retrieval->irb_generic & irb_partial);

				const bool fullscan = (maxSegs == 0);
				const bool unique = uniqueIdx && equality && (minSegs == segCount);

				string bounds;
				if (!unique && !fullscan)
				{
					if (retrieval->irb_lower_count && retrieval->irb_upper_count)
					{
						if (equality)
						{
							if (partial)
								bounds.printf(" (partial match: %d/%d)", maxSegs, segCount);
							else
								bounds.printf(" (full match)");
						}
						else
						{
							bounds.printf(" (lower bound: %d/%d, upper bound: %d/%d)",
										  retrieval->irb_lower_count, segCount,
										  retrieval->irb_upper_count, segCount);
						}
					}
					else if (retrieval->irb_lower_count)
					{
						bounds.printf(" (lower bound: %d/%d)",
									  retrieval->irb_lower_count, segCount);
					}
					else if (retrieval->irb_upper_count)
					{
						bounds.printf(" (upper bound: %d/%d)",
									  retrieval->irb_upper_count, segCount);
					}
				}

				plan += "Index " + printName(tdbb, indexName.c_str()) +
					(fullscan ? " Full" : unique ? " Unique" : " Range") + " Scan" + bounds;
			}
			else
			{
				plan += (plan.hasData() ? ", " : "") + printName(tdbb, indexName.c_str(), false);
			}
		}
		break;

	default:
		fb_assert(false);
	}
}