/ Check-in [ee9dffd9]
Login

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

Overview
Comment:Update sqlite3_column_decltype() to return NULL as the declartion type for an expression that is not a column reference. (CVS 1646)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:ee9dffd986621490af7bd45c7fe070bb7da8c357
User & Date: danielk1977 2004-06-21 07:36:32
Context
2004-06-21
08:18
Ensure sqlite3ErrorMsg() is used to report errors during compilation, sqlite3Error() during execution. Also remove unused param from sqlite3VdbeReset() and Finalize(). (CVS 1647) check-in: 7a33daef user: danielk1977 tags: trunk
07:36
Update sqlite3_column_decltype() to return NULL as the declartion type for an expression that is not a column reference. (CVS 1646) check-in: ee9dffd9 user: danielk1977 tags: trunk
06:50
Update sqlite3_changes() to match the documentation and add sqlite3_total_changes(). (CVS 1645) check-in: ae2f4a09 user: danielk1977 tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/expr.c.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
....
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains routines used for analyzing expressions and
** for generating VDBE code that evaluates expressions in SQLite.
**
** $Id: expr.c,v 1.145 2004/06/19 14:49:12 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

char const *sqlite3AffinityString(char affinity){
  switch( affinity ){
    case SQLITE_AFF_INTEGER: return "i";
................................................................................
      }
      break;
    }
  }
  return nErr;
}

/*
** Return one of the SQLITE_AFF_* affinity types that indicates the likely
** data type of the result of the given expression.
**
** Not every expression has a fixed type.  If the type cannot be determined
** at compile-time, then try to return the type affinity if the expression
** is a column.  Otherwise just return SQLITE_AFF_NONE.
**
** The sqlite3ExprResolveIds() and sqlite3ExprCheck() routines must have
** both been called on the expression before it is passed to this routine.
*/
int sqlite3ExprType(Expr *p){
  if( p==0 ) return SQLITE_AFF_NONE;
  while( p ) switch( p->op ){
    case TK_CONCAT:
    case TK_STRING:
    case TK_BLOB:
      return SQLITE_AFF_TEXT;

    case TK_AS:
      p = p->pLeft;
      break;

    case TK_VARIABLE:
    case TK_NULL:
      return SQLITE_AFF_NONE;

    case TK_SELECT:   /*** FIX ME ****/
    case TK_COLUMN:   /*** FIX ME ****/
    case TK_CASE:     /*** FIX ME ****/

    default:
      return SQLITE_AFF_NUMERIC;
  }
  return SQLITE_AFF_NONE;
}

/*
** Generate an instruction that will put the integer describe by
** text z[0..n-1] on the stack.
*/
static void codeInteger(Vdbe *v, const char *z, int n){
  int i;
  if( sqlite3GetInt32(z, &i) ){







|







 







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
....
1055
1056
1057
1058
1059
1060
1061





































1062
1063
1064
1065
1066
1067
1068
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains routines used for analyzing expressions and
** for generating VDBE code that evaluates expressions in SQLite.
**
** $Id: expr.c,v 1.146 2004/06/21 07:36:32 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

char const *sqlite3AffinityString(char affinity){
  switch( affinity ){
    case SQLITE_AFF_INTEGER: return "i";
................................................................................
      }
      break;
    }
  }
  return nErr;
}






































