Fossil SCM
Made the query col argument ordering more flexible/forgiving.
Commit
a561c43919e549d05e840ce358efb29f059e7a81
Parent
09d7df15972dcf3…
2 files changed
+63
-12
+14
-1
+63
-12
| --- src/th_main.c | ||
| +++ src/th_main.c | ||
| @@ -874,10 +874,11 @@ | ||
| 874 | 874 | |
| 875 | 875 | |
| 876 | 876 | struct Th_Sqlite { |
| 877 | 877 | sqlite3_stmt ** aStmt; |
| 878 | 878 | int nStmt; |
| 879 | + int colCmdIndex; | |
| 879 | 880 | }; |
| 880 | 881 | #define Th_Sqlite_KEY "Th_Sqlite" |
| 881 | 882 | typedef struct Th_Sqlite Th_Sqlite; |
| 882 | 883 | |
| 883 | 884 | static Th_Sqlite * Th_sqlite_manager( Th_Interp * interp ){ |
| @@ -1193,10 +1194,11 @@ | ||
| 1193 | 1194 | /* |
| 1194 | 1195 | ** TH Syntax: |
| 1195 | 1196 | ** |
| 1196 | 1197 | ** query col string stmtId Index |
| 1197 | 1198 | ** query stmtId col string Index |
| 1199 | +** query stmtId col Index string | |
| 1198 | 1200 | ** |
| 1199 | 1201 | ** Returns the result column value at the given 0-based index. |
| 1200 | 1202 | */ |
| 1201 | 1203 | static int queryColStringCmd( |
| 1202 | 1204 | Th_Interp *interp, |
| @@ -1232,10 +1234,11 @@ | ||
| 1232 | 1234 | /* |
| 1233 | 1235 | ** TH Syntax: |
| 1234 | 1236 | ** |
| 1235 | 1237 | ** query col int stmtId Index |
| 1236 | 1238 | ** query stmtId col int Index |
| 1239 | +** query stmtId col Index int | |
| 1237 | 1240 | ** |
| 1238 | 1241 | ** Returns the result column value at the given 0-based index. |
| 1239 | 1242 | */ |
| 1240 | 1243 | static int queryColIntCmd( |
| 1241 | 1244 | Th_Interp *interp, |
| @@ -1269,10 +1272,11 @@ | ||
| 1269 | 1272 | /* |
| 1270 | 1273 | ** TH Syntax: |
| 1271 | 1274 | ** |
| 1272 | 1275 | ** query col double stmtId Index |
| 1273 | 1276 | ** query stmtId col double Index |
| 1277 | +** query stmtId col Index double | |
| 1274 | 1278 | ** |
| 1275 | 1279 | ** Returns the result column value at the given 0-based index. |
| 1276 | 1280 | */ |
| 1277 | 1281 | static int queryColDoubleCmd( |
| 1278 | 1282 | Th_Interp *interp, |
| @@ -1303,12 +1307,13 @@ | ||
| 1303 | 1307 | } |
| 1304 | 1308 | |
| 1305 | 1309 | /* |
| 1306 | 1310 | ** TH Syntax: |
| 1307 | 1311 | ** |
| 1308 | -** query col is_null stmtId Index | |
| 1312 | +** query col isnull stmtId Index | |
| 1309 | 1313 | ** query stmtId col is_null Index |
| 1314 | +** query stmtId col Index isnull | |
| 1310 | 1315 | ** |
| 1311 | 1316 | ** Returns non-0 if the given 0-based result column index contains |
| 1312 | 1317 | ** an SQL NULL value, else returns 0. |
| 1313 | 1318 | */ |
| 1314 | 1319 | static int queryColIsNullCmd( |
| @@ -1316,22 +1321,24 @@ | ||
| 1316 | 1321 | void *p, |
| 1317 | 1322 | int argc, |
| 1318 | 1323 | const char **argv, |
| 1319 | 1324 | int *argl |
| 1320 | 1325 | ){ |
| 1326 | + Th_Sqlite * sq = Th_sqlite_manager(interp); | |
| 1327 | + int index = sq->colCmdIndex; | |
| 1321 | 1328 | sqlite3_stmt * pStmt = (sqlite3_stmt*)p; |
| 1322 | 1329 | int requireArgc = pStmt ? 2 : 3; |
| 1330 | + if( index >= 0 ) --requireArgc; | |
| 1323 | 1331 | double rc = 0; |
| 1324 | - int index = -1; | |
| 1325 | 1332 | if( argc!=requireArgc ){ |
| 1326 | 1333 | return Th_WrongNumArgs2(interp, |
| 1327 | 1334 | argv[0], argl[0], |
| 1328 | 1335 | "StmtHandle Index"); |
| 1329 | 1336 | } |
| 1330 | 1337 | if(!pStmt){ |
| 1331 | 1338 | queryStmtIndexArgs(interp, argc, argv, argl, &pStmt, &index); |
| 1332 | - }else{ | |
| 1339 | + }else if(index<0){ | |
| 1333 | 1340 | Th_ToInt(interp, argv[1], argl[1], &index); |
| 1334 | 1341 | } |
| 1335 | 1342 | if(index < 0){ |
| 1336 | 1343 | return TH_ERROR; |
| 1337 | 1344 | } |
| @@ -1344,10 +1351,11 @@ | ||
| 1344 | 1351 | /* |
| 1345 | 1352 | ** TH Syntax: |
| 1346 | 1353 | ** |
| 1347 | 1354 | ** query col type stmtId Index |
| 1348 | 1355 | ** query stmtId col type Index |
| 1356 | +** query stmtId col Index type | |
| 1349 | 1357 | ** |
| 1350 | 1358 | ** Returns the sqlite type identifier for the given 0-based result |
| 1351 | 1359 | ** column index. The values are available in TH as $SQLITE_NULL, |
| 1352 | 1360 | ** $SQLITE_INTEGER, etc. |
| 1353 | 1361 | */ |
| @@ -1356,22 +1364,24 @@ | ||
| 1356 | 1364 | void *p, |
| 1357 | 1365 | int argc, |
| 1358 | 1366 | const char **argv, |
| 1359 | 1367 | int *argl |
| 1360 | 1368 | ){ |
| 1369 | + Th_Sqlite * sq = Th_sqlite_manager(interp); | |
| 1370 | + int index = sq->colCmdIndex; | |
| 1361 | 1371 | sqlite3_stmt * pStmt = (sqlite3_stmt*)p; |
| 1362 | 1372 | int requireArgc = pStmt ? 2 : 3; |
| 1373 | + if( index >= 0 ) --requireArgc; | |
| 1363 | 1374 | double rc = 0; |
| 1364 | - int index = -1; | |
| 1365 | 1375 | if( argc!=requireArgc ){ |
| 1366 | 1376 | return Th_WrongNumArgs2(interp, |
| 1367 | 1377 | argv[0], argl[0], |
| 1368 | 1378 | "StmtHandle Index"); |
| 1369 | 1379 | } |
| 1370 | 1380 | if(!pStmt){ |
| 1371 | 1381 | queryStmtIndexArgs(interp, argc, argv, argl, &pStmt, &index); |
| 1372 | - }else{ | |
| 1382 | + }else if(index<0){ | |
| 1373 | 1383 | Th_ToInt( interp, argv[1], argl[1], &index ); |
| 1374 | 1384 | } |
| 1375 | 1385 | if(index < 0){ |
| 1376 | 1386 | return TH_ERROR; |
| 1377 | 1387 | } |
| @@ -1416,10 +1426,11 @@ | ||
| 1416 | 1426 | /* |
| 1417 | 1427 | ** TH Syntax: |
| 1418 | 1428 | ** |
| 1419 | 1429 | ** query col name stmtId Index |
| 1420 | 1430 | ** query stmtId col name Index |
| 1431 | +** query stmtId col Index name | |
| 1421 | 1432 | ** |
| 1422 | 1433 | ** Returns the result column name at the given 0-based index. |
| 1423 | 1434 | */ |
| 1424 | 1435 | static int queryColNameCmd( |
| 1425 | 1436 | Th_Interp *interp, |
| @@ -1426,23 +1437,25 @@ | ||
| 1426 | 1437 | void *p, |
| 1427 | 1438 | int argc, |
| 1428 | 1439 | const char **argv, |
| 1429 | 1440 | int *argl |
| 1430 | 1441 | ){ |
| 1442 | + Th_Sqlite * sq = Th_sqlite_manager(interp); | |
| 1443 | + int index = sq->colCmdIndex; | |
| 1431 | 1444 | sqlite3_stmt * pStmt = (sqlite3_stmt*)p; |
| 1432 | 1445 | int requireArgc = pStmt ? 2 : 3; |
| 1433 | 1446 | char const * val; |
| 1434 | 1447 | int rc = 0; |
| 1435 | - int index = -1; | |
| 1448 | + if( index >= 0 ) --requireArgc; | |
| 1436 | 1449 | if( argc!=requireArgc ){ |
| 1437 | 1450 | return Th_WrongNumArgs2(interp, |
| 1438 | 1451 | argv[0], argl[0], |
| 1439 | 1452 | "StmtHandle Index"); |
| 1440 | 1453 | } |
| 1441 | 1454 | if(!pStmt){ |
| 1442 | 1455 | queryStmtIndexArgs(interp, argc, argv, argl, &pStmt, &index); |
| 1443 | - }else{ | |
| 1456 | + }else if(index<0){ | |
| 1444 | 1457 | Th_ToInt( interp, argv[1], argl[1], &index ); |
| 1445 | 1458 | } |
| 1446 | 1459 | if(index < 0){ |
| 1447 | 1460 | return TH_ERROR; |
| 1448 | 1461 | } |
| @@ -1460,10 +1473,11 @@ | ||
| 1460 | 1473 | /* |
| 1461 | 1474 | ** TH Syntax: |
| 1462 | 1475 | ** |
| 1463 | 1476 | ** query col time stmtId Index format |
| 1464 | 1477 | ** query stmtId col name Index format |
| 1478 | +** query stmtId col Index name format | |
| 1465 | 1479 | ** |
| 1466 | 1480 | ** Returns the result column name at the given 0-based index. |
| 1467 | 1481 | */ |
| 1468 | 1482 | static int queryColTimeCmd( |
| 1469 | 1483 | Th_Interp *interp, |
| @@ -1470,30 +1484,34 @@ | ||
| 1470 | 1484 | void *ctx, |
| 1471 | 1485 | int argc, |
| 1472 | 1486 | const char **argv, |
| 1473 | 1487 | int *argl |
| 1474 | 1488 | ){ |
| 1489 | + Th_Sqlite * sq = Th_sqlite_manager(interp); | |
| 1490 | + int index = sq->colCmdIndex; | |
| 1475 | 1491 | sqlite3_stmt * pStmt = (sqlite3_stmt*)ctx; |
| 1476 | 1492 | int minArgs = pStmt ? 3 : 4; |
| 1477 | 1493 | int argPos; |
| 1478 | 1494 | char const * val; |
| 1479 | 1495 | char * fval; |
| 1480 | 1496 | int i, rc = 0; |
| 1481 | - int index = -1; | |
| 1482 | 1497 | char const * fmt; |
| 1483 | 1498 | Blob sql = empty_blob; |
| 1499 | + if( index >= 0 ) --minArgs; | |
| 1484 | 1500 | if( argc<minArgs ){ |
| 1485 | 1501 | return Th_WrongNumArgs2(interp, |
| 1486 | 1502 | argv[0], argl[0], |
| 1487 | 1503 | "StmtHandle Index Format"); |
| 1488 | 1504 | } |
| 1489 | 1505 | if(!pStmt){ |
| 1490 | 1506 | queryStmtIndexArgs(interp, argc, argv, argl, &pStmt, &index); |
| 1491 | 1507 | argPos = 3; |
| 1492 | - }else{ | |
| 1508 | + }else if(index<0){ | |
| 1493 | 1509 | Th_ToInt( interp, argv[1], argl[1], &index ); |
| 1494 | 1510 | argPos = 2; |
| 1511 | + }else{ | |
| 1512 | + argPos = 1; | |
| 1495 | 1513 | } |
| 1496 | 1514 | if(index < 0){ |
| 1497 | 1515 | return TH_ERROR; |
| 1498 | 1516 | } |
| 1499 | 1517 | val = sqlite3_column_text( pStmt, index ); |
| @@ -1750,22 +1768,55 @@ | ||
| 1750 | 1768 | void *ctx, |
| 1751 | 1769 | int argc, |
| 1752 | 1770 | const char **argv, |
| 1753 | 1771 | int *argl |
| 1754 | 1772 | ){ |
| 1773 | + int colIndex = -1; | |
| 1755 | 1774 | static Th_SubCommand aSub[] = { |
| 1756 | 1775 | {"count", queryColCountCmd}, |
| 1757 | - {"is_null", queryColIsNullCmd}, | |
| 1776 | + {"is_null", queryColIsNullCmd}, | |
| 1777 | + {"isnull", queryColIsNullCmd}, | |
| 1778 | + {"name", queryColNameCmd}, | |
| 1779 | + {"double", queryColDoubleCmd}, | |
| 1780 | + {"int", queryColIntCmd}, | |
| 1781 | + {"string", queryColStringCmd}, | |
| 1782 | + {"time", queryColTimeCmd}, | |
| 1783 | + {"type", queryColTypeCmd}, | |
| 1784 | + {0, 0} | |
| 1785 | + }; | |
| 1786 | + static Th_SubCommand aSubWithIndex[] = { | |
| 1787 | + {"is_null", queryColIsNullCmd}, | |
| 1788 | + {"isnull", queryColIsNullCmd}, | |
| 1758 | 1789 | {"name", queryColNameCmd}, |
| 1759 | 1790 | {"double", queryColDoubleCmd}, |
| 1760 | 1791 | {"int", queryColIntCmd}, |
| 1761 | 1792 | {"string", queryColStringCmd}, |
| 1762 | 1793 | {"time", queryColTimeCmd}, |
| 1763 | - {"type", queryColTypeCmd}, | |
| 1794 | + {"type", queryColTypeCmd}, | |
| 1764 | 1795 | {0, 0} |
| 1765 | 1796 | }; |
| 1766 | - Th_CallSubCommand2( interp, ctx, argc, argv, argl, aSub ); | |
| 1797 | + Th_Sqlite * sq = Th_sqlite_manager(interp); | |
| 1798 | + assert(NULL != sq); | |
| 1799 | + if( 1 == argc ){ | |
| 1800 | + Th_WrongNumArgs2( interp, argv[0], argl[0], | |
| 1801 | + "subcommand"); | |
| 1802 | + return TH_ERROR; | |
| 1803 | + }else if( 0 == Th_TryInt(interp,argv[1], argl[1], &colIndex) ){ | |
| 1804 | + if(colIndex <0){ | |
| 1805 | + Th_ErrorMessage( interp, "Invalid column index.", NULL, 0); | |
| 1806 | + return TH_ERROR; | |
| 1807 | + } | |
| 1808 | + ++argv; | |
| 1809 | + ++argl; | |
| 1810 | + --argc; | |
| 1811 | + } | |
| 1812 | + sq->colCmdIndex = colIndex; | |
| 1813 | + /* TODO: accept the index as the first param after "col", and make | |
| 1814 | + subcommands aware of sq->colCmdIndex. | |
| 1815 | + */ | |
| 1816 | + Th_CallSubCommand2( interp, ctx, argc, argv, argl, | |
| 1817 | + (colIndex<0) ? aSub : aSubWithIndex ); | |
| 1767 | 1818 | } |
| 1768 | 1819 | |
| 1769 | 1820 | |
| 1770 | 1821 | static int queryTopLevelCmd( |
| 1771 | 1822 | Th_Interp *interp, |
| 1772 | 1823 |
| --- src/th_main.c | |
| +++ src/th_main.c | |
| @@ -874,10 +874,11 @@ | |
| 874 | |
| 875 | |
| 876 | struct Th_Sqlite { |
| 877 | sqlite3_stmt ** aStmt; |
| 878 | int nStmt; |
| 879 | }; |
| 880 | #define Th_Sqlite_KEY "Th_Sqlite" |
| 881 | typedef struct Th_Sqlite Th_Sqlite; |
| 882 | |
| 883 | static Th_Sqlite * Th_sqlite_manager( Th_Interp * interp ){ |
| @@ -1193,10 +1194,11 @@ | |
| 1193 | /* |
| 1194 | ** TH Syntax: |
| 1195 | ** |
| 1196 | ** query col string stmtId Index |
| 1197 | ** query stmtId col string Index |
| 1198 | ** |
| 1199 | ** Returns the result column value at the given 0-based index. |
| 1200 | */ |
| 1201 | static int queryColStringCmd( |
| 1202 | Th_Interp *interp, |
| @@ -1232,10 +1234,11 @@ | |
| 1232 | /* |
| 1233 | ** TH Syntax: |
| 1234 | ** |
| 1235 | ** query col int stmtId Index |
| 1236 | ** query stmtId col int Index |
| 1237 | ** |
| 1238 | ** Returns the result column value at the given 0-based index. |
| 1239 | */ |
| 1240 | static int queryColIntCmd( |
| 1241 | Th_Interp *interp, |
| @@ -1269,10 +1272,11 @@ | |
| 1269 | /* |
| 1270 | ** TH Syntax: |
| 1271 | ** |
| 1272 | ** query col double stmtId Index |
| 1273 | ** query stmtId col double Index |
| 1274 | ** |
| 1275 | ** Returns the result column value at the given 0-based index. |
| 1276 | */ |
| 1277 | static int queryColDoubleCmd( |
| 1278 | Th_Interp *interp, |
| @@ -1303,12 +1307,13 @@ | |
| 1303 | } |
| 1304 | |
| 1305 | /* |
| 1306 | ** TH Syntax: |
| 1307 | ** |
| 1308 | ** query col is_null stmtId Index |
| 1309 | ** query stmtId col is_null Index |
| 1310 | ** |
| 1311 | ** Returns non-0 if the given 0-based result column index contains |
| 1312 | ** an SQL NULL value, else returns 0. |
| 1313 | */ |
| 1314 | static int queryColIsNullCmd( |
| @@ -1316,22 +1321,24 @@ | |
| 1316 | void *p, |
| 1317 | int argc, |
| 1318 | const char **argv, |
| 1319 | int *argl |
| 1320 | ){ |
| 1321 | sqlite3_stmt * pStmt = (sqlite3_stmt*)p; |
| 1322 | int requireArgc = pStmt ? 2 : 3; |
| 1323 | double rc = 0; |
| 1324 | int index = -1; |
| 1325 | if( argc!=requireArgc ){ |
| 1326 | return Th_WrongNumArgs2(interp, |
| 1327 | argv[0], argl[0], |
| 1328 | "StmtHandle Index"); |
| 1329 | } |
| 1330 | if(!pStmt){ |
| 1331 | queryStmtIndexArgs(interp, argc, argv, argl, &pStmt, &index); |
| 1332 | }else{ |
| 1333 | Th_ToInt(interp, argv[1], argl[1], &index); |
| 1334 | } |
| 1335 | if(index < 0){ |
| 1336 | return TH_ERROR; |
| 1337 | } |
| @@ -1344,10 +1351,11 @@ | |
| 1344 | /* |
| 1345 | ** TH Syntax: |
| 1346 | ** |
| 1347 | ** query col type stmtId Index |
| 1348 | ** query stmtId col type Index |
| 1349 | ** |
| 1350 | ** Returns the sqlite type identifier for the given 0-based result |
| 1351 | ** column index. The values are available in TH as $SQLITE_NULL, |
| 1352 | ** $SQLITE_INTEGER, etc. |
| 1353 | */ |
| @@ -1356,22 +1364,24 @@ | |
| 1356 | void *p, |
| 1357 | int argc, |
| 1358 | const char **argv, |
| 1359 | int *argl |
| 1360 | ){ |
| 1361 | sqlite3_stmt * pStmt = (sqlite3_stmt*)p; |
| 1362 | int requireArgc = pStmt ? 2 : 3; |
| 1363 | double rc = 0; |
| 1364 | int index = -1; |
| 1365 | if( argc!=requireArgc ){ |
| 1366 | return Th_WrongNumArgs2(interp, |
| 1367 | argv[0], argl[0], |
| 1368 | "StmtHandle Index"); |
| 1369 | } |
| 1370 | if(!pStmt){ |
| 1371 | queryStmtIndexArgs(interp, argc, argv, argl, &pStmt, &index); |
| 1372 | }else{ |
| 1373 | Th_ToInt( interp, argv[1], argl[1], &index ); |
| 1374 | } |
| 1375 | if(index < 0){ |
| 1376 | return TH_ERROR; |
| 1377 | } |
| @@ -1416,10 +1426,11 @@ | |
| 1416 | /* |
| 1417 | ** TH Syntax: |
| 1418 | ** |
| 1419 | ** query col name stmtId Index |
| 1420 | ** query stmtId col name Index |
| 1421 | ** |
| 1422 | ** Returns the result column name at the given 0-based index. |
| 1423 | */ |
| 1424 | static int queryColNameCmd( |
| 1425 | Th_Interp *interp, |
| @@ -1426,23 +1437,25 @@ | |
| 1426 | void *p, |
| 1427 | int argc, |
| 1428 | const char **argv, |
| 1429 | int *argl |
| 1430 | ){ |
| 1431 | sqlite3_stmt * pStmt = (sqlite3_stmt*)p; |
| 1432 | int requireArgc = pStmt ? 2 : 3; |
| 1433 | char const * val; |
| 1434 | int rc = 0; |
| 1435 | int index = -1; |
| 1436 | if( argc!=requireArgc ){ |
| 1437 | return Th_WrongNumArgs2(interp, |
| 1438 | argv[0], argl[0], |
| 1439 | "StmtHandle Index"); |
| 1440 | } |
| 1441 | if(!pStmt){ |
| 1442 | queryStmtIndexArgs(interp, argc, argv, argl, &pStmt, &index); |
| 1443 | }else{ |
| 1444 | Th_ToInt( interp, argv[1], argl[1], &index ); |
| 1445 | } |
| 1446 | if(index < 0){ |
| 1447 | return TH_ERROR; |
| 1448 | } |
| @@ -1460,10 +1473,11 @@ | |
| 1460 | /* |
| 1461 | ** TH Syntax: |
| 1462 | ** |
| 1463 | ** query col time stmtId Index format |
| 1464 | ** query stmtId col name Index format |
| 1465 | ** |
| 1466 | ** Returns the result column name at the given 0-based index. |
| 1467 | */ |
| 1468 | static int queryColTimeCmd( |
| 1469 | Th_Interp *interp, |
| @@ -1470,30 +1484,34 @@ | |
| 1470 | void *ctx, |
| 1471 | int argc, |
| 1472 | const char **argv, |
| 1473 | int *argl |
| 1474 | ){ |
| 1475 | sqlite3_stmt * pStmt = (sqlite3_stmt*)ctx; |
| 1476 | int minArgs = pStmt ? 3 : 4; |
| 1477 | int argPos; |
| 1478 | char const * val; |
| 1479 | char * fval; |
| 1480 | int i, rc = 0; |
| 1481 | int index = -1; |
| 1482 | char const * fmt; |
| 1483 | Blob sql = empty_blob; |
| 1484 | if( argc<minArgs ){ |
| 1485 | return Th_WrongNumArgs2(interp, |
| 1486 | argv[0], argl[0], |
| 1487 | "StmtHandle Index Format"); |
| 1488 | } |
| 1489 | if(!pStmt){ |
| 1490 | queryStmtIndexArgs(interp, argc, argv, argl, &pStmt, &index); |
| 1491 | argPos = 3; |
| 1492 | }else{ |
| 1493 | Th_ToInt( interp, argv[1], argl[1], &index ); |
| 1494 | argPos = 2; |
| 1495 | } |
| 1496 | if(index < 0){ |
| 1497 | return TH_ERROR; |
| 1498 | } |
| 1499 | val = sqlite3_column_text( pStmt, index ); |
| @@ -1750,22 +1768,55 @@ | |
| 1750 | void *ctx, |
| 1751 | int argc, |
| 1752 | const char **argv, |
| 1753 | int *argl |
| 1754 | ){ |
| 1755 | static Th_SubCommand aSub[] = { |
| 1756 | {"count", queryColCountCmd}, |
| 1757 | {"is_null", queryColIsNullCmd}, |
| 1758 | {"name", queryColNameCmd}, |
| 1759 | {"double", queryColDoubleCmd}, |
| 1760 | {"int", queryColIntCmd}, |
| 1761 | {"string", queryColStringCmd}, |
| 1762 | {"time", queryColTimeCmd}, |
| 1763 | {"type", queryColTypeCmd}, |
| 1764 | {0, 0} |
| 1765 | }; |
| 1766 | Th_CallSubCommand2( interp, ctx, argc, argv, argl, aSub ); |
| 1767 | } |
| 1768 | |
| 1769 | |
| 1770 | static int queryTopLevelCmd( |
| 1771 | Th_Interp *interp, |
| 1772 |
| --- src/th_main.c | |
| +++ src/th_main.c | |
| @@ -874,10 +874,11 @@ | |
| 874 | |
| 875 | |
| 876 | struct Th_Sqlite { |
| 877 | sqlite3_stmt ** aStmt; |
| 878 | int nStmt; |
| 879 | int colCmdIndex; |
| 880 | }; |
| 881 | #define Th_Sqlite_KEY "Th_Sqlite" |
| 882 | typedef struct Th_Sqlite Th_Sqlite; |
| 883 | |
| 884 | static Th_Sqlite * Th_sqlite_manager( Th_Interp * interp ){ |
| @@ -1193,10 +1194,11 @@ | |
| 1194 | /* |
| 1195 | ** TH Syntax: |
| 1196 | ** |
| 1197 | ** query col string stmtId Index |
| 1198 | ** query stmtId col string Index |
| 1199 | ** query stmtId col Index string |
| 1200 | ** |
| 1201 | ** Returns the result column value at the given 0-based index. |
| 1202 | */ |
| 1203 | static int queryColStringCmd( |
| 1204 | Th_Interp *interp, |
| @@ -1232,10 +1234,11 @@ | |
| 1234 | /* |
| 1235 | ** TH Syntax: |
| 1236 | ** |
| 1237 | ** query col int stmtId Index |
| 1238 | ** query stmtId col int Index |
| 1239 | ** query stmtId col Index int |
| 1240 | ** |
| 1241 | ** Returns the result column value at the given 0-based index. |
| 1242 | */ |
| 1243 | static int queryColIntCmd( |
| 1244 | Th_Interp *interp, |
| @@ -1269,10 +1272,11 @@ | |
| 1272 | /* |
| 1273 | ** TH Syntax: |
| 1274 | ** |
| 1275 | ** query col double stmtId Index |
| 1276 | ** query stmtId col double Index |
| 1277 | ** query stmtId col Index double |
| 1278 | ** |
| 1279 | ** Returns the result column value at the given 0-based index. |
| 1280 | */ |
| 1281 | static int queryColDoubleCmd( |
| 1282 | Th_Interp *interp, |
| @@ -1303,12 +1307,13 @@ | |
| 1307 | } |
| 1308 | |
| 1309 | /* |
| 1310 | ** TH Syntax: |
| 1311 | ** |
| 1312 | ** query col isnull stmtId Index |
| 1313 | ** query stmtId col is_null Index |
| 1314 | ** query stmtId col Index isnull |
| 1315 | ** |
| 1316 | ** Returns non-0 if the given 0-based result column index contains |
| 1317 | ** an SQL NULL value, else returns 0. |
| 1318 | */ |
| 1319 | static int queryColIsNullCmd( |
| @@ -1316,22 +1321,24 @@ | |
| 1321 | void *p, |
| 1322 | int argc, |
| 1323 | const char **argv, |
| 1324 | int *argl |
| 1325 | ){ |
| 1326 | Th_Sqlite * sq = Th_sqlite_manager(interp); |
| 1327 | int index = sq->colCmdIndex; |
| 1328 | sqlite3_stmt * pStmt = (sqlite3_stmt*)p; |
| 1329 | int requireArgc = pStmt ? 2 : 3; |
| 1330 | if( index >= 0 ) --requireArgc; |
| 1331 | double rc = 0; |
| 1332 | if( argc!=requireArgc ){ |
| 1333 | return Th_WrongNumArgs2(interp, |
| 1334 | argv[0], argl[0], |
| 1335 | "StmtHandle Index"); |
| 1336 | } |
| 1337 | if(!pStmt){ |
| 1338 | queryStmtIndexArgs(interp, argc, argv, argl, &pStmt, &index); |
| 1339 | }else if(index<0){ |
| 1340 | Th_ToInt(interp, argv[1], argl[1], &index); |
| 1341 | } |
| 1342 | if(index < 0){ |
| 1343 | return TH_ERROR; |
| 1344 | } |
| @@ -1344,10 +1351,11 @@ | |
| 1351 | /* |
| 1352 | ** TH Syntax: |
| 1353 | ** |
| 1354 | ** query col type stmtId Index |
| 1355 | ** query stmtId col type Index |
| 1356 | ** query stmtId col Index type |
| 1357 | ** |
| 1358 | ** Returns the sqlite type identifier for the given 0-based result |
| 1359 | ** column index. The values are available in TH as $SQLITE_NULL, |
| 1360 | ** $SQLITE_INTEGER, etc. |
| 1361 | */ |
| @@ -1356,22 +1364,24 @@ | |
| 1364 | void *p, |
| 1365 | int argc, |
| 1366 | const char **argv, |
| 1367 | int *argl |
| 1368 | ){ |
| 1369 | Th_Sqlite * sq = Th_sqlite_manager(interp); |
| 1370 | int index = sq->colCmdIndex; |
| 1371 | sqlite3_stmt * pStmt = (sqlite3_stmt*)p; |
| 1372 | int requireArgc = pStmt ? 2 : 3; |
| 1373 | if( index >= 0 ) --requireArgc; |
| 1374 | double rc = 0; |
| 1375 | if( argc!=requireArgc ){ |
| 1376 | return Th_WrongNumArgs2(interp, |
| 1377 | argv[0], argl[0], |
| 1378 | "StmtHandle Index"); |
| 1379 | } |
| 1380 | if(!pStmt){ |
| 1381 | queryStmtIndexArgs(interp, argc, argv, argl, &pStmt, &index); |
| 1382 | }else if(index<0){ |
| 1383 | Th_ToInt( interp, argv[1], argl[1], &index ); |
| 1384 | } |
| 1385 | if(index < 0){ |
| 1386 | return TH_ERROR; |
| 1387 | } |
| @@ -1416,10 +1426,11 @@ | |
| 1426 | /* |
| 1427 | ** TH Syntax: |
| 1428 | ** |
| 1429 | ** query col name stmtId Index |
| 1430 | ** query stmtId col name Index |
| 1431 | ** query stmtId col Index name |
| 1432 | ** |
| 1433 | ** Returns the result column name at the given 0-based index. |
| 1434 | */ |
| 1435 | static int queryColNameCmd( |
| 1436 | Th_Interp *interp, |
| @@ -1426,23 +1437,25 @@ | |
| 1437 | void *p, |
| 1438 | int argc, |
| 1439 | const char **argv, |
| 1440 | int *argl |
| 1441 | ){ |
| 1442 | Th_Sqlite * sq = Th_sqlite_manager(interp); |
| 1443 | int index = sq->colCmdIndex; |
| 1444 | sqlite3_stmt * pStmt = (sqlite3_stmt*)p; |
| 1445 | int requireArgc = pStmt ? 2 : 3; |
| 1446 | char const * val; |
| 1447 | int rc = 0; |
| 1448 | if( index >= 0 ) --requireArgc; |
| 1449 | if( argc!=requireArgc ){ |
| 1450 | return Th_WrongNumArgs2(interp, |
| 1451 | argv[0], argl[0], |
| 1452 | "StmtHandle Index"); |
| 1453 | } |
| 1454 | if(!pStmt){ |
| 1455 | queryStmtIndexArgs(interp, argc, argv, argl, &pStmt, &index); |
| 1456 | }else if(index<0){ |
| 1457 | Th_ToInt( interp, argv[1], argl[1], &index ); |
| 1458 | } |
| 1459 | if(index < 0){ |
| 1460 | return TH_ERROR; |
| 1461 | } |
| @@ -1460,10 +1473,11 @@ | |
| 1473 | /* |
| 1474 | ** TH Syntax: |
| 1475 | ** |
| 1476 | ** query col time stmtId Index format |
| 1477 | ** query stmtId col name Index format |
| 1478 | ** query stmtId col Index name format |
| 1479 | ** |
| 1480 | ** Returns the result column name at the given 0-based index. |
| 1481 | */ |
| 1482 | static int queryColTimeCmd( |
| 1483 | Th_Interp *interp, |
| @@ -1470,30 +1484,34 @@ | |
| 1484 | void *ctx, |
| 1485 | int argc, |
| 1486 | const char **argv, |
| 1487 | int *argl |
| 1488 | ){ |
| 1489 | Th_Sqlite * sq = Th_sqlite_manager(interp); |
| 1490 | int index = sq->colCmdIndex; |
| 1491 | sqlite3_stmt * pStmt = (sqlite3_stmt*)ctx; |
| 1492 | int minArgs = pStmt ? 3 : 4; |
| 1493 | int argPos; |
| 1494 | char const * val; |
| 1495 | char * fval; |
| 1496 | int i, rc = 0; |
| 1497 | char const * fmt; |
| 1498 | Blob sql = empty_blob; |
| 1499 | if( index >= 0 ) --minArgs; |
| 1500 | if( argc<minArgs ){ |
| 1501 | return Th_WrongNumArgs2(interp, |
| 1502 | argv[0], argl[0], |
| 1503 | "StmtHandle Index Format"); |
| 1504 | } |
| 1505 | if(!pStmt){ |
| 1506 | queryStmtIndexArgs(interp, argc, argv, argl, &pStmt, &index); |
| 1507 | argPos = 3; |
| 1508 | }else if(index<0){ |
| 1509 | Th_ToInt( interp, argv[1], argl[1], &index ); |
| 1510 | argPos = 2; |
| 1511 | }else{ |
| 1512 | argPos = 1; |
| 1513 | } |
| 1514 | if(index < 0){ |
| 1515 | return TH_ERROR; |
| 1516 | } |
| 1517 | val = sqlite3_column_text( pStmt, index ); |
| @@ -1750,22 +1768,55 @@ | |
| 1768 | void *ctx, |
| 1769 | int argc, |
| 1770 | const char **argv, |
| 1771 | int *argl |
| 1772 | ){ |
| 1773 | int colIndex = -1; |
| 1774 | static Th_SubCommand aSub[] = { |
| 1775 | {"count", queryColCountCmd}, |
| 1776 | {"is_null", queryColIsNullCmd}, |
| 1777 | {"isnull", queryColIsNullCmd}, |
| 1778 | {"name", queryColNameCmd}, |
| 1779 | {"double", queryColDoubleCmd}, |
| 1780 | {"int", queryColIntCmd}, |
| 1781 | {"string", queryColStringCmd}, |
| 1782 | {"time", queryColTimeCmd}, |
| 1783 | {"type", queryColTypeCmd}, |
| 1784 | {0, 0} |
| 1785 | }; |
| 1786 | static Th_SubCommand aSubWithIndex[] = { |
| 1787 | {"is_null", queryColIsNullCmd}, |
| 1788 | {"isnull", queryColIsNullCmd}, |
| 1789 | {"name", queryColNameCmd}, |
| 1790 | {"double", queryColDoubleCmd}, |
| 1791 | {"int", queryColIntCmd}, |
| 1792 | {"string", queryColStringCmd}, |
| 1793 | {"time", queryColTimeCmd}, |
| 1794 | {"type", queryColTypeCmd}, |
| 1795 | {0, 0} |
| 1796 | }; |
| 1797 | Th_Sqlite * sq = Th_sqlite_manager(interp); |
| 1798 | assert(NULL != sq); |
| 1799 | if( 1 == argc ){ |
| 1800 | Th_WrongNumArgs2( interp, argv[0], argl[0], |
| 1801 | "subcommand"); |
| 1802 | return TH_ERROR; |
| 1803 | }else if( 0 == Th_TryInt(interp,argv[1], argl[1], &colIndex) ){ |
| 1804 | if(colIndex <0){ |
| 1805 | Th_ErrorMessage( interp, "Invalid column index.", NULL, 0); |
| 1806 | return TH_ERROR; |
| 1807 | } |
| 1808 | ++argv; |
| 1809 | ++argl; |
| 1810 | --argc; |
| 1811 | } |
| 1812 | sq->colCmdIndex = colIndex; |
| 1813 | /* TODO: accept the index as the first param after "col", and make |
| 1814 | subcommands aware of sq->colCmdIndex. |
| 1815 | */ |
| 1816 | Th_CallSubCommand2( interp, ctx, argc, argv, argl, |
| 1817 | (colIndex<0) ? aSub : aSubWithIndex ); |
| 1818 | } |
| 1819 | |
| 1820 | |
| 1821 | static int queryTopLevelCmd( |
| 1822 | Th_Interp *interp, |
| 1823 |
+14
-1
| --- www/th1_query.wiki | ||
| +++ www/th1_query.wiki | ||
| @@ -96,10 +96,16 @@ | ||
| 96 | 96 | |
| 97 | 97 | * <tt>bind int StmtId Index Value</tt> |
| 98 | 98 | * <tt>bind double StmtId Index Value</tt> |
| 99 | 99 | * <tt>bind null StmtId Index</tt> |
| 100 | 100 | * <tt>bind string StmtId Index Value</tt> |
| 101 | + | |
| 102 | +Note that all of those optionally accept the statement handle directly after | |
| 103 | +the "query" command (before the "col" subcommand). e.g. | |
| 104 | +<tt>query bind null $stmt 1</tt> and | |
| 105 | +<tt>query $stmt bind null 1</tt> are equivalent. | |
| 106 | + | |
| 101 | 107 | |
| 102 | 108 | Achtung: the bind API uses 1-based indexes, just like SQL does. |
| 103 | 109 | |
| 104 | 110 | <nowiki><pre> |
| 105 | 111 | set stmt [query prepare "SELECT ... WHERE user=?"] |
| @@ -115,17 +121,24 @@ | ||
| 115 | 121 | |
| 116 | 122 | The <tt>col xxx</tt> familys of subcommands are for fetching |
| 117 | 123 | values and metadata from result rows. |
| 118 | 124 | |
| 119 | 125 | * <tt>col count StmtId</tt> Returns the number of result columns in the statement. |
| 120 | - * <tt>col is_null StmtId Index</tt> Returns non-0 if the given column contains an SQL NULL value. | |
| 126 | + * <tt>col isnull StmtId Index</tt> Returns non-0 if the given column contains an SQL NULL value. | |
| 121 | 127 | * <tt>col double StmtId Index</tt> |
| 122 | 128 | * <tt>col int StmtId Index</tt> |
| 123 | 129 | * <tt>col string StmtId Index</tt> |
| 124 | 130 | * <tt>col string StmtId Index Format Modifiers</tt> See below. |
| 125 | 131 | * <tt>col type StmtId Index</tt> Return value corresponds to one of the <tt>SQLITE_TYPENAME</tt> family of constants. |
| 126 | 132 | |
| 133 | +Note that all of those optionally accept the statement handle directly after | |
| 134 | +the "query" command (before the "col" subcommand). e.g. | |
| 135 | +<tt>query $stmt col count</tt> and | |
| 136 | +<tt>query col count $stmt</tt> are equivalent. They also accept the column index | |
| 137 | +either before or after the type name, e.g. | |
| 138 | +<tt>query $stmt col 1 string</tt> and <tt>query $stmt col string 1</tt> are equivalent. | |
| 139 | + | |
| 127 | 140 | Achtung: the col API uses 0-based indexes, just like SQL does. |
| 128 | 141 | |
| 129 | 142 | <h3>col time</h3> |
| 130 | 143 | |
| 131 | 144 | This function is a proxy for sqlite3's |
| 132 | 145 |
| --- www/th1_query.wiki | |
| +++ www/th1_query.wiki | |
| @@ -96,10 +96,16 @@ | |
| 96 | |
| 97 | * <tt>bind int StmtId Index Value</tt> |
| 98 | * <tt>bind double StmtId Index Value</tt> |
| 99 | * <tt>bind null StmtId Index</tt> |
| 100 | * <tt>bind string StmtId Index Value</tt> |
| 101 | |
| 102 | Achtung: the bind API uses 1-based indexes, just like SQL does. |
| 103 | |
| 104 | <nowiki><pre> |
| 105 | set stmt [query prepare "SELECT ... WHERE user=?"] |
| @@ -115,17 +121,24 @@ | |
| 115 | |
| 116 | The <tt>col xxx</tt> familys of subcommands are for fetching |
| 117 | values and metadata from result rows. |
| 118 | |
| 119 | * <tt>col count StmtId</tt> Returns the number of result columns in the statement. |
| 120 | * <tt>col is_null StmtId Index</tt> Returns non-0 if the given column contains an SQL NULL value. |
| 121 | * <tt>col double StmtId Index</tt> |
| 122 | * <tt>col int StmtId Index</tt> |
| 123 | * <tt>col string StmtId Index</tt> |
| 124 | * <tt>col string StmtId Index Format Modifiers</tt> See below. |
| 125 | * <tt>col type StmtId Index</tt> Return value corresponds to one of the <tt>SQLITE_TYPENAME</tt> family of constants. |
| 126 | |
| 127 | Achtung: the col API uses 0-based indexes, just like SQL does. |
| 128 | |
| 129 | <h3>col time</h3> |
| 130 | |
| 131 | This function is a proxy for sqlite3's |
| 132 |
| --- www/th1_query.wiki | |
| +++ www/th1_query.wiki | |
| @@ -96,10 +96,16 @@ | |
| 96 | |
| 97 | * <tt>bind int StmtId Index Value</tt> |
| 98 | * <tt>bind double StmtId Index Value</tt> |
| 99 | * <tt>bind null StmtId Index</tt> |
| 100 | * <tt>bind string StmtId Index Value</tt> |
| 101 | |
| 102 | Note that all of those optionally accept the statement handle directly after |
| 103 | the "query" command (before the "col" subcommand). e.g. |
| 104 | <tt>query bind null $stmt 1</tt> and |
| 105 | <tt>query $stmt bind null 1</tt> are equivalent. |
| 106 | |
| 107 | |
| 108 | Achtung: the bind API uses 1-based indexes, just like SQL does. |
| 109 | |
| 110 | <nowiki><pre> |
| 111 | set stmt [query prepare "SELECT ... WHERE user=?"] |
| @@ -115,17 +121,24 @@ | |
| 121 | |
| 122 | The <tt>col xxx</tt> familys of subcommands are for fetching |
| 123 | values and metadata from result rows. |
| 124 | |
| 125 | * <tt>col count StmtId</tt> Returns the number of result columns in the statement. |
| 126 | * <tt>col isnull StmtId Index</tt> Returns non-0 if the given column contains an SQL NULL value. |
| 127 | * <tt>col double StmtId Index</tt> |
| 128 | * <tt>col int StmtId Index</tt> |
| 129 | * <tt>col string StmtId Index</tt> |
| 130 | * <tt>col string StmtId Index Format Modifiers</tt> See below. |
| 131 | * <tt>col type StmtId Index</tt> Return value corresponds to one of the <tt>SQLITE_TYPENAME</tt> family of constants. |
| 132 | |
| 133 | Note that all of those optionally accept the statement handle directly after |
| 134 | the "query" command (before the "col" subcommand). e.g. |
| 135 | <tt>query $stmt col count</tt> and |
| 136 | <tt>query col count $stmt</tt> are equivalent. They also accept the column index |
| 137 | either before or after the type name, e.g. |
| 138 | <tt>query $stmt col 1 string</tt> and <tt>query $stmt col string 1</tt> are equivalent. |
| 139 | |
| 140 | Achtung: the col API uses 0-based indexes, just like SQL does. |
| 141 | |
| 142 | <h3>col time</h3> |
| 143 | |
| 144 | This function is a proxy for sqlite3's |
| 145 |