/ Check-in [6199f2f2]
Login

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

Overview
Comment:Protect Tcl_Obj pointers from change using Tcl_IncrRefCount() while executing SQL statements in the TCL bindings. (CVS 1903)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:6199f2f243514bbd4befbf768a7e03aec775bed2
User & Date: drh 2004-08-26 00:56:05
Context
2004-08-26
01:12
Update the TCL binding documentation to describe the newly added ability to specify TCL variable names in the body of an SQL statement. (CVS 1904) check-in: b3b9e581 user: drh tags: trunk
00:56
Protect Tcl_Obj pointers from change using Tcl_IncrRefCount() while executing SQL statements in the TCL bindings. (CVS 1903) check-in: 6199f2f2 user: drh tags: trunk
2004-08-25
04:07
Host parameter names conform to SQL-2003. (CVS 1902) check-in: fd584d1c user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/tclsqlite.c.

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
694
695
696
697
698
699
700



701
702
703
704
705
706
707
...
713
714
715
716
717
718
719

720
721
722
723
724
725
726
...
737
738
739
740
741
742
743
744
745






746
747
748
749
750
751
752
753
754
755
756
757


758
759
760
761
762
763
764
765
766
767
768


769
770
771
772
773
774
775
...
848
849
850
851
852
853
854








855
856
857
858
859
860
861
...
864
865
866
867
868
869
870

871
872
873
874
875
876
877
**    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.
**
*************************************************************************
** A TCL Interface to SQLite
**
** $Id: tclsqlite.c,v 1.102 2004/08/25 04:07:02 drh Exp $
*/
#ifndef NO_TCL     /* Omit this whole file if TCL is unavailable */

#include "sqliteInt.h"
#include "hash.h"
#include "tcl.h"
#include <stdlib.h>
................................................................................
  */
  case DB_EVAL: {
    char const *zSql;      /* Next SQL statement to execute */
    char const *zLeft;     /* What is left after first stmt in zSql */
    sqlite3_stmt *pStmt;   /* Compiled SQL statment */
    Tcl_Obj *pArray;       /* Name of array into which results are written */
    Tcl_Obj *pScript;      /* Script to run for each result set */




    Tcl_Obj *pRet = Tcl_NewObj();
    Tcl_IncrRefCount(pRet);

    if( objc<3 || objc>5 ){
      Tcl_WrongNumArgs(interp, 2, objv, "SQL ?ARRAY-NAME? ?SCRIPT?");
      return TCL_ERROR;
................................................................................
      pScript = objv[3];
    }else{
      pArray = objv[3];
      if( Tcl_GetString(pArray)[0]==0 ) pArray = 0;
      pScript = objv[4];
    }


    zSql = Tcl_GetStringFromObj(objv[2], 0);
    while( zSql[0] ){
      int i;      /* Loop counter */
      int nVar;   /* Number of wildcards in the SQL */
      int nCol;   /* Number of columns in the result set */
      Tcl_Obj **apColName = 0;   /* Array of column names */
  
................................................................................
          break;
        }else{
          zSql = zLeft;
          continue;
        }
      }

      /* Bind values to wildcards that begin with $ */  
      nVar = sqlite3_bind_parameter_count(pStmt);






      for(i=1; i<=nVar; i++){
        const char *zVar = sqlite3_bind_parameter_name(pStmt, i);
        if( zVar[0]=='$' || zVar[0]==':' ){
          Tcl_Obj *pVar = Tcl_GetVar2Ex(interp, &zVar[1], 0, 0);
          if( pVar ){
            int n;
            u8 *data;
            char *zType = pVar->typePtr ? pVar->typePtr->name : "";
            char c = zType[0];
            if( c=='b' && strcmp(zType,"bytearray")==0 ){
              data = Tcl_GetByteArrayFromObj(pVar, &n);
              sqlite3_bind_blob(pStmt, i, data, n, SQLITE_STATIC);


            }else if( (c=='b' && strcmp(zType,"boolean")==0) ||
                  (c=='i' && strcmp(zType,"int")==0) ){
              Tcl_GetIntFromObj(interp, pVar, &n);
              sqlite3_bind_int(pStmt, i, n);
            }else if( c=='d' && strcmp(zType,"double")==0 ){
              double r;
              Tcl_GetDoubleFromObj(interp, pVar, &r);
              sqlite3_bind_double(pStmt, i, r);
            }else{
              data = Tcl_GetStringFromObj(pVar, &n);
              sqlite3_bind_text(pStmt, i, data, n, SQLITE_STATIC);


            }
          }
        }
      }
   

      /* Compute column names */
................................................................................
      /* Free the column name objects */
      if( pScript ){
        for(i=0; i<nCol; i++){
          Tcl_DecrRefCount(apColName[i]);
        }
        Tcl_Free((char*)apColName);
      }









      /* Finalize the statement.  If the result code is SQLITE_SCHEMA, then
      ** try again to execute the same statement
      */
      if( SQLITE_SCHEMA==sqlite3_finalize(pStmt) ){
        continue;
      }
................................................................................
        Tcl_SetObjResult(interp, dbTextToObj(sqlite3_errmsg(pDb->db)));
        rc = TCL_ERROR;
        break;
      }

      zSql = zLeft;
    }


    if( rc==TCL_OK ){
      Tcl_SetObjResult(interp, pRet);
    }
    Tcl_DecrRefCount(pRet);

    break;







