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.
В этой точке я понял, что убил достаточно собственных нервных клеток и пора вынести мозг другим.
dimitr on 22 января, 2017
20К полей — это пять! Слабо 70К?