SQLITE_BUSY The database file is locked (database is locked) in wicket - sqlite

I am doing a project in wicket
How to solve the problem.
I came across such a message:
WicketMessage: Can't instantiate page using constructor public itucs.blg361.g03.HomePage()
Root cause:
java.lang.UnsupportedOperationException: [SQLITE_BUSY] The database file is locked (database is locked)
at itucs.blg361.g03.CategoryEvents.CategoryEventCollection.getCategoryEvents(CategoryEventCollection.java:41)
public List<CategoryEvent> getCategoryEvents() {
List<CategoryEvent> categoryEvents = new
LinkedList<CategoryEvent>();
try {
String query = "SELECT id, name, group_id"
+ " FROM event_category";
Statement statement = this.db.createStatement();
ResultSet result = statement.executeQuery(query);
while (result.next()) {
int id = result.getInt("id");
String name = result.getString("name");
int group_id = result.getInt("group_id");
categoryEvents.add(new CategoryEvent(id, name, group_id));
}
} catch (SQLException ex) {
throw new UnsupportedOperationException(ex.getMessage());
}
return categoryEvents;
}
at itucs.blg361.g03.HomePage.(HomePage.java:71)
categories = categoryCollection.getCategoryEvents();
at java.lang.reflect.Constructor.newInstance(Constructor.java:525)

Sqlite allows only one writer to the whole database at a time and, unless you selected "WAL" journal mode, no reader while writing. Moreover unless you explicitly ask it to wait, it simply returns the SQLITE_BUSY status for any attempt to access the database while conflicting operation is running.
You can tell sqlite to wait for the database to become available for a specified amount of time. The C-level API is sqlite3_busy_timeout; I never used sqlite from Java though, so I don't know where to find it there.

(...) tell sqlite to wait for the database to become available for specified amount of time.
In order to do it from Java, run the following statement just like a simple SQL statement:
pragma busy_timeout=30000; -- Busy timeout set to 30000 milliseconds

Related

Flyway reports success even though database gave warnings

We are using Flyway 4 (great tool!) on Oracle.
When invalid DDL is committed, the continuous database build breaks.. and all the team gets an email.. all good so far.
But when, code that breaks one of our stored procedures is committed.. ie procedure gets created, but it fails to compile.. we still get a successful migration reported from Flyway.
During the migration we see something like :
DB: Warning: execution completed with warning (SQL State: 99999 - Error Code: 17110)
..but still the Flyway ant task reports success.
As we have a lot of stored procedures, 9 times out of 10 it is these that are broken by developers, and not the DDL. We really would like Flyway to fail on a warning also. Can anyone advise how best to approach this?
Solved! Found an acceptable solution for us and implemented it as follows, utilising Flyways callback mechanism which is documented on the Flyway website.
There are many callbacks available and are invoked at various points, but the one that appears to suit our needs is afterMigrate. In the callback, we can execute sql (on Oracle) which counts the number of invalid objects in the user schema at hand
So, implementing a java afterMigrate callback as follows does the job:
public void afterMigrate(Connection connection) {
String countInvalidObjs = "select count(*) " +
"from user_objects " +
"where object_type in ('FUNCTION','PROCEDURE','PACKAGE','PACKAGE BODY','TRIGGER') " +
"and status = 'INVALID' ";
int invalidObjCount = -1;
Statement statement;
try {
statement = connection.createStatement();
ResultSet rs = statement.executeQuery(countInvalidObjs);
while (rs.next()) {
invalidObjCount = rs.getInt(1);
}
} catch(Throwable t) {
System.out.println("*error* " + t.getMessage());
} finally {
if(invalidObjCount!=0) {
throw new IllegalArgumentException("fail to complete migration, build finished with databse warnings");
}
}
}

What is the best approah to insert large records return from webservice in SQLite

