SQLite

Check-in [6e98373ca1]
Login

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

Overview
Comment:For infix functions (LIKE, GLOB, REGEXP, and MATCH) treat the left operand as the first argument for the purposes of virtual table function overloading, even though the left operand is really the the second argument. (CVS 3324)
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 6e98373ca11c9d476f4c6b1841c6e006b7a49f29
User & Date: drh 2006-07-08 18:35:00.000
Context
2006-07-08
18:41
Better comment to describe the confusing operand reversal for infix functions. (CVS 3325) (check-in: 30dfb9bf21 user: drh tags: trunk)
18:35
For infix functions (LIKE, GLOB, REGEXP, and MATCH) treat the left operand as the first argument for the purposes of virtual table function overloading, even though the left operand is really the the second argument. (CVS 3324) (check-in: 6e98373ca1 user: drh tags: trunk)
18:09
Add tests and minor fixes to the xFindFunction method of virtual tables. (CVS 3323) (check-in: 3c4233e074 user: drh tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/expr.c.
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
**    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.263 2006/07/08 17:06:44 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

/*
** Return the 'affinity' of the expression pExpr if any.
**







|







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
**    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.264 2006/07/08 18:35:00 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

/*
** Return the 'affinity' of the expression pExpr if any.
**
1671
1672
1673
1674
1675
1676
1677







1678


1679
1680
1681
1682
1683
1684
1685
      CollSeq *pColl = 0;
      zId = (char*)pExpr->token.z;
      nId = pExpr->token.n;
      pDef = sqlite3FindFunction(pParse->db, zId, nId, nExpr, enc, 0);
      assert( pDef!=0 );
      nExpr = sqlite3ExprCodeExprList(pParse, pList);
#ifndef SQLITE_OMIT_VIRTUALTABLE







      if( nExpr>0 ){


        pDef = sqlite3VtabOverloadFunction(pDef, nExpr, pList->a[0].pExpr);
      }
#endif
      for(i=0; i<nExpr && i<32; i++){
        if( sqlite3ExprIsConstant(pList->a[i].pExpr) ){
          constMask |= (1<<i);
        }







>
>
>
>
>
>
>
|
>
>







1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
      CollSeq *pColl = 0;
      zId = (char*)pExpr->token.z;
      nId = pExpr->token.n;
      pDef = sqlite3FindFunction(pParse->db, zId, nId, nExpr, enc, 0);
      assert( pDef!=0 );
      nExpr = sqlite3ExprCodeExprList(pParse, pList);
#ifndef SQLITE_OMIT_VIRTUALTABLE
      if( nExpr>=2 && (pExpr->flags & EP_InfixFunc) ){
        /* For infix functions GLOB, LIKE, REGEXP, and MATCH, check
        ** the second argument to the function which is operand to
        ** left of the function name.  Users normally consider the
        ** left operand to be the first argument, even though it is
        ** really the second argument to the underlying function. */
        pDef = sqlite3VtabOverloadFunction(pDef, nExpr, pList->a[1].pExpr);
      }else if( nExpr>0 ){
        /* For normal functions, go by the first argument - the first
        ** argument after the "(" that follows the function name */
        pDef = sqlite3VtabOverloadFunction(pDef, nExpr, pList->a[0].pExpr);
      }
#endif
      for(i=0; i<nExpr && i<32; i++){
        if( sqlite3ExprIsConstant(pList->a[i].pExpr) ){
          constMask |= (1<<i);
        }
Changes to src/parse.y.
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.204 2006/06/16 08:01:04 danielk1977 Exp $
*/

// All token codes are small integers with #defines that begin with "TK_"
%token_prefix TK_

// The type of the data attached to each token is Token.  This is also the
// default type for non-terminals.







|







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.205 2006/07/08 18:35:00 drh Exp $
*/

// All token codes are small integers with #defines that begin with "TK_"
%token_prefix TK_

// The type of the data attached to each token is Token.  This is also the
// default type for non-terminals.
702
703
704
705
706
707
708

709
710
711
712
713
714
715
  pList = sqlite3ExprListAppend(pList, X, 0);
  if( E ){
    pList = sqlite3ExprListAppend(pList, E, 0);
  }
  A = sqlite3ExprFunction(pList, &OP.eOperator);
  if( OP.not ) A = sqlite3Expr(TK_NOT, A, 0, 0);
  sqlite3ExprSpan(A, &X->span, &Y->span);

}

expr(A) ::= expr(X) ISNULL|NOTNULL(E). {
  A = sqlite3Expr(@E, X, 0, 0);
  sqlite3ExprSpan(A,&X->span,&E);
}
expr(A) ::= expr(X) IS NULL(E). {







>







702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
  pList = sqlite3ExprListAppend(pList, X, 0);
  if( E ){
    pList = sqlite3ExprListAppend(pList, E, 0);
  }
  A = sqlite3ExprFunction(pList, &OP.eOperator);
  if( OP.not ) A = sqlite3Expr(TK_NOT, A, 0, 0);
  sqlite3ExprSpan(A, &X->span, &Y->span);
  if( A ) A->flags |= EP_InfixFunc;
}

