You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by va...@apache.org on 2019/09/05 19:11:41 UTC

[couchdb] branch prototype/fdb-layer updated: Add a max db name length config option

This is an automated email from the ASF dual-hosted git repository.

vatamane pushed a commit to branch prototype/fdb-layer
in repository https://gitbox.apache.org/repos/asf/couchdb.git


The following commit(s) were added to refs/heads/prototype/fdb-layer by this push:
     new d6b6155  Add a max db name length config option
d6b6155 is described below

commit d6b6155f2c0f016c276d7bb2f051b14bfe97201e
Author: Nick Vatamaniuc <va...@apache.org>
AuthorDate: Thu Sep 5 14:50:58 2019 -0400

    Add a max db name length config option
    
    This is done for compatibility with CouchDB < 4.x where this limit was
    implicitly enforced by the file system's max filename size. The default value
    enforces the same limit for FDB in case users decide to replicate back and
    forth between old and new instances with 'create_target = true' option.
---
 rel/overlay/etc/default.ini      |  7 +++++++
 src/fabric/src/fabric2_db.erl    | 20 ++++++++++++++++++++
 test/elixir/test/basics_test.exs |  7 +++++++
 3 files changed, 34 insertions(+)

diff --git a/rel/overlay/etc/default.ini b/rel/overlay/etc/default.ini
index 9f892b6..51d450b 100644
--- a/rel/overlay/etc/default.ini
+++ b/rel/overlay/etc/default.ini
@@ -37,6 +37,13 @@ default_security = admin_local
 ; influenced directly with this setting - increase for faster processing at the
 ; expense of more memory usage.
 changes_doc_ids_optimization_threshold = 100
+;
+; Maximum database name length. The default setting is chosen for CouchDB < 4.x
+; compatibility, where it was determined by the maximum file name size. On most
+; current file systems that is 255, and with timestamp and ".couch" extension
+; subtracted it ends up as 238.
+;max_database_name_length = 238
+;
 ; Maximum document ID length. Can be set to an integer or 'infinity'.
 ;max_document_id_length = infinity
 ;
diff --git a/src/fabric/src/fabric2_db.erl b/src/fabric/src/fabric2_db.erl
index b2945b6..f3036e4 100644
--- a/src/fabric/src/fabric2_db.erl
+++ b/src/fabric/src/fabric2_db.erl
@@ -131,6 +131,10 @@
 -include("fabric2.hrl").
 
 
+% Default max database name length is based on CouchDb < 4.x compatibility. See
+% default.ini entry for additional information.
+-define(DEFAULT_MAX_DATABASE_NAME_LENGTH, 238).
+
 -define(DBNAME_REGEX,
     "^[a-z][a-z0-9\\_\\$()\\+\\-\\/]*" % use the stock CouchDB regex
     "(\\.[0-9]{10,})?$" % but allow an optional shard timestamp at the end
@@ -866,6 +870,22 @@ validate_dbname(DbName) when is_binary(DbName) ->
         DbName, Normalized, fun validate_dbname_int/2).
 
 validate_dbname_int(DbName, Normalized) when is_binary(DbName) ->
+    case validate_dbname_length(DbName) of
+        ok -> validate_dbname_pat(DbName, Normalized);
+        {error, _} = Error -> Error
+    end.
+
+
+validate_dbname_length(DbName) ->
+    MaxLength = config:get_integer("couchdb", "max_database_name_length",
+        ?DEFAULT_MAX_DATABASE_NAME_LENGTH),
+    case byte_size(DbName) =< MaxLength of
+        true -> ok;
+        false -> {error, {database_name_too_long, DbName}}
+    end.
+
+
+validate_dbname_pat(DbName, Normalized) ->
     DbNoExt = couch_util:drop_dot_couch_ext(DbName),
     case re:run(DbNoExt, ?DBNAME_REGEX, [{capture,none}, dollar_endonly]) of
         match ->
diff --git a/test/elixir/test/basics_test.exs b/test/elixir/test/basics_test.exs
index 736cdbb..cde11aa 100644
--- a/test/elixir/test/basics_test.exs
+++ b/test/elixir/test/basics_test.exs
@@ -45,6 +45,13 @@ defmodule BasicsTest do
     {:ok, _} = delete_db(db_name)
   end
 
+  test "Exceeding configured DB name size limit returns an error" do
+    db_name = String.duplicate("x", 239)
+    resp = Couch.put("/#{db_name}")
+    assert resp.status_code == 400
+    assert resp.body["error"] == "database_name_too_long"
+  end
+
   @tag :with_db
   test "Created database has appropriate db info name", context do
     db_name = context[:db_name]