Fossil SCM

Added docs for the th1 query API. Added basic th1 argv-handling API.

stephan 2012-07-14 10:22 th1-query-api
Commit a8eace9a2adf75c160fdaa6bb05bc710ca10dd7f
2 files changed +360 -7 +20 -5
+360 -7
--- src/th_main.c
+++ src/th_main.c
@@ -433,11 +433,247 @@
433433
}
434434
Th_SetResult(interp, g.zRepositoryName, -1);
435435
return TH_OK;
436436
}
437437
438
+
439
+extern const char *find_option(const char *zLong, const char *zShort, int hasArg);
440
+
441
+/*
442
+** TH Syntax:
443
+**
444
+** argv_len
445
+**
446
+** Returns the number of command-line arguments.
447
+*/
448
+static int argvArgcCmd(
449
+ Th_Interp *interp,
450
+ void *p,
451
+ int argc,
452
+ const char **argv,
453
+ int *argl
454
+){
455
+ Th_SetResultInt( interp, g.argc );
456
+ return TH_OK;
457
+}
458
+
459
+#define TH_USE_ARGV
460
+#ifdef TH_USE_ARGV
461
+/*
462
+** TH Syntax:
463
+**
464
+** argv_getat Index
465
+**
466
+** Returns the raw argument at the given index, throwing if
467
+** out of bounds.
468
+*/
469
+static int argvGetAtCmd(
470
+ Th_Interp *interp,
471
+ void *p,
472
+ int argc,
473
+ const char **argv,
474
+ int *argl
475
+){
476
+ char const * zVal;
477
+ int pos = 0;
478
+ if( argc != 2 ){
479
+ return Th_WrongNumArgs(interp, "argv_get Index");
480
+ }
481
+ if( TH_OK != Th_ToInt(interp, argv[1], argl[1], &pos) ){
482
+ return TH_ERROR;
483
+ }
484
+ if( pos < 0 || pos >= g.argc ){
485
+ Th_ErrorMessage(interp, "Argument out of range:", argv[1], argl[1]);
486
+ return TH_ERROR;
487
+ }
488
+ if( 0 == pos ){/*special case*/
489
+ zVal = fossil_nameofexe();
490
+ }else{
491
+ zVal = (pos>0 && pos<g.argc) ? g.argv[pos] : 0;
492
+ }
493
+ Th_SetResult( interp, zVal, zVal ? strlen(zVal) : 0 );
494
+ return TH_OK;
495
+}
496
+
497
+
498
+/*
499
+** TH Syntax:
500
+**
501
+** argv_getstr longName ??shortName? ?defaultValue??
502
+**
503
+** Functions more or less like Fossil's find_option().
504
+** If the given argument is found then its value is returned,
505
+** else defaultValue is returned. If that is not set
506
+** and the option is not found, an error is thrown.
507
+** If defaultValue is provided, shortName must also be provided
508
+** but it may be empty. For example:
509
+**
510
+** set foo [argv_getstr foo "" "hi, world"]
511
+**
512
+** ACHTUNG: find_option() removes any entries it finds from
513
+** g.argv, such that future calls to find_option() will not
514
+** find the same option.
515
+*/
516
+static int argvFindOptionStringCmd(
517
+ Th_Interp *interp,
518
+ void *p,
519
+ int argc,
520
+ const char **argv,
521
+ int *argl
522
+){
523
+ enum { BufLen = 100 };
524
+ char zLong[BufLen] = {0};
525
+ char zShort[BufLen] = {0};
526
+ char aBuf[BufLen] = {0};
527
+ int hasArg;
528
+ char const * zVal = NULL;
529
+ char const * zDefault = NULL;
530
+ if( 1 < argc ){
531
+ assert( argl[1] < BufLen );
532
+ snprintf( zLong, BufLen, "%s", argv[1] );
533
+ }
534
+ if( (2 < argc) && (0 < argl[2]) ){
535
+ assert( argl[2] < BufLen );
536
+ snprintf( zShort, BufLen, "%s", argv[2] );
537
+ }
538
+ if( 3 < argc){
539
+ zDefault = argv[3];
540
+ }
541
+
542
+ if(0 == zLong[0]){
543
+ return Th_WrongNumArgs(interp, "argv_getstr longName ?shortName? ?defaultVal?");
544
+ }
545
+ zVal = find_option( zLong, zShort[0] ? zShort : NULL, 1 );
546
+ if(!zVal){
547
+ zVal = zDefault;
548
+ if(!zVal){
549
+ Th_ErrorMessage(interp, "Option not found and no default provided:", zLong, -1);
550
+ return TH_ERROR;
551
+ }
552
+ }
553
+ Th_SetResult( interp, zVal, zVal ? strlen(zVal) : 0 );
554
+ return TH_OK;
555
+}
556
+
557
+/*
558
+** TH Syntax:
559
+**
560
+** argv_getbool longName ??shortName? ?defaultValue??
561
+**
562
+** Works just like argv_getstr but treats any empty value or one
563
+** starting with the digit '0' as a boolean false.
564
+**
565
+** Returns the result as an integer 0 (false) or 1 (true).
566
+*/
567
+static int argvFindOptionBoolCmd(
568
+ Th_Interp *interp,
569
+ void *p,
570
+ int argc,
571
+ const char **argv,
572
+ int *argl
573
+){
574
+ enum { BufLen = 100 };
575
+ char zLong[BufLen] = {0};
576
+ char zShort[BufLen] = {0};
577
+ char aBuf[BufLen] = {0};
578
+ int hasArg;
579
+ char const * zVal = NULL;
580
+ char const * zDefault = NULL;
581
+ int val;
582
+ int rc;
583
+ if( 1 < argc ){
584
+ assert( argl[1] < BufLen );
585
+ snprintf( zLong, BufLen, "%s", argv[1] );
586
+ }
587
+ if( (2 < argc) && (0 < argl[2]) ){
588
+ assert( argl[2] < BufLen );
589
+ snprintf( zShort, BufLen, "%s", argv[2] );
590
+ }
591
+ if( 3 < argc){
592
+ zDefault = argv[3];
593
+ }
594
+
595
+ if(0 == zLong[0]){
596
+ return Th_WrongNumArgs(interp, "argv_getbool longName ?shortName? ?defaultVal?");
597
+ }
598
+ zVal = find_option( zLong, zShort[0] ? zShort : NULL, 0 );
599
+ if(zVal && !*zVal){
600
+ zVal = "1";
601
+ }
602
+ if(!zVal){
603
+ zVal = zDefault;
604
+ if(!zVal){
605
+ Th_ErrorMessage(interp, "Option not found and no default provided:", zLong, -1);
606
+ return TH_ERROR;
607
+ }
608
+ }
609
+ if( !*zVal ){
610
+ zVal = "0";
611
+ }
612
+ zVal = (zVal && *zVal && (*zVal!='0')) ? zVal : 0;
613
+ Th_SetResultInt( interp, zVal ? 1 : 0 );
614
+ return TH_OK;
615
+}
616
+
617
+/*
618
+** TH Syntax:
619
+**
620
+** argv_getint longName ?shortName? ?defaultValue?
621
+*/
622
+static int argvFindOptionIntCmd(
623
+ Th_Interp *interp,
624
+ void *p,
625
+ int argc,
626
+ const char **argv,
627
+ int *argl
628
+){
629
+ enum { BufLen = 100 };
630
+ char zLong[BufLen] = {0};
631
+ char zShort[BufLen] = {0};
632
+ char aBuf[BufLen] = {0};
633
+ int hasArg;
634
+ char const * zVal = NULL;
635
+ char const * zDefault = NULL;
636
+ int val = 0;
637
+ if( 1 < argc ){
638
+ assert( argl[1] < BufLen );
639
+ snprintf( zLong, BufLen, "%s", argv[1] );
640
+ }
641
+ if( (2 < argc) && (0 < argl[2]) ){
642
+ assert( argl[2] < BufLen );
643
+ snprintf( zShort, BufLen, "%s", argv[2] );
644
+ }
645
+ if( 3 < argc){
646
+ zDefault = argv[3];
647
+ }
648
+
649
+ if(0 == zLong[0]){
650
+ return Th_WrongNumArgs(interp, "argv_getint longName ?shortName? ?defaultVal?");
651
+ }
652
+ zVal = find_option( zLong, zShort[0] ? zShort : NULL, 0 );
653
+ if(!zVal){
654
+ zVal = zDefault;
655
+ if(!zVal){
656
+ Th_ErrorMessage(interp, "Option not found and no default provided:", zLong, -1);
657
+ return TH_ERROR;
658
+ }
659
+ }
660
+ Th_ToInt(interp, zVal, strlen(zVal), &val);
661
+ Th_SetResultInt( interp, val );
662
+ return TH_OK;
663
+}
664
+#endif
665
+/* end TH_USE_ARGV */
666
+
438667
#ifdef TH_USE_SQLITE
668
+/*
669
+** TH Syntax:
670
+**
671
+** query_prepare SQL
672
+**
673
+** Returns an opaque statement identifier.
674
+*/
439675
static int queryPrepareCmd(
440676
Th_Interp *interp,
441677
void *p,
442678
int argc,
443679
const char **argv,
@@ -498,10 +734,17 @@
498734
}
499735
return pStmt;
500736
501737
}
502738
739
+/*
740
+** TH Syntax:
741
+**
742
+** query_finalize stmtId
743
+**
744
+** sqlite3_finalize()s the given statement.
745
+*/
503746
static int queryFinalizeCmd(
504747
Th_Interp *interp,
505748
void *p,
506749
int argc,
507750
const char **argv,
@@ -523,10 +766,13 @@
523766
rc = Th_FinalizeStmt( interp, rc );
524767
Th_SetResultInt( interp, rc );
525768
return TH_OK;
526769
}
527770
771
+/*
772
+** Reports the current sqlite3_errmsg() via TH and returns TH_ERROR.
773
+*/
528774
static int queryReportDbErr( Th_Interp * interp ){
529775
char const * msg = sqlite3_errmsg( g.db );
530776
Th_ErrorMessage(interp, "db error:", msg, -1);
531777
return TH_ERROR;
532778
}
@@ -575,10 +821,18 @@
575821
}
576822
return 0;
577823
}
578824
}
579825
826
+/*
827
+** TH Syntax:
828
+**
829
+** query_step stmtId
830
+**
831
+** Steps the given statement handle. Returns 0 at the end of the set,
832
+** a positive value if it fetches a row, and throws on error.
833
+*/
580834
static int queryStepCmd(
581835
Th_Interp *interp,
582836
void *p,
583837
int argc,
584838
const char **argv,
@@ -606,10 +860,17 @@
606860
}
607861
Th_SetResultInt( interp, rc );
608862
return TH_OK;
609863
}
610864
865
+/*
866
+** TH Syntax:
867
+**
868
+** query_col_string stmtId Index
869
+**
870
+** Returns the result column value at the given 0-based index.
871
+*/
611872
static int queryColStringCmd(
612873
Th_Interp *interp,
613874
void *p,
614875
int argc,
615876
const char **argv,
@@ -630,10 +891,17 @@
630891
valLen = val ? sqlite3_column_bytes( pStmt, index ) : 0;
631892
Th_SetResult( interp, val, valLen );
632893
return TH_OK;
633894
}
634895
896
+/*
897
+** TH Syntax:
898
+**
899
+** query_col_int stmtId Index
900
+**
901
+** Returns the result column value at the given 0-based index.
902
+*/
635903
static int queryColIntCmd(
636904
Th_Interp *interp,
637905
void *p,
638906
int argc,
639907
const char **argv,
@@ -651,10 +919,17 @@
651919
}
652920
Th_SetResultInt( interp, sqlite3_column_int( pStmt, index ) );
653921
return TH_OK;
654922
}
655923
924
+/*
925
+** TH Syntax:
926
+**
927
+** query_col_double stmtId Index
928
+**
929
+** Returns the result column value at the given 0-based index.
930
+*/
656931
static int queryColDoubleCmd(
657932
Th_Interp *interp,
658933
void *p,
659934
int argc,
660935
const char **argv,
@@ -672,10 +947,18 @@
672947
}
673948
Th_SetResultDouble( interp, sqlite3_column_double( pStmt, index ) );
674949
return TH_OK;
675950
}
676951
952
+/*
953
+** TH Syntax:
954
+**
955
+** query_col_is_null stmtId Index
956
+**
957
+** Returns non-0 if the given 0-based result column index contains
958
+** an SQL NULL value, else returns 0.
959
+*/
677960
static int queryColIsNullCmd(
678961
Th_Interp *interp,
679962
void *p,
680963
int argc,
681964
const char **argv,
@@ -689,14 +972,25 @@
689972
}
690973
queryStmtIndexArgs(interp, argc, argv, argl, &pStmt, &index);
691974
if(index < 0){
692975
return TH_ERROR;
693976
}
694
- Th_SetResultInt( interp, SQLITE_NULL==sqlite3_column_type( pStmt, index ) );
977
+ Th_SetResultInt( interp,
978
+ SQLITE_NULL==sqlite3_column_type( pStmt, index )
979
+ ? 1 : 0);
695980
return TH_OK;
696981
}
697982
983
+/*
984
+** TH Syntax:
985
+**
986
+** query_col_type stmtId Index
987
+**
988
+** Returns the sqlite type identifier for the given 0-based result
989
+** column index. The values are available in TH as $SQLITE_NULL,
990
+** $SQLITE_INTEGER, etc.
991
+*/
698992
static int queryColTypeCmd(
699993
Th_Interp *interp,
700994
void *p,
701995
int argc,
702996
const char **argv,
@@ -714,10 +1008,17 @@
7141008
}
7151009
Th_SetResultInt( interp, sqlite3_column_type( pStmt, index ) );
7161010
return TH_OK;
7171011
}
7181012
1013
+/*
1014
+** TH Syntax:
1015
+**
1016
+** query_col_count stmtId
1017
+**
1018
+** Returns the number of result columns in the query.
1019
+*/
7191020
static int queryColCountCmd(
7201021
Th_Interp *interp,
7211022
void *p,
7221023
int argc,
7231024
const char **argv,
@@ -735,10 +1036,17 @@
7351036
rc = sqlite3_column_count( pStmt );
7361037
Th_SetResultInt( interp, rc );
7371038
return TH_OK;
7381039
}
7391040
1041
+/*
1042
+** TH Syntax:
1043
+**
1044
+** query_col_count stmtId Index
1045
+**
1046
+** Returns the result column name at the given 0-based index.
1047
+*/
7401048
static int queryColNameCmd(
7411049
Th_Interp *interp,
7421050
void *p,
7431051
int argc,
7441052
const char **argv,
@@ -767,10 +1075,17 @@
7671075
Th_SetResult( interp, val, strlen( val ) );
7681076
return TH_OK;
7691077
}
7701078
}
7711079
1080
+/*
1081
+** TH Syntax:
1082
+**
1083
+** query_bind_null stmtId Index
1084
+**
1085
+** Binds a value to the given 1-based parameter index.
1086
+*/
7721087
static int queryBindNullCmd(
7731088
Th_Interp *interp,
7741089
void *p,
7751090
int argc,
7761091
const char **argv,
@@ -793,10 +1108,17 @@
7931108
Th_SetResultInt( interp, 0 );
7941109
return TH_OK;
7951110
}
7961111
7971112
1113
+/*
1114
+** TH Syntax:
1115
+**
1116
+** query_bind_string stmtId Index Value
1117
+**
1118
+** Binds a value to the given 1-based parameter index.
1119
+*/
7981120
static int queryBindStringCmd(
7991121
Th_Interp *interp,
8001122
void *p,
8011123
int argc,
8021124
const char **argv,
@@ -818,10 +1140,17 @@
8181140
}
8191141
Th_SetResultInt( interp, 0 );
8201142
return TH_OK;
8211143
}
8221144
1145
+/*
1146
+** TH Syntax:
1147
+**
1148
+** query_bind_int stmtId Index Value
1149
+**
1150
+** Binds a value to the given 1-based parameter index.
1151
+*/
8231152
static int queryBindIntCmd(
8241153
Th_Interp *interp,
8251154
void *p,
8261155
int argc,
8271156
const char **argv,
@@ -848,10 +1177,17 @@
8481177
}
8491178
Th_SetResultInt( interp, 0 );
8501179
return TH_OK;
8511180
}
8521181
1182
+/*
1183
+** TH Syntax:
1184
+**
1185
+** query_bind_double stmtId Index Value
1186
+**
1187
+** Binds a value to the given 1-based parameter index.
1188
+*/
8531189
static int queryBindDoubleCmd(
8541190
Th_Interp *interp,
8551191
void *p,
8561192
int argc,
8571193
const char **argv,
@@ -890,11 +1226,10 @@
8901226
** The interpreter is stored in the g.interp global variable.
8911227
*/
8921228
void Th_FossilInit(void){
8931229
static PutsCmdData puts_Html = {0, 0, 0};
8941230
static PutsCmdData puts_Normal = {1, 0, 0};
895
- static PutsCmdData puts_Ext = {1, " ", "\n"};
8961231
static struct _Command {
8971232
const char *zName;
8981233
Th_CommandProc xProc;
8991234
void *pContext;
9001235
} aCommand[] = {
@@ -906,13 +1241,21 @@
9061241
{"hasfeature", hasfeatureCmd, 0},
9071242
{"htmlize", htmlizeCmd, 0},
9081243
{"date", dateCmd, 0},
9091244
{"html", putsCmd, &puts_Html},
9101245
{"puts", putsCmd, &puts_Normal},
911
- {"putsl", putsCmd, &puts_Ext},
9121246
{"wiki", wikiCmd, 0},
9131247
{"repository", repositoryCmd, 0},
1248
+
1249
+#ifdef TH_USE_ARGV
1250
+ {"argv_len", argvArgcCmd, 0},
1251
+ {"argv_getat", argvGetAtCmd, 0},
1252
+ {"argv_getstr", argvFindOptionStringCmd, 0},
1253
+ {"argv_getbool", argvFindOptionBoolCmd, 0},
1254
+ {"argv_getint", argvFindOptionIntCmd, 0},
1255
+#endif
1256
+
9141257
#ifdef TH_USE_SQLITE
9151258
{"query_bind_int", queryBindIntCmd, 0},
9161259
{"query_bind_double", queryBindDoubleCmd,0},
9171260
{"query_bind_null", queryBindNullCmd, 0},
9181261
{"query_bind_string", queryBindStringCmd,0},
@@ -925,10 +1268,11 @@
9251268
{"query_col_type", queryColTypeCmd, 0},
9261269
{"query_finalize", queryFinalizeCmd, 0},
9271270
{"query_prepare", queryPrepareCmd, 0},
9281271
{"query_step", queryStepCmd, 0},
9291272
#endif
1273
+
9301274
{0, 0, 0}
9311275
};
9321276
if( g.interp==0 ){
9331277
int i;
9341278
g.interp = Th_CreateInterp(&vtab);
@@ -945,13 +1289,13 @@
9451289
}
9461290
#ifdef TH_USE_SQLITE
9471291
{
9481292
enum { BufLen = 100 };
9491293
char buf[BufLen];
950
- int i;
951
-#define SET(K) i = snprintf(buf, BufLen, "%d", K); \
952
- Th_SetVar( g.interp, #K, strlen(#K), buf, i );
1294
+ int i, l;
1295
+#define SET(K) l = snprintf(buf, BufLen, "%d", K); \
1296
+ Th_SetVar( g.interp, #K, strlen(#K), buf, l );
9531297
SET(SQLITE_BLOB);
9541298
SET(SQLITE_DONE);
9551299
SET(SQLITE_ERROR);
9561300
SET(SQLITE_FLOAT);
9571301
SET(SQLITE_INTEGER);
@@ -1119,17 +1463,26 @@
11191463
return rc;
11201464
}
11211465
11221466
/*
11231467
** COMMAND: test-th-render
1468
+** COMMAND: th1
1469
+**
1470
+** Processes a file provided on the command line as a TH1-capable
1471
+** script/page. Output is sent to stdout or the CGI output buffer, as
1472
+** appropriate. The input file is assumed to be text/wiki/HTML content
1473
+** which may contain TH1 tag blocks. Each block is executed in the
1474
+** same TH1 interpreter instance.
1475
+**
11241476
*/
11251477
void test_th_render(void){
11261478
Blob in;
11271479
if( g.argc<3 ){
11281480
usage("FILE");
1481
+ assert(0 && "usage() does not return");
11291482
}
1130
- db_open_config(0); /* Needed for global "tcl" setting. */
11311483
blob_zero(&in);
1484
+ db_open_config(0); /* Needed for global "tcl" setting. */
11321485
db_find_and_open_repository(OPEN_ANY_SCHEMA,0) /* for query_xxx tests. */;
11331486
blob_read_from_file(&in, g.argv[2]);
11341487
Th_Render(blob_str(&in));
11351488
}
11361489
--- src/th_main.c
+++ src/th_main.c
@@ -433,11 +433,247 @@
433 }
434 Th_SetResult(interp, g.zRepositoryName, -1);
435 return TH_OK;
436 }
437
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
438 #ifdef TH_USE_SQLITE
 
 
 
 
 
 
 
439 static int queryPrepareCmd(
440 Th_Interp *interp,
441 void *p,
442 int argc,
443 const char **argv,
@@ -498,10 +734,17 @@
498 }
499 return pStmt;
500
501 }
502
 
 
 
 
 
 
 
503 static int queryFinalizeCmd(
504 Th_Interp *interp,
505 void *p,
506 int argc,
507 const char **argv,
@@ -523,10 +766,13 @@
523 rc = Th_FinalizeStmt( interp, rc );
524 Th_SetResultInt( interp, rc );
525 return TH_OK;
526 }
527
 
 
 
528 static int queryReportDbErr( Th_Interp * interp ){
529 char const * msg = sqlite3_errmsg( g.db );
530 Th_ErrorMessage(interp, "db error:", msg, -1);
531 return TH_ERROR;
532 }
@@ -575,10 +821,18 @@
575 }
576 return 0;
577 }
578 }
579
 
 
 
 
 
 
 
 
580 static int queryStepCmd(
581 Th_Interp *interp,
582 void *p,
583 int argc,
584 const char **argv,
@@ -606,10 +860,17 @@
606 }
607 Th_SetResultInt( interp, rc );
608 return TH_OK;
609 }
610
 
 
 
 
 
 
 
