Fossil

Check-in [f2ee33d4]
Login

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

Overview
Comment:Added query reset, refactored bind commands to accept their indexes in the same way as the col commands do (and expanded the remaining col commands which did not do so).
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | th1-query-api
Files: files | file ages | folders
SHA1: f2ee33d46085df6e2a6de35f6402e437f4bde7e3
User & Date: stephan 2012-07-15 15:28:11
Context
2012-07-15
17:33
Started adding infrastructure to allow us to expand the ob handler support to include more types. Added another th1 test script. check-in: 726f998b user: stephan tags: th1-query-api
15:28
Added query reset, refactored bind commands to accept their indexes in the same way as the col commands do (and expanded the remaining col commands which did not do so). check-in: f2ee33d4 user: stephan tags: th1-query-api
14:54
Made the query col argument ordering more flexible/forgiving. check-in: a561c439 user: stephan tags: th1-query-api
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/th_main.c.

1186
1187
1188
1189
1190
1191
1192


















1193
1194
1195
1196
1197
1198
1199
....
1203
1204
1205
1206
1207
1208
1209


1210
1211
1212
1213
1214

1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
....
1243
1244
1245
1246
1247
1248
1249


1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
....
1281
1282
1283
1284
1285
1286
1287


1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
....
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
....
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
....
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
1687
1688
1689
1690
1691
....
1709
1710
1711
1712
1713
1714
1715


1716
1717
1718
1719
1720
1721

1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732


1733
1734
1735
1736
1737
1738
1739
....
1749
1750
1751
1752
1753
1754
1755

1756
1757
1758
1759
1760
1761
1762
















1763

1764
1765
1766
1767
1768
1769
1770
....
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
....
1826
1827
1828
1829
1830
1831
1832

1833
1834
1835
1836
1837
1838
1839
....
1841
1842
1843
1844
1845
1846
1847

1848
1849
1850
1851
1852
1853
1854
      break;
    default:
      return queryReportDbErr( interp );
  }
  Th_SetResultInt( interp, rc );
  return TH_OK;
}



















