/ Check-in [ae301db8]
Login
SQLite training in Houston TX on 2019-11-05 (details)
Part of the 2019 Tcl Conference

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Add serial-types 8 and 9 for integer constants of 0 and 1 that use zero bytes of storage. Make the default file format 4. Add the SQLITE_DEFAULT_FILE_FORMAT compile-time option to lower the default file format number so that newly created databases can be read and written by older versions of SQLite. (CVS 2845)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: ae301db8a61a74bc72f67f5766811d89a3b3ec72
User & Date: drh 2005-12-29 19:23:07
Context
2005-12-29
23:04
Bug fix in codec processing. (CVS 2846) check-in: a88580bc user: drh tags: trunk
19:23
Add serial-types 8 and 9 for integer constants of 0 and 1 that use zero bytes of storage. Make the default file format 4. Add the SQLITE_DEFAULT_FILE_FORMAT compile-time option to lower the default file format number so that newly created databases can be read and written by older versions of SQLite. (CVS 2845) check-in: ae301db8 user: drh tags: trunk
12:53
Fix for ticket #1575. (CVS 2844) check-in: 1586921b user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Show Whitespace Changes Patch

Changes to src/build.c.

18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
...
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
....
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
....
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
....
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
....
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
**     CREATE INDEX
**     DROP INDEX
**     creating ID lists
**     BEGIN TRANSACTION
**     COMMIT
**     ROLLBACK
**
** $Id: build.c,v 1.362 2005/12/29 01:11:37 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

/*
** This routine is called when a new SQL statement is beginning to
** be parsed.  Initialize the pParse structure as needed.
................................................................................

    /* If the file format and encoding in the database have not been set, 
    ** set them now.
    */
    sqlite3VdbeAddOp(v, OP_ReadCookie, iDb, 1);   /* file_format */
    lbl = sqlite3VdbeMakeLabel(v);
    sqlite3VdbeAddOp(v, OP_If, 0, lbl);
    sqlite3VdbeAddOp(v, OP_Integer, 1, 0);   /* file format defaults to 1 */
    sqlite3VdbeAddOp(v, OP_SetCookie, iDb, 1);
    sqlite3VdbeAddOp(v, OP_Integer, db->enc, 0);
    sqlite3VdbeAddOp(v, OP_SetCookie, iDb, 4);
    sqlite3VdbeResolveLabel(v, lbl);

    /* This just creates a place-holder record in the sqlite_master table.
    ** The record created does not contain anything yet.  It will be replaced
................................................................................
  Index *pIndex = 0;   /* The index to be created */
  char *zName = 0;     /* Name of the index */
  int nName;           /* Number of characters in zName */
  int i, j;
  Token nullId;        /* Fake token for an empty ID list */
  DbFixer sFix;        /* For assigning database names to pTable */
  int sortOrderMask;   /* 1 to honor DESC in index.  0 to ignore. */
  int descSeen = 0;    /* Changes to true if a DESC is seen */
  sqlite3 *db = pParse->db;
  Db *pDb;             /* The specific table containing the indexed database */
  int iDb;             /* Index of the database that is being written */
  Token *pName = 0;    /* Unqualified name of the index to create */
  struct ExprList_item *pListItem; /* For looping over pList */

  if( pParse->nErr || sqlite3Tsd()->mallocFailed ) goto exit_create_index;
