diff --git a/COPYRIGHT b/COPYRIGHT
new file mode 100644
--- /dev/null
+++ b/COPYRIGHT
@@ -0,0 +1,426 @@
+GNU Lesser General Public License
+
+Version 2.1, February 1999
+
+    Copyright (C) 1991, 1999 Free Software Foundation, Inc. 59 Temple Place,
+    Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and
+    distribute verbatim copies of this license document, but changing it is not
+    allowed.
+
+    [This is the first released version of the Lesser GPL. It also counts as
+    the successor of the GNU Library Public License, version 2, hence the
+    version number 2.1.]
+
+Preamble
+
+The licenses for most software are designed to take away your freedom to share
+and change it. By contrast, the GNU General Public Licenses are intended to
+guarantee your freedom to share and change free software--to make sure the
+software is free for all its users.
+
+This license, the Lesser General Public License, applies to some specially
+designated software packages--typically libraries--of the Free Software
+Foundation and other authors who decide to use it. You can use it too, but we
+suggest you first think carefully about whether this license or the ordinary
+General Public License is the better strategy to use in any particular case,
+based on the explanations below.
+
+When we speak of free software, we are referring to freedom of use, not price.
+Our General Public Licenses are designed to make sure that you have the freedom
+to distribute copies of free software (and charge for this service if you
+wish); that you receive source code or can get it if you want it; that you can
+change the software and use pieces of it in new free programs; and that you are
+informed that you can do these things.
+
+To protect your rights, we need to make restrictions that forbid distributors
+to deny you these rights or to ask you to surrender these rights. These
+restrictions translate to certain responsibilities for you if you distribute
+copies of the library or if you modify it.
+
+For example, if you distribute copies of the library, whether gratis or for a
+fee, you must give the recipients all the rights that we gave you. You must
+make sure that they, too, receive or can get the source code. If you link other
+code with the library, you must provide complete object files to the
+recipients, so that they can relink them with the library after making changes
+to the library and recompiling it. And you must show them these terms so they
+know their rights.
+
+We protect your rights with a two-step method: (1) we copyright the library,
+and (2) we offer you this license, which gives you legal permission to copy,
+distribute and/or modify the library.
+
+To protect each distributor, we want to make it very clear that there is no
+warranty for the free library. Also, if the library is modified by someone else
+and passed on, the recipients should know that what they have is not the
+original version, so that the original author's reputation will not be affected
+by problems that might be introduced by others.
+
+Finally, software patents pose a constant threat to the existence of any free
+program. We wish to make sure that a company cannot effectively restrict the
+users of a free program by obtaining a restrictive license from a patent
+holder. Therefore, we insist that any patent license obtained for a version of
+the library must be consistent with the full freedom of use specified in this
+license.
+
+Most GNU software, including some libraries, is covered by the ordinary GNU
+General Public License. This license, the GNU Lesser General Public License,
+applies to certain designated libraries, and is quite different from the
+ordinary General Public License. We use this license for certain libraries in
+order to permit linking those libraries into non-free programs.
+
+When a program is linked with a library, whether statically or using a shared
+library, the combination of the two is legally speaking a combined work, a
+derivative of the original library. The ordinary General Public License
+therefore permits such linking only if the entire combination fits its criteria
+of freedom. The Lesser General Public License permits more lax criteria for
+linking other code with the library.
+
+We call this license the "Lesser" General Public License because it does Less
+to protect the user's freedom than the ordinary General Public License. It also
+provides other free software developers Less of an advantage over competing
+non-free programs. These disadvantages are the reason we use the ordinary
+General Public License for many libraries. However, the Lesser license provides
+advantages in certain special circumstances.
+
+For example, on rare occasions, there may be a special need to encourage the
+widest possible use of a certain library, so that it becomes a de-facto
+standard. To achieve this, non-free programs must be allowed to use the
+library. A more frequent case is that a free library does the same job as
+widely used non-free libraries. In this case, there is little to gain by
+limiting the free library to free software only, so we use the Lesser General
+Public License.
+
+In other cases, permission to use a particular library in non-free programs
+enables a greater number of people to use a large body of free software. For
+example, permission to use the GNU C Library in non-free programs enables many
+more people to use the whole GNU operating system, as well as its variant, the
+GNU/Linux operating system.
+
+Although the Lesser General Public License is Less protective of the users'
+freedom, it does ensure that the user of a program that is linked with the
+Library has the freedom and the wherewithal to run that program using a
+modified version of the Library.
+
+The precise terms and conditions for copying, distribution and modification
+follow. Pay close attention to the difference between a "work based on the
+library" and a "work that uses the library". The former contains code derived
+from the library, whereas the latter must be combined with the library in order
+to run.
+
+TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+0. This License Agreement applies to any software library or other program
+which contains a notice placed by the copyright holder or other authorized
+party saying it may be distributed under the terms of this Lesser General
+Public License (also called "this License"). Each licensee is addressed as
+"you".
+
+A "library" means a collection of software functions and/or data prepared so as
+to be conveniently linked with application programs (which use some of those
+functions and data) to form executables.
+
+The "Library", below, refers to any such software library or work which has
+been distributed under these terms. A "work based on the Library" means either
+the Library or any derivative work under copyright law: that is to say, a work
+containing the Library or a portion of it, either verbatim or with
+modifications and/or translated straightforwardly into another language.
+(Hereinafter, translation is included without limitation in the term
+"modification".)
+
+"Source code" for a work means the preferred form of the work for making
+modifications to it. For a library, complete source code means all the source
+code for all modules it contains, plus any associated interface definition
+files, plus the scripts used to control compilation and installation of the
+library.
+
+Activities other than copying, distribution and modification are not covered by
+this License; they are outside its scope. The act of running a program using
+the Library is not restricted, and output from such a program is covered only
+if its contents constitute a work based on the Library (independent of the use
+of the Library in a tool for writing it). Whether that is true depends on what
+the Library does and what the program that uses the Library does.
+
+1. You may copy and distribute verbatim copies of the Library's complete source
+code as you receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice and
+disclaimer of warranty; keep intact all the notices that refer to this License
+and to the absence of any warranty; and distribute a copy of this License along
+with the Library.
+
+You may charge a fee for the physical act of transferring a copy, and you may
+at your option offer warranty protection in exchange for a fee.
+
+2. You may modify your copy or copies of the Library or any portion of it, thus
+forming a work based on the Library, and copy and distribute such modifications
+or work under the terms of Section 1 above, provided that you also meet all of
+these conditions:
+
+    a) The modified work must itself be a software library.
+
+    b) You must cause the files modified to carry prominent notices stating
+    that you changed the files and the date of any change.
+
+    c) You must cause the whole of the work to be licensed at no charge to all
+    third parties under the terms of this License.
+
+    d) If a facility in the modified Library refers to a function or a table of
+    data to be supplied by an application program that uses the facility, other
+    than as an argument passed when the facility is invoked, then you must make
+    a good faith effort to ensure that, in the event an application does not
+    supply such function or table, the facility still operates, and performs
+    whatever part of its purpose remains meaningful.
+
+    (For example, a function in a library to compute square roots has a purpose
+    that is entirely well-defined independent of the application. Therefore,
+    Subsection 2d requires that any application-supplied function or table used
+    by this function must be optional: if the application does not supply it,
+    the square root function must still compute square roots.)
+
+    These requirements apply to the modified work as a whole. If identifiable
+    sections of that work are not derived from the Library, and can be
+    reasonably considered independent and separate works in themselves, then
+    this License, and its terms, do not apply to those sections when you
+    distribute them as separate works. But when you distribute the same
+    sections as part of a whole which is a work based on the Library, the
+    distribution of the whole must be on the terms of this License, whose
+    permissions for other licensees extend to the entire whole, and thus to
+    each and every part regardless of who wrote it.
+
+    Thus, it is not the intent of this section to claim rights or contest your
+    rights to work written entirely by you; rather, the intent is to exercise
+    the right to control the distribution of derivative or collective works
+    based on the Library.
+
+    In addition, mere aggregation of another work not based on the Library with
+    the Library (or with a work based on the Library) on a volume of a storage
+    or distribution medium does not bring the other work under the scope of
+    this License.
+
+3. You may opt to apply the terms of the ordinary GNU General Public License
+instead of this License to a given copy of the Library. To do this, you must
+alter all the notices that refer to this License, so that they refer to the
+ordinary GNU General Public License, version 2, instead of to this License. (If
+a newer version than version 2 of the ordinary GNU General Public License has
+appeared, then you can specify that version instead if you wish.) Do not make
+any other change in these notices.
+
+Once this change is made in a given copy, it is irreversible for that copy, so
+the ordinary GNU General Public License applies to all subsequent copies and
+derivative works made from that copy.
+
+This option is useful when you wish to copy part of the code of the Library
+into a program that is not a library.
+
+4. You may copy and distribute the Library (or a portion or derivative of it,
+under Section 2) in object code or executable form under the terms of Sections
+1 and 2 above provided that you accompany it with the complete corresponding
+machine-readable source code, which must be distributed under the terms of
+Sections 1 and 2 above on a medium customarily used for software interchange.
+
+If distribution of object code is made by offering access to copy from a
+designated place, then offering equivalent access to copy the source code from
+the same place satisfies the requirement to distribute the source code, even
+though third parties are not compelled to copy the source along with the object
+code.
+
+5. A program that contains no derivative of any portion of the Library, but is
+designed to work with the Library by being compiled or linked with it, is
+called a "work that uses the Library". Such a work, in isolation, is not a
+derivative work of the Library, and therefore falls outside the scope of this
+License.
+
+However, linking a "work that uses the Library" with the Library creates an
+executable that is a derivative of the Library (because it contains portions of
+the Library), rather than a "work that uses the library". The executable is
+therefore covered by this License. Section 6 states terms for distribution of
+such executables.
+
+When a "work that uses the Library" uses material from a header file that is
+part of the Library, the object code for the work may be a derivative work of
+the Library even though the source code is not. Whether this is true is
+especially significant if the work can be linked without the Library, or if the
+work is itself a library. The threshold for this to be true is not precisely
+defined by law.
+
+If such an object file uses only numerical parameters, data structure layouts
+and accessors, and small macros and small inline functions (ten lines or less
+in length), then the use of the object file is unrestricted, regardless of
+whether it is legally a derivative work. (Executables containing this object
+code plus portions of the Library will still fall under Section 6.)
+
+Otherwise, if the work is a derivative of the Library, you may distribute the
+object code for the work under the terms of Section 6. Any executables
+containing that work also fall under Section 6, whether or not they are linked
+directly with the Library itself.
+
+6. As an exception to the Sections above, you may also combine or link a "work
+that uses the Library" with the Library to produce a work containing portions
+of the Library, and distribute that work under terms of your choice, provided
+that the terms permit modification of the work for the customer's own use and
+reverse engineering for debugging such modifications.
+
+You must give prominent notice with each copy of the work that the Library is
+used in it and that the Library and its use are covered by this License. You
+must supply a copy of this License. If the work during execution displays
+copyright notices, you must include the copyright notice for the Library among
+them, as well as a reference directing the user to the copy of this License.
+Also, you must do one of these things:
+
+    a) Accompany the work with the complete corresponding machine-readable
+    source code for the Library including whatever changes were used in the
+    work (which must be distributed under Sections 1 and 2 above); and, if the
+    work is an executable linked with the Library, with the complete
+    machine-readable "work that uses the Library", as object code and/or source
+    code, so that the user can modify the Library and then relink to produce a
+    modified executable containing the modified Library. (It is understood that
+    the user who changes the contents of definitions files in the Library will
+    not necessarily be able to recompile the application to use the modified
+    definitions.)
+
+    b) Use a suitable shared library mechanism for linking with the Library. A
+    suitable mechanism is one that (1) uses at run time a copy of the library
+    already present on the user's computer system, rather than copying library
+    functions into the executable, and (2) will operate properly with a
+    modified version of the library, if the user installs one, as long as the
+    modified version is interface-compatible with the version that the work was
+    made with.
+
+    c) Accompany the work with a written offer, valid for at least three years,
+    to give the same user the materials specified in Subsection 6a, above, for
+    a charge no more than the cost of performing this distribution.
+
+    d) If distribution of the work is made by offering access to copy from a
+    designated place, offer equivalent access to copy the above specified
+    materials from the same place.
+
+    e) Verify that the user has already received a copy of these materials or
+    that you have already sent this user a copy.
+
+For an executable, the required form of the "work that uses the Library" must
+include any data and utility programs needed for reproducing the executable
+from it. However, as a special exception, the materials to be distributed need
+not include anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the operating
+system on which the executable runs, unless that component itself accompanies
+the executable.
+
+It may happen that this requirement contradicts the license restrictions of
+other proprietary libraries that do not normally accompany the operating
+system. Such a contradiction means you cannot use both them and the Library
+together in an executable that you distribute.
+
+7. You may place library facilities that are a work based on the Library
+side-by-side in a single library together with other library facilities not
+covered by this License, and distribute such a combined library, provided that
+the separate distribution of the work based on the Library and of the other
+library facilities is otherwise permitted, and provided that you do these two
+things:
+
+    a) Accompany the combined library with a copy of the same work based on the
+    Library, uncombined with any other library facilities. This must be
+    distributed under the terms of the Sections above.
+
+    b) Give prominent notice with the combined library of the fact that part of
+    it is a work based on the Library, and explaining where to find the
+    accompanying uncombined form of the same work.
+
+8. You may not copy, modify, sublicense, link with, or distribute the Library
+except as expressly provided under this License. Any attempt otherwise to copy,
+modify, sublicense, link with, or distribute the Library is void, and will
+automatically terminate your rights under this License. However, parties who
+have received copies, or rights, from you under this License will not have
+their licenses terminated so long as such parties remain in full compliance.
+
+9. You are not required to accept this License, since you have not signed it.
+However, nothing else grants you permission to modify or distribute the Library
+or its derivative works. These actions are prohibited by law if you do not
+accept this License. Therefore, by modifying or distributing the Library (or
+any work based on the Library), you indicate your acceptance of this License to
+do so, and all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+10. Each time you redistribute the Library (or any work based on the Library),
+the recipient automatically receives a license from the original licensor to
+copy, distribute, link with or modify the Library subject to these terms and
+conditions. You may not impose any further restrictions on the recipients'
+exercise of the rights granted herein. You are not responsible for enforcing
+compliance by third parties with this License.
+
+11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues), conditions
+are imposed on you (whether by court order, agreement or otherwise) that
+contradict the conditions of this License, they do not excuse you from the
+conditions of this License. If you cannot distribute so as to satisfy
+simultaneously your obligations under this License and any other pertinent
+obligations, then as a consequence you may not distribute the Library at all.
+For example, if a patent license would not permit royalty-free redistribution
+of the Library by all those who receive copies directly or indirectly through
+you, then the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply, and
+the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any patents or
+other property right claims or to contest validity of any such claims; this
+section has the sole purpose of protecting the integrity of the free software
+distribution system which is implemented by public license practices. Many
+people have made generous contributions to the wide range of software
+distributed through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing to
+distribute software through any other system and a licensee cannot impose that
+choice.
+
+This section is intended to make thoroughly clear what is believed to be a
+consequence of the rest of this License.
+
+12. If the distribution and/or use of the Library is restricted in certain
+countries either by patents or by copyrighted interfaces, the original
+copyright holder who places the Library under this License may add an explicit
+geographical distribution limitation excluding those countries, so that
+distribution is permitted only in or among countries not thus excluded. In such
+case, this License incorporates the limitation as if written in the body of
+this License.
+
+13. The Free Software Foundation may publish revised and/or new versions of the
+Lesser General Public License from time to time. Such new versions will be
+similar in spirit to the present version, but may differ in detail to address
+new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library specifies
+a version number of this License which applies to it and "any later version",
+you have the option of following the terms and conditions either of that
+version or of any later version published by the Free Software Foundation. If
+the Library does not specify a license version number, you may choose any
+version ever published by the Free Software Foundation.
+
+14. If you wish to incorporate parts of the Library into other free programs
+whose distribution conditions are incompatible with these, write to the author
+to ask for permission. For software which is copyrighted by the Free Software
+Foundation, write to the Free Software Foundation; we sometimes make exceptions
+for this. Our decision will be guided by the two goals of preserving the free
+status of all derivatives of our free software and of promoting the sharing and
+reuse of software generally.
+
+NO WARRANTY
+
+15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR
+THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE
+STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE
+LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND
+PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU
+ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL
+ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE
+LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR
+INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA
+BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER
+OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+END OF TERMS AND CONDITIONS
diff --git a/LICENSE b/LICENSE
deleted file mode 100644
--- a/LICENSE
+++ /dev/null
@@ -1,31 +0,0 @@
-Copyright (c) 2007, Evgeny Jukov
-Copyright (c) 2008-2009, Maurício C. Antunes
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are
-met:
-
-    * Redistributions of source code must retain the above copyright
-      notice, this list of conditions and the following disclaimer.
-
-    * Redistributions in binary form must reproduce the above copyright
-      notice, this list of conditions and the following disclaimer in
-      the documentation and/or other materials provided with the
-      distribution.
-
-    * Neither the name of the authors nor the names of their
-      contributors may be used to endorse or promote products derived
-      from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
-IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
-TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNERS
-OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
-PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
-LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/Setup.hs b/Setup.hs
--- a/Setup.hs
+++ b/Setup.hs
@@ -1,3 +1,5 @@
 #!/usr/bin/env runhaskell
