aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/date.c29
-rw-r--r--src/sqliteInt.h2
-rw-r--r--src/vdbeapi.c23
-rw-r--r--src/vdbeaux.c1
4 files changed, 51 insertions, 4 deletions
diff --git a/src/date.c b/src/date.c
index a3e58bc4e..21077df93 100644
--- a/src/date.c
+++ b/src/date.c
@@ -331,11 +331,13 @@ 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().
**
** Return the number of errors.
*/
-static int setDateTimeToCurrent(sqlite3_context *context, DateTime *p){
+static int setCurrentStmtTime(sqlite3_context *context, DateTime *p){
p->iJD = sqlite3StmtCurrentTime(context);
if( p->iJD>0 ){
p->validJD = 1;
@@ -346,6 +348,23 @@ static int setDateTimeToCurrent(sqlite3_context *context, DateTime *p){
}
/*
+** Set the time to the current time reported for the current transaction.
+** The same time is set for all calls to this routine within the same
+** transaction.
+**
+** Return the number of errors.
+*/
+static int setCurrentTxnTime(sqlite3_context *context, DateTime *p){
+ p->iJD = sqlite3TxnCurrentTime(context);
+ if( p->iJD>0 ){
+ p->validJD = 1;
+ return 0;
+ }else{
+ return 1;
+ }
+}
+
+/*
** Input "r" is a numeric quantity which might be a julian day number,
** or the number of seconds since 1970. If the value if r is within
** range of a julian day number, install it as such and set validJD.
@@ -387,7 +406,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);
+ }else if( sqlite3StrICmp(zDate,"txn")==0 && sqlite3NotPureFunc(context) ){
+ return setCurrentTxnTime(context, p);
}else if( sqlite3AtoF(zDate, &r, sqlite3Strlen30(zDate), SQLITE_UTF8)>0 ){
setRawDateNumber(p, r);
return 0;
@@ -946,7 +967,7 @@ static int isDate(
memset(p, 0, sizeof(*p));
if( argc==0 ){
if( !sqlite3NotPureFunc(context) ) return 1;
- return setDateTimeToCurrent(context, p);
+ return setCurrentStmtTime(context, p);
}
if( (eType = sqlite3_value_type(argv[0]))==SQLITE_FLOAT
|| eType==SQLITE_INTEGER ){
diff --git a/src/sqliteInt.h b/src/sqliteInt.h
index 3da5f13d5..638260c5d 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 */
@@ -5341,6 +5342,7 @@ FuncDef *sqlite3VtabOverloadFunction(sqlite3 *,FuncDef*, int nArg, Expr*);
void sqlite3VtabUsesAllSchemas(sqlite3_index_info*);
#endif
sqlite3_int64 sqlite3StmtCurrentTime(sqlite3_context*);
+sqlite3_int64 sqlite3TxnCurrentTime(sqlite3_context*);
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..432c1fa22 100644
--- a/src/vdbeapi.c
+++ b/src/vdbeapi.c
@@ -988,6 +988,29 @@ sqlite3_int64 sqlite3StmtCurrentTime(sqlite3_context *p){
}
/*
+** Return the current time for a transaction. If the current time
+** is requested more than once within the same transaction
+** the 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.
+*/
+sqlite3_int64 sqlite3TxnCurrentTime(sqlite3_context *p){
+ int rc;
+#ifndef SQLITE_ENABLE_STAT4
+ sqlite3_int64 *piTime = &p->pVdbe->db->txnTime;
+ assert( p->pVdbe!=0 );
+#else
+ sqlite3_int64 iTime = 0;
+ sqlite3_int64 *piTime = p->pVdbe!=0 ? &p->pVdbe->db->txnTime : &iTime;
+#endif
+ if( *piTime==0 ){
+ rc = sqlite3OsCurrentTimeInt64(p->pOut->db->pVfs, piTime);
+ if( rc ) *piTime = 0;
+ }
+ return *piTime;
+}
+
+/*
** Create a new aggregate context for p and return a pointer to
** its pMem->z element.
*/
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 );