diff --git a/doc/sphinx/book/box/authentication.rst b/doc/sphinx/book/box/authentication.rst index 1f1483dae9c079e22d9dc0505c4c37ebdeda5a1e..eaf292017e35fabd7347f340c21f3706837b4621 100644 --- a/doc/sphinx/book/box/authentication.rst +++ b/doc/sphinx/book/box/authentication.rst @@ -47,6 +47,8 @@ client application, read the `scramble.h`_ header file. .. _MySQL introduced several years ago: http://dev.mysql.com/doc/refman/4.1/en/password-hashing.html .. _scramble.h: https://github.com/tarantool/tarantool/blob/master/src/scramble.h +.. _authentication-users: + =========================================================== Users and the _user space =========================================================== @@ -235,8 +237,10 @@ privilege to read from a space named ``space55``, and then took the privilege aw Only the creator of a space can drop, alter, or truncate the space. Only the creator of a user can change a different user's password. +.. _authentication-funcs: + =========================================================== - Functions and _func space + Functions and the _func space =========================================================== The fields in the _func space are: @@ -362,6 +366,8 @@ and later a guest user, who wishes to see the payroll, might say: box.session.su('manager') box.space.payroll:select{'Jones'} +.. _authentication-roles: + =========================================================== Roles =========================================================== diff --git a/doc/sphinx/book/box/box_index.rst b/doc/sphinx/book/box/box_index.rst index fd7e22aa47434dacbae11572027093eeeee35d8a..785e1271596fbea1c6a3b3a426cd46c03ccd7c0f 100644 --- a/doc/sphinx/book/box/box_index.rst +++ b/doc/sphinx/book/box/box_index.rst @@ -30,7 +30,7 @@ API is a direct binding to corresponding methods of index objects of type * :samp:`{index_object}` = an :ref:`object reference <object-reference>`. - :rtype: string + :rtype: .. data:: parts @@ -107,15 +107,15 @@ API is a direct binding to corresponding methods of index objects of type Note: Formally the logic for TREE index searches is: |br| comparison-operator is = or >= or > or <= or < depending on iterator-type |br| for i = 1 to number-of-parts-of-search-value |br| - |nbsp| if search-value-part[i] is ``nil`` |br| - |nbsp| or search-value-part[i] <comparison-operator> index-key-part[i] is true |br| + |nbsp| if (search-value-part[i] is ``nil`` and <comparison-operator> is "=") |br| + |nbsp| or (search-value-part[i] <comparison-operator> index-key-part[i] is true) |br| |nbsp| then comparison-result[i] is true |br| if all comparison-results are true, then search-value "matches" index key. |br| - Notice how, according to this logic, regardless what the iterator type is, - a comparison is always true when a search-value-part is ``nil`` or is missing. - This behavior applies for the memtx storage engine only - (the sophia storage engine does not allow search-value-parts to be ``nil`` or missing). - This behavior of searches with nil is subject to change. + Notice how, according to this logic, regardless what the index-key-part contains, + the comparison-result for equality is always true when a search-value-part is ``nil`` + or is missing. This behavior of searches with nil is subject to change. + + Note re storage engine: sophia does not allow search-value-parts to be ``nil`` or missing. +---------------+-----------+---------------------------------------------+ | Type | Arguments | Description | @@ -130,6 +130,8 @@ API is a direct binding to corresponding methods of index objects of type | or 'REQ' | value | ``box.index.EQ``. | | | | Tuples are returned in descending order by | | | | index key. | + | | | Note re storage engine: sophia does not | + | | | REQ. | +---------------+-----------+---------------------------------------------+ | box.index.GT | search | The comparison operator is '>' (greater | | or 'GT' | value | than). | @@ -459,6 +461,8 @@ API is a direct binding to corresponding methods of index objects of type - - ['Tuple with bit value = 01', 1] ... + .. _index_min: + .. method:: min([key-value]) Find the minimum value in the specified index. @@ -477,6 +481,8 @@ API is a direct binding to corresponding methods of index objects of type Complexity Factors: Index size, Index type. + Note re storage engine: sophia does not support :codenormal:`min()`. + **Example:** .. code-block:: tarantoolsession @@ -486,6 +492,8 @@ API is a direct binding to corresponding methods of index objects of type - ['Alpha!', 55, 'This is the first tuple!'] ... + .. _index_max: + .. method:: max([key-value]) Find the maximum value in the specified index. @@ -504,6 +512,8 @@ API is a direct binding to corresponding methods of index objects of type Complexity Factors: Index size, Index type. + Note re storage engine: sophia does not support :codenormal:`max()`. + **Example:** .. code-block:: tarantoolsession @@ -513,6 +523,8 @@ API is a direct binding to corresponding methods of index objects of type - ['Gamma!', 55, 'This is the third tuple!'] ... + .. _index_random: + .. method:: random(random-value) Find a random value in the specified index. This method is useful when it's @@ -529,6 +541,8 @@ API is a direct binding to corresponding methods of index objects of type Complexity Factors: Index size, Index type. + Note re storage engine: sophia does not support :codenormal:`random()`. + **Example:** .. code-block:: tarantoolsession @@ -538,6 +552,8 @@ API is a direct binding to corresponding methods of index objects of type - ['Beta!', 66, 'This is the second tuple!'] ... + .. _index_count: + .. method:: count(key-value, options) Iterate over an index, counting the number of @@ -555,6 +571,8 @@ API is a direct binding to corresponding methods of index objects of type is only applicable for the memtx storage engine. :rtype: number + Note re storage engine: sophia does not support :codenormal:`count()`. + **Example:** .. code-block:: tarantoolsession @@ -604,6 +622,8 @@ API is a direct binding to corresponding methods of index objects of type :return: the deleted tuple. :rtype: tuple + .. _index_alter: + .. method:: alter({options}) Alter an index. @@ -620,6 +640,8 @@ API is a direct binding to corresponding methods of index objects of type the first index cannot be changed to {unique = false}, or the alter function is only applicable for the memtx storage engine. + Note re storage engine: sophia does not support :codenormal:`alter()`. + **Example:** .. code-block:: tarantoolsession diff --git a/doc/sphinx/book/box/box_schema.rst b/doc/sphinx/book/box/box_schema.rst index e35dad3e909dfe817bc34d4944a26d0bd39184f0..f167140de74fa86b2c9751c899c0fe55b6d541ee 100644 --- a/doc/sphinx/book/box/box_schema.rst +++ b/doc/sphinx/book/box/box_schema.rst @@ -6,7 +6,9 @@ .. module:: box.schema -The ``box.schema`` package has one data-definition function: ``space.create()``. +The ``box.schema`` package has data-definition functions +for spaces, users, roles, and function tuples. + .. function:: box.schema.space.create(space-name [, {options} ]) @@ -14,7 +16,7 @@ The ``box.schema`` package has one data-definition function: ``space.create()``. :param string space-name: name of space, which should not be a number and should not contain special characters - :param table options: + :param table options: see "Options for box.schema.space.create" chart, below :return: space object :rtype: userdata @@ -42,6 +44,17 @@ The ``box.schema`` package has one data-definition function: ``space.create()``. | format | field names+types | table | (blank) | +---------------+--------------------+---------+---------------------+ + :param num space-id: the numeric identifier established by box.schema.space.create + + Note: for symmetry, there are other box.schema functions targeting + space objects, for example + :codenormal:`box.schema.space.drop(`:codeitalic:`space-id`:codenormal:`)` + will drop a space. However, the common approach is to use functions + attached to the space objects, for example + :func:`space_object:drop() <space_object.drop>`. + + Note re storage engine: sophia does not support temporary spaces. + ================================================= Example ================================================= @@ -68,3 +81,238 @@ For an illustration with the :code:`format` clause, see After a space is created, usually the next step is to :func:`create an index <space_object.create_index>` for it, and then it is available for insert, select, and all the other :mod:`box.space` functions. + + +.. function:: box.schema.user.create(user-name [, {options} ]) + + Create a user. + For explanation of how Tarantool maintains user data, see + section :ref:`Users and the _user space <authentication-users>`. + + :param string user-name: name of user, which should not be a number + and should not contain special characters + :param table options: if_not_exists, password + + :return: nil + + Examples: |br| + :codenormal:`box.schema.user.create('Lena')` |br| + :codenormal:`box.schema.user.create('Lena', {password='X'})` |br| + :codenormal:`box.schema.user.create('Lena', {if_not_exists=false})` + +.. function:: box.schema.user.drop(user-name) + + Drop a user. + For explanation of how Tarantool maintains user data, see + section :ref:`Users and the _user space <authentication-users>`. + + :param string user-name: the name of the user + + Example: |br| + :codenormal:`box.schema.user.drop('Lena')` + +.. function:: box.schema.user.exists(user-name) + + Return true if a user exists; return false if a user does not exist. + + :param string user-name: the name of the user + :rtype: bool + + Example: |br| + :codenormal:`box.schema.user.exists('Lena')` + +.. function:: box.schema.user.grant(user-name, privileges) + + Grant :ref:`privileges <privileges>` to a user. + + :param string user-name: the name of the user + :param string privileges: either privilege,object-type,object-name + or privilege,'universe' where privilege = + 'read' or 'write' or 'execute' or a combination + and object-type = 'space' or 'function'. + Or: role-name. + + Examples: |br| + :codenormal:`box.schema.user.grant('Lena','read', 'space', 'tester')` |br| + :codenormal:`box.schema.user.grant('Lena','execute', 'function', 'f')` |br| + :codenormal:`box.schema.user.grant('Lena','read,write', 'universe')` |br| + :codenormal:`box.schema.user.grant('Lena', 'Accountant')` + +.. function:: box.schema.user.revoke(user-name, privileges) + + Revoke :ref:`privileges <privileges>` from a user. + + :param string user-name: the name of the user + :param string privileges: either privilege,object-type,object-name + or privilege,'universe' where privilege = + 'read' or 'write' or 'execute' or a combination + and object-type = 'space' or 'function'. + Or: role-name. + + Examples: |br| + :codenormal:`box.schema.user.revoke('Lena','read', 'space', 'tester')` |br| + :codenormal:`box.schema.user.revoke('Lena','execute', 'function', 'f')` |br| + :codenormal:`box.schema.user.revoke('Lena','read,write', 'universe')` |br| + :codenormal:`box.schema.user.revoke('Lena', 'Accountant')` + +.. function:: box.schema.user.password(password) + + Return a hash of a password. + + :param string password: password + :rtype: string + + Example: |br| + :codenormal:`box.schema.user.password('ЛЕÐÐ')` + +.. function:: box.schema.user.passwd([user-name,] password) + + Associate a password with the user who is currently logged in. + or with another user. + Users who wish to change their own passwords should + use box.schema.user.passwd(password). + Administrators who wish to change passwords of other users should + use box.schema.user.passwd(user-name, password). + + :param string user-name: user-name + :param string password: password + + Examples: |br| + :codenormal:`box.schema.user.passwd('ЛЕÐÐ')` |br| + :codenormal:`box.schema.user.passwd('Lena', 'ЛЕÐÐ')` + +.. function:: box.schema.user.info([user-name]) + + Return a description of a user's privileges. + + :param string user-name: the name of the user. + This is optional; if it is not + supplied, then the information + will be for the user who is + currently logged in. + + Example: |br| + :codenormal:`box.schema.user.info()` |br| + :codenormal:`box.schema.user.info('Lena')` + +.. function:: box.schema.role.create(role-name [, {options} ]) + + Create a role. + For explanation of how Tarantool maintains role data, see + section :ref:`Roles <authentication-roles>`. + + :param string role-name: name of role, which should not be a number + and should not contain special characters + :param table options: if_not_exists + + :return: nil + + Examples: |br| + :codenormal:`box.schema.role.create('Accountant')` |br| + :codenormal:`box.schema.role.create('Accountant', {if_not_exists=false})` + +.. function:: box.schema.role.drop(role-name) + + Drop a role. + For explanation of how Tarantool maintains role data, see + section :ref:`Roles <authentication-roles>`. + + :param string role-name: the name of the role + + Example: |br| + :codenormal:`box.schema.role.drop('Accountant')` + +.. function:: box.schema.role.exists(role-name) + + Return true if a role exists; return false if a role does not exist. + + :param string role-name: the name of the role + :rtype: bool + + Example: |br| + :codenormal:`box.schema.role.exists('Accountant')` + +.. function:: box.schema.role.grant(role-name, privileges) + + Grant :ref:`privileges <privileges>` to a role. + + :param string role-name: the name of the role + :param string privileges: either privilege,object-type,object-name + or privilege,'universe' where privilege = + 'read' or 'write' or 'execute' or a combination + and object-type = 'space' or 'function'. + Or: role-name. + + Examples: |br| + :codenormal:`box.schema.role.grant('Accountant','read', 'space', 'tester')` |br| + :codenormal:`box.schema.role.grant('Accountant','execute', 'function', 'f')` |br| + :codenormal:`box.schema.role.grant('Accountant','read,write', 'universe')` |br| + :codenormal:`box.schema.role.grant('public', 'Accountant')` + +.. function:: box.schema.role.revoke(role-name, privileges) + + Revoke :ref:`privileges <privileges>` to a role. + + :param string role-name: the name of the role + :param string privileges: either privilege,object-type,object-name + or privilege,'universe' where privilege = + 'read' or 'write' or 'execute' or a combination + and object-type = 'space' or 'function' + + Examples: |br| + :codenormal:`box.schema.role.revoke('Accountant','read', 'space', 'tester')` |br| + :codenormal:`box.schema.role.revoke('Accountant','execute', 'function', 'f')` |br| + :codenormal:`box.schema.role.revoke('Accountant','read,write', 'universe')` |br| + :codenormal:`box.schema.role.revoke('public', 'Accountant')` + +.. function:: box.schema.role.info([role-name]) + + Return a description of a role's privileges. + + :param string role-name: the name of the role. + + Example: |br| + :codenormal:`box.schema.role.info('Accountant')` + +.. function:: box.schema.func.create(func-name [, {options} ]) + + Create a function tuple. + This does not create the function itself -- that is done with Lua -- + but if it is necessary to grant privileges for a function, + box.schema.func.create must be done first. + For explanation of how Tarantool maintains function data, see + section :ref:`Functions and the _func space <authentication-funcs>`. + + :param string func-name: name of function, which should not be a number + and should not contain special characters + :param table options: if_not_exists, setuid, language + + :return: nil + + Examples: |br| + :codenormal:`box.schema.func.create('calculate')` |br| + :codenormal:`box.schema.func.create('calculate', {if_not_exists=false})` |br| + :codenormal:`box.schema.func.create('calculate', {setuid=false})` |br| + :codenormal:`box.schema.func.create('calculate', {language='LUA'})` + +.. function:: box.schema.func.drop(func-name) + + Drop a function tuple. + For explanation of how Tarantool maintains function data, see + section :ref:`Functions and the _func space <authentication-funcs>`. + + :param string func-name: the name of the function + + Example: |br| + :codenormal:`box.schema.func.drop('calculate')` + +.. function:: box.schema.func.exists(func-name) + + Return true if a function tuple exists; return false if a function tuple does not exist. + + :param string func-name: the name of the function + :rtype: bool + + Example: |br| + :codenormal:`box.schema.func.exists('calculate')` + diff --git a/doc/sphinx/book/box/box_space.rst b/doc/sphinx/book/box/box_space.rst index 7e9eae971c5ba4d832eeb96707ff98e59ee82c8d..e4591008412d0cb4c65b482ab52e949b469e1454 100644 --- a/doc/sphinx/book/box/box_space.rst +++ b/doc/sphinx/book/box/box_space.rst @@ -84,9 +84,12 @@ A list of all ``box.space`` functions follows, then comes a list of all | | types | | | +---------------+--------------------+-----------------------------+---------------------+ - Possible errors: too many parts. A type option other than TREE, or a - unique option other than unique, or a parts option with more than one - field component, is only applicable for the memtx storage engine. + Possible errors: too many parts. + + Note re storage engine: sophia supports only the TREE index type, + and supports only one index per space, + and supports only the unique = true option, + and requires that field numbers be in order starting with 1. .. code-block:: tarantoolsession @@ -110,6 +113,8 @@ A list of all ``box.space`` functions follows, then comes a list of all Possible errors: If a tuple with the same unique-key value already exists, returns :errcode:`ER_TUPLE_FOUND`. + Note re storage engine: sophia will return nil, rather than the inserted tuple. + **Example:** .. code-block:: tarantoolsession @@ -284,6 +289,8 @@ A list of all ``box.space`` functions follows, then comes a list of all **Complexity Factors:** Index size, Index type, Number of indexes accessed, WAL settings. + Note re storage engine: sophia will return nil, rather than the inserted tuple. + **Example:** .. code-block:: lua @@ -338,6 +345,8 @@ A list of all ``box.space`` functions follows, then comes a list of all **Complexity Factors:** Index size, Index type, number of indexes accessed, WAL settings. + Note re storage engine: sophia will return nil, rather than the updated tuple. + Thus, in the instruction: .. code-block:: lua @@ -502,6 +511,8 @@ A list of all ``box.space`` functions follows, then comes a list of all **Complexity Factors:** Index size, Index type + Note re storage engine: sophia will return nil, rather than the deleted tuple. + **Example:** .. code-block:: tarantoolsession @@ -611,6 +622,8 @@ A list of all ``box.space`` functions follows, then comes a list of all - 2 ... + .. _space_truncate: + .. method:: truncate() Deletes all tuples. @@ -621,6 +634,8 @@ A list of all ``box.space`` functions follows, then comes a list of all :return: nil + Note re storage engine: sophia does not support :codenormal:`truncate`. + **Example:** .. code-block:: tarantoolsession @@ -714,12 +729,14 @@ A list of all ``box.space`` functions follows, then comes a list of all - 998 ... + .. _space_auto_increment: + .. method:: auto_increment{field-value [, field-value ...]} Insert a new tuple using an auto-increment primary key. The space specified by space_object must have a ``NUM`` primary key index of type ``TREE``. The primary-key field will be incremented before the insert. - This is only applicable for the memtx storage engine. + Note re storage engine: sophia does not support auto_increment. Parameters: :samp:`{space_object}` = an :ref:`object reference <object-reference>`; :codeitalic:`field-value(s)` (type = Lua table or scalar) = tuple's fields, other than the primary-key field. diff --git a/doc/sphinx/book/box/index.rst b/doc/sphinx/book/box/index.rst index a7092bf03a91e712d1089afad1becd467117d816..c4dde6d29ce399e834adf1ecb055a0bd23b6bdb8 100644 --- a/doc/sphinx/book/box/index.rst +++ b/doc/sphinx/book/box/index.rst @@ -296,6 +296,8 @@ all computer instructions until a yield, then switch to execute the instructions of a different fiber. Thus (say) the thread reads row#x for the sake of fiber#1, then writes row#y for the sake of fiber#2. +.. _yields_must_happen: + **FACT #3**: yields must happen, otherwise the transaction processor thread would stick permanently on the same fiber. There are implicit yields: every data-change operation @@ -321,6 +323,8 @@ the function holds a consistent view of the database until the UPDATE ends. For the combination “UPDATE plus SELECT†the view is not consistent, because after the UPDATE the transaction processor thread can switch to another fiber, and delete the tuple that was just updated. +Note re storage engine: sophia handles yields differently, see +:ref:`differences between memtx and sophia <sophia_diff>`. Since locks don't exist, and disk writes only involve the write-ahead log, transactions are usually fast. Also the Tarantool server may not be using @@ -581,9 +585,12 @@ The manual concentrates on memtx because it is the default and has been around longer. But sophia is a working key-value engine and will especially appeal to users who like to see data go directly to disk, so that recovery time might be shorter and database size might be larger. For architectural explanations and -benchmarks, see `sphia.org`_. On the other hand, sophia lacks some functions and +benchmarks, see `sphia.org`_ and Appendix E: :ref:`sophia <sophia>`. +On the other hand, sophia lacks some functions and options that are available with memtx. Where that is the case, the relevant -description will contain the words "only applicable for the memtx storage engine". +description will contain a note beginning with the words +"Note re storage engine: sophia". The end of this chapter has coverage +for all :ref:`the differeences between memtx and sophia <sophia_diff>`. .. _sphia.org: http://sphia.org @@ -603,5 +610,8 @@ description will contain the words "only applicable for the memtx storage engine admin atomic authentication - limitations triggers + limitations + sophia_diff + + diff --git a/doc/sphinx/book/box/limitations.rst b/doc/sphinx/book/box/limitations.rst index b6fdbceec0acf6df9be7a62e9e1d25d0a6c1481f..a4c7de9c2da62cf172840e33d2063876681dce12 100644 --- a/doc/sphinx/book/box/limitations.rst +++ b/doc/sphinx/book/box/limitations.rst @@ -4,11 +4,14 @@ .. _lim_fields_in_index: -**Number of fields in an index** +**Number of parts in an index** - For BITSET indexes, the maximum is 1. For TREE or HASH indexes, the maximum + For TREE or HASH indexes, the maximum is 255 (``box.schema.INDEX_PART_MAX``). For RTREE indexes, the maximum is 1 but the field is an ARRAY. + For BITSET indexes, the maximum is 1. + + Note re storage engine: sophia allows 8 parts in an index. .. _lim_indexes_in_space: @@ -77,14 +80,7 @@ .. _lim_sophia: -**Limitations which are only applicable for the sophia storage engine** - - The maximum number of indexes in a space is - always 1, that is, secondary indexes are not supported. Indexes must be - type=TREE, that is, the options type=HASH or type=RTREE or type=BITSET are - not supported. Indexes must be unique, that is, the option unique=false - is not supported. The ``alter()`` and ``count()`` and - ``min()`` and ``max()`` and ``random()`` and ``auto_increment()`` functions - are not supported. Temporary spaces are not supported. - The maximum number of fields in an index is 8. +For additional limitations which apply only to the sophia +storage engine, see section +:ref:`Differences between memtx and sophia <sophia_diff>`. diff --git a/doc/sphinx/book/box/sophia_diff.rst b/doc/sphinx/book/box/sophia_diff.rst new file mode 100644 index 0000000000000000000000000000000000000000..9bac36dd7f44230e8d542aee15c5dbd48fc0e4cb --- /dev/null +++ b/doc/sphinx/book/box/sophia_diff.rst @@ -0,0 +1,61 @@ +.. _sophia_diff: + +------------------------------------------------------------------------------- + Differences between memtx and sophia storage engines +------------------------------------------------------------------------------- + + The primary difference between memtx and sophia is that + memtx is an "in-memory" engine while sophia is an "on-disk" + engine. An in-memory storage engine is generally faster, + and the memtx engine is justifiably the default for Tarantool, + but there are two situations where an on-disk engine such as + sophia would be preferable: + (1) when the database is larger than the available memory and + adding more memory is not a realistic option; + (2) when the server frequently goes down due to errors + or a simple desire to save power -- bringing the server + back up and restoring a memtx database into memory takes time. + + Here are behavior differences which affect programmers. + All of these differences have been noted elsewhere in + sentences that begin with the words "Note re storage engine: sophia". + + With memtx, the maximum number of indexes per space is 10. |br| + With sophia, the maximum is 1, that is, only primary indexes are supported. + Since primary indexes are always unique, it follows that sophia indexes must be unique. + + With memtx, the maximum number of (TREE) index-key parts is 255. |br| + With sophia, the maximum is 8. + + With memtx, the index type can be TREE or HASH or RTREE or BITSET. |br| + With sophia, the only index type is TREE. + + With memtx, field numbers for index parts may be in any order. |br| + With sophia, they must be in order, with no gaps, starting with field number 1. + + With memtx, for index searches, ``nil`` is considered to be equal to any scalar key-part. |br| + With memtx, ``nil`` or missing parts are not allowed. + + With memtx, temporary spaces are supported. |br| + With sophia, they are not. + + With memtx, the :ref:`alter() <index_alter>` and :ref:`count() <index_count>` + and :ref:`min() <index_min>` and :ref:`max() <index_max>` and + :ref:`random() <index_random>` and :ref:`auto_increment() <space_auto_increment>` + and :ref:`truncate() <space_truncate>` functions are supported. |br| + With sophia, they are not. + + With memtx, insert and replace and update will return a tuple, if successful. |br| + With sophia, insert and replace and update will return nil. + + With memtx, the REQ (reverse equality) comparison-operator is supported. |br| + With sophia, it is not. + (This is a minor matter because on a unique index EQ and REQ do the same thing.) + + It was explained :ref:`earlier <yields_must_happen>` that memtx does not "yield" on a select request, + it yields only on data-change requests. However, sophia does yield on a select + request, or on an equivalent such as get() or pairs(). This has significance + for cooperative multitasking. + + For more about sophia, see Appendix E :ref:`sophia <sophia>`. +