On Monday, 27 January, 2020 10:31, James K. Lowden <jklow...@schemamania.org> 
wrote:

>On Sun, 26 Jan 2020 12:01:32 -0700
>"Keith Medcalf" <kmedc...@dessus.com> wrote:

>> Now that the table exists, use "SELECT * FROM <table>" to determine
>> the number of columns in the table (which will include computed
>> always columns, if any).
>...
>> Otherwise, Richard *may* make some changes to the .import logic which
>> *might* appear in the next release version.

>I imagine it's already being considered: if pragma table_info included
>a column with the SQL for generated columns (and NULL) otherwise, the
>shell could use that instead of SELECT * to determine the number of
>insertable columns.

That data is already in the schema structures as is the assigned affinity:

SQLite version 3.31.0 2020-01-27 17:01:49
Enter ".help" for usage hints.
sqlite> .schema details
CREATE TABLE Details
(
    ApplianceID     integer not null references Appliances(ApplianceID) on 
delete cascade,
    SrcIntID        integer not null references Interfaces(InterfaceID) on 
delete cascade,
    DstIntID        integer not null references Interfaces(InterfaceID) on 
delete cascade,
    Transport       text not null collate nocase,
    SrcHostID       integer not null references Hosts(HostID) on delete cascade,
    SrcPort         integer not null,
    DstHostID       integer not null references Hosts(HostID) on delete cascade,
    DstPort         integer not null,
    Action          integer not null,
    Count           integer not null,
    FileID          integer not null references Files(FileID) on delete cascade
);
sqlite> .mode col
sqlite> .head on
sqlite> pragma table_xinfo(details);
cid         name        type        aff         coll        notnull     
dflt_value  pk          rowid       autoinc     hidden
----------  ----------  ----------  ----------  ----------  ----------  
----------  ----------  ----------  ----------  ----------
-1                                  INTEGER                 0                   
    1           1           0           1
0           ApplianceI  integer     INTEGER                 1                   
    0           0           0           0
1           SrcIntID    integer     INTEGER                 1                   
    0           0           0           0
2           DstIntID    integer     INTEGER                 1                   
    0           0           0           0
3           Transport   text        TEXT        nocase      1                   
    0           0           0           0
4           SrcHostID   integer     INTEGER                 1                   
    0           0           0           0
5           SrcPort     integer     INTEGER                 1                   
    0           0           0           0
6           DstHostID   integer     INTEGER                 1                   
    0           0           0           0
7           DstPort     integer     INTEGER                 1                   
    0           0           0           0
8           Action      integer     INTEGER                 1                   
    0           0           0           0
9           Count       integer     INTEGER                 1                   
    0           0           0           0
10          FileID      integer     INTEGER                 1                   
    0           0           0           0
sqlite> create table x(id integer primary key, a datetime not null, c as (id + 
1), d as (id + 2) stored, e as (id + 3));
sqlite> pragma table_xinfo(x);
cid         name        type        aff         coll        notnull     
dflt_value  pk          rowid       autoinc     hidden
----------  ----------  ----------  ----------  ----------  ----------  
----------  ----------  ----------  ----------  ----------
0           id          integer     INTEGER                 0                   
    1           1           0           0
1           a           datetime    NUMERIC                 1                   
    0           0           0           0
2           c                       BLOB                    0                   
    0           0           0           2
3           d                       BLOB                    0                   
    0           0           0           3
4           e                       BLOB                    0                   
    0           0           0           2

This is my "modified" table_info pragma that returns somewhat more information 
for each column (all of which comes from the in the in-memory schema).  The 
"hidden" value is 0 for visible columns, 1 for "hidden" columns, 2 for computed 
virtual columns and 3 for computed stored columns.  I also added a 
database_info pragma that returns a list of objects in all attached schema's so 
that it is easier to define useful information views.