/*
** Generate an instruction that will put the integer describe by
** text z[0..n-1] on the stack.
*/
static void codeInteger(Vdbe *v, const char *z, int n){
  int i;
  if( sqlite3GetInt32(z, &i) ){

Changes to src/select.c.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
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
660
661
662
663
...
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle SELECT statements in SQLite.
**
** $Id: select.c,v 1.193 2004/06/19 14:49:12 drh Exp $
*/
#include "sqliteInt.h"


/*
** Allocate a new Select structure and return a pointer to that
** structure.
................................................................................
** If the declaration type is the exact datatype definition extracted from
** the original CREATE TABLE statement if the expression is a column.
** 
** The declaration type for an expression is either TEXT, NUMERIC or ANY.
** The declaration type for a ROWID field is INTEGER.
*/
static const char *columnType(Parse *pParse, SrcList *pTabList, Expr *pExpr){
  char const *zType = 0;
  int j;
  if( pExpr==0 ) return 0;

  if( pExpr->op==TK_COLUMN && pTabList ){

    Table *pTab;
    int iCol = pExpr->iColumn;
    for(j=0; j<pTabList->nSrc && pTabList->a[j].iCursor!=pExpr->iTable; j++){}
    assert( j<pTabList->nSrc );
    pTab = pTabList->a[j].pTab;
    if( iCol<0 ) iCol = pTab->iPKey;
    assert( iCol==-1 || (iCol>=0 && iCol<pTab->nCol) );
    if( iCol<0 ){
      zType = "INTEGER";
    }else{
      zType = pTab->aCol[iCol].zType;
      if( !zType ) zType = "";
    }
  }else{
    switch( sqlite3ExprType(pExpr) ){
      case SQLITE_AFF_TEXT:     zType = "TEXT";    break;

      case SQLITE_AFF_NUMERIC:  zType = "NUMERIC"; break;
      default:                  zType = "ANY";     break;





    }


  }

  return zType;
}

/*
** Generate code that will tell the VDBE the declaration types of columns
** in the result set.
*/
................................................................................
  ExprList *pEList    /* Expressions defining the result set */
){
  Vdbe *v = pParse->pVdbe;
  int i;
  for(i=0; i<pEList->nExpr; i++){
    Expr *p = pEList->a[i].pExpr;
    const char *zType = columnType(pParse, pTabList, p);
    if( p==0 ) continue;
    /* The vdbe must make it's own copy of the column-type, in case the 
    ** schema is reset before this virtual machine is deleted.
    */
    sqlite3VdbeSetColName(v, i+pEList->nExpr, zType, strlen(zType));
  }
}








|







 







|

|
>
|
>
|
|
|
|
|
|
|
|
|
|
|
<
|
<
|
<
>
|
|
>
>
>
>
>

>
>

>







 







|







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
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
660
661
662
663
664
665
666
667
668
669
670
671
...
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle SELECT statements in SQLite.
**
** $Id: select.c,v 1.194 2004/06/21 07:36:32 danielk1977 Exp $
*/
#include "sqliteInt.h"


/*
** Allocate a new Select structure and return a pointer to that
** structure.
................................................................................
** If the declaration type is the exact datatype definition extracted from
** the original CREATE TABLE statement if the expression is a column.
** 
** The declaration type for an expression is either TEXT, NUMERIC or ANY.
** The declaration type for a ROWID field is INTEGER.
*/
static const char *columnType(Parse *pParse, SrcList *pTabList, Expr *pExpr){
  char const *zType;
  int j;
  if( pExpr==0 || pTabList==0 ) return 0;

  switch( pExpr->op ){
    case TK_COLUMN: {
      Table *pTab;
      int iCol = pExpr->iColumn;
      for(j=0; j<pTabList->nSrc && pTabList->a[j].iCursor!=pExpr->iTable; j++){}
      assert( j<pTabList->nSrc );
      pTab = pTabList->a[j].pTab;
      if( iCol<0 ) iCol = pTab->iPKey;
      assert( iCol==-1 || (iCol>=0 && iCol<pTab->nCol) );
      if( iCol<0 ){
        zType = "INTEGER";
      }else{
        zType = pTab->aCol[iCol].zType;

      }

      break;

    }
    case TK_AS:
      zType = columnType(pParse, pTabList, pExpr->pLeft); 
      break;
    case TK_SELECT: {
      Select *pS = pExpr->pSelect;
      zType = columnType(pParse, pS->pSrc, pS->pEList->a[0].pExpr); 
      break;
    }
    default:
      zType = 0;
  }
  
  return zType;
}

/*
** Generate code that will tell the VDBE the declaration types of columns
** in the result set.
*/
................................................................................
  ExprList *pEList    /* Expressions defining the result set */
){
  Vdbe *v = pParse->pVdbe;
  int i;
  for(i=0; i<pEList->nExpr; i++){
    Expr *p = pEList->a[i].pExpr;
    const char *zType = columnType(pParse, pTabList, p);
    if( zType==0 ) continue;
    /* The vdbe must make it's own copy of the column-type, in case the 
    ** schema is reset before this virtual machine is deleted.
    */
    sqlite3VdbeSetColName(v, i+pEList->nExpr, zType, strlen(zType));
  }
}

