Skip to content

Commit bd0267e

Browse files
committed
Implement statement_timeout with timespecs
1 parent 31e44c1 commit bd0267e

File tree

5 files changed

+33
-8
lines changed

5 files changed

+33
-8
lines changed

ext/sqlite3/database.c

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,11 @@
1212

1313
VALUE cSqlite3Database;
1414

15+
// Function to check if two timespec structures are equal
16+
int timespec_equal(const struct timespec* ts1, const struct timespec* ts2) {
17+
return (ts1->tv_sec == ts2->tv_sec) && (ts1->tv_nsec == ts2->tv_nsec);
18+
}
19+
1520
static void
1621
database_mark(void *ctx)
1722
{
@@ -266,12 +271,11 @@ rb_sqlite3_statement_timeout(void *context)
266271
struct timespec currentTime;
267272
clock_gettime(CLOCK_MONOTONIC, &currentTime);
268273

269-
if (ctx->stmt_deadline == 0) {
270-
ctx->stmt_deadline = currentTime.tv_sec * 1e9 + currentTime.tv_nsec + (long long)ctx->stmt_timeout * 1e6;
271-
} else {
272-
long long timeDiff = ctx->stmt_deadline - (currentTime.tv_sec * 1e9 + currentTime.tv_nsec);
273-
274-
if (timeDiff < 0) { return 1; }
274+
if (!timespecisset(&ctx->stmt_deadline)) {
275+
// Set stmt_deadline if not already set
276+
ctx->stmt_deadline = currentTime;
277+
} else if (timespecafter(&currentTime, &ctx->stmt_deadline)) {
278+
return 1;
275279
}
276280

277281
return 0;

ext/sqlite3/database.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ struct _sqlite3Ruby {
77
sqlite3 *db;
88
VALUE busy_handler;
99
int stmt_timeout;
10-
long long stmt_deadline;
10+
struct timespec stmt_deadline;
1111
};
1212

1313
typedef struct _sqlite3Ruby sqlite3Ruby;

ext/sqlite3/sqlite3_ruby.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ extern VALUE cSqlite3Blob;
4141
#include <statement.h>
4242
#include <exception.h>
4343
#include <backup.h>
44+
#include <timespec.h>
4445

4546
int bignum_to_int64(VALUE big, sqlite3_int64 *result);
4647

ext/sqlite3/statement.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ prepare(VALUE self, VALUE db, VALUE sql)
7070
);
7171

7272
CHECK(db_ctx->db, status);
73-
db_ctx->stmt_deadline = 0;
73+
timespecclear(&db_ctx->stmt_deadline);
7474

7575
return rb_str_new2(tail);
7676
}

ext/sqlite3/timespec.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#define timespecclear(tsp) (tsp)->tv_sec = (tsp)->tv_nsec = 0
2+
#define timespecisset(tsp) ((tsp)->tv_sec || (tsp)->tv_nsec)
3+
#define timespecisvalid(tsp) \
4+
((tsp)->tv_nsec >= 0 && (tsp)->tv_nsec < 1000000000L)
5+
#define timespeccmp(tsp, usp, cmp) \
6+
(((tsp)->tv_sec == (usp)->tv_sec) ? \
7+
((tsp)->tv_nsec cmp (usp)->tv_nsec) : \
8+
((tsp)->tv_sec cmp (usp)->tv_sec))
9+
#define timespecsub(tsp, usp, vsp) \
10+
do { \
11+
(vsp)->tv_sec = (tsp)->tv_sec - (usp)->tv_sec; \
12+
(vsp)->tv_nsec = (tsp)->tv_nsec - (usp)->tv_nsec; \
13+
if ((vsp)->tv_nsec < 0) { \
14+
(vsp)->tv_sec--; \
15+
(vsp)->tv_nsec += 1000000000L; \
16+
} \
17+
} while (0)
18+
#define timespecafter(tsp, usp) \
19+
(((tsp)->tv_sec > (usp)->tv_sec) || \
20+
((tsp)->tv_sec == (usp)->tv_sec && (tsp)->tv_nsec > (usp)->tv_nsec))

0 commit comments

Comments
 (0)