+
 import Distribution.Simple
+
 main = defaultMain
diff --git a/hsSqlite3.cabal b/hsSqlite3.cabal
--- a/hsSqlite3.cabal
+++ b/hsSqlite3.cabal
@@ -1,17 +1,45 @@
-name: hsSqlite3
 cabal-version: >= 1.2.3
-version: 0.0.6
-build-type: Simple
-synopsis: Database package using sqlite3.
-author: Evgeny Jukov
-maintainer: Maurício C. Antunes <mauricio.antunes@gmail.com>
-stability: experimental, not usable yet
-homepage: http://bitbucket.org/mauricio/hssqlite3
-license: BSD3
-license-file: LICENSE
-category: database
-library
-  hs-source-dirs: src
-  build-depends: base, bindings-sqlite3, utf8-string
-  exposed-modules:
-    Database.HsSqlite3
+Name: hsSqlite3
+Version: 0.1
+License: LGPL
+Maintainer: Evgeny Jukov <masloed@gmail.com>
+Author: Evgeny Jukov
+Stability: Alpha
+Copyright: Copyright (c) 2007 Evgeny Jukov
+license-file: COPYRIGHT
+Synopsis: Sqlite3 bindings
+description: Bindings for Sqlite3
+Category: Database
+Build-Type: Simple
+Data-Files: src/hs_sqlite3_test.hs
+Data-Files: src/hs_sqlite3_test.sql
+Library
+  Hs-Source-Dirs: src
+  Extensions:
+    RankNTypes
+    FlexibleContexts
+    DeriveDataTypeable
+    GADTs
+    EmptyDataDecls
+    FlexibleInstances
+  Exposed-Modules: 
+    Database.Sqlite3,
+    Database.Sqlite3.Middle
+  Build-Depends:
+    base >=3 && <5,
+    utf8-string >=0.3.5 && <0.3.6,
+    mtl >=1.1 && <1.2,
+    bindings-sqlite3 >=1.0 && <1.1,
+    bytestring >=0.9 && <1.0
+-- Executable hs_sqlite3_test
+--   Main-Is: hs_sqlite3_test.hs
+--   HS-Source-Dirs: src
+--   Extensions:
+--     RankNTypes
+--     FlexibleContexts
+--     DeriveDataTypeable
+--     GADTs
+--     EmptyDataDecls
+--     FlexibleInstances
+--     PatternSignatures
+--     TypeOperators
diff --git a/src/Database/HsSqlite3.hs b/src/Database/HsSqlite3.hs
deleted file mode 100644
--- a/src/Database/HsSqlite3.hs
+++ /dev/null
@@ -1,579 +0,0 @@
-
-module Database.HsSqlite3
- ( module Database.Sqlite3.Low
- , Val ( IntV, Int64V, DoubleV, TextV, BlobV, NullV )
- , fetch
- , bind
- , row
- , test
- , sql
- ) where
-
-import Data.Char
-import Control.Monad
-import Data.Int
-import Database.Sqlite3.Low
-import qualified Data.ByteString as B
-import Control.Arrow
-import Data.Typeable
-
-import Control.Monad.Trans
-import Control.Monad.Error
-import Control.Monad.State.Lazy
-
-import Data.Monoid
-
-import Data.State hiding (fetch)
-
-import qualified Codec.Binary.UTF8.String as UTF8
-
---
-
-class ValID a where
- valID  :: a -> Int
-
-class ValFetch a where
- valFetch :: (Int,Int) -> DbIO a
-
-class ValBind a where
- valBind :: (Int,a) -> DbIO ()
-
-class ValID a => ValCast a b where
- valCast :: a -> b
-
-data Val
- = IntV    Int
- | Int64V  Int64
- | DoubleV Double
- | TextV   String
- | BlobV   B.ByteString
- | NullV
- deriving Show
-
-instance ValID Val where
- valID (IntV    _) = 1
- valID (Int64V  _) = 1
- valID (DoubleV _) = 2
- valID (TextV   _) = 3
- valID (BlobV   _) = 4
- valID  NullV      = 5
-
-instance ValFetch Val where
- valFetch (t,n) = do
-  case t of
-   1 -> liftM IntV    $ column_int n
-   2 -> liftM DoubleV $ column_double n
-   3 -> liftM TextV   $ column_text n
-   4 -> liftM BlobV   $ column_blob n
-   5 -> return NullV
-
-instance ValBind Val where
- valBind (t,v) = do
-  case v of
-   IntV a -> bind_int (t,a)
-   TextV a -> bind_text (t,a)
-
-instance ValCast Val Int where
- valCast (IntV a) = a
-
-instance ValCast Val Double where
- valCast (DoubleV a) = a
-
-instance ValCast Val String where
- valCast (TextV a) = a
-
-instance ValCast Val B.ByteString where
- valCast (BlobV a) = a
-
-instance ValCast Val () where
- valCast NullV = ()
-
-instance ValID Int          where valID _ = 1
-instance ValID Double       where valID _ = 2
-instance ValID String       where valID _ = 3
-instance ValID B.ByteString where valID _ = 4
-instance ValID ()           where valID _ = 5
-
-reqType :: Int -> (Int -> DbIO a) -> (Int,Int) -> DbIO a
-reqType t' a (t,v) =  do
- errIf (t'/=t) "ValFetch"
- a v
-
-instance ValFetch Int where
- valFetch = reqType 1 column_int
-
-instance ValFetch Double where
- valFetch = reqType 2 column_double
-
-instance ValFetch String where
- valFetch = reqType 3 column_text
-
-instance ValFetch B.ByteString where
- valFetch = reqType 4 column_blob
-
-instance ValFetch () where
- valFetch = reqType 5 (\_ -> return ())
-
-instance ValBind Int where
- valBind = bind_int
-
-instance ValBind String where
- valBind = bind_text
-
-instance ValCast Int Val where
- valCast a = IntV a
-
-instance ValCast Double Val where
- valCast a = DoubleV a
-
-instance ValCast String Val where
- valCast a = TextV a
-
-instance ValCast B.ByteString Val where
- valCast a = BlobV a
-
-instance ValCast () Val where
- valCast a = NullV
-
---
-
-fetch :: ValFetch a => String -> DbIO [[a]]
-fetch sql = do
- liftIO $ putStr $ UTF8.encodeString $ sql++"\n"
- prepare sql
- stat <- step
- case stat of
-  True -> finalize >> return []
-  False -> do
-   cn <- column_count
-   ty <- mapM column_type [0..cn-1]
-   let ft = mapM valFetch (zip ty [0..])
-   x <- ft
-   xs <- fetchRow ft
-   finalize
-   return (x:xs)
- where
-  fetchRow ft = do
-   end <- step
-   case end of
-    True -> return []
-    False -> do
-     x <- ft
-     xs <- fetchRow ft
-     return (x:xs)
-
-sql :: String -> DbIO ()
-sql sql = do
- liftIO $ putStr $ UTF8.encodeString $ sql++"\n"
- prepare sql
- step
- finalize
-
-bind :: String -> [[Val]] -> DbIO ()
-bind sql tab = do
- liftIO $ putStr $ UTF8.encodeString $ sql++"\n"
- debug tab
- prepare sql
- mapM_ (\row -> mapM_ (\(v,n) -> valBind (n,v)) (zip row [1..]) >> step >> reset) tab
- finalize
-
-fetchOne' :: ValFetch a => String -> Int -> DbIO [[a]]
-fetchOne' sql num = fetch sql'
- where sql' = concat [sql," LIMIT 1 OFFSET ", show num]
-
-row :: ValFetch a => String -> Int -> DbIO [a]
-row sql num = liftM head $ fetchOne' sql num
-
-test :: String -> DbIO Bool
-test sql = do
- tab :: [[Val]] <- fetchOne' sql 0
- case length tab of
-  1 -> return True
-  _ -> return False
-
-
-
-Patch from Evgeny:
-
-Utilization of types
-For fetch
-> tab :: [Nil :. Int :. Int :. Double] <- fetch "SELECT * FROM test01"
->  liftIO $ mapM print tab
-
-And for bind
-> bind "INSERT INTO test01 VALUES(?,?,?)" $
->  replicate 7 $
->    Nil :. (1::Int) :. (2::Int) :. (3.0::Double)
-
-This is stack with different types
-> Nil :. (1::Int) :. (2::Int) :. (3.0::Double)
-
-Definition of stack
-> data Stack a where
->    Nil  :: Stack ()
->    (:.) :: Stack a -> b -> Stack (Stack a, b)
-
-This is class for new kinds of values.
-"T" means used in type stack ... type manipulations ...
-> class Cell a where
->   bindT   :: Int -> a -> Db ()
->   columnT :: Int -> Db a
->   idT     :: a -> Int
-
-> instance Cell Int where
->   idT _    = 1
->   columnT  = columnInt
->   bindT    = bindInt
-
-> instance Cell Double where
->  idT _    = 2
->  columnT  = columnDouble
->  bindT    = bindDouble
-
-Equality test of derived types and database types
-> fetchBody derived = do
->  cn <- columnCount
->  dbTypes <- mapM columnType $ enumFromThenTo (cn-1) (cn-2) 0
->  case dbTypes == derived of
-   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
->   False -> fail "different database and haskell types"
->   True  -> return ()
->  x  <- columnStack
->  xs <- fetchTail
->  finalize
->  return (x:xs)
-
-Middle level:
-
-Abstract away from state and errors
-> class DbError e where
->  makeErr :: CInt -> e
->  castErr :: e -> Maybe CInt
-
-> class MonadIO m => MonadDb m where
->  getDb     :: m (Ptr L.Sqlite3)
->  putDb     :: Ptr L.Sqlite3 -> m ()
->  cleanDb   :: m ()
->  isDbReady :: m Bool
->  getSt     :: m (Ptr L.Stmt)
->  putSt     :: Ptr L.Stmt -> m ()
->  cleanSt   :: m ()
->  isStReady :: m Bool
-
-Simple instance for MonadDb (in Sqlite3.hs)
-> data SimpleState = SimpleState
-> { database  :: Maybe (Ptr L.Sqlite3)
-> , statement :: Maybe (Ptr L.Stmt ) }
-> ...
-> instance MonadDb (StateT SimpleState (ErrorT (Either CInt String) IO)) where
-
- > getDb = get >>= maybe (fail "Empty database")  return . database
- > getSt = get >>= maybe (fail "Empty statement") return . statement
-
- > putDb x = modify $ \a -> a { database  = Just x }
- > putSt x = modify $ \a -> a { statement = Just x }
-
- > cleanDb = modify $ \a -> a { database  = Nothing }
- > cleanSt = modify $ \a -> a { statement = Nothing }
-
- > isDbReady = get >>= return . maybe False (const True) . database
- > isStReady = get >>= return . maybe False (const True) . statement
-
-
-
-
-
-
-type Void = Word8
-
-foreign import ccall unsafe "sqlite3_open" c_open
- :: CString -> Ptr (Ptr Void) -> IO Int
-
-foreign import ccall unsafe "sqlite3_close" c_close
- :: Ptr Void -> IO Int
-
-foreign import ccall unsafe "sqlite3_errmsg" c_errmsg
- :: Ptr Void -> IO CString
-
-foreign import ccall unsafe "sqlite3_prepare_v2" c_prepare
- :: Ptr Void -> CString -> Int -> Ptr (Ptr Void) -> Ptr CString -> IO Int
-
-foreign import ccall unsafe "sqlite3_finalize" c_finalize
- :: Ptr Void -> IO Int
-
-foreign import ccall unsafe "sqlite3_reset" c_reset
- :: Ptr Void -> IO Int
-
-foreign import ccall unsafe "sqlite3_bind_int" c_bind_int
- :: Ptr Void -> Int -> Int -> IO Int
-
-foreign import ccall unsafe "sqlite3_bind_text" c_bind_text
- :: Ptr Void -> Int -> CString -> Int -> Int -> IO Int
-
-foreign import ccall unsafe "sqlite3_step" c_step
- :: Ptr Void -> IO Int
-
-foreign import ccall unsafe "sqlite3_column_blob" c_column_blob
- :: Ptr Void -> Int -> IO CString
-
-foreign import ccall unsafe "sqlite3_column_bytes" c_column_bytes
- :: Ptr Void -> Int -> IO Int
-
-foreign import ccall unsafe "sqlite3_column_count" c_column_count
- :: Ptr Void -> IO Int
-
-foreign import ccall unsafe "sqlite3_column_int" c_column_int
- :: Ptr Void -> Int -> IO Int
-
-foreign import ccall unsafe "sqlite3_column_double" c_column_double
- :: Ptr Void -> Int -> IO Double
-
-foreign import ccall unsafe "sqlite3_column_text" c_column_text
- :: Ptr Void -> Int -> IO CString
-
-foreign import ccall unsafe "sqlite3_column_type" c_column_type
- :: Ptr Void -> Int -> IO Int
-
-type DbE a =
- (Error e
- ,MonadError e m
- ,MonadState sg m
- ,LocalState sg StateDb
- ,Monad m
- ) => m a
-
-type DbIO a =
- (LocalState sg StateDb
- ,MonadIO m
- ,MonadState sg m
- ,MonadError e m
- ,Error e
- ,Monad m
- ) => m a
-
-type E a =
- (MonadError e m
- ,Error e
- ) => m a
-
-data StateDb = SD
- { dbP :: Maybe (Ptr Void)
- , stP :: Maybe (Ptr Void)
- } deriving (Show, Typeable)
-
-instance ZeroState StateDb where
- zeroState = SD
-  { dbP = Nothing
-  , stP = Nothing }
-
-setDB :: Ptr Void -> DbE ()
-setDB ptr = get >>= \st@(SD { dbP = dbP }) ->
- case dbP of
-   Nothing -> put (st { dbP = Just ptr })
-   Just _  -> err "Database is allready set"
-
-setST :: Ptr Void -> DbE ()
-setST ptr = get >>= \st@(SD { stP = stP }) ->
-    case stP of
-      Nothing -> put (st { stP = Just ptr })
-      Just _  -> err "Statement is allready set"
-
-isSetDB :: DbE Bool
-isSetDB = get >>= \(SD { dbP = dbP }) ->
-    case dbP of
-      Nothing -> return False
-      Just _ -> return True
-
-getDB :: DbE (Ptr Void)
-getDB = get >>= \(SD { dbP = dbP }) ->
-    case dbP of
-      Just a  -> return a
-      Nothing -> err "Database is not set"
-
-getST :: DbE (Ptr Void)
-getST = get >>= \(SD { stP = stP }) ->
-    case stP of
-      Just a  -> return a
-      Nothing -> err "Statement is not set"
-
-clearDB :: DbE ()
-clearDB = get >>= \st@(SD { dbP = dbP }) ->
-    case dbP of
-      Just _  -> put (st { dbP = Nothing })
-      Nothing -> err "Database is allready clear"
-
-clearST :: DbE ()
-clearST = get >>= \st@(SD { stP = stP }) ->
-    case stP of
-      Just _  -> put (st { stP = Nothing })
-      Nothing -> err "Statement is allready clear"
-
---
-
-err :: String -> E x
-err a = throwError $ strMsg a
-
-
-errRc :: Int -> String -> DbIO ()
-errRc 0 _ = return ()
-errRc rc msg = do
- ans <- isSetDB
- case ans of
-  True -> do
-    ptr <- getDB
-    cstr <- liftIO $ c_errmsg ptr
-    reason <- liftIO $ peekCString cstr
-    err $ "Foreign: "++msg++": (rc="++show rc++") "++reason
-  False ->
-    err $ "Foreign: "++msg++": (rc="++show rc++")"
-
-errIf :: Bool -> String -> DbIO ()
-errIf False _ = return ()
-errIf True msg = do
- ans <- isSetDB
- case ans of
-  True -> do
-    ptr <- getDB
-    cstr <- liftIO $ c_errmsg ptr
-    reason <- liftIO $ peekCString cstr
-    err $ "Foreign: "++msg++": "++reason
-  False ->
-    err $ "Foreign: "++msg
-
---debug a = liftIO $ hPutStr stderr $ "DEBUG: " ++ show a ++ "\n"
-
-debug :: Show a => a -> DbIO ()
-debug a = liftIO $ hPutStr stderr ("DEBUG: " ++ show a ++ "\n")
-
---cont :: ((a -> IO (b,s)) -> IO (b,s)) -> (a -> StateT s IO b) -> StateT s IO b
---cont f g = StateT $ \st -> liftIO $ f $ \a -> (runStateT (g a)) st
-
-fin a b = catchError a (\e -> b >> throwError e)
-
-try a = catchError (liftM Right a) (\e -> return $ Left e)
-
---
-
-open :: String -> DbIO ()
-open path = do
- pptr <- i malloc
- cstr <- i$ newCString path
- debug (path,cstr,pptr,"open")
- rc <- i$ c_open cstr pptr
- ptr <- i$ peek pptr
- setDB ptr
- fin (errRc rc "open") $ do
-   r <- try close
-   case r of
-     Left _   -> clearDB
-     Right () -> return ()
- where i = liftIO
-
-close :: DbIO ()
-close = do
- ptr <- getDB
- debug (ptr,"close")
- rc <- liftIO $ c_close ptr
- errRc rc "close"
- clearDB
-
-prepare :: String -> DbIO ()
-prepare sql = do
- pptr <- i malloc
- (cstr,len) <- i$ newCStringLen sql
- debug (sql,cstr,len,pptr,"prepare")
- ptr <- getDB
- rc <- i$ c_prepare ptr cstr len pptr nullPtr
- sptr <- i$ peek pptr
- setST sptr
- fin (errRc rc "prepare") $ do
-   r <- try finalize
-   case r of
-     Left _ -> clearST
-     Right () -> return ()
- where i = liftIO
-
-finalize :: DbIO ()
-finalize = do
- ptr <- getST
- debug (ptr,"finalize")
- rc <- liftIO $ c_finalize ptr
- errRc rc "finalize"
- clearST
-
-reset :: DbIO ()
-reset = do
- ptr <- getST
- debug (ptr,"reset")
- rc <- liftIO $ c_reset ptr
- errRc rc "reset"
-
-step :: DbIO Bool
-step = do
- ptr <- getST
- debug (ptr,"step")
- rc <- liftIO $ c_step ptr
- errIf (rc /= 100 && rc /= 101) $ "step: "++show rc
- return (rc == 101)
-
-bind_int :: (Int,Int) -> DbIO ()
-bind_int (num,val) = do
- ptr <- getST
- debug (ptr,"bind_int")
- rc <- liftIO $ c_bind_int ptr num val
- errRc rc "bind_int"
-
-bind_text :: (Int,String) -> DbIO ()
-bind_text (num,val) = do
- (cstr,len) <- liftIO $ newCStringLen val
- ptr <- getST
- debug (ptr,"bind_text")
- rc <- liftIO $ c_bind_text ptr num cstr len (-1)
- errRc rc "bind_text"
-
-column_bytes :: Int -> DbIO Int
-column_bytes num = do
- ptr <- getST
- debug (ptr,"column_bytes")
- liftIO $ c_column_bytes ptr num
-
-column_count :: DbIO Int
-column_count = do
- ptr <- getST
- debug (ptr,"column_count")
- liftIO $ c_column_count ptr
-
-column_int :: Int -> DbIO Int
-column_int num = do
- ptr <- getST
- debug (ptr,"column_int")
- liftIO $ c_column_int ptr num
-
-column_double :: Int -> DbIO Double
-column_double num = do
- ptr <- getST
- debug (ptr,"column_double")
- liftIO $ c_column_double ptr num
-
-column_type :: Int -> DbIO Int
-column_type num = do
- ptr <- getST
- debug (ptr,"column_type")
- liftIO $ c_column_type ptr num
-
-column_text :: Int -> DbIO String
-column_text num = do
- ptr <- getST
- by <- column_bytes num
- debug (ptr,by,"column_text")
- tx <- liftIO $ c_column_text ptr num
- utf <- liftIO $ peekCStringLen (tx,by)
- return $ UTF8.decodeString utf
-
-column_blob :: Int -> DbIO B.ByteString
-column_blob num = do
- ptr <- getST
- debug (ptr,"column_blob")
- by <- column_bytes num
- bl <- liftIO $ c_column_blob ptr num
- return $ B.packCStringLen (bl,by)
diff --git a/src/Database/Sqlite3.hs b/src/Database/Sqlite3.hs
new file mode 100644
--- /dev/null
+++ b/src/Database/Sqlite3.hs
@@ -0,0 +1,204 @@
+{-
+  Copyright (C) <2007-2009> <Evgeny Jukov>
+  <If you contribute to Database.Sqlite3, please add your name here.>
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later
+  version.
+-}
+
+module Database.Sqlite3
+ ( sql, bind, fetch, runSimpleDb
+ , Stack(..), Nil, (:.), Cell(..)
+ ) where
+
+import Foreign
+import Foreign.C
+import Data.Char
+import Control.Monad
+import Data.Int
+import Bindings.Sqlite3
+import qualified Data.ByteString as B
+import Control.Arrow
+
+import Control.Monad.Trans
+import Control.Monad.Error
+import Control.Monad.State.Lazy
+
+import Data.Monoid
+
+
+import qualified Codec.Binary.UTF8.String as UTF8
+
+import Database.Sqlite3.Middle
+
+--
+
+fstT :: Stack (a, b) -> a
+fstT _ = error "fstT"
+
+sndT :: Stack (a, b) -> b
+sndT _ = error "sndT"
+
+headT :: [a] -> a
+headT _ = error "headT"
+
+performT :: Monad m => m a -> a
+performT _ = error "performT"
+
+derivT :: (Monad m, TypesStack a)
+      => ([Int] -> m [Stack a]) -> m [Stack a]
+derivT f = fix $ \self -> do
+  f $ typesStack $ headT $ performT self
+
+infixl 9 :.
+
+type Nil = Stack ()
+type a :. b = Stack (a, b)
+
+data Stack a where
+  Nil  :: Stack ()
+  (:.) :: Stack a -> b -> Stack (Stack a, b)
+
+instance (Show a, Show b) => Show (Stack (a, b)) where
+  show (Nil :. a) = show a
+  show (a :. b) = show a ++ "," ++ show b
+
+class Length a where
+  lengthT :: Stack a -> Int
+
+instance Length () where
+  lengthT _ = 0
+
+instance Show (Stack ()) where
+  show _ = []
+
+instance Length a => Length (Stack a, b) where
+  lengthT a = lengthT (fstT a) + 1
+
+class Cell a where
+  bindT   :: Int -> a -> Db ()
+  columnT :: Int -> Db a
+  idT     :: a -> Int
+
+instance TypesStack () where
+  typesStack _ = []
+
+instance (TypesStack a, Cell b) => TypesStack (Stack a, b) where
+  typesStack a = idT (sndT a) : typesStack (fstT a)
+
+class Length a => ColumnStack a where
+  columnStack :: Db (Stack a)
+
+instance ColumnStack () where
+  columnStack = return Nil
+
+instance (ColumnStack a, Cell b) => ColumnStack (Stack a, b) where
+  columnStack = fix $ \self -> do
+    let stack = performT self
+    a <- columnStack
+    b <- columnT $ lengthT stack - 1
+    return (a :. b)
+
+class Length a => BindStack a where
+  bindStack :: Stack a -> Db ()
+
+instance (BindStack a, Cell b) => BindStack (Stack a, b) where
+  bindStack o@(a :. b) = do
+    bindStack a
+    bindT (lengthT o) b
+
+instance BindStack () where
+  bindStack _ = return ()
+
+sql :: String -> Db ()
+sql sql = do
+  prepare sql
+  step
+  finalize
+
+class TypesStack a where
+  typesStack :: Stack a -> [Int]
+
+--
+
+bind :: BindStack a => String -> [Stack a] -> Db ()
+bind sql tab = do
+  prepare sql
+  mapM (\a -> bindStack a >> step >> reset) tab
+  finalize
+
+fetch sql = do
+  prepare sql
+  a <- step
+  if a
+   then finalize >> return []
+   else derivT fetchBody
+
+fetchTail :: ColumnStack a => Db [Stack a]
+fetchTail = do
+  a <- step
+  if a
+   then return []
+   else do
+    x  <- columnStack
+    xs <- fetchTail
+    return (x:xs)
+
+data SimpleState = SimpleState
+ { database  :: Maybe (Ptr C'sqlite3)
+ , statement :: Maybe (Ptr C'sqlite3_stmt ) }
+
+type SimpleDb a =
+ StateT SimpleState (ErrorT (Either CInt String) IO) a
+
+instance Error (Either CInt String) where
+  strMsg = Right
+
+instance DbError (Either CInt a) where
+  makeErr = Left
+  castErr (Left a) = Just a
+  castErr _ = Nothing
+
+runSimpleDb :: SimpleDb a -> IO a
+runSimpleDb a = do
+  c <- runErrorT tupleM
+  case c of
+    (Left (Left a))  -> fail (show a)
+    (Left (Right a)) -> fail a
+    (Right (a,_))    -> return a
+ where 
+  tupleM = runStateT (errorHook a) $ SimpleState Nothing Nothing
+
+instance MonadDb (StateT SimpleState (ErrorT (Either CInt String) IO)) where
+  getDb = get >>= maybe (fail "Empty database")  return . database
+  getSt = get >>= maybe (fail "Empty statement") return . statement
+  putDb x = modify $ \a -> a { database  = Just x }
+  putSt x = modify $ \a -> a { statement = Just x }
+  cleanDb = modify $ \a -> a { database  = Nothing }
+  cleanSt = modify $ \a -> a { statement = Nothing }
+  isDbReady = get >>= return . maybe False (const True) . database
+  isStReady = get >>= return . maybe False (const True) . statement
+
+fetchBody derived = do
+  cn <- columnCount
+  dbTypes <- mapM columnType $ enumFromThenTo (cn-1) (cn-2) 0
+  case dbTypes == derived of
+   False -> fail "different database and haskell types"
+   True  -> return ()
+  x  <- columnStack
+  xs <- fetchTail
+  finalize
+  return (x:xs)
+
+instance Cell Int where
+  idT _    = 1
+  columnT  = columnInt
+  bindT    = bindInt
+
+instance Cell Double where
+  idT _    = 2
+  columnT  = columnDouble
+  bindT    = bindDouble
diff --git a/src/Database/Sqlite3/Middle.hs b/src/Database/Sqlite3/Middle.hs
new file mode 100644
--- /dev/null
+++ b/src/Database/Sqlite3/Middle.hs
@@ -0,0 +1,154 @@
+module Database.Sqlite3.Middle where
+
+import Bindings.Sqlite3
+import qualified Data.ByteString as B
+
+import Codec.Binary.UTF8.String
+import Control.Monad.Error
+import Foreign.C hiding (newCString)
+import Foreign.Marshal.Alloc
+import Foreign.Marshal.Array
+import Foreign.Ptr
+import Foreign.Storable
+
+type Db a = (DbError e, MonadError e m, MonadDb m) => m a
+
+class DbError e where
+  makeErr :: CInt -> e
+  castErr :: e -> Maybe CInt
+
+class MonadIO m => MonadDb m where
+  getDb     :: m (Ptr C'sqlite3)
+  putDb     :: Ptr C'sqlite3 -> m ()
+  cleanDb   :: m ()
+  isDbReady :: m Bool
+  getSt     :: m (Ptr C'sqlite3_stmt)
+  putSt     :: Ptr C'sqlite3_stmt -> m ()
+  cleanSt   :: m ()
+  isStReady :: m Bool
+
+open :: String -> Db ()
+open path = do
+  cpath <- liftIO $ newCString path
+  db'   <- liftIO $ malloc
+  rc    <- liftIO $ c'sqlite3_open cpath db'
+  db    <- liftIO $ peek db'
+  putDb db
+  liftIO $ free db'
+  err rc
+
+close :: Db ()
+close = do
+  db <- getDb
+  rc  <- liftIO $ c'sqlite3_close db
+  cleanDb
+  err rc
+
+prepare :: String -> Db ()
+prepare sql = do
+  cstr <- liftIO $ newCString sql
+  let len = toEnum $ length sql
+  st'  <- liftIO $ malloc
+  db   <- getDb
+  rc   <- liftIO $ c'sqlite3_prepare db cstr len st' nullPtr
+  st   <- liftIO $ peek st'
+  putSt st
+  liftIO $ free st'
+  err rc
+
+finalize :: Db ()
+finalize = do
+  st <- getSt
+  rc <- liftIO $ c'sqlite3_finalize st
+  cleanSt
+  err rc
+
+reset :: Db ()
+reset = do
+  st <- getSt
+  rc <- liftIO $ c'sqlite3_reset st
+  err rc
+
+step :: Db Bool
+step = do
+  st <- getSt
+  rc <- liftIO $ c'sqlite3_step st
+  case rc of
+    100 -> return False
+    101 -> return True
+    _   -> throwError (makeErr rc)
+
+bindInt :: Int -> Int -> Db ()
+bindInt num val = do
+  st <- getSt
+  rc <- liftIO $ c'sqlite3_bind_int st (toEnum num) (toEnum val)
+  err rc
+
+bindDouble :: Int -> Double -> Db ()
+bindDouble num val = do
+  st <- getSt
+  rc <- liftIO $ c'sqlite3_bind_double st (toEnum num) (realToFrac val)
+  err rc
+
+bindText :: Int -> String -> Db ()
+bindText num val = do
+  cstr <- liftIO $ newCString val
+  let len = toEnum $ length val
+  st   <- getSt
+  rc   <- liftIO $ c'sqlite3_bind_text st (toEnum num) cstr len nullFunPtr
+  err rc
+
+columnBytes :: Int -> Db Int
+columnBytes num = do
+  st <- getSt
+  cint <- liftIO $ c'sqlite3_column_bytes st (toEnum num)
+  return (fromEnum cint)
+
+columnCount :: Db Int
+columnCount = do
+  st <- getSt
+  cint <- liftIO $ c'sqlite3_column_count st
+  return (fromEnum cint)
+
+columnInt :: Int -> Db Int
+columnInt num = do
+  st <- getSt
+  cint <- liftIO $ c'sqlite3_column_int st (toEnum num)
+  return (fromEnum cint)
+
+columnType :: Int -> Db Int
+columnType num = do
+  st <- getSt
+  cint <- liftIO $ c'sqlite3_column_type st (toEnum num)
+  return (fromEnum cint)
+
+columnDouble :: Int -> Db Double
+columnDouble num = do
+  st <- getSt
+  x <- liftIO $ c'sqlite3_column_double st (toEnum num)
+  return (realToFrac x)
+
+columnBlob :: Int -> Db B.ByteString
+columnBlob num = do
+  st <- getSt
+  by <- columnBytes num
+  bl <- liftIO $ c'sqlite3_column_blob st (toEnum num)
+  liftIO $ B.packCStringLen (castPtr bl,by)
+
+errorHook x = catchError x hook where
+ hook e = do
+   ignore finalize
+   ignore close
+   throwError e
+
+ignore x = catchError (x >> return ()) (const $ return ())
+
+newCString :: String -> IO CString
+newCString = newArray0 0 . map fromIntegral . encode
+
+err :: CInt -> Db ()
+err 0 = return ()
+err x = throwError (makeErr x)
+
+
+
diff --git a/src/Examples/hs_sqlite3_test.hs b/src/Examples/hs_sqlite3_test.hs
deleted file mode 100644
--- a/src/Examples/hs_sqlite3_test.hs
+++ /dev/null
@@ -1,27 +0,0 @@
--- Not yet updated, and so should
--- not be built (yet).
-
-import Data.Char
-import Database.Sqlite3 (Val (IntV,TextV))
-import qualified Database.Sqlite3 as S
-import qualified Data.ByteString as B
-
-import Control.Monad.Trans
-import Control.Monad.Error
-import Control.Monad.State.Lazy
-import Data.State
-
-instance LocalState a a where
- getState = id
- putState a _ = a
-
-main = do
-  x <- (`runStateT` (zeroState :: S.StateDb)) $ do
-    S.open "db"
-    tab :: [[Val]] <- S.fetch "SELECT * FROM test_tab"
-    S.bind "INSERT INTO test_tab VALUES (?,?,?)" $
-       replicate 4
-        [IntV 5,TextV "B test",TextV "test C test"]
-    S.close
-    return tab
-  putStr $ "end"++ show x ++"\n"
diff --git a/src/hs_sqlite3_test.hs b/src/hs_sqlite3_test.hs
new file mode 100644
--- /dev/null
+++ b/src/hs_sqlite3_test.hs
@@ -0,0 +1,20 @@
+import Database.Sqlite3
+import Database.Sqlite3.Middle
+import Control.Monad.Trans
+
+main = runSimpleDb $ do
+
+  open "db"
+
+  liftIO $ print "Start"
+
+  tab :: [Nil :. Int :. Int :. Double] <- fetch "SELECT * FROM test01"
+  liftIO $ mapM print tab
+
+  bind "INSERT INTO test01 VALUES(?,?,?)" $
+    replicate 7 $
+      Nil :. (1::Int) :. (2::Int) :. (3.0::Double)
+
+  close
+
+  liftIO $ print "Finish"
diff --git a/src/hs_sqlite3_test.sql b/src/hs_sqlite3_test.sql
new file mode 100644
--- /dev/null
+++ b/src/hs_sqlite3_test.sql
@@ -0,0 +1,9 @@
+CREATE TABLE IF NOT EXISTS test01 (
+ a INT NOT NULL,
+ b INT NOT NULL,
+ c DOUBLE NOT NULL
+);
+
+INSERT INTO test01 VALUES(1,2,3.0);
+INSERT INTO test01 VALUES(2,3,4.0);
+INSERT INTO test01 VALUES(3,4,5.0);