/*
** TH Syntax:
**
** query col string stmtId Index
** query stmtId col string Index
** query stmtId col Index string
................................................................................
static int queryColStringCmd(
  Th_Interp *interp,
  void *p, 
  int argc, 
  const char **argv, 
  int *argl
){


  sqlite3_stmt * pStmt = (sqlite3_stmt*)p;
  int requireArgc = pStmt ? 2 : 3;
  char const * val;
  int index = -1;
  int valLen;

  if( argc!=requireArgc ){
    return Th_WrongNumArgs2(interp,
                            argv[0], argl[0],
                            "StmtHandle Index");
  }
  if(!pStmt){
    queryStmtIndexArgs(interp, argc, argv, argl, &pStmt, &index);
  }else{
    Th_ToInt(interp, argv[1], argl[1], &index);
  }
  if(index < 0){
    return TH_ERROR;
  }
  val = sqlite3_column_text( pStmt, index );
  valLen = val ? sqlite3_column_bytes( pStmt, index ) : 0;
................................................................................
static int queryColIntCmd(
  Th_Interp *interp,
  void *p, 
  int argc, 
  const char **argv, 
  int *argl
){


  sqlite3_stmt * pStmt = (sqlite3_stmt*)p;
  int requireArgc = pStmt ? 2 : 3;
  int rc = 0;
  int index = -1;
  if( argc!=requireArgc ){
    return Th_WrongNumArgs2(interp,
                            argv[0], argl[0],
                            "StmtHandle Index");
  }
  if(!pStmt){
    queryStmtIndexArgs(interp, argc, argv, argl, &pStmt, &index);
  }else{
    Th_ToInt(interp, argv[1], argl[1], &index);
  }
     
  if(index < 0){
    return TH_ERROR;
  }
  Th_SetResultInt( interp, sqlite3_column_int( pStmt, index ) );
  return TH_OK;
}

................................................................................
static int queryColDoubleCmd(
  Th_Interp *interp,
  void *p, 
  int argc, 
  const char **argv, 
  int *argl
){


  sqlite3_stmt * pStmt = (sqlite3_stmt*)p;
  int requireArgc = pStmt ? 2 : 3;
  double rc = 0;
  int index = -1;
  if( argc!=requireArgc ){
    return Th_WrongNumArgs2(interp,
                            argv[0], argl[0],
                            "StmtHandle Index");
  }
  if(!pStmt){
    queryStmtIndexArgs(interp, argc, argv, argl, &pStmt, &index);
  }else{
    Th_ToInt(interp, argv[1], argl[1], &index);
  }
  if(index < 0){
    return TH_ERROR;
  }
  Th_SetResultDouble( interp, sqlite3_column_double( pStmt, index ) );
  return TH_OK;
................................................................................
static int queryBindNullCmd(
  Th_Interp *interp,
  void *p, 
  int argc, 
  const char **argv, 
  int *argl
){


  sqlite3_stmt * pStmt = (sqlite3_stmt*)p;
  int requireArgc = pStmt ? 2 : 3;

  int rc;
  int index = 0;
  if( argc!=requireArgc ){
    return Th_WrongNumArgs2(interp,
                            argv[0], argl[0],
                            "StmtHandle Index");
  }
  if(!pStmt){
    queryStmtIndexArgs(interp, argc, argv, argl, &pStmt, &index);
  }else{
    Th_ToInt( interp, argv[1], argl[1], &index );
  }
  if(index < 1){
    return TH_ERROR;
  }
  rc = sqlite3_bind_null( pStmt, index );
  if(rc){
................................................................................
static int queryBindStringCmd(
  Th_Interp *interp,
  void *p, 
  int argc, 
  const char **argv, 
  int *argl
){


  sqlite3_stmt * pStmt = (sqlite3_stmt*)p;
  int requireArgc = pStmt ? 3 : 4;
  int rc;
  int index = 0;

  if( argc!=requireArgc ){
    return Th_WrongNumArgs2(interp,
                            argv[0], argl[0],
                            "StmtHandle Index Value");
  }
  if(!pStmt){
    queryStmtIndexArgs(interp, argc, argv, argl, &pStmt, &index);

  }else{
    Th_ToInt( interp, argv[1], argl[1], &index );



  }
  if(index < 1){
    return TH_ERROR;
  }
  rc = sqlite3_bind_text( pStmt, index, argv[3], argl[3], SQLITE_TRANSIENT );
  if(rc){
    return queryReportDbErr( interp );
  }
  Th_SetResultInt( interp, 0 );
  return TH_OK;
}

................................................................................
static int queryBindIntCmd(
  Th_Interp *interp,
  void *p, 
  int argc, 
  const char **argv, 
  int *argl
){


  sqlite3_stmt * pStmt = (sqlite3_stmt*)p;
  int requireArgc = pStmt ? 3 : 4;
  int rc;
  int index = 0;
  int argPos;
  int val;

  if( argc!=requireArgc ){
    return Th_WrongNumArgs2(interp,
                            argv[0], argl[0],
                            "StmtHandle Index Value");
  }
  if(!pStmt){
    queryStmtIndexArgs(interp, argc, argv, argl, &pStmt, &index);
    argPos = 3;
  }else{
    Th_ToInt( interp, argv[1], argl[1], &index );
    argPos = 2;


  }
  if(index < 1){
    return TH_ERROR;
  }
  if( 0 != Th_ToInt( interp, argv[argPos], argl[argPos], &val ) ){
    return TH_ERROR;
  }
................................................................................
static int queryBindDoubleCmd(
  Th_Interp *interp,
  void *p, 
  int argc, 
  const char **argv, 
  int *argl
){


  sqlite3_stmt * pStmt = (sqlite3_stmt*)p;
  int requireArgc = pStmt ? 3 : 4;
  int rc;
  int index = 0;
  int argPos;
  double val;

  if( argc!=requireArgc ){
    return Th_WrongNumArgs2(interp,
                            argv[0], argl[0],
                            "StmtHandle Index Value");
  }
  if(!pStmt){
    queryStmtIndexArgs(interp, argc, argv, argl, &pStmt, &index);
    argPos = 3;
  }else{
    Th_ToInt( interp, argv[1], argl[1], &index );
    argPos = 2;


  }
  if(index < 1){
    return TH_ERROR;
  }
  if( 0 != Th_ToDouble( interp, argv[argPos], argl[argPos], &val ) ){
    return TH_ERROR;
  }
................................................................................
static int queryBindTopLevelCmd(
  Th_Interp *interp,
  void *ctx, 
  int argc, 
  const char **argv, 
  int *argl
){

  static Th_SubCommand aSub[] = {
    {"int",    queryBindIntCmd},
    {"double", queryBindDoubleCmd},
    {"null",   queryBindNullCmd},
    {"string", queryBindStringCmd},
    {0, 0}
  };
















  Th_CallSubCommand2( interp, ctx, argc, argv, argl, aSub );

}

static int queryColTopLevelCmd(
  Th_Interp *interp,
  void *ctx, 
  int argc, 
  const char **argv, 
................................................................................
      return TH_ERROR;
    }
    ++argv;
    ++argl;
    --argc;
  }
  sq->colCmdIndex = colIndex;
  /* TODO: accept the index as the first param after "col", and make
     subcommands aware of sq->colCmdIndex.
  */
  Th_CallSubCommand2( interp, ctx, argc, argv, argl,
                      (colIndex<0) ? aSub : aSubWithIndex );
}