sqlite> create temporary table x(x);
sqlite> .width 8 8 64
sqlite> pragma database_info;
schema    type      name
--------  --------  
----------------------------------------------------------------
main      view      Details_v
main      table     sqlite_master
main      table     Hosts
main      table     Appliances
main      table     Files
main      table     Interfaces
main      table     RuleSet
main      table     Details
main      table     sqlite_stat1
main      table     sqlite_stat4
main      index     DetailPortClean
main      index     DetailsDstIntID
main      index     DetailsSrcIntID
main      index     DetailsDstHostID
main      index     DetailCoalesce
main      index     sqlite_autoindex_Hosts_1
main      index     sqlite_autoindex_Appliances_1
main      index     sqlite_autoindex_Files_1
main      index     sqlite_autoindex_Interfaces_1
main      index     sqlite_autoindex_RuleSet_1
main      index     HostsByName
main      index     DetailsSrcHostId
main      index     FilesApplianceID
main      index     DetailsApplianceID
main      index     DetailsFileID
temp      table     x
temp      table     sqlite_temp_master
main      etable    sqlite_stmt
main      etable    json_tree
main      etable    fts3tokenize
main      etable    pragma_module_list
main      etable    wholenumber
main      etable    pragma_database_list
main      etable    zipfile
main      etable    sqlite_dbpage
main      etable    sqlite_memstat
main      etable    completion
main      etable    generate_series
main      etable    delta_parse
main      etable    json_each
main      etable    sqlite_btreeinfo
main      etable    dbstat
main      etable    prefixes
main      etable    carray
main      etable    transitive_closure
main      etable    fsdir

>I'm a little confused, though.  ISTR the shell does something clever
>with .import, because constraints that enforce numeric types are
>violated even when the data are numeric.  Is that simply because the
>shell uses sqlite3_bind_text for every column, and the system doesn't
>attempt to convert numeric text to a numeric type, regardless of the
>column's declared type?

It depends if you are importing into a table that already exists or into a new 
one.  If you are importing into a new table, then the column names have no 
affinity (they are BLOBs) and therefore store the text as text (and the first 
row contains column names).  If you import into a pre-existing table then 
column affinity is applied when importing the data and no header row is parsed 
(ie, the header is treated as data).

sqlite> .mode csv
sqlite> .import ../sqlite/t.csv test1
sqlite> .mode col
sqlite> select * from test1;
a           b           c           d
----------  ----------  ----------  ----------
1           2           3           4
2           3           4           5
3           4           5           6
4           5           6           7
sqlite> select typeof(a), a from test1;
typeof(a)   a
----------  ----------
text        1
text        2
text        3
text        4
sqlite> drop table test1;
sqlite> create table test1 (a numeric, b numeric, c numeric, d numeric);
sqlite> .mode csv
sqlite> .import ../sqlite/t.csv test1
sqlite> .mode col
sqlite> select * from test1;
a           b           c           d
----------  ----------  ----------  ----------
a           b           c           d
1           2           3           4
2           3           4           5
3           4           5           6
4           5           6           7
sqlite> select typeof(a), a from test1;
typeof(a)   a
----------  ----------
text        a
integer     1
integer     2
integer     3
integer     4

If you mean importing into a pre-existing table as above that is declared with 
"check typeof(a) in ('integer', 'real')" then yes.  The check constraint is run 
before affinity is applied rather than after (unfortunately) ...

sqlite> drop table test1;
sqlite> create table test1(a numeric check (typeof(a) in ('integer','real')), b 
numeric, c numeric, d numeric);
sqlite> .mode csv
sqlite> .import ../sqlite/s.csv test1
../sqlite/s.csv:1: INSERT failed: CHECK constraint failed: test1
../sqlite/s.csv:2: INSERT failed: CHECK constraint failed: test1
../sqlite/s.csv:3: INSERT failed: CHECK constraint failed: test1
../sqlite/s.csv:4: INSERT failed: CHECK constraint failed: test1

-- 
The fact that there's a Highway to Hell but only a Stairway to Heaven says a 
lot about anticipated traffic volume.



_______________________________________________
sqlite-users mailing list
sqlite-users@mailinglists.sqlite.org
http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users

Reply via email to