611 static int queryColStringCmd(
612 Th_Interp *interp,
613 void *p,
614 int argc,
615 const char **argv,
@@ -630,10 +891,17 @@
630 valLen = val ? sqlite3_column_bytes( pStmt, index ) : 0;
631 Th_SetResult( interp, val, valLen );
632 return TH_OK;
633 }
634
 
 
 
 
 
 
 
635 static int queryColIntCmd(
636 Th_Interp *interp,
637 void *p,
638 int argc,
639 const char **argv,
@@ -651,10 +919,17 @@
651 }
652 Th_SetResultInt( interp, sqlite3_column_int( pStmt, index ) );
653 return TH_OK;
654 }
655
 
 
 
 
 
 
 
656 static int queryColDoubleCmd(
657 Th_Interp *interp,
658 void *p,
659 int argc,
660 const char **argv,
@@ -672,10 +947,18 @@
672 }
673 Th_SetResultDouble( interp, sqlite3_column_double( pStmt, index ) );
674 return TH_OK;
675 }
676
 
 
 
 
 
 
 
 
677 static int queryColIsNullCmd(
678 Th_Interp *interp,
679 void *p,
680 int argc,
681 const char **argv,
@@ -689,14 +972,25 @@
689 }
690 queryStmtIndexArgs(interp, argc, argv, argl, &pStmt, &index);
691 if(index < 0){
692 return TH_ERROR;
693 }
694 Th_SetResultInt( interp, SQLITE_NULL==sqlite3_column_type( pStmt, index ) );
 
 
695 return TH_OK;
696 }
697
 
 
 
 
 
 
 
 
 
