[hyena/sqlite] [Hyena.Data.Sqlite] Keep ref to custom functions
- From: Gabriel Burt <gburt src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [hyena/sqlite] [Hyena.Data.Sqlite] Keep ref to custom functions
- Date: Sun, 14 Nov 2010 01:12:03 +0000 (UTC)
commit 7f5463e232ce1b1aaba9633143c6ae8c594eeb4a
Author: Gabriel Burt <gabriel burt gmail com>
Date: Sat Nov 13 19:05:00 2010 -0600
[Hyena.Data.Sqlite] Keep ref to custom functions
Also add FieldNames property to IDataReader, and add copyright header.
Hyena.Data.Sqlite/Hyena.Data.Sqlite/Sqlite.cs | 120 ++++++++++++++++++------
1 files changed, 90 insertions(+), 30 deletions(-)
---
diff --git a/Hyena.Data.Sqlite/Hyena.Data.Sqlite/Sqlite.cs b/Hyena.Data.Sqlite/Hyena.Data.Sqlite/Sqlite.cs
index f818161..de5fad0 100644
--- a/Hyena.Data.Sqlite/Hyena.Data.Sqlite/Sqlite.cs
+++ b/Hyena.Data.Sqlite/Hyena.Data.Sqlite/Sqlite.cs
@@ -1,3 +1,31 @@
+//
+// Sqlite.cs
+//
+// Authors:
+// Gabriel Burt <gburt novell com>
+//
+// Copyright (C) 2010 Novell, Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
using System;
using System.Linq;
using System.Text;
@@ -5,6 +33,8 @@ using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices;
+using Hyena;
+
namespace Hyena.Data.Sqlite
{
public class Connection : IDisposable
@@ -27,7 +57,6 @@ namespace Hyena.Data.Sqlite
if (ptr == IntPtr.Zero)
throw new Exception ("Unable to open connection");
- Console.WriteLine ("Opened connection to {0}", dbPath);
Native.sqlite3_extended_result_codes (ptr, 1);
AddFunction<BinaryFunction> ();
@@ -97,9 +126,17 @@ namespace Hyena.Data.Sqlite
public void Execute (string sql)
{
+ // TODO
+ // * The application must insure that the 1st parameter to sqlite3_exec() is a valid and open database connection.
+ // * The application must not close database connection specified by the 1st parameter to sqlite3_exec() while sqlite3_exec() is running.
+ // * The application must not modify the SQL statement text passed into the 2nd parameter of sqlite3_exec() while sqlite3_exec() is running.
CheckError (Native.sqlite3_exec (Ptr, Native.GetUtf8Bytes (sql), IntPtr.Zero, IntPtr.Zero, IntPtr.Zero), sql);
}
+ // We need to keep a managed ref to the function objects we create so
+ // they won't get GC'd
+ List<SqliteFunction> functions = new List<SqliteFunction> ();
+
const int UTF16 = 4;
public void AddFunction<T> () where T : SqliteFunction
{
@@ -122,6 +159,7 @@ namespace Hyena.Data.Sqlite
ptr, pr.Name, UTF16, IntPtr.Zero, f._CompareFunc
));
}
+ functions.Add (f);
}
public void RemoveFunction<T> () where T : SqliteFunction
@@ -138,6 +176,11 @@ namespace Hyena.Data.Sqlite
ptr, pr.Name, UTF16, IntPtr.Zero, null
));
}
+
+ var func = functions.FirstOrDefault (f => f is T);
+ if (func != null) {
+ functions.Remove (func);
+ }
}
}
@@ -160,6 +203,7 @@ namespace Hyena.Data.Sqlite
T Get<T> (string columnName);
object Get (int i, Type asType);
int FieldCount { get; }
+ string [] FieldNames { get; }
}
public class Statement : IDisposable, IEnumerable<IDataReader>
@@ -207,14 +251,16 @@ namespace Hyena.Data.Sqlite
internal void CheckReading ()
{
CheckDisposed ();
- if (!Reading)
+ if (!Reading) {
throw new InvalidOperationException ("Statement is not readable");
+ }
}
internal void CheckDisposed ()
{
- if (disposed)
+ if (disposed) {
throw new InvalidOperationException ("Statement is disposed");
+ }
}
private string ShortSql { get { return CommandText.Substring (0, Math.Min (CommandText.Length, 20)); } }
@@ -251,7 +297,7 @@ namespace Hyena.Data.Sqlite
object [] null_val = new object [] { null };
public Statement Bind (params object [] vals)
{
- CheckDisposed ();
+ Reset ();
if (vals == null && ParameterCount == 1)
vals = null_val;
@@ -259,8 +305,6 @@ namespace Hyena.Data.Sqlite
if (vals == null || vals.Length != ParameterCount || ParameterCount == 0)
throw new ArgumentException ("vals", String.Format ("Statement has {0} parameters", ParameterCount));
- Reset ();
-
for (int i = 1; i <= vals.Length; i++) {
int code = 0;
object o = SqliteUtils.ToDbFormat (vals[i - 1]);
@@ -304,8 +348,9 @@ namespace Hyena.Data.Sqlite
private void Reset ()
{
CheckDisposed ();
- if (Reading)
+ if (Reading) {
throw new InvalidOperationException ("Can't reset statement while it's being read; make sure to Dispose any IDataReaders");
+ }
CheckError (Native.sqlite3_reset (ptr));
}
@@ -347,7 +392,7 @@ namespace Hyena.Data.Sqlite
}
}
- public class QueryReader : IDisposable, IDataReader
+ public class QueryReader : IDataReader
{
Dictionary<string, int> columns;
int column_count = -1;
@@ -373,6 +418,16 @@ namespace Hyena.Data.Sqlite
}
}
+ string [] field_names;
+ public string [] FieldNames {
+ get {
+ if (field_names == null) {
+ field_names = Columns.Keys.OrderBy (f => Columns[f]).ToArray ();
+ }
+ return field_names;
+ }
+ }
+
public bool Read ()
{
Statement.CheckDisposed ();
@@ -428,28 +483,27 @@ namespace Hyena.Data.Sqlite
public object Get (int i, Type asType)
{
- var o = this[i];
- if (o != null && o.GetType () == asType)
- return o;
-
- o = GetAs (o, asType);
- if (o != null && o.GetType () == asType)
- return o;
-
- return SqliteUtils.FromDbFormat (asType, o);
+ return GetAs (this[i], asType);
}
- private object GetAs (object o, Type type)
+ internal static object GetAs (object o, Type type)
{
+ if (o != null && o.GetType () == type)
+ return o;
+
if (o == null)
- return null;
+ o = null;
else if (type == typeof(uint))
- return (uint)(long)o;
+ o = (uint)(long)o;
else if (type == typeof(ulong))
- return (ulong)(long)o;
+ o = (ulong)(long)o;
else if (type == typeof(float))
- return (float)(double)o;
- return o;
+ o = (float)(double)o;
+
+ if (o != null && o.GetType () == type)
+ return o;
+
+ return SqliteUtils.FromDbFormat (type, o);
}
static Type long_type = typeof(long);
@@ -475,18 +529,24 @@ namespace Hyena.Data.Sqlite
return Get<T> (GetColumnIndex (columnName));
}
+ private Dictionary<string, int> Columns {
+ get {
+ if (columns == null) {
+ columns = new Dictionary<string, int> ();
+ for (int i = 0; i < FieldCount; i++) {
+ columns[Native.sqlite3_column_name16 (Ptr, i).PtrToString ()] = i;
+ }
+ }
+ return columns;
+ }
+ }
+
private int GetColumnIndex (string columnName)
{
Statement.CheckReading ();
- if (columns == null) {
- columns = new Dictionary<string, int> ();
- for (int i = 0; i < FieldCount; i++) {
- columns[Native.sqlite3_column_name16 (Ptr, i).PtrToString ()] = i;
- }
- }
int col = 0;
- if (!columns.TryGetValue (columnName, out col))
+ if (!Columns.TryGetValue (columnName, out col))
throw new ArgumentException ("columnName");
return col;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]