From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from localhost (localhost [127.0.0.1]) by turing.freelists.org (Avenir Technologies Mail Multiplex) with ESMTP id 948F62C3CC for ; Wed, 4 Apr 2018 14:11:33 -0400 (EDT) Received: from turing.freelists.org ([127.0.0.1]) by localhost (turing.freelists.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 8w7vvd9gae92 for ; Wed, 4 Apr 2018 14:11:33 -0400 (EDT) Received: from smtp59.i.mail.ru (smtp59.i.mail.ru [217.69.128.39]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by turing.freelists.org (Avenir Technologies Mail Multiplex) with ESMTPS id 04DC02C12B for ; Wed, 4 Apr 2018 14:11:32 -0400 (EDT) From: "n.pettik" Message-Id: <24260C14-041C-4F08-AC1B-B3F6ABBBA679@tarantool.org> Content-Type: multipart/alternative; boundary="Apple-Mail=_7C4A95CC-3ABE-467D-846B-1A6A54C7436C" Mime-Version: 1.0 (Mac OS X Mail 10.3 \(3273\)) Subject: [tarantool-patches] Re: [PATCH 2/2] sql: rework 'DROP INDEX' and 'DROP TABLE' handling Date: Wed, 4 Apr 2018 21:11:29 +0300 In-Reply-To: <69bcb5b2-34b5-5c64-31b3-016d9a699348@tarantool.org> References: <2bccf40f38d3e3e3d2182c6c8111050770d69821.1522769126.git.korablev@tarantool.org> <69bcb5b2-34b5-5c64-31b3-016d9a699348@tarantool.org> Sender: tarantool-patches-bounce@freelists.org Errors-to: tarantool-patches-bounce@freelists.org Reply-To: tarantool-patches@freelists.org List-help: List-unsubscribe: List-software: Ecartis version 1.0.0 List-Id: tarantool-patches List-subscribe: List-owner: List-post: List-archive: To: Vladislav Shpilevoy Cc: tarantool-patches@freelists.org --Apple-Mail=_7C4A95CC-3ABE-467D-846B-1A6A54C7436C Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=utf-8 > On 3 Apr 2018, at 21:27, Vladislav Shpilevoy = wrote: >=20 > See 6 comments below. >=20 > 03.04.2018 19:14, Nikita Pettik =D0=BF=D0=B8=D1=88=D0=B5=D1=82: >> As a part of SQL data dictionary integration, 'DROP INDEX' and >> 'DROP TABLE' statements proccessing has been refactored in order >> to avoid using SQL specific internal structures. >> However, triggers still aren't transfered to server, so to drop them >> it is required to lookup SQL table and emit apporpriate opcodes. >> Also, added comments and fixed codestyle for functions processing >> 'DROP' routine. >>=20 >> Part of #3222. >> --- >> src/box/sql/build.c | 241 = ++++++++++++++++++++++++++---------------------- >> src/box/sql/parse.c | 6 +- >> src/box/sql/parse.y | 6 +- >> src/box/sql/sqliteInt.h | 6 +- >> 4 files changed, 140 insertions(+), 119 deletions(-) >>=20 >> diff --git a/src/box/sql/build.c b/src/box/sql/build.c >> index 61194e06b..219cc974b 100644 >> --- a/src/box/sql/build.c >> +++ b/src/box/sql/build.c >> @@ -46,6 +46,7 @@ >> #include "sqliteInt.h" >> #include "vdbeInt.h" >> #include "tarantoolInt.h" >> +#include "box/box.h" >> #include "box/sequence.h" >> #include "box/session.h" >> #include "box/identifier.h" >> @@ -2152,48 +2153,50 @@ sql_clear_stat_spaces(Parse * pParse, const = char *zType, const char *zName) >> zType, zName); >> } >> -/* >> +/** >> * Generate code to drop a table. >> + * This routine includes dropping triggers, sequences, >> + * all indexes and entry from _space space. >> + * >> + * @param parse_context Current parsing context. >> + * @param space Space to be dropped. >> + * @param is_view True, if space is >> */ >> static void >> -sqlite3CodeDropTable(Parse * pParse, Table * pTab, int isView) >> +sql_code_drop_table(struct Parse *parse_context, struct space = *space, >> + bool is_view) >> { >> - Vdbe *v; >> - sqlite3 *db =3D pParse->db; >> - Trigger *pTrigger; >> - >> - v =3D sqlite3GetVdbe(pParse); >>=20 >> + struct sqlite3 *db =3D parse_context->db; >> + struct Vdbe *v =3D sqlite3GetVdbe(parse_context); >> assert(v !=3D 0); > 1. Lets in all new code use explicit =3D=3D/!=3D NULL. Fixed: - assert(v !=3D 0); + assert(v !=3D NULL); >> /* >> * Drop all triggers associated with the table being >> * dropped. Code is generated to remove entries from >> * _trigger. OP_DropTrigger will remove it from internal >> * SQL structures. >> - */ >> - pTrigger =3D pTab->pTrigger; >> - /* Do not account triggers deletion - they will be accounted >> + * >> + * Do not account triggers deletion - they will be accounted > 2. Out of 66. Fixed: - * Do not account triggers deletion - they will be accounted - * in DELETE from _space below. + * Do not account triggers deletion - they will be + * accounted in DELETE from _space below. >> @@ -2214,7 +2216,7 @@ sqlite3CodeDropTable(Parse * pParse, Table * = pTab, int isView) >> * Drop all _space and _index entries that refer to the >> * table. >> */ >> - if (!isView) { >> + if (!is_view) { > 3. I looked at the indexes deletion more carefully and noticed, that = you can avoid any allocations > here. Why can not you just walk through space->index array and = generate OP_SDelete opcodes for > each index, starting from 1 (to skip primary)? AFAIK the entire index = array is not changed until you > reach VdbeExec, so you can do not save index identifiers on region to = generate opcodes. IDK why I didn=E2=80=99t do it in this way (probably due to my = =E2=80=98paranoia=E2=80=99). Reworked: - uint32_t *iids =3D - (uint32_t *) region_alloc(&fiber()->gc, - = sizeof(uint32_t) * - (index_count - = 1)); - /* Save index ids to be deleted except for PK. = */ for (uint32_t i =3D 1; i < index_count; ++i) { - iids[i - 1] =3D = space->index[i]->def->iid; - } - for (uint32_t i =3D 0; i < index_count - 1; ++i) = { - sqlite3VdbeAddOp2(v, OP_Integer, = iids[i], + sqlite3VdbeAddOp2(v, OP_Integer, + = space->index[i]->def->iid, space_id_reg + 1); sqlite3VdbeAddOp3(v, OP_MakeRecord, space_id_reg, 2, = idx_rec_reg); @@ -2233,7 +2226,7 @@ sql_code_drop_table(struct Parse *parse_context, = struct space *space, idx_rec_reg); VdbeComment((v, "Remove secondary index iid = =3D %u", - iids[i])); + = space->index[i]->def->iid)); >> uint32_t index_count =3D space->index_count; >> if (index_count > 1) { >> /* >> @@ -2257,71 +2259,78 @@ sqlite3CodeDropTable(Parse * pParse, Table * = pTab, int isView) >> sqlite3VdbeAddOp2(v, OP_SDelete, BOX_SPACE_ID, idx_rec_reg); >> sqlite3VdbeChangeP5(v, OPFLAG_NCHANGE); >> VdbeComment((v, "Delete entry from _space")); >> - /* Remove the table entry from SQLite's internal schema and = modify >> - * the schema cookie. >> + /* >> + * Remove the table entry from SQLite's internal schema >> + * and modify the schema cookie. >> */ > 4. But you have deleted cookie updates in the previous commit. Source = code of OP_DropTable and all > called there functions does not contain cookie changes. Removed obsolete comment: - /* - * Remove the table entry from SQLite's internal schema - * and modify the schema cookie. - */ + /* Remove the table entry from SQLite's internal schema. */ >> + sqlite3VdbeAddOp4(v, OP_DropTable, 0, 0, 0, space->def->name, = 0); >> - sqlite3VdbeAddOp4(v, OP_DropTable, 0, 0, 0, pTab->zName, 0); >> - >> - /* FIXME: DDL is impossible inside a transaction so far. >> + /* >> * Replace to _space/_index will fail if active >> * transaction. So, don't pretend, that we are able to >> * anything back. To be fixed when transactions >> * DDL are enabled. >> */ >> - /* sqlite3ChangeCookie(pParse); */ >> sqliteViewResetAll(db); >> } >> -/* >> +/** >> * This routine is called to do the work of a DROP TABLE statement. >> - * pName is the name of the table to be dropped. >> + * >> + * @param parse_context Current parsing context. >> + * @param table_name_list List containing table name. >> + * @param is_view True, if statement is really 'DROP VIEW'. >> + * @param if_exists True, if statement contains 'IF EXISTS' clause. >> */ >> void >> -sqlite3DropTable(Parse * pParse, SrcList * pName, int isView, int = noErr) >> +sql_drop_table(struct Parse *parse_context, struct SrcList = *table_name_list, >> + bool is_view, bool if_exists) >> { >> - Table *pTab; >> - Vdbe *v =3D sqlite3GetVdbe(pParse); >> - sqlite3 *db =3D pParse->db; >> - >> + struct Vdbe *v =3D sqlite3GetVdbe(parse_context); >> + struct sqlite3 *db =3D parse_context->db; >> if (v =3D=3D NULL || db->mallocFailed) { >> goto exit_drop_table; >> } >> - /* Activate changes counting here to account >> + /* >> + * Activate changes counting here to account >> * DROP TABLE IF NOT EXISTS, if the table really does not >> * exist. >> */ >> - if (!pParse->nested) >> + if (!parse_context->nested) > 5. Please, use explicit !=3D 0. Why you use !int, the variable seems = to be boolean. It slightly confuses. This this not !=3D check, but vice versa =3D=3D 0 check. ! In this case would better fit, wouldn=E2=80=99t it? (Since any number except for 0 would be converted to false) >> sqlite3VdbeCountChanges(v); >> - assert(pParse->nErr =3D=3D 0); >> - assert(pName->nSrc =3D=3D 1); >> - assert(db->pSchema !=3D NULL); >> - if (noErr) >> - db->suppressErr++; >> - assert(isView =3D=3D 0 || isView =3D=3D LOCATE_VIEW); >> - pTab =3D sqlite3LocateTable(pParse, isView, pName->a[0].zName); >> - if (noErr) >> - db->suppressErr--; >> - >> - if (pTab =3D=3D 0) >> + assert(parse_context->nErr =3D=3D 0); >> + assert(table_name_list->nSrc =3D=3D 1); >> + assert(is_view =3D=3D 0 || is_view =3D=3D LOCATE_VIEW); >> + const char *space_name =3D table_name_list->a[0].zName; >> + uint32_t space_id =3D box_space_id_by_name(space_name, >> + strlen(space_name)); >> + if (space_id =3D=3D BOX_ID_NIL) { >> + if (!is_view && !if_exists) >> + sqlite3ErrorMsg(parse_context, "no such table: = %s", >> + space_name); >> + if (is_view && !if_exists) >> + sqlite3ErrorMsg(parse_context, "no such view: = %s", >> + space_name); >> goto exit_drop_table; >> -#ifndef SQLITE_OMIT_VIEW >> - /* Ensure DROP TABLE is not used on a view, and DROP VIEW is not = used >> - * on a table. >> + } >> + struct space *space =3D space_by_id(space_id); >> + assert(space !=3D NULL); >> + /* >> + * Ensure DROP TABLE is not used on a view, >> + * and DROP VIEW is not used on a table. >> */ >> - if (isView && !space_is_view(pTab)) { >> - sqlite3ErrorMsg(pParse, "use DROP TABLE to delete table = %s", >> - pTab->zName); >> + if (is_view && !space->def->opts.is_view) { >> + sqlite3ErrorMsg(parse_context, "use DROP TABLE to delete = table %s", >> + space_name); >> goto exit_drop_table; >> } >> - if (!isView && space_is_view(pTab)) { >> - sqlite3ErrorMsg(pParse, "use DROP VIEW to delete view = %s", >> - pTab->zName); >> + if (!is_view && space->def->opts.is_view) { >> + sqlite3ErrorMsg(parse_context, "use DROP VIEW to delete = view %s", >> + space_name); >> goto exit_drop_table; >> } >> -#endif >> - >> - /* Generate code to remove the table from Tarantool and internal = SQL >> + /* >> + * Generate code to remove the table from Tarantool and internal = SQL > 6. Out of 66. Fixed whole comment (to fit into 66 chars): - * Generate code to remove the table from Tarantool and internal = SQL - * tables. Basically, it consists from 3 stages: - * 1. Delete statistics from _stat1 and _stat4 tables (if any = exist) - * 2. In case of presence of FK constraints, i.e. current table = is child - * or parent, then start new transaction and erase from table - * all data row by row. On each deletion check whether any FK - * violations have occurred. If ones take place, then = rollback - * transaction and halt VDBE. Otherwise, commit transaction. - * 3. Drop table by truncating (if step 2 was skipped), removing - * indexes from _index table and eventually tuple with = corresponding - * space_id from _space. + * Generate code to remove the table from Tarantool + * and internal SQL tables. Basically, it consists + * from 3 stages: + * 1. Delete statistics from _stat1 and _stat4 tables. + * 2. In case of presence of FK constraints, i.e. current + * table is child or parent, then start new transaction + * and erase from table all data row by row. On each + * deletion check whether any FK violations have + * occurred. If ones take place, then rollback + * transaction and halt VDBE. + * 3. Drop table by truncating (if step 2 was skipped), + * removing indexes from _index space and eventually + * tuple with corresponding space_id from _space. */ --Apple-Mail=_7C4A95CC-3ABE-467D-846B-1A6A54C7436C Content-Transfer-Encoding: quoted-printable Content-Type: text/html; charset=utf-8
On 3 Apr 2018, at 21:27, Vladislav Shpilevoy <v.shpilevoy@tarantool.org> wrote:

See 6 comments below.
03.04.2018 19:14, Nikita Pettik = =D0=BF=D0=B8=D1=88=D0=B5=D1=82:
As a part of SQL data = dictionary integration, 'DROP INDEX' and
'DROP TABLE' = statements proccessing has been refactored in order
to = avoid using SQL specific internal structures.
However, = triggers still aren't transfered to server, so to drop them
it is required to lookup SQL table and emit apporpriate = opcodes.
Also, added comments and fixed codestyle for = functions processing
'DROP' routine.

Part of #3222.
---
 src/box/sql/build.c     | 241 = ++++++++++++++++++++++++++----------------------
 src/box/sql/parse.c     | =   6 +-
 src/box/sql/parse.y =     |   6 +-
 src/box/sql/sqliteInt.h |   6 +-
 4 files changed, 140 insertions(+), 119 deletions(-)

diff --git a/src/box/sql/build.c = b/src/box/sql/build.c
index 61194e06b..219cc974b 100644
--- a/src/box/sql/build.c
+++ = b/src/box/sql/build.c
@@ -46,6 +46,7 @@
 #include "sqliteInt.h"
 #include = "vdbeInt.h"
 #include "tarantoolInt.h"
+#include "box/box.h"
 #include = "box/sequence.h"
 #include "box/session.h"
 #include "box/identifier.h"
@@ -2152,48 = +2153,50 @@ sql_clear_stat_spaces(Parse * pParse, const char *zType, = const char *zName)
     zType, = zName);
 }
 -/*
+/**
  * Generate code to drop a = table.
+ * This routine includes dropping triggers, = sequences,
+ * all indexes and entry from _space space.
+ *
+ * @param parse_context Current parsing = context.
+ * @param space Space to be dropped.
+ * @param is_view True, if space is
  */
 static void
-sqlite3CodeDropTable(Parse * pParse, Table * pTab, int = isView)
+sql_code_drop_table(struct Parse *parse_context, = struct space *space,
+     bool = is_view)
 {
- Vdbe = *v;
- sqlite3 *db =3D pParse->db;
- Trigger = *pTrigger;
-
- v =3D sqlite3GetVdbe(pParse);

+ struct sqlite3 *db =3D = parse_context->db;
+ struct Vdbe *v =3D = sqlite3GetVdbe(parse_context);
  assert(v = !=3D 0);
1. Lets in all new code use explicit = =3D=3D/!=3D NULL.

Fixed:
-       assert(v !=3D = 0);
+       assert(v !=3D = NULL);

  /*
   * Drop = all triggers associated with the table being
   * dropped. Code is = generated to remove entries from
   * _trigger. OP_DropTrigger = will remove it from internal
   * SQL structures.
- =  */
- = pTrigger =3D pTab->pTrigger;
- /* Do not = account triggers deletion - they will be accounted
+  *
+  * Do not account triggers = deletion - they will be accounted
2. Out of 66.

Fixed:
-       =  * Do not account triggers deletion - they will be = accounted
-        * in DELETE from _space = below.
+        * Do not account triggers = deletion - they will be
+        * = accounted in DELETE from _space below.

@@ -2214,7 +2216,7 @@ = sqlite3CodeDropTable(Parse * pParse, Table * pTab, int isView)
   * Drop = all _space and _index entries that refer to the
   * table.
   */
- = if (!isView) {
+ if (!is_view) {
3. I looked at the indexes deletion more = carefully and noticed, that you can avoid any allocations
here. Why can not you just walk through = space->index array and generate OP_SDelete opcodes for
each index, starting from 1 (to skip primary)? = AFAIK the entire index array is not changed until you
reach VdbeExec, so you can do not save index = identifiers on region to generate opcodes.

IDK why I = didn=E2=80=99t do it in this way (probably due to my = =E2=80=98paranoia=E2=80=99).
Reworked:

-             =           uint32_t *iids =3D
-   =                     =         (uint32_t *) = region_alloc(&fiber()->gc,
-       =                     =                     =           sizeof(uint32_t) *
-   =                     =                     =               (index_count - = 1));
-                 =       /* Save index ids to be deleted except for PK. = */
                =         for (uint32_t i =3D 1; i < index_count; = ++i) {
-               =                 iids[i - 1] =3D = space->index[i]->def->iid;
-       =                 }
- =                     =   for (uint32_t i =3D 0; i < index_count - 1; ++i) {
- =                     =           sqlite3VdbeAddOp2(v, OP_Integer, = iids[i],
+               =                 = sqlite3VdbeAddOp2(v, OP_Integer,
+         =                     =                     = space->index[i]->def->iid,
      =                     =                     =     space_id_reg + 1);
        =                     =     sqlite3VdbeAddOp3(v, OP_MakeRecord,
  =                     =                     =         space_id_reg, 2, idx_rec_reg);
@@ = -2233,7 +2226,7 @@ sql_code_drop_table(struct Parse *parse_context, = struct space *space,
            =                     =                   = idx_rec_reg);
              =                   = VdbeComment((v,
            =                     =              "Remove secondary index = iid =3D %u",
-             =                     =            iids[i]));
+   =                     =                     =  space->index[i]->def->iid));

  uint32_t = index_count =3D space->index_count;
  if = (index_count > 1) {
  /*
@@ -2257,71 = +2259,78 @@ sqlite3CodeDropTable(Parse * pParse, Table * pTab, int = isView)
  sqlite3VdbeAddOp2(v, OP_SDelete, = BOX_SPACE_ID, idx_rec_reg);
  = sqlite3VdbeChangeP5(v, OPFLAG_NCHANGE);
  = VdbeComment((v, "Delete entry from _space"));
- /* Remove = the table entry from SQLite's internal schema and modify
- =  * the schema = cookie.
+ /*
+  * Remove the table entry = from SQLite's internal schema
+  * and modify the schema = cookie.
   */
4. But you have deleted cookie updates in = the previous commit. Source code of OP_DropTable and all
called there functions does not contain cookie = changes.

Removed obsolete comment:

-       /*
-   =      * Remove the table entry from SQLite's internal = schema
-        * and modify the schema = cookie.
-        */
+   =     /* Remove the table entry from SQLite's internal schema. = */

+ = sqlite3VdbeAddOp4(v, OP_DropTable, 0, 0, 0, = space->def->name, 0);
 - = sqlite3VdbeAddOp4(v, OP_DropTable, 0, 0, 0, pTab->zName, = 0);
-
- /* FIXME: DDL is impossible = inside a transaction so far.
+ /*
   * Replace to _space/_index = will fail if active
   * transaction. So, don't = pretend, that we are able to
   * anything back. To be = fixed when transactions
   * DDL are enabled.
   */
- = /* sqlite3ChangeCookie(pParse); */
  = sqliteViewResetAll(db);
 }
 -/*
+/**
  * This = routine is called to do the work of a DROP TABLE statement.
- * pName is the name of the table to be dropped.
+ *
+ * @param parse_context Current parsing = context.
+ * @param table_name_list List containing table = name.
+ * @param is_view True, if statement is really = 'DROP VIEW'.
+ * @param if_exists True, if statement = contains 'IF EXISTS' clause.
  */
 void
-sqlite3DropTable(Parse * pParse, = SrcList * pName, int isView, int noErr)
+sql_drop_table(struct Parse *parse_context, struct SrcList = *table_name_list,
+       = ; bool is_view, bool if_exists)
 {
- = Table *pTab;
- Vdbe *v =3D = sqlite3GetVdbe(pParse);
- sqlite3 *db =3D pParse->db;
-
+ struct Vdbe *v =3D = sqlite3GetVdbe(parse_context);
+ struct = sqlite3 *db =3D parse_context->db;
  if (v =3D=3D= NULL || db->mallocFailed) {
  goto = exit_drop_table;
  }
- /* = Activate changes counting here to account
+ /*
+ =  * Activate = changes counting here to account
   * DROP TABLE IF NOT EXISTS, = if the table really does not
   * exist.
   */
- = if (!pParse->nested)
+ if = (!parse_context->nested)
5. Please, use explicit !=3D 0. = Why you use !int, the variable seems to be boolean. It slightly = confuses.

This this not !=3D check, but vice versa =3D=3D 0 = check.
! In this case would better fit, wouldn=E2=80=99t = it?
(Since any number except for 0 would be converted to = false)

  = sqlite3VdbeCountChanges(v);
- = assert(pParse->nErr =3D=3D 0);
- = assert(pName->nSrc =3D=3D 1);
- = assert(db->pSchema !=3D NULL);
- if = (noErr)
- db->suppressErr++;
- = assert(isView =3D=3D 0 || isView =3D=3D LOCATE_VIEW);
- = pTab =3D sqlite3LocateTable(pParse, isView, = pName->a[0].zName);
- if (noErr)
- = db->suppressErr--;
-
- if (pTab = =3D=3D 0)
+ assert(parse_context->nErr =3D=3D= 0);
+ assert(table_name_list->nSrc =3D=3D 1);
+ = assert(is_view =3D=3D 0 || is_view =3D=3D LOCATE_VIEW);
+ = const char *space_name =3D table_name_list->a[0].zName;
+ = uint32_t space_id =3D box_space_id_by_name(space_name,
+ = = = = = =  strlen(space_name));
+ = if (space_id =3D=3D BOX_ID_NIL) {
+ if = (!is_view && !if_exists)
+ = sqlite3ErrorMsg(parse_context, "no such table: %s",
+ = = = = = space_name);
+ if (is_view && = !if_exists)
+ sqlite3ErrorMsg(parse_context, = "no such view: %s",
+ space_name);
  goto exit_drop_table;
-#ifndef = SQLITE_OMIT_VIEW
- /* Ensure DROP TABLE is not used = on a view, and DROP VIEW is not used
-  * on a table.
+ = }
+ struct space *space =3D = space_by_id(space_id);
+ assert(space !=3D NULL);
+ = /*
+  * Ensure DROP TABLE is not = used on a view,
+  * and DROP VIEW is not used = on a table.
   */
- if = (isView && !space_is_view(pTab)) {
- = sqlite3ErrorMsg(pParse, "use DROP TABLE to delete table %s",
- = = = = pTab->zName);
+ if (is_view && = !space->def->opts.is_view) {
+ = sqlite3ErrorMsg(parse_context, "use DROP TABLE to delete table = %s",
+ space_name);
  goto = exit_drop_table;
  }
- if = (!isView && space_is_view(pTab)) {
- = sqlite3ErrorMsg(pParse, "use DROP VIEW to delete view %s",
- = = = = pTab->zName);
+ if (!is_view && = space->def->opts.is_view) {
+ = sqlite3ErrorMsg(parse_context, "use DROP VIEW to delete view = %s",
+ space_name);
  goto = exit_drop_table;
  }
-#endif
-
- /* Generate code to remove the = table from Tarantool and internal SQL
+ /*
+ =  * Generate = code to remove the table from Tarantool and internal SQL
6. Out of = 66.

Fixed whole = comment (to fit into 66 chars):

-=        * Generate code to remove the table from = Tarantool and internal SQL
-        * = tables. Basically, it consists from 3 stages:
-     =    * 1. Delete statistics from _stat1 and _stat4 tables (if = any exist)
-        * 2. In case of = presence of FK constraints, i.e. current table is child
- =        *    or parent, then start new = transaction and erase from table
-       =  *    all data row by row. On each deletion check whether = any FK
-        *    violations = have occurred. If ones take place, then rollback
-   =      *    transaction and halt VDBE. Otherwise, = commit transaction.
-        * 3. Drop = table by truncating (if step 2 was skipped), removing
-   =      *    indexes from _index table and = eventually tuple with corresponding
-       =  *    space_id from _space.
+     =    * Generate code to remove the table from = Tarantool
+        * and internal SQL = tables. Basically, it consists
+        * = from 3 stages:
+        * 1. Delete = statistics from _stat1 and _stat4 tables.
+     =    * 2. In case of presence of FK constraints, i.e. = current
+        *    table is = child or parent, then start new transaction
+     =    *    and erase from table all data row by row. On = each
+        *    deletion = check whether any FK violations have
+       =  *    occurred. If ones take place, then = rollback
+        *   =  transaction and halt VDBE.
+       =  * 3. Drop table by truncating (if step 2 was skipped),
+ =        *    removing indexes from _index = space and eventually
+        *   =  tuple with corresponding space_id from _space.
  =        */


= --Apple-Mail=_7C4A95CC-3ABE-467D-846B-1A6A54C7436C--