Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Allow CREATE TABLE and CREATE INDEX on attached databases. (CVS 1483) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
4984a130ccf3b8e486941a5d0d0cc70a |
User & Date: | danielk1977 2004-05-28 11:37:27.000 |
Context
2004-05-28
| ||
12:11 | Allow DROP TABLE and DROP INDEX on attached databases. (CVS 1484) (check-in: 2fb3708e10 user: danielk1977 tags: trunk) | |
11:37 | Allow CREATE TABLE and CREATE INDEX on attached databases. (CVS 1483) (check-in: 4984a130cc user: danielk1977 tags: trunk) | |
08:21 | Tables and indices use the same record format. (CVS 1482) (check-in: 1b15b32bdb user: drh tags: trunk) | |
Changes
Changes to src/build.c.
︙ | ︙ | |||
19 20 21 22 23 24 25 | ** DROP INDEX ** creating ID lists ** BEGIN TRANSACTION ** COMMIT ** ROLLBACK ** PRAGMA ** | | | 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | ** DROP INDEX ** creating ID lists ** BEGIN TRANSACTION ** COMMIT ** ROLLBACK ** PRAGMA ** ** $Id: build.c,v 1.194 2004/05/28 11:37:27 danielk1977 Exp $ */ #include "sqliteInt.h" #include <ctype.h> /* ** This routine is called when a new SQL statement is beginning to ** be parsed. Check to see if the schema for the database needs |
︙ | ︙ | |||
395 396 397 398 399 400 401 | char *sqlite3TableNameFromToken(Token *pName){ char *zName = sqliteStrNDup(pName->z, pName->n); sqlite3Dequote(zName); return zName; } /* | | < | < | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 | char *sqlite3TableNameFromToken(Token *pName){ char *zName = sqliteStrNDup(pName->z, pName->n); sqlite3Dequote(zName); return zName; } /* ** Open the sqlite_master table stored in database number iDb for ** writing. The table is opened using cursor 0. */ void sqlite3OpenMasterTable(Vdbe *v, int iDb){ sqlite3VdbeAddOp(v, OP_Integer, iDb, 0); sqlite3VdbeAddOp(v, OP_OpenWrite, 0, MASTER_ROOT); sqlite3VdbeAddOp(v, OP_SetNumColumns, 0, 5); /* sqlite_master has 5 columns */ } /* ** The token *pName contains the name of a database (either "main" or ** "temp" or the name of an attached db). This routine returns the ** index of the named database in db->aDb[], or -1 if the named db ** does not exist. */ int findDb(sqlite3 *db, Token *pName){ int i; for(i=0; i<db->nDb; i++){ if( pName->n==strlen(db->aDb[i].zName) && 0==sqlite3StrNICmp(db->aDb[i].zName, pName->z, pName->n) ){ return i; } } return -1; } static int resolveSchemaName( Parse *pParse, Token *pName1, Token *pName2, Token **pUnqual ){ int iDb; sqlite3 *db = pParse->db; if( pName2 && pName2->n>0 ){ assert( !db->init.busy ); *pUnqual = pName2; iDb = findDb(db, pName1); if( iDb<0 ){ sqlite3ErrorMsg(pParse, "unknown database %T", pName1); pParse->nErr++; return -1; } }else{ assert( db->init.iDb==0 || db->init.busy ); iDb = db->init.iDb; *pUnqual = pName1; } return iDb; } /* ** Begin constructing a new table representation in memory. This is ** the first of several action routines that get called in response ** to a CREATE TABLE statement. In particular, this routine is called ** after seeing tokens "CREATE" and "TABLE" and the table name. The ** pStart token is the CREATE and pName is the table name. The isTemp |
︙ | ︙ | |||
426 427 428 429 430 431 432 | ** routines will be called to add more information to this record. ** At the end of the CREATE TABLE statement, the sqlite3EndTable() routine ** is called to complete the construction of the new table record. */ void sqlite3StartTable( Parse *pParse, /* Parser context */ Token *pStart, /* The "CREATE" token */ | | > | > > > > > > > > > > > > > > > > > > > > > > > | > > > > > | | 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 | ** routines will be called to add more information to this record. ** At the end of the CREATE TABLE statement, the sqlite3EndTable() routine ** is called to complete the construction of the new table record. */ void sqlite3StartTable( Parse *pParse, /* Parser context */ Token *pStart, /* The "CREATE" token */ Token *pName1, /* First part of the name of the table or view */ Token *pName2, /* Second part of the name of the table or view */ int isTemp, /* True if this is a TEMP table */ int isView /* True if this is a VIEW */ ){ Table *pTable; Index *pIdx; char *zName; sqlite *db = pParse->db; Vdbe *v; int iDb; /* Database number to create the table in */ Token *pName; /* Unqualified name of the table to create */ /* The table or view name to create is passed to this routine via tokens ** pName1 and pName2. If the table name was fully qualified, for example: ** ** CREATE TABLE xxx.yyy (...); ** ** Then pName1 is set to "xxx" and pName2 "yyy". On the other hand if ** the table name is not fully qualified, i.e.: ** ** CREATE TABLE yyy(...); ** ** Then pName1 is set to "yyy" and pName2 is "". ** ** The call below sets the pName pointer to point at the token (pName1 or ** pName2) that stores the unqualified table name. The variable iDb is ** set to the index of the database that the table or view is to be ** created in. */ iDb = resolveSchemaName(pParse, pName1, pName2, &pName); if( iDb<0 ) return; if( isTemp && iDb>1 ){ /* If creating a temp table, the name may not be qualified */ sqlite3ErrorMsg(pParse, "temporary table name must be unqualified"); pParse->nErr++; return; } if( isTemp ) iDb = 1; pParse->sNameToken = *pName; zName = sqlite3TableNameFromToken(pName); if( zName==0 ) return; if( db->init.iDb==1 ) isTemp = 1; #ifndef SQLITE_OMIT_AUTHORIZATION assert( (isTemp & 1)==isTemp ); { int code; char *zDb = db->aDb[iDb].zName; if( sqlite3AuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(isTemp), 0, zDb) ){ sqliteFree(zName); return; } if( isView ){ if( isTemp ){ code = SQLITE_CREATE_TEMP_VIEW; |
︙ | ︙ | |||
469 470 471 472 473 474 475 | } if( sqlite3AuthCheck(pParse, code, zName, 0, zDb) ){ sqliteFree(zName); return; } } #endif | < | 539 540 541 542 543 544 545 546 547 548 549 550 551 552 | } if( sqlite3AuthCheck(pParse, code, zName, 0, zDb) ){ sqliteFree(zName); return; } } #endif /* Before trying to create a temporary table, make sure the Btree for ** holding temporary tables is open. */ if( isTemp && db->aDb[1].pBt==0 && !pParse->explain ){ int rc = sqlite3BtreeFactory(db, 0, 0, MAX_PAGES, &db->aDb[1].pBt); if( rc!=SQLITE_OK ){ |
︙ | ︙ | |||
500 501 502 503 504 505 506 | ** index or table name. Issue an error message if it does. ** ** If we are re-reading the sqlite_master table because of a schema ** change and a new permanent table is found whose name collides with ** an existing temporary table, that is not an error. */ pTable = sqlite3FindTable(db, zName, 0); | < | 569 570 571 572 573 574 575 576 577 578 579 580 581 582 | ** index or table name. Issue an error message if it does. ** ** If we are re-reading the sqlite_master table because of a schema ** change and a new permanent table is found whose name collides with ** an existing temporary table, that is not an error. */ pTable = sqlite3FindTable(db, zName, 0); if( pTable!=0 && (pTable->iDb==iDb || !db->init.busy) ){ sqlite3ErrorMsg(pParse, "table %T already exists", pName); sqliteFree(zName); return; } if( (pIdx = sqlite3FindIndex(db, zName, 0))!=0 && (pIdx->iDb==0 || !db->init.busy) ){ |
︙ | ︙ | |||
535 536 537 538 539 540 541 | ** and allocate the record number for the table entry now. Before any ** PRIMARY KEY or UNIQUE keywords are parsed. Those keywords will cause ** indices to be created and the table record must come before the ** indices. Hence, the record number for the table must be allocated ** now. */ if( !db->init.busy && (v = sqlite3GetVdbe(pParse))!=0 ){ | | > > > > | | | | 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 | ** and allocate the record number for the table entry now. Before any ** PRIMARY KEY or UNIQUE keywords are parsed. Those keywords will cause ** indices to be created and the table record must come before the ** indices. Hence, the record number for the table must be allocated ** now. */ if( !db->init.busy && (v = sqlite3GetVdbe(pParse))!=0 ){ sqlite3BeginWriteOperation(pParse, 0, iDb); if( !isTemp ){ /* Every time a new table is created the file-format ** and encoding meta-values are set in the database, in ** case this is the first table created. */ sqlite3VdbeAddOp(v, OP_Integer, db->file_format, 0); sqlite3VdbeAddOp(v, OP_SetCookie, iDb, 1); sqlite3VdbeAddOp(v, OP_Integer, db->enc, 0); sqlite3VdbeAddOp(v, OP_SetCookie, iDb, 4); } sqlite3OpenMasterTable(v, iDb); sqlite3VdbeAddOp(v, OP_NewRecno, 0, 0); sqlite3VdbeAddOp(v, OP_Dup, 0, 0); sqlite3VdbeAddOp(v, OP_String, 0, 0); sqlite3VdbeAddOp(v, OP_PutIntKey, 0, 0); } } |
︙ | ︙ | |||
717 718 719 720 721 722 723 | if( iCol>=0 && iCol<pTab->nCol ){ zType = pTab->aCol[iCol].zType; } if( zType && sqlite3StrICmp(zType, "INTEGER")==0 ){ pTab->iPKey = iCol; pTab->keyConf = onError; }else{ | | | 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 | if( iCol>=0 && iCol<pTab->nCol ){ zType = pTab->aCol[iCol].zType; } if( zType && sqlite3StrICmp(zType, "INTEGER")==0 ){ pTab->iPKey = iCol; pTab->keyConf = onError; }else{ sqlite3CreateIndex(pParse, 0, 0, 0, pList, onError, 0, 0); pList = 0; } primary_key_exit: sqlite3IdListDelete(pList); return; } |
︙ | ︙ | |||
846 847 848 849 850 851 852 | ** ** This plan is not completely bullet-proof. It is possible for ** the schema to change multiple times and for the cookie to be ** set back to prior value. But schema changes are infrequent ** and the probability of hitting the same cookie value is only ** 1 chance in 2^32. So we're safe enough. */ | | | | 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 | ** ** This plan is not completely bullet-proof. It is possible for ** the schema to change multiple times and for the cookie to be ** set back to prior value. But schema changes are infrequent ** and the probability of hitting the same cookie value is only ** 1 chance in 2^32. So we're safe enough. */ void sqlite3ChangeCookie(sqlite *db, Vdbe *v, int iDb){ if( db->next_cookie==db->aDb[0].schema_cookie ){ unsigned char r; sqlite3Randomness(1, &r); db->next_cookie = db->aDb[0].schema_cookie + r + 1; db->flags |= SQLITE_InternChanges; sqlite3VdbeAddOp(v, OP_Integer, db->next_cookie, 0); sqlite3VdbeAddOp(v, OP_SetCookie, iDb, 0); } } /* ** Measure the number of characters needed to output the given ** identifier. The number returned includes any quotes used ** but does not include the null terminator. |
︙ | ︙ | |||
1011 1012 1013 1014 1015 1016 1017 | } p->tnum = 0; sqlite3VdbeAddOp(v, OP_Pull, 1, 0); sqlite3VdbeOp3(v, OP_String, 0, 0, p->pSelect==0?"table":"view", P3_STATIC); sqlite3VdbeOp3(v, OP_String, 0, 0, p->zName, 0); sqlite3VdbeOp3(v, OP_String, 0, 0, p->zName, 0); sqlite3VdbeAddOp(v, OP_Dup, 4, 0); | < > > > > > > | > | > | | 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 | } p->tnum = 0; sqlite3VdbeAddOp(v, OP_Pull, 1, 0); sqlite3VdbeOp3(v, OP_String, 0, 0, p->pSelect==0?"table":"view", P3_STATIC); sqlite3VdbeOp3(v, OP_String, 0, 0, p->zName, 0); sqlite3VdbeOp3(v, OP_String, 0, 0, p->zName, 0); sqlite3VdbeAddOp(v, OP_Dup, 4, 0); if( pSelect ){ char *z = createTableStmt(p); n = z ? strlen(z) : 0; sqlite3VdbeAddOp(v, OP_String, 0, 0); sqlite3VdbeChangeP3(v, -1, z, n); sqliteFree(z); }else{ if( p->pSelect ){ sqlite3VdbeOp3(v, OP_String, 0, 0, "CREATE VIEW ", P3_STATIC); }else{ sqlite3VdbeOp3(v, OP_String, 0, 0, "CREATE TABLE ", P3_STATIC); } assert( pEnd!=0 ); n = Addr(pEnd->z) - Addr(pParse->sNameToken.z) + 1; sqlite3VdbeAddOp(v, OP_String, 0, 0); sqlite3VdbeChangeP3(v, -1, pParse->sNameToken.z, n); sqlite3VdbeAddOp(v, OP_Concat, 2, 0); } sqlite3VdbeOp3(v, OP_MakeRecord, 5, 0, "tttit", P3_STATIC); sqlite3VdbeAddOp(v, OP_PutIntKey, 0, 0); if( !p->iDb ){ sqlite3ChangeCookie(db, v, p->iDb); } sqlite3VdbeAddOp(v, OP_Close, 0, 0); if( pSelect ){ sqlite3VdbeAddOp(v, OP_Integer, p->iDb, 0); sqlite3VdbeAddOp(v, OP_OpenWrite, 1, 0); pParse->nTab = 2; sqlite3Select(pParse, pSelect, SRT_Table, 1, 0, 0, 0, 0); |
︙ | ︙ | |||
1075 1076 1077 1078 1079 1080 1081 | ){ Table *p; int n; const char *z; Token sEnd; DbFixer sFix; | | | 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 | ){ Table *p; int n; const char *z; Token sEnd; DbFixer sFix; sqlite3StartTable(pParse, pBegin, pName, 0, isTemp, 1); p = pParse->pNewTable; if( p==0 || pParse->nErr ){ sqlite3SelectDelete(pSelect); return; } if( sqlite3FixInit(&sFix, pParse, p->iDb, "view", pName) && sqlite3FixSelect(&sFix, pSelect) |
︙ | ︙ | |||
1345 1346 1347 1348 1349 1350 1351 | /* Drop all SQLITE_TEMP_MASTER entries that refer to the table */ if( pTable->iDb!=1 ){ sqlite3OpenMasterTable(v, 1); base = sqlite3VdbeAddOpList(v, ArraySize(dropTable), dropTable); sqlite3VdbeChangeP3(v, base+1, pTable->zName, 0); } | | | | 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 | /* Drop all SQLITE_TEMP_MASTER entries that refer to the table */ if( pTable->iDb!=1 ){ sqlite3OpenMasterTable(v, 1); base = sqlite3VdbeAddOpList(v, ArraySize(dropTable), dropTable); sqlite3VdbeChangeP3(v, base+1, pTable->zName, 0); } if( pTable->iDb!=1 ){ /* Temp database has no schema cookie */ sqlite3ChangeCookie(db, v, pTable->iDb); } sqlite3VdbeAddOp(v, OP_Close, 0, 0); if( !isView ){ sqlite3VdbeAddOp(v, OP_Destroy, pTable->tnum, pTable->iDb); for(pIdx=pTable->pIndex; pIdx; pIdx=pIdx->pNext){ sqlite3VdbeAddOp(v, OP_Destroy, pIdx->tnum, pIdx->iDb); } |
︙ | ︙ | |||
1513 1514 1515 1516 1517 1518 1519 | ** ** pList is a list of columns to be indexed. pList will be NULL if this ** is a primary key or unique-constraint on the most recent column added ** to the table currently under construction. */ void sqlite3CreateIndex( Parse *pParse, /* All information about this parse */ | | > | | > > > > > | > > > > > > > | > > > > > > > > > > > > | > > > | > > > > > > > > > | 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 | ** ** pList is a list of columns to be indexed. pList will be NULL if this ** is a primary key or unique-constraint on the most recent column added ** to the table currently under construction. */ void sqlite3CreateIndex( Parse *pParse, /* All information about this parse */ Token *pName1, /* First part of index name. May be NULL */ Token *pName2, /* Second part of index name. May be NULL */ Token *pTblName, /* Name of the table to index. Use pParse->pNewTable if 0 */ IdList *pList, /* A list of columns to be indexed */ int onError, /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */ Token *pStart, /* The CREATE token that begins a CREATE TABLE statement */ Token *pEnd /* The ")" that closes the CREATE INDEX statement */ ){ Table *pTab = 0; /* Table to be indexed */ Index *pIndex; /* The index to be created */ char *zName = 0; int i, j; Token nullId; /* Fake token for an empty ID list */ DbFixer sFix; /* For assigning database names to pTable */ int isTemp; /* True for a temporary index */ sqlite *db = pParse->db; int iDb; /* Index of the database that is being written */ Token *pName = 0; /* Unqualified name of the index to create */ /* if( pParse->nErr || sqlite3_malloc_failed ) goto exit_create_index; if( db->init.busy && sqlite3FixInit(&sFix, pParse, db->init.iDb, "index", pName) && sqlite3FixSrcList(&sFix, pTable) ){ goto exit_create_index; } */ /* ** Find the table that is to be indexed. Return early if not found. */ if( pTblName!=0 ){ char *zTblName; /* Use the two-part index name to determine the database ** to search for the table. If no database name is specified, ** iDb is set to 0. In this case search both the temp and main ** databases for the named table. */ assert( pName1 && pName2 ); iDb = resolveSchemaName(pParse, pName1, pName2, &pName); if( iDb<0 ) goto exit_create_index; /* Now search for the table in the database iDb. If iDb is ** zero, then search both the "main" and "temp" databases. */ zTblName = sqlite3TableNameFromToken(pTblName); if( !zTblName ){ pParse->nErr++; pParse->rc = SQLITE_NOMEM; goto exit_create_index; } assert( pName1!=0 ); if( iDb==0 ){ pTab = sqlite3FindTable(db, zTblName, "temp"); } if( !pTab ){ pTab = sqlite3LocateTable(pParse, zTblName, db->aDb[iDb].zName); } sqliteFree( zTblName ); if( !pTab ) goto exit_create_index; iDb = pTab->iDb; }else{ assert( pName==0 ); pTab = pParse->pNewTable; iDb = pTab->iDb; } if( pTab==0 || pParse->nErr ) goto exit_create_index; if( pTab->readOnly ){ sqlite3ErrorMsg(pParse, "table %s may not be indexed", pTab->zName); goto exit_create_index; } /* if( pTab->iDb>=2 && db->init.busy==0 ){ sqlite3ErrorMsg(pParse, "table %s may not have indices added", pTab->zName); goto exit_create_index; } */ if( pTab->pSelect ){ sqlite3ErrorMsg(pParse, "views may not be indexed"); goto exit_create_index; } isTemp = pTab->iDb==1; /* |
︙ | ︙ | |||
1607 1608 1609 1610 1611 1612 1613 | } /* Check for authorization to create an index. */ #ifndef SQLITE_OMIT_AUTHORIZATION { const char *zDb = db->aDb[pTab->iDb].zName; | < < | 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 | } /* Check for authorization to create an index. */ #ifndef SQLITE_OMIT_AUTHORIZATION { const char *zDb = db->aDb[pTab->iDb].zName; if( sqlite3AuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(isTemp), 0, zDb) ){ goto exit_create_index; } i = SQLITE_CREATE_INDEX; if( isTemp ) i = SQLITE_CREATE_TEMP_INDEX; if( sqlite3AuthCheck(pParse, i, zName, pTab->zName, zDb) ){ goto exit_create_index; |
︙ | ︙ | |||
1644 1645 1646 1647 1648 1649 1650 | pIndex->aiColumn = (int*)&pIndex->keyInfo.aColl[pList->nId]; pIndex->zName = (char*)&pIndex->aiColumn[pList->nId]; strcpy(pIndex->zName, zName); pIndex->pTable = pTab; pIndex->nColumn = pList->nId; pIndex->onError = onError; pIndex->autoIndex = pName==0; | | | 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 | pIndex->aiColumn = (int*)&pIndex->keyInfo.aColl[pList->nId]; pIndex->zName = (char*)&pIndex->aiColumn[pList->nId]; strcpy(pIndex->zName, zName); pIndex->pTable = pTab; pIndex->nColumn = pList->nId; pIndex->onError = onError; pIndex->autoIndex = pName==0; pIndex->iDb = iDb; /* Scan the names of the columns of the table to be indexed and ** load the column indices into the Index structure. Report an error ** if any column is not found. */ for(i=0; i<pList->nId; i++){ for(j=0; j<pTab->nCol; j++){ |
︙ | ︙ | |||
1702 1703 1704 1705 1706 1707 1708 | pOther->pNext = pIndex; } /* If the db->init.busy is 1 it means we are reading the SQL off the ** "sqlite_master" table on the disk. So do not write to the disk ** again. Extract the table number from the db->init.newTnum field. */ | | | < | | | | | | | > > | | > | | 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 | pOther->pNext = pIndex; } /* If the db->init.busy is 1 it means we are reading the SQL off the ** "sqlite_master" table on the disk. So do not write to the disk ** again. Extract the table number from the db->init.newTnum field. */ if( db->init.busy && pTblName!=0 ){ pIndex->tnum = db->init.newTnum; } /* If the db->init.busy is 0 then create the index on disk. This ** involves writing the index into the master table and filling in the ** index with the current table contents. ** ** The db->init.busy is 0 when the user first enters a CREATE INDEX ** command. db->init.busy is 1 when a database is opened and ** CREATE INDEX statements are read out of the master table. In ** the latter case the index already exists on disk, which is why ** we don't want to recreate it. ** ** If pTblName==0 it means this index is generated as a primary key ** or UNIQUE constraint of a CREATE TABLE statement. Since the table ** has just been created, it contains no data and the index initialization ** step can be skipped. */ else if( db->init.busy==0 ){ int n; Vdbe *v; int lbl1, lbl2; int i; v = sqlite3GetVdbe(pParse); if( v==0 ) goto exit_create_index; if( pTblName!=0 ){ sqlite3BeginWriteOperation(pParse, 0, iDb); sqlite3OpenMasterTable(v, iDb); } sqlite3VdbeAddOp(v, OP_NewRecno, 0, 0); sqlite3VdbeOp3(v, OP_String, 0, 0, "index", P3_STATIC); sqlite3VdbeOp3(v, OP_String, 0, 0, pIndex->zName, 0); sqlite3VdbeOp3(v, OP_String, 0, 0, pTab->zName, 0); sqlite3VdbeOp3(v, OP_CreateIndex, 0, iDb,(char*)&pIndex->tnum,P3_POINTER); pIndex->tnum = 0; if( pTblName ){ sqlite3VdbeCode(v, OP_Dup, 0, 0, OP_Integer, iDb, 0, 0); sqlite3VdbeOp3(v, OP_OpenWrite, 1, 0, (char*)&pIndex->keyInfo, P3_KEYINFO); } sqlite3VdbeAddOp(v, OP_String, 0, 0); if( pStart && pEnd ){ sqlite3VdbeChangeP3(v, -1, "CREATE INDEX ", n); sqlite3VdbeAddOp(v, OP_String, 0, 0); n = Addr(pEnd->z) - Addr(pName->z) + 1; sqlite3VdbeChangeP3(v, -1, pName->z, n); sqlite3VdbeAddOp(v, OP_Concat, 2, 0); } sqlite3VdbeOp3(v, OP_MakeRecord, 5, 0, "tttit", P3_STATIC); sqlite3VdbeAddOp(v, OP_PutIntKey, 0, 0); if( pTblName ){ sqlite3VdbeAddOp(v, OP_Integer, pTab->iDb, 0); sqlite3VdbeAddOp(v, OP_OpenRead, 2, pTab->tnum); /* VdbeComment((v, "%s", pTab->zName)); */ sqlite3VdbeAddOp(v, OP_SetNumColumns, 2, pTab->nCol); lbl2 = sqlite3VdbeMakeLabel(v); sqlite3VdbeAddOp(v, OP_Rewind, 2, lbl2); lbl1 = sqlite3VdbeAddOp(v, OP_Recno, 2, 0); |
︙ | ︙ | |||
1780 1781 1782 1783 1784 1785 1786 | sqlite3VdbeOp3(v, OP_IdxPut, 1, pIndex->onError!=OE_None, "indexed columns are not unique", P3_STATIC); sqlite3VdbeAddOp(v, OP_Next, 2, lbl1); sqlite3VdbeResolveLabel(v, lbl2); sqlite3VdbeAddOp(v, OP_Close, 2, 0); sqlite3VdbeAddOp(v, OP_Close, 1, 0); } | | | | | 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 | sqlite3VdbeOp3(v, OP_IdxPut, 1, pIndex->onError!=OE_None, "indexed columns are not unique", P3_STATIC); sqlite3VdbeAddOp(v, OP_Next, 2, lbl1); sqlite3VdbeResolveLabel(v, lbl2); sqlite3VdbeAddOp(v, OP_Close, 2, 0); sqlite3VdbeAddOp(v, OP_Close, 1, 0); } if( pTblName!=0 ){ if( !isTemp ){ sqlite3ChangeCookie(db, v, iDb); } sqlite3VdbeAddOp(v, OP_Close, 0, 0); sqlite3EndWriteOperation(pParse); } } /* Clean up before exiting */ exit_create_index: sqlite3IdListDelete(pList); /* sqlite3SrcListDelete(pTable); */ sqliteFree(zName); return; } /* ** This routine will drop an existing named index. This routine ** implements the DROP INDEX statement. |
︙ | ︙ | |||
1859 1860 1861 1862 1863 1864 1865 | }; int base; sqlite3BeginWriteOperation(pParse, 0, pIndex->iDb); sqlite3OpenMasterTable(v, pIndex->iDb); base = sqlite3VdbeAddOpList(v, ArraySize(dropIndex), dropIndex); sqlite3VdbeChangeP3(v, base+1, pIndex->zName, 0); | | | | 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 | }; int base; sqlite3BeginWriteOperation(pParse, 0, pIndex->iDb); sqlite3OpenMasterTable(v, pIndex->iDb); base = sqlite3VdbeAddOpList(v, ArraySize(dropIndex), dropIndex); sqlite3VdbeChangeP3(v, base+1, pIndex->zName, 0); if( pIndex->iDb!=1 ){ sqlite3ChangeCookie(db, v, pIndex->iDb); } sqlite3VdbeAddOp(v, OP_Close, 0, 0); sqlite3VdbeAddOp(v, OP_Destroy, pIndex->tnum, pIndex->iDb); sqlite3EndWriteOperation(pParse); } /* Delete the in-memory description of this index. |
︙ | ︙ |
Changes to src/parse.y.
︙ | ︙ | |||
10 11 12 13 14 15 16 | ** ************************************************************************* ** This file contains SQLite's grammar for SQL. Process this file ** using the lemon parser generator to generate C code that runs ** the parser. Lemon will also generate a header file containing ** numeric codes for all of the tokens. ** | | | 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | ** ************************************************************************* ** This file contains SQLite's grammar for SQL. Process this file ** using the lemon parser generator to generate C code that runs ** the parser. Lemon will also generate a header file containing ** numeric codes for all of the tokens. ** ** @(#) $Id: parse.y,v 1.120 2004/05/28 11:37:28 danielk1977 Exp $ */ %token_prefix TK_ %token_type {Token} %default_type {Token} %extra_argument {Parse *pParse} %syntax_error { if( pParse->zErrMsg==0 ){ |
︙ | ︙ | |||
83 84 85 86 87 88 89 | cmd ::= COMMIT trans_opt. {sqlite3CommitTransaction(pParse);} cmd ::= END trans_opt. {sqlite3CommitTransaction(pParse);} cmd ::= ROLLBACK trans_opt. {sqlite3RollbackTransaction(pParse);} ///////////////////// The CREATE TABLE statement //////////////////////////// // cmd ::= create_table create_table_args. | | | | 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 | cmd ::= COMMIT trans_opt. {sqlite3CommitTransaction(pParse);} cmd ::= END trans_opt. {sqlite3CommitTransaction(pParse);} cmd ::= ROLLBACK trans_opt. {sqlite3RollbackTransaction(pParse);} ///////////////////// The CREATE TABLE statement //////////////////////////// // cmd ::= create_table create_table_args. create_table ::= CREATE(X) temp(T) TABLE nm(Y) dbnm(Z). { sqlite3StartTable(pParse,&X,&Y,&Z,T,0); } %type temp {int} temp(A) ::= TEMP. {A = 1;} temp(A) ::= . {A = 0;} create_table_args ::= LP columnlist conslist_opt RP(X). { sqlite3EndTable(pParse,&X,0); } |
︙ | ︙ | |||
184 185 186 187 188 189 190 | // In addition to the type name, we also care about the primary key and // UNIQUE constraints. // ccons ::= NULL onconf. ccons ::= NOT NULL onconf(R). {sqlite3AddNotNull(pParse, R);} ccons ::= PRIMARY KEY sortorder onconf(R). {sqlite3AddPrimaryKey(pParse,0,R);} | | | 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 | // In addition to the type name, we also care about the primary key and // UNIQUE constraints. // ccons ::= NULL onconf. ccons ::= NOT NULL onconf(R). {sqlite3AddNotNull(pParse, R);} ccons ::= PRIMARY KEY sortorder onconf(R). {sqlite3AddPrimaryKey(pParse,0,R);} ccons ::= UNIQUE onconf(R). {sqlite3CreateIndex(pParse,0,0,0,0,R,0,0);} ccons ::= CHECK LP expr RP onconf. ccons ::= REFERENCES nm(T) idxlist_opt(TA) refargs(R). {sqlite3CreateForeignKey(pParse,0,&T,TA,R);} ccons ::= defer_subclause(D). {sqlite3DeferForeignKey(pParse,D);} ccons ::= COLLATE id(C). {sqlite3AddCollateType(pParse, C.z, C.n);} // The next group of rules parses the arguments to a REFERENCES clause |
︙ | ︙ | |||
229 230 231 232 233 234 235 | conslist ::= conslist COMMA tcons. conslist ::= conslist tcons. conslist ::= tcons. tcons ::= CONSTRAINT nm. tcons ::= PRIMARY KEY LP idxlist(X) RP onconf(R). {sqlite3AddPrimaryKey(pParse,X,R);} tcons ::= UNIQUE LP idxlist(X) RP onconf(R). | | | 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 | conslist ::= conslist COMMA tcons. conslist ::= conslist tcons. conslist ::= tcons. tcons ::= CONSTRAINT nm. tcons ::= PRIMARY KEY LP idxlist(X) RP onconf(R). {sqlite3AddPrimaryKey(pParse,X,R);} tcons ::= UNIQUE LP idxlist(X) RP onconf(R). {sqlite3CreateIndex(pParse,0,0,0,X,R,0,0);} tcons ::= CHECK expr onconf. tcons ::= FOREIGN KEY LP idxlist(FA) RP REFERENCES nm(T) idxlist_opt(TA) refargs(R) defer_subclause_opt(D). { sqlite3CreateForeignKey(pParse, FA, &T, TA, R); sqlite3DeferForeignKey(pParse, D); } %type defer_subclause_opt {int} |
︙ | ︙ | |||
723 724 725 726 727 728 729 | {A = sqlite3ExprListAppend(X,Y,0);} exprlist(A) ::= expritem(X). {A = sqlite3ExprListAppend(0,X,0);} expritem(A) ::= expr(X). {A = X;} expritem(A) ::= . {A = 0;} ///////////////////////////// The CREATE INDEX command /////////////////////// // | | | < | | 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 | {A = sqlite3ExprListAppend(X,Y,0);} exprlist(A) ::= expritem(X). {A = sqlite3ExprListAppend(0,X,0);} expritem(A) ::= expr(X). {A = X;} expritem(A) ::= . {A = 0;} ///////////////////////////// The CREATE INDEX command /////////////////////// // cmd ::= CREATE(S) uniqueflag(U) INDEX nm(X) dbnm(D) ON nm(Y) LP idxlist(Z) RP(E) onconf(R). { if( U!=OE_None ) U = R; if( U==OE_Default) U = OE_Abort; sqlite3CreateIndex(pParse, &X, &D, &Y, Z, U, &S, &E); } %type uniqueflag {int} uniqueflag(A) ::= UNIQUE. { A = OE_Abort; } uniqueflag(A) ::= . { A = OE_None; } %type idxlist {IdList*} |
︙ | ︙ |
Changes to src/sqliteInt.h.
1 2 3 4 5 6 7 8 9 10 11 12 13 | /* ** 2001 September 15 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** Internal interface definitions for SQLite. ** | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | /* ** 2001 September 15 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** Internal interface definitions for SQLite. ** ** @(#) $Id: sqliteInt.h,v 1.257 2004/05/28 11:37:28 danielk1977 Exp $ */ #include "config.h" #include "sqlite.h" #include "hash.h" #include "parse.h" #include <stdio.h> #include <stdlib.h> |
︙ | ︙ | |||
965 966 967 968 969 970 971 | ** carry around information that is global to the entire parse. */ struct Parse { sqlite *db; /* The main database structure */ int rc; /* Return code from execution */ char *zErrMsg; /* An error message */ Token sErrToken; /* The token at which the error occurred */ | | | 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 | ** carry around information that is global to the entire parse. */ struct Parse { sqlite *db; /* The main database structure */ int rc; /* Return code from execution */ char *zErrMsg; /* An error message */ Token sErrToken; /* The token at which the error occurred */ Token sNameToken; /* Token with unqualified schema object name */ Token sLastToken; /* The last token parsed */ const char *zTail; /* All SQL text past the last semicolon parsed */ Table *pNewTable; /* A table being constructed by CREATE TABLE */ Vdbe *pVdbe; /* An engine for executing database bytecode */ u8 colNamesSet; /* TRUE after OP_ColumnName has been issued to pVdbe */ u8 explain; /* True if the EXPLAIN flag is found on the query */ u8 nameClash; /* A permanent table name clashes with temp table name */ |
︙ | ︙ | |||
1195 1196 1197 1198 1199 1200 1201 | void sqlite3Pragma(Parse*,Token*,Token*,int); void sqlite3ResetInternalSchema(sqlite*, int); void sqlite3BeginParse(Parse*,int); void sqlite3RollbackInternalChanges(sqlite*); void sqlite3CommitInternalChanges(sqlite*); Table *sqlite3ResultSetOfSelect(Parse*,char*,Select*); void sqlite3OpenMasterTable(Vdbe *v, int); | | | 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 | void sqlite3Pragma(Parse*,Token*,Token*,int); void sqlite3ResetInternalSchema(sqlite*, int); void sqlite3BeginParse(Parse*,int); void sqlite3RollbackInternalChanges(sqlite*); void sqlite3CommitInternalChanges(sqlite*); Table *sqlite3ResultSetOfSelect(Parse*,char*,Select*); void sqlite3OpenMasterTable(Vdbe *v, int); void sqlite3StartTable(Parse*,Token*,Token*,Token*,int,int); void sqlite3AddColumn(Parse*,Token*); void sqlite3AddNotNull(Parse*, int); void sqlite3AddPrimaryKey(Parse*, IdList*, int); void sqlite3AddColumnType(Parse*,Token*,Token*); void sqlite3AddDefaultValue(Parse*,Token*,int); void sqlite3AddCollateType(Parse*, const char*, int); CollSeq *sqlite3ChangeCollatingFunction(sqlite*,const char*,int, |
︙ | ︙ | |||
1217 1218 1219 1220 1221 1222 1223 | IdList *sqlite3IdListAppend(IdList*, Token*); int sqlite3IdListIndex(IdList*,const char*); SrcList *sqlite3SrcListAppend(SrcList*, Token*, Token*); void sqlite3SrcListAddAlias(SrcList*, Token*); void sqlite3SrcListAssignCursors(Parse*, SrcList*); void sqlite3IdListDelete(IdList*); void sqlite3SrcListDelete(SrcList*); | | | 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 | IdList *sqlite3IdListAppend(IdList*, Token*); int sqlite3IdListIndex(IdList*,const char*); SrcList *sqlite3SrcListAppend(SrcList*, Token*, Token*); void sqlite3SrcListAddAlias(SrcList*, Token*); void sqlite3SrcListAssignCursors(Parse*, SrcList*); void sqlite3IdListDelete(IdList*); void sqlite3SrcListDelete(SrcList*); void sqlite3CreateIndex(Parse*,Token*,Token*,Token*,IdList*,int,Token*,Token*); void sqlite3DropIndex(Parse*, SrcList*); void sqlite3AddKeyType(Vdbe*, ExprList*); void sqlite3AddIdxKeyType(Vdbe*, Index*); int sqlite3Select(Parse*, Select*, int, int, Select*, int, int*, char *aff); Select *sqlite3SelectNew(ExprList*,SrcList*,Expr*,ExprList*,Expr*,ExprList*, int,int,int); void sqlite3SelectDelete(Select*); |
︙ | ︙ | |||
1280 1281 1282 1283 1284 1285 1286 | Select *sqlite3SelectDup(Select*); FuncDef *sqlite3FindFunction(sqlite*,const char*,int,int,int); void sqlite3RegisterBuiltinFunctions(sqlite*); void sqlite3RegisterDateTimeFunctions(sqlite*); int sqlite3SafetyOn(sqlite*); int sqlite3SafetyOff(sqlite*); int sqlite3SafetyCheck(sqlite*); | | | 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 | Select *sqlite3SelectDup(Select*); FuncDef *sqlite3FindFunction(sqlite*,const char*,int,int,int); void sqlite3RegisterBuiltinFunctions(sqlite*); void sqlite3RegisterDateTimeFunctions(sqlite*); int sqlite3SafetyOn(sqlite*); int sqlite3SafetyOff(sqlite*); int sqlite3SafetyCheck(sqlite*); void sqlite3ChangeCookie(sqlite*, Vdbe*, int); void sqlite3BeginTrigger(Parse*, Token*,int,int,IdList*,SrcList*,int,Expr*,int); void sqlite3FinishTrigger(Parse*, TriggerStep*, Token*); void sqlite3DropTrigger(Parse*, SrcList*); void sqlite3DropTriggerPtr(Parse*, Trigger*, int); int sqlite3TriggersExist(Parse* , Trigger* , int , int , int, ExprList*); int sqlite3CodeRowTrigger(Parse*, int, ExprList*, int, Table *, int, int, int, int); |
︙ | ︙ | |||
1346 1347 1348 1349 1350 1351 1352 | char const *sqlite3AffinityString(char affinity); int sqlite3IndexAffinityOk(Expr *pExpr, char idx_affinity); char sqlite3ExprAffinity(Expr *pExpr); int sqlite3atoi64(const char*, i64*); void sqlite3Error(sqlite *, int, const char*,...); int sqlite3utfTranslate(const void *, int , u8 , void **, int *, u8); u8 sqlite3UtfReadBom(const void *zData, int nData); | | | 1346 1347 1348 1349 1350 1351 1352 1353 | char const *sqlite3AffinityString(char affinity); int sqlite3IndexAffinityOk(Expr *pExpr, char idx_affinity); char sqlite3ExprAffinity(Expr *pExpr); int sqlite3atoi64(const char*, i64*); void sqlite3Error(sqlite *, int, const char*,...); int sqlite3utfTranslate(const void *, int , u8 , void **, int *, u8); u8 sqlite3UtfReadBom(const void *zData, int nData); void *sqlite3HexToBlob(const char *z); |
Changes to src/trigger.c.
︙ | ︙ | |||
201 202 203 204 205 206 207 | sqlite3BeginWriteOperation(pParse, 0, 0); sqlite3OpenMasterTable(v, nt->iDb); addr = sqlite3VdbeAddOpList(v, ArraySize(insertTrig), insertTrig); sqlite3VdbeChangeP3(v, addr+2, nt->name, 0); sqlite3VdbeChangeP3(v, addr+3, nt->table, 0); sqlite3VdbeChangeP3(v, addr+5, pAll->z, pAll->n); if( nt->iDb==0 ){ | | | 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 | sqlite3BeginWriteOperation(pParse, 0, 0); sqlite3OpenMasterTable(v, nt->iDb); addr = sqlite3VdbeAddOpList(v, ArraySize(insertTrig), insertTrig); sqlite3VdbeChangeP3(v, addr+2, nt->name, 0); sqlite3VdbeChangeP3(v, addr+3, nt->table, 0); sqlite3VdbeChangeP3(v, addr+5, pAll->z, pAll->n); if( nt->iDb==0 ){ sqlite3ChangeCookie(db, v, 0); } sqlite3VdbeAddOp(v, OP_Close, 0, 0); sqlite3EndWriteOperation(pParse); } if( !pParse->explain ){ Table *pTab; |
︙ | ︙ | |||
463 464 465 466 467 468 469 | }; sqlite3BeginWriteOperation(pParse, 0, 0); sqlite3OpenMasterTable(v, pTrigger->iDb); base = sqlite3VdbeAddOpList(v, ArraySize(dropTrigger), dropTrigger); sqlite3VdbeChangeP3(v, base+1, pTrigger->name, 0); if( pTrigger->iDb==0 ){ | | | 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 | }; sqlite3BeginWriteOperation(pParse, 0, 0); sqlite3OpenMasterTable(v, pTrigger->iDb); base = sqlite3VdbeAddOpList(v, ArraySize(dropTrigger), dropTrigger); sqlite3VdbeChangeP3(v, base+1, pTrigger->name, 0); if( pTrigger->iDb==0 ){ sqlite3ChangeCookie(db, v, 0); } sqlite3VdbeAddOp(v, OP_Close, 0, 0); sqlite3EndWriteOperation(pParse); } /* * If this is not an "explain", then delete the trigger structure. |
︙ | ︙ |
Changes to src/util.c.
︙ | ︙ | |||
10 11 12 13 14 15 16 | ** ************************************************************************* ** Utility functions used throughout sqlite. ** ** This file contains functions for allocating memory, comparing ** strings, and stuff like that. ** | | | 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | ** ************************************************************************* ** Utility functions used throughout sqlite. ** ** This file contains functions for allocating memory, comparing ** strings, and stuff like that. ** ** $Id: util.c,v 1.93 2004/05/28 11:37:28 danielk1977 Exp $ */ #include "sqliteInt.h" #include <stdarg.h> #include <ctype.h> /* ** If malloc() ever fails, this global variable gets set to 1. |
︙ | ︙ | |||
1295 1296 1297 1298 1299 1300 1301 | do{ i++; v >>= 7; }while( v!=0 && i<9 ); return i; } | | | 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 | do{ i++; v >>= 7; }while( v!=0 && i<9 ); return i; } void *sqlite3HexToBlob(const char *z){ char *zBlob; int i; int n = strlen(z); if( n%2 ) return 0; zBlob = (char *)sqliteMalloc(n/2); |
︙ | ︙ |
Changes to src/vdbe.c.
︙ | ︙ | |||
39 40 41 42 43 44 45 | ** ** Various scripts scan this source file in order to generate HTML ** documentation, headers files, or other derived files. The formatting ** of the code in this file is, therefore, important. See other comments ** in this file for details. If in doubt, do not deviate from existing ** commenting and indentation practices when changing or adding code. ** | | | 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | ** ** Various scripts scan this source file in order to generate HTML ** documentation, headers files, or other derived files. The formatting ** of the code in this file is, therefore, important. See other comments ** in this file for details. If in doubt, do not deviate from existing ** commenting and indentation practices when changing or adding code. ** ** $Id: vdbe.c,v 1.344 2004/05/28 11:37:28 danielk1977 Exp $ */ #include "sqliteInt.h" #include "os.h" #include <ctype.h> #include "vdbeInt.h" /* |
︙ | ︙ | |||
689 690 691 692 693 694 695 696 697 698 699 | pTos->flags = MEM_Str|MEM_Static|MEM_Term; pTos->z = pOp->p3; pTos->n = strlen(pTos->z); pTos->enc = TEXT_Utf8; Realify(pTos, 0); break; } /* Opcode: String * * P3 ** ** The string value P3 is pushed onto the stack. If P3==0 then a | > > > > > > > > > > | > < > > > > > > > > > | > > > > | 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 | pTos->flags = MEM_Str|MEM_Static|MEM_Term; pTos->z = pOp->p3; pTos->n = strlen(pTos->z); pTos->enc = TEXT_Utf8; Realify(pTos, 0); break; } #if 0 /* Opcode: String8 * * P3 ** ** This opcode does not exist at vdbe execution time. */ case OP_String8: { break; } #endif /* Opcode: String * * P3 ** ** The string value P3 is pushed onto the stack. If P3==0 then a ** NULL is pushed onto the stack. P3 is assumed to be a nul terminated ** string encoded with the database native encoding. */ case OP_String: { pTos++; if( pOp->p3 ){ pTos->flags = MEM_Str|MEM_Static|MEM_Term; pTos->z = pOp->p3; pTos->n = strlen(pTos->z); pTos->enc = TEXT_Utf8; sqlite3VdbeChangeEncoding(pTos, db->enc); /* if( db->enc==TEXT_Utf8 ){ pTos->n = strlen(pTos->z); }else{ pTos->n = sqlite3utf16ByteLen(pTos->z, -1); } pTos->enc = db->enc; */ }else{ pTos->flags = MEM_Null; } break; } #if 0 /* Opcode: HexBlob * * P3 ** ** This opcode does not exist at vdbe execution time. */ case OP_HexBlob: { break; } #endif /* Opcode: Blob P1 * P3 ** ** P3 points to a blob of data P1 bytes long. Push this ** value onto the stack. This instruction is not coded directly ** by the compiler. Instead, the compiler layer specifies ** an OP_HexBlob opcode, with the hex string representation of ** the blob as P3. This opcode is transformed to an OP_Blob ** before execution (within the sqlite3_prepare() function). */ case OP_Blob: { pTos++; sqlite3VdbeMemSetStr(pTos, pOp->p3, pOp->p1, 0, 0); break; } |
︙ | ︙ |
Changes to src/vdbeaux.c.
︙ | ︙ | |||
606 607 608 609 610 611 612 | return rc; } /* ** If pOp is an OP_HexBlob opcode, then transform it to an OP_Blob ** opcode. */ | | > > > > > > > > > > > > > > > > > > > > > > > | 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 | return rc; } /* ** If pOp is an OP_HexBlob opcode, then transform it to an OP_Blob ** opcode. */ static int translateOp(Op *pOp, u8 enc){ if( pOp->opcode==OP_HexBlob ){ pOp->p1 = strlen(pOp->p3)/2; if( pOp->p1 ){ char *zBlob = sqlite3HexToBlob(pOp->p3); if( !zBlob ) return SQLITE_NOMEM; if( pOp->p3type==P3_DYNAMIC ){ sqliteFree(pOp->p3); } pOp->p3 = zBlob; pOp->p3type = P3_DYNAMIC; }else{ pOp->p3type = P3_STATIC; pOp->p3 = ""; } pOp->opcode = OP_Blob; } else if( pOp->opcode==OP_String8 ){ if( pOp->p3 ){ void *z = 0; switch( enc ){ case TEXT_Utf16be: z = sqlite3utf8to16be(pOp->p3, -1); if( !z ) return SQLITE_NOMEM; break; case TEXT_Utf16le: z = sqlite3utf8to16be(pOp->p3, -1); if( !z ) return SQLITE_NOMEM; break; } if( z ){ if( pOp->p3type==P3_DYNAMIC ) sqliteFree( pOp->p3 ); } } pOp->opcode = OP_String; } return SQLITE_OK; } /* ** Prepare a virtual machine for execution. This involves things such ** as allocating stack space and initializing the program counter. ** After the VDBE has be prepped, it can be executed by one or more |
︙ | ︙ | |||
700 701 702 703 704 705 706 | p->aOp[i].cycles = 0; } } #endif if( !isExplain ){ int i; for(i=0; i<p->nOp; i++){ | | | 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 | p->aOp[i].cycles = 0; } } #endif if( !isExplain ){ int i; for(i=0; i<p->nOp; i++){ translateOp(&p->aOp[i], p->db->enc); } } } /* ** Remove any elements that remain on the sorter for the VDBE given. |
︙ | ︙ |
Added test/attach3.test.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 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 | # 2003 July 1 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # This file implements regression tests for SQLite library. The # focus of this script is testing the ATTACH and DETACH commands # and schema changes to attached databases. # # $Id: attach3.test,v 1.1 2004/05/28 11:37:29 danielk1977 Exp $ # set testdir [file dirname $argv0] source $testdir/tester.tcl # Create tables t1 and t2 in the main database execsql { CREATE TABLE t1(a, b); CREATE TABLE t2(c, d); } # Create tables t1 and t2 in database file test2.db file delete -force test2.db sqlite db2 test2.db execsql { CREATE TABLE t1(a, b); CREATE TABLE t2(c, d); } db2 db2 close # Create a table in the auxilary database. do_test attach3-1 { execsql { ATTACH 'test2.db' AS aux; } } {} do_test attach3-2 { execsql { CREATE TABLE aux.t3(e, f); } } {} do_test attach3-3 { execsql { SELECT * FROM sqlite_master WHERE name = 't3'; } } {} do_test attach3-4 { execsql { SELECT * FROM aux.sqlite_master WHERE name = 't3'; } } {table t3 t3 4 {CREATE TABLE t3(e, f)}} do_test attach3-5 { execsql { INSERT INTO t3 VALUES(1, 2); SELECT * FROM t3; } } {1 2} # Create an index on the auxilary database table. do_test attach4-1 { execsql { CREATE INDEX aux.i1 on t3(e); } } {} execsql { pragma vdbe_trace = off; } do_test attach4-2 { execsql { SELECT * FROM sqlite_master WHERE name = 'i1'; } } {} do_test attach4-3 { execsql { SELECT * FROM aux.sqlite_master WHERE name = 'i1'; } } {index i1 t3 5 {CREATE INDEX i1 on t3(e)}} finish_test |
Changes to test/select1.test.
1 2 3 4 5 6 7 8 9 10 11 12 13 | # 2001 September 15 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # This file implements regression tests for SQLite library. The # focus of this file is testing the SELECT statement. # | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | # 2001 September 15 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # This file implements regression tests for SQLite library. The # focus of this file is testing the SELECT statement. # # $Id: select1.test,v 1.32 2004/05/28 11:37:29 danielk1977 Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl # Try to select on a non-existant table. # do_test select1-1.1 { |
︙ | ︙ | |||
531 532 533 534 535 536 537 | FROM test1 ORDER BY f1 } } {1 -3 1 -3} # Check the behavior when the result set is empty # | > > | | | | | | > | 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 | FROM test1 ORDER BY f1 } } {1 -3 1 -3} # Check the behavior when the result set is empty # # SQLite v3 always sets r(*). # # do_test select1-9.1 { # catch {unset r} # set r(*) {} # db eval {SELECT * FROM test1 WHERE f1<0} r {} # set r(*) # } {} do_test select1-9.2 { execsql {PRAGMA empty_result_callbacks=on} catch {unset r} set r(*) {} db eval {SELECT * FROM test1 WHERE f1<0} r {} set r(*) } {f1 f2} do_test select1-9.3 { set r(*) {} db eval {SELECT * FROM test1 WHERE f1<(select count(*) from test2)} r {} |
︙ | ︙ |
Changes to test/select2.test.
1 2 3 4 5 6 7 8 9 10 11 12 13 | # 2001 September 15 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # This file implements regression tests for SQLite library. The # focus of this file is testing the SELECT statement. # | | > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | # 2001 September 15 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # This file implements regression tests for SQLite library. The # focus of this file is testing the SELECT statement. # # $Id: select2.test,v 1.22 2004/05/28 11:37:29 danielk1977 Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl # Create a table with some data # execsql {CREATE TABLE tbl1(f1 int, f2 int)} execsql {BEGIN} for {set i 0} {$i<=30} {incr i} { execsql "INSERT INTO tbl1 VALUES([expr {$i%9}],[expr {$i%10}])" } execsql {COMMIT} # Do a second query inside a first. # do_test select2-1.1 { set sql {SELECT DISTINCT f1 FROM tbl1 ORDER BY f1} set r {} catch {unset data} db eval $sql data { set f1 $data(f1) lappend r $f1: set sql2 "SELECT f2 FROM tbl1 WHERE f1=$f1 ORDER BY f2" db eval $sql2 d2 { lappend r $d2(f2) } |
︙ | ︙ |