|







 







>
>
>







 







>







 







|

>
>
>
>
>
>












>
>











>
>







 







>
>
>
>
>
>
>
>







 







>







7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
...
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
...
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
...
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
...
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
**    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.
**
*************************************************************************
** A TCL Interface to SQLite
**
** $Id: tclsqlite.c,v 1.103 2004/08/26 00:56:05 drh Exp $
*/
#ifndef NO_TCL     /* Omit this whole file if TCL is unavailable */

#include "sqliteInt.h"
#include "hash.h"
#include "tcl.h"
#include <stdlib.h>
................................................................................
  */
  case DB_EVAL: {
    char const *zSql;      /* Next SQL statement to execute */
    char const *zLeft;     /* What is left after first stmt in zSql */
    sqlite3_stmt *pStmt;   /* Compiled SQL statment */
    Tcl_Obj *pArray;       /* Name of array into which results are written */
    Tcl_Obj *pScript;      /* Script to run for each result set */
    Tcl_Obj **apParm;      /* Parameters that need a Tcl_DecrRefCount() */
    int nParm;             /* Number of entries used in apParm[] */
    Tcl_Obj *aParm[10];    /* Static space for apParm[] in the common case */

    Tcl_Obj *pRet = Tcl_NewObj();
    Tcl_IncrRefCount(pRet);

    if( objc<3 || objc>5 ){
      Tcl_WrongNumArgs(interp, 2, objv, "SQL ?ARRAY-NAME? ?SCRIPT?");
      return TCL_ERROR;
................................................................................
      pScript = objv[3];
    }else{
      pArray = objv[3];
      if( Tcl_GetString(pArray)[0]==0 ) pArray = 0;
      pScript = objv[4];
    }

    Tcl_IncrRefCount(objv[2]);
    zSql = Tcl_GetStringFromObj(objv[2], 0);
    while( zSql[0] ){
      int i;      /* Loop counter */
      int nVar;   /* Number of wildcards in the SQL */
      int nCol;   /* Number of columns in the result set */
      Tcl_Obj **apColName = 0;   /* Array of column names */
  
................................................................................
          break;
        }else{
          zSql = zLeft;
          continue;
        }
      }

      /* Bind values to wildcards that begin with $ or : */  
      nVar = sqlite3_bind_parameter_count(pStmt);
      nParm = 0;
      if( nVar>sizeof(aParm)/sizeof(aParm[0]) ){
        apParm = (Tcl_Obj**)Tcl_Alloc(nVar*sizeof(apParm[0]));
      }else{
        apParm = aParm;
      }
      for(i=1; i<=nVar; i++){
        const char *zVar = sqlite3_bind_parameter_name(pStmt, i);
        if( zVar[0]=='$' || zVar[0]==':' ){
          Tcl_Obj *pVar = Tcl_GetVar2Ex(interp, &zVar[1], 0, 0);
          if( pVar ){
            int n;
            u8 *data;
            char *zType = pVar->typePtr ? pVar->typePtr->name : "";
            char c = zType[0];
            if( c=='b' && strcmp(zType,"bytearray")==0 ){
              data = Tcl_GetByteArrayFromObj(pVar, &n);
              sqlite3_bind_blob(pStmt, i, data, n, SQLITE_STATIC);
              Tcl_IncrRefCount(pVar);
              apParm[nParm++] = pVar;
            }else if( (c=='b' && strcmp(zType,"boolean")==0) ||
                  (c=='i' && strcmp(zType,"int")==0) ){
              Tcl_GetIntFromObj(interp, pVar, &n);
              sqlite3_bind_int(pStmt, i, n);
            }else if( c=='d' && strcmp(zType,"double")==0 ){
              double r;
              Tcl_GetDoubleFromObj(interp, pVar, &r);
              sqlite3_bind_double(pStmt, i, r);
            }else{
              data = Tcl_GetStringFromObj(pVar, &n);
              sqlite3_bind_text(pStmt, i, data, n, SQLITE_STATIC);
              Tcl_IncrRefCount(pVar);
              apParm[nParm++] = pVar;
            }
          }
        }
      }
   

      /* Compute column names */
................................................................................
      /* Free the column name objects */
      if( pScript ){
        for(i=0; i<nCol; i++){
          Tcl_DecrRefCount(apColName[i]);
        }
        Tcl_Free((char*)apColName);
      }

      /* Free the bound string and blob parameters */
      for(i=0; i<nParm; i++){
        Tcl_DecrRefCount(apParm[i]);
      }
      if( apParm!=aParm ){
        Tcl_Free((char*)apParm);
      }

      /* Finalize the statement.  If the result code is SQLITE_SCHEMA, then
      ** try again to execute the same statement
      */
      if( SQLITE_SCHEMA==sqlite3_finalize(pStmt) ){
        continue;
      }
................................................................................
        Tcl_SetObjResult(interp, dbTextToObj(sqlite3_errmsg(pDb->db)));
        rc = TCL_ERROR;
        break;
      }

      zSql = zLeft;
    }
    Tcl_DecrRefCount(objv[2]);

    if( rc==TCL_OK ){
      Tcl_SetObjResult(interp, pRet);
    }
    Tcl_DecrRefCount(pRet);

    break;