How to use my own sqlite database? - database

I put my database field in "assets" folder. And use the code from this blog to copy the database to "/data/data/my_packname/databases/", (This copy code i run it in the onCreate() method when i run this app) then use select * from ... to get data. But it gives me the exception: no such table.
Someone told me that if i am attempting to copy the file in SQLiteOpenHelper's onCreate(), it's too late. So the copy file code can not copy the complete file.
So i need to use adb or ddms to pull the database first?
So, Anyone can teach me how to use my own databse?
Can you tell me the setup?

I've used the instructions in that blog post and found them, while on the right track, to severely complicate the issue by unnecessarily extending SQLiteOpenHelper. I've had much better luck doing the following:
Create a utility class that creates the static db by copying it into the correct directory from assets, but doesn't get itself so hung up on following the SQLiteOpenHelper format.
Using the same utility class to open the db by using SQLiteDatabase.openDatabase()
Edit: Here is a version of this utility class I've created; it's not quite complete, but you'll get the drift.
public class DbUtils {
private static final String DB_PATH = "/data/data/com.mypackage.myapp/databases/";
private static final String DB_NAME = "my.db";
public static void createDatabaseIfNotExists(Context context) throws IOException {
boolean createDb = false;
File dbDir = new File(DB_PATH);
File dbFile = new File(DB_PATH + DB_NAME);
if (!dbDir.exists()) {
dbDir.mkdir();
createDb = true;
}
else if (!dbFile.exists()) {
createDb = true;
}
else {
// Check that we have the latest version of the db
boolean doUpgrade = false;
// Insert your own logic here on whether to upgrade the db; I personally
// just store the db version # in a text file, but you can do whatever
// you want. I've tried MD5 hashing the db before, but that takes a while.
// If we are doing an upgrade, basically we just delete the db then
// flip the switch to create a new one
if (doUpgrade) {
dbFile.delete();
createDb = true;
}
}
if (createDb) {
// Open your local db as the input stream
InputStream myInput = context.getAssets().open(DB_NAME);
// Open the empty db as the output stream
OutputStream myOutput = new FileOutputStream(dbFile);
// transfer bytes from the inputfile to the outputfile
byte[] buffer = new byte[1024];
int length;
while ((length = myInput.read(buffer)) > 0) {
myOutput.write(buffer, 0, length);
}
// Close the streams
myOutput.flush();
myOutput.close();
myInput.close();
}
}
public static SQLiteDatabase getStaticDb() {
return SQLiteDatabase.openDatabase(DB_PATH + DB_NAME, null, SQLiteDatabase.OPEN_READONLY);
}
}

After you've copied the database, you should try closing and reopening the SQLiteDatabase object before executing any query on it. I had a similar problem with copying a db from an input stream and that's what solved it for me.

here is my Version from "Silvio Donnini" Code :),
now you can update the Database easily.
private static final String DB_PATH = "/data/data/pakagename/databases/";
private static final String DB_NAME = "databaseName";
private static SQLiteDatabase db;
public static void createDatabaseIfNotExists(Context context,int version) throws IOException {
boolean createDb = false;
File dbDir = new File(DB_PATH);
File dbFile = new File(DB_PATH + DB_NAME);
if (!dbDir.exists()) {
dbDir.mkdir();
createDb = true;
}
else if (!dbFile.exists()) {
createDb = true;
}
else {
// Check that we have the latest version of the db
db = SQLiteDatabase.openDatabase(DB_PATH + DB_NAME, null, SQLiteDatabase.OPEN_READONLY);
if (db.getVersion() != version) {
dbFile.delete();
createDb = true;
}
}
if (createDb) {
// Open your local db as the input stream
InputStream myInput = context.getResources().openRawResource(R.raw.database);
// Open the empty db as the output stream
OutputStream myOutput = new FileOutputStream(dbFile);
// transfer bytes from the inputfile to the outputfile
byte[] buffer = new byte[1024];
int length;
while ((length = myInput.read(buffer)) > 0) {
myOutput.write(buffer, 0, length);
}
// Close the streams
myOutput.flush();
myOutput.close();
myInput.close();
SQLiteDatabase dbwrite = SQLiteDatabase.openDatabase(DB_PATH + DB_NAME, null, SQLiteDatabase.OPEN_READWRITE);
dbwrite.setVersion(version);
dbwrite.close();
if (db != null)
db = SQLiteDatabase.openDatabase(DB_PATH + DB_NAME, null, SQLiteDatabase.OPEN_READONLY);
}
}
public static SQLiteDatabase getStaticDb() {
if (db != null)
return db;
return SQLiteDatabase.openDatabase(DB_PATH + DB_NAME, null, SQLiteDatabase.OPEN_READONLY);
}

