Поля без знака int кажутся неправильно введенными в System.Int32 System.Data.SQLite

Используя System.Data.SQLite, я создаю таблицу с целочисленными столбцами без знака:

@"CREATE TABLE widgets (" +
    @"id unsigned integer(10) PRIMARY KEY, " +
    @"fkey unsigned integer(10), " + ...

а затем вставьте такие значения, как

INSERT INTO widgets (id, fkey, ...) VALUES (4294967295, 3456, ...

Однако, перебирая строки и столбцы этой таблицы, я обнаруживаю, что row["id"] имеет тип System.Int32 (а не UInt32) и, что неудивительно, 4294967295 интерпретируется как -1. На самом деле, все беззнаковые целые поля в таблице (не только идентификатор первичного ключа неправильно набран как System.Int32)

Между тем спецификация типа SQLite говорит, что целые числа хранятся в 1, 2, 3, 4, 6 или 8 байтах в зависимости от величины значения. 4294967295 = 0xFFFFFFFF занимает всего четыре байта. Это также кажется несовместимым с так называемой «динамической типизацией» SQLite. Когда я вставляю больше, чем 4294967295 положительных значений, тип остается System.Int32.

Это баг или фича?

PS1:

моя таблица содержит 1 строку с идентификатором столбца = 2 ^ 32-1 = 4294967295 (или больше), и я печатаю типы всех столбцов с помощью

public void PrintDataTypes(DataTable dt) {
    foreach (DataRow row in dt.Rows) {
        foreach (DataColumn col in dt.Columns)
            Console.WriteLine("name={0}, type={1}", 
                               col.ToString(),
                               row[col].GetType().ToString());
        return; // after 1st row is done
    }
}

И я неизменно получаю

name=id, type=System.Int32
name=fkey, type=System.Int32
...    

person user2770141    schedule 18.11.2013    source источник
comment
См. sqlite.org/datatype3.html - насколько мне известно, SQLite игнорирует ключевое слово unsigned и спецификатор размера. Чтобы определить, почему вы видите Int32, вы можете опубликовать код, который вы используете для чтения из таблицы.   -  person C.Evenhuis    schedule 18.11.2013
comment
Спасибо! Я добавил PS1 в исходный пост, чтобы объяснить, как я получаю System.Int32.   -  person user2770141    schedule 18.11.2013
comment
Ссылаясь на предложенную вами ссылку: например, класс хранения INTEGER включает 6 различных целочисленных типов данных разной длины. Это имеет значение на диске. Но как только значения INTEGER считываются с диска и помещаются в память для обработки, они преобразуются в наиболее общий тип данных (8-байтовое целое число со знаком).   -  person user2770141    schedule 18.11.2013
comment
В SQLite все целые числа имеют один и тот же тип, 64 бита со знаком. (Меньшее хранилище — это просто оптимизация). Использование Int32 выглядит как ошибка в драйвере БД.   -  person CL.    schedule 18.11.2013
comment
Все еще отсутствует то, как таблица SQlite становится DataTable. Возможно, это неправильная конфигурация адаптера или таблицы. Они строго типизированы, что такое SELECT-запрос?   -  person Henk Holterman    schedule 13.12.2013
comment
Во многих базах данных целые значения всегда подписаны. Однако на большинстве языков вы можете без проблем преобразовать их в неподписанные. Например, в C# uint val = (uint)signedIntegerValue.   -  person Erik    schedule 31.03.2014


Ответы (1)


Вы не получите беззнаковый целочисленный столбец в SqLite, даже если вы указали беззнаковый в своем SQL. Да, я лично считаю это явным недостатком - он даже не выводит предупреждение, увидев вашу «неподписанную» спецификацию в вашем SQL. Таким образом, ваш столбец имеет 64-битную подпись, и максимальное значение, которое вы можете сохранить, действительно равно 2 в 63-й степени.

person JamesWHurst    schedule 13.04.2014