diff options
author | drh <> | 2023-02-08 12:47:37 +0000 |
---|---|---|
committer | drh <> | 2023-02-08 12:47:37 +0000 |
commit | 821fe31fd7fe0ff69457e97a522ccfe892cc3d1e (patch) | |
tree | e4f857f3b84af76b159c3937066feb6516e6fafd /src | |
parent | 51b0373998e820ba81bab459e9134c4a9cec6225 (diff) | |
parent | 159cbfe1cbb9a725cb206479181870adfcb8b6fa (diff) | |
download | sqlite-821fe31fd7fe0ff69457e97a522ccfe892cc3d1e.tar.gz sqlite-821fe31fd7fe0ff69457e97a522ccfe892cc3d1e.zip |
Add the 'txn' date/time format. Change CURRENT_TIMESTAMP and similar to use
'tnx'-style semantics instead of 'now'-style.
FossilOrigin-Name: 61cc8ed8d3541eddf23a9d542179c3f0223c5b8519b54d3be79988a376e25a89
Diffstat (limited to 'src')
-rw-r--r-- | src/date.c | 33 | ||||
-rw-r--r-- | src/sqliteInt.h | 3 | ||||
-rw-r--r-- | src/vdbeapi.c | 17 | ||||
-rw-r--r-- | src/vdbeaux.c | 1 |
4 files changed, 37 insertions, 17 deletions
diff --git a/src/date.c b/src/date.c index a3e58bc4e..8546b5dc8 100644 --- a/src/date.c +++ b/src/date.c @@ -331,12 +331,16 @@ static int parseYyyyMmDd(const char *zDate, DateTime *p){ } /* -** Set the time to the current time reported by the VFS. +** Set the time to the current time reported for the prepared statement +** that is currently executing. The same time is reported for all +** invocations of this routine from within the same call to sqlite3_step(). +** +** Or if bTxn is true, use the transaction time. ** ** Return the number of errors. */ -static int setDateTimeToCurrent(sqlite3_context *context, DateTime *p){ - p->iJD = sqlite3StmtCurrentTime(context); +static int setCurrentStmtTime(sqlite3_context *context, DateTime *p, int bTxn){ + p->iJD = sqlite3StmtCurrentTime(context, bTxn); if( p->iJD>0 ){ p->validJD = 1; return 0; @@ -387,7 +391,9 @@ static int parseDateOrTime( }else if( parseHhMmSs(zDate, p)==0 ){ return 0; }else if( sqlite3StrICmp(zDate,"now")==0 && sqlite3NotPureFunc(context) ){ - return setDateTimeToCurrent(context, p); + return setCurrentStmtTime(context, p, 0); + }else if( sqlite3StrICmp(zDate,"txn")==0 && sqlite3NotPureFunc(context) ){ + return setCurrentStmtTime(context, p, 1); }else if( sqlite3AtoF(zDate, &r, sqlite3Strlen30(zDate), SQLITE_UTF8)>0 ){ setRawDateNumber(p, r); return 0; @@ -931,8 +937,11 @@ static int parseModifier( ** the resulting time into the DateTime structure p. Return 0 ** on success and 1 if there are any errors. ** -** If there are zero parameters (if even argv[0] is undefined) -** then assume a default value of "now" for argv[0]. +** If there are zero parameters (if argc<=0) then assume a default +** value of "now" for argv[0] if argc==0 and "txn" if argc<0. SQL +** functions will always have argc>=0, but the special implementations +** of CURRENT_TIME, CURRENT_DATE, and CURRENT_TIMESTAMP set argc to -1 +** in order to force the use of 'txn' semantics. */ static int isDate( sqlite3_context *context, @@ -944,9 +953,9 @@ static int isDate( const unsigned char *z; int eType; memset(p, 0, sizeof(*p)); - if( argc==0 ){ + if( argc<=0 ){ if( !sqlite3NotPureFunc(context) ) return 1; - return setDateTimeToCurrent(context, p); + return setCurrentStmtTime(context, p, argc<0); } if( (eType = sqlite3_value_type(argv[0]))==SQLITE_FLOAT || eType==SQLITE_INTEGER ){ @@ -1253,7 +1262,7 @@ static void ctimeFunc( sqlite3_value **NotUsed2 ){ UNUSED_PARAMETER2(NotUsed, NotUsed2); - timeFunc(context, 0, 0); + timeFunc(context, -1, 0); } /* @@ -1267,7 +1276,7 @@ static void cdateFunc( sqlite3_value **NotUsed2 ){ UNUSED_PARAMETER2(NotUsed, NotUsed2); - dateFunc(context, 0, 0); + dateFunc(context, -1, 0); } /* @@ -1281,7 +1290,7 @@ static void ctimestampFunc( sqlite3_value **NotUsed2 ){ UNUSED_PARAMETER2(NotUsed, NotUsed2); - datetimeFunc(context, 0, 0); + datetimeFunc(context, -1, 0); } #endif /* !defined(SQLITE_OMIT_DATETIME_FUNCS) */ @@ -1312,7 +1321,7 @@ static void currentTimeFunc( UNUSED_PARAMETER(argc); UNUSED_PARAMETER(argv); - iT = sqlite3StmtCurrentTime(context); + iT = sqlite3StmtCurrentTime(context, 1); if( iT<=0 ) return; t = iT/1000 - 10000*(sqlite3_int64)21086676; #if HAVE_GMTIME_R diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 3da5f13d5..73378dbf6 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -1621,6 +1621,7 @@ struct sqlite3 { u8 nSqlExec; /* Number of pending OP_SqlExec opcodes */ u8 eOpenState; /* Current condition of the connection */ int nextPagesize; /* Pagesize after VACUUM if >0 */ + i64 txnTime; /* Timestamp for current transaction */ i64 nChange; /* Value returned by sqlite3_changes() */ i64 nTotalChange; /* Value returned by sqlite3_total_changes() */ int aLimit[SQLITE_N_LIMIT]; /* Limits */ @@ -5340,7 +5341,7 @@ FuncDef *sqlite3VtabOverloadFunction(sqlite3 *,FuncDef*, int nArg, Expr*); && !defined(SQLITE_OMIT_VIRTUALTABLE) void sqlite3VtabUsesAllSchemas(sqlite3_index_info*); #endif -sqlite3_int64 sqlite3StmtCurrentTime(sqlite3_context*); +sqlite3_int64 sqlite3StmtCurrentTime(sqlite3_context*, int); int sqlite3VdbeParameterIndex(Vdbe*, const char*, int); int sqlite3TransferBindings(sqlite3_stmt *, sqlite3_stmt *); void sqlite3ParseObjectInit(Parse*,sqlite3*); diff --git a/src/vdbeapi.c b/src/vdbeapi.c index 476b6a2ad..722d1215f 100644 --- a/src/vdbeapi.c +++ b/src/vdbeapi.c @@ -970,18 +970,27 @@ int sqlite3_vtab_in_next(sqlite3_value *pVal, sqlite3_value **ppOut){ ** statement, the exact same time is returned for each invocation regardless ** of the amount of time that elapses between invocations. In other words, ** the time returned is always the time of the first call. +** +** Or, if bTxn, return the transaction time. The transaction time is the +** same for all calls within the same transaction. +** +** bTxn is 0 for SQL like datetime('now') and is 1 for datetime('txn'). */ -sqlite3_int64 sqlite3StmtCurrentTime(sqlite3_context *p){ +sqlite3_int64 sqlite3StmtCurrentTime(sqlite3_context *p, int bTxn){ int rc; #ifndef SQLITE_ENABLE_STAT4 - sqlite3_int64 *piTime = &p->pVdbe->iCurrentTime; + sqlite3_int64 *piTime; + sqlite3 *db = p->pOut->db; assert( p->pVdbe!=0 ); + piTime = bTxn ? &db->txnTime : &p->pVdbe->iCurrentTime; #else sqlite3_int64 iTime = 0; - sqlite3_int64 *piTime = p->pVdbe!=0 ? &p->pVdbe->iCurrentTime : &iTime; + sqlite3_int64 *piTime; + sqlite3 *db = p->pOut->db; + piTime = bTxn ? &db->txnTime : p->pVdbe!=0 ? &p->pVdbe->iCurrentTime : &iTime; #endif if( *piTime==0 ){ - rc = sqlite3OsCurrentTimeInt64(p->pOut->db->pVfs, piTime); + rc = sqlite3OsCurrentTimeInt64(db->pVfs, piTime); if( rc ) *piTime = 0; } return *piTime; diff --git a/src/vdbeaux.c b/src/vdbeaux.c index d04d8f1e1..82dc60715 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -3394,6 +3394,7 @@ int sqlite3VdbeHalt(Vdbe *p){ */ if( db->autoCommit ){ sqlite3ConnectionUnlocked(db); + db->txnTime = 0; } assert( db->nVdbeActive>0 || db->autoCommit==0 || db->nStatement==0 ); |