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К?