aboutsummaryrefslogtreecommitdiffstats
path: root/Software/Visual_Studio/Tango.Synchronization/Local/SqliteDataBase.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Software/Visual_Studio/Tango.Synchronization/Local/SqliteDataBase.cs')
-rw-r--r--Software/Visual_Studio/Tango.Synchronization/Local/SqliteDataBase.cs434
1 files changed, 434 insertions, 0 deletions
diff --git a/Software/Visual_Studio/Tango.Synchronization/Local/SqliteDataBase.cs b/Software/Visual_Studio/Tango.Synchronization/Local/SqliteDataBase.cs
new file mode 100644
index 000000000..35e54c66a
--- /dev/null
+++ b/Software/Visual_Studio/Tango.Synchronization/Local/SqliteDataBase.cs
@@ -0,0 +1,434 @@
+using Tango.Synchronization;
+using System;
+using System.Collections.Generic;
+using System.Data;
+using System.Data.SQLite;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Tango.Synchronization.Local
+{
+ /// <summary>
+ /// Represents an SQLite database adapter used for synchronization by <see cref="LocalDBComparer"/>.
+ /// </summary>
+ /// <seealso cref="Tango.Synchronization.ISqlDataBase" />
+ public class SQLiteDataBase : ILocalDataBase
+ {
+ private SQLiteConnection _connection;
+
+ /// <summary>
+ /// Gets the database source URL/File.
+ /// </summary>
+ public String Source { get; private set; }
+
+ /// <summary>
+ /// Gets the database tables collection.
+ /// </summary>
+ public List<DataTable> Tables { get; private set; }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="SQLiteDataBase"/> class.
+ /// </summary>
+ /// <param name="filePath">The file path.</param>
+ public SQLiteDataBase(String filePath)
+ {
+ Source = filePath;
+
+ _connection = new SQLiteConnection(String.Format("Data Source={0};Version=3;New={1};Compress=FALSE;",
+ filePath,
+ (File.Exists(filePath) ? "False" : "True")
+ ));
+
+ _connection.Open();
+ }
+
+ /// <summary>
+ /// Loads the tables (Must be done before any synchronization).
+ /// </summary>
+ public void LoadTables()
+ {
+ Tables = new List<DataTable>();
+
+ var command = _connection.CreateCommand();
+ command.CommandText = "SELECT name FROM sqlite_master WHERE type = 'table'";
+ var reader = command.ExecuteReader();
+
+ while (reader.Read())
+ {
+ String name = reader.GetString(0);
+
+ if (name != Constants.SEQUENCE_TABLE_NAME)
+ {
+ Debug.WriteLine(name);
+ Tables.Add(LoadTable(name));
+ }
+ }
+ }
+
+ /// <summary>
+ /// Loads the table.
+ /// </summary>
+ /// <param name="name">The name.</param>
+ /// <returns></returns>
+ private DataTable LoadTable(String name)
+ {
+ var tableCommand = _connection.CreateCommand();
+ tableCommand.CommandText = "SELECT * FROM " + name;
+
+ DataTable table = new DataTable(name);
+ table.Load(tableCommand.ExecuteReader());
+
+ var infoCommand = _connection.CreateCommand();
+ infoCommand.CommandText = String.Format("PRAGMA table_info({0});", name);
+ DataTable infoTable = new DataTable(name);
+ infoTable.Load(infoCommand.ExecuteReader());
+
+ table.ExtendedProperties.Add(Constants.TABLE_INFO, infoTable);
+
+ for (int i = 0; i < table.Columns.Count; i++)
+ {
+ DataColumn column = table.Columns[i];
+ column.ExtendedProperties.Add(Constants.COLUMN_TYPE, infoTable.Rows[i][Constants.COLUMN_TYPE]);
+ column.ExtendedProperties.Add(Constants.IS_NOT_NULL, infoTable.Rows[i][Constants.IS_NOT_NULL]);
+ column.ExtendedProperties.Add(Constants.DEFAULT_VALUE, infoTable.Rows[i][Constants.DEFAULT_VALUE]);
+ }
+
+ return table;
+ }
+
+ /// <summary>
+ /// Clones a table from another database into this database.
+ /// </summary>
+ /// <param name="otherDB">The other database.</param>
+ /// <param name="otherTable">The other table.</param>
+ /// <returns></returns>
+ public DataTable CloneTableFrom(ILocalDataBase otherDB, DataTable otherTable)
+ {
+ String cmd = String.Format("CREATE TABLE {0} (", otherTable.TableName);
+
+ foreach (DataColumn column in otherTable.Columns)
+ {
+ cmd += String.Format("{0} {1} {2} {3} {4} {5}",
+ column.ColumnName,
+ column.GetSQLType(),
+ otherTable.PrimaryKey.Contains(column) ? "PRIMARY KEY" : null,
+ column.Unique ? "UNIQUE" : null,
+ column.IsNotNull() ? "NOT NULL" : null,
+ column.HasDefaultValue() ? ("DEFAULT " + column.GetDefaultValue()) : null)
+
+ + ", " + Environment.NewLine;
+ }
+
+ cmd += ");";
+
+ cmd = cmd.Remove(cmd.LastIndexOf(","), 1);
+
+ var createCommand = _connection.CreateCommand();
+ createCommand.CommandText = cmd;
+ createCommand.ExecuteNonQuery();
+
+ var attacheCommand = _connection.CreateCommand();
+ attacheCommand.CommandText = String.Format("ATTACH DATABASE '{0}' AS other;", otherDB.Source);
+ attacheCommand.ExecuteNonQuery();
+
+ var copyCommand = _connection.CreateCommand();
+ copyCommand.CommandText = String.Format("INSERT INTO main.{0} SELECT * FROM {1}.{0};", otherTable.TableName, "other");
+ copyCommand.ExecuteNonQuery();
+
+ var detacheCommand = _connection.CreateCommand();
+ detacheCommand.CommandText = "DETACH other;";
+ detacheCommand.ExecuteNonQuery();
+
+ var table = LoadTable(otherTable.TableName);
+ Tables.Add(table);
+ return table;
+ }
+
+ /// <summary>
+ /// Gets the SQL command for <see cref="CloneTableFrom(ILocalDataBase, DataTable)" />.
+ /// </summary>
+ /// <param name="otherDB">The other database.</param>
+ /// <param name="otherTable">The other table.</param>
+ /// <returns></returns>
+ public String GetCloneTableFromCommand(ILocalDataBase otherDB, DataTable otherTable)
+ {
+ String cmd = String.Format("CREATE TABLE {0} (", otherTable.TableName);
+
+ foreach (DataColumn column in otherTable.Columns)
+ {
+ cmd += String.Format("{0} {1} {2} {3} {4} {5}",
+ column.ColumnName,
+ column.GetSQLType(),
+ otherTable.PrimaryKey.Contains(column) ? "PRIMARY KEY" : null,
+ column.Unique ? "UNIQUE" : null,
+ column.IsNotNull() ? "NOT NULL" : null,
+ column.HasDefaultValue() ? ("DEFAULT " + column.GetDefaultValue()) : null)
+
+ + ", " + Environment.NewLine;
+ }
+
+ cmd += ");";
+
+ cmd = cmd.Remove(cmd.LastIndexOf(","), 1);
+
+ cmd += Environment.NewLine;
+
+ cmd += String.Format("ATTACH DATABASE '{0}' AS other;", otherDB.Source);
+
+ cmd += Environment.NewLine;
+
+ cmd += String.Format("INSERT INTO main.{0} SELECT * FROM {1}.{0};", otherTable.TableName, "other");
+
+ cmd += Environment.NewLine;
+
+ cmd += "DETACH other;";
+
+ return cmd;
+ }
+
+ /// <summary>
+ /// Adds the specified column to the specified table.
+ /// </summary>
+ /// <param name="table">The table.</param>
+ /// <param name="column">The column.</param>
+ /// <returns></returns>
+ public DataColumn AddColumn(DataTable table, DataColumn column)
+ {
+ var insertCommand = _connection.CreateCommand();
+ insertCommand.CommandText = String.Format("ALTER TABLE {0} ADD COLUMN {1} {2} {3} {4} {5} {6}",
+ table.TableName,
+ column.ColumnName,
+ column.GetSQLType(),
+ table.PrimaryKey.Contains(column) ? "PRIMARY KEY" : null,
+ column.Unique ? "UNIQUE" : null,
+ column.IsNotNull() ? "NOT NULL" : null,
+ column.HasDefaultValue() ? ("DEFAULT " + column.GetDefaultValue()) : null);
+
+
+ insertCommand.ExecuteNonQuery();
+ var t = LoadTable(table.TableName);
+ var index = Tables.IndexOf(Tables.Single(x => x.TableName == table.TableName));
+ Tables[index] = t;
+ return t.Columns[column.ColumnName];
+ }
+
+ /// <summary>
+ /// Gets the SQL command for <see cref="AddColumn(DataTable, DataColumn)" />.
+ /// </summary>
+ /// <param name="table">The table.</param>
+ /// <param name="column">The column.</param>
+ /// <returns></returns>
+ public String GetAddColumnCommand(DataTable table, DataColumn column)
+ {
+ String cmd = String.Format("ALTER TABLE {0} ADD COLUMN {1} {2} {3} {4} {5} {6}",
+ table.TableName,
+ column.ColumnName,
+ column.GetSQLType(),
+ table.PrimaryKey.Contains(column) ? "PRIMARY KEY" : null,
+ column.Unique ? "UNIQUE" : null,
+ column.IsNotNull() ? "NOT NULL" : null,
+ column.HasDefaultValue() ? ("DEFAULT " + column.GetDefaultValue()) : null);
+
+ return cmd;
+ }
+
+ /// <summary>
+ /// Adds the specified row to the specified table.
+ /// </summary>
+ /// <param name="table">The table.</param>
+ /// <param name="row">The row.</param>
+ public void AddRow(DataTable table, DataRow row)
+ {
+ var insertCommand = _connection.CreateCommand();
+
+ List<String> values = new List<string>();
+
+ for (int i = 0; i < row.ItemArray.Length; i++)
+ {
+ String value = row.ItemArray[i].ToString();
+
+ double num = 0;
+
+ if (row.ItemArray[i].GetType() == typeof(DateTime))
+ {
+ value = ((DateTime)row.ItemArray[i]).ToSQLiteDateString();
+ }
+
+ if (!double.TryParse(value, out num))
+ {
+ value = "'" + value + "'";
+ }
+
+ values.Add(value);
+ }
+
+ insertCommand.CommandText = String.Format("INSERT INTO {0} VALUES({1});", table.TableName, String.Join(",", values));
+ insertCommand.ExecuteNonQuery();
+
+ var desRow = table.NewRow();
+ desRow.ItemArray = row.ItemArray.Clone() as object[];
+ }
+
+ /// <summary>
+ /// Gets the SQL command for <see cref="AddRow(DataTable, DataRow)" />.
+ /// </summary>
+ /// <param name="table">The table.</param>
+ /// <param name="row">The row.</param>
+ /// <returns></returns>
+ public String GetAddRowCommand(DataTable table, DataRow row)
+ {
+ List<String> values = new List<string>();
+
+ for (int i = 0; i < row.ItemArray.Length; i++)
+ {
+ String value = row.ItemArray[i].ToString();
+
+ double num = 0;
+
+ if (row.ItemArray[i].GetType() == typeof(DateTime))
+ {
+ value = ((DateTime)row.ItemArray[i]).ToSQLiteDateString();
+ }
+
+ if (!double.TryParse(value, out num))
+ {
+ value = "'" + value + "'";
+ }
+
+ values.Add(value);
+ }
+
+ String cmd = String.Format("INSERT INTO {0} VALUES({1});", table.TableName, String.Join("," + Environment.NewLine, values));
+ return cmd;
+ }
+
+ /// <summary>
+ /// Updates the matching row by the row GUID.
+ /// </summary>
+ /// <param name="table">The table.</param>
+ /// <param name="row">The row.</param>
+ public void UpdateRow(DataTable table, DataRow row)
+ {
+ var updateCommand = _connection.CreateCommand();
+
+ List<String> values = new List<string>();
+
+ for (int i = 0; i < row.ItemArray.Length; i++)
+ {
+ String value = row.ItemArray[i].ToString();
+
+ double num = 0;
+
+ if (row.ItemArray[i].GetType() == typeof(DateTime))
+ {
+ value = ((DateTime)row.ItemArray[i]).ToSQLiteDateString();
+ }
+
+ if (!double.TryParse(value, out num))
+ {
+ value = "'" + value + "'";
+ }
+
+ values.Add(value);
+ }
+
+ String cmd = String.Format("UPDATE {0} SET ", table.TableName);
+
+ String guid = String.Empty;
+
+ for (int columnIndex = 0; columnIndex < table.Columns.Count; columnIndex++)
+ {
+ DataColumn column = table.Columns[columnIndex];
+ if (column.ColumnName == Constants.ID)
+ {
+ continue;
+ }
+ else if (column.ColumnName == Constants.GUID)
+ {
+ guid = values[columnIndex];
+ continue;
+ }
+
+ cmd += String.Format("{0} = {1},{2}", column.ColumnName, values[columnIndex], Environment.NewLine);
+ }
+
+ cmd = cmd.Remove(cmd.LastIndexOf(","), 1);
+
+ cmd += "WHERE" + Environment.NewLine;
+ cmd += String.Format("{0} = {1};", Constants.GUID, guid);
+
+ updateCommand.CommandText = cmd;
+ updateCommand.ExecuteNonQuery();
+ var desRow = table.NewRow();
+ desRow.ItemArray = row.ItemArray.Clone() as object[];
+ }
+
+ /// <summary>
+ /// Gets the SQL command for <see cref="UpdateRow(DataTable, DataRow)" />.
+ /// </summary>
+ /// <param name="table">The table.</param>
+ /// <param name="row">The row.</param>
+ /// <returns></returns>
+ public String GetUpdateRowCommand(DataTable table, DataRow row)
+ {
+ List<String> values = new List<string>();
+
+ for (int i = 0; i < row.ItemArray.Length; i++)
+ {
+ String value = row.ItemArray[i].ToString();
+
+ double num = 0;
+
+ if (row.ItemArray[i].GetType() == typeof(DateTime))
+ {
+ value = ((DateTime)row.ItemArray[i]).ToSQLiteDateString();
+ }
+
+ if (!double.TryParse(value, out num))
+ {
+ value = "'" + value + "'";
+ }
+
+ values.Add(value);
+ }
+
+ String cmd = String.Format("UPDATE {0} SET ", table.TableName);
+
+ String guid = String.Empty;
+
+ for (int columnIndex = 0; columnIndex < table.Columns.Count; columnIndex++)
+ {
+ DataColumn column = table.Columns[columnIndex];
+ if (column.ColumnName == Constants.ID)
+ {
+ continue;
+ }
+ else if (column.ColumnName == Constants.GUID)
+ {
+ guid = values[columnIndex];
+ continue;
+ }
+
+ cmd += String.Format("{0} = {1},{2}", column.ColumnName, values[columnIndex], Environment.NewLine);
+ }
+
+ cmd = cmd.Remove(cmd.LastIndexOf(","), 1);
+
+ cmd += "WHERE" + Environment.NewLine;
+ cmd += String.Format("{0} = {1};", Constants.GUID, guid);
+
+ return cmd;
+ }
+
+ /// <summary>
+ /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
+ /// </summary>
+ public void Dispose()
+ {
+ _connection.Close();
+ }
+ }
+}