I know this is an old question, but I lost a lot of time figuring it out, with the help of all the replies.
The issue is that a device stores a database in his data/data/.../databases folder. So, when you change sth about the database (name, add android metadata table, size..) it wont make any difference because of the stored database and the method that checked for existing database.
To get the newest database, after changing it, you must run the program without checking for existing databses (e.g. instead of dbExist = checkDataBase(); make it just false).
dbExist = checkDataBase();
Change to:
dbExists = false;
After you picked up the "new" databse you can return to checking the existing ones.
Hope it helps someone,
dina

I know this is an old post, but for those who still get here after a Google or a Bing search, this is the solution to the stated problem:
in createDataBase() there is the following check;
this.getReadableDatabase();
This checks if there is already a database with the provided name and if not creates an empty database such that it can be overwritten with the one in the assets folder. On newer devices this works flawlessly but there are some devices on which this doesn't work. Mainly older devices. I do not know exactly why, but it seems like the getReadableDatabase() function not only gets the database but also opens it. If you then copy the database from the assets folder over it, it still has the pointer to an empty database and you will get table does not exist errors.
So in order to make it work on all devices you should modify it to the following lines:
SQLiteDatabase db = this.getReadableDatabase();
if (db.isOpen()){
db.close();
}
Even if the database is opened in the check, it is closed thereafter and it will not give you any more trouble.

Calm down guys,After long research finally found silly mistake for "no such table" error
Check name of database in Assets folder if it's like "DATABASE_NAME.EXTENSION" then put full name in Helper class with extension its solved my problem.
like say in Assets name of database is login.sqlite or login.db anything. put DB_NAME=login.sqlite fully with extention.
this tutorial now works perfectly.

The way of creating database from article you've posted is slightly diffrent from that how it's done in android examples (I don't want to say if it's good or bad).
I've learned how to use databases from SDKs NotePad sample
It's good example to start from, becouse it covers both database creation topic and database access through ContentProvider (it's really the only good way to get data from db, otherwise you will have problems when trying to get data simultaneusly from many places of your code).
You should note that SQLiteOpenHelper is really powerful and "it will help you" if you will use it properly. For example it stores current database version (not sqlite version but number you assingn with database schema version) and when you create new application version with new database structure you can update current schema to the new version in onUpdate.

Related

Xamarin Forms - How do i use a Premade Local Database? [Solved] [duplicate]