Using Async-based Webservice and Async framework in WinRT (Win8) to get a large recordsets(1000 to 5000) from a remote Ms SQL Server.
I want to know :
1) Which is the best approach to handle to insert large recordsets into SQLite?
2) Using RollBack transaction will start all over again if there is connection error. The below method will insert whatever and I can update the data later if the records are not complete. Is this a good approach?
3) Any better way to enhance my below solution?
This foreach statement to handle
each reords in returned result which returned from Async-Based WebService:
foreach (WebServiceList _List in IList)
{
InsertNewItems(_List.No, _List.Description, _List.Unit_Price, _List.Base_Unit_of_Measure);
}
private void InsertNewItems(string ItemNo, string ItemName, decimal ItemPrice, string ItemBUoM)
{
var existingItem = (db2.Table().Where(c => c.No == ItemNo)).SingleOrDefault();
if (existingItem != null)
{
existingItem.No = ItemNo;
existingItem.Description = ItemName;
existingItem.Unit_Price = ItemPrice;
existingItem.BaseUnitofMeasure = ItemBUoM;
int success = db2.Update(existingItem);
}
else
{
int success = db2.Insert(new Item()
{
No = ItemNo,
Description = ItemName,
Unit_Price = ItemPrice,
Base_Unit_of_Measure = ItemBUoM
});
}
}
You should use RunInTransaction from sqlite-net. The documentation for it says,
Executes action within a (possibly nested) transaction by wrapping it
in a SAVEPOINT. If an exception occurs the whole transaction is rolled
back, not just the current savepoint. The exception is rethrown.
using (var db = new SQLiteConnection(DbPath))
{
db.RunInTransaction(() =>
{
db.InsertOrReplace(MyObj);
});
}
Wiki article for Transactions at GitHub
The most important performance aspect for bulk inserts is to use a single transaction. If you want to handle aborts, I suggest that you feed the data in sufficiently large parts and restart from that point on next time. An SQL transaction either finishes completely or rolls back completely, so unless the input data changes between two runs, there should be no need to do an insert-or-update.
See, for example, here for a discussion of SQLite bulk insert performance using different methods.

Blackberry not creating a valid sqlite database

