diff --git a/src/Microsoft.Data.Sqlite.Core/SqliteConnection.cs b/src/Microsoft.Data.Sqlite.Core/SqliteConnection.cs
index ee280db4..c74abdca 100644
--- a/src/Microsoft.Data.Sqlite.Core/SqliteConnection.cs
+++ b/src/Microsoft.Data.Sqlite.Core/SqliteConnection.cs
@@ -556,5 +556,168 @@ public AggregateContext(T seed)
public T Accumulate { get; set; }
public Exception Exception { get; set; }
}
+
+ ///
+ /// System.Data.Common, initial implementation of API DBConnection.GetSchema(String)
+ /// Returns schema information for the data source of this DbConnection using the specified string for the schema name.
+ ///
+ /// A DataTable that contains supported MetaDataCollections.
+ public override DataTable GetSchema()
+ => GetSchema(DbMetaDataCollectionNames.MetaDataCollections, null);
+
+ ///
+ /// System.Data.Common, initial implementation of API DBConnection.GetSchema(String)
+ /// Returns schema information for the data source of this DbConnection using the specified string for the schema name.
+ ///
+ /// Specifies the name of the schema to return.
+ /// A DataTable that contains schema information.
+ public override System.Data.DataTable GetSchema(string collectionName)
+ => GetSchema(collectionName, null);
+
+ ///
+ /// System.Data.Common, initial implementation of API DBConnection.GetSchema(String)
+ /// Returns schema information for the data source of this DbConnection using the specified string for the schema name.
+ ///
+ /// Specifies the name of the schema to return.
+ /// Restrictions not supported yet.
+ /// A DataTable that contains schema information.
+ public override System.Data.DataTable GetSchema(string collectionName, string[] restrictions)
+ {
+ var dt = new DataTable(collectionName);
+ switch (collectionName)
+ {
+ case "MetaDataCollections":
+ dt.Columns.AddRange(new[] {
+ new DataColumn("CollectionName", typeof(string)),
+ new DataColumn("NumberOfRestrictions", typeof(int)),
+ new DataColumn("NumberOfIdentifierParts", typeof(int))
+ });
+ dt.Rows.Add("MetaDataCollections", 0, 0);
+ dt.Rows.Add("DataTypes", 0, 0);
+ dt.Rows.Add("Tables", 0, 0);
+ dt.Rows.Add("ForeignKeys", 0, 0);
+ return dt;
+
+ case "DataTypes":
+ dt.Columns.AddRange(new[] {
+ new DataColumn(DbMetaDataColumnNames.DataType, typeof(string)),
+ new DataColumn(DbMetaDataColumnNames.TypeName, typeof(string)),
+ new DataColumn(DbMetaDataColumnNames.ProviderDbType, typeof(int))
+ });
+ dt.Rows.Add(new object[] { "System.Int16", "smallint", 10 });
+ dt.Rows.Add(new object[] { "System.Int32","int",11 });
+ dt.Rows.Add(new object[] { "System.Double","real",8 });
+ dt.Rows.Add(new object[] { "System.Single","single",15 });
+ dt.Rows.Add(new object[] { "System.Double","float",8 });
+ dt.Rows.Add(new object[] { "System.Double","double",8 });
+ dt.Rows.Add(new object[] { "System.Decimal","money",7 });
+ dt.Rows.Add(new object[] { "System.Decimal","currency",7 });
+ dt.Rows.Add(new object[] { "System.Decimal","decimal",7 });
+ dt.Rows.Add(new object[] { "System.Decimal","numeric",7 });
+ dt.Rows.Add(new object[] { "System.Boolean","bit",3 });
+ dt.Rows.Add(new object[] { "System.Boolean","yesno",3 });
+ dt.Rows.Add(new object[] { "System.Boolean","logical",3 });
+ dt.Rows.Add(new object[] { "System.Boolean","bool",3 });
+ dt.Rows.Add(new object[] { "System.Boolean","boolean",3 });
+ dt.Rows.Add(new object[] { "System.Byte","tinyint",2 });
+ dt.Rows.Add(new object[] { "System.Int64","integer",12 });
+ dt.Rows.Add(new object[] { "System.Int64","counter",12 });
+ dt.Rows.Add(new object[] { "System.Int64","autoincrement",12 });
+ dt.Rows.Add(new object[] { "System.Int64","identity",12 });
+ dt.Rows.Add(new object[] { "System.Int64","long",12 });
+ dt.Rows.Add(new object[] { "System.Int64","bigint",12 });
+ dt.Rows.Add(new object[] { "System.Byte[]","binary",1 });
+ dt.Rows.Add(new object[] { "System.Byte[]","varbinary",1 });
+ dt.Rows.Add(new object[] { "System.Byte[]","blob",1 });
+ dt.Rows.Add(new object[] { "System.Byte[]","image",1 });
+ dt.Rows.Add(new object[] { "System.Byte[]","general",1 });
+ dt.Rows.Add(new object[] { "System.Byte[]","oleobject",1 });
+ dt.Rows.Add(new object[] { "System.String","varchar",16 });
+ dt.Rows.Add(new object[] { "System.String","nvarchar",16 });
+ dt.Rows.Add(new object[] { "System.String","memo",16 });
+ dt.Rows.Add(new object[] { "System.String","longtext",16 });
+ dt.Rows.Add(new object[] { "System.String","note",16 });
+ dt.Rows.Add(new object[] { "System.String","text",16 });
+ dt.Rows.Add(new object[] { "System.String","ntext",16 });
+ dt.Rows.Add(new object[] { "System.String","string",16 });
+ dt.Rows.Add(new object[] { "System.String","char",16 });
+ dt.Rows.Add(new object[] { "System.String","nchar",16 });
+ dt.Rows.Add(new object[] { "System.DateTime","datetime",6 });
+ dt.Rows.Add(new object[] { "System.DateTime","smalldate",6 });
+ dt.Rows.Add(new object[] { "System.DateTime","timestamp",6 });
+ dt.Rows.Add(new object[] { "System.DateTime","date",6 });
+ dt.Rows.Add(new object[] { "System.DateTime","time",6 });
+ dt.Rows.Add(new object[] { "System.Guid","uniqueidentifier",4 });
+ dt.Rows.Add(new object[] { "System.Guid","guid",4 });
+ return dt;
+ case "Tables":
+ dt.Columns.AddRange(new[] {
+ new DataColumn("TABLE_TYPE"),
+ new DataColumn("TABLE_CATALOG"),
+ new DataColumn("TABLE_NAME")
+ });
+ var typesQuery = "SELECT type as TABLE_TYPE, 'main' as TABLE_CATALOG, name as TABLE_NAME FROM sqlite_master WHERE type='table';";
+ if(this.State != ConnectionState.Open)
+ {
+ this.Open();
+ }
+ using (var com = new SqliteCommand(typesQuery, this))
+ using(var reader = com.ExecuteReader())
+ {
+ while (reader.Read()) {
+ dt.Rows.Add(new object[] { reader.GetString(0), reader.GetString(1), reader.GetString(2) });
+ }
+ }
+ return dt;
+ case "ForeignKeys":
+ var tableQuery = "SELECT name as TABLE_NAME FROM sqlite_master WHERE type='table';";
+ var tables = new List();
+
+ if (this.State != ConnectionState.Open)
+ {
+ this.Open();
+ }
+
+ using (var com = new SqliteCommand(tableQuery, this))
+ using (var reader = com.ExecuteReader())
+ {
+ while (reader.Read())
+ {
+ tables.Add(reader.GetString(0));
+ }
+ }
+ dt.Columns.AddRange(new[] {
+ new DataColumn("TABLE_NAME"),
+ new DataColumn("FKEY_TO_CATALOG"),
+ new DataColumn("TABLE_CATALOG"),
+ new DataColumn("FKEY_TO_TABLE"),
+ new DataColumn("FKEY_FROM_COLUMN"),
+ new DataColumn("FKEY_TO_COLUMN"),
+ new DataColumn("CONSTRAINT_NAME")
+ });
+ foreach(var tablename in tables){
+ var relationQuery = "pragma foreign_key_list(" + tablename + ")";
+ using (var com = new SqliteCommand(relationQuery, this))
+ using (var reader = com.ExecuteReader())
+ {
+ while (reader.Read())
+ {
+ dt.Rows.Add(new object[] {
+ tablename,
+ "main",
+ "main",
+ reader.GetString(2),
+ reader.GetString(3),
+ reader.GetString(4),
+ "fk_" + tablename + reader.GetString(0)
+ });
+ }
+ }
+ }
+ return dt;
+ default:
+ throw new NotImplementedException("Not yet supported: GetSchema(\"" + collectionName + "\"). We do accept PRs.");
+ }
+ }
}
}
diff --git a/test/Microsoft.Data.Sqlite.Tests/SqliteConnectionTest.cs b/test/Microsoft.Data.Sqlite.Tests/SqliteConnectionTest.cs
index e87b9f5a..9f2b3d50 100644
--- a/test/Microsoft.Data.Sqlite.Tests/SqliteConnectionTest.cs
+++ b/test/Microsoft.Data.Sqlite.Tests/SqliteConnectionTest.cs
@@ -890,5 +890,36 @@ public void DataChange_event_works()
Assert.Equal(101, list[0].RowId);
}
}
+
+ [Fact]
+ public void GetSchema_has_collections()
+ {
+ var connectionString = "Data Source=:memory:";
+
+ var connection = new SqliteConnection(connectionString);
+
+ var collections = connection.GetSchema("MetaDataCollections", new string[] { });
+ Assert.Equal("CollectionName", collections.Columns[0].ColumnName);
+ Assert.True(collections.Rows != null);
+ var crow1 = String.Join(",", collections.Rows[0].ItemArray);
+ Assert.Equal("MetaDataCollections,0,0", crow1);
+
+ var dataTypes = connection.GetSchema("DataTypes");
+ Assert.Equal("DataType", dataTypes.Columns[0].ColumnName);
+ Assert.True(dataTypes.Rows != null);
+ Assert.True(dataTypes.Rows.Count > 15);
+ var drow1 = String.Join(",", dataTypes.Rows[0].ItemArray);
+ Assert.Equal("System.Int16,smallint,10", drow1);
+
+ var tables = connection.GetSchema("Tables");
+ Assert.Equal("TABLE_TYPE", tables.Columns[0].ColumnName);
+ Assert.True(tables.Rows != null);
+
+ var fkKeys = connection.GetSchema("ForeignKeys");
+ Assert.Equal("TABLE_NAME", fkKeys.Columns[0].ColumnName);
+ Assert.True(fkKeys.Rows!=null);
+
+ }
+
}
}