I have started using the Xamarin plugin for Visual Studio to create an Android app.
I have a local SQL database, and I want to call it to display data. I don't see how I can do this. Is it possible?
After thinking this was a trivial thing to do, I was proven wrong when I tried setup a quick test project. This post will contain a full tutorial on setting up a DB for an Android App in Xamarin that will come in handy as a reference for future Xamarin users.
At a glance:
Add Sqlite.cs to your project.
Add your database file as an Asset.
Set your database file to build as an AndroidAsset.
Manually copy the database file out of your apk to another directory.
Open a database connetion using Sqlite.SqliteConnection.
Operate on the database using Sqlite.
Setting up a local database for a Xamarin Android project
1. Add Sqlite.cs to your project.
Start by going to this repository and downloading Sqlite.cs; this provides the Sqlite API that you can use to run queries against your db. Add the file to your project as a source file.
2. Add DB as asset.
Next, get your DB and copy it into the Assets directory of your Android project and then import it into your project so that it appears beneath the Assets folder within your solution:
I'm using the Chinook_Sqlite.sqlite database sample renamed to db.sqlite from this site throughout this example.
3. Set DB to build as AndroidAsset.
Right click on the DB file and set it to build action AndroidAsset. This will ensure that it is included into the assets directory of the APK.
4. Manually copy DB out of your APK.
As the DB is included as an Asset (packaged within the APK) you will need to extract it out.
You can do this with the following code:
string dbName = "db.sqlite";
string dbPath = Path.Combine (Android.OS.Environment.ExternalStorageDirectory.ToString (), dbName);
// Check if your DB has already been extracted.
if (!File.Exists(dbPath))
{
using (BinaryReader br = new BinaryReader(Android.App.Application.Context.Assets.Open(dbName)))
{
using (BinaryWriter bw = new BinaryWriter(new FileStream(dbPath, FileMode.Create)))
{
byte[] buffer = new byte[2048];
int len = 0;
while ((len = br.Read(buffer, 0, buffer.Length)) > 0)
{
bw.Write (buffer, 0, len);
}
}
}
}
This extracts the DB as a binary file from the APK and places it into the system external storage path. Realistically the DB can go wherever you want, I've just chosen to stick it here.
I also read that Android has a databases folder that will store databases directly; I couldn't get it to work so I've just ran with this method of using an existing DB.
5. Open DB Connection.
Now open a connection to the DB through the Sqlite.SqliteConnection class:
using (var conn = new SQLite.SQLiteConnection(dbPath))
{
// Do stuff here...
}
6. Operate on DB.
Lastly, as Sqlite.net is an ORM, you can operate on the database using your own data types:
public class Album
{
[PrimaryKey, AutoIncrement]
public int AlbumId { get; set; }
public string Title { get; set; }
public int ArtistId { get; set; }
}
// Other code...
using (var conn = new SQLite.SQLiteConnection(dbPath))
{
var cmd = new SQLite.SQLiteCommand (conn);
cmd.CommandText = "select * from Album";
var r = cmd.ExecuteQuery<Album> ();
Console.Write (r);
}
Summary
And that's how to add an existing Sqlite database to your Xamarin solution for Android! For more information check out the examples included with the Sqlite.net library, its unit tests and the examples in the Xamarin documentation.
Here is the one that I'm using and it's working
install the Sqlite plugin
create interface to access different platforms services
create a model for the table
implement the interface that you created earlier on all of the
platform you want to use
use the plugin to create, get, insert, etc on your table
for more detailed information check this

Best practices for file system of application data JavaFX