expr(A) ::= expr(X) ISNULL|NOTNULL(E). {
  A = sqlite3Expr(@E, X, 0, 0);
  sqlite3ExprSpan(A,&X->span,&E);
}
expr(A) ::= expr(X) IS NULL(E). {
Changes to src/sqliteInt.h.
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.518 2006/07/08 17:06:44 drh Exp $
*/
#ifndef _SQLITEINT_H_
#define _SQLITEINT_H_

/*
** Extra interface definitions for those who need them
*/













|







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.519 2006/07/08 18:35:00 drh Exp $
*/
#ifndef _SQLITEINT_H_
#define _SQLITEINT_H_

/*
** Extra interface definitions for those who need them
*/
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
** If the Expr is of type OP_Column, and the table it is selecting from
** is a disk table or the "old.*" pseudo-table, then pTab points to the
** corresponding table definition.
*/
struct Expr {
  u8 op;                 /* Operation performed by this node */
  char affinity;         /* The affinity of the column or 0 if not a column */
  u8 flags;              /* Various flags.  See below */
  CollSeq *pColl;        /* The collation type of the column or 0 */
  Expr *pLeft, *pRight;  /* Left and right subnodes */
  ExprList *pList;       /* A list of expressions used as function arguments
                         ** or in "<expr> IN (<expr-list)" */
  Token token;           /* An operand token */
  Token span;            /* Complete text of the expression */
  int iTable, iColumn;   /* When op==TK_COLUMN, then this expr node means the







|







984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
** If the Expr is of type OP_Column, and the table it is selecting from
** is a disk table or the "old.*" pseudo-table, then pTab points to the
** corresponding table definition.
*/
struct Expr {
  u8 op;                 /* Operation performed by this node */
  char affinity;         /* The affinity of the column or 0 if not a column */
  u16 flags;             /* Various flags.  See below */
  CollSeq *pColl;        /* The collation type of the column or 0 */
  Expr *pLeft, *pRight;  /* Left and right subnodes */
  ExprList *pList;       /* A list of expressions used as function arguments
                         ** or in "<expr> IN (<expr-list)" */
  Token token;           /* An operand token */
  Token span;            /* Complete text of the expression */
  int iTable, iColumn;   /* When op==TK_COLUMN, then this expr node means the
1012
1013
1014
1015
1016
1017
1018

1019
1020
1021
1022
1023
1024
1025
#define EP_FromJoin     0x01  /* Originated in ON or USING clause of a join */
#define EP_Agg          0x02  /* Contains one or more aggregate functions */
#define EP_Resolved     0x04  /* IDs have been resolved to COLUMNs */
#define EP_Error        0x08  /* Expression contains one or more errors */
#define EP_Distinct     0x10  /* Aggregate function with DISTINCT keyword */
#define EP_VarSelect    0x20  /* pSelect is correlated, not constant */
#define EP_Dequoted     0x40  /* True if the string has been dequoted */


/*
** These macros can be used to test, set, or clear bits in the 
** Expr.flags field.
*/
#define ExprHasProperty(E,P)     (((E)->flags&(P))==(P))
#define ExprHasAnyProperty(E,P)  (((E)->flags&(P))!=0)







>







1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
#define EP_FromJoin     0x01  /* Originated in ON or USING clause of a join */
#define EP_Agg          0x02  /* Contains one or more aggregate functions */
#define EP_Resolved     0x04  /* IDs have been resolved to COLUMNs */
#define EP_Error        0x08  /* Expression contains one or more errors */
#define EP_Distinct     0x10  /* Aggregate function with DISTINCT keyword */
#define EP_VarSelect    0x20  /* pSelect is correlated, not constant */
#define EP_Dequoted     0x40  /* True if the string has been dequoted */
#define EP_InfixFunc    0x80  /* True for an infix function: LIKE, GLOB, etc */

/*
** These macros can be used to test, set, or clear bits in the 
** Expr.flags field.
*/
#define ExprHasProperty(E,P)     (((E)->flags&(P))==(P))
#define ExprHasAnyProperty(E,P)  (((E)->flags&(P))!=0)
Changes to test/vtab1.test.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 2006 June 10
#
# 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 creating and dropping virtual tables.
#
# $Id: vtab1.test,v 1.34 2006/07/08 18:09:15 drh Exp $

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

ifcapable !vtab||!schema_pragmas {
  finish_test
  return













|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 2006 June 10
#
# 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 creating and dropping virtual tables.
#
# $Id: vtab1.test,v 1.35 2006/07/08 18:35:00 drh Exp $

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

ifcapable !vtab||!schema_pragmas {
  finish_test
  return
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858



859




860


861
  }
} {1 0}
proc ::echo_glob_overload {a b} {
 return [list $b $a]
}
do_test vtab1.11-2 {
  execsql {
    SELECT a like b FROM e
  }
} {0 0}
do_test vtab1.11-3 {
  execsql {
    SELECT a glob b FROM e
  }
} {{1 ?} {2 3}}











finish_test







|




|

|
>
>
>
|
>
>
>
>
|
>
>

844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
  }
} {1 0}
proc ::echo_glob_overload {a b} {
 return [list $b $a]
}
do_test vtab1.11-2 {
  execsql {
    SELECT a like 'b' FROM e
  }
} {0 0}
do_test vtab1.11-3 {
  execsql {
    SELECT a glob '2' FROM e
  }
} {{1 2} {2 2}}
do_test vtab1.11-4 {
  execsql {
    SELECT  glob('2',a) FROM e
  }
} {0 1}
do_test vtab1.11-5 {
  execsql {
    SELECT  glob(a,'2') FROM e
  }
} {{2 1} {2 2}}

finish_test