................................................................................
  pIndex->nColumn = pList->nExpr;
  pIndex->onError = onError;
  pIndex->autoIndex = pName==0;
  pIndex->iDb = iDb;

  /* Check to see if we should honor DESC requests on index columns
  */
  if( pDb->file_format>=4 || (!pDb->descIndex && !db->init.busy) ){
    sortOrderMask = -1;   /* Honor DESC */
  }else{
    sortOrderMask = 0;    /* Ignore DESC */
  }

  /* Scan the names of the columns of the table to be indexed and
  ** load the column indices into the Index structure.  Report an error
................................................................................
    }
    assert( pIndex->keyInfo.aColl[i] );
    if( !db->init.busy && 
        sqlite3CheckCollSeq(pParse, pIndex->keyInfo.aColl[i]) 
    ){
      goto exit_create_index;
    }
    requestedSortOrder = pListItem->sortOrder;
    pDb->descIndex |= requestedSortOrder;
    requestedSortOrder &= sortOrderMask;
    pIndex->keyInfo.aSortOrder[i] = requestedSortOrder;
    descSeen |= requestedSortOrder;
  }
  pIndex->keyInfo.nField = pList->nExpr;
  sqlite3DefaultRowEst(pIndex);

  if( pTab==pParse->pNewTable ){
    /* This routine has been called to create an automatic index as a
    ** result of a PRIMARY KEY or UNIQUE clause on a column definition, or
................................................................................

    /* Create the rootpage for the index
    */
    sqlite3BeginWriteOperation(pParse, 1, iDb);
    sqlite3VdbeAddOp(v, OP_CreateIndex, iDb, 0);
    sqlite3VdbeAddOp(v, OP_MemStore, iMem, 0);

    /* Make sure the file_format is at least 4 if we have DESC indices. */
    if( descSeen ){
      sqlite3MinimumFileFormat(pParse, iDb, 4);
    }

    /* Gather the complete text of the CREATE INDEX statement into
    ** the zStmt variable
    */
    if( pStart && pEnd ){
      /* A named index with an explicit CREATE INDEX statement */
      zStmt = sqlite3MPrintf("CREATE%s INDEX %.*s",
        onError==OE_None ? "" : " UNIQUE",







|







 







|







 







<







 







|







 







|
<
<

<







 







<
<
<
<
<







18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
...
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
....
2108
2109
2110
2111
2112
2113
2114

2115
2116
2117
2118
2119
2120
2121
....
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
....
2294
2295
2296
2297
2298
2299
2300
2301


2302

2303
2304
2305
2306
2307
2308
2309
....
2396
2397
2398
2399
2400
2401
2402





2403
2404
2405
2406
2407
2408
2409
**     CREATE INDEX
**     DROP INDEX
**     creating ID lists
**     BEGIN TRANSACTION
**     COMMIT
**     ROLLBACK
**
** $Id: build.c,v 1.363 2005/12/29 19:23:07 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

/*
** This routine is called when a new SQL statement is beginning to
** be parsed.  Initialize the pParse structure as needed.
................................................................................

    /* If the file format and encoding in the database have not been set, 
    ** set them now.
    */
    sqlite3VdbeAddOp(v, OP_ReadCookie, iDb, 1);   /* file_format */
    lbl = sqlite3VdbeMakeLabel(v);
    sqlite3VdbeAddOp(v, OP_If, 0, lbl);
    sqlite3VdbeAddOp(v, OP_Integer, SQLITE_DEFAULT_FILE_FORMAT, 0);
    sqlite3VdbeAddOp(v, OP_SetCookie, iDb, 1);
    sqlite3VdbeAddOp(v, OP_Integer, db->enc, 0);
    sqlite3VdbeAddOp(v, OP_SetCookie, iDb, 4);
    sqlite3VdbeResolveLabel(v, lbl);

    /* This just creates a place-holder record in the sqlite_master table.
    ** The record created does not contain anything yet.  It will be replaced
................................................................................
  Index *pIndex = 0;   /* The index to be created */
  char *zName = 0;     /* Name of the index */
  int nName;           /* Number of characters in zName */
  int i, j;
  Token nullId;        /* Fake token for an empty ID list */
  DbFixer sFix;        /* For assigning database names to pTable */
  int sortOrderMask;   /* 1 to honor DESC in index.  0 to ignore. */

  sqlite3 *db = pParse->db;
  Db *pDb;             /* The specific table containing the indexed database */
  int iDb;             /* Index of the database that is being written */
  Token *pName = 0;    /* Unqualified name of the index to create */
  struct ExprList_item *pListItem; /* For looping over pList */

  if( pParse->nErr || sqlite3Tsd()->mallocFailed ) goto exit_create_index;
................................................................................
  pIndex->nColumn = pList->nExpr;
  pIndex->onError = onError;
  pIndex->autoIndex = pName==0;
  pIndex->iDb = iDb;

  /* Check to see if we should honor DESC requests on index columns
  */
  if( pDb->file_format>=4 ){
    sortOrderMask = -1;   /* Honor DESC */
  }else{
    sortOrderMask = 0;    /* Ignore DESC */
  }

  /* Scan the names of the columns of the table to be indexed and
  ** load the column indices into the Index structure.  Report an error
................................................................................
    }
    assert( pIndex->keyInfo.aColl[i] );
    if( !db->init.busy && 
        sqlite3CheckCollSeq(pParse, pIndex->keyInfo.aColl[i]) 
    ){
      goto exit_create_index;
    }
    requestedSortOrder = pListItem->sortOrder & sortOrderMask;


    pIndex->keyInfo.aSortOrder[i] = requestedSortOrder;

  }
  pIndex->keyInfo.nField = pList->nExpr;
  sqlite3DefaultRowEst(pIndex);

  if( pTab==pParse->pNewTable ){
    /* This routine has been called to create an automatic index as a
    ** result of a PRIMARY KEY or UNIQUE clause on a column definition, or
................................................................................

    /* Create the rootpage for the index
    */
    sqlite3BeginWriteOperation(pParse, 1, iDb);
    sqlite3VdbeAddOp(v, OP_CreateIndex, iDb, 0);
    sqlite3VdbeAddOp(v, OP_MemStore, iMem, 0);






    /* Gather the complete text of the CREATE INDEX statement into
    ** the zStmt variable
    */
    if( pStart && pEnd ){
      /* A named index with an explicit CREATE INDEX statement */
      zStmt = sqlite3MPrintf("CREATE%s INDEX %.*s",
        onError==OE_None ? "" : " UNIQUE",

Changes to src/prepare.c.

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
...
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains the implementation of the sqlite3_prepare()
** interface, and routines that contribute to loading the database schema
** from disk.
**
** $Id: prepare.c,v 1.10 2005/12/16 01:06:17 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
#include <ctype.h>

/*
** Fill the InitData structure with an error message that indicates
................................................................................
  pDb->cache_size = size;
  sqlite3BtreeSetCacheSize(pDb->pBt, pDb->cache_size);

  /*
  ** file_format==1    Version 3.0.0.
  ** file_format==2    Version 3.1.3.  // ALTER TABLE ADD COLUMN
  ** file_format==3    Version 3.1.4.  // ditto but with non-NULL defaults
  ** file_format==4    Version 3.3.0.  // DESC indices
  */
  pDb->file_format = meta[1];
  if( pDb->file_format==0 ){
    pDb->file_format = 1;
  }
  if( pDb->file_format>4 ){
    sqlite3BtreeCloseCursor(curMain);
    sqlite3SetString(pzErrMsg, "unsupported file format", (char*)0);
    return SQLITE_ERROR;
  }


  /* Read the schema information out of the schema tables







|







 







|





|







9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
...
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains the implementation of the sqlite3_prepare()
** interface, and routines that contribute to loading the database schema
** from disk.
**
** $Id: prepare.c,v 1.11 2005/12/29 19:23:07 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
#include <ctype.h>

/*
** Fill the InitData structure with an error message that indicates
................................................................................
  pDb->cache_size = size;
  sqlite3BtreeSetCacheSize(pDb->pBt, pDb->cache_size);

  /*
  ** file_format==1    Version 3.0.0.
  ** file_format==2    Version 3.1.3.  // ALTER TABLE ADD COLUMN
  ** file_format==3    Version 3.1.4.  // ditto but with non-NULL defaults
  ** file_format==4    Version 3.3.0.  // DESC indices.  Boolean constants
  */
  pDb->file_format = meta[1];
  if( pDb->file_format==0 ){
    pDb->file_format = 1;
  }
  if( pDb->file_format>SQLITE_MAX_FILE_FORMAT ){
    sqlite3BtreeCloseCursor(curMain);
    sqlite3SetString(pzErrMsg, "unsupported file format", (char*)0);
    return SQLITE_ERROR;
  }


  /* Read the schema information out of the schema tables

Changes to src/sqliteInt.h.

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
136
137
138
139
140
141
142











143
144
145
146
147
148
149
...
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
**    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.443 2005/12/29 01:11:37 drh Exp $
*/
#ifndef _SQLITEINT_H_
#define _SQLITEINT_H_

/*
** Many people are failing to set -DNDEBUG=1 when compiling SQLite.
** Setting NDEBUG makes the code smaller and run faster.  So the following
................................................................................
#define MAX_ATTACHED 10

/*
** The maximum value of a ?nnn wildcard that the parser will accept.
*/
#define SQLITE_MAX_VARIABLE_NUMBER 999












/*
** Provide a default value for TEMP_STORE in case it is not specified
** on the command-line
*/
#ifndef TEMP_STORE
# define TEMP_STORE 1
#endif
................................................................................
  Hash idxHash;        /* All (named) indices indexed by name */
  Hash trigHash;       /* All triggers indexed by name */
  Hash aFKey;          /* Foreign keys indexed by to-table */
  u16 flags;           /* Flags associated with this database */
  u8 inTrans;          /* 0: not writable.  1: Transaction.  2: Checkpoint */
  u8 safety_level;     /* How aggressive at synching data to disk */
  u8 file_format;      /* Schema format version for this file */
  u8 descIndex;        /* True if any index uses the DESC attribute */
  int cache_size;      /* Number of pages to use in the cache */
  Table *pSeqTab;      /* The sqlite_sequence table used by AUTOINCREMENT */
  void *pAux;               /* Auxiliary data.  Usually NULL */
  void (*xFreeAux)(void*);  /* Routine to free pAux */
};

/*







|







 







>
>
>
>
>
>
>
>
>
>
>







 







<







7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
...
367
368
369
370
371
372
373

374
375
376
377
378
379
380
**    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.444 2005/12/29 19:23:07 drh Exp $
*/
#ifndef _SQLITEINT_H_
#define _SQLITEINT_H_

/*
** Many people are failing to set -DNDEBUG=1 when compiling SQLite.
** Setting NDEBUG makes the code smaller and run faster.  So the following
................................................................................
#define MAX_ATTACHED 10

/*
** The maximum value of a ?nnn wildcard that the parser will accept.
*/
#define SQLITE_MAX_VARIABLE_NUMBER 999

/*
** The "file format" number is an integer that is incremented whenever
** the VDBE-level file format changes.  The following macros define the
** the default file format for new databases and the maximum file format
** that the library can read.
*/
#define SQLITE_MAX_FILE_FORMAT 4
#ifndef SQLITE_DEFAULT_FILE_FORMAT
# define SQLITE_DEFAULT_FILE_FORMAT 4
#endif

/*
** Provide a default value for TEMP_STORE in case it is not specified
** on the command-line
*/
#ifndef TEMP_STORE
# define TEMP_STORE 1
#endif
................................................................................
  Hash idxHash;        /* All (named) indices indexed by name */
  Hash trigHash;       /* All triggers indexed by name */
  Hash aFKey;          /* Foreign keys indexed by to-table */
  u16 flags;           /* Flags associated with this database */
  u8 inTrans;          /* 0: not writable.  1: Transaction.  2: Checkpoint */
  u8 safety_level;     /* How aggressive at synching data to disk */
  u8 file_format;      /* Schema format version for this file */

  int cache_size;      /* Number of pages to use in the cache */
  Table *pSeqTab;      /* The sqlite_sequence table used by AUTOINCREMENT */
  void *pAux;               /* Auxiliary data.  Usually NULL */
  void (*xFreeAux)(void*);  /* Routine to free pAux */
};

/*

Changes to src/vdbe.c.

39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
....
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
....
2145
2146
2147
2148
2149
2150
2151

2152
2153
2154
2155
2156
2157
2158
2159
2160
2161

2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
....
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
....
2511
2512
2513
2514
2515
2516
2517

2518
2519
2520
2521
2522
2523
2524
2525

2526
2527







2528
2529
2530
2531
2532
2533
2534
**
** 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.508 2005/12/21 18:36:46 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
#include <ctype.h>
#include "vdbeInt.h"

/*
................................................................................
** The mapping from character to affinity is given by the SQLITE_AFF_
** macros defined in sqliteInt.h.
**
** If P3 is NULL then all index fields have the affinity NONE.
**
** See also OP_MakeIdxRec
*/
/* Opcode: MakeRecordI P1 P2 P3
**
** This opcode works just OP_MakeRecord except that it reads an extra
** integer from the stack (thus reading a total of abs(P1+1) entries)
** and appends that extra integer to the end of the record as a varint.
** This results in an index key.
*/
case OP_MakeIdxRec:
................................................................................
  Mem *pData0;

  int leaveOnStack;      /* If true, leave the entries on the stack */
  int nField;            /* Number of fields in the record */
  int jumpIfNull;        /* Jump here if non-zero and any entries are NULL. */
  int addRowid;          /* True to append a rowid column at the end */
  char *zAffinity;       /* The affinity string for the record */


  leaveOnStack = ((pOp->p1<0)?1:0);
  nField = pOp->p1 * (leaveOnStack?-1:1);
  jumpIfNull = pOp->p2;
  addRowid = pOp->opcode==OP_MakeIdxRec;
  zAffinity = pOp->p3;

  pData0 = &pTos[1-nField];
  assert( pData0>=p->aStack );
  containsNull = 0;


  /* Loop through the elements that will make up the record to figure
  ** out how much space is required for the new record.
  */
  for(pRec=pData0; pRec<=pTos; pRec++){
    if( zAffinity ){
      applyAffinity(pRec, zAffinity[pRec-pData0], db->enc);
    }
    if( pRec->flags&MEM_Null ){
      containsNull = 1;
    }
    serial_type = sqlite3VdbeSerialType(pRec);
    nData += sqlite3VdbeSerialTypeLen(serial_type);
    nHdr += sqlite3VarintLen(serial_type);
  }

  /* If we have to append a varint rowid to this record, set 'rowid'
  ** to the value of the rowid and increase nByte by the amount of space
  ** required to store it and the 0x00 seperator byte.
  */
  if( addRowid ){
    pRowid = &pTos[0-nField];
    assert( pRowid>=p->aStack );
    sqlite3VdbeMemIntegerify(pRowid);
    serial_type = sqlite3VdbeSerialType(pRowid);
    nData += sqlite3VdbeSerialTypeLen(serial_type);
    nHdr += sqlite3VarintLen(serial_type);
  }

  /* Add the initial header varint and total the size */
  nHdr += nVarint = sqlite3VarintLen(nHdr);
  if( nVarint<sqlite3VarintLen(nHdr) ){
................................................................................
    zNewRecord = (u8*)zTemp;
  }

  /* Write the record */
  zCsr = zNewRecord;
  zCsr += sqlite3PutVarint(zCsr, nHdr);
  for(pRec=pData0; pRec<=pTos; pRec++){
    serial_type = sqlite3VdbeSerialType(pRec);
    zCsr += sqlite3PutVarint(zCsr, serial_type);      /* serial type */
  }
  if( addRowid ){
    zCsr += sqlite3PutVarint(zCsr, sqlite3VdbeSerialType(pRowid));
  }
  for(pRec=pData0; pRec<=pTos; pRec++){
    zCsr += sqlite3VdbeSerialPut(zCsr, pRec);  /* serial data */
  }
  if( addRowid ){
    zCsr += sqlite3VdbeSerialPut(zCsr, pRowid);
  }
  assert( zCsr==(zNewRecord+nByte) );

  /* Pop entries off the stack if required. Push the new record on. */
  if( !leaveOnStack ){
    popStack(&pTos, nField+addRowid);
  }
................................................................................
case OP_OpenWrite: {       /* no-push */
  int i = pOp->p1;
  int p2 = pOp->p2;
  int wrFlag;
  Btree *pX;
  int iDb;
  Cursor *pCur;

  
  assert( pTos>=p->aStack );
  sqlite3VdbeMemIntegerify(pTos);
  iDb = pTos->i;
  assert( (pTos->flags & MEM_Dyn)==0 );
  pTos--;
  assert( iDb>=0 && iDb<db->nDb );
  pX = db->aDb[iDb].pBt;

  assert( pX!=0 );
  wrFlag = pOp->opcode==OP_OpenWrite;







  if( p2<=0 ){
    assert( pTos>=p->aStack );
    sqlite3VdbeMemIntegerify(pTos);
    p2 = pTos->i;
    assert( (pTos->flags & MEM_Dyn)==0 );
    pTos--;
    assert( p2>=2 );







|







 







|







 







>










>











|












|







 







|



|


|


|







 







>







|
>

|
>
>
>
>
>
>
>







39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
....
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
....
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
....
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
....
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
**
** 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.509 2005/12/29 19:23:07 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
#include <ctype.h>
#include "vdbeInt.h"

/*
................................................................................
** The mapping from character to affinity is given by the SQLITE_AFF_
** macros defined in sqliteInt.h.
**
** If P3 is NULL then all index fields have the affinity NONE.
**
** See also OP_MakeIdxRec
*/
/* Opcode: MakeIdxRec P1 P2 P3
**
** This opcode works just OP_MakeRecord except that it reads an extra
** integer from the stack (thus reading a total of abs(P1+1) entries)
** and appends that extra integer to the end of the record as a varint.
** This results in an index key.
*/
case OP_MakeIdxRec:
................................................................................
  Mem *pData0;

  int leaveOnStack;      /* If true, leave the entries on the stack */
  int nField;            /* Number of fields in the record */
  int jumpIfNull;        /* Jump here if non-zero and any entries are NULL. */
  int addRowid;          /* True to append a rowid column at the end */
  char *zAffinity;       /* The affinity string for the record */
  int file_format;       /* File format to use for encoding */

  leaveOnStack = ((pOp->p1<0)?1:0);
  nField = pOp->p1 * (leaveOnStack?-1:1);
  jumpIfNull = pOp->p2;
  addRowid = pOp->opcode==OP_MakeIdxRec;
  zAffinity = pOp->p3;

  pData0 = &pTos[1-nField];
  assert( pData0>=p->aStack );
  containsNull = 0;
  file_format = p->minWriteFileFormat;

  /* Loop through the elements that will make up the record to figure
  ** out how much space is required for the new record.
  */
  for(pRec=pData0; pRec<=pTos; pRec++){
    if( zAffinity ){
      applyAffinity(pRec, zAffinity[pRec-pData0], db->enc);
    }
    if( pRec->flags&MEM_Null ){
      containsNull = 1;
    }
    serial_type = sqlite3VdbeSerialType(pRec, file_format);
    nData += sqlite3VdbeSerialTypeLen(serial_type);
    nHdr += sqlite3VarintLen(serial_type);
  }

  /* If we have to append a varint rowid to this record, set 'rowid'
  ** to the value of the rowid and increase nByte by the amount of space
  ** required to store it and the 0x00 seperator byte.
  */
  if( addRowid ){
    pRowid = &pTos[0-nField];
    assert( pRowid>=p->aStack );
    sqlite3VdbeMemIntegerify(pRowid);
    serial_type = sqlite3VdbeSerialType(pRowid, 0);
    nData += sqlite3VdbeSerialTypeLen(serial_type);
    nHdr += sqlite3VarintLen(serial_type);
  }

  /* Add the initial header varint and total the size */
  nHdr += nVarint = sqlite3VarintLen(nHdr);
  if( nVarint<sqlite3VarintLen(nHdr) ){
................................................................................
    zNewRecord = (u8*)zTemp;
  }

  /* Write the record */
  zCsr = zNewRecord;
  zCsr += sqlite3PutVarint(zCsr, nHdr);
  for(pRec=pData0; pRec<=pTos; pRec++){
    serial_type = sqlite3VdbeSerialType(pRec, file_format);
    zCsr += sqlite3PutVarint(zCsr, serial_type);      /* serial type */
  }
  if( addRowid ){
    zCsr += sqlite3PutVarint(zCsr, sqlite3VdbeSerialType(pRowid, 0));
  }
  for(pRec=pData0; pRec<=pTos; pRec++){
    zCsr += sqlite3VdbeSerialPut(zCsr, pRec, file_format);  /* serial data */
  }
  if( addRowid ){
    zCsr += sqlite3VdbeSerialPut(zCsr, pRowid, 0);
  }
  assert( zCsr==(zNewRecord+nByte) );

  /* Pop entries off the stack if required. Push the new record on. */
  if( !leaveOnStack ){
    popStack(&pTos, nField+addRowid);
  }
................................................................................
case OP_OpenWrite: {       /* no-push */
  int i = pOp->p1;
  int p2 = pOp->p2;
  int wrFlag;
  Btree *pX;
  int iDb;
  Cursor *pCur;
  Db *pDb;
  
  assert( pTos>=p->aStack );
  sqlite3VdbeMemIntegerify(pTos);
  iDb = pTos->i;
  assert( (pTos->flags & MEM_Dyn)==0 );
  pTos--;
  assert( iDb>=0 && iDb<db->nDb );
  pDb = &db->aDb[iDb];
  pX = pDb->pBt;
  assert( pX!=0 );
  if( pOp->opcode==OP_OpenWrite ){
    wrFlag = 1;
    if( pDb->file_format < p->minWriteFileFormat ){
      p->minWriteFileFormat = pDb->file_format;
    }
  }else{
    wrFlag = 0;
  }
  if( p2<=0 ){
    assert( pTos>=p->aStack );
    sqlite3VdbeMemIntegerify(pTos);
    p2 = pTos->i;
    assert( (pTos->flags & MEM_Dyn)==0 );
    pTos--;
    assert( p2>=2 );

Changes to src/vdbeInt.h.

303
304
305
306
307
308
309

310
311
312
313
314
315
316
...
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
  int popStack;           /* Pop the stack this much on entry to VdbeExec() */
  char *zErrMsg;          /* Error message written here */
  u8 resOnStack;          /* True if there are result values on the stack */
  u8 explain;             /* True if EXPLAIN present on SQL command */
  u8 changeCntOn;         /* True to update the change-counter */
  u8 aborted;             /* True if ROLLBACK in another VM causes an abort */
  u8 expired;             /* True if the VM needs to be recompiled */

  int nChange;            /* Number of db changes made since last reset */
  i64 startTime;          /* Time when query started - used for profiling */
};

/*
** The following are allowed values for Vdbe.magic
*/
................................................................................
#if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE)
void sqlite3VdbePrintOp(FILE*, int, Op*);
#endif
#ifdef SQLITE_DEBUG
void sqlite3VdbePrintSql(Vdbe*);
#endif
int sqlite3VdbeSerialTypeLen(u32);
u32 sqlite3VdbeSerialType(Mem*);
int sqlite3VdbeSerialPut(unsigned char*, Mem*);
int sqlite3VdbeSerialGet(const unsigned char*, u32, Mem*);
void sqlite3VdbeDeleteAuxData(VdbeFunc*, int);

int sqlite2BtreeKeyCompare(BtCursor *, const void *, int, int, int *);
int sqlite3VdbeIdxKeyCompare(Cursor*, int , const unsigned char*, int*);
int sqlite3VdbeIdxRowid(BtCursor *, i64 *);
int sqlite3MemCompare(const Mem*, const Mem*, const CollSeq*);







>







 







|
|







303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
...
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
  int popStack;           /* Pop the stack this much on entry to VdbeExec() */
  char *zErrMsg;          /* Error message written here */
  u8 resOnStack;          /* True if there are result values on the stack */
  u8 explain;             /* True if EXPLAIN present on SQL command */
  u8 changeCntOn;         /* True to update the change-counter */
  u8 aborted;             /* True if ROLLBACK in another VM causes an abort */
  u8 expired;             /* True if the VM needs to be recompiled */
  u8 minWriteFileFormat;  /* Minimum file format for writable database files */
  int nChange;            /* Number of db changes made since last reset */
  i64 startTime;          /* Time when query started - used for profiling */
};

/*
** The following are allowed values for Vdbe.magic
*/
................................................................................
#if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE)
void sqlite3VdbePrintOp(FILE*, int, Op*);
#endif
#ifdef SQLITE_DEBUG
void sqlite3VdbePrintSql(Vdbe*);
#endif
int sqlite3VdbeSerialTypeLen(u32);
u32 sqlite3VdbeSerialType(Mem*, int);
int sqlite3VdbeSerialPut(unsigned char*, Mem*, int);
int sqlite3VdbeSerialGet(const unsigned char*, u32, Mem*);
void sqlite3VdbeDeleteAuxData(VdbeFunc*, int);

int sqlite2BtreeKeyCompare(BtCursor *, const void *, int, int, int *);
int sqlite3VdbeIdxKeyCompare(Cursor*, int , const unsigned char*, int*);
int sqlite3VdbeIdxRowid(BtCursor *, i64 *);
int sqlite3MemCompare(const Mem*, const Mem*, const CollSeq*);

Changes to src/vdbeaux.c.

778
779
780
781
782
783
784

785
786
787
788
789
790
791
....
1486
1487
1488
1489
1490
1491
1492
1493


1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511




1512
1513
1514
1515
1516
1517
1518
1519
....
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
....
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582




1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
....
1646
1647
1648
1649
1650
1651
1652






1653
1654
1655
1656
1657
1658
1659
  p->uniqueCnt = 0;
  p->returnDepth = 0;
  p->errorAction = OE_Abort;
  p->popStack =  0;
  p->explain |= isExplain;
  p->magic = VDBE_MAGIC_RUN;
  p->nChange = 0;

#ifdef VDBE_PROFILE
  {
    int i;
    for(i=0; i<p->nOp; i++){
      p->aOp[i].cnt = 0;
      p->aOp[i].cycles = 0;
    }
................................................................................
**      1                     1            signed integer
**      2                     2            signed integer
**      3                     3            signed integer
**      4                     4            signed integer
**      5                     6            signed integer
**      6                     8            signed integer
**      7                     8            IEEE float
**     8-11                                reserved for expansion


**    N>=12 and even       (N-12)/2        BLOB
**    N>=13 and odd        (N-13)/2        text
**
*/

/*
** Return the serial-type for the value stored in pMem.
*/
u32 sqlite3VdbeSerialType(Mem *pMem){
  int flags = pMem->flags;

  if( flags&MEM_Null ){
    return 0;
  }
  if( flags&MEM_Int ){
    /* Figure out whether to use 1, 2, 4, 6 or 8 bytes. */
#   define MAX_6BYTE ((((i64)0x00001000)<<32)-1)
    i64 i = pMem->i;




    u64 u = i<0 ? -i : i;
    if( u<=127 ) return 1;
    if( u<=32767 ) return 2;
    if( u<=8388607 ) return 3;
    if( u<=2147483647 ) return 4;
    if( u<=MAX_6BYTE ) return 5;
    return 6;
  }
................................................................................
}

/*
** Write the serialized data blob for the value stored in pMem into 
** buf. It is assumed that the caller has allocated sufficient space.
** Return the number of bytes written.
*/ 
int sqlite3VdbeSerialPut(unsigned char *buf, Mem *pMem){
  u32 serial_type = sqlite3VdbeSerialType(pMem);
  int len;

  /* NULL */
  if( serial_type==0 ){
    return 0;
  }
 
  /* Integer and Real */
  if( serial_type<=7 ){
    u64 v;
    int i;
    if( serial_type==7 ){
      v = *(u64*)&pMem->r;
    }else{
      v = *(u64*)&pMem->i;
    }
................................................................................
      buf[i] = (v&0xFF);
      v >>= 8;
    }
    return len;
  }
  
  /* String or blob */
  assert( serial_type>=12 );
  len = sqlite3VdbeSerialTypeLen(serial_type);
  memcpy(buf, pMem->z, len);
  return len;
}





/*
** Deserialize the data blob pointed to by buf as serial type serial_type
** and store the result in pMem.  Return the number of bytes read.
*/ 
int sqlite3VdbeSerialGet(
  const unsigned char *buf,     /* Buffer to deserialize from */
  u32 serial_type,              /* Serial type to deserialize */
  Mem *pMem                     /* Memory cell to write value into */
){
  switch( serial_type ){
    case 8:    /* Reserved for future use */
    case 9:    /* Reserved for future use */
    case 10:   /* Reserved for future use */
    case 11:   /* Reserved for future use */
    case 0: {  /* NULL */
      pMem->flags = MEM_Null;
      break;
    }
    case 1: { /* 1-byte signed integer */
................................................................................
        pMem->i = *(i64*)&x;
        pMem->flags = MEM_Int;
      }else{
        pMem->r = *(double*)&x;
        pMem->flags = MEM_Real;
      }
      return 8;






    }
    default: {
      int len = (serial_type-12)/2;
      pMem->z = (char *)buf;
      pMem->n = len;
      pMem->xDel = 0;
      if( serial_type&0x01 ){







>







 







|
>
>








|









>
>
>
>
|







 







|
|


<
<
<
<
<

|







 







|




>
>
>
>











<
<







 







>
>
>
>
>
>







778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
....
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
....
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561





1562
1563
1564
1565
1566
1567
1568
1569
1570
....
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599


1600
1601
1602
1603
1604
1605
1606
....
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
  p->uniqueCnt = 0;
  p->returnDepth = 0;
  p->errorAction = OE_Abort;
  p->popStack =  0;
  p->explain |= isExplain;
  p->magic = VDBE_MAGIC_RUN;
  p->nChange = 0;
  p->minWriteFileFormat = 255;
#ifdef VDBE_PROFILE
  {
    int i;
    for(i=0; i<p->nOp; i++){
      p->aOp[i].cnt = 0;
      p->aOp[i].cycles = 0;
    }
................................................................................
**      1                     1            signed integer
**      2                     2            signed integer
**      3                     3            signed integer
**      4                     4            signed integer
**      5                     6            signed integer
**      6                     8            signed integer
**      7                     8            IEEE float
**      8                     0            Integer constant 0
**      9                     0            Integer constant 1
**     10,11                               reserved for expansion
**    N>=12 and even       (N-12)/2        BLOB
**    N>=13 and odd        (N-13)/2        text
**
*/

/*
** Return the serial-type for the value stored in pMem.
*/
u32 sqlite3VdbeSerialType(Mem *pMem, int file_format){
  int flags = pMem->flags;

  if( flags&MEM_Null ){
    return 0;
  }
  if( flags&MEM_Int ){
    /* Figure out whether to use 1, 2, 4, 6 or 8 bytes. */
#   define MAX_6BYTE ((((i64)0x00001000)<<32)-1)
    i64 i = pMem->i;
    u64 u;
    if( file_format>=4 && (i&1)==i ){
      return 8+i;
    }
    u = i<0 ? -i : i;
    if( u<=127 ) return 1;
    if( u<=32767 ) return 2;
    if( u<=8388607 ) return 3;
    if( u<=2147483647 ) return 4;
    if( u<=MAX_6BYTE ) return 5;
    return 6;
  }
................................................................................
}

/*
** Write the serialized data blob for the value stored in pMem into 
** buf. It is assumed that the caller has allocated sufficient space.
** Return the number of bytes written.
*/ 
int sqlite3VdbeSerialPut(unsigned char *buf, Mem *pMem, int file_format){
  u32 serial_type = sqlite3VdbeSerialType(pMem, file_format);
  int len;






  /* Integer and Real */
  if( serial_type<=7 && serial_type>0 ){
    u64 v;
    int i;
    if( serial_type==7 ){
      v = *(u64*)&pMem->r;
    }else{
      v = *(u64*)&pMem->i;
    }
................................................................................
      buf[i] = (v&0xFF);
      v >>= 8;
    }
    return len;
  }

  /* String or blob */
  if( serial_type>=12 ){
    len = sqlite3VdbeSerialTypeLen(serial_type);
    memcpy(buf, pMem->z, len);
    return len;
  }

  /* NULL or constants 0 or 1 */
  return 0;
}

/*
** Deserialize the data blob pointed to by buf as serial type serial_type
** and store the result in pMem.  Return the number of bytes read.
*/ 
int sqlite3VdbeSerialGet(
  const unsigned char *buf,     /* Buffer to deserialize from */
  u32 serial_type,              /* Serial type to deserialize */
  Mem *pMem                     /* Memory cell to write value into */
){
  switch( serial_type ){


    case 10:   /* Reserved for future use */
    case 11:   /* Reserved for future use */
    case 0: {  /* NULL */
      pMem->flags = MEM_Null;
      break;
    }
    case 1: { /* 1-byte signed integer */
................................................................................
        pMem->i = *(i64*)&x;
        pMem->flags = MEM_Int;
      }else{
        pMem->r = *(double*)&x;
        pMem->flags = MEM_Real;
      }
      return 8;
    }
    case 8:    /* Integer 0 */
    case 9: {  /* Integer 1 */
      pMem->i = serial_type-8;
      pMem->flags = MEM_Int;
      return 0;
    }
    default: {
      int len = (serial_type-12)/2;
      pMem->z = (char *)buf;
      pMem->n = len;
      pMem->xDel = 0;
      if( serial_type&0x01 ){

Changes to test/descidx1.test.

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
..
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#    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 descending indices.
#
# $Id: descidx1.test,v 1.2 2005/12/21 18:36:46 drh Exp $
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# This procedure sets the value of the file-format in file 'test.db'
# to $newval. Also, the schema cookie is incremented.
................................................................................
proc get_file_format {{fname test.db}} {
  set bt [btree_open $fname 10 0]
  set meta [btree_get_meta $bt]
  btree_close $bt
  lindex $meta 2
}

# Verify that the file format jumps to (at least) 4 as soon as a
# descending index is created.
#
do_test descidx1-1.1 {
  execsql {
    CREATE TABLE t1(a,b);
    CREATE INDEX i1 ON t1(b ASC);
  }
  get_file_format
} {1}
do_test descidx1-1.2 {
  execsql {
    CREATE INDEX i2 ON t1(a DESC);
  }
  get_file_format
} {4}








|







 







|
<







|







7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
..
36
37
38
39
40
41
42
43

44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#    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 descending indices.
#
# $Id: descidx1.test,v 1.3 2005/12/29 19:23:07 drh Exp $
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# This procedure sets the value of the file-format in file 'test.db'
# to $newval. Also, the schema cookie is incremented.
................................................................................
proc get_file_format {{fname test.db}} {
  set bt [btree_open $fname 10 0]
  set meta [btree_get_meta $bt]
  btree_close $bt
  lindex $meta 2
}

# Verify that the file format starts as 4.

#
do_test descidx1-1.1 {
  execsql {
    CREATE TABLE t1(a,b);
    CREATE INDEX i1 ON t1(b ASC);
  }
  get_file_format
} {4}
do_test descidx1-1.2 {
  execsql {
    CREATE INDEX i2 ON t1(a DESC);
  }
  get_file_format
} {4}

Changes to test/descidx2.test.

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
..
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#    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 descending indices.
#
# $Id: descidx2.test,v 1.1 2005/12/21 18:36:46 drh Exp $
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# This procedure sets the value of the file-format in file 'test.db'
# to $newval. Also, the schema cookie is incremented.
................................................................................
proc get_file_format {{fname test.db}} {
  set bt [btree_open $fname 10 0]
  set meta [btree_get_meta $bt]
  btree_close $bt
  lindex $meta 2
}

# Verify that the file format jumps to (at least) 4 as soon as a
# descending index is created.
#
do_test descidx2-1.1 {
  execsql {
    CREATE TABLE t1(a,b);
    CREATE INDEX i1 ON t1(b ASC);
  }
  get_file_format
} {1}
do_test descidx2-1.2 {
  execsql {
    CREATE INDEX i2 ON t1(a DESC);
  }
  get_file_format
} {4}








|







 







|
<







|







7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
..
36
37
38
39
40
41
42
43

44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#    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 descending indices.
#
# $Id: descidx2.test,v 1.2 2005/12/29 19:23:07 drh Exp $
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# This procedure sets the value of the file-format in file 'test.db'
# to $newval. Also, the schema cookie is incremented.
................................................................................
proc get_file_format {{fname test.db}} {
  set bt [btree_open $fname 10 0]
  set meta [btree_get_meta $bt]
  btree_close $bt
  lindex $meta 2
}

# Verify that the file format starts as 4

#
do_test descidx2-1.1 {
  execsql {
    CREATE TABLE t1(a,b);
    CREATE INDEX i1 ON t1(b ASC);
  }
  get_file_format
} {4}
do_test descidx2-1.2 {
  execsql {
    CREATE INDEX i2 ON t1(a DESC);
  }
  get_file_format
} {4}

Changes to test/types.test.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
...
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library. Specfically
# it tests that the different storage classes (integer, real, text etc.)
# all work correctly.
#
# $Id: types.test,v 1.16 2005/11/14 22:29:06 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Tests in this file are organized roughly as follows:
#
# types-1.*.*: Test that values are stored using the expected storage
................................................................................
} [list 0 120 -120 30000 -30000 2100000000 -2100000000 \
        9000000000000000000 -9000000000000000000]

# Check that all the record sizes are as we expected.
do_test types-2.1.9 {
  set root [db eval {select rootpage from sqlite_master where name = 't1'}]
  record_sizes $root
} {3 3 3 4 4 6 6 10 10}

# Insert some reals. These should be 10 byte records.
do_test types-2.2.1 {
  execsql {
    CREATE TABLE t2(a float);
    INSERT INTO t2 VALUES(0.0);
    INSERT INTO t2 VALUES(12345.678);
................................................................................
  }
} {0.0 12345.678 -12345.678}

# Check that all the record sizes are as we expected.
do_test types-2.2.3 {
  set root [db eval {select rootpage from sqlite_master where name = 't2'}]
  record_sizes $root
} {3 10 10}

# Insert a NULL. This should be a two byte record.
do_test types-2.3.1 {
  execsql {
    CREATE TABLE t3(a nullvalue);
    INSERT INTO t3 VALUES(NULL);
  }







|







 







|







 







|







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
...
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library. Specfically
# it tests that the different storage classes (integer, real, text etc.)
# all work correctly.
#
# $Id: types.test,v 1.17 2005/12/29 19:23:07 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Tests in this file are organized roughly as follows:
#
# types-1.*.*: Test that values are stored using the expected storage
................................................................................
} [list 0 120 -120 30000 -30000 2100000000 -2100000000 \
        9000000000000000000 -9000000000000000000]

# Check that all the record sizes are as we expected.
do_test types-2.1.9 {
  set root [db eval {select rootpage from sqlite_master where name = 't1'}]
  record_sizes $root
} {2 3 3 4 4 6 6 10 10}

# Insert some reals. These should be 10 byte records.
do_test types-2.2.1 {
  execsql {
    CREATE TABLE t2(a float);
    INSERT INTO t2 VALUES(0.0);
    INSERT INTO t2 VALUES(12345.678);
................................................................................
  }
} {0.0 12345.678 -12345.678}

# Check that all the record sizes are as we expected.
do_test types-2.2.3 {
  set root [db eval {select rootpage from sqlite_master where name = 't2'}]
  record_sizes $root
} {2 10 10}

# Insert a NULL. This should be a two byte record.
do_test types-2.3.1 {
  execsql {
    CREATE TABLE t3(a nullvalue);
    INSERT INTO t3 VALUES(NULL);
  }