@@ -41,6 +41,7 @@ typedef struct ConnCacheEntry
41
41
bool keep_connections ; /* setting value of keep_connections
42
42
* server option */
43
43
bool truncatable ; /* check table can truncate or not */
44
+ bool readonly ; /* option force_readonly, readonly SQLite file mode */
44
45
bool invalidated ; /* true if reconnect is pending */
45
46
Oid serverid ; /* foreign server OID used to get server name */
46
47
List * stmtList ; /* list stmt associated with conn */
@@ -60,7 +61,7 @@ PG_FUNCTION_INFO_V1(sqlite_fdw_get_connections);
60
61
PG_FUNCTION_INFO_V1 (sqlite_fdw_disconnect );
61
62
PG_FUNCTION_INFO_V1 (sqlite_fdw_disconnect_all );
62
63
63
- static sqlite3 * sqlite_open_db (const char * dbpath );
64
+ static sqlite3 * sqlite_open_db (const char * dbpath , int flags );
64
65
static void sqlite_make_new_connection (ConnCacheEntry * entry , ForeignServer * server );
65
66
void sqlite_do_sql_command (sqlite3 * conn , const char * sql , int level , List * * busy_connection );
66
67
static void sqlite_begin_remote_xact (ConnCacheEntry * entry );
@@ -184,21 +185,21 @@ sqlite_get_connection(ForeignServer *server, bool truncatable)
184
185
}
185
186
186
187
/*
187
- * Open remote sqlite database using specified database path.
188
+ * Open remote sqlite database using specified database path
189
+ * and flags of opened file descriptor mode.
188
190
*/
189
191
static sqlite3 *
190
- sqlite_open_db (const char * dbpath )
192
+ sqlite_open_db (const char * dbpath , int flags )
191
193
{
192
194
sqlite3 * conn = NULL ;
193
195
int rc ;
194
196
char * err ;
195
-
196
- rc = sqlite3_open (dbpath , & conn );
197
+ const char * zVfs = NULL ;
198
+ rc = sqlite3_open_v2 (dbpath , & conn , flags , zVfs );
197
199
if (rc != SQLITE_OK )
198
200
ereport (ERROR ,
199
201
(errcode (ERRCODE_FDW_UNABLE_TO_ESTABLISH_CONNECTION ),
200
- errmsg ("failed to open SQLite DB. rc=%d path=%s" , rc , dbpath )));
201
-
202
+ errmsg ("Failed to open SQLite DB, file '%s', result code %d" , dbpath , rc )));
202
203
/* make 'LIKE' of SQLite case sensitive like PostgreSQL */
203
204
rc = sqlite3_exec (conn , "pragma case_sensitive_like=1" ,
204
205
NULL , NULL , & err );
@@ -208,9 +209,10 @@ sqlite_open_db(const char *dbpath)
208
209
209
210
sqlite3_free (err );
210
211
sqlite3_close (conn );
212
+ conn = NULL ;
211
213
ereport (ERROR ,
212
214
(errcode (ERRCODE_FDW_UNABLE_TO_ESTABLISH_CONNECTION ),
213
- errmsg ("failed to open SQLite DB. rc=%d err=%s " , rc , perr )));
215
+ errmsg ("Failed to open SQLite DB, file '%s', SQLite error '%s', result code %d " , dbpath , perr , rc )));
214
216
}
215
217
/* add included inner SQLite functions from separate c file
216
218
* for using in data unifying during deparsing
@@ -219,6 +221,7 @@ sqlite_open_db(const char *dbpath)
219
221
return conn ;
220
222
}
221
223
224
+
222
225
/*
223
226
* Reset all transient state fields in the cached connection entry and
224
227
* establish new connection to the remote server.
@@ -228,6 +231,7 @@ sqlite_make_new_connection(ConnCacheEntry *entry, ForeignServer *server)
228
231
{
229
232
const char * dbpath = NULL ;
230
233
ListCell * lc ;
234
+ int flags = 0 ;
231
235
232
236
Assert (entry -> conn == NULL );
233
237
@@ -236,6 +240,7 @@ sqlite_make_new_connection(ConnCacheEntry *entry, ForeignServer *server)
236
240
entry -> invalidated = false;
237
241
entry -> stmtList = NULL ;
238
242
entry -> keep_connections = true;
243
+ entry -> readonly = false;
239
244
entry -> server_hashvalue =
240
245
GetSysCacheHashValue1 (FOREIGNSERVEROID ,
241
246
ObjectIdGetDatum (server -> serverid ));
@@ -247,10 +252,13 @@ sqlite_make_new_connection(ConnCacheEntry *entry, ForeignServer *server)
247
252
dbpath = defGetString (def );
248
253
else if (strcmp (def -> defname , "keep_connections" ) == 0 )
249
254
entry -> keep_connections = defGetBoolean (def );
255
+ else if (strcmp (def -> defname , "force_readonly" ) == 0 )
256
+ entry -> readonly = defGetBoolean (def );
250
257
}
251
258
259
+ flags = flags | (entry -> readonly ? SQLITE_OPEN_READONLY : SQLITE_OPEN_READWRITE );
252
260
/* Try to make the connection */
253
- entry -> conn = sqlite_open_db (dbpath );
261
+ entry -> conn = sqlite_open_db (dbpath , flags );
254
262
}
255
263
256
264
/*
@@ -282,8 +290,9 @@ sqlite_cleanup_connection(void)
282
290
{
283
291
ereport (ERROR ,
284
292
(errcode (ERRCODE_FDW_UNABLE_TO_CREATE_EXECUTION ),
285
- errmsg ("close connection failed: %s rc=%d" , sqlite3_errmsg (entry -> conn ), rc )
286
- ));
293
+ errmsg ("Failed to close SQLite DB" ),
294
+ errhint ("SQLite error '%s', SQLite result code %d" , sqlite3_errmsg (entry -> conn ), rc )
295
+ ));
287
296
}
288
297
}
289
298
}
@@ -327,15 +336,18 @@ sqlite_do_sql_command(sqlite3 * conn, const char *sql, int level, List **busy_co
327
336
{
328
337
ereport (level ,
329
338
(errcode (ERRCODE_FDW_ERROR ),
330
- errmsg ("SQLite failed to execute sql: %s %s" , sql , perr )
331
- ));
339
+ errmsg ("SQLite failed to execute a query" ),
340
+ errcontext ("SQL query: %s" , sql ),
341
+ errhint ("SQLite error '%s'" , perr )));
342
+
332
343
pfree (perr );
333
344
}
334
345
}
335
346
else
336
347
ereport (level ,
337
348
(errcode (ERRCODE_FDW_ERROR ),
338
- errmsg ("SQLite failed to execute sql: %s" , sql )
349
+ errmsg ("SQLite failed to execute a query" ),
350
+ errcontext ("SQL query: %s" , sql )
339
351
));
340
352
}
341
353
}
@@ -401,10 +413,10 @@ sqlitefdw_report_error(int elevel, sqlite3_stmt * stmt, sqlite3 * conn,
401
413
}
402
414
ereport (ERROR ,
403
415
(errcode (sqlstate ),
404
- errmsg ("failed to execute remote SQL: rc=%d %s \n sql=%s" ,
405
- rc , message ? message : "" , sql ? sql : "" )
406
- ));
407
-
416
+ errmsg ("Failed to execute remote SQL" ) ,
417
+ errcontext ( "SQL query: %s" , sql ? sql : "" ),
418
+ errhint ( "SQLite error '%s', SQLite result code %d" , message ? message : "" , rc )
419
+ ));
408
420
}
409
421
410
422
@@ -903,9 +915,12 @@ sqlitefdw_abort_cleanup(ConnCacheEntry *entry, bool toplevel, List **busy_connec
903
915
{
904
916
char sql [100 ];
905
917
int curlevel = GetCurrentTransactionNestLevel ();
906
- snprintf (sql , sizeof (sql ),
907
- "ROLLBACK TO SAVEPOINT s%d; RELEASE SAVEPOINT s%d" ,
908
- curlevel , curlevel );
918
+ snprintf (sql ,
919
+ sizeof (sql ),
920
+ "ROLLBACK TO SAVEPOINT s%d; RELEASE SAVEPOINT s%d" ,
921
+ curlevel ,
922
+ curlevel
923
+ );
909
924
if (!sqlite3_get_autocommit (entry -> conn ))
910
925
sqlite_do_sql_command (entry -> conn , sql , ERROR , busy_connection );
911
926
}
0 commit comments