FB3. Max Row Size

Все начиналось достаточно безобидно — я поправил в описании информационного свойства «Maximum Row Size» значение с 65536 на 65565.

Потом сообразил, что надо бы поправить эту константу в коде IBProvider.

Потом пришла мысль, которая должна была прийти в самом начале — «надо бы посмотреть на сайте FB». Посмотрел.

Maximum row size = 64KB

Maximum number of columns per table = Depends on data types used. (Example: 16,384 INTEGER (4-byte) values per row.)

А потом решил таки проверить все это самому на Firebird 3.0.2.32651.

Накатал код на VBScript.

option explicit

dim s

s="create table t2_16384("

dim i

for i=1 to 16384
 if(i>1)then
  s=s&","
 end if
  
 s=s&"c"&i&" INTEGER"
next 'i

s=s&")"

'wscript.echo s

dim cn
set cn=createobject("ADODB.Connection")

cn.provider="LCPI.IBProvider.3"

cn.Properties("location").value      ="localhost:d:\database\ram\ibp_test_fb30_d3.gdb"
cn.Properties("user id").value       ="GAMER"
cn.Properties("password").value      ="vermut"
cn.Properties("auto_commit").value   =true
cn.Properties("dbclient_type").value ="fb.direct"

stop

call cn.open()

call cn.execute(s)

Сначала мне НЕ удалось создать таблицу с 16,384 integer. Ошибка при коммите (автоматической транзакции). Какая именно ошибка — не понятно.

Ладно. Черт с ней, с ошибкой.

Таблицу с 16383 integer я создать смог. Но не смог её открыть ни в IBExpert, ни через IBProvider.

Ну, думаю — ладно, напишу в им трекер про 16384. Накатал проникновенный текст… Надо бы этот проклятый текст ошибки коммита указать.

Переписал код на C# и наш ADO.NET провайдер — там ошибки нормально выводятся.

И тут началось самое интересное.

Я смог создать таблицы и с 16384 колонками и с 16385 колонками… и с двадцатью тысячами INTEGER-колонок тоже смог создать.

Вот этот адский скрипт на C#:

using System;
using System.Text;

using xdb=lcpi.data.oledb;

namespace ConsoleApplication1
{
 class Program
 {
  const uint c_cols=20000;

  static void Main(string[] args)
  {
   try
   {
    var s=new StringBuilder();

    s.AppendFormat("create table test2_integer_{0}(",c_cols);

    for(uint i = 0;i != c_cols;)
    {
     ++i;

     if(i>1)s.Append(",");

     s.AppendFormat("c{0} integer",i);
    }//for i

    s.Append(")");

    var csb=new xdb.OleDbConnectionStringBuilder();

    csb.Provider="LCPI.IBProvider.3";
    csb.Location="localhost:d:\\database\\ram\\ibp_test_fb30_d3.gdb";
    csb.UserID="GAMER";
    csb.Password="vermut";
    csb.IBProvider.dbclient_type="fb.direct";

    var cn=new xdb.OleDbConnection(csb.ConnectionString);

    cn.Open();

    using(var tr=cn.BeginTransaction())
    {
     var cmd=new xdb.OleDbCommand(null,cn,tr);

     cmd.CommandText=s.ToString();

     cmd.ExecuteNonQuery();

     tr.Commit();
    }
   }
   catch(Exception e)
   {
    Console.WriteLine("ERROR: {0} - {1}",e.Source,e.Message);
   }
  }
 }
}

А вот таблицу с 16383-я INTEGER колонок я создать не смог!

Текст ошибки:

ERROR: Multiple Sources - 1. [Firebird] unsuccessful metadata update
new record size of 67580 bytes is too big
TABLE TEST2_INTEGER_16383

Код ошибки COM: XACT_E_COMMITFAILED. SQL State: "54000". Код ошибки DBMS: 335544681.
--------------------------------
2. [LCPI.IBProvider.3] Ошибка подтверждения транзакции. Транзакция будет отменена.

Код ошибки COM: XACT_E_COMMITFAILED.
--------------------------------
3. [lcpi.data.oledb.OleDbTransaction] Коммит транзакции [уровень: 1, fRetaining: false] завершился с ошибками.

Код ошибки COM: XACT_E_COMMITFAILED.

В этой точке я понял, что убил достаточно собственных нервных клеток и пора вынести мозг другим.

One Comment

dimitr  on 22 января, 2017

20К полей — это пять! Слабо 70К?

Leave a Comment