698 static int queryColTypeCmd(
699 Th_Interp *interp,
700 void *p,
701 int argc,
702 const char **argv,
@@ -714,10 +1008,17 @@
714 }
715 Th_SetResultInt( interp, sqlite3_column_type( pStmt, index ) );
716 return TH_OK;
717 }
718
 
 
 
 
 
 
 
719 static int queryColCountCmd(
720 Th_Interp *interp,
721 void *p,
722 int argc,
723 const char **argv,
@@ -735,10 +1036,17 @@
735 rc = sqlite3_column_count( pStmt );
736 Th_SetResultInt( interp, rc );
737 return TH_OK;
738 }
739
 
 
 
 
 
 
 
740 static int queryColNameCmd(
741 Th_Interp *interp,
742 void *p,
743 int argc,
744 const char **argv,
@@ -767,10 +1075,17 @@
767 Th_SetResult( interp, val, strlen( val ) );
768 return TH_OK;
769 }
770 }
771
 
 
 
 
 
 
 
772 static int queryBindNullCmd(
773 Th_Interp *interp,
774 void *p,
775 int argc,
776 const char **argv,
@@ -793,10 +1108,17 @@
793 Th_SetResultInt( interp, 0 );
794 return TH_OK;
795 }
796
797
 
 
 
 
 
 
 