I have a very unusual problem.
I'm trying to create a simple database (6 tables, 4 of which only have 2 columns).
I'm using an in-house database library which I've used in a previous project, and it does work.
However with my current project there are occasional bugs. Basically the database isn't created correctly. It is added to the sdcard but when I access it I get a DatabaseException.
When I access the device from the desktop manager and try to open the database (with SQLite Database Browser v2.0b1) I get "File is not a SQLite 3 database".
UPDATE
I found that this happens when I delete the database manually off the sdcard.
Since there's no way to stop a user doing that, is there anything I can do to handle it?
CODE
public static boolean initialize()
{
boolean memory_card_available = ApplicationInterface.isSDCardIn();
String application_name = ApplicationInterface.getApplicationName();
if (memory_card_available == true)
{
file_path = "file:///SDCard/" + application_name + ".db";
}
else
{
file_path = "file:///store/" + application_name + ".db";
}
try
{
uri = URI.create(file_path);
FileClass.hideFile(file_path);
} catch (MalformedURIException mue)
{
}
return create(uri);
}
private static boolean create(URI db_file)
{
boolean response = false;
try
{
db = DatabaseFactory.create(db_file);
db.close();
response = true;
} catch (Exception e)
{
}
return response;
}
My only suggestion is keep a default database in your assets - if there is a problem with the one on the SD Card, attempt to recreate it by copying the default one.
Not a very good answer I expect.
Since it looks like your problem is that the user is deleting your database, just make sure to catch exceptions when you open it (or access it ... wherever you're getting the exception):
try {
URI uri = URI.create("file:///SDCard/Databases/database1.db");
sqliteDB = DatabaseFactory.open(myURI);
Statement st = sqliteDB.createStatement( "CREATE TABLE 'Employee' ( " +
"'Name' TEXT, " +
"'Age' INTEGER )" );
st.prepare();
st.execute();
} catch ( DatabaseException e ) {
System.out.println( e.getMessage() );
// TODO: decide if you want to create a new database here, or
// alert the user if the SDCard is not available
}
Note that even though it's probably unusual for a user to delete a private file that your app creates, it's perfectly normal for the SDCard to be unavailable because the device is connected to a PC via USB. So, you really should always be testing for this condition (file open error).
See this answer regarding checking for SDCard availability.
Also, read this about SQLite db storage locations, and make sure to review this answer by Michael Donohue about eMMC storage.
Update: SQLite Corruption
See this link describing the many ways SQLite databases can be corrupted. It definitely sounded to me like maybe the .db file was deleted, but not the journal / wal file. If that was it, you could try deleting database1* programmatically before you create database1.db. But, your comments seem to suggest that it was something else. Perhaps you could look into the file locking failure modes, too.
If you are desperate, you might try changing your code to use a different name (e.g. database2, database3) each time you create a new db, to make sure you're not getting artifacts from the previous db.

The underlying provider failed on Open

I made 3 Ajax processes to run the below code at the same time.
but one of the processes throw exception that message says "The underlying provider failed on Open."
try{
orderRepository orderRepo = new orderRepository(); // get context (Mysql)
var result = (from x in orderRepo.orders
where x.orderid == orderno
select new {x.tracking, x.status, x.charged }).SingleOrDefault();
charged = result.charged;
}catch(Exception e){
log.Error(e.Message); // The underlying provider failed on Open.
}
And, I run the 1 Ajax call that failed before, then It passes through.
It happen to 1 of 3 (Ajax) process, sometimes, 2 of 5 process.
I guess it because all process try to using Database same time. but I couldn't find the solution.
This is my connection string,
<add name="EFMysqlContext" connectionString="server=10.0.0.10;User Id=root;pwd=xxxx;Persist Security Info=True;database=shop_db" providerName="Mysql.Data.MySqlClient" />
Anybody know the solution or something I can try, please advise me.
Thanks
It sounds like a problem because of concurrent connection with SQL Server using same username. Have you tried destroying/disposing the repository(or connection) object after using it?
Give it a try:
try{
using( orderRepository orderRepo = new orderRepository()) // get context (Mysql)
{
var result = (from x in orderRepo.orders
where x.orderid == orderno
select new {x.tracking, x.status, x.charged }).SingleOrDefault();
charged = result.charged;
} // orderRepo object automatically gets disposed here
catch(Exception e){
log.Error(e.Message); // The underlying provider failed on Open.
} }
Not sure if it matters, but your provider name is Mysql.Data.MySqlClient and not MySql.Data.MySqlClient (if it is case-sensitive, this could be the cause).

Simplest way to access a DB2 database on iSeries from a Linux (ubuntu) machine?

I would like to run an SQL query on an iSeries (...or "System i" or "AS/400"...) machine as part of a Nagios check, but haven't found a suitable way of interfacing the database yet.
IBM suggests using the ODBC driver of System i Access for Linux with unixODBC, but since both systems are new to me, I'd like to know if there are other ways of doing this.
Hacks involving telnet and expect are perfectly fine. :-)
I think this would be the simplest ...
Same as Access for Linux but it is the open source version: JTOpen
example taken from iSeries Information Center:
// Connect to the server.
Connection c = DriverManager.getConnection("jdbc:as400://mySystem");
// Create a Statement object.
Statement s = c.createStatement();
// Run an SQL statement that creates
// a table in the database.
s.executeUpdate("CREATE TABLE MYLIBRARY.MYTABLE (NAME VARCHAR(20), ID INTEGER)");
// Run an SQL statement that inserts
// a record into the table.
s.executeUpdate("INSERT INTO MYLIBRARY.MYTABLE (NAME, ID) VALUES ('DAVE', 123)");
// Run an SQL statement that inserts
// a record into the table.
s.executeUpdate("INSERT INTO MYLIBRARY.MYTABLE (NAME, ID) VALUES ('CINDY', 456)");
// Run an SQL query on the table.
ResultSet rs = s.executeQuery("SELECT * FROM MYLIBRARY.MYTABLE");
// Close the Statement and the
// Connection.
s.close();
c.close();
Found at Nagios Exchange:
DB2 Checker
Download DB2 Checker
untested...
I had this source on my disk. It's a good example. For clarity, I did change the machine, catalog and table name in the source. Hope it helps. It uses the JDBC driver from the JTOpen project.
Notice that with this specific driver you can access the iSeries DB2 database as any other database. Also, the DB2 database on the iSeries is just one of the versions of the IBM Universal Database. However, you can do iSeries specific tricks, even with the JDBC driver. But if you want to stay SQL defaults only, that is fine too.
import java.sql.*;
public class TestSQL {
public static void main(String[] args) {
try {
DriverManager
.registerDriver(new com.ibm.as400.access.AS400JDBCDriver());
Connection conn = DriverManager
.getConnection("jdbc:as400://YOURISERIES/YOURLIBRARY");
Statement select = conn.createStatement();
ResultSet rs = select.executeQuery("select * from whatever");
ResultSetMetaData rsmd = rs.getMetaData();
while (rs.next()) {
for (int x=1; x <= rsmd.getColumnCount(); x++) {
System.out.print(rs.getString(x));
}
System.out.println();
}
} catch (Exception e) {
System.out.println("error: " + e.getMessage());
}
System.exit(0);
}
}

Resources