I am trying to build an inventory management system and have recently asked a question about how to be able to store images in a package within my src file. I was told that you should not store images where class files are stored but have not been told what the best practices are for file systems. I have created a new page that allows the user to input all the data about a new part that they are adding to the system and upload an image associated with the part. When they save, everything worked fine until you try to reload the parts database. If you 'refresh' eclipse and then update the database, everything was fine because you could see the image pop into the package when refreshed. (All database info was updated properly as well.
I was told not to store these types of 'new' images with the program files but to create a separate file system to store these types of images. Is there a best practice for these types of file systems? My confusion is when the program gets saved where ever it is going to be saved, I can't have it point to an absolute path because it might not be saved on a C drive or K drive and I wouldn't want an images folder just sitting on the C drive that has all of the parts images for anyone to mess with. Please give me some good resources on how to build these file systems. I would like the images folder 'packaged' with the program when I compile it and package all the files together, I have not been able to find any good information on this, thanks!
To answer this question, probably not in the best way, but works pretty well.
I ended up making another menuItem and menu that you can see at the top 'Image Management', where it lets the user set the location that they would like to save all the images as well as a location to back up the images. it creates the directory if it is not there or it will save over the images if the directory is already there. This menu will only appear if the user has admin privileges. I would think that this could be set up with an install wizard, but I have no idea how to make one, where it only runs on installation. I am also going to add an autosave feature to save to both locations if a backup location has been set. This is the best way I can think of managing all the parts images, if anyone has some good input, please let me know. I considered a server, but think that is too much for this application and retrieving images every time the tableView populates would take a lot of time. If interested the code I used is:
public class ImageDirectoryController implements Initializable{
#FXML private AnchorPane imageDirectory;
#FXML private Label imageDirLbl, backupLbl;
#FXML private Button setLocationButton, backupButton;
#FXML private TextField imageDirPathTxtField;
Stage window;
String image_directory;
#Override
public void initialize(URL location, ResourceBundle resources) {
// TODO Auto-generated method stub
}
public void setImageDirectory(String image_address, String backup_address) {
imageDirLbl.setText(image_address);
backupLbl.setText(backup_address);
}
#FXML
public void setLocationButtonClicked () {
String imagesPath = imageDirPathTxtField.getText() + "tolmarImages\\";
File files = new File(imagesPath + "asepticImages");
File generalFiles = new File(imagesPath + "generalImages");
File facilitiesFiles = new File(imagesPath + "facilitiesImages");
boolean answer = ConfirmBox.display("Set Image", "Are you sure you want to set this location?");
if(answer) {
if (!files.exists()) {
if (files.mkdirs() && generalFiles.mkdirs() && facilitiesFiles.mkdirs()) {
JOptionPane.showMessageDialog (null, "New Image directories have been created!", "Image directory created", JOptionPane.INFORMATION_MESSAGE);
} else {
JOptionPane.showMessageDialog (null, "Failed to create multiple directories!", "Image directory not created", JOptionPane.INFORMATION_MESSAGE);
}
}
DBConnection dBC = new DBConnection();
Connection con = dBC.getDBConnection();
String updateStmt = "UPDATE image_address SET image_address = ? WHERE rowid = ?";
try {
PreparedStatement myStmt = con.prepareStatement(updateStmt);
myStmt.setString(1, imageDirPathTxtField.getText());
myStmt.setInt(2, 1);
myStmt.executeUpdate();
myStmt.close();
imageDirPathTxtField.clear();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
#FXML
public void backupButtonClicked () {
String backupStatus = null;
if (backupLbl.getText().equals("")&& !imageDirPathTxtField.getText().equals("")) {
backupStatus = imageDirPathTxtField.getText();
} else if (!imageDirPathTxtField.getText().equals("")) {
backupStatus = imageDirPathTxtField.getText();
} else if (!backupLbl.getText().equals("")){
backupStatus = backupLbl.getText();
} else {
JOptionPane.showMessageDialog(null, "You must create a directory.", "No directory created", JOptionPane.INFORMATION_MESSAGE);
return;
}
boolean answer = ConfirmBox.display("Set Image", "Are you sure you want to backup the images?");
if(answer) {
DBConnection dBC = new DBConnection();
Connection con = dBC.getDBConnection();
String updateStmt = "UPDATE image_address SET image_address = ? WHERE rowid = 2";
try {
PreparedStatement myStmt = con.prepareStatement(updateStmt);
myStmt.setString(1, backupStatus);
myStmt.executeUpdate();
myStmt.close();
String source = imageDirLbl.getText() + "tolmarImages";
File srcDir = new File(source);
String destination = backupStatus + "tolmarImages";
File destDir = new File(destination);
try {
FileUtils.copyDirectory(srcDir, destDir);
JOptionPane.showMessageDialog(null, "Images copied successfully.", "Images copied", JOptionPane.INFORMATION_MESSAGE);
} catch (IOException e) {
e.printStackTrace();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}

Create persistent Sqlite db in Windows phone 8

I am trying my hands on Windows phone 8 applications and I am stuck into a weird situation here. I am using sqlite in order to create sqlite db and add values into the database. I am able to create the database and add the values in the database successfully but I am having a weird situation here.
Everytime I close the emulator and start the project again the database gets created again which should not be happening because I created the db the very first time I run the application.
Does anybody know why, and how I can prevent it from recreating the database each time?
public string DB_PATH = Path.Combine(Path.Combine(ApplicationData.Current.LocalFolder.Path, "aa.sqlite"));
private SQLiteConnection dtCon;
public MainPage()
{
InitializeComponent();
CreateDatabase();
dtCon = new SQLiteConnection(DB_PATH);
var tp = dtCon.Query<Contacts>("select * from contacts").ToList();
}
private async void CreateDatabase()
{
bool isDatabaseExisting = false;
//Checking if database already exists
try
{
Windows.Storage.StorageFile storagefile = await Windows.Storage.ApplicationData.Current.LocalFolder.GetFileAsync("aa.sqlite");
isDatabaseExisting = true;
}
catch
{
isDatabaseExisting = false;
}
//if not exists then creating database
if (!isDatabaseExisting)
{
String str = System.IO.Path.Combine(Windows.Storage.ApplicationData.Current.LocalFolder.Path, "sqlite.db");
AddDataToDB(DB_PATH);
}
}
private void AddDataToDB(string str)
{
// Create the database connection.
dtCon = new SQLiteConnection(str);
// Create the table Task, if it doesn't exist.
dtCon.CreateTable<Contacts>();
Contacts oContacts = new Contacts();
oContacts.Name = "dfgdf";
oContacts.Detail = "asdfsf";
dtCon.Insert(oContacts);
}
I'm pretty sure when you close your emulator and restart, you're basically just uninstalling the application. Which is why your files or not there anymore -- as it looks like you're storing your data in isolated storage. I do not know if there is anyway around this.
You can buy a very cheap Windows 8/8.1 Phone and the files will persist until you manually uninstall the test application.
As #Chubosaurus says, closing and re-opening the emulator will remove all the apps. You can generally keep it running as long as you want and keep re-deploying your app to the emulator (although obviously rebooting the host PC will kill it).
You can save and restore the data from your emulator image via the ISETool command. See more here
Try adding Console.WriteLine("True"); and Console.WriteLine("False"); into the expected places after checking isDatabaseExisting to see/understand what the code path really is.

deploying winform application with embedded sqlite

I'm deploying a winform application built with vs 2008 0n XP sp3.
I created a database with empty schema which i dropped in the root folder of the project and in properties i choosed Build Action: Embedded Resources and Copy to Output directory : Copy always. Now instead of having connectionstring in the app.config connectionString section, i put an entry in appSetting: key="database";value="mydb.db;Version=3".
So to create my connectionString i used :
SQLiteConnection con = new SQLiteConnection("Data Source=" + Path.Combine(Application.StartupPath, ConfigurationManager.AppSettings["database"]));
Everything works fine and i packaged the app with a setup project.Now after i installed the app the database could not be found and i was obliged to copy the database to the Application Folder in the setup project for it to work.
what i thought is that db is supposed to be in the app dll because of copy always .but i can't access it.So what exactly did i do wrong?
i'm suspecting i should have just connected to the root db meaning not using Application.StartupPath
But i'm here asking for the best practices cause what i did is working but still looking like workaround so please can anyone share his experience with me?
thanks for reading
Embedded Resource means the database gets embedded in your dll. The Copy to output directory setting doesn't apply in this case, that's used for Build Action: Content.
With the database embedded, you basically have to un-embed it on first use. To do this read it out of the Assembly and store it to a file.
class EmbeddedResourceTest
{
public static void Test()
{
string path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Test.db");
using(var resourceStream = typeof(EmbeddedResourceTest).Assembly.GetManifestResourceStream("Test.db"))
{
using(var fileStream = File.OpenWrite(path))
{
CopyStream(resourceStream, fileStream);
}
}
// now access database using 'path'
}
public static void CopyStream(Stream inputStream, Stream outputStream)
{
CopyStream(inputStream, outputStream, 4096);
}
public static void CopyStream(Stream inputStream, Stream outputStream, int bufferLength)
{
var buffer = new byte[bufferLength];
int bytesRead;
while ((bytesRead = inputStream.Read(buffer, 0, bufferLength)) > 0)
{
outputStream.Write(buffer, 0, bytesRead);
}
}
}

How to do database schema migrations in Android?

Is there a standard way to do database schema migrations on Android? For example, user installs newer version of my Android app but the new version needs to make updates to the database schema (and wiping the user's database and starting over is not an option!). So I need to run some ALTER statements and/or copy tables the first time my new version runs.
Yes SQLiteOpenHelper has support for migrating between different versions of DB schemas.
Upgrading is done by implementing
public abstract void onUpgrade (SQLiteDatabase db, int oldVersion, int newVersion)
And Rolling back to a previous version is also supported :
public abstract void onDowngrade (SQLiteDatabase db, int oldVersion, int newVersion)
With a little bit of thought, you can nearly automate a lot of the SQLiteOpenHelper methods. Have a look at this blog post http://www.greenmoonsoftware.com/2012/02/sqlite-schema-migration-in-android/
Update: I ran into some issues if the database updates take a while to complete. Have a look at this blog entry for an implementation that works for me. http://www.greenmoonsoftware.com/2012/05/android-developer-how-to-safely-update-the-application-database/
As of version 3.0 Flyway now supports database migrations on Android. It works with SQLite, but also with any other database you wish to use (local in-memory one, or a DB on the server for two-tier apps).
Migrations can be written in both SQL and Java.
All the above answers concerning SQLiteOpenHelper are correct, but they all contain a kind of antipattern - creating/modifying DB structure with Strings. It makes both development and maintenance more expensive. Sometimes a migration consists of many statements, some of them may be quite big. Writing them as Strings, without any syntax higlighting... well, for small structures it might work, but for some bigger ones it'd be a nightmare.
A better way to manage schema changes would be to keep each migration script in external file and make SQLiteOpenHelper's onUpgrade method execute them automatically, in the proper order. Here's an article covering this topic: http://www.vertabelo.com/blog/sqlite-on-android-handling-database-structure-changes. I hope this helps.
You can enhance default SQLiteOpenHelper with library Android-Migrator, that allow you to apply migrations from sql files in android assets folder.
I know this is an old one but I have developed an open source eclipse plugin that is a domain specific language (DSL written with XText) that allows you to specify a database as a list of migrations.
It generates your ContentProvider, SqliteOpenHelper and Contract for you, into an API that resembles an API like the Contacts API or Media API.
I have written a basic guide that helps you get started here http://robotoworks.com/mechanoid-plugin/mechanoid-db/
So far it supports create table, create view and alter table statements, I hope to fully implement Sqlite syntax where appropriate for this DSL.
Hope that helps and sorry for the spam! :)
yanchenko's answer is correct, however, you might want to take a look at Droid Migrate, which is a framework I wrote that makes extensive use of SQLiteOpenHelper to facilitate automatic SQLite migrations (much like how Rails does it).
I also wanted something like flyway what I used in my Spring projects, but for android it seems not easy to make it work, so I created a very basic class which basically does the same.
So just put the sql files to the assets folder here: assets/dbmigration/yourdatabasenamelowercase in the format vN.sql where N is the version number. Then from onUpgrade just call like this:
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
new DbMigrationHelper().doMigrate(context, db, DATABASE_NAME, oldVersion, newVersion);
}
onCreate is basically the same, but with fixed version parameters: 0 and 1
And this doMigrate method executes all the scripts in between the fromVersion - toVersion range (excluding fromVersion) in the proper order. So if you call it with e.g. 2 and 5 it will execute the v3.sql then v4.sql and then v5.sql from the proper asset folder. Each script can contain multiple statements (they must be separated with semicolons) and the scripts can contain full line sql comments (started with --). I hope that it can be useful for someone :)
So the class:
/**
* This class helps getting sql resources from asset for migration and to split complex scripts to sql statements automatically.<br>
* To create assets folder: right click on app (Project view) > new > folder > Assets folder ... and just click finish now you have src/main/assets folder.
*/
public class DbMigrationHelper {
private static final String TAG = "DbMig";
public void doMigrate(Context context, SQLiteDatabase db, String dbName, int fromVersion, int toVersion){
Objects.requireNonNull(context,"Context can not be null");
Objects.requireNonNull(db, "Database can not be null");
Objects.requireNonNull(dbName,"Database name can not be null");
if(fromVersion > toVersion){
throw new RuntimeException("old version (" + fromVersion + ") > new version (" + toVersion + ")");
}
if(fromVersion == toVersion){
Log.d(TAG,"Old and New versions are the same: " + fromVersion + " no migration will be done");
return;
}
try {
for (int i = fromVersion + 1; i <= toVersion; i++){
Log.i(TAG,"Migrating to version " + i);
String script = inputStreamToString(context.getAssets().open("dbmigration/"+dbName.toLowerCase()+"/v"+i+".sql"));
executeScript(script, db);
Log.i(TAG,"Migration to v" +i+ " has done.");
}
Log.i(TAG,"Migration finished.");
} catch (Exception e) {
throw new RuntimeException("Migration script problem: "+e.getMessage(),e);
}
}
private void executeScript(String script, SQLiteDatabase db){
Objects.requireNonNull(script,"Script is null");
List<String> statements = splitSqlScriptToStatements(script);
for(String statement : statements){
Log.i(TAG, "Executing: "+statement);
db.execSQL(statement);
}
}
private String inputStreamToString(InputStream is) throws IOException {
StringBuilder sb = new StringBuilder();
try(BufferedReader br = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8 ))){
String str;
while ((str = br.readLine()) != null) {
sb.append(str).append("\n");
}
return sb.toString();
}finally {
is.close();
}
}
/**
* Splits sql script to statements. Removes empty lines and FULL LINE comments (started with --).<br>
* <b>All statements must be terminated with ;</b>
* #param sqlScript the full script content
* #return Sql statements in the exact order they are in the script
*/
private List<String> splitSqlScriptToStatements(String sqlScript){
List<String> res = new LinkedList<>();
if (sqlScript == null) {
return res;
}
List<String> valuableLines = removeCommentedAndEmptyLines(splitToLines(sqlScript));
StringBuilder buffer = new StringBuilder("");
for(String line : valuableLines){
if(buffer.length()>0){
buffer.append(" ");
}
buffer.append(line.trim());
if(line.trim().endsWith(";")){
res.add(buffer.toString());
buffer = new StringBuilder("");
}
}
if(buffer.length()>0){
res.add(buffer.toString());
}
return res;
}
/**
* Splits the given full text by \n
* #param sql
* #return not null list of lines
*/
private List<String> splitToLines(String sql){
List<String> res = new LinkedList<>();
if(sql == null){
return res;
}
return Arrays.asList(sql.split("\\r?\\n"));
}
/**
*
* #param src
* #return non empty list of lines containing no comments no empty lines
*/
private List<String> removeCommentedAndEmptyLines(List<String> src){
List<String> res = new LinkedList<>();
if(src == null){
return res;
}
for(String s : src){
if(s != null && !s.trim().startsWith("--") && !s.trim().isEmpty()){
res.add(s);
}
}
return res;
}
}

Resources