static int queryTopLevelCmd(
  Th_Interp *interp,
................................................................................
  int *argl
){
  int stmtId = 0;
  sqlite3_stmt * pStmt = NULL;
  static Th_SubCommand aSubAll[] = {
    {"bind",        queryBindTopLevelCmd},
    {"col",         queryColTopLevelCmd},

    {"step",        queryStepCmd},
    {"finalize",    queryFinalizeCmd},
    {"prepare",     queryPrepareCmd},
    {"strftime",    queryStrftimeCmd},
    {0, 0}
  };
  static Th_SubCommand aSubWithStmt[] = {
................................................................................
     being supplied a statement via pStmt
     or via one of their args.
   */
    {"bind",        queryBindTopLevelCmd},
    {"col",         queryColTopLevelCmd},
    {"step",        queryStepCmd},
    {"finalize",    queryFinalizeCmd},

    {0, 0}
  };


  assert( NULL != Th_sqlite_manager(interp) );
  if( 1 == argc ){
      Th_WrongNumArgs2( interp, argv[0], argl[0],







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







 







>
>



<

>







|







 







>
>



|







|


<







 







>
>



|







|







 







>
>


>

<







|







 







>
>



|
>







>
|

>
>
>




|







 







>
>



<


>








|


>
>







 







>
>



<


>








|


>
>







 







>







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

>







 







<
<
<







 







>







 







>







1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
....
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232

1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
....
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285

1286
1287
1288
1289
1290
1291
1292
....
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
....
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
....
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
....
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704

1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
....
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756

1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
....
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
....
1864
1865
1866
1867
1868
1869
1870



1871
1872
1873
1874
1875
1876
1877
....
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
....
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
      break;
    default:
      return queryReportDbErr( interp );
  }
  Th_SetResultInt( interp, rc );
  return TH_OK;
}

static int queryResetCmd(
  Th_Interp *interp,
  void *p, 
  int argc, 
  const char **argv, 
  int *argl
){
  sqlite3_stmt * pStmt = (sqlite3_stmt*)p;
  int const rc = sqlite3_reset(pStmt);
  if(rc){
    Th_ErrorMessage(interp, "Reset of statement failed.", NULL, 0);
    return TH_ERROR;
  }else{
    return TH_OK;
  }
}


/*
** TH Syntax:
**
** query col string stmtId Index
** query stmtId col string Index
** query stmtId col Index string
................................................................................
static int queryColStringCmd(
  Th_Interp *interp,
  void *p, 
  int argc, 
  const char **argv, 
  int *argl
){
  Th_Sqlite * sq = Th_sqlite_manager(interp);
  int index = sq->colCmdIndex;
  sqlite3_stmt * pStmt = (sqlite3_stmt*)p;
  int requireArgc = pStmt ? 2 : 3;
  char const * val;

  int valLen;
  if( index >= 0 ) --requireArgc;
  if( argc!=requireArgc ){
    return Th_WrongNumArgs2(interp,
                            argv[0], argl[0],
                            "StmtHandle Index");
  }
  if(!pStmt){
    queryStmtIndexArgs(interp, argc, argv, argl, &pStmt, &index);
  }else if(index<0){
    Th_ToInt(interp, argv[1], argl[1], &index);
  }
  if(index < 0){
    return TH_ERROR;
  }
  val = sqlite3_column_text( pStmt, index );
  valLen = val ? sqlite3_column_bytes( pStmt, index ) : 0;
................................................................................
static int queryColIntCmd(
  Th_Interp *interp,
  void *p, 
  int argc, 
  const char **argv, 
  int *argl
){
  Th_Sqlite * sq = Th_sqlite_manager(interp);
  int index = sq->colCmdIndex;
  sqlite3_stmt * pStmt = (sqlite3_stmt*)p;
  int requireArgc = pStmt ? 2 : 3;
  int rc = 0;
  if( index >= 0 ) --requireArgc;
  if( argc!=requireArgc ){
    return Th_WrongNumArgs2(interp,
                            argv[0], argl[0],
                            "StmtHandle Index");
  }
  if(!pStmt){
    queryStmtIndexArgs(interp, argc, argv, argl, &pStmt, &index);
  }else if(index<0){
    Th_ToInt(interp, argv[1], argl[1], &index);
  }

  if(index < 0){
    return TH_ERROR;
  }
  Th_SetResultInt( interp, sqlite3_column_int( pStmt, index ) );
  return TH_OK;
}

................................................................................
static int queryColDoubleCmd(
  Th_Interp *interp,
  void *p, 
  int argc, 
  const char **argv, 
  int *argl
){
  Th_Sqlite * sq = Th_sqlite_manager(interp);
  int index = sq->colCmdIndex;
  sqlite3_stmt * pStmt = (sqlite3_stmt*)p;
  int requireArgc = pStmt ? 2 : 3;
  double rc = 0;
  if( index >= 0 ) --requireArgc;
  if( argc!=requireArgc ){
    return Th_WrongNumArgs2(interp,
                            argv[0], argl[0],
                            "StmtHandle Index");
  }
  if(!pStmt){
    queryStmtIndexArgs(interp, argc, argv, argl, &pStmt, &index);
  }else if(index<0){
    Th_ToInt(interp, argv[1], argl[1], &index);
  }
  if(index < 0){
    return TH_ERROR;
  }
  Th_SetResultDouble( interp, sqlite3_column_double( pStmt, index ) );
  return TH_OK;
................................................................................
static int queryBindNullCmd(
  Th_Interp *interp,
  void *p, 
  int argc, 
  const char **argv, 
  int *argl
){
  Th_Sqlite * sq = Th_sqlite_manager(interp);
  int index = sq->colCmdIndex;
  sqlite3_stmt * pStmt = (sqlite3_stmt*)p;
  int requireArgc = pStmt ? 2 : 3;
  if( index > 0 ) --requireArgc;
  int rc;

  if( argc!=requireArgc ){
    return Th_WrongNumArgs2(interp,
                            argv[0], argl[0],
                            "StmtHandle Index");
  }
  if(!pStmt){
    queryStmtIndexArgs(interp, argc, argv, argl, &pStmt, &index);
  }else if(index<1){
    Th_ToInt( interp, argv[1], argl[1], &index );
  }
  if(index < 1){
    return TH_ERROR;
  }
  rc = sqlite3_bind_null( pStmt, index );
  if(rc){
................................................................................
static int queryBindStringCmd(
  Th_Interp *interp,
  void *p, 
  int argc, 
  const char **argv, 
  int *argl
){
  Th_Sqlite * sq = Th_sqlite_manager(interp);
  int index = sq->colCmdIndex;
  sqlite3_stmt * pStmt = (sqlite3_stmt*)p;
  int requireArgc = pStmt ? 3 : 4;
  int rc;
  int argPos;
  if( index > 0 ) --requireArgc;
  if( argc!=requireArgc ){
    return Th_WrongNumArgs2(interp,
                            argv[0], argl[0],
                            "StmtHandle Index Value");
  }
  if(!pStmt){
    queryStmtIndexArgs(interp, argc, argv, argl, &pStmt, &index);
    argPos = 3;
  }else if(index<1){
    Th_ToInt( interp, argv[1], argl[1], &index );
    argPos = 2;
  }else{
    argPos = 1;
  }
  if(index < 1){
    return TH_ERROR;
  }
  rc = sqlite3_bind_text( pStmt, index, argv[argPos], argl[argPos], SQLITE_TRANSIENT );
  if(rc){
    return queryReportDbErr( interp );
  }
  Th_SetResultInt( interp, 0 );
  return TH_OK;
}

................................................................................
static int queryBindIntCmd(
  Th_Interp *interp,
  void *p, 
  int argc, 
  const char **argv, 
  int *argl
){
  Th_Sqlite * sq = Th_sqlite_manager(interp);
  int index = sq->colCmdIndex;
  sqlite3_stmt * pStmt = (sqlite3_stmt*)p;
  int requireArgc = pStmt ? 3 : 4;
  int rc;

  int argPos;
  int val;
  if( index > 0 ) --requireArgc;
  if( argc!=requireArgc ){
    return Th_WrongNumArgs2(interp,
                            argv[0], argl[0],
                            "StmtHandle Index Value");
  }
  if(!pStmt){
    queryStmtIndexArgs(interp, argc, argv, argl, &pStmt, &index);
    argPos = 3;
  }else if(index<1){
    Th_ToInt( interp, argv[1], argl[1], &index );
    argPos = 2;
  }else{
    argPos = 1;
  }
  if(index < 1){
    return TH_ERROR;
  }
  if( 0 != Th_ToInt( interp, argv[argPos], argl[argPos], &val ) ){
    return TH_ERROR;
  }
................................................................................
static int queryBindDoubleCmd(
  Th_Interp *interp,
  void *p, 
  int argc, 
  const char **argv, 
  int *argl
){
  Th_Sqlite * sq = Th_sqlite_manager(interp);
  int index = sq->colCmdIndex;
  sqlite3_stmt * pStmt = (sqlite3_stmt*)p;
  int requireArgc = pStmt ? 3 : 4;
  int rc;

  int argPos;
  double val;
  if( index > 0 ) --requireArgc;
  if( argc!=requireArgc ){
    return Th_WrongNumArgs2(interp,
                            argv[0], argl[0],
                            "StmtHandle Index Value");
  }
  if(!pStmt){
    queryStmtIndexArgs(interp, argc, argv, argl, &pStmt, &index);
    argPos = 3;
  }else if(index<1){
    Th_ToInt( interp, argv[1], argl[1], &index );
    argPos = 2;
  }else{
    argPos = 1;
  }
  if(index < 1){
    return TH_ERROR;
  }
  if( 0 != Th_ToDouble( interp, argv[argPos], argl[argPos], &val ) ){
    return TH_ERROR;
  }
................................................................................
static int queryBindTopLevelCmd(
  Th_Interp *interp,
  void *ctx, 
  int argc, 
  const char **argv, 
  int *argl
){
  int colIndex = -1;
  static Th_SubCommand aSub[] = {
    {"int",    queryBindIntCmd},
    {"double", queryBindDoubleCmd},
    {"null",   queryBindNullCmd},
    {"string", queryBindStringCmd},
    {0, 0}
  };
  Th_Sqlite * sq = Th_sqlite_manager(interp);
  assert(NULL != sq);
  if( 1 == argc ){
      Th_WrongNumArgs2( interp, argv[0], argl[0],
                        "subcommand");
      return TH_ERROR;
  }else if( 0 == Th_TryInt(interp,argv[1], argl[1], &colIndex) ){
    if(colIndex <0){
      Th_ErrorMessage( interp, "Invalid column index.", NULL, 0);
      return TH_ERROR;
    }
    ++argv;
    ++argl;
    --argc;
  }
  sq->colCmdIndex = colIndex;
  Th_CallSubCommand2( interp, ctx, argc, argv, argl, aSub );

}

static int queryColTopLevelCmd(
  Th_Interp *interp,
  void *ctx, 
  int argc, 
  const char **argv, 
................................................................................
      return TH_ERROR;
    }
    ++argv;
    ++argl;
    --argc;
  }
  sq->colCmdIndex = colIndex;



  Th_CallSubCommand2( interp, ctx, argc, argv, argl,
                      (colIndex<0) ? aSub : aSubWithIndex );
}


static int queryTopLevelCmd(
  Th_Interp *interp,
................................................................................
  int *argl
){
  int stmtId = 0;
  sqlite3_stmt * pStmt = NULL;
  static Th_SubCommand aSubAll[] = {
    {"bind",        queryBindTopLevelCmd},
    {"col",         queryColTopLevelCmd},
    {"reset",       queryResetCmd},
    {"step",        queryStepCmd},
    {"finalize",    queryFinalizeCmd},
    {"prepare",     queryPrepareCmd},
    {"strftime",    queryStrftimeCmd},
    {0, 0}
  };
  static Th_SubCommand aSubWithStmt[] = {
................................................................................
     being supplied a statement via pStmt
     or via one of their args.
   */
    {"bind",        queryBindTopLevelCmd},
    {"col",         queryColTopLevelCmd},
    {"step",        queryStepCmd},
    {"finalize",    queryFinalizeCmd},
    {"reset",       queryResetCmd},
    {0, 0}
  };


  assert( NULL != Th_sqlite_manager(interp) );
  if( 1 == argc ){
      Th_WrongNumArgs2( interp, argv[0], argl[0],

Changes to test/th1-query-api-1.th1.

52
53
54
55
56
57
58
59



60
61

62
63
64
65
66
67
68
..
73
74
75
76
77
78
79


80
81
82

83
84
85



86
87
88
89
90
91
92
}

set sql {SELECT uid, login FROM user WHERE uid!=?}
#set sql {SELECT uid, login FROM user WHERE login=?}
#set sql {SELECT tagid, value, null FROM tagxref WHERE value IS ? LIMIT 3}
set stmt [query prepare $sql]
puts "stmt ID=" $stmt "\n"
query bind int $stmt 1 3



#set stmt [query prepare $sql]
#query bind string $stmt 1 stephan

#set stmt [query prepare $sql]
#query $stmt bind null 1
puts "USER LIST:\n"
catch {
    proc my_each {stmt colCount} {
        upvar 2 sep sep
        puts [query $stmt col int 0] " (type=" [query $stmt col type 0] ")" $sep
................................................................................
#        for {set i 0} {$i < $colCount} {incr i} {
#            if {$i > 0} { puts $sep }
#        }
        puts "\n"
#        error "hi!"
    }
    query_step_each $stmt my_each


#    query_step_each $stmt {
#        proc each {stmt cc} { puts hi "\n" }
#    }

} rc
query finalize $stmt
puts rc = $rc "\n"




set consts [list SQLITE_BLOB SQLITE_DONE SQLITE_ERROR SQLITE_FLOAT SQLITE_INTEGER SQLITE_NULL SQLITE_OK SQLITE_ROW SQLITE_TEXT]
#set consts $SQLITE_CONSTANTS
puts consts = $consts "\n"
for {set i 0} {$i < [llength $consts]} {incr i} {
    set x [lindex $consts $i]
    puts \$$x = [expr \$$x] "\n"







|
>
>
>

<
>







 







>
>



>


<
>
>
>







52
53
54
55
56
57
58
59
60
61
62
63

64
65
66
67
68
69
70
71
..
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90

91
92
93
94
95
96
97
98
99
100
}

set sql {SELECT uid, login FROM user WHERE uid!=?}
#set sql {SELECT uid, login FROM user WHERE login=?}
#set sql {SELECT tagid, value, null FROM tagxref WHERE value IS ? LIMIT 3}
set stmt [query prepare $sql]
puts "stmt ID=" $stmt "\n"
#query bind int $stmt 1 3
#query $stmt bind 1 int 3
query $stmt bind 1 string 3
#query $stmt bind string 1 3
#set stmt [query prepare $sql]

#query $stmt bind 1 string 1
#set stmt [query prepare $sql]
#query $stmt bind null 1
puts "USER LIST:\n"
catch {
    proc my_each {stmt colCount} {
        upvar 2 sep sep
        puts [query $stmt col int 0] " (type=" [query $stmt col type 0] ")" $sep
................................................................................
#        for {set i 0} {$i < $colCount} {incr i} {
#            if {$i > 0} { puts $sep }
#        }
        puts "\n"
#        error "hi!"
    }
    query_step_each $stmt my_each
#    query reset $stmt
#    query $stmt reset 
#    query_step_each $stmt {
#        proc each {stmt cc} { puts hi "\n" }
#    }
    return 0
} rc
query finalize $stmt

if { 0 != $rc } {
        puts "ERROR: $rc\n"
}

set consts [list SQLITE_BLOB SQLITE_DONE SQLITE_ERROR SQLITE_FLOAT SQLITE_INTEGER SQLITE_NULL SQLITE_OK SQLITE_ROW SQLITE_TEXT]
#set consts $SQLITE_CONSTANTS
puts consts = $consts "\n"
for {set i 0} {$i < [llength $consts]} {incr i} {
    set x [lindex $consts $i]
    puts \$$x = [expr \$$x] "\n"

Added test/th1-query-api-2.th1.













































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
<th1>
catch {
    set stmt [query prepare {
        SELECT login, cap, cexpire, mtime, NULL FROM user
        WHERE uid<? AND cexpire IS NOT NULL
        AND mtime IS NOT NULL
    }]
    puts "stmt ID=$stmt\n"
#    query bind int $stmt 1 2
#    query $stmt bind int 1 2
    query $stmt bind 1 int 2
# segfault:    query bind 1 int $stmt 2
    set sep "\n"
    for {} {0 < [query $stmt step]} {} {
        puts [query $stmt col string 0] $sep
        puts [query $stmt col time 2 {%Y%m%d @ %H:%M:%S}] $sep
        puts [query $stmt col time 2 {%Y%m%d @ %H:%M:%S} {+10 years}] $sep
        puts [query $stmt col 2 time {%Y%m%d @ %H:%M:%S} {+10 years}] $sep
#        puts [query col time $stmt 2 %s] $sep
        puts [query col time $stmt 3 %s unixepoch] $sep
#        puts [query strftime %s [query col string $stmt 3] unixepoch]
        puts [query strftime %s [query col string $stmt 3] unixepoch] $sep
        puts [query strftime {%Y%m%d @ %H:%M:%S} [query col string $stmt 2] {+10 years}] $sep
        puts "\n"
        puts "old isnull: " [query col isnull $stmt 4] "\n"

        puts "new old isnull: " [query col 4 isnull $stmt] "\n"
        puts "new isnull: " [query $stmt col isnull 4] "\n"
        puts "new new isnull: " [query $stmt col 4 isnull] "\n"

        puts "old col type: " [query col type $stmt 1] "\n"
        puts "new col type: " [query $stmt col type 1] "\n"
        puts "new new col type: " [query $stmt col 1 type] "\n"

        puts "old col name: " [query col name $stmt 1] "\n"
        puts "new col name: " [query $stmt col name 1] "\n"
        puts "new new col name: " [query $stmt col 1 name] "\n"

        puts "old col double: " [query col double $stmt 2] "\n"
        puts "new col double: " [query $stmt col double 2] "\n"
        puts "new new col double: " [query $stmt col 2 double] "\n"

        puts "old col int: " [query col int $stmt 2] "\n"
        puts "new col int: " [query $stmt col int 2] "\n"
        puts "new new col int: " [query $stmt col 2 int] "\n"

        puts "old col string: " [query col string $stmt 2] "\n"
        puts "new col string: " [query $stmt col string 2] "\n"
        puts "new new col string: " [query $stmt col 2 string] "\n"

        puts "\n"
    }

    puts "alt-form col count: " [query $stmt col count] "\n"
    query finalize $stmt
    return 0
} rc
if {0 != $rc} {
    puts "ERROR: $rc\n"
}
puts "Done!\n"


ob start
puts buffered
set x [ob get pop]
puts x=$x


</th1>

Changes to www/th1_query.wiki.

74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
..
98
99
100
101
102
103
104
105


106
107
108
109
110
111
112
...
151
152
153
154
155
156
157














<nowiki><pre>
for {} {0 &lt; [query $stmt step]} {} {
   puts [query $stmt col string 0] "\n"
}
</pre></nowiki>


<h2>strftime</h2>

This works like <tt>col time</tt> (described below) but takes its
value from an arbitrary source specified by the 3rd argument.

<nowiki><pre>
query strftime %s 1319211587 unixepoch
query strftime {%Y%m%d @ %H:%M:%S} [query $stmt col string 2] {+10 years}]
</pre></nowiki>


<h2>bind xxx</h2>

The <tt>bind xxx</tt> family of subcommands attach values to queries
before stepping through them. The subcommands include:
................................................................................
   *  <tt>bind double StmtId Index Value</tt>
   *  <tt>bind null StmtId Index</tt>
   *  <tt>bind string StmtId Index Value</tt>

Note that all of those optionally accept the statement handle directly after
the "query" command (before the "col" subcommand). e.g.
<tt>query bind null $stmt 1</tt> and
<tt>query $stmt bind null 1</tt> are equivalent.




Achtung: the bind API uses 1-based indexes, just like SQL does.

<nowiki><pre>
set stmt [query prepare "SELECT ... WHERE user=?"]
query $stmt bind int 1 drh
................................................................................

Any remaining arguments are treated as "modifiers" and passed as-is to strfmtime. For example:

<nowiki><pre>
query $stmt col time $index {%Y%m%d @ %H:%M:%S} {+5 years}
query $stmt col time $index %s unixepoch
</pre></nowiki>





















|

|
|


|
|







 







|
>
>







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
..
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
...
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
<nowiki><pre>
for {} {0 &lt; [query $stmt step]} {} {
   puts [query $stmt col string 0] "\n"
}
</pre></nowiki>


<h2>reset</h2>

Resets a query so that it can be executed again. This is only needed when
binding parameters in a loop - call it at the end of each loop iteration.

<nowiki><pre>
query $stmt reset
query reset $stmt
</pre></nowiki>


<h2>bind xxx</h2>

The <tt>bind xxx</tt> family of subcommands attach values to queries
before stepping through them. The subcommands include:
................................................................................
   *  <tt>bind double StmtId Index Value</tt>
   *  <tt>bind null StmtId Index</tt>
   *  <tt>bind string StmtId Index Value</tt>

Note that all of those optionally accept the statement handle directly after
the "query" command (before the "col" subcommand). e.g.
<tt>query bind null $stmt 1</tt> and
<tt>query $stmt bind null 1</tt> are equivalent. They also accept the column index
either before or after the type name, e.g.
<tt>query $stmt bind 1 string ...</tt> and <tt>query $stmt bind string 1 ...</tt> are equivalent.


Achtung: the bind API uses 1-based indexes, just like SQL does.

<nowiki><pre>
set stmt [query prepare "SELECT ... WHERE user=?"]
query $stmt bind int 1 drh
................................................................................

Any remaining arguments are treated as "modifiers" and passed as-is to strfmtime. For example:

<nowiki><pre>
query $stmt col time $index {%Y%m%d @ %H:%M:%S} {+5 years}
query $stmt col time $index %s unixepoch
</pre></nowiki>




<h2>strftime</h2>

This works like <tt>col time</tt> (described below) but takes its
value from an arbitrary source specified by the 3rd argument.

<nowiki><pre>
query strftime %s 1319211587 unixepoch
query strftime {%Y%m%d @ %H:%M:%S} [query $stmt col string 2] {+10 years}]
</pre></nowiki>