798 static int queryBindStringCmd(
799 Th_Interp *interp,
800 void *p,
801 int argc,
802 const char **argv,
@@ -818,10 +1140,17 @@
818 }
819 Th_SetResultInt( interp, 0 );
820 return TH_OK;
821 }
822
 
 
 
 
 
 
 
823 static int queryBindIntCmd(
824 Th_Interp *interp,
825 void *p,
826 int argc,
827 const char **argv,
@@ -848,10 +1177,17 @@
848 }
849 Th_SetResultInt( interp, 0 );
850 return TH_OK;
851 }
852
 
 
 
 
 
 
 
853 static int queryBindDoubleCmd(
854 Th_Interp *interp,
855 void *p,
856 int argc,
857 const char **argv,
@@ -890,11 +1226,10 @@
890 ** The interpreter is stored in the g.interp global variable.
891 */
892 void Th_FossilInit(void){
893 static PutsCmdData puts_Html = {0, 0, 0};
894 static PutsCmdData puts_Normal = {1, 0, 0};
895 static PutsCmdData puts_Ext = {1, " ", "\n"};
896 static struct _Command {
897 const char *zName;
898 Th_CommandProc xProc;
899 void *pContext;
900 } aCommand[] = {
@@ -906,13 +1241,21 @@
906 {"hasfeature", hasfeatureCmd, 0},
907 {"htmlize", htmlizeCmd, 0},
908 {"date", dateCmd, 0},
909 {"html", putsCmd, &puts_Html},
910 {"puts", putsCmd, &puts_Normal},
911 {"putsl", putsCmd, &puts_Ext},
912 {"wiki", wikiCmd, 0},
913 {"repository", repositoryCmd, 0},
 
 
 
 
 
 
 
 
 
914 #ifdef TH_USE_SQLITE
915 {"query_bind_int", queryBindIntCmd, 0},
916 {"query_bind_double", queryBindDoubleCmd,0},
917 {"query_bind_null", queryBindNullCmd, 0},
918 {"query_bind_string", queryBindStringCmd,0},
@@ -925,10 +1268,11 @@
925 {"query_col_type", queryColTypeCmd, 0},
926 {"query_finalize", queryFinalizeCmd, 0},
927 {"query_prepare", queryPrepareCmd, 0},
928 {"query_step", queryStepCmd, 0},
929 #endif
 
930 {0, 0, 0}
931 };
932 if( g.interp==0 ){
933 int i;
934 g.interp = Th_CreateInterp(&vtab);
@@ -945,13 +1289,13 @@
945 }
946 #ifdef TH_USE_SQLITE
947 {
948 enum { BufLen = 100 };
949 char buf[BufLen];
950 int i;
951 #define SET(K) i = snprintf(buf, BufLen, "%d", K); \
952 Th_SetVar( g.interp, #K, strlen(#K), buf, i );
953 SET(SQLITE_BLOB);
954 SET(SQLITE_DONE);
955 SET(SQLITE_ERROR);
956 SET(SQLITE_FLOAT);
957 SET(SQLITE_INTEGER);
@@ -1119,17 +1463,26 @@
1119 return rc;
1120 }
1121
1122 /*
1123 ** COMMAND: test-th-render
 
 
 
 
 
 
 
 
1124 */
1125 void test_th_render(void){
1126 Blob in;
1127 if( g.argc<3 ){
1128 usage("FILE");
 
1129 }
1130 db_open_config(0); /* Needed for global "tcl" setting. */
1131 blob_zero(&in);
 
1132 db_find_and_open_repository(OPEN_ANY_SCHEMA,0) /* for query_xxx tests. */;
1133 blob_read_from_file(&in, g.argv[2]);
1134 Th_Render(blob_str(&in));
1135 }
1136
--- src/th_main.c
+++ src/th_main.c
@@ -433,11 +433,247 @@
433 }
434 Th_SetResult(interp, g.zRepositoryName, -1);
435 return TH_OK;
436 }
437
438
439 extern const char *find_option(const char *zLong, const char *zShort, int hasArg);
440
441 /*
442 ** TH Syntax:
443 **
444 ** argv_len
445 **
446 ** Returns the number of command-line arguments.
447 */
448 static int argvArgcCmd(
449 Th_Interp *interp,
450 void *p,
451 int argc,
452 const char **argv,
453 int *argl
454 ){
455 Th_SetResultInt( interp, g.argc );
456 return TH_OK;
457 }
458
459 #define TH_USE_ARGV
460 #ifdef TH_USE_ARGV
461 /*
462 ** TH Syntax:
463 **
464 ** argv_getat Index
465 **
466 ** Returns the raw argument at the given index, throwing if
467 ** out of bounds.
468 */
469 static int argvGetAtCmd(
470 Th_Interp *interp,
471 void *p,
472 int argc,
473 const char **argv,
474 int *argl
475 ){
476 char const * zVal;
477 int pos = 0;
478 if( argc != 2 ){
479 return Th_WrongNumArgs(interp, "argv_get Index");
480 }
481 if( TH_OK != Th_ToInt(interp, argv[1], argl[1], &pos) ){
482 return TH_ERROR;
483 }
484 if( pos < 0 || pos >= g.argc ){
485 Th_ErrorMessage(interp, "Argument out of range:", argv[1], argl[1]);
486 return TH_ERROR;
487 }
488 if( 0 == pos ){/*special case*/
489 zVal = fossil_nameofexe();
490 }else{
491 zVal = (pos>0 && pos<g.argc) ? g.argv[pos] : 0;
492 }
493 Th_SetResult( interp, zVal, zVal ? strlen(zVal) : 0 );
494 return TH_OK;
495 }
496
497
498 /*
499 ** TH Syntax:
500 **
501 ** argv_getstr longName ??shortName? ?defaultValue??
502 **
503 ** Functions more or less like Fossil's find_option().
504 ** If the given argument is found then its value is returned,
505 ** else defaultValue is returned. If that is not set
506 ** and the option is not found, an error is thrown.
507 ** If defaultValue is provided, shortName must also be provided
508 ** but it may be empty. For example:
509 **
510 ** set foo [argv_getstr foo "" "hi, world"]
511 **
512 ** ACHTUNG: find_option() removes any entries it finds from
513 ** g.argv, such that future calls to find_option() will not
514 ** find the same option.
515 */
516 static int argvFindOptionStringCmd(
517 Th_Interp *interp,
518 void *p,
519 int argc,
520 const char **argv,
521 int *argl
522 ){
523 enum { BufLen = 100 };
524 char zLong[BufLen] = {0};
525 char zShort[BufLen] = {0};
526 char aBuf[BufLen] = {0};
527 int hasArg;
528 char const * zVal = NULL;
529 char const * zDefault = NULL;
530 if( 1 < argc ){
531 assert( argl[1] < BufLen );
532 snprintf( zLong, BufLen, "%s", argv[1] );
533 }
534 if( (2 < argc) && (0 < argl[2]) ){
535 assert( argl[2] < BufLen );
536 snprintf( zShort, BufLen, "%s", argv[2] );
537 }
538 if( 3 < argc){
539 zDefault = argv[3];
540 }
541
542 if(0 == zLong[0]){
543 return Th_WrongNumArgs(interp, "argv_getstr longName ?shortName? ?defaultVal?");
544 }
545 zVal = find_option( zLong, zShort[0] ? zShort : NULL, 1 );
546 if(!zVal){
547 zVal = zDefault;
548 if(!zVal){
549 Th_ErrorMessage(interp, "Option not found and no default provided:", zLong, -1);
550 return TH_ERROR;
551 }
552 }
553 Th_SetResult( interp, zVal, zVal ? strlen(zVal) : 0 );
554 return TH_OK;
555 }
556
557 /*
558 ** TH Syntax:
559 **
560 ** argv_getbool longName ??shortName? ?defaultValue??
561 **
562 ** Works just like argv_getstr but treats any empty value or one
563 ** starting with the digit '0' as a boolean false.
564 **
565 ** Returns the result as an integer 0 (false) or 1 (true).
566 */
567 static int argvFindOptionBoolCmd(
568 Th_Interp *interp,
569 void *p,
570 int argc,
571 const char **argv,
572 int *argl
573 ){
574 enum { BufLen = 100 };
575 char zLong[BufLen] = {0};
576 char zShort[BufLen] = {0};
577 char aBuf[BufLen] = {0};
578 int hasArg;
579 char const * zVal = NULL;
580 char const * zDefault = NULL;
581 int val;
582 int rc;
583 if( 1 < argc ){
584 assert( argl[1] < BufLen );
585 snprintf( zLong, BufLen, "%s", argv[1] );
586 }
587 if( (2 < argc) && (0 < argl[2]) ){
588 assert( argl[2] < BufLen );
589 snprintf( zShort, BufLen, "%s", argv[2] );
590 }
591 if( 3 < argc){
592 zDefault = argv[3];
593 }
594
595 if(0 == zLong[0]){
596 return Th_WrongNumArgs(interp, "argv_getbool longName ?shortName? ?defaultVal?");
597 }
598 zVal = find_option( zLong, zShort[0] ? zShort : NULL, 0 );
599 if(zVal && !*zVal){
600 zVal = "1";
601 }
602 if(!zVal){
603 zVal = zDefault;
604 if(!zVal){
605 Th_ErrorMessage(interp, "Option not found and no default provided:", zLong, -1);
606 return TH_ERROR;
607 }
608 }
609 if( !*zVal ){
610 zVal = "0";
611 }
612 zVal = (zVal && *zVal && (*zVal!='0')) ? zVal : 0;
613 Th_SetResultInt( interp, zVal ? 1 : 0 );
614 return TH_OK;
615 }
616
617 /*
618 ** TH Syntax:
619 **
620 ** argv_getint longName ?shortName? ?defaultValue?
621 */
622 static int argvFindOptionIntCmd(
623 Th_Interp *interp,
624 void *p,
625 int argc,
626 const char **argv,
627 int *argl
628 ){
629 enum { BufLen = 100 };
630 char zLong[BufLen] = {0};
631 char zShort[BufLen] = {0};
632 char aBuf[BufLen] = {0};
633 int hasArg;
634 char const * zVal = NULL;
635 char const * zDefault = NULL;
636 int val = 0;
637 if( 1 < argc ){
638 assert( argl[1] < BufLen );
639 snprintf( zLong, BufLen, "%s", argv[1] );
640 }
641 if( (2 < argc) && (0 < argl[2]) ){
642 assert( argl[2] < BufLen );
643 snprintf( zShort, BufLen, "%s", argv[2] );
644 }
645 if( 3 < argc){
646 zDefault = argv[3];
647 }
648
649 if(0 == zLong[0]){
650 return Th_WrongNumArgs(interp, "argv_getint longName ?shortName? ?defaultVal?");
651 }
652 zVal = find_option( zLong, zShort[0] ? zShort : NULL, 0 );
653 if(!zVal){
654 zVal = zDefault;
655 if(!zVal){
656 Th_ErrorMessage(interp, "Option not found and no default provided:", zLong, -1);
657 return TH_ERROR;
658 }
659 }
660 Th_ToInt(interp, zVal, strlen(zVal), &val);
661 Th_SetResultInt( interp, val );
662 return TH_OK;
663 }
664 #endif
665 /* end TH_USE_ARGV */
666
667 #ifdef TH_USE_SQLITE
668 /*
669 ** TH Syntax:
670 **
671 ** query_prepare SQL
672 **
673 ** Returns an opaque statement identifier.
674 */
675 static int queryPrepareCmd(
676 Th_Interp *interp,
677 void *p,
678 int argc,
679 const char **argv,
@@ -498,10 +734,17 @@
734 }
735 return pStmt;
736
737 }
738
739 /*
740 ** TH Syntax:
741 **
742 ** query_finalize stmtId
743 **
744 ** sqlite3_finalize()s the given statement.
745 */
746 static int queryFinalizeCmd(
747 Th_Interp *interp,
748 void *p,
749 int argc,
750 const char **argv,
@@ -523,10 +766,13 @@
766 rc = Th_FinalizeStmt( interp, rc );
767 Th_SetResultInt( interp, rc );
768 return TH_OK;
769 }
770
771 /*
772 ** Reports the current sqlite3_errmsg() via TH and returns TH_ERROR.
773 */
774 static int queryReportDbErr( Th_Interp * interp ){
775 char const * msg = sqlite3_errmsg( g.db );
776 Th_ErrorMessage(interp, "db error:", msg, -1);
777 return TH_ERROR;
778 }
@@ -575,10 +821,18 @@
821 }
822 return 0;
823 }
824 }
825
826 /*
827 ** TH Syntax:
828 **
829 ** query_step stmtId
830 **
831 ** Steps the given statement handle. Returns 0 at the end of the set,
832 ** a positive value if it fetches a row, and throws on error.
833 */
834 static int queryStepCmd(
835 Th_Interp *interp,
836 void *p,
837 int argc,
838 const char **argv,
@@ -606,10 +860,17 @@
860 }
861 Th_SetResultInt( interp, rc );
862 return TH_OK;
863 }
864
865 /*
866 ** TH Syntax:
867 **
868 ** query_col_string stmtId Index
869 **
870 ** Returns the result column value at the given 0-based index.
871 */
872 static int queryColStringCmd(
873 Th_Interp *interp,
874 void *p,
875 int argc,
876 const char **argv,
@@ -630,10 +891,17 @@
891 valLen = val ? sqlite3_column_bytes( pStmt, index ) : 0;
892 Th_SetResult( interp, val, valLen );
893 return TH_OK;
894 }
895
896 /*
897 ** TH Syntax:
898 **
899 ** query_col_int stmtId Index
900 **
901 ** Returns the result column value at the given 0-based index.
902 */
903 static int queryColIntCmd(
904 Th_Interp *interp,
905 void *p,
906 int argc,
907 const char **argv,
@@ -651,10 +919,17 @@
919 }
920 Th_SetResultInt( interp, sqlite3_column_int( pStmt, index ) );
921 return TH_OK;
922 }
923
924 /*
925 ** TH Syntax:
926 **
927 ** query_col_double stmtId Index
928 **
929 ** Returns the result column value at the given 0-based index.
930 */
931 static int queryColDoubleCmd(
932 Th_Interp *interp,
933 void *p,
934 int argc,
935 const char **argv,
@@ -672,10 +947,18 @@
947 }
948 Th_SetResultDouble( interp, sqlite3_column_double( pStmt, index ) );
949 return TH_OK;
950 }
951
952 /*
953 ** TH Syntax:
954 **
955 ** query_col_is_null stmtId Index
956 **
957 ** Returns non-0 if the given 0-based result column index contains
958 ** an SQL NULL value, else returns 0.
959 */
960 static int queryColIsNullCmd(
961 Th_Interp *interp,
962 void *p,
963 int argc,
964 const char **argv,
@@ -689,14 +972,25 @@
972 }
973 queryStmtIndexArgs(interp, argc, argv, argl, &pStmt, &index);
974 if(index < 0){
975 return TH_ERROR;
976 }
977 Th_SetResultInt( interp,
978 SQLITE_NULL==sqlite3_column_type( pStmt, index )
979 ? 1 : 0);
980 return TH_OK;
981 }
982
983 /*
984 ** TH Syntax:
985 **
986 ** query_col_type stmtId Index
987 **
988 ** Returns the sqlite type identifier for the given 0-based result
989 ** column index. The values are available in TH as $SQLITE_NULL,
990 ** $SQLITE_INTEGER, etc.
991 */
992 static int queryColTypeCmd(
993 Th_Interp *interp,
994 void *p,
995 int argc,
996 const char **argv,
@@ -714,10 +1008,17 @@
1008 }
1009 Th_SetResultInt( interp, sqlite3_column_type( pStmt, index ) );
1010 return TH_OK;
1011 }
1012
1013 /*
1014 ** TH Syntax:
1015 **
1016 ** query_col_count stmtId
1017 **
1018 ** Returns the number of result columns in the query.
1019 */
1020 static int queryColCountCmd(
1021 Th_Interp *interp,
1022 void *p,
1023 int argc,
1024 const char **argv,
@@ -735,10 +1036,17 @@
1036 rc = sqlite3_column_count( pStmt );
1037 Th_SetResultInt( interp, rc );
1038 return TH_OK;
1039 }
1040
1041 /*
1042 ** TH Syntax:
1043 **
1044 ** query_col_count stmtId Index
1045 **
1046 ** Returns the result column name at the given 0-based index.
1047 */
1048 static int queryColNameCmd(
1049 Th_Interp *interp,
1050 void *p,
1051 int argc,
1052 const char **argv,
@@ -767,10 +1075,17 @@
1075 Th_SetResult( interp, val, strlen( val ) );
1076 return TH_OK;
1077 }
1078 }
1079
1080 /*
1081 ** TH Syntax:
1082 **
1083 ** query_bind_null stmtId Index
1084 **
1085 ** Binds a value to the given 1-based parameter index.
1086 */
1087 static int queryBindNullCmd(
1088 Th_Interp *interp,
1089 void *p,
1090 int argc,
1091 const char **argv,
@@ -793,10 +1108,17 @@
1108 Th_SetResultInt( interp, 0 );
1109 return TH_OK;
1110 }
1111
1112
1113 /*
1114 ** TH Syntax:
1115 **
1116 ** query_bind_string stmtId Index Value
1117 **
1118 ** Binds a value to the given 1-based parameter index.
1119 */
1120 static int queryBindStringCmd(
1121 Th_Interp *interp,
1122 void *p,
1123 int argc,
1124 const char **argv,
@@ -818,10 +1140,17 @@
1140 }
1141 Th_SetResultInt( interp, 0 );
1142 return TH_OK;
1143 }
1144
1145 /*
1146 ** TH Syntax:
1147 **
1148 ** query_bind_int stmtId Index Value
1149 **
1150 ** Binds a value to the given 1-based parameter index.
1151 */
1152 static int queryBindIntCmd(
1153 Th_Interp *interp,
1154 void *p,
1155 int argc,
1156 const char **argv,
@@ -848,10 +1177,17 @@
1177 }
1178 Th_SetResultInt( interp, 0 );
1179 return TH_OK;
1180 }
1181
1182 /*
1183 ** TH Syntax:
1184 **
1185 ** query_bind_double stmtId Index Value
1186 **
1187 ** Binds a value to the given 1-based parameter index.
1188 */
1189 static int queryBindDoubleCmd(
1190 Th_Interp *interp,
1191 void *p,
1192 int argc,
1193 const char **argv,
@@ -890,11 +1226,10 @@
1226 ** The interpreter is stored in the g.interp global variable.
1227 */
1228 void Th_FossilInit(void){
1229 static PutsCmdData puts_Html = {0, 0, 0};
1230 static PutsCmdData puts_Normal = {1, 0, 0};
 
1231 static struct _Command {
1232 const char *zName;
1233 Th_CommandProc xProc;
1234 void *pContext;
1235 } aCommand[] = {
@@ -906,13 +1241,21 @@
1241 {"hasfeature", hasfeatureCmd, 0},
1242 {"htmlize", htmlizeCmd, 0},
1243 {"date", dateCmd, 0},
1244 {"html", putsCmd, &puts_Html},
1245 {"puts", putsCmd, &puts_Normal},
 
1246 {"wiki", wikiCmd, 0},
1247 {"repository", repositoryCmd, 0},
1248
1249 #ifdef TH_USE_ARGV
1250 {"argv_len", argvArgcCmd, 0},
1251 {"argv_getat", argvGetAtCmd, 0},
1252 {"argv_getstr", argvFindOptionStringCmd, 0},
1253 {"argv_getbool", argvFindOptionBoolCmd, 0},
1254 {"argv_getint", argvFindOptionIntCmd, 0},
1255 #endif
1256
1257 #ifdef TH_USE_SQLITE
1258 {"query_bind_int", queryBindIntCmd, 0},
1259 {"query_bind_double", queryBindDoubleCmd,0},
1260 {"query_bind_null", queryBindNullCmd, 0},
1261 {"query_bind_string", queryBindStringCmd,0},
@@ -925,10 +1268,11 @@
1268 {"query_col_type", queryColTypeCmd, 0},
1269 {"query_finalize", queryFinalizeCmd, 0},
1270 {"query_prepare", queryPrepareCmd, 0},
1271 {"query_step", queryStepCmd, 0},
1272 #endif
1273
1274 {0, 0, 0}
1275 };
1276 if( g.interp==0 ){
1277 int i;
1278 g.interp = Th_CreateInterp(&vtab);
@@ -945,13 +1289,13 @@
1289 }
1290 #ifdef TH_USE_SQLITE
1291 {
1292 enum { BufLen = 100 };
1293 char buf[BufLen];
1294 int i, l;
1295 #define SET(K) l = snprintf(buf, BufLen, "%d", K); \
1296 Th_SetVar( g.interp, #K, strlen(#K), buf, l );
1297 SET(SQLITE_BLOB);
1298 SET(SQLITE_DONE);
1299 SET(SQLITE_ERROR);
1300 SET(SQLITE_FLOAT);
1301 SET(SQLITE_INTEGER);
@@ -1119,17 +1463,26 @@
1463 return rc;
1464 }
1465
1466 /*
1467 ** COMMAND: test-th-render
1468 ** COMMAND: th1
1469 **
1470 ** Processes a file provided on the command line as a TH1-capable
1471 ** script/page. Output is sent to stdout or the CGI output buffer, as
1472 ** appropriate. The input file is assumed to be text/wiki/HTML content
1473 ** which may contain TH1 tag blocks. Each block is executed in the
1474 ** same TH1 interpreter instance.
1475 **
1476 */
1477 void test_th_render(void){
1478 Blob in;
1479 if( g.argc<3 ){
1480 usage("FILE");
1481 assert(0 && "usage() does not return");
1482 }
 
1483 blob_zero(&in);
1484 db_open_config(0); /* Needed for global "tcl" setting. */
1485 db_find_and_open_repository(OPEN_ANY_SCHEMA,0) /* for query_xxx tests. */;
1486 blob_read_from_file(&in, g.argv[2]);
1487 Th_Render(blob_str(&in));
1488 }
1489
--- test/th1-query-api-1.th1
+++ test/th1-query-api-1.th1
@@ -25,14 +25,11 @@
2525
puts "a=${a}" ! \n
2626
2727
set stmt [query_prepare {SELECT login, cap FROM user}]
2828
set colCount [query_col_count $stmt]
2929
puts "query column count: ${colCount}\n"
30
-#set stmt2 [query_prepare {SELECT cap, login FROM user}]
31
-#puts "stmt=${stmt} stmt2=${stmt2}\n"
32
-#putsl "step =" [query_step $stmt]
33
-#putsl "cap =" [query_col_string $stmt 1]
30
+puts "stmt id=${stmt}\n"
3431
3532
proc noop {} {}
3633
proc incr {name {step 1}} {
3734
upvar $name x
3835
set x [expr $x+$step]
@@ -59,11 +56,10 @@
5956
puts "\n"
6057
}
6158
unset row
6259
6360
query_finalize $stmt
64
-#query_finalize $stmt2
6561
6662
6763
proc query_step_each {{stmt} {callback}} {
6864
set colNames(0) 0
6965
set colCount [query_col_count $stmt]
@@ -117,7 +113,26 @@
117113
for {set i 0} {$i < [llength $consts]} {incr i} {
118114
set x [lindex $consts $i]
119115
puts \$$x = [expr \$$x] "\n"
120116
}
121117
118
+set ARGC [argv_len]
119
+puts ARGC = $ARGC "\n"
120
+for {set i 0} {$i < $ARGC} {incr i} {
121
+ puts "argv_getat $i = " [argv_getat $i] \n
122
+}
123
+
124
+set magicDefault hi
125
+set optA [argv_getstr AA a $magicDefault]
126
+puts "argv_getstr AA = " $optA \n
127
+
128
+set optA [argv_getbool BB b 0]
129
+puts "argv_getbool BB = " $optA \n
130
+
131
+set exception 0
132
+catch {
133
+ argv_getint noSuchOptionAndNoDefault
134
+} exception
135
+puts exception = $exception "\n"
136
+
122137
puts "If you got this far, you win!\n"
123138
</th1>
124139
--- test/th1-query-api-1.th1
+++ test/th1-query-api-1.th1
@@ -25,14 +25,11 @@
25 puts "a=${a}" ! \n
26
27 set stmt [query_prepare {SELECT login, cap FROM user}]
28 set colCount [query_col_count $stmt]
29 puts "query column count: ${colCount}\n"
30 #set stmt2 [query_prepare {SELECT cap, login FROM user}]
31 #puts "stmt=${stmt} stmt2=${stmt2}\n"
32 #putsl "step =" [query_step $stmt]
33 #putsl "cap =" [query_col_string $stmt 1]
34
35 proc noop {} {}
36 proc incr {name {step 1}} {
37 upvar $name x
38 set x [expr $x+$step]
@@ -59,11 +56,10 @@
59 puts "\n"
60 }
61 unset row
62
63 query_finalize $stmt
64 #query_finalize $stmt2
65
66
67 proc query_step_each {{stmt} {callback}} {
68 set colNames(0) 0
69 set colCount [query_col_count $stmt]
@@ -117,7 +113,26 @@
117 for {set i 0} {$i < [llength $consts]} {incr i} {
118 set x [lindex $consts $i]
119 puts \$$x = [expr \$$x] "\n"
120 }
121
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
122 puts "If you got this far, you win!\n"
123 </th1>
124
--- test/th1-query-api-1.th1
+++ test/th1-query-api-1.th1
@@ -25,14 +25,11 @@
25 puts "a=${a}" ! \n
26
27 set stmt [query_prepare {SELECT login, cap FROM user}]
28 set colCount [query_col_count $stmt]
29 puts "query column count: ${colCount}\n"
30 puts "stmt id=${stmt}\n"
 
 
 
31
32 proc noop {} {}
33 proc incr {name {step 1}} {
34 upvar $name x
35 set x [expr $x+$step]
@@ -59,11 +56,10 @@
56 puts "\n"
57 }
58 unset row
59
60 query_finalize $stmt
 
61
62
63 proc query_step_each {{stmt} {callback}} {
64 set colNames(0) 0
65 set colCount [query_col_count $stmt]
@@ -117,7 +113,26 @@
113 for {set i 0} {$i < [llength $consts]} {incr i} {
114 set x [lindex $consts $i]
115 puts \$$x = [expr \$$x] "\n"
116 }
117
118 set ARGC [argv_len]
119 puts ARGC = $ARGC "\n"
120 for {set i 0} {$i < $ARGC} {incr i} {
121 puts "argv_getat $i = " [argv_getat $i] \n
122 }
123
124 set magicDefault hi
125 set optA [argv_getstr AA a $magicDefault]
126 puts "argv_getstr AA = " $optA \n
127
128 set optA [argv_getbool BB b 0]
129 puts "argv_getbool BB = " $optA \n
130
131 set exception 0
132 catch {
133 argv_getint noSuchOptionAndNoDefault
134 } exception
135 puts exception = $exception "\n"
136
137 puts "If you got this far, you win!\n"
138 </th1>
139

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button