Skip to content
Snippets Groups Projects
  1. Apr 13, 2020
    • Chris Sosnin's avatar
      box: provide a user friendly frontend for accessing session settings · 5ea94c51
      Chris Sosnin authored
      - space_object:update() is hard to use for configuring session settings,
      so we provide box.session.settings table, which can be used in a much more
      native way.
      
      - Prior to this patch sql settings were not accessible before box.cfg()
      call, even though these flags can be set right after session creation.
      
      Part of #4711
      5ea94c51
    • Serge Petrenko's avatar
      box: introduce indices by UUID · b238def8
      Serge Petrenko authored
      It is now possible to create an index over UUID values, returned by
      `uuid.new()`.
      
      Closes #4268
      Closes #2916
      
      @TarantoolBot document
      Title: Document uuid field type.
      
      There's a new field type -- UUID, it accepts values returned by
      `uuid.new()`.
      
      The index may be either unique or non-unique, nullable or non-nullable,
      and may be a primary key.
      
      The values in an index are ordered lexicographically by their string
      representation.
      
      To create an index over a uuid field for space `test`, say:
      ```
      box.space.test:create_index("pk", {parts={1, 'uuid'}})
      ```
      Now you may insert uuids into the space:
      ```
      tarantool> box.space.test:insert{uuid.new()}
      ---
      - [e631fdcc-0e8a-4d2f-83fd-b0ce6762b13f]
      ...
      
      tarantool> box.space.test:insert{uuid.fromstr('64d22e4d-ac92-4a23-899a-e59f34af5479')}
      ---
      - [64d22e4d-ac92-4a23-899a-e59f34af5479]
      ...
      
      tarantool> box.space.test:select{}
      ---
      - - [64d22e4d-ac92-4a23-899a-e59f34af5479]
        - [e631fdcc-0e8a-4d2f-83fd-b0ce6762b13f]
      ...
      
      ```
      b238def8
    • Serge Petrenko's avatar
      box: add MsgPack encoding/decoding for UUID · d68fc292
      Serge Petrenko authored
      A special format for encoding UUIDs to MsgPack is introduced.
      It is supported by both lua and C encoders/decoders, and it is now
      possible to insert UUIDs into spaces, but only into unindexed fields
      without format for now.
      
      Prerequisite #4268
      
      @TarantoolBot document
      Title: Internals: msgpack format for UUID
      
      UUID values share the MessagePack type with decimals:
      both use MP_EXT. A new subtype is introduced for UUIDs,
      MP_UUID = `0x02`
      UUID is encoded as follows:
      ```
          +--------+---------+-----------+
          | MP_EXT | MP_UUID | UuidValue |
          +--------+---------+-----------+
      ```
      Since UUID is 16 bytes in size, the header, MP_EXT, is always the same:
      `0xd8`. MP_UUID = `0x02` follows. The header is followed by the 16
      bytes of the UuidValue.
      
      UuidValue consists of 11 fields, which are encoded as big endian
      unsigned integers in the following order: `time_low` (4 bytes), `time_mid`
      (2 bytes), `time_hi_and_version` (2 bytes), `clock_seq_hi_and_reserved` (1
      byte), `clock_seq_low` (1 byte), `node[0], ..., node[5]` (1 byte each).
      
      The total size of such a representation is 18 bytes, whereas storing
      uuids as strings requires from 34 (when '-'s are ommitted) to 38 bytes
      per UUID, giving a 2x space usage improvement.
      d68fc292
  2. Apr 10, 2020
  3. Apr 08, 2020
  4. Apr 07, 2020
    • Nikita Pettik's avatar
      sql: reset values to be bound after execution · df03a7e8
      Nikita Pettik authored
      Before this patch prepared statements didn't reset bound values after
      its execution. As a result, if during next execution cycle not all
      parameters were provided, cached values would appear. For instance:
      
      prep = box.prepare('select :a, :b, :c')
      prep:execute({{[':a'] = 1}, {[':b'] = 2}, {[':c'] = 3}}
      -- [1, 2, 3]
      prep:execute({{[':a'] = 1}, {[':b'] = 2}})
      -- [1, 2, 3]
      
      However, expected result for the last query should be [1, 2, NULL].
      Let's fix it and always reset all binding values before next execution.
      
      Closes #4825
      df03a7e8
    • Nikita Pettik's avatar
      iproto: support error stacked diagnostic area · 4c465312
      Nikita Pettik authored
      This patch introduces support of stacked errors in IProto protocol and
      in net.box module.
      
      Closes #1148
      
      @TarantoolBot document
      Title: Stacked error diagnostic area
      
      Starting from now errors can be organized into lists. To achieve this
      Lua table representing error object is extended with .prev field and
      e:set_prev(err) method. .prev field returns previous error if any exist.
      e:set_prev(err) method expects err to be error object or nil and sets
      err as previous error of e. For instance:
      ```
      e1 = box.error.new({code = 111, reason = "cause"})
      e2 = box.error.new({code = 111, reason = "cause of cause"})
      
      e1:set_prev(e2)
      assert(e1.prev == e2) -- true
      ```
      Cycles are not allowed for error lists:
      ```
      e2:set_prev(e1)
      - error: 'builtin/error.lua: Cycles are not allowed'
      ```
      Nil is valid input to :set_prev() method:
      ```
      e1:set_prev(nil)
      assert(e1.prev == nil) -- true
      ```
      Note that error can be 'previous' only to the one error at once:
      ```
      e1:set_prev(e2)
      e3:set_prev(e2)
      assert(e1.prev == nil) -- true
      assert(e3.prev == e2) -- true
      ```
      Setting previous error does not erase its own previous members:
      ```
      -- e1 -> e2 -> e3 -> e4
      e1:set_prev(e2)
      e2:set_prev(e3)
      e3:set_prev(e4)
      e2:set_prev(e5)
      -- Now there are two lists: e1->e2->e5 and e3->e4
      assert(e1.prev == e2) -- true
      assert(e2.prev == e5) -- true
      assert(e3.prev == e4) -- true
      ```
      Alternatively:
      ```
      e1:set_prev(e2)
      e2:set_prev(e3)
      e3:set_prev(e4)
      e5:set_prev(e3)
      -- Now there are two lists: e1->e2 and e5->e3->e4
      assert(e1.prev == e2) -- true
      assert(e2.prev == nil) -- true
      assert(e5.prev == e3) -- true
      assert(e3.prev == e4) -- true
      ``
      Stacked diagnostics is also supported by IProto protocol. Now responses
      containing errors always (even if there's only one error to be returned)
      include new IProto key: IPROTO_ERROR_STACK (0x51). So, body corresponding to
      error response now looks like:
      ```
      MAP{IPROTO_ERROR : string, IPROTO_ERROR_STACK : ARRAY[MAP{ERROR_CODE : uint, ERROR_MESSAGE : string}, MAP{...}, ...]}
      ```
      where IPROTO_ERROR is 0x31 key, IPROTO_ERROR_STACK is 0x52, ERROR_CODE
      is 0x01 and ERROR_MESSAGE is 0x02.
      Instances of older versions (without support of stacked errors in
      protocol) simply ignore unknown keys and still rely only on IPROTO_ERROR
      key.
      4c465312
    • Nikita Pettik's avatar
      box: always promote error created via box.error() to diag · 4bcaf15e
      Nikita Pettik authored
      This patch makes box.error() always promote error to the diagnostic
      area despite of passed arguments.
      
      Closes #4829
      
      @TarantoolBot document
      Title: always promote error created via box.error() to diag
      
      box.error() is able to accept two types of argument: either pair of code
      and reason (box.error{code = 555, reason = 'Arbitrary message'}) or error
      object (box.error(err)). In the first case error is promoted to
      diagnostic area, meanwhile in the latter - it is not:
      ```
      e1 = box.error.new({code = 111, reason = "cause"})
      box.error({code = 111, reason = "err"})
      - error: err
      box.error.last()
      - err
      box.error(e1)
      - error: cause
      box.error.last()
      - err
      ```
      From now box.error(e1) sets error to diagnostic area as well:
      ```
      box.error(e1)
      - error: cause
      box.error.last()
      - cause
      ```
      4bcaf15e
    • Nikita Pettik's avatar
      box: use stacked diagnostic area for functional indexes · c15cef54
      Nikita Pettik authored
      Since we've introduced stacked diagnostic in previous commit, let's use
      it in the code implementing functional indexes.
      
      Part of #1148
      c15cef54
    • Nikita Pettik's avatar
      box: introduce stacked diagnostic area · 3b887d04
      Nikita Pettik authored
      In terms of implementation, now struct error objects can be organized
      into double-linked lists. To achieve this pointers to the next and
      previous elements (cause and effect correspondingly) have been added to
      struct error. It is worth mentioning that already existing rlist and
      stailq list implementations are not suitable: rlist is cycled list, as a
      result it is impossible to start iteration over the list from random
      list entry and finish it at the logical end of the list; stailq is
      single-linked list leaving no possibility to remove elements from the
      middle of the list.
      
      As a part of C interface, box_error_add() has been introduced. In
      contrast to box_error_set() it does not replace last raised error, but
      instead it adds error to the list of diagnostic errors having already
      been set. If error is to be deleted (its reference counter hits 0 value)
      it is unlinked from the list it belongs to and destroyed. Meanwhile,
      error destruction leads to decrement of reference counter of its
      previous error and so on.
      
      To organize errors into lists in Lua, table representing error object in
      Lua now has .prev field (corresponding to 'previous' error) and method
      :set_prev(e). The latter accepts error object (i.e. created via
      box.error.new() or box.error.last()) and nil value. Both field .prev and
      :set_prev() method are implemented as ffi functions. Also note that
      cycles are not allowed while organizing errors into lists:
      e1 -> e2 -> e3; e3:set_prev(e1) -- would lead to error.
      
      Part of #1148
      3b887d04
  5. Apr 02, 2020
    • Alexander V. Tikhonov's avatar
      gitlab-ci: add memory leaks detection via LSAN · e737400d
      Alexander V. Tikhonov authored
      The change enables memory leaks detection to existing ASAN testing
      routine and introduces suppression files with the corresponding
      exception list:
       * address sanitizer for compile-time: asan/asan.supp
       * memory leak sanitizer for run-time: asan/lsan.supp
      
      Furthermore, added engine and replication suites for ASAN testing
      routine.
      
      Additionally to the tests blacklisted within #4359,
      'box/on_shutdown.test.lua' is also disabled since it fails the
      introduced leak check. All blacklisted tests have to be enabled
      within #4360.
      
      Close #2058
      e737400d
    • Alexander V. Tikhonov's avatar
      test: use default replication connection timeout · fb892b7a
      Alexander V. Tikhonov authored
      All local connection timeout settings not related to the testing
      scenario are removed within this change. Instead of removed values
      the default one from src/box/lua/load_cfg.lua will be used.
      The approach with a single default value helps to avoid flaky test
      results regarding different timeout values and makes the future
      maintainence easier.
      
      The change is required for LSAN and ASAN testing machinery since it
      introduces a little overhead and cause failures for tests with
      excessively strict time limits.
      
      Needed for #2058
      fb892b7a
  6. Mar 27, 2020
    • Nikita Pettik's avatar
      box/error: don't set error created via box.error.new to diag · eaa86088
      Nikita Pettik authored
      To achieve this let's refactor luaT_error_create() to return error
      object instead of setting it via box_error_set().
      luaT_error_create() is used both to handle box.error() and
      box.error.new() invocations, and box.error() is still expected to set
      error to diagnostic area. So, luaT_error_call() which implements
      box.error() processing at the end calls diag_set_error().
      It is worth mentioning that net.box module relied on the fact that
      box.error.new() set error to diagnostic area: otherwise request errors
      don't get to diagnostic area on client side.
      
      Needed for #1148
      Closes #4778
      
      @TarantoolBot document
      Title: Don't promote error created via box.error.new to diagnostic area
      
      Now box.error.new() only creates error object, but doesn't set it to
      Tarantool's diagnostic area:
      ```
      box.error.clear()
      e = box.error.new({code = 111, reason = "cause"})
      assert(box.error.last() == nil)
      ---
      - true
      ...
      ```
      To set error in diagnostic area explicitly box.error.set() has been
      introduced. It accepts error object which is set as last system error
      (i.e. becomes available via box.error.last()).
      Finally, box.error.new() does not longer accept error object as an
      argument (this was undocumented feature).
      Note that patch does not affect box.error(), which still pushes error to
      diagnostic area. This fact is reflected in docs:
      '''
      Emulate a request error, with text based on one of the pre-defined
      Tarantool errors...
      '''
      eaa86088
  7. Mar 26, 2020
    • Vladislav Shpilevoy's avatar
      fio: close unused descriptors automatically · 3d5b4daa
      Vladislav Shpilevoy authored
      Fio.open() returned a file descriptor, which was not closed
      automatically after all its links were nullified. In other words,
      GC didn't close the descriptor.
      
      This was not really useful, because after fio.open() an exception
      may appear, and user needed to workaround this to manually call
      fio_object:close(). Also this was not consistent with io.open().
      
      Now fio.open() object closes the descriptor automatically when
      GCed.
      
      Closes #4727
      
      @TarantoolBot document
      Title: fio descriptor is closed automatically by GC
      
      fio.open() returns a descriptor which can be closed manually by
      calling :close() method, or it will be closed automatically, when
      it has no references, and GC deletes it.
      
      :close() method existed always, auto GC was added just now.
      
      Keep in mind, that the number of file descriptors is limited, and
      they can end earlier than GC will be triggered to collect not
      used descriptors. It is always better to close them manually as
      soon as possible.
      3d5b4daa
    • Vladislav Shpilevoy's avatar
      fiber: introduce schedule_task() internal function · 8443bd93
      Vladislav Shpilevoy authored
      fiber._internal.schedule_task() is an API for a singleton fiber
      worker object. It serves for not urgent delayed execution of
      functions. Main purpose - schedule execution of a function, which
      is going to yield, from a context, where a yield is not allowed.
      Such as an FFI object's GC callback.
      
      It will be used by SWIM and by fio, whose destruction yields, but
      they need to use GC finalizer, where a yield is not allowed.
      
      Part of #4727
      8443bd93
    • Nikita Pettik's avatar
      box/error: introduce box.error.set() method · f00945a1
      Nikita Pettik authored
      box.error.set(err) sets err to instance's diagnostics area. Argument err
      is supposed to be instance of error object. This method is required
      since we are going to avoid adding created via box.error.new() errors to
      Tarantool's diagnostic area.
      
      Needed for #1148
      Part of #4778
      f00945a1
    • Nikita Pettik's avatar
      test: move box.error tests to box/error.test.lua · 195d99d0
      Nikita Pettik authored
      We are going to introduce more tests related to error module, so let's
      move all error-related tests from box/misc.test.lua to a separate test
      file (box/error.test.lua).
      
      Needed for #1148
      195d99d0
    • Cyrill Gorcunov's avatar
      test: unit/popen -- provide a child process · 12086678
      Cyrill Gorcunov authored
      
      Testing via plain C interface with a shell is not stable,
      the shell might simply be misconfigured or not found and
      we will simply stuck forever (the signal handling in libev
      is tricky and requires at least idle cycles or similar to
      pass event processing). Thus lets rather run a program we
      know is presenting in the system (popen-child executable).
      
      Fixes #4811
      
      Signed-off-by: default avatarCyrill Gorcunov <gorcunov@gmail.com>
      12086678
  8. Mar 25, 2020
  9. Mar 20, 2020
    • Nikita Pettik's avatar
      vinyl: update mem ptr in vy_build_insert_tuple() after yield · 17f6af7d
      Nikita Pettik authored
      vy_build_insert_tuple() processes insertion into secondary indexes being
      created. It contains yield points during which in-memory level of LSM
      tree may change (for example rotate owing to triggered dump). So after
      yield point it is required to fetch from LSM struct pointer to mem again
      to operate on valid metadata. This patch updates pointer to mem after
      mentioned yield point.
      
      Closes #4810
      17f6af7d
    • Vladislav Shpilevoy's avatar
      box: on cfg properly check memory quota · 74cec5f5
      Vladislav Shpilevoy authored
      
      box_check_config() didn't check memtx_memory and vinyl_memory
      upper bound. As a result, it was possible to set memory size
      higher than what the quota allows as maximum.
      
      That worked only when box.cfg() was called first time, because
      quota_init() does not check its value. Subsequent box.cfg() calls
      use quota_set(), which aborts the program if a size is too big.
      Only in debug mode. In release quota_set() also worked with any
      sizes.
      
      Closes #4705
      
      Reviewed-by: default avatarIgor Munkin <imun@tarantool.org>
      Reviewed-by: default avatarNikita Pettik <korablev@tarantool.org>
      74cec5f5
    • Leonid Vasiliev's avatar
      Add some cancellation guard · 63d75e92
      Leonid Vasiliev authored
      We need to set a thread cancellation guard, because
      another thread may cancel the current thread at a
      really bad time (messages flush, mutex lock)
      
      Fixes: #4127
      63d75e92
    • Vladislav Shpilevoy's avatar
      fiber: extend max fiber name length to 255 · f4f886bd
      Vladislav Shpilevoy authored
      
      Users keep complaining about too short fiber name. New limit is
      255, should be enough for any sane name.
      
      Closes #4394
      
      Reviewed-by: default avatarCyrill Gorcunov <gorcunov@gmail.com>
      Reviewed-by: default avatarNikita Pettik <korablev@tarantool.org>
      
      @TarantoolBot document
      Title: fiber.name length limit.
      
      It was 32, now it is 255. Besides, it seems like `fiber.name`
      `{truncate = true}` option is not documented.
      
      By default, if a new name is too long, `fiber.name(new_name)`
      fails with an exception. To make it always succeed there is an
      option 'truncate': `fiber.name(new_name, {truncate = true})`. It
      truncates the name to the max length if it is too long.
      f4f886bd
  10. Mar 19, 2020
    • Vladislav Shpilevoy's avatar
      iproto: show real port in logs and box.info.listen · 2c3acf2b
      Vladislav Shpilevoy authored
      Box.cfg{listen = 0} automatically chooses a port. But it was
      impossible to obtain a real port the instance is bound to.
      
      An ability to see a real port may help to make test-run more
      robust, because it won't depend on which ports are free, and
      won't need to pre-choose them in advance.
      
      Now box.info.listen shows a real address, or nil when listen is
      turned off. Also a real address is logged instead of the dummy
      0-port one.
      
      Closes #4620
      
      @TarantoolBot document
      Title: box.info.listen - real address
      
      New value in box.info - listen. It is a real address to which the
      instance was bound. For example, if box.cfg.listen was set with
      a zero port, box.info.listen will show a real port. The address
      is stored as a string:
      
          - unix/:<path> for UNIX domain sockets;
          - <ip>:<port> for IPv4;
          - [ip]:<port> for IPv6.
      
      If the instance does not listen anything, box.info.listen is nil.
      2c3acf2b
  11. Mar 18, 2020
    • Oleg Babin's avatar
      box: allow to retrieve the last generated value of sequence · 64c69fe0
      Oleg Babin authored
      
      This patch introduces "current" function for sequences.
      It returns the last retrieved value of specified sequence or
      throws an error if no value has been generated yet.
      
      This patch partially reverts 3ff1f1e3
      (box: remove sequence_get) here similar function "get" was removed
      to avoid possible misleading with "currval" function of PosgreSQL
      that returns the last obtained value of the sequence in the scope
      of current session. In contrast "current" returns the last globally
      retrieved value of the sequence.
      
      Closes #4752
      
      Reviewed-by: default avatarVladislav Shpilevoy <v.shpilevoy@tarantool.org>
      Reviewed-by: default avatarNikita Pettik <korablev@tarantool.org>
      
      @TarantoolBot document
      Title: sequence:current()
      
      This patch introduces "current" function for sequences.
      It returns the last retrieved value of specified sequence or
      throws an error if no value has been generated yet ("next"
      has not been called yet or right after "reset" is called).
      
      Lua:
      
      Example:
      
      ```lua
      sq = box.schema.sequence.create('test')
      ---
      ...
      sq:current()
      ---
      - error: Sequence 'test' is not started
      ...
      sq:next()
      ---
      - 1
      ...
      sq:current()
      ---
      - 1
      ...
      sq:set(42)
      ---
      ...
      sq:current()
      ---
      - 42
      ...
      sq:reset()
      ---
      ...
      sq:current()  -- error
      ---
      - error: Sequence 'test' is not started
      ...
      ```
      
      C API:
      
      ```C
      int
      box_sequence_current(uint32_t seq_id, int64_t *result);
      ```
      
      Where:
        * seq_id - sequence identifier;
        * result - pointer to a variable where the current sequence
        value will be stored on success.
      
      Returns 0 on success and -1 otherwise. In case of an error user
      could get it via `box_error_last()`.
      64c69fe0
  12. Mar 17, 2020
  13. Mar 16, 2020
  14. Mar 10, 2020
    • Olga Arkhangelskaia's avatar
      memtx: fix out of memory handling for rtree · 3b4fbdc0
      Olga Arkhangelskaia authored
      When tarantool tries to recover rtree from a snapshot and memtx_memory value
      is lower than it has been when the snapshot was created, server suffers from
      segmentation fault. This happens because there is no out of memory error
      handling in rtree lib. In another words, we do not check the result of
      malloc operation.
      The execution flow in case of recovery uses different way and the secondary
      keys are build in batches. That way has no checks and reservations.
      The patch adds memtx_rtree_index_reserve implementation to make sure that any
      memory allocation in rtree will fail. Although this gives us no additional
      optimization as in case of memtx_tree, the memory reservation prevents
      tarantool from segmentation fault. If there is not enough memory to be reserved
      server will fail gently with the "Failed to allocate" error message.
      
      Closes #4619
      3b4fbdc0
  15. Mar 08, 2020
    • Maria's avatar
      box: netbox.self and connect should work interchangeably · 0bcf9a59
      Maria authored
      Despite what was stated in the documentation, netbox.connect was not always
      equivalent to netbox.self. In particular, they converted tuple to different
      types - table and cdata respectively.
      
      The patch fixes the issue and covers all cases where netbox.self and connect
      perform conversion of types - e.g., for box.error.
      
      Closes #4513
      0bcf9a59
  16. Mar 06, 2020
    • Vladislav Shpilevoy's avatar
      test: fix fio.test.lua flakiness · d8a9f1d9
      Vladislav Shpilevoy authored
      In 89c73e64 ("fio: respect
      $TMPDIR in fio.tempdir(), when it is set") was added a test
      checking that fio.tempdir() returns a path to a folder, stored
      by a path specified in $TMPDIR environment variable.
      
      Check was done by calling Lua returned_path:find(tmpdir_path).
      If tmpdir path contained 'special' characters such as '.', it
      didn't match, because string.find() takes a regular expression,
      not just a string.
      
      string.startswith() works fine.
      
      Follow-up #4794
      d8a9f1d9
    • Maria's avatar
      Hotfix for b0f588f6: don't account :execute() call twice · c05f5d4a
      Maria authored
      The patch fixes a bug for the commit b0f588f6 where statistics on
      box.execute was collected twice. This happened because
      sql_prepare_and_execute called sql_execute under the hood, so there's
      no need to do rmean_collect in both of them.
      
      Follow-up #4756
      c05f5d4a
  17. Mar 05, 2020
    • Vladislav Shpilevoy's avatar
      fio: respect $TMPDIR in fio.tempdir(), when it is set · 89c73e64
      Vladislav Shpilevoy authored
      TMPDIR is an environment variable used to tell what a directory
      should be used to create temporary files. It is described in the
      POSIX standard, and should be used by programs creating temporary
      files.
      
      Closes #4794
      
      @TarantoolBot document
      Title: fio.tempdir() $TMPDIR
      
      fio.tempdir() stores created temporary directory into /tmp by
      default. This can be changed by setting TMPDIR environment
      variable. Before starting Tarantool, or at runtime by
      os.setenv().
      89c73e64
    • Maria's avatar
      box: replication shouldn't leak user password · a806549d
      Maria authored
      It was possible to leak user password through setting 'replication'
      configuration option in first box.cfg invocation. This happened due
      to unconditional logging in load_cfg function. The patch introduces
      conditional logging.
      
      Closes #4493
      a806549d
  18. Mar 04, 2020
    • Roman Khabibov's avatar
      sql: support constraint drop · 85adac03
      Roman Khabibov authored
      Extend <ALTER TABLE> statement to drop table constraints by their
      names.
      
      Closes #4120
      
      @TarantoolBot document
      Title: Drop table constraints in SQL
      Now, it is possible to drop table constraints (PRIMARY KEY,
      UNIQUE, FOREIGN KEY, CHECK) using
      <ALTER TABLE table_name DROP CONSTRAINT constraint_name> statement
      by their names.
      
      For example:
      
      tarantool> box.execute([[CREATE TABLE test (
                                   a INTEGER PRIMARY KEY,
                                   b INTEGER,
                                   CONSTRAINT cnstr CHECK (a >= 0)
                              );]])
      ---
      - row_count: 1
      ...
      
      tarantool> box.execute('ALTER TABLE test DROP CONSTRAINT cnstr;')
      ---
      - row_count: 1
      ...
      
      The same for all the other constraints.
      85adac03
    • Roman Khabibov's avatar
      sql: improve "no such constraint" error message · 7d558ae8
      Roman Khabibov authored
      Clarify the error message for better user handling. Add the name
      of space where the constraint under dropping wasn't founded.
      
      Part of #4120
      7d558ae8
Loading