Advertisement
Guest User

Untitled

a guest
Feb 22nd, 2011
293
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 14.75 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4.  
  5. using System.Runtime.InteropServices;
  6. using System.Data;
  7. using System.Collections;
  8.  
  9. namespace SQLiteWrapper
  10. {
  11.     /// <summary>
  12.     /// SQLite wrapper with functions for opening, closing and executing queries.
  13.     /// </summary>
  14.     public class SQLiteBase
  15.     {
  16.         // imports system functions for work with pointers
  17.         [DllImport("kernel32")]
  18.         private extern static IntPtr HeapAlloc(IntPtr heap, UInt32 flags, UInt32 bytes);
  19.  
  20.         [DllImport("kernel32")]
  21.         private extern static IntPtr GetProcessHeap();
  22.  
  23.         [DllImport("kernel32")]
  24.         private extern static int lstrlen(IntPtr str);
  25.  
  26.         // imports SQLite functions
  27.         [DllImport("sqlite3")]
  28.         private static extern int sqlite3_open(IntPtr fileName, out IntPtr database);
  29.  
  30.         [DllImport("sqlite3")]
  31.         private static extern int sqlite3_close(IntPtr database);
  32.  
  33.         [DllImport("sqlite3")]
  34.         private static extern int sqlite3_exec(IntPtr database, IntPtr query, IntPtr callback, IntPtr arguments, out IntPtr error);
  35.  
  36.         [DllImport("sqlite3")]
  37.         private static extern IntPtr sqlite3_errmsg(IntPtr database);
  38.  
  39.         [DllImport("sqlite3")]
  40.         private static extern int sqlite3_prepare_v2(IntPtr database, IntPtr query, int length, out IntPtr statement, out IntPtr tail);
  41.  
  42.         [DllImport("sqlite3")]
  43.         private static extern int sqlite3_step(IntPtr statement);
  44.  
  45.         [DllImport("sqlite3")]
  46.         private static extern int sqlite3_column_count(IntPtr statement);
  47.  
  48.         [DllImport("sqlite3")]
  49.         private static extern IntPtr sqlite3_column_name(IntPtr statement, int columnNumber);
  50.  
  51.         [DllImport("sqlite3")]
  52.         private static extern int sqlite3_column_type(IntPtr statement, int columnNumber);
  53.  
  54.         [DllImport("sqlite3")]
  55.         private static extern int sqlite3_column_int(IntPtr statement, int columnNumber);
  56.  
  57.         [DllImport("sqlite3")]
  58.         private static extern double sqlite3_column_double(IntPtr statement, int columnNumber);
  59.  
  60.         [DllImport("sqlite3")]
  61.         private static extern IntPtr sqlite3_column_text(IntPtr statement, int columnNumber);
  62.  
  63.         [DllImport("sqlite3")]
  64.         private static extern IntPtr sqlite3_column_blob(IntPtr statement, int columnNumber);
  65.  
  66.         [DllImport("sqlite3")]
  67.         private static extern IntPtr sqlite3_column_table_name(IntPtr statement, int columnNumber);
  68.  
  69.         [DllImport("sqlite3")]
  70.         private static extern int sqlite3_finalize(IntPtr handle);
  71.  
  72.         // SQLite constants
  73.         private const int SQL_OK = 0;
  74.         private const int SQL_ROW = 100;
  75.         private const int SQL_DONE = 101;
  76.  
  77.         /// <summary>
  78.         /// SQLite data types.
  79.         /// </summary>
  80.         public enum SQLiteDataTypes {
  81.             /// <summary>
  82.             /// Integer numbers.
  83.             /// </summary>
  84.             INT = 1,
  85.             /// <summary>
  86.             /// Decimal numbers.
  87.             /// </summary>
  88.             FLOAT,
  89.             /// <summary>
  90.             /// All kinds of texts.
  91.             /// </summary>
  92.             TEXT,
  93.             /// <summary>
  94.             /// Blob objects - binary large objects.
  95.             /// </summary>
  96.             BLOB,
  97.             /// <summary>
  98.             /// Nothing.
  99.             /// </summary>
  100.             NULL };
  101.  
  102.         // pointer to database
  103.         private IntPtr database;
  104.  
  105.         /// <summary>
  106.         /// Creates new instance of SQLiteBase class with no database attached.
  107.         /// </summary>
  108.         public SQLiteBase()
  109.         {
  110.             database = IntPtr.Zero;
  111.         }
  112.  
  113.         /// <summary>
  114.         /// Creates new instance of SQLiteBase class and opens database with given name.
  115.         /// </summary>
  116.         /// <param name="baseName">Name (and path) to SQLite database file</param>
  117.         public SQLiteBase(String baseName)
  118.         {
  119.             OpenDatabase(baseName);
  120.         }
  121.  
  122.         /// <summary>
  123.         /// Opens database.
  124.         /// </summary>
  125.         /// <param name="baseName">Name of database file</param>
  126.         public void OpenDatabase(String baseName)
  127.         {
  128.             // opens database
  129.             if (sqlite3_open(StringToPointer(baseName), out database) != SQL_OK)
  130.             {
  131.                 // if there is some error, database pointer is set to 0 and exception is throws
  132.                 database = IntPtr.Zero;
  133.                 throw new Exception("Error with opening database " + baseName + "!");
  134.             }
  135.         }
  136.  
  137.         /// <summary>
  138.         /// Closes opened database.
  139.         /// </summary>
  140.         public void CloseDatabase()
  141.         {
  142.             // closes the database if there is one opened
  143.             if (database != IntPtr.Zero)
  144.             {
  145.                 sqlite3_close(database);
  146.             }
  147.         }
  148.  
  149.         /// <summary>
  150.         /// Returns the list of tables in opened database.
  151.         /// </summary>
  152.         /// <returns></returns>
  153.         public ArrayList GetTables()
  154.         {
  155.             // executes query that select names of all tables and views in master table of every database
  156.             String query = "SELECT name FROM sqlite_master " +
  157.                                         "WHERE type IN ('table','view') AND name NOT LIKE 'sqlite_%'" +
  158.                                         "UNION ALL " +
  159.                                         "SELECT name FROM sqlite_temp_master " +
  160.                                         "WHERE type IN ('table','view') " +
  161.                                         "ORDER BY 1";
  162.             DataTable table = ExecuteQuery(query);
  163.  
  164.             // when table is generater, it writes all table names in list that is returned
  165.             ArrayList list = new ArrayList();
  166.             foreach (DataRow row in table.Rows)
  167.             {
  168.                 list.Add(row.ItemArray[0].ToString());
  169.             }
  170.             return list;
  171.         }
  172.  
  173.         /// <summary>
  174.         /// Executes query that does not return anything (e.g. UPDATE, INSERT, DELETE).
  175.         /// </summary>
  176.         /// <param name="query"></param>
  177.         public void ExecuteNonQuery(String query)
  178.         {
  179.             // calles SQLite function that executes non-query
  180.             IntPtr error;
  181.             sqlite3_exec(database, StringToPointer(query), IntPtr.Zero, IntPtr.Zero, out error);
  182.             // if there is error, excetion is thrown
  183.             if (error != IntPtr.Zero)
  184.                 throw new Exception("Error with executing non-query: \"" + query + "\"!\n" + PointerToString(sqlite3_errmsg(error)));
  185.         }
  186.  
  187.         /// <summary>
  188.         /// Executes query that does return something (e.g. SELECT).
  189.         /// </summary>
  190.         /// <param name="query"></param>
  191.         /// <returns></returns>
  192.         public DataTable ExecuteQuery(String query)
  193.         {
  194.             // processed query
  195.             IntPtr statement;
  196.  
  197.             // excess data, it has no use
  198.             IntPtr excessData;
  199.  
  200.             // process query and make statement
  201.             sqlite3_prepare_v2(database, StringToPointer(query), GetPointerLenght(StringToPointer(query)), out statement, out excessData);
  202.  
  203.             // table for result of function
  204.             DataTable table = new DataTable();
  205.  
  206.             // reads first row - it is different from next rows because it also creates table columns
  207.             // result - returns SLQ_ROW while there is next row
  208.             int result = ReadFirstRow(statement, ref table);
  209.  
  210.             // reads rows
  211.             while (result == SQL_ROW)
  212.             {
  213.                 result = ReadNextRow(statement, ref table);
  214.             }
  215.  
  216.             // finalize executing this query
  217.             sqlite3_finalize(statement);
  218.  
  219.             // returns table
  220.             return table;
  221.         }
  222.  
  223.         // private function for reading firs row and creating DataTable
  224.         private int ReadFirstRow(IntPtr statement, ref DataTable table)
  225.         {
  226.             // create new instance of DataTable with name "resultTable"
  227.             table = new DataTable("resultTable");
  228.  
  229.             // evaluates statement
  230.             int resultType = sqlite3_step(statement);
  231.  
  232.             // if result of statement is SQL_ROW, create new table and write row in it
  233.             if (resultType == SQL_ROW)
  234.             {
  235.                 // returns number of columns returned by statement
  236.                 int columnCount = sqlite3_column_count(statement);
  237.  
  238.                 // declartaion of variables for reading first row
  239.                 String columnName = "";
  240.                 int columnType = 0;
  241.                 object[] columnValues = new object[columnCount];
  242.  
  243.                 // reads columns one by one
  244.                 for (int i = 0; i < columnCount; i++)
  245.                 {
  246.                     // returns the name of current column
  247.                     columnName = PointerToString(sqlite3_column_name(statement, i));
  248.  
  249.                     // returns the type of current column
  250.                     columnType = sqlite3_column_type(statement, i);
  251.  
  252.                     // checks type of columns - neccessary because different functions are required for different types
  253.                     switch (columnType)
  254.                     {
  255.                             // in case of integer column
  256.                         case (int)SQLiteDataTypes.INT:
  257.                             {
  258.                                 // adds new integer column to table
  259.                                 table.Columns.Add(columnName, Type.GetType("System.Int32"));
  260.  
  261.                                 // writes column value in object array
  262.                                 columnValues[i] = sqlite3_column_int(statement, i);
  263.                                 break;
  264.                             }
  265.                             // same as for integer, this one is for float
  266.                         case (int)SQLiteDataTypes.FLOAT:
  267.                             {
  268.                                 table.Columns.Add(columnName, Type.GetType("System.Single"));
  269.                                 columnValues[i] = sqlite3_column_double(statement, i);
  270.                                 break;
  271.                             }
  272.                             // ... for text
  273.                         case (int)SQLiteDataTypes.TEXT:
  274.                             {
  275.                                 table.Columns.Add(columnName, Type.GetType("System.String"));
  276.                                 columnValues[i] = PointerToString(sqlite3_column_text(statement, i));
  277.                                 break;
  278.                             }
  279.                             // ... for blob - blob are written in table as strings!!
  280.                         case (int)SQLiteDataTypes.BLOB:
  281.                             {
  282.                                 table.Columns.Add(columnName, Type.GetType("System.String"));
  283.                                 columnValues[i] = PointerToString(sqlite3_column_blob(statement, i));
  284.                                 break;
  285.                             }
  286.                             // in case of something other, value is read as string
  287.                         default:
  288.                             {
  289.                                 table.Columns.Add(columnName, Type.GetType("System.String"));
  290.                                 columnValues[i] = "";
  291.                                 break;
  292.                             }
  293.                     }
  294.                 }
  295.  
  296.                 // writes column values to table
  297.                 table.Rows.Add(columnValues);
  298.             }
  299.  
  300.             // evalute statemnet for next results
  301.             return sqlite3_step(statement);
  302.         }
  303.  
  304.         // private function for reading rows other than first
  305.         // it' same like first row, only without creating table and columns
  306.         private int ReadNextRow(IntPtr statement, ref DataTable table)
  307.         {
  308.             int columnCount = sqlite3_column_count(statement);
  309.  
  310.             int columnType = 0;
  311.             object[] columnValues = new object[columnCount];
  312.  
  313.             for (int i = 0; i < columnCount; i++)
  314.             {
  315.                 columnType = sqlite3_column_type(statement, i);
  316.  
  317.                 switch (columnType)
  318.                 {
  319.                     case (int)SQLiteDataTypes.INT:
  320.                         {
  321.                             columnValues[i] = sqlite3_column_int(statement, i);
  322.                             break;
  323.                         }
  324.                     case (int)SQLiteDataTypes.FLOAT:
  325.                         {
  326.                             columnValues[i] = sqlite3_column_double(statement, i);
  327.                             break;
  328.                         }
  329.                     case (int)SQLiteDataTypes.TEXT:
  330.                         {
  331.                             columnValues[i] = PointerToString(sqlite3_column_text(statement, i));
  332.                             break;
  333.                         }
  334.                     case (int)SQLiteDataTypes.BLOB:
  335.                         {
  336.                             columnValues[i] = PointerToString(sqlite3_column_blob(statement, i));
  337.                             break;
  338.                         }
  339.                     default:
  340.                         {
  341.                             columnValues[i] = "";
  342.                             break;
  343.                         }
  344.                 }
  345.             }
  346.             table.Rows.Add(columnValues);
  347.             return sqlite3_step(statement);
  348.         }
  349.  
  350.         // converts string to pointer
  351.         private IntPtr StringToPointer(String str)
  352.         {
  353.             // if string is null, pointer is 0
  354.             if (str == null)
  355.             {
  356.                 return IntPtr.Zero;
  357.             }
  358.             else
  359.             {
  360.                 // else, convert it to pointer
  361.                 Encoding encoding = Encoding.UTF8;
  362.                 Byte[] bytes = encoding.GetBytes(str);
  363.                 int length = bytes.Length + 1;
  364.                 IntPtr pointer = HeapAlloc(GetProcessHeap(), 0, (UInt32)length);
  365.                 Marshal.Copy(bytes, 0, pointer, bytes.Length);
  366.                 Marshal.WriteByte(pointer, bytes.Length, 0);
  367.                 return pointer;
  368.             }
  369.         }
  370.  
  371.         // convert pointer to string
  372.         private String PointerToString(IntPtr ptr)
  373.         {
  374.             if (ptr == IntPtr.Zero)
  375.                 return null;
  376.  
  377.             Encoding encoding = Encoding.UTF8;
  378.  
  379.             int length = GetPointerLenght(ptr);
  380.             Byte[] bytes = new Byte[length];
  381.             Marshal.Copy(ptr, bytes, 0, length);
  382.             return encoding.GetString(bytes, 0, length);
  383.         }
  384.  
  385.         // returns length of pointer
  386.         private int GetPointerLenght(IntPtr ptr)
  387.         {
  388.             if (ptr == IntPtr.Zero)
  389.                 return 0;
  390.             return lstrlen(ptr);
  391.         }
  392.     }
  393. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement