Beispiel #1
0
QuotaForIntervalsPtr Quota::get(const String & quota_key, const String & user_name, const Poco::Net::IPAddress & ip)
{
    if (!quota_key.empty() && !ignore_key_if_not_keyed && (!is_keyed || keyed_by_ip))
        throw Exception("Quota " + name + " (for user " + user_name + ") doesn't allow client supplied keys.",
            ErrorCodes::QUOTA_DOESNT_ALLOW_KEYS);

    /** Quota is calculated separately:
      * - for each IP-address, if 'keyed_by_ip';
      * - otherwise for each 'quota_key', if present;
      * - otherwise for each 'user_name'.
      */

    UInt64 quota_key_hashed = sipHash64(
        keyed_by_ip
            ? ip.toString()
            : (!quota_key.empty()
                ? quota_key
                : user_name));

    std::lock_guard<std::mutex> lock(mutex);

    Container::iterator it = quota_for_keys.find(quota_key_hashed);
    if (quota_for_keys.end() == it)
        it = quota_for_keys.emplace(quota_key_hashed, std::make_shared<QuotaForIntervals>(max, user_name)).first;

    return it->second;
}
StoragePtr TableFunctionShardByHash::execute(ASTPtr ast_function, Context & context) const
{
	ASTs & args_func = typeid_cast<ASTFunction &>(*ast_function).children;

	const char * err = "Table function 'shardByHash' requires 4 parameters: "
		"cluster name, key string to hash, name of remote database, name of remote table.";

	if (args_func.size() != 1)
		throw Exception(err, ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH);

	ASTs & args = typeid_cast<ASTExpressionList &>(*args_func.at(0)).children;

	if (args.size() != 4)
		throw Exception(err, ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH);

	String cluster_name;
	String key;
	String remote_database;
	String remote_table;

	auto getStringLiteral = [](const IAST & node, const char * description)
	{
		const ASTLiteral * lit = typeid_cast<const ASTLiteral *>(&node);
		if (!lit)
			throw Exception(description + String(" must be string literal (in single quotes)."), ErrorCodes::BAD_ARGUMENTS);

		if (lit->value.getType() != Field::Types::String)
			throw Exception(description + String(" must be string literal (in single quotes)."), ErrorCodes::BAD_ARGUMENTS);

		return safeGet<const String &>(lit->value);
	};

	cluster_name = getClusterName(*args[0]);
	key = getStringLiteral(*args[1], "Key to hash");

	args[2] = evaluateConstantExpressionOrIdentidierAsLiteral(args[2], context);
	args[3] = evaluateConstantExpressionOrIdentidierAsLiteral(args[3], context);

	remote_database = static_cast<const ASTLiteral &>(*args[2]).value.safeGet<String>();
	remote_table = static_cast<const ASTLiteral &>(*args[3]).value.safeGet<String>();

	/// Аналогично другим TableFunctions.
	for (auto & arg : args)
		if (ASTIdentifier * id = typeid_cast<ASTIdentifier *>(arg.get()))
			id->kind = ASTIdentifier::Table;

	const Cluster & cluster = context.getCluster(cluster_name);
	size_t shard_index = sipHash64(key) % cluster.getShardCount();

	std::shared_ptr<Cluster> shard(cluster.getClusterWithSingleShard(shard_index).release());

	return StorageDistributed::create(
		getName(),
		std::make_shared<NamesAndTypesList>(getStructureOfRemoteTable(*shard, remote_database, remote_table, context)),
		remote_database,
		remote_table,
		shard,
		context);
}