Changes to src/sqliteInt.h.

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
....
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
**    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.296 2004/06/21 06:50:28 danielk1977 Exp $
*/
#include "config.h"
#include "sqlite3.h"
#include "hash.h"
#include "parse.h"
#include <stdio.h>
#include <stdlib.h>
................................................................................
Index *sqlite3FindIndex(sqlite*,const char*, const char*);
void sqlite3UnlinkAndDeleteIndex(sqlite*,Index*);
void sqlite3Vacuum(Parse*, Token*);
int sqlite3RunVacuum(char**, sqlite*);
int sqlite3GlobCompare(const unsigned char*,const unsigned char*);
char *sqlite3NameFromToken(Token*);
int sqlite3ExprCheck(Parse*, Expr*, int, int*);
int sqlite3ExprType(Expr*);
int sqlite3ExprCompare(Expr*, Expr*);
int sqliteFuncId(Token*);
int sqlite3ExprResolveIds(Parse*, SrcList*, ExprList*, Expr*);
int sqlite3ExprAnalyzeAggregates(Parse*, Expr*);
Vdbe *sqlite3GetVdbe(Parse*);
void sqlite3Randomness(int, void*);
void sqlite3RollbackAll(sqlite*);







|







 







<







7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
....
1279
1280
1281
1282
1283
1284
1285

1286
1287
1288
1289
1290
1291
1292
**    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.297 2004/06/21 07:36:32 danielk1977 Exp $
*/
#include "config.h"
#include "sqlite3.h"
#include "hash.h"
#include "parse.h"
#include <stdio.h>
#include <stdlib.h>
................................................................................
Index *sqlite3FindIndex(sqlite*,const char*, const char*);
void sqlite3UnlinkAndDeleteIndex(sqlite*,Index*);
void sqlite3Vacuum(Parse*, Token*);
int sqlite3RunVacuum(char**, sqlite*);
int sqlite3GlobCompare(const unsigned char*,const unsigned char*);
char *sqlite3NameFromToken(Token*);
int sqlite3ExprCheck(Parse*, Expr*, int, int*);

int sqlite3ExprCompare(Expr*, Expr*);
int sqliteFuncId(Token*);
int sqlite3ExprResolveIds(Parse*, SrcList*, ExprList*, Expr*);
int sqlite3ExprAnalyzeAggregates(Parse*, Expr*);
Vdbe *sqlite3GetVdbe(Parse*);
void sqlite3Randomness(int, void*);
void sqlite3RollbackAll(sqlite*);

Changes to test/capi2.test.

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
#    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 testing the callback-free C/C++ API.
#
# $Id: capi2.test,v 1.15 2004/06/21 06:50:29 danielk1977 Exp $
#

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

# proc sqlite_step {stmt N VALS COLS} {
#   upvar $VALS vals
................................................................................
  lappend rc $TAIL
} {0 {}}
do_test capi2-3.7 {
  list [sqlite3_step $VM] \
       [sqlite3_column_count $VM] \
       [get_row_values $VM] \
       [get_column_names $VM]
} {SQLITE_ROW 1 {{}} {5/0 NUMERIC}}
do_test capi2-3.8 {
  sqlite3_finalize $VM
} {SQLITE_OK}
do_test capi2-3.9 {
  execsql {CREATE UNIQUE INDEX i1 ON t1(a)}
  set VM [sqlite3_prepare $DB {INSERT INTO t1 VALUES(1,2,3)} -1 TAIL]
  set TAIL







|







 







|







7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
#    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 testing the callback-free C/C++ API.
#
# $Id: capi2.test,v 1.16 2004/06/21 07:36:33 danielk1977 Exp $
#

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

# proc sqlite_step {stmt N VALS COLS} {
#   upvar $VALS vals
................................................................................
  lappend rc $TAIL
} {0 {}}
do_test capi2-3.7 {
  list [sqlite3_step $VM] \
       [sqlite3_column_count $VM] \
       [get_row_values $VM] \
       [get_column_names $VM]
} {SQLITE_ROW 1 {{}} {5/0 {}}}
do_test capi2-3.8 {
  sqlite3_finalize $VM
} {SQLITE_OK}
do_test capi2-3.9 {
  execsql {CREATE UNIQUE INDEX i1 ON t1(a)}
  set VM [sqlite3_prepare $DB {INSERT INTO t1 VALUES(1,2,3)} -1 TAIL]
  set TAIL

Changes to test/table.test.

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
333
334
335
336
337
338
339




340
341
342
343
344
345
346
347
348
349
350
351
...
498
499
500
501
502
503
504













505


#    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 CREATE TABLE statement.
#
# $Id: table.test,v 1.27 2004/06/19 00:16:31 drh Exp $

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

# Create a basic table and verify it is added to sqlite_master
#
do_test table-1.1 {
................................................................................
} {1 2 3}
do_test table-8.3 {
  execsql2 {
    CREATE TABLE [t4'abc] AS SELECT count(*) as cnt, max(b+c) FROM [t3'xyz];
    SELECT * FROM [t4'abc];
  }
} {cnt 1 max(b+c) 5}




do_test table-8.3.1 {
  execsql {
    SELECT sql FROM sqlite_master WHERE name='t4''abc'
  }
} {{CREATE TABLE 't4''abc'(cnt NUMERIC,'max(b+c)' NUMERIC)}}
do_test table-8.4 {
  execsql2 {
    CREATE TEMPORARY TABLE t5 AS SELECT count(*) AS [y'all] FROM [t3'xyz];
    SELECT * FROM t5;
  }
} {y'all 1}
do_test table-8.5 {
................................................................................
do_test table-11.2 {
  execsql {
    SELECT typeof(a+b), typeof(a||b), typeof(c+d), typeof(c||d)
    FROM t7 LIMIT 1;
  }
} {null null null null}














finish_test









|







 







>
>
>
>




|







 







>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
...
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
#    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 CREATE TABLE statement.
#
# $Id: table.test,v 1.28 2004/06/21 07:36:33 danielk1977 Exp $

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

# Create a basic table and verify it is added to sqlite_master
#
do_test table-1.1 {
................................................................................
} {1 2 3}
do_test table-8.3 {
  execsql2 {
    CREATE TABLE [t4'abc] AS SELECT count(*) as cnt, max(b+c) FROM [t3'xyz];
    SELECT * FROM [t4'abc];
  }
} {cnt 1 max(b+c) 5}

# Update for v3: The declaration type of anything except a column is now a
# NULL pointer, so the created table has no column types. (Changed result
# from {{CREATE TABLE 't4''abc'(cnt NUMERIC,'max(b+c)' NUMERIC)}}).
do_test table-8.3.1 {
  execsql {
    SELECT sql FROM sqlite_master WHERE name='t4''abc'
  }
} {{CREATE TABLE 't4''abc'(cnt,'max(b+c)')}}
do_test table-8.4 {
  execsql2 {
    CREATE TEMPORARY TABLE t5 AS SELECT count(*) AS [y'all] FROM [t3'xyz];
    SELECT * FROM t5;
  }
} {y'all 1}
do_test table-8.5 {
................................................................................
do_test table-11.2 {
  execsql {
    SELECT typeof(a+b), typeof(a||b), typeof(c+d), typeof(c||d)
    FROM t7 LIMIT 1;
  }
} {null null null null}

# Test that when creating a table using CREATE TABLE AS, column types are
# assigned correctly for (SELECT ...) and 'x AS y' expressions.
do_test table-12.1 {
  execsql {
    CREATE TABLE t8 AS SELECT b, h, a as i, (SELECT f FROM t7) as j FROM t7;
  }
} {}
do_test table-12.2 {
  execsql {
    SELECT sql FROM sqlite_master WHERE tbl_name = 't8'
  }
} {{CREATE TABLE t8(b number(5,10),h,i integer,j BLOB)}}

finish_test