Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Fix the sqlite3_table_column_metadata() routine so that it gives the correct answer for the "rowid" column in a WITHOUT ROWID table. Enhance it so that it can be used to check for the existence of a table by setting the column name parameter to NULL. The routine is now included in the build by default, even without the SQLITE_ENABLE_COLUMN_METADATA compile-time option. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
cf9be419a16156a9814e1378bb49b780 |
User & Date: | drh 2014-12-09 22:24:42.981 |
Context
2014-12-10
| ||
04:58 | Fix typos in the documentation for sqlite3_table_column_metadata(). No changes to code. (check-in: 3528f8dd39 user: drh tags: trunk) | |
2014-12-09
| ||
22:24 | Fix the sqlite3_table_column_metadata() routine so that it gives the correct answer for the "rowid" column in a WITHOUT ROWID table. Enhance it so that it can be used to check for the existence of a table by setting the column name parameter to NULL. The routine is now included in the build by default, even without the SQLITE_ENABLE_COLUMN_METADATA compile-time option. (check-in: cf9be419a1 user: drh tags: trunk) | |
20:13 | Add extra tests to e_walckpt.test. (check-in: 84f9581019 user: dan tags: trunk) | |
Changes
Changes to src/main.c.
︙ | ︙ | |||
3184 3185 3186 3187 3188 3189 3190 | pTab = sqlite3FindTable(db, zTableName, zDbName); if( !pTab || pTab->pSelect ){ pTab = 0; goto error_out; } /* Find the column for which info is requested */ | | | < < < > > > > | | > | 3184 3185 3186 3187 3188 3189 3190 3191 3192 3193 3194 3195 3196 3197 3198 3199 3200 3201 3202 3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 | pTab = sqlite3FindTable(db, zTableName, zDbName); if( !pTab || pTab->pSelect ){ pTab = 0; goto error_out; } /* Find the column for which info is requested */ if( zColumnName==0 ){ /* Query for existance of table only */ }else{ for(iCol=0; iCol<pTab->nCol; iCol++){ pCol = &pTab->aCol[iCol]; if( 0==sqlite3StrICmp(pCol->zName, zColumnName) ){ break; } } if( iCol==pTab->nCol ){ if( HasRowid(pTab) && sqlite3IsRowid(zColumnName) ){ iCol = pTab->iPKey; pCol = iCol>=0 ? &pTab->aCol[iCol] : 0; }else{ pTab = 0; goto error_out; } } } /* The following block stores the meta information that will be returned ** to the caller in local variables zDataType, zCollSeq, notnull, primarykey ** and autoinc. At this point there are two possibilities: ** |
︙ | ︙ |
Changes to src/sqlite.h.in.
︙ | ︙ | |||
5148 5149 5150 5151 5152 5153 5154 | */ SQLITE_DEPRECATED void sqlite3_soft_heap_limit(int N); /* ** CAPI3REF: Extract Metadata About A Column Of A Table ** | | > | > | > > > > > > | < | | > | | | | | < | 5148 5149 5150 5151 5152 5153 5154 5155 5156 5157 5158 5159 5160 5161 5162 5163 5164 5165 5166 5167 5168 5169 5170 5171 5172 5173 5174 5175 5176 5177 5178 5179 5180 5181 5182 5183 5184 5185 5186 5187 5188 5189 5190 5191 5192 5193 5194 5195 5196 5197 5198 5199 5200 5201 5202 5203 5204 5205 5206 5207 5208 5209 5210 5211 5212 5213 5214 5215 5216 5217 5218 5219 5220 5221 5222 5223 | */ SQLITE_DEPRECATED void sqlite3_soft_heap_limit(int N); /* ** CAPI3REF: Extract Metadata About A Column Of A Table ** ** ^The sqlite3_table_column_metadata(X,D,T,C,....) routine returns ** information about column C of table T in database D ** on [database connection] X. ^The sqlite3_table_column_metadata() ** interface returns SQLITE_OK and fills in the non-NULL pointers in ** the final five arguments with appropriate vaules if the specified ** column exists. ^The sqlite3_table_column_metadata() interface returns ** SQLITE_ERROR and if the specified column does not exist. ** If the column-name parameter to sqlite3_table_column_metadata() is a ** NULL pointer, then the routine simply checks for the existance of the ** table and returns SQLITE_OK if the table exists and SQLITE_ERROR if it ** does not. ** ** ^The column is identified by the second, third and fourth parameters to ** this function. ^The second parameter is either the name of the database ** (i.e. "main", "temp", or an attached database) containing the specified ** table or NULL. ^If it is NULL, then all attached databases are searched ** for the table using the same algorithm used by the database engine to ** resolve unqualified table references. ** ** ^The third and fourth parameters to this function are the table and column ** name of the desired column, respectively. ** ** ^Metadata is returned by writing to the memory locations passed as the 5th ** and subsequent parameters to this function. ^Any of these arguments may be ** NULL, in which case the corresponding element of metadata is omitted. ** ** ^(<blockquote> ** <table border="1"> ** <tr><th> Parameter <th> Output<br>Type <th> Description ** ** <tr><td> 5th <td> const char* <td> Data type ** <tr><td> 6th <td> const char* <td> Name of default collation sequence ** <tr><td> 7th <td> int <td> True if column has a NOT NULL constraint ** <tr><td> 8th <td> int <td> True if column is part of the PRIMARY KEY ** <tr><td> 9th <td> int <td> True if column is [AUTOINCREMENT] ** </table> ** </blockquote>)^ ** ** ^The memory pointed to by the character pointers returned for the ** declaration type and collation sequence is valid until the next ** call to any SQLite API function. ** ** ^If the specified table is actually a view, an [error code] is returned. ** ** ^If the specified column is "rowid", "oid" or "_rowid_" and the table ** is not a [WITHOUT ROWID] table and an ** [INTEGER PRIMARY KEY] column has been explicitly declared, then the output ** parameters are set for the explicitly declared column. ^(If there is no ** [INTEGER PRIMARY KEY] column, then the outputs ** for the [rowid] are set as follows: ** ** <pre> ** data type: "INTEGER" ** collation sequence: "BINARY" ** not null: 0 ** primary key: 1 ** auto increment: 0 ** </pre>)^ ** ** ^This function causes all database schemas to be read from disk and ** parsed, if that has not already been done, and returns an error if ** any errors are encountered while loading the schema. */ int sqlite3_table_column_metadata( sqlite3 *db, /* Connection handle */ const char *zDbName, /* Database name or NULL */ const char *zTableName, /* Table name */ const char *zColumnName, /* Column name */ char const **pzDataType, /* OUTPUT: Declared data type */ |
︙ | ︙ |
Changes to src/test1.c.
︙ | ︙ | |||
1584 1585 1586 1587 1588 1589 1590 | const char *zDatatype; const char *zCollseq; int notnull; int primarykey; int autoincrement; | | | | 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 | const char *zDatatype; const char *zCollseq; int notnull; int primarykey; int autoincrement; if( objc!=5 && objc!=4 ){ Tcl_WrongNumArgs(interp, 1, objv, "DB dbname tblname colname"); return TCL_ERROR; } if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; zDb = Tcl_GetString(objv[2]); zTbl = Tcl_GetString(objv[3]); zCol = objc==5 ? Tcl_GetString(objv[4]) : 0; if( strlen(zDb)==0 ) zDb = 0; rc = sqlite3_table_column_metadata(db, zDb, zTbl, zCol, &zDatatype, &zCollseq, ¬null, &primarykey, &autoincrement); if( rc!=SQLITE_OK ){ |
︙ | ︙ |
Changes to test/colmeta.test.
︙ | ︙ | |||
19 20 21 22 23 24 25 26 27 28 29 30 31 32 | # Set up a schema in the main and temp test databases. do_test colmeta-0 { execsql { CREATE TABLE abc(a, b, c); CREATE TABLE abc2(a PRIMARY KEY COLLATE NOCASE, b VARCHAR(32), c); CREATE TABLE abc3(a NOT NULL, b INTEGER PRIMARY KEY, c); } ifcapable autoinc { execsql { CREATE TABLE abc4(a, b INTEGER PRIMARY KEY AUTOINCREMENT, c); } } ifcapable view { | > > | 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | # Set up a schema in the main and temp test databases. do_test colmeta-0 { execsql { CREATE TABLE abc(a, b, c); CREATE TABLE abc2(a PRIMARY KEY COLLATE NOCASE, b VARCHAR(32), c); CREATE TABLE abc3(a NOT NULL, b INTEGER PRIMARY KEY, c); CREATE TABLE abc5(w,x,y,z,PRIMARY KEY(x,z)) WITHOUT ROWID; CREATE TABLE abc6(rowid TEXT COLLATE rtrim, oid REAL, _rowid_ BLOB); } ifcapable autoinc { execsql { CREATE TABLE abc4(a, b INTEGER PRIMARY KEY AUTOINCREMENT, c); } } ifcapable view { |
︙ | ︙ | |||
48 49 50 51 52 53 54 55 | 4 {main abc2 b} {0 {VARCHAR(32) BINARY 0 0 0}} 5 {{} abc2 a} {0 {{} NOCASE 0 1 0}} 6 {{} abc3 a} {0 {{} BINARY 1 0 0}} 7 {{} abc3 b} {0 {INTEGER BINARY 0 1 0}} 13 {main abc rowid} {0 {INTEGER BINARY 0 1 0}} 14 {main abc3 rowid} {0 {INTEGER BINARY 0 1 0}} 16 {main abc d} {1 {no such table column: abc.d}} } | > > > > > > > > | | | | | | | > > > > > > > > > > > | 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 | 4 {main abc2 b} {0 {VARCHAR(32) BINARY 0 0 0}} 5 {{} abc2 a} {0 {{} NOCASE 0 1 0}} 6 {{} abc3 a} {0 {{} BINARY 1 0 0}} 7 {{} abc3 b} {0 {INTEGER BINARY 0 1 0}} 13 {main abc rowid} {0 {INTEGER BINARY 0 1 0}} 14 {main abc3 rowid} {0 {INTEGER BINARY 0 1 0}} 16 {main abc d} {1 {no such table column: abc.d}} 20 {main abc5 w} {0 {{} BINARY 0 0 0}} 21 {main abc5 x} {0 {{} BINARY 1 1 0}} 22 {main abc5 y} {0 {{} BINARY 0 0 0}} 23 {main abc5 z} {0 {{} BINARY 1 1 0}} 24 {main abc5 rowid} {1 {no such table column: abc5.rowid}} 30 {main abc6 rowid} {0 {TEXT rtrim 0 0 0}} 31 {main abc6 oid} {0 {REAL BINARY 0 0 0}} 32 {main abc6 _rowid_} {0 {BLOB BINARY 0 0 0}} } ifcapable autoinc { set tests [concat $tests { 100 {{} abc4 b} {0 {INTEGER BINARY 0 1 1}} 101 {main abc4 rowid} {0 {INTEGER BINARY 0 1 1}} }] } ifcapable view { set tests [concat $tests { 200 {{} v1 a} {1 {no such table column: v1.a}} 201 {main v1 b} {1 {no such table column: v1.b}} 202 {main v1 badname} {1 {no such table column: v1.badname}} 203 {main v1 rowid} {1 {no such table column: v1.rowid}} }] } foreach {tn params results} $tests { set ::DB [sqlite3_connection_pointer db] set tstbody [concat sqlite3_table_column_metadata $::DB $params] do_test colmeta-$tn.1 { list [catch $tstbody msg] [set msg] } $results db close sqlite3 db test.db set ::DB [sqlite3_connection_pointer db] set tstbody [concat sqlite3_table_column_metadata $::DB $params] do_test colmeta-$tn.2 { list [catch $tstbody msg] [set msg] } $results } # Calling sqlite3_table_column_metadata with a NULL column name merely # checks for the existance of the table. # do_test colmeta-300 { catch {sqlite3_table_column_metadata $::DB main xyzzy} res } {1} do_test colmeta-301 { catch {sqlite3_table_column_metadata $::DB main abc} res } {0} finish_test |