pysqlite-2.6.3/000755 000765 000024 00000000000 11526730255 014331 5ustar00ghaeringstaff000000 000000 pysqlite-2.6.3/cross_bdist_wininst.py000644 000765 000024 00000033076 11343657406 021010 0ustar00ghaeringstaff000000 000000 # Gerhard Haering is responsible for the hacked version of this # module. # # This is a modified version of the bdist_wininst distutils command to make it # possible to build installers *with extension modules* on Unix. """distutils.command.bdist_wininst Implements the Distutils 'bdist_wininst' command: create a windows installer exe-program.""" # This module should be kept compatible with Python 2.1. __revision__ = "$Id: bdist_wininst.py 59620 2007-12-31 14:47:07Z christian.heimes $" import sys, os, string from distutils.core import Command from distutils.util import get_platform from distutils.dir_util import create_tree, remove_tree from distutils.errors import * from distutils.sysconfig import get_python_version from distutils import log class bdist_wininst (Command): description = "create an executable installer for MS Windows" user_options = [('bdist-dir=', None, "temporary directory for creating the distribution"), ('keep-temp', 'k', "keep the pseudo-installation tree around after " + "creating the distribution archive"), ('target-version=', None, "require a specific python version" + " on the target system"), ('no-target-compile', 'c', "do not compile .py to .pyc on the target system"), ('no-target-optimize', 'o', "do not compile .py to .pyo (optimized)" "on the target system"), ('dist-dir=', 'd', "directory to put final built distributions in"), ('bitmap=', 'b', "bitmap to use for the installer instead of python-powered logo"), ('title=', 't', "title to display on the installer background instead of default"), ('skip-build', None, "skip rebuilding everything (for testing/debugging)"), ('install-script=', None, "basename of installation script to be run after" "installation or before deinstallation"), ('pre-install-script=', None, "Fully qualified filename of a script to be run before " "any files are installed. This script need not be in the " "distribution"), ] boolean_options = ['keep-temp', 'no-target-compile', 'no-target-optimize', 'skip-build'] def initialize_options (self): self.bdist_dir = None self.keep_temp = 0 self.no_target_compile = 0 self.no_target_optimize = 0 self.target_version = None self.dist_dir = None self.bitmap = None self.title = None self.skip_build = 0 self.install_script = None self.pre_install_script = None # initialize_options() def finalize_options (self): if self.bdist_dir is None: bdist_base = self.get_finalized_command('bdist').bdist_base self.bdist_dir = os.path.join(bdist_base, 'wininst') if not self.target_version: self.target_version = "" if not self.skip_build and self.distribution.has_ext_modules(): short_version = get_python_version() if self.target_version and self.target_version != short_version: raise DistutilsOptionError, \ "target version can only be %s, or the '--skip_build'" \ " option must be specified" % (short_version,) self.target_version = short_version self.set_undefined_options('bdist', ('dist_dir', 'dist_dir')) if self.install_script: for script in self.distribution.scripts: if self.install_script == os.path.basename(script): break else: raise DistutilsOptionError, \ "install_script '%s' not found in scripts" % \ self.install_script # finalize_options() def run (self): # HACK I disabled this check. if 0 and (sys.platform != "win32" and (self.distribution.has_ext_modules() or self.distribution.has_c_libraries())): raise DistutilsPlatformError \ ("distribution contains extensions and/or C libraries; " "must be compiled on a Windows 32 platform") if not self.skip_build: self.run_command('build') install = self.reinitialize_command('install', reinit_subcommands=1) install.root = self.bdist_dir install.skip_build = self.skip_build install.warn_dir = 0 install_lib = self.reinitialize_command('install_lib') # we do not want to include pyc or pyo files install_lib.compile = 0 install_lib.optimize = 0 if self.distribution.has_ext_modules(): # If we are building an installer for a Python version other # than the one we are currently running, then we need to ensure # our build_lib reflects the other Python version rather than ours. # Note that for target_version!=sys.version, we must have skipped the # build step, so there is no issue with enforcing the build of this # version. target_version = self.target_version if not target_version: assert self.skip_build, "Should have already checked this" target_version = sys.version[0:3] plat_specifier = ".%s-%s" % (get_platform(), target_version) build = self.get_finalized_command('build') build.build_lib = os.path.join(build.build_base, 'lib' + plat_specifier) # Use a custom scheme for the zip-file, because we have to decide # at installation time which scheme to use. for key in ('purelib', 'platlib', 'headers', 'scripts', 'data'): value = string.upper(key) if key == 'headers': value = value + '/Include/$dist_name' setattr(install, 'install_' + key, value) log.info("installing to %s", self.bdist_dir) install.ensure_finalized() # avoid warning of 'install_lib' about installing # into a directory not in sys.path sys.path.insert(0, os.path.join(self.bdist_dir, 'PURELIB')) install.run() del sys.path[0] # And make an archive relative to the root of the # pseudo-installation tree. from tempfile import mktemp archive_basename = mktemp() fullname = self.distribution.get_fullname() arcname = self.make_archive(archive_basename, "zip", root_dir=self.bdist_dir) # create an exe containing the zip-file self.create_exe(arcname, fullname, self.bitmap) if self.distribution.has_ext_modules(): pyversion = get_python_version() else: pyversion = 'any' self.distribution.dist_files.append(('bdist_wininst', pyversion, self.get_installer_filename(fullname))) # remove the zip-file again log.debug("removing temporary file '%s'", arcname) os.remove(arcname) if not self.keep_temp: remove_tree(self.bdist_dir, dry_run=self.dry_run) # run() def get_inidata (self): # Return data describing the installation. lines = [] metadata = self.distribution.metadata # Write the [metadata] section. lines.append("[metadata]") # 'info' will be displayed in the installer's dialog box, # describing the items to be installed. info = (metadata.long_description or '') + '\n' # Escape newline characters def escape(s): return string.replace(s, "\n", "\\n") for name in ["author", "author_email", "description", "maintainer", "maintainer_email", "name", "url", "version"]: data = getattr(metadata, name, "") if data: info = info + ("\n %s: %s" % \ (string.capitalize(name), escape(data))) lines.append("%s=%s" % (name, escape(data))) # The [setup] section contains entries controlling # the installer runtime. lines.append("\n[Setup]") if self.install_script: lines.append("install_script=%s" % self.install_script) lines.append("info=%s" % escape(info)) lines.append("target_compile=%d" % (not self.no_target_compile)) lines.append("target_optimize=%d" % (not self.no_target_optimize)) if self.target_version: lines.append("target_version=%s" % self.target_version) title = self.title or self.distribution.get_fullname() lines.append("title=%s" % escape(title)) import time import distutils build_info = "Built %s with distutils-%s" % \ (time.ctime(time.time()), distutils.__version__) lines.append("build_info=%s" % build_info) return string.join(lines, "\n") # get_inidata() def create_exe (self, arcname, fullname, bitmap=None): import struct self.mkpath(self.dist_dir) cfgdata = self.get_inidata() installer_name = self.get_installer_filename(fullname) self.announce("creating %s" % installer_name) if bitmap: bitmapdata = open(bitmap, "rb").read() bitmaplen = len(bitmapdata) else: bitmaplen = 0 file = open(installer_name, "wb") file.write(self.get_exe_bytes()) if bitmap: file.write(bitmapdata) # Convert cfgdata from unicode to ascii, mbcs encoded try: unicode except NameError: pass else: if isinstance(cfgdata, unicode): cfgdata = cfgdata.encode("mbcs") # Append the pre-install script cfgdata = cfgdata + "\0" if self.pre_install_script: script_data = open(self.pre_install_script, "r").read() cfgdata = cfgdata + script_data + "\n\0" else: # empty pre-install script cfgdata = cfgdata + "\0" file.write(cfgdata) # The 'magic number' 0x1234567B is used to make sure that the # binary layout of 'cfgdata' is what the wininst.exe binary # expects. If the layout changes, increment that number, make # the corresponding changes to the wininst.exe sources, and # recompile them. header = struct.pack(" # # This file is part of pysqlite. # # This software is provided 'as-is', without any express or implied # warranty. In no event will the authors be held liable for any damages # arising from the use of this software. # # Permission is granted to anyone to use this software for any purpose, # including commercial applications, and to alter it and redistribute it # freely, subject to the following restrictions: # # 1. The origin of this software must not be misrepresented; you must not # claim that you wrote the original software. If you use this software # in a product, an acknowledgment in the product documentation would be # appreciated but is not required. # 2. Altered source versions must be plainly marked as such, and must not be # misrepresented as being the original software. # 3. This notice may not be removed or altered from any source distribution. import glob, os, re, sys import urllib import zipfile from distutils.core import setup, Extension, Command from distutils.command.build import build from distutils.command.build_ext import build_ext import cross_bdist_wininst # If you need to change anything, it should be enough to change setup.cfg. sqlite = "sqlite" PYSQLITE_EXPERIMENTAL = False sources = ["src/module.c", "src/connection.c", "src/cursor.c", "src/cache.c", "src/microprotocols.c", "src/prepare_protocol.c", "src/statement.c", "src/util.c", "src/row.c"] if PYSQLITE_EXPERIMENTAL: sources.append("src/backup.c") include_dirs = [] library_dirs = [] libraries = [] runtime_library_dirs = [] extra_objects = [] define_macros = [] long_description = \ """Python interface to SQLite 3 pysqlite is an interface to the SQLite 3.x embedded relational database engine. It is almost fully compliant with the Python database API version 2.0 also exposes the unique features of SQLite.""" if sys.platform != "win32": define_macros.append(('MODULE_NAME', '"pysqlite2.dbapi2"')) else: define_macros.append(('MODULE_NAME', '\\"pysqlite2.dbapi2\\"')) class DocBuilder(Command): description = "Builds the documentation" user_options = [] def initialize_options(self): pass def finalize_options(self): pass def run(self): import os, shutil try: shutil.rmtree("build/doc") except OSError: pass os.makedirs("build/doc") rc = os.system("sphinx-build doc/sphinx build/doc") if rc != 0: print "Is sphinx installed? If not, try 'sudo easy_install sphinx'." AMALGAMATION_ROOT = "amalgamation" def get_amalgamation(): """Download the SQLite amalgamation if it isn't there, already.""" if os.path.exists(AMALGAMATION_ROOT): return os.mkdir(AMALGAMATION_ROOT) print "Downloading amalgation." # find out what's current amalgamation ZIP file download_page = urllib.urlopen("http://sqlite.org/download.html").read() pattern = re.compile("(sqlite-amalgamation.*?\.zip)") download_file = pattern.findall(download_page)[0] amalgamation_url = "http://sqlite.org/" + download_file # and download it urllib.urlretrieve(amalgamation_url, "tmp.zip") zf = zipfile.ZipFile("tmp.zip") files = ["sqlite3.c", "sqlite3.h"] directory = zf.namelist()[0] for fn in files: print "Extracting", fn outf = open(AMALGAMATION_ROOT + os.sep + fn, "wb") outf.write(zf.read(directory + fn)) outf.close() zf.close() os.unlink("tmp.zip") class AmalgamationBuilder(build): description = "Build a statically built pysqlite using the amalgamtion." def __init__(self, *args, **kwargs): MyBuildExt.amalgamation = True build.__init__(self, *args, **kwargs) class MyBuildExt(build_ext): amalgamation = False def build_extension(self, ext): if self.amalgamation: get_amalgamation() ext.define_macros.append(("SQLITE_ENABLE_FTS3", "1")) # build with fulltext search enabled ext.define_macros.append(("SQLITE_ENABLE_RTREE", "1")) # build with fulltext search enabled ext.sources.append(os.path.join(AMALGAMATION_ROOT, "sqlite3.c")) ext.include_dirs.append(AMALGAMATION_ROOT) build_ext.build_extension(self, ext) def __setattr__(self, k, v): # Make sure we don't link against the SQLite library, no matter what setup.cfg says if self.amalgamation and k == "libraries": v = None self.__dict__[k] = v def get_setup_args(): PYSQLITE_VERSION = None version_re = re.compile('#define PYSQLITE_VERSION "(.*)"') f = open(os.path.join("src", "module.h")) for line in f: match = version_re.match(line) if match: PYSQLITE_VERSION = match.groups()[0] PYSQLITE_MINOR_VERSION = ".".join(PYSQLITE_VERSION.split('.')[:2]) break f.close() if not PYSQLITE_VERSION: print "Fatal error: PYSQLITE_VERSION could not be detected!" sys.exit(1) data_files = [("pysqlite2-doc", glob.glob("doc/*.html") \ + glob.glob("doc/*.txt") \ + glob.glob("doc/*.css")), ("pysqlite2-doc/code", glob.glob("doc/code/*.py"))] py_modules = ["sqlite"] setup_args = dict( name = "pysqlite", version = PYSQLITE_VERSION, description = "DB-API 2.0 interface for SQLite 3.x", long_description=long_description, author = "Gerhard Haering", author_email = "gh@ghaering.de", license = "zlib/libpng license", platforms = "ALL", url = "http://pysqlite.googlecode.com/", download_url = "http://code.google.com/p/pysqlite/downloads/list", # Description of the modules and packages in the distribution package_dir = {"pysqlite2": "lib"}, packages = ["pysqlite2", "pysqlite2.test"] + (["pysqlite2.test.py25"], [])[sys.version_info < (2, 5)], scripts=[], data_files = data_files, ext_modules = [Extension( name="pysqlite2._sqlite", sources=sources, include_dirs=include_dirs, library_dirs=library_dirs, runtime_library_dirs=runtime_library_dirs, libraries=libraries, extra_objects=extra_objects, define_macros=define_macros )], classifiers = [ "Development Status :: 5 - Production/Stable", "Intended Audience :: Developers", "License :: OSI Approved :: zlib/libpng License", "Operating System :: MacOS :: MacOS X", "Operating System :: Microsoft :: Windows", "Operating System :: POSIX", "Programming Language :: C", "Programming Language :: Python", "Topic :: Database :: Database Engines/Servers", "Topic :: Software Development :: Libraries :: Python Modules"], cmdclass = {"build_docs": DocBuilder} ) setup_args["cmdclass"].update({"build_docs": DocBuilder, "build_ext": MyBuildExt, "build_static": AmalgamationBuilder, "cross_bdist_wininst": cross_bdist_wininst.bdist_wininst}) return setup_args def main(): setup(**get_setup_args()) if __name__ == "__main__": main() pysqlite-2.6.3/src/000755 000765 000024 00000000000 11526730255 015120 5ustar00ghaeringstaff000000 000000 pysqlite-2.6.3/src/backup.h000644 000765 000024 00000002535 11461566564 016553 0ustar00ghaeringstaff000000 000000 /* backup.h - definitions for the backup type * * Copyright (C) 2010 Gerhard Häring * * This file is part of pysqlite. * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages * arising from the use of this software. * * Permission is granted to anyone to use this software for any purpose, * including commercial applications, and to alter it and redistribute it * freely, subject to the following restrictions: * * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software * in a product, an acknowledgment in the product documentation would be * appreciated but is not required. * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. */ #ifndef PYSQLITE_BACKUP_H #define PYSQLITE_BACKUP_H #include "Python.h" #include "sqlite3.h" #include "connection.h" typedef struct { PyObject_HEAD sqlite3_backup* backup; pysqlite_Connection* source_con; pysqlite_Connection* dest_con; } pysqlite_Backup; extern PyTypeObject pysqlite_BackupType; int pysqlite_backup_setup_types(void); #endif pysqlite-2.6.3/src/cache.c000644 000765 000024 00000031204 11343754771 016335 0ustar00ghaeringstaff000000 000000 /* cache .c - a LRU cache * * Copyright (C) 2004-2010 Gerhard Häring * * This file is part of pysqlite. * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages * arising from the use of this software. * * Permission is granted to anyone to use this software for any purpose, * including commercial applications, and to alter it and redistribute it * freely, subject to the following restrictions: * * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software * in a product, an acknowledgment in the product documentation would be * appreciated but is not required. * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. */ #include "sqlitecompat.h" #include "cache.h" #include /* only used internally */ pysqlite_Node* pysqlite_new_node(PyObject* key, PyObject* data) { pysqlite_Node* node; node = (pysqlite_Node*) (pysqlite_NodeType.tp_alloc(&pysqlite_NodeType, 0)); if (!node) { return NULL; } Py_INCREF(key); node->key = key; Py_INCREF(data); node->data = data; node->prev = NULL; node->next = NULL; return node; } void pysqlite_node_dealloc(pysqlite_Node* self) { Py_DECREF(self->key); Py_DECREF(self->data); Py_TYPE(self)->tp_free((PyObject*)self); } int pysqlite_cache_init(pysqlite_Cache* self, PyObject* args, PyObject* kwargs) { PyObject* factory; int size = 10; self->factory = NULL; if (!PyArg_ParseTuple(args, "O|i", &factory, &size)) { return -1; } /* minimum cache size is 5 entries */ if (size < 5) { size = 5; } self->size = size; self->first = NULL; self->last = NULL; self->mapping = PyDict_New(); if (!self->mapping) { return -1; } Py_INCREF(factory); self->factory = factory; self->decref_factory = 1; return 0; } void pysqlite_cache_dealloc(pysqlite_Cache* self) { pysqlite_Node* node; pysqlite_Node* delete_node; if (!self->factory) { /* constructor failed, just get out of here */ return; } /* iterate over all nodes and deallocate them */ node = self->first; while (node) { delete_node = node; node = node->next; Py_DECREF(delete_node); } if (self->decref_factory) { Py_DECREF(self->factory); } Py_DECREF(self->mapping); Py_TYPE(self)->tp_free((PyObject*)self); } PyObject* pysqlite_cache_get(pysqlite_Cache* self, PyObject* args) { PyObject* key = args; pysqlite_Node* node; pysqlite_Node* ptr; PyObject* data; node = (pysqlite_Node*)PyDict_GetItem(self->mapping, key); if (node) { /* an entry for this key already exists in the cache */ /* increase usage counter of the node found */ if (node->count < LONG_MAX) { node->count++; } /* if necessary, reorder entries in the cache by swapping positions */ if (node->prev && node->count > node->prev->count) { ptr = node->prev; while (ptr->prev && node->count > ptr->prev->count) { ptr = ptr->prev; } if (node->next) { node->next->prev = node->prev; } else { self->last = node->prev; } if (node->prev) { node->prev->next = node->next; } if (ptr->prev) { ptr->prev->next = node; } else { self->first = node; } node->next = ptr; node->prev = ptr->prev; if (!node->prev) { self->first = node; } ptr->prev = node; } } else { /* There is no entry for this key in the cache, yet. We'll insert a new * entry in the cache, and make space if necessary by throwing the * least used item out of the cache. */ if (PyDict_Size(self->mapping) == self->size) { if (self->last) { node = self->last; if (PyDict_DelItem(self->mapping, self->last->key) != 0) { return NULL; } if (node->prev) { node->prev->next = NULL; } self->last = node->prev; node->prev = NULL; Py_DECREF(node); } } data = PyObject_CallFunction(self->factory, "O", key); if (!data) { return NULL; } node = pysqlite_new_node(key, data); if (!node) { return NULL; } node->prev = self->last; Py_DECREF(data); if (PyDict_SetItem(self->mapping, key, (PyObject*)node) != 0) { Py_DECREF(node); return NULL; } if (self->last) { self->last->next = node; } else { self->first = node; } self->last = node; } Py_INCREF(node->data); return node->data; } PyObject* pysqlite_cache_display(pysqlite_Cache* self, PyObject* args) { pysqlite_Node* ptr; PyObject* prevkey; PyObject* nextkey; PyObject* fmt_args; PyObject* template; PyObject* display_str; ptr = self->first; while (ptr) { if (ptr->prev) { prevkey = ptr->prev->key; } else { prevkey = Py_None; } Py_INCREF(prevkey); if (ptr->next) { nextkey = ptr->next->key; } else { nextkey = Py_None; } Py_INCREF(nextkey); fmt_args = Py_BuildValue("OOO", prevkey, ptr->key, nextkey); if (!fmt_args) { return NULL; } template = PyString_FromString("%s <- %s ->%s\n"); if (!template) { Py_DECREF(fmt_args); return NULL; } display_str = PyString_Format(template, fmt_args); Py_DECREF(template); Py_DECREF(fmt_args); if (!display_str) { return NULL; } PyObject_Print(display_str, stdout, Py_PRINT_RAW); Py_DECREF(display_str); Py_DECREF(prevkey); Py_DECREF(nextkey); ptr = ptr->next; } Py_INCREF(Py_None); return Py_None; } static PyMethodDef cache_methods[] = { {"get", (PyCFunction)pysqlite_cache_get, METH_O, PyDoc_STR("Gets an entry from the cache or calls the factory function to produce one.")}, {"display", (PyCFunction)pysqlite_cache_display, METH_NOARGS, PyDoc_STR("For debugging only.")}, {NULL, NULL} }; PyTypeObject pysqlite_NodeType = { PyVarObject_HEAD_INIT(NULL, 0) MODULE_NAME "Node", /* tp_name */ sizeof(pysqlite_Node), /* tp_basicsize */ 0, /* tp_itemsize */ (destructor)pysqlite_node_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /* tp_flags */ 0, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ 0, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ (initproc)0, /* tp_init */ 0, /* tp_alloc */ 0, /* tp_new */ 0 /* tp_free */ }; PyTypeObject pysqlite_CacheType = { PyVarObject_HEAD_INIT(NULL, 0) MODULE_NAME ".Cache", /* tp_name */ sizeof(pysqlite_Cache), /* tp_basicsize */ 0, /* tp_itemsize */ (destructor)pysqlite_cache_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /* tp_flags */ 0, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ cache_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ (initproc)pysqlite_cache_init, /* tp_init */ 0, /* tp_alloc */ 0, /* tp_new */ 0 /* tp_free */ }; extern int pysqlite_cache_setup_types(void) { int rc; pysqlite_NodeType.tp_new = PyType_GenericNew; pysqlite_CacheType.tp_new = PyType_GenericNew; rc = PyType_Ready(&pysqlite_NodeType); if (rc < 0) { return rc; } rc = PyType_Ready(&pysqlite_CacheType); return rc; } pysqlite-2.6.3/src/cache.h000644 000765 000024 00000004433 11343727263 016342 0ustar00ghaeringstaff000000 000000 /* cache.h - definitions for the LRU cache * * Copyright (C) 2004-2010 Gerhard Häring * * This file is part of pysqlite. * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages * arising from the use of this software. * * Permission is granted to anyone to use this software for any purpose, * including commercial applications, and to alter it and redistribute it * freely, subject to the following restrictions: * * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software * in a product, an acknowledgment in the product documentation would be * appreciated but is not required. * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. */ #ifndef PYSQLITE_CACHE_H #define PYSQLITE_CACHE_H #include "Python.h" /* The LRU cache is implemented as a combination of a doubly-linked with a * dictionary. The list items are of type 'Node' and the dictionary has the * nodes as values. */ typedef struct _pysqlite_Node { PyObject_HEAD PyObject* key; PyObject* data; long count; struct _pysqlite_Node* prev; struct _pysqlite_Node* next; } pysqlite_Node; typedef struct { PyObject_HEAD int size; /* a dictionary mapping keys to Node entries */ PyObject* mapping; /* the factory callable */ PyObject* factory; pysqlite_Node* first; pysqlite_Node* last; /* if set, decrement the factory function when the Cache is deallocated. * this is almost always desirable, but not in the pysqlite context */ int decref_factory; } pysqlite_Cache; extern PyTypeObject pysqlite_NodeType; extern PyTypeObject pysqlite_CacheType; int pysqlite_node_init(pysqlite_Node* self, PyObject* args, PyObject* kwargs); void pysqlite_node_dealloc(pysqlite_Node* self); int pysqlite_cache_init(pysqlite_Cache* self, PyObject* args, PyObject* kwargs); void pysqlite_cache_dealloc(pysqlite_Cache* self); PyObject* pysqlite_cache_get(pysqlite_Cache* self, PyObject* args); int pysqlite_cache_setup_types(void); #endif pysqlite-2.6.3/src/connection.c000644 000765 000024 00000142400 11526453702 017423 0ustar00ghaeringstaff000000 000000 /* connection.c - the connection type * * Copyright (C) 2004-2010 Gerhard Häring * * This file is part of pysqlite. * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages * arising from the use of this software. * * Permission is granted to anyone to use this software for any purpose, * including commercial applications, and to alter it and redistribute it * freely, subject to the following restrictions: * * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software * in a product, an acknowledgment in the product documentation would be * appreciated but is not required. * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. */ #include "cache.h" #include "module.h" #include "connection.h" #include "statement.h" #include "cursor.h" #include "prepare_protocol.h" #include "util.h" #include "sqlitecompat.h" #ifdef PYSQLITE_EXPERIMENTAL #include "backup.h" #endif #include "pythread.h" #define ACTION_FINALIZE 1 #define ACTION_RESET 2 #if SQLITE_VERSION_NUMBER >= 3003008 #ifndef SQLITE_OMIT_LOAD_EXTENSION #define HAVE_LOAD_EXTENSION #endif #endif static int pysqlite_connection_set_isolation_level(pysqlite_Connection* self, PyObject* isolation_level); static void _pysqlite_drop_unused_cursor_references(pysqlite_Connection* self); static void _sqlite3_result_error(sqlite3_context* ctx, const char* errmsg, int len) { /* in older SQLite versions, calling sqlite3_result_error in callbacks * triggers a bug in SQLite that leads either to irritating results or * segfaults, depending on the SQLite version */ #if SQLITE_VERSION_NUMBER >= 3003003 sqlite3_result_error(ctx, errmsg, len); #else PyErr_SetString(pysqlite_OperationalError, errmsg); #endif } int pysqlite_connection_init(pysqlite_Connection* self, PyObject* args, PyObject* kwargs) { static char *kwlist[] = {"database", "timeout", "detect_types", "isolation_level", "check_same_thread", "factory", "cached_statements", NULL, NULL}; PyObject* database; int detect_types = 0; PyObject* isolation_level = NULL; PyObject* factory = NULL; int check_same_thread = 1; int cached_statements = 100; double timeout = 5.0; int rc; PyObject* class_attr = NULL; PyObject* class_attr_str = NULL; int is_apsw_connection = 0; PyObject* database_utf8; if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|diOiOi", kwlist, &database, &timeout, &detect_types, &isolation_level, &check_same_thread, &factory, &cached_statements)) { return -1; } self->initialized = 1; self->begin_statement = NULL; self->statement_cache = NULL; self->statements = NULL; self->cursors = NULL; Py_INCREF(Py_None); self->row_factory = Py_None; Py_INCREF(&PyUnicode_Type); self->text_factory = (PyObject*)&PyUnicode_Type; if (PyString_Check(database) || PyUnicode_Check(database)) { if (PyString_Check(database)) { database_utf8 = database; Py_INCREF(database_utf8); } else { database_utf8 = PyUnicode_AsUTF8String(database); if (!database_utf8) { return -1; } } Py_BEGIN_ALLOW_THREADS rc = sqlite3_open(PyString_AsString(database_utf8), &self->db); Py_END_ALLOW_THREADS Py_DECREF(database_utf8); if (rc != SQLITE_OK) { _pysqlite_seterror(self->db, NULL); return -1; } } else { /* Create a pysqlite connection from a APSW connection */ class_attr = PyObject_GetAttrString(database, "__class__"); if (class_attr) { class_attr_str = PyObject_Str(class_attr); if (class_attr_str) { if (strcmp(PyString_AsString(class_attr_str), "") == 0) { /* In the APSW Connection object, the first entry after * PyObject_HEAD is the sqlite3* we want to get hold of. * Luckily, this is the same layout as we have in our * pysqlite_Connection */ self->db = ((pysqlite_Connection*)database)->db; Py_INCREF(database); self->apsw_connection = database; is_apsw_connection = 1; } } } Py_XDECREF(class_attr_str); Py_XDECREF(class_attr); if (!is_apsw_connection) { PyErr_SetString(PyExc_ValueError, "database parameter must be string or APSW Connection object"); return -1; } } if (!isolation_level) { isolation_level = PyString_FromString(""); if (!isolation_level) { return -1; } } else { Py_INCREF(isolation_level); } self->isolation_level = NULL; pysqlite_connection_set_isolation_level(self, isolation_level); Py_DECREF(isolation_level); self->statement_cache = (pysqlite_Cache*)PyObject_CallFunction((PyObject*)&pysqlite_CacheType, "Oi", self, cached_statements); if (PyErr_Occurred()) { return -1; } self->created_statements = 0; self->created_cursors = 0; /* Create lists of weak references to statements/cursors */ self->statements = PyList_New(0); self->cursors = PyList_New(0); if (!self->statements || !self->cursors) { return -1; } /* By default, the Cache class INCREFs the factory in its initializer, and * decrefs it in its deallocator method. Since this would create a circular * reference here, we're breaking it by decrementing self, and telling the * cache class to not decref the factory (self) in its deallocator. */ self->statement_cache->decref_factory = 0; Py_DECREF(self); self->inTransaction = 0; self->detect_types = detect_types; self->timeout = timeout; (void)sqlite3_busy_timeout(self->db, (int)(timeout*1000)); #ifdef WITH_THREAD self->thread_ident = PyThread_get_thread_ident(); #endif self->check_same_thread = check_same_thread; self->function_pinboard = PyDict_New(); if (!self->function_pinboard) { return -1; } self->collations = PyDict_New(); if (!self->collations) { return -1; } self->Warning = pysqlite_Warning; self->Error = pysqlite_Error; self->InterfaceError = pysqlite_InterfaceError; self->DatabaseError = pysqlite_DatabaseError; self->DataError = pysqlite_DataError; self->OperationalError = pysqlite_OperationalError; self->IntegrityError = pysqlite_IntegrityError; self->InternalError = pysqlite_InternalError; self->ProgrammingError = pysqlite_ProgrammingError; self->NotSupportedError = pysqlite_NotSupportedError; return 0; } /* Empty the entire statement cache of this connection */ void pysqlite_flush_statement_cache(pysqlite_Connection* self) { pysqlite_Node* node; pysqlite_Statement* statement; node = self->statement_cache->first; while (node) { statement = (pysqlite_Statement*)(node->data); (void)pysqlite_statement_finalize(statement); node = node->next; } Py_DECREF(self->statement_cache); self->statement_cache = (pysqlite_Cache*)PyObject_CallFunction((PyObject*)&pysqlite_CacheType, "O", self); Py_DECREF(self); self->statement_cache->decref_factory = 0; } /* action in (ACTION_RESET, ACTION_FINALIZE) */ void pysqlite_do_all_statements(pysqlite_Connection* self, int action, int reset_cursors) { int i; PyObject* weakref; PyObject* statement; pysqlite_Cursor* cursor; for (i = 0; i < PyList_Size(self->statements); i++) { weakref = PyList_GetItem(self->statements, i); statement = PyWeakref_GetObject(weakref); if (statement != Py_None) { if (action == ACTION_RESET) { (void)pysqlite_statement_reset((pysqlite_Statement*)statement); } else { (void)pysqlite_statement_finalize((pysqlite_Statement*)statement); } } } if (reset_cursors) { for (i = 0; i < PyList_Size(self->cursors); i++) { weakref = PyList_GetItem(self->cursors, i); cursor = (pysqlite_Cursor*)PyWeakref_GetObject(weakref); if ((PyObject*)cursor != Py_None) { cursor->reset = 1; } } } } void pysqlite_connection_dealloc(pysqlite_Connection* self) { PyObject* ret = NULL; Py_XDECREF(self->statement_cache); /* Clean up if user has not called .close() explicitly. */ if (self->db) { Py_BEGIN_ALLOW_THREADS sqlite3_close(self->db); Py_END_ALLOW_THREADS } else if (self->apsw_connection) { ret = PyObject_CallMethod(self->apsw_connection, "close", ""); Py_XDECREF(ret); Py_XDECREF(self->apsw_connection); } if (self->begin_statement) { PyMem_Free(self->begin_statement); } Py_XDECREF(self->isolation_level); Py_XDECREF(self->function_pinboard); Py_XDECREF(self->row_factory); Py_XDECREF(self->text_factory); Py_XDECREF(self->collations); Py_XDECREF(self->statements); Py_XDECREF(self->cursors); self->ob_type->tp_free((PyObject*)self); } /* * Registers a cursor with the connection. * * 0 => error; 1 => ok */ int pysqlite_connection_register_cursor(pysqlite_Connection* connection, PyObject* cursor) { PyObject* weakref; weakref = PyWeakref_NewRef((PyObject*)cursor, NULL); if (!weakref) { goto error; } if (PyList_Append(connection->cursors, weakref) != 0) { Py_CLEAR(weakref); goto error; } Py_DECREF(weakref); return 1; error: return 0; } PyObject* pysqlite_connection_cursor(pysqlite_Connection* self, PyObject* args, PyObject* kwargs) { static char *kwlist[] = {"factory", NULL, NULL}; PyObject* factory = NULL; PyObject* cursor; if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O", kwlist, &factory)) { return NULL; } if (!pysqlite_check_thread(self) || !pysqlite_check_connection(self)) { return NULL; } if (factory == NULL) { factory = (PyObject*)&pysqlite_CursorType; } cursor = PyObject_CallFunction(factory, "O", self); _pysqlite_drop_unused_cursor_references(self); if (cursor && self->row_factory != Py_None) { Py_XDECREF(((pysqlite_Cursor*)cursor)->row_factory); Py_INCREF(self->row_factory); ((pysqlite_Cursor*)cursor)->row_factory = self->row_factory; } return cursor; } #ifdef PYSQLITE_EXPERIMENTAL PyObject* pysqlite_connection_backup(pysqlite_Connection* self, PyObject* args, PyObject* kwargs) { static char *kwlist[] = {"dest_db", "source_name", "dest_db_name", NULL, NULL}; char* source_name; char* dest_name; pysqlite_Connection* dest_con; pysqlite_Backup* backup; if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O!ss", kwlist, &pysqlite_ConnectionType, &dest_con, &source_name, &dest_name)) { return NULL; } if (!pysqlite_check_thread(self) || !pysqlite_check_connection(self)) { return NULL; } backup = PyObject_New(pysqlite_Backup, &pysqlite_BackupType); if (!backup) { return NULL; } Py_INCREF(self); backup->source_con = self; Py_INCREF(dest_con); backup->dest_con = dest_con; backup->backup = sqlite3_backup_init(dest_con->db, dest_name, self->db, source_name); return (PyObject*)backup; } #endif PyObject* pysqlite_connection_close(pysqlite_Connection* self, PyObject* args) { PyObject* ret; int rc; if (!pysqlite_check_thread(self)) { return NULL; } pysqlite_do_all_statements(self, ACTION_FINALIZE, 1); if (self->db) { if (self->apsw_connection) { ret = PyObject_CallMethod(self->apsw_connection, "close", ""); Py_XDECREF(ret); Py_XDECREF(self->apsw_connection); self->apsw_connection = NULL; self->db = NULL; } else { Py_BEGIN_ALLOW_THREADS rc = sqlite3_close(self->db); Py_END_ALLOW_THREADS if (rc != SQLITE_OK) { _pysqlite_seterror(self->db, NULL); return NULL; } else { self->db = NULL; } } } Py_INCREF(Py_None); return Py_None; } /* * Checks if a connection object is usable (i. e. not closed). * * 0 => error; 1 => ok */ int pysqlite_check_connection(pysqlite_Connection* con) { if (!con->initialized) { PyErr_SetString(pysqlite_ProgrammingError, "Base Connection.__init__ not called."); return 0; } if (!con->db) { PyErr_SetString(pysqlite_ProgrammingError, "Cannot operate on a closed database."); return 0; } else { return 1; } } PyObject* _pysqlite_connection_begin(pysqlite_Connection* self) { int rc; const char* tail; sqlite3_stmt* statement; Py_BEGIN_ALLOW_THREADS rc = sqlite3_prepare(self->db, self->begin_statement, -1, &statement, &tail); Py_END_ALLOW_THREADS if (rc != SQLITE_OK) { _pysqlite_seterror(self->db, statement); goto error; } rc = pysqlite_step(statement, self); if (rc == SQLITE_DONE) { self->inTransaction = 1; } else { _pysqlite_seterror(self->db, statement); } Py_BEGIN_ALLOW_THREADS rc = sqlite3_finalize(statement); Py_END_ALLOW_THREADS if (rc != SQLITE_OK && !PyErr_Occurred()) { _pysqlite_seterror(self->db, NULL); } error: if (PyErr_Occurred()) { return NULL; } else { Py_INCREF(Py_None); return Py_None; } } PyObject* pysqlite_connection_commit(pysqlite_Connection* self, PyObject* args) { int rc; const char* tail; sqlite3_stmt* statement; if (!pysqlite_check_thread(self) || !pysqlite_check_connection(self)) { return NULL; } if (self->inTransaction) { pysqlite_do_all_statements(self, ACTION_RESET, 0); Py_BEGIN_ALLOW_THREADS rc = sqlite3_prepare(self->db, "COMMIT", -1, &statement, &tail); Py_END_ALLOW_THREADS if (rc != SQLITE_OK) { _pysqlite_seterror(self->db, NULL); goto error; } rc = pysqlite_step(statement, self); if (rc == SQLITE_DONE) { self->inTransaction = 0; } else { _pysqlite_seterror(self->db, statement); } Py_BEGIN_ALLOW_THREADS rc = sqlite3_finalize(statement); Py_END_ALLOW_THREADS if (rc != SQLITE_OK && !PyErr_Occurred()) { _pysqlite_seterror(self->db, NULL); } } error: if (PyErr_Occurred()) { return NULL; } else { Py_INCREF(Py_None); return Py_None; } } PyObject* pysqlite_connection_rollback(pysqlite_Connection* self, PyObject* args) { int rc; const char* tail; sqlite3_stmt* statement; if (!pysqlite_check_thread(self) || !pysqlite_check_connection(self)) { return NULL; } if (self->inTransaction) { pysqlite_do_all_statements(self, ACTION_RESET, 1); Py_BEGIN_ALLOW_THREADS rc = sqlite3_prepare(self->db, "ROLLBACK", -1, &statement, &tail); Py_END_ALLOW_THREADS if (rc != SQLITE_OK) { _pysqlite_seterror(self->db, NULL); goto error; } rc = pysqlite_step(statement, self); if (rc == SQLITE_DONE) { self->inTransaction = 0; } else { _pysqlite_seterror(self->db, statement); } Py_BEGIN_ALLOW_THREADS rc = sqlite3_finalize(statement); Py_END_ALLOW_THREADS if (rc != SQLITE_OK && !PyErr_Occurred()) { _pysqlite_seterror(self->db, NULL); } } error: if (PyErr_Occurred()) { return NULL; } else { Py_INCREF(Py_None); return Py_None; } } void _pysqlite_set_result(sqlite3_context* context, PyObject* py_val) { long longval; const char* buffer; Py_ssize_t buflen; PyObject* stringval; if ((!py_val) || PyErr_Occurred()) { sqlite3_result_null(context); } else if (py_val == Py_None) { sqlite3_result_null(context); } else if (PyInt_Check(py_val)) { longval = PyInt_AsLong(py_val); sqlite3_result_int64(context, (PY_LONG_LONG)longval); } else if (PyFloat_Check(py_val)) { sqlite3_result_double(context, PyFloat_AsDouble(py_val)); } else if (PyBuffer_Check(py_val)) { if (PyObject_AsCharBuffer(py_val, &buffer, &buflen) != 0) { PyErr_SetString(PyExc_ValueError, "could not convert BLOB to buffer"); } else { sqlite3_result_blob(context, buffer, buflen, SQLITE_TRANSIENT); } } else if (PyString_Check(py_val)) { sqlite3_result_text(context, PyString_AsString(py_val), -1, SQLITE_TRANSIENT); } else if (PyUnicode_Check(py_val)) { stringval = PyUnicode_AsUTF8String(py_val); if (stringval) { sqlite3_result_text(context, PyString_AsString(stringval), -1, SQLITE_TRANSIENT); Py_DECREF(stringval); } } else { /* TODO: raise error */ } } PyObject* _pysqlite_build_py_params(sqlite3_context *context, int argc, sqlite3_value** argv) { PyObject* args; int i; sqlite3_value* cur_value; PyObject* cur_py_value; const char* val_str; PY_LONG_LONG val_int; Py_ssize_t buflen; void* raw_buffer; args = PyTuple_New(argc); if (!args) { return NULL; } for (i = 0; i < argc; i++) { cur_value = argv[i]; switch (sqlite3_value_type(argv[i])) { case SQLITE_INTEGER: val_int = sqlite3_value_int64(cur_value); cur_py_value = PyInt_FromLong((long)val_int); break; case SQLITE_FLOAT: cur_py_value = PyFloat_FromDouble(sqlite3_value_double(cur_value)); break; case SQLITE_TEXT: val_str = (const char*)sqlite3_value_text(cur_value); cur_py_value = PyUnicode_DecodeUTF8(val_str, strlen(val_str), NULL); /* TODO: have a way to show errors here */ if (!cur_py_value) { PyErr_Clear(); Py_INCREF(Py_None); cur_py_value = Py_None; } break; case SQLITE_BLOB: buflen = sqlite3_value_bytes(cur_value); cur_py_value = PyBuffer_New(buflen); if (!cur_py_value) { break; } if (PyObject_AsWriteBuffer(cur_py_value, &raw_buffer, &buflen)) { Py_DECREF(cur_py_value); cur_py_value = NULL; break; } memcpy(raw_buffer, sqlite3_value_blob(cur_value), buflen); break; case SQLITE_NULL: default: Py_INCREF(Py_None); cur_py_value = Py_None; } if (!cur_py_value) { Py_DECREF(args); return NULL; } PyTuple_SetItem(args, i, cur_py_value); } return args; } void _pysqlite_func_callback(sqlite3_context* context, int argc, sqlite3_value** argv) { PyObject* args; PyObject* py_func; PyObject* py_retval = NULL; #ifdef WITH_THREAD PyGILState_STATE threadstate; threadstate = PyGILState_Ensure(); #endif py_func = (PyObject*)sqlite3_user_data(context); args = _pysqlite_build_py_params(context, argc, argv); if (args) { py_retval = PyObject_CallObject(py_func, args); Py_DECREF(args); } if (py_retval) { _pysqlite_set_result(context, py_retval); Py_DECREF(py_retval); } else { if (_enable_callback_tracebacks) { PyErr_Print(); } else { PyErr_Clear(); } _sqlite3_result_error(context, "user-defined function raised exception", -1); } #ifdef WITH_THREAD PyGILState_Release(threadstate); #endif } static void _pysqlite_step_callback(sqlite3_context *context, int argc, sqlite3_value** params) { PyObject* args; PyObject* function_result = NULL; PyObject* aggregate_class; PyObject** aggregate_instance; PyObject* stepmethod = NULL; #ifdef WITH_THREAD PyGILState_STATE threadstate; threadstate = PyGILState_Ensure(); #endif aggregate_class = (PyObject*)sqlite3_user_data(context); aggregate_instance = (PyObject**)sqlite3_aggregate_context(context, sizeof(PyObject*)); if (*aggregate_instance == 0) { *aggregate_instance = PyObject_CallFunction(aggregate_class, ""); if (PyErr_Occurred()) { *aggregate_instance = 0; if (_enable_callback_tracebacks) { PyErr_Print(); } else { PyErr_Clear(); } _sqlite3_result_error(context, "user-defined aggregate's '__init__' method raised error", -1); goto error; } } stepmethod = PyObject_GetAttrString(*aggregate_instance, "step"); if (!stepmethod) { goto error; } args = _pysqlite_build_py_params(context, argc, params); if (!args) { goto error; } function_result = PyObject_CallObject(stepmethod, args); Py_DECREF(args); if (!function_result) { if (_enable_callback_tracebacks) { PyErr_Print(); } else { PyErr_Clear(); } _sqlite3_result_error(context, "user-defined aggregate's 'step' method raised error", -1); } error: Py_XDECREF(stepmethod); Py_XDECREF(function_result); #ifdef WITH_THREAD PyGILState_Release(threadstate); #endif } void _pysqlite_final_callback(sqlite3_context* context) { PyObject* function_result = NULL; PyObject** aggregate_instance; PyObject* aggregate_class; #ifdef WITH_THREAD PyGILState_STATE threadstate; threadstate = PyGILState_Ensure(); #endif aggregate_class = (PyObject*)sqlite3_user_data(context); aggregate_instance = (PyObject**)sqlite3_aggregate_context(context, sizeof(PyObject*)); if (!*aggregate_instance) { /* this branch is executed if there was an exception in the aggregate's * __init__ */ goto error; } function_result = PyObject_CallMethod(*aggregate_instance, "finalize", ""); if (!function_result) { if (_enable_callback_tracebacks) { PyErr_Print(); } else { PyErr_Clear(); } _sqlite3_result_error(context, "user-defined aggregate's 'finalize' method raised error", -1); } else { _pysqlite_set_result(context, function_result); } error: Py_XDECREF(*aggregate_instance); Py_XDECREF(function_result); #ifdef WITH_THREAD PyGILState_Release(threadstate); #endif } static void _pysqlite_drop_unused_statement_references(pysqlite_Connection* self) { PyObject* new_list; PyObject* weakref; int i; /* we only need to do this once in a while */ if (self->created_statements++ < 200) { return; } self->created_statements = 0; new_list = PyList_New(0); if (!new_list) { return; } for (i = 0; i < PyList_Size(self->statements); i++) { weakref = PyList_GetItem(self->statements, i); if (PyWeakref_GetObject(weakref) != Py_None) { if (PyList_Append(new_list, weakref) != 0) { Py_DECREF(new_list); return; } } } Py_DECREF(self->statements); self->statements = new_list; } static void _pysqlite_drop_unused_cursor_references(pysqlite_Connection* self) { PyObject* new_list; PyObject* weakref; int i; /* we only need to do this once in a while */ if (self->created_cursors++ < 200) { return; } self->created_cursors = 0; new_list = PyList_New(0); if (!new_list) { return; } for (i = 0; i < PyList_Size(self->cursors); i++) { weakref = PyList_GetItem(self->cursors, i); if (PyWeakref_GetObject(weakref) != Py_None) { if (PyList_Append(new_list, weakref) != 0) { Py_DECREF(new_list); return; } } } Py_DECREF(self->cursors); self->cursors = new_list; } PyObject* pysqlite_connection_create_function(pysqlite_Connection* self, PyObject* args, PyObject* kwargs) { static char *kwlist[] = {"name", "narg", "func", NULL, NULL}; PyObject* func; char* name; int narg; int rc; if (!pysqlite_check_thread(self) || !pysqlite_check_connection(self)) { return NULL; } if (!PyArg_ParseTupleAndKeywords(args, kwargs, "siO", kwlist, &name, &narg, &func)) { return NULL; } rc = sqlite3_create_function(self->db, name, narg, SQLITE_UTF8, (void*)func, _pysqlite_func_callback, NULL, NULL); if (rc != SQLITE_OK) { /* Workaround for SQLite bug: no error code or string is available here */ PyErr_SetString(pysqlite_OperationalError, "Error creating function"); return NULL; } else { if (PyDict_SetItem(self->function_pinboard, func, Py_None) == -1) return NULL; Py_INCREF(Py_None); return Py_None; } } PyObject* pysqlite_connection_create_aggregate(pysqlite_Connection* self, PyObject* args, PyObject* kwargs) { PyObject* aggregate_class; int n_arg; char* name; static char *kwlist[] = { "name", "n_arg", "aggregate_class", NULL }; int rc; if (!pysqlite_check_thread(self) || !pysqlite_check_connection(self)) { return NULL; } if (!PyArg_ParseTupleAndKeywords(args, kwargs, "siO:create_aggregate", kwlist, &name, &n_arg, &aggregate_class)) { return NULL; } rc = sqlite3_create_function(self->db, name, n_arg, SQLITE_UTF8, (void*)aggregate_class, 0, &_pysqlite_step_callback, &_pysqlite_final_callback); if (rc != SQLITE_OK) { /* Workaround for SQLite bug: no error code or string is available here */ PyErr_SetString(pysqlite_OperationalError, "Error creating aggregate"); return NULL; } else { if (PyDict_SetItem(self->function_pinboard, aggregate_class, Py_None) == -1) return NULL; Py_INCREF(Py_None); return Py_None; } } static int _authorizer_callback(void* user_arg, int action, const char* arg1, const char* arg2 , const char* dbname, const char* access_attempt_source) { PyObject *ret; int rc; #ifdef WITH_THREAD PyGILState_STATE gilstate; gilstate = PyGILState_Ensure(); #endif ret = PyObject_CallFunction((PyObject*)user_arg, "issss", action, arg1, arg2, dbname, access_attempt_source); if (!ret) { if (_enable_callback_tracebacks) { PyErr_Print(); } else { PyErr_Clear(); } rc = SQLITE_DENY; } else { if (PyInt_Check(ret)) { rc = (int)PyInt_AsLong(ret); } else { rc = SQLITE_DENY; } Py_DECREF(ret); } #ifdef WITH_THREAD PyGILState_Release(gilstate); #endif return rc; } static int _progress_handler(void* user_arg) { int rc; PyObject *ret; #ifdef WITH_THREAD PyGILState_STATE gilstate; gilstate = PyGILState_Ensure(); #endif ret = PyObject_CallFunction((PyObject*)user_arg, ""); if (!ret) { if (_enable_callback_tracebacks) { PyErr_Print(); } else { PyErr_Clear(); } /* abort query if error occurred */ rc = 1; } else { rc = (int)PyObject_IsTrue(ret); Py_DECREF(ret); } #ifdef WITH_THREAD PyGILState_Release(gilstate); #endif return rc; } static PyObject* pysqlite_connection_set_authorizer(pysqlite_Connection* self, PyObject* args, PyObject* kwargs) { PyObject* authorizer_cb; static char *kwlist[] = { "authorizer_callback", NULL }; int rc; if (!pysqlite_check_thread(self) || !pysqlite_check_connection(self)) { return NULL; } if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O:set_authorizer", kwlist, &authorizer_cb)) { return NULL; } rc = sqlite3_set_authorizer(self->db, _authorizer_callback, (void*)authorizer_cb); if (rc != SQLITE_OK) { PyErr_SetString(pysqlite_OperationalError, "Error setting authorizer callback"); return NULL; } else { if (PyDict_SetItem(self->function_pinboard, authorizer_cb, Py_None) == -1) return NULL; Py_INCREF(Py_None); return Py_None; } } static PyObject* pysqlite_connection_set_progress_handler(pysqlite_Connection* self, PyObject* args, PyObject* kwargs) { PyObject* progress_handler; int n; static char *kwlist[] = { "progress_handler", "n", NULL }; if (!pysqlite_check_thread(self) || !pysqlite_check_connection(self)) { return NULL; } if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi:set_progress_handler", kwlist, &progress_handler, &n)) { return NULL; } if (progress_handler == Py_None) { /* None clears the progress handler previously set */ sqlite3_progress_handler(self->db, 0, 0, (void*)0); } else { sqlite3_progress_handler(self->db, n, _progress_handler, progress_handler); if (PyDict_SetItem(self->function_pinboard, progress_handler, Py_None) == -1) return NULL; } Py_INCREF(Py_None); return Py_None; } #ifdef HAVE_LOAD_EXTENSION static PyObject* pysqlite_enable_load_extension(pysqlite_Connection* self, PyObject* args) { int rc; int onoff; if (!pysqlite_check_thread(self) || !pysqlite_check_connection(self)) { return NULL; } if (!PyArg_ParseTuple(args, "i", &onoff)) { return NULL; } rc = sqlite3_enable_load_extension(self->db, onoff); if (rc != SQLITE_OK) { PyErr_SetString(pysqlite_OperationalError, "Error enabling load extension"); return NULL; } else { Py_INCREF(Py_None); return Py_None; } } static PyObject* pysqlite_load_extension(pysqlite_Connection* self, PyObject* args) { int rc; char* extension_name; char* errmsg; if (!pysqlite_check_thread(self) || !pysqlite_check_connection(self)) { return NULL; } if (!PyArg_ParseTuple(args, "s", &extension_name)) { return NULL; } rc = sqlite3_load_extension(self->db, extension_name, 0, &errmsg); if (rc != 0) { PyErr_SetString(pysqlite_OperationalError, errmsg); return NULL; } else { Py_INCREF(Py_None); return Py_None; } } #endif int pysqlite_check_thread(pysqlite_Connection* self) { #ifdef WITH_THREAD if (self->check_same_thread) { if (PyThread_get_thread_ident() != self->thread_ident) { PyErr_Format(pysqlite_ProgrammingError, "SQLite objects created in a thread can only be used in that same thread." "The object was created in thread id %ld and this is thread id %ld", self->thread_ident, PyThread_get_thread_ident()); return 0; } } #endif return 1; } static PyObject* pysqlite_connection_get_isolation_level(pysqlite_Connection* self, void* unused) { Py_INCREF(self->isolation_level); return self->isolation_level; } static PyObject* pysqlite_connection_get_total_changes(pysqlite_Connection* self, void* unused) { if (!pysqlite_check_connection(self)) { return NULL; } else { return Py_BuildValue("i", sqlite3_total_changes(self->db)); } } static int pysqlite_connection_set_isolation_level(pysqlite_Connection* self, PyObject* isolation_level) { PyObject* res; PyObject* begin_statement; char* begin_statement_str; Py_XDECREF(self->isolation_level); if (self->begin_statement) { PyMem_Free(self->begin_statement); self->begin_statement = NULL; } if (isolation_level == Py_None) { Py_INCREF(Py_None); self->isolation_level = Py_None; res = pysqlite_connection_commit(self, NULL); if (!res) { return -1; } Py_DECREF(res); self->inTransaction = 0; } else { Py_INCREF(isolation_level); self->isolation_level = isolation_level; begin_statement = PyString_FromString("BEGIN "); if (!begin_statement) { return -1; } PyString_Concat(&begin_statement, isolation_level); if (!begin_statement) { return -1; } begin_statement_str = PyString_AsString(begin_statement); if (!begin_statement_str) { Py_DECREF(begin_statement); return -1; } self->begin_statement = PyMem_Malloc(strlen(begin_statement_str) + 2); if (!self->begin_statement) { Py_DECREF(begin_statement); return -1; } strcpy(self->begin_statement, begin_statement_str); Py_DECREF(begin_statement); } return 0; } PyObject* pysqlite_connection_call(pysqlite_Connection* self, PyObject* args, PyObject* kwargs) { PyObject* sql; pysqlite_Statement* statement; PyObject* weakref; int rc; if (!pysqlite_check_thread(self) || !pysqlite_check_connection(self)) { return NULL; } if (!PyArg_ParseTuple(args, "O", &sql)) { return NULL; } _pysqlite_drop_unused_statement_references(self); statement = PyObject_New(pysqlite_Statement, &pysqlite_StatementType); if (!statement) { return NULL; } rc = pysqlite_statement_create(statement, self, sql); if (rc != SQLITE_OK) { if (rc == PYSQLITE_TOO_MUCH_SQL) { PyErr_SetString(pysqlite_ProgrammingError, "You can only execute one statement at a time."); } else if (rc == PYSQLITE_SQL_WRONG_TYPE) { PyErr_SetString(pysqlite_ProgrammingError, "SQL is of wrong type. Must be string or unicode."); } else { (void)pysqlite_statement_reset(statement); _pysqlite_seterror(self->db, NULL); } Py_CLEAR(statement); } else { weakref = PyWeakref_NewRef((PyObject*)statement, NULL); if (!weakref) { Py_CLEAR(statement); goto error; } if (PyList_Append(self->statements, weakref) != 0) { Py_CLEAR(weakref); goto error; } Py_DECREF(weakref); } error: return (PyObject*)statement; } PyObject* pysqlite_connection_execute(pysqlite_Connection* self, PyObject* args, PyObject* kwargs) { PyObject* cursor = 0; PyObject* result = 0; PyObject* method = 0; cursor = PyObject_CallMethod((PyObject*)self, "cursor", ""); if (!cursor) { goto error; } method = PyObject_GetAttrString(cursor, "execute"); if (!method) { Py_CLEAR(cursor); goto error; } result = PyObject_CallObject(method, args); if (!result) { Py_CLEAR(cursor); } error: Py_XDECREF(result); Py_XDECREF(method); return cursor; } PyObject* pysqlite_connection_executemany(pysqlite_Connection* self, PyObject* args, PyObject* kwargs) { PyObject* cursor = 0; PyObject* result = 0; PyObject* method = 0; cursor = PyObject_CallMethod((PyObject*)self, "cursor", ""); if (!cursor) { goto error; } method = PyObject_GetAttrString(cursor, "executemany"); if (!method) { Py_CLEAR(cursor); goto error; } result = PyObject_CallObject(method, args); if (!result) { Py_CLEAR(cursor); } error: Py_XDECREF(result); Py_XDECREF(method); return cursor; } PyObject* pysqlite_connection_executescript(pysqlite_Connection* self, PyObject* args, PyObject* kwargs) { PyObject* cursor = 0; PyObject* result = 0; PyObject* method = 0; cursor = PyObject_CallMethod((PyObject*)self, "cursor", ""); if (!cursor) { goto error; } method = PyObject_GetAttrString(cursor, "executescript"); if (!method) { Py_CLEAR(cursor); goto error; } result = PyObject_CallObject(method, args); if (!result) { Py_CLEAR(cursor); } error: Py_XDECREF(result); Py_XDECREF(method); return cursor; } /* ------------------------- COLLATION CODE ------------------------ */ static int pysqlite_collation_callback( void* context, int text1_length, const void* text1_data, int text2_length, const void* text2_data) { PyObject* callback = (PyObject*)context; PyObject* string1 = 0; PyObject* string2 = 0; #ifdef WITH_THREAD PyGILState_STATE gilstate; #endif PyObject* retval = NULL; int result = 0; #ifdef WITH_THREAD gilstate = PyGILState_Ensure(); #endif if (PyErr_Occurred()) { goto finally; } string1 = PyString_FromStringAndSize((const char*)text1_data, text1_length); string2 = PyString_FromStringAndSize((const char*)text2_data, text2_length); if (!string1 || !string2) { goto finally; /* failed to allocate strings */ } retval = PyObject_CallFunctionObjArgs(callback, string1, string2, NULL); if (!retval) { /* execution failed */ goto finally; } result = PyInt_AsLong(retval); if (PyErr_Occurred()) { result = 0; } finally: Py_XDECREF(string1); Py_XDECREF(string2); Py_XDECREF(retval); #ifdef WITH_THREAD PyGILState_Release(gilstate); #endif return result; } static PyObject * pysqlite_connection_interrupt(pysqlite_Connection* self, PyObject* args) { PyObject* retval = NULL; if (!pysqlite_check_connection(self)) { goto finally; } sqlite3_interrupt(self->db); Py_INCREF(Py_None); retval = Py_None; finally: return retval; } /* Function author: Paul Kippes * Class method of Connection to call the Python function _iterdump * of the sqlite3 module. */ static PyObject * pysqlite_connection_iterdump(pysqlite_Connection* self, PyObject* args) { PyObject* retval = NULL; PyObject* module = NULL; PyObject* module_dict; PyObject* pyfn_iterdump; if (!pysqlite_check_connection(self)) { goto finally; } module = PyImport_ImportModule("pysqlite2.dump"); if (!module) { goto finally; } module_dict = PyModule_GetDict(module); if (!module_dict) { goto finally; } pyfn_iterdump = PyDict_GetItemString(module_dict, "_iterdump"); if (!pyfn_iterdump) { PyErr_SetString(pysqlite_OperationalError, "Failed to obtain _iterdump() reference"); goto finally; } args = PyTuple_New(1); if (!args) { goto finally; } Py_INCREF(self); PyTuple_SetItem(args, 0, (PyObject*)self); retval = PyObject_CallObject(pyfn_iterdump, args); finally: Py_XDECREF(args); Py_XDECREF(module); return retval; } static PyObject * pysqlite_connection_create_collation(pysqlite_Connection* self, PyObject* args) { PyObject* callable; PyObject* uppercase_name = 0; PyObject* name; PyObject* retval; char* chk; int rc; if (!pysqlite_check_thread(self) || !pysqlite_check_connection(self)) { goto finally; } if (!PyArg_ParseTuple(args, "O!O:create_collation(name, callback)", &PyString_Type, &name, &callable)) { goto finally; } uppercase_name = PyObject_CallMethod(name, "upper", ""); if (!uppercase_name) { goto finally; } chk = PyString_AsString(uppercase_name); while (*chk) { if ((*chk >= '0' && *chk <= '9') || (*chk >= 'A' && *chk <= 'Z') || (*chk == '_')) { chk++; } else { PyErr_SetString(pysqlite_ProgrammingError, "invalid character in collation name"); goto finally; } } if (callable != Py_None && !PyCallable_Check(callable)) { PyErr_SetString(PyExc_TypeError, "parameter must be callable"); goto finally; } if (callable != Py_None) { if (PyDict_SetItem(self->collations, uppercase_name, callable) == -1) goto finally; } else { if (PyDict_DelItem(self->collations, uppercase_name) == -1) goto finally; } rc = sqlite3_create_collation(self->db, PyString_AsString(uppercase_name), SQLITE_UTF8, (callable != Py_None) ? callable : NULL, (callable != Py_None) ? pysqlite_collation_callback : NULL); if (rc != SQLITE_OK) { PyDict_DelItem(self->collations, uppercase_name); _pysqlite_seterror(self->db, NULL); goto finally; } finally: Py_XDECREF(uppercase_name); if (PyErr_Occurred()) { retval = NULL; } else { Py_INCREF(Py_None); retval = Py_None; } return retval; } /* Called when the connection is used as a context manager. Returns itself as a * convenience to the caller. */ static PyObject * pysqlite_connection_enter(pysqlite_Connection* self, PyObject* args) { Py_INCREF(self); return (PyObject*)self; } /** Called when the connection is used as a context manager. If there was any * exception, a rollback takes place; otherwise we commit. */ static PyObject * pysqlite_connection_exit(pysqlite_Connection* self, PyObject* args) { PyObject* exc_type, *exc_value, *exc_tb; char* method_name; PyObject* result; if (!PyArg_ParseTuple(args, "OOO", &exc_type, &exc_value, &exc_tb)) { return NULL; } if (exc_type == Py_None && exc_value == Py_None && exc_tb == Py_None) { method_name = "commit"; } else { method_name = "rollback"; } result = PyObject_CallMethod((PyObject*)self, method_name, ""); if (!result) { return NULL; } Py_DECREF(result); Py_INCREF(Py_False); return Py_False; } static char connection_doc[] = PyDoc_STR("SQLite database connection object."); static PyGetSetDef connection_getset[] = { {"isolation_level", (getter)pysqlite_connection_get_isolation_level, (setter)pysqlite_connection_set_isolation_level}, {"total_changes", (getter)pysqlite_connection_get_total_changes, (setter)0}, {NULL} }; static PyMethodDef connection_methods[] = { #ifdef PYSQLITE_EXPERIMENTAL {"backup", (PyCFunction)pysqlite_connection_backup, METH_VARARGS|METH_KEYWORDS, PyDoc_STR("Backup database.")}, #endif {"cursor", (PyCFunction)pysqlite_connection_cursor, METH_VARARGS|METH_KEYWORDS, PyDoc_STR("Return a cursor for the connection.")}, {"close", (PyCFunction)pysqlite_connection_close, METH_NOARGS, PyDoc_STR("Closes the connection.")}, {"commit", (PyCFunction)pysqlite_connection_commit, METH_NOARGS, PyDoc_STR("Commit the current transaction.")}, {"rollback", (PyCFunction)pysqlite_connection_rollback, METH_NOARGS, PyDoc_STR("Roll back the current transaction.")}, {"create_function", (PyCFunction)pysqlite_connection_create_function, METH_VARARGS|METH_KEYWORDS, PyDoc_STR("Creates a new function. Non-standard.")}, {"create_aggregate", (PyCFunction)pysqlite_connection_create_aggregate, METH_VARARGS|METH_KEYWORDS, PyDoc_STR("Creates a new aggregate. Non-standard.")}, {"set_authorizer", (PyCFunction)pysqlite_connection_set_authorizer, METH_VARARGS|METH_KEYWORDS, PyDoc_STR("Sets authorizer callback. Non-standard.")}, #ifdef HAVE_LOAD_EXTENSION {"enable_load_extension", (PyCFunction)pysqlite_enable_load_extension, METH_VARARGS, PyDoc_STR("Enable dynamic loading of SQLite extension modules. Non-standard.")}, {"load_extension", (PyCFunction)pysqlite_load_extension, METH_VARARGS, PyDoc_STR("Load SQLite extension module. Non-standard.")}, #endif {"set_progress_handler", (PyCFunction)pysqlite_connection_set_progress_handler, METH_VARARGS|METH_KEYWORDS, PyDoc_STR("Sets progress handler callback. Non-standard.")}, {"execute", (PyCFunction)pysqlite_connection_execute, METH_VARARGS, PyDoc_STR("Executes a SQL statement. Non-standard.")}, {"executemany", (PyCFunction)pysqlite_connection_executemany, METH_VARARGS, PyDoc_STR("Repeatedly executes a SQL statement. Non-standard.")}, {"executescript", (PyCFunction)pysqlite_connection_executescript, METH_VARARGS, PyDoc_STR("Executes a multiple SQL statements at once. Non-standard.")}, {"create_collation", (PyCFunction)pysqlite_connection_create_collation, METH_VARARGS, PyDoc_STR("Creates a collation function. Non-standard.")}, {"interrupt", (PyCFunction)pysqlite_connection_interrupt, METH_NOARGS, PyDoc_STR("Abort any pending database operation. Non-standard.")}, {"iterdump", (PyCFunction)pysqlite_connection_iterdump, METH_NOARGS, PyDoc_STR("Returns iterator to the dump of the database in an SQL text format. Non-standard.")}, {"__enter__", (PyCFunction)pysqlite_connection_enter, METH_NOARGS, PyDoc_STR("For context manager. Non-standard.")}, {"__exit__", (PyCFunction)pysqlite_connection_exit, METH_VARARGS, PyDoc_STR("For context manager. Non-standard.")}, {NULL, NULL} }; static struct PyMemberDef connection_members[] = { {"Warning", T_OBJECT, offsetof(pysqlite_Connection, Warning), RO}, {"Error", T_OBJECT, offsetof(pysqlite_Connection, Error), RO}, {"InterfaceError", T_OBJECT, offsetof(pysqlite_Connection, InterfaceError), RO}, {"DatabaseError", T_OBJECT, offsetof(pysqlite_Connection, DatabaseError), RO}, {"DataError", T_OBJECT, offsetof(pysqlite_Connection, DataError), RO}, {"OperationalError", T_OBJECT, offsetof(pysqlite_Connection, OperationalError), RO}, {"IntegrityError", T_OBJECT, offsetof(pysqlite_Connection, IntegrityError), RO}, {"InternalError", T_OBJECT, offsetof(pysqlite_Connection, InternalError), RO}, {"ProgrammingError", T_OBJECT, offsetof(pysqlite_Connection, ProgrammingError), RO}, {"NotSupportedError", T_OBJECT, offsetof(pysqlite_Connection, NotSupportedError), RO}, {"row_factory", T_OBJECT, offsetof(pysqlite_Connection, row_factory)}, {"text_factory", T_OBJECT, offsetof(pysqlite_Connection, text_factory)}, {NULL} }; PyTypeObject pysqlite_ConnectionType = { PyVarObject_HEAD_INIT(NULL, 0) MODULE_NAME ".Connection", /* tp_name */ sizeof(pysqlite_Connection), /* tp_basicsize */ 0, /* tp_itemsize */ (destructor)pysqlite_connection_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ (ternaryfunc)pysqlite_connection_call, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /* tp_flags */ connection_doc, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ connection_methods, /* tp_methods */ connection_members, /* tp_members */ connection_getset, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ (initproc)pysqlite_connection_init, /* tp_init */ 0, /* tp_alloc */ 0, /* tp_new */ 0 /* tp_free */ }; extern int pysqlite_connection_setup_types(void) { pysqlite_ConnectionType.tp_new = PyType_GenericNew; return PyType_Ready(&pysqlite_ConnectionType); } pysqlite-2.6.3/src/connection.h000644 000765 000024 00000012023 11343727267 017434 0ustar00ghaeringstaff000000 000000 /* connection.h - definitions for the connection type * * Copyright (C) 2004-2010 Gerhard Häring * * This file is part of pysqlite. * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages * arising from the use of this software. * * Permission is granted to anyone to use this software for any purpose, * including commercial applications, and to alter it and redistribute it * freely, subject to the following restrictions: * * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software * in a product, an acknowledgment in the product documentation would be * appreciated but is not required. * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. */ #ifndef PYSQLITE_CONNECTION_H #define PYSQLITE_CONNECTION_H #include "Python.h" #include "pythread.h" #include "structmember.h" #include "cache.h" #include "module.h" #include "sqlite3.h" typedef struct { PyObject_HEAD sqlite3* db; /* 1 if we are currently within a transaction, i. e. if a BEGIN has been * issued */ int inTransaction; /* the type detection mode. Only 0, PARSE_DECLTYPES, PARSE_COLNAMES or a * bitwise combination thereof makes sense */ int detect_types; /* the timeout value in seconds for database locks */ double timeout; /* for internal use in the timeout handler: when did the timeout handler * first get called with count=0? */ double timeout_started; /* None for autocommit, otherwise a PyString with the isolation level */ PyObject* isolation_level; /* NULL for autocommit, otherwise a string with the BEGIN statment; will be * freed in connection destructor */ char* begin_statement; /* 1 if a check should be performed for each API call if the connection is * used from the same thread it was created in */ int check_same_thread; int initialized; /* thread identification of the thread the connection was created in */ long thread_ident; pysqlite_Cache* statement_cache; /* Lists of weak references to statements and cursors used within this connection */ PyObject* statements; PyObject* cursors; /* Counters for how many statements/cursors were created in the connection. May be * reset to 0 at certain intervals */ int created_statements; int created_cursors; PyObject* row_factory; /* Determines how bytestrings from SQLite are converted to Python objects: * - PyUnicode_Type: Python Unicode objects are constructed from UTF-8 bytestrings * - OptimizedUnicode: Like before, but for ASCII data, only PyStrings are created. * - PyString_Type: PyStrings are created as-is. * - Any custom callable: Any object returned from the callable called with the bytestring * as single parameter. */ PyObject* text_factory; /* remember references to functions/classes used in * create_function/create/aggregate, use these as dictionary keys, so we * can keep the total system refcount constant by clearing that dictionary * in connection_dealloc */ PyObject* function_pinboard; /* a dictionary of registered collation name => collation callable mappings */ PyObject* collations; /* if our connection was created from a APSW connection, we keep a * reference to the APSW connection around and get rid of it in our * destructor */ PyObject* apsw_connection; /* Exception objects */ PyObject* Warning; PyObject* Error; PyObject* InterfaceError; PyObject* DatabaseError; PyObject* DataError; PyObject* OperationalError; PyObject* IntegrityError; PyObject* InternalError; PyObject* ProgrammingError; PyObject* NotSupportedError; } pysqlite_Connection; extern PyTypeObject pysqlite_ConnectionType; PyObject* pysqlite_connection_alloc(PyTypeObject* type, int aware); void pysqlite_connection_dealloc(pysqlite_Connection* self); PyObject* pysqlite_connection_cursor(pysqlite_Connection* self, PyObject* args, PyObject* kwargs); PyObject* pysqlite_connection_close(pysqlite_Connection* self, PyObject* args); PyObject* _pysqlite_connection_begin(pysqlite_Connection* self); PyObject* pysqlite_connection_commit(pysqlite_Connection* self, PyObject* args); PyObject* pysqlite_connection_rollback(pysqlite_Connection* self, PyObject* args); PyObject* pysqlite_connection_new(PyTypeObject* type, PyObject* args, PyObject* kw); int pysqlite_connection_init(pysqlite_Connection* self, PyObject* args, PyObject* kwargs); int pysqlite_connection_register_cursor(pysqlite_Connection* connection, PyObject* cursor); int pysqlite_check_thread(pysqlite_Connection* self); int pysqlite_check_connection(pysqlite_Connection* con); int pysqlite_connection_setup_types(void); #endif pysqlite-2.6.3/src/cursor.c000644 000765 000024 00000105012 11343726644 016604 0ustar00ghaeringstaff000000 000000 /* cursor.c - the cursor type * * Copyright (C) 2004-2010 Gerhard Häring * * This file is part of pysqlite. * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages * arising from the use of this software. * * Permission is granted to anyone to use this software for any purpose, * including commercial applications, and to alter it and redistribute it * freely, subject to the following restrictions: * * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software * in a product, an acknowledgment in the product documentation would be * appreciated but is not required. * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. */ #include "cursor.h" #include "module.h" #include "util.h" #include "sqlitecompat.h" /* used to decide wether to call PyInt_FromLong or PyLong_FromLongLong */ #ifndef INT32_MIN #define INT32_MIN (-2147483647 - 1) #endif #ifndef INT32_MAX #define INT32_MAX 2147483647 #endif PyObject* pysqlite_cursor_iternext(pysqlite_Cursor* self); static char* errmsg_fetch_across_rollback = "Cursor needed to be reset because of commit/rollback and can no longer be fetched from."; static pysqlite_StatementKind detect_statement_type(char* statement) { char buf[20]; char* src; char* dst; src = statement; /* skip over whitepace */ while (*src == '\r' || *src == '\n' || *src == ' ' || *src == '\t') { src++; } if (*src == 0) return STATEMENT_INVALID; dst = buf; *dst = 0; while (isalpha(*src) && dst - buf < sizeof(buf) - 2) { *dst++ = tolower(*src++); } *dst = 0; if (!strcmp(buf, "select")) { return STATEMENT_SELECT; } else if (!strcmp(buf, "insert")) { return STATEMENT_INSERT; } else if (!strcmp(buf, "update")) { return STATEMENT_UPDATE; } else if (!strcmp(buf, "delete")) { return STATEMENT_DELETE; } else if (!strcmp(buf, "replace")) { return STATEMENT_REPLACE; } else { return STATEMENT_OTHER; } } static int pysqlite_cursor_init(pysqlite_Cursor* self, PyObject* args, PyObject* kwargs) { pysqlite_Connection* connection; if (!PyArg_ParseTuple(args, "O!", &pysqlite_ConnectionType, &connection)) { return -1; } Py_INCREF(connection); self->connection = connection; self->statement = NULL; self->next_row = NULL; self->in_weakreflist = NULL; self->row_cast_map = PyList_New(0); if (!self->row_cast_map) { return -1; } Py_INCREF(Py_None); self->description = Py_None; Py_INCREF(Py_None); self->lastrowid= Py_None; self->arraysize = 1; self->closed = 0; self->reset = 0; self->rowcount = -1L; Py_INCREF(Py_None); self->row_factory = Py_None; if (!pysqlite_check_thread(self->connection)) { return -1; } if (!pysqlite_connection_register_cursor(connection, (PyObject*)self)) { return -1; } self->initialized = 1; return 0; } static void pysqlite_cursor_dealloc(pysqlite_Cursor* self) { int rc; /* Reset the statement if the user has not closed the cursor */ if (self->statement) { rc = pysqlite_statement_reset(self->statement); Py_DECREF(self->statement); } Py_XDECREF(self->connection); Py_XDECREF(self->row_cast_map); Py_XDECREF(self->description); Py_XDECREF(self->lastrowid); Py_XDECREF(self->row_factory); Py_XDECREF(self->next_row); if (self->in_weakreflist != NULL) { PyObject_ClearWeakRefs((PyObject*)self); } self->ob_type->tp_free((PyObject*)self); } PyObject* _pysqlite_get_converter(PyObject* key) { PyObject* upcase_key; PyObject* retval; upcase_key = PyObject_CallMethod(key, "upper", ""); if (!upcase_key) { return NULL; } retval = PyDict_GetItem(converters, upcase_key); Py_DECREF(upcase_key); return retval; } int pysqlite_build_row_cast_map(pysqlite_Cursor* self) { int i; const char* type_start = (const char*)-1; const char* pos; const char* colname; const char* decltype; PyObject* py_decltype; PyObject* converter; PyObject* key; if (!self->connection->detect_types) { return 0; } Py_XDECREF(self->row_cast_map); self->row_cast_map = PyList_New(0); for (i = 0; i < sqlite3_column_count(self->statement->st); i++) { converter = NULL; if (self->connection->detect_types & PARSE_COLNAMES) { colname = sqlite3_column_name(self->statement->st, i); if (colname) { for (pos = colname; *pos != 0; pos++) { if (*pos == '[') { type_start = pos + 1; } else if (*pos == ']' && type_start != (const char*)-1) { key = PyString_FromStringAndSize(type_start, pos - type_start); if (!key) { /* creating a string failed, but it is too complicated * to propagate the error here, we just assume there is * no converter and proceed */ break; } converter = _pysqlite_get_converter(key); Py_DECREF(key); break; } } } } if (!converter && self->connection->detect_types & PARSE_DECLTYPES) { decltype = sqlite3_column_decltype(self->statement->st, i); if (decltype) { for (pos = decltype;;pos++) { /* Converter names are split at '(' and blanks. * This allows 'INTEGER NOT NULL' to be treated as 'INTEGER' and * 'NUMBER(10)' to be treated as 'NUMBER', for example. * In other words, it will work as people expect it to work.*/ if (*pos == ' ' || *pos == '(' || *pos == 0) { py_decltype = PyString_FromStringAndSize(decltype, pos - decltype); if (!py_decltype) { return -1; } break; } } converter = _pysqlite_get_converter(py_decltype); Py_DECREF(py_decltype); } } if (!converter) { converter = Py_None; } if (PyList_Append(self->row_cast_map, converter) != 0) { if (converter != Py_None) { Py_DECREF(converter); } Py_XDECREF(self->row_cast_map); self->row_cast_map = NULL; return -1; } } return 0; } PyObject* _pysqlite_build_column_name(const char* colname) { const char* pos; if (!colname) { Py_INCREF(Py_None); return Py_None; } for (pos = colname;; pos++) { if (*pos == 0 || *pos == '[') { if ((*pos == '[') && (pos > colname) && (*(pos-1) == ' ')) { pos--; } return PyString_FromStringAndSize(colname, pos - colname); } } } PyObject* pysqlite_unicode_from_string(const char* val_str, int optimize) { const char* check; int is_ascii = 0; if (optimize) { is_ascii = 1; check = val_str; while (*check) { if (*check & 0x80) { is_ascii = 0; break; } check++; } } if (is_ascii) { return PyString_FromString(val_str); } else { return PyUnicode_DecodeUTF8(val_str, strlen(val_str), NULL); } } /* * Returns a row from the currently active SQLite statement * * Precondidition: * - sqlite3_step() has been called before and it returned SQLITE_ROW. */ PyObject* _pysqlite_fetch_one_row(pysqlite_Cursor* self) { int i, numcols; PyObject* row; PyObject* item = NULL; int coltype; PY_LONG_LONG intval; PyObject* converter; PyObject* converted; Py_ssize_t nbytes; PyObject* buffer; void* raw_buffer; const char* val_str; char buf[200]; const char* colname; if (self->reset) { PyErr_SetString(pysqlite_InterfaceError, errmsg_fetch_across_rollback); return NULL; } Py_BEGIN_ALLOW_THREADS numcols = sqlite3_data_count(self->statement->st); Py_END_ALLOW_THREADS row = PyTuple_New(numcols); if (!row) { return NULL; } for (i = 0; i < numcols; i++) { if (self->connection->detect_types) { converter = PyList_GetItem(self->row_cast_map, i); if (!converter) { converter = Py_None; } } else { converter = Py_None; } if (converter != Py_None) { nbytes = sqlite3_column_bytes(self->statement->st, i); val_str = (const char*)sqlite3_column_blob(self->statement->st, i); if (!val_str) { Py_INCREF(Py_None); converted = Py_None; } else { item = PyString_FromStringAndSize(val_str, nbytes); if (!item) { return NULL; } converted = PyObject_CallFunction(converter, "O", item); Py_DECREF(item); if (!converted) { break; } } } else { Py_BEGIN_ALLOW_THREADS coltype = sqlite3_column_type(self->statement->st, i); Py_END_ALLOW_THREADS if (coltype == SQLITE_NULL) { Py_INCREF(Py_None); converted = Py_None; } else if (coltype == SQLITE_INTEGER) { intval = sqlite3_column_int64(self->statement->st, i); if (intval < INT32_MIN || intval > INT32_MAX) { converted = PyLong_FromLongLong(intval); } else { converted = PyInt_FromLong((long)intval); } } else if (coltype == SQLITE_FLOAT) { converted = PyFloat_FromDouble(sqlite3_column_double(self->statement->st, i)); } else if (coltype == SQLITE_TEXT) { val_str = (const char*)sqlite3_column_text(self->statement->st, i); if ((self->connection->text_factory == (PyObject*)&PyUnicode_Type) || (self->connection->text_factory == pysqlite_OptimizedUnicode)) { converted = pysqlite_unicode_from_string(val_str, self->connection->text_factory == pysqlite_OptimizedUnicode ? 1 : 0); if (!converted) { colname = sqlite3_column_name(self->statement->st, i); if (!colname) { colname = ""; } PyOS_snprintf(buf, sizeof(buf) - 1, "Could not decode to UTF-8 column '%s' with text '%s'", colname , val_str); PyErr_SetString(pysqlite_OperationalError, buf); } } else if (self->connection->text_factory == (PyObject*)&PyString_Type) { converted = PyString_FromString(val_str); } else { converted = PyObject_CallFunction(self->connection->text_factory, "s", val_str); } } else { /* coltype == SQLITE_BLOB */ nbytes = sqlite3_column_bytes(self->statement->st, i); buffer = PyBuffer_New(nbytes); if (!buffer) { break; } if (PyObject_AsWriteBuffer(buffer, &raw_buffer, &nbytes)) { break; } memcpy(raw_buffer, sqlite3_column_blob(self->statement->st, i), nbytes); converted = buffer; } } if (converted) { PyTuple_SetItem(row, i, converted); } else { Py_INCREF(Py_None); PyTuple_SetItem(row, i, Py_None); } } if (PyErr_Occurred()) { Py_DECREF(row); row = NULL; } return row; } /* * Checks if a cursor object is usable. * * 0 => error; 1 => ok */ static int check_cursor(pysqlite_Cursor* cur) { if (!cur->initialized) { PyErr_SetString(pysqlite_ProgrammingError, "Base Cursor.__init__ not called."); return 0; } if (cur->closed) { PyErr_SetString(pysqlite_ProgrammingError, "Cannot operate on a closed cursor."); return 0; } else { return pysqlite_check_thread(cur->connection) && pysqlite_check_connection(cur->connection); } } PyObject* _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* args) { PyObject* operation; PyObject* operation_bytestr = NULL; char* operation_cstr; PyObject* parameters_list = NULL; PyObject* parameters_iter = NULL; PyObject* parameters = NULL; int i; int rc; PyObject* func_args; PyObject* result; int numcols; PY_LONG_LONG lastrowid; int statement_type; PyObject* descriptor; PyObject* second_argument = NULL; int allow_8bit_chars; if (!check_cursor(self)) { return NULL; } self->reset = 0; /* Make shooting yourself in the foot with not utf-8 decodable 8-bit-strings harder */ allow_8bit_chars = ((self->connection->text_factory != (PyObject*)&PyUnicode_Type) && (self->connection->text_factory != pysqlite_OptimizedUnicode)); Py_XDECREF(self->next_row); self->next_row = NULL; if (multiple) { /* executemany() */ if (!PyArg_ParseTuple(args, "OO", &operation, &second_argument)) { return NULL; } if (!PyString_Check(operation) && !PyUnicode_Check(operation)) { PyErr_SetString(PyExc_ValueError, "operation parameter must be str or unicode"); return NULL; } if (PyIter_Check(second_argument)) { /* iterator */ Py_INCREF(second_argument); parameters_iter = second_argument; } else { /* sequence */ parameters_iter = PyObject_GetIter(second_argument); if (!parameters_iter) { return NULL; } } } else { /* execute() */ if (!PyArg_ParseTuple(args, "O|O", &operation, &second_argument)) { return NULL; } if (!PyString_Check(operation) && !PyUnicode_Check(operation)) { PyErr_SetString(PyExc_ValueError, "operation parameter must be str or unicode"); return NULL; } parameters_list = PyList_New(0); if (!parameters_list) { return NULL; } if (second_argument == NULL) { second_argument = PyTuple_New(0); if (!second_argument) { goto error; } } else { Py_INCREF(second_argument); } if (PyList_Append(parameters_list, second_argument) != 0) { Py_DECREF(second_argument); goto error; } Py_DECREF(second_argument); parameters_iter = PyObject_GetIter(parameters_list); if (!parameters_iter) { goto error; } } if (self->statement != NULL) { /* There is an active statement */ rc = pysqlite_statement_reset(self->statement); } if (PyString_Check(operation)) { operation_cstr = PyString_AsString(operation); } else { operation_bytestr = PyUnicode_AsUTF8String(operation); if (!operation_bytestr) { goto error; } operation_cstr = PyString_AsString(operation_bytestr); } /* reset description and rowcount */ Py_DECREF(self->description); Py_INCREF(Py_None); self->description = Py_None; self->rowcount = -1L; func_args = PyTuple_New(1); if (!func_args) { goto error; } Py_INCREF(operation); if (PyTuple_SetItem(func_args, 0, operation) != 0) { goto error; } if (self->statement) { (void)pysqlite_statement_reset(self->statement); Py_DECREF(self->statement); } self->statement = (pysqlite_Statement*)pysqlite_cache_get(self->connection->statement_cache, func_args); Py_DECREF(func_args); if (!self->statement) { goto error; } if (self->statement->in_use) { Py_DECREF(self->statement); self->statement = PyObject_New(pysqlite_Statement, &pysqlite_StatementType); if (!self->statement) { goto error; } rc = pysqlite_statement_create(self->statement, self->connection, operation); if (rc != SQLITE_OK) { Py_CLEAR(self->statement); goto error; } } pysqlite_statement_reset(self->statement); pysqlite_statement_mark_dirty(self->statement); statement_type = detect_statement_type(operation_cstr); if (self->connection->begin_statement) { switch (statement_type) { case STATEMENT_UPDATE: case STATEMENT_DELETE: case STATEMENT_INSERT: case STATEMENT_REPLACE: if (!self->connection->inTransaction) { result = _pysqlite_connection_begin(self->connection); if (!result) { goto error; } Py_DECREF(result); } break; case STATEMENT_OTHER: /* it's a DDL statement or something similar - we better COMMIT first so it works for all cases */ if (self->connection->inTransaction) { result = pysqlite_connection_commit(self->connection, NULL); if (!result) { goto error; } Py_DECREF(result); } break; case STATEMENT_SELECT: if (multiple) { PyErr_SetString(pysqlite_ProgrammingError, "You cannot execute SELECT statements in executemany()."); goto error; } break; } } while (1) { parameters = PyIter_Next(parameters_iter); if (!parameters) { break; } pysqlite_statement_mark_dirty(self->statement); pysqlite_statement_bind_parameters(self->statement, parameters, allow_8bit_chars); if (PyErr_Occurred()) { goto error; } /* Keep trying the SQL statement until the schema stops changing. */ while (1) { /* Actually execute the SQL statement. */ rc = pysqlite_step(self->statement->st, self->connection); if (rc == SQLITE_DONE || rc == SQLITE_ROW) { /* If it worked, let's get out of the loop */ break; } /* Something went wrong. Re-set the statement and try again. */ rc = pysqlite_statement_reset(self->statement); if (rc == SQLITE_SCHEMA) { /* If this was a result of the schema changing, let's try again. */ rc = pysqlite_statement_recompile(self->statement, parameters); if (rc == SQLITE_OK) { continue; } else { /* If the database gave us an error, promote it to Python. */ (void)pysqlite_statement_reset(self->statement); _pysqlite_seterror(self->connection->db, NULL); goto error; } } else { if (PyErr_Occurred()) { /* there was an error that occurred in a user-defined callback */ if (_enable_callback_tracebacks) { PyErr_Print(); } else { PyErr_Clear(); } } (void)pysqlite_statement_reset(self->statement); _pysqlite_seterror(self->connection->db, NULL); goto error; } } if (pysqlite_build_row_cast_map(self) != 0) { PyErr_SetString(pysqlite_OperationalError, "Error while building row_cast_map"); goto error; } if (rc == SQLITE_ROW || (rc == SQLITE_DONE && statement_type == STATEMENT_SELECT)) { if (self->description == Py_None) { Py_BEGIN_ALLOW_THREADS numcols = sqlite3_column_count(self->statement->st); Py_END_ALLOW_THREADS Py_DECREF(self->description); self->description = PyTuple_New(numcols); if (!self->description) { goto error; } for (i = 0; i < numcols; i++) { descriptor = PyTuple_New(7); if (!descriptor) { goto error; } PyTuple_SetItem(descriptor, 0, _pysqlite_build_column_name(sqlite3_column_name(self->statement->st, i))); Py_INCREF(Py_None); PyTuple_SetItem(descriptor, 1, Py_None); Py_INCREF(Py_None); PyTuple_SetItem(descriptor, 2, Py_None); Py_INCREF(Py_None); PyTuple_SetItem(descriptor, 3, Py_None); Py_INCREF(Py_None); PyTuple_SetItem(descriptor, 4, Py_None); Py_INCREF(Py_None); PyTuple_SetItem(descriptor, 5, Py_None); Py_INCREF(Py_None); PyTuple_SetItem(descriptor, 6, Py_None); PyTuple_SetItem(self->description, i, descriptor); } } } if (rc == SQLITE_ROW) { if (multiple) { PyErr_SetString(pysqlite_ProgrammingError, "executemany() can only execute DML statements."); goto error; } self->next_row = _pysqlite_fetch_one_row(self); } else if (rc == SQLITE_DONE && !multiple) { pysqlite_statement_reset(self->statement); Py_CLEAR(self->statement); } switch (statement_type) { case STATEMENT_UPDATE: case STATEMENT_DELETE: case STATEMENT_INSERT: case STATEMENT_REPLACE: if (self->rowcount == -1L) { self->rowcount = 0L; } self->rowcount += (long)sqlite3_changes(self->connection->db); } Py_DECREF(self->lastrowid); if (!multiple && statement_type == STATEMENT_INSERT) { Py_BEGIN_ALLOW_THREADS lastrowid = sqlite3_last_insert_rowid(self->connection->db); Py_END_ALLOW_THREADS self->lastrowid = PyInt_FromLong((long)lastrowid); } else { Py_INCREF(Py_None); self->lastrowid = Py_None; } if (multiple) { rc = pysqlite_statement_reset(self->statement); } Py_XDECREF(parameters); } error: /* just to be sure (implicit ROLLBACKs with ON CONFLICT ROLLBACK/OR * ROLLBACK could have happened */ #ifdef SQLITE_VERSION_NUMBER #if SQLITE_VERSION_NUMBER >= 3002002 self->connection->inTransaction = !sqlite3_get_autocommit(self->connection->db); #endif #endif Py_XDECREF(operation_bytestr); Py_XDECREF(parameters); Py_XDECREF(parameters_iter); Py_XDECREF(parameters_list); if (PyErr_Occurred()) { self->rowcount = -1L; return NULL; } else { Py_INCREF(self); return (PyObject*)self; } } PyObject* pysqlite_cursor_execute(pysqlite_Cursor* self, PyObject* args) { return _pysqlite_query_execute(self, 0, args); } PyObject* pysqlite_cursor_executemany(pysqlite_Cursor* self, PyObject* args) { return _pysqlite_query_execute(self, 1, args); } PyObject* pysqlite_cursor_executescript(pysqlite_Cursor* self, PyObject* args) { PyObject* script_obj; PyObject* script_str = NULL; const char* script_cstr; sqlite3_stmt* statement; int rc; PyObject* result; if (!PyArg_ParseTuple(args, "O", &script_obj)) { return NULL; } if (!check_cursor(self)) { return NULL; } self->reset = 0; if (PyString_Check(script_obj)) { script_cstr = PyString_AsString(script_obj); } else if (PyUnicode_Check(script_obj)) { script_str = PyUnicode_AsUTF8String(script_obj); if (!script_str) { return NULL; } script_cstr = PyString_AsString(script_str); } else { PyErr_SetString(PyExc_ValueError, "script argument must be unicode or string."); return NULL; } /* commit first */ result = pysqlite_connection_commit(self->connection, NULL); if (!result) { goto error; } Py_DECREF(result); while (1) { Py_BEGIN_ALLOW_THREADS rc = sqlite3_prepare(self->connection->db, script_cstr, -1, &statement, &script_cstr); Py_END_ALLOW_THREADS if (rc != SQLITE_OK) { _pysqlite_seterror(self->connection->db, NULL); goto error; } /* execute statement, and ignore results of SELECT statements */ rc = SQLITE_ROW; while (rc == SQLITE_ROW) { rc = pysqlite_step(statement, self->connection); /* TODO: we probably need more error handling here */ } if (rc != SQLITE_DONE) { (void)sqlite3_finalize(statement); _pysqlite_seterror(self->connection->db, NULL); goto error; } rc = sqlite3_finalize(statement); if (rc != SQLITE_OK) { _pysqlite_seterror(self->connection->db, NULL); goto error; } if (*script_cstr == (char)0) { break; } } error: Py_XDECREF(script_str); if (PyErr_Occurred()) { return NULL; } else { Py_INCREF(self); return (PyObject*)self; } } PyObject* pysqlite_cursor_getiter(pysqlite_Cursor *self) { Py_INCREF(self); return (PyObject*)self; } PyObject* pysqlite_cursor_iternext(pysqlite_Cursor *self) { PyObject* next_row_tuple; PyObject* next_row; int rc; if (!check_cursor(self)) { return NULL; } if (self->reset) { PyErr_SetString(pysqlite_InterfaceError, errmsg_fetch_across_rollback); return NULL; } if (!self->next_row) { if (self->statement) { (void)pysqlite_statement_reset(self->statement); Py_DECREF(self->statement); self->statement = NULL; } return NULL; } next_row_tuple = self->next_row; self->next_row = NULL; if (self->row_factory != Py_None) { next_row = PyObject_CallFunction(self->row_factory, "OO", self, next_row_tuple); Py_DECREF(next_row_tuple); } else { next_row = next_row_tuple; } if (self->statement) { rc = pysqlite_step(self->statement->st, self->connection); if (rc != SQLITE_DONE && rc != SQLITE_ROW) { (void)pysqlite_statement_reset(self->statement); Py_DECREF(next_row); _pysqlite_seterror(self->connection->db, NULL); return NULL; } if (rc == SQLITE_ROW) { self->next_row = _pysqlite_fetch_one_row(self); } } return next_row; } PyObject* pysqlite_cursor_fetchone(pysqlite_Cursor* self, PyObject* args) { PyObject* row; row = pysqlite_cursor_iternext(self); if (!row && !PyErr_Occurred()) { Py_INCREF(Py_None); return Py_None; } return row; } PyObject* pysqlite_cursor_fetchmany(pysqlite_Cursor* self, PyObject* args, PyObject* kwargs) { static char *kwlist[] = {"size", NULL, NULL}; PyObject* row; PyObject* list; int maxrows = self->arraysize; int counter = 0; if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:fetchmany", kwlist, &maxrows)) { return NULL; } list = PyList_New(0); if (!list) { return NULL; } /* just make sure we enter the loop */ row = Py_None; while (row) { row = pysqlite_cursor_iternext(self); if (row) { PyList_Append(list, row); Py_DECREF(row); } else { break; } if (++counter == maxrows) { break; } } if (PyErr_Occurred()) { Py_DECREF(list); return NULL; } else { return list; } } PyObject* pysqlite_cursor_fetchall(pysqlite_Cursor* self, PyObject* args) { PyObject* row; PyObject* list; list = PyList_New(0); if (!list) { return NULL; } /* just make sure we enter the loop */ row = (PyObject*)Py_None; while (row) { row = pysqlite_cursor_iternext(self); if (row) { PyList_Append(list, row); Py_DECREF(row); } } if (PyErr_Occurred()) { Py_DECREF(list); return NULL; } else { return list; } } PyObject* pysqlite_noop(pysqlite_Connection* self, PyObject* args) { /* don't care, return None */ Py_INCREF(Py_None); return Py_None; } PyObject* pysqlite_cursor_close(pysqlite_Cursor* self, PyObject* args) { if (!pysqlite_check_thread(self->connection) || !pysqlite_check_connection(self->connection)) { return NULL; } if (self->statement) { (void)pysqlite_statement_reset(self->statement); Py_CLEAR(self->statement); } self->closed = 1; Py_INCREF(Py_None); return Py_None; } static PyMethodDef cursor_methods[] = { {"execute", (PyCFunction)pysqlite_cursor_execute, METH_VARARGS, PyDoc_STR("Executes a SQL statement.")}, {"executemany", (PyCFunction)pysqlite_cursor_executemany, METH_VARARGS, PyDoc_STR("Repeatedly executes a SQL statement.")}, {"executescript", (PyCFunction)pysqlite_cursor_executescript, METH_VARARGS, PyDoc_STR("Executes a multiple SQL statements at once. Non-standard.")}, {"fetchone", (PyCFunction)pysqlite_cursor_fetchone, METH_NOARGS, PyDoc_STR("Fetches one row from the resultset.")}, {"fetchmany", (PyCFunction)pysqlite_cursor_fetchmany, METH_VARARGS|METH_KEYWORDS, PyDoc_STR("Fetches several rows from the resultset.")}, {"fetchall", (PyCFunction)pysqlite_cursor_fetchall, METH_NOARGS, PyDoc_STR("Fetches all rows from the resultset.")}, {"close", (PyCFunction)pysqlite_cursor_close, METH_NOARGS, PyDoc_STR("Closes the cursor.")}, {"setinputsizes", (PyCFunction)pysqlite_noop, METH_VARARGS, PyDoc_STR("Required by DB-API. Does nothing in pysqlite.")}, {"setoutputsize", (PyCFunction)pysqlite_noop, METH_VARARGS, PyDoc_STR("Required by DB-API. Does nothing in pysqlite.")}, {NULL, NULL} }; static struct PyMemberDef cursor_members[] = { {"connection", T_OBJECT, offsetof(pysqlite_Cursor, connection), RO}, {"description", T_OBJECT, offsetof(pysqlite_Cursor, description), RO}, {"arraysize", T_INT, offsetof(pysqlite_Cursor, arraysize), 0}, {"lastrowid", T_OBJECT, offsetof(pysqlite_Cursor, lastrowid), RO}, {"rowcount", T_LONG, offsetof(pysqlite_Cursor, rowcount), RO}, {"row_factory", T_OBJECT, offsetof(pysqlite_Cursor, row_factory), 0}, {NULL} }; static char cursor_doc[] = PyDoc_STR("SQLite database cursor class."); PyTypeObject pysqlite_CursorType = { PyVarObject_HEAD_INIT(NULL, 0) MODULE_NAME ".Cursor", /* tp_name */ sizeof(pysqlite_Cursor), /* tp_basicsize */ 0, /* tp_itemsize */ (destructor)pysqlite_cursor_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_ITER|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */ cursor_doc, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ offsetof(pysqlite_Cursor, in_weakreflist), /* tp_weaklistoffset */ (getiterfunc)pysqlite_cursor_getiter, /* tp_iter */ (iternextfunc)pysqlite_cursor_iternext, /* tp_iternext */ cursor_methods, /* tp_methods */ cursor_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ (initproc)pysqlite_cursor_init, /* tp_init */ 0, /* tp_alloc */ 0, /* tp_new */ 0 /* tp_free */ }; extern int pysqlite_cursor_setup_types(void) { pysqlite_CursorType.tp_new = PyType_GenericNew; return PyType_Ready(&pysqlite_CursorType); } pysqlite-2.6.3/src/cursor.h000644 000765 000024 00000005023 11343727273 016611 0ustar00ghaeringstaff000000 000000 /* cursor.h - definitions for the cursor type * * Copyright (C) 2004-2010 Gerhard Häring * * This file is part of pysqlite. * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages * arising from the use of this software. * * Permission is granted to anyone to use this software for any purpose, * including commercial applications, and to alter it and redistribute it * freely, subject to the following restrictions: * * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software * in a product, an acknowledgment in the product documentation would be * appreciated but is not required. * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. */ #ifndef PYSQLITE_CURSOR_H #define PYSQLITE_CURSOR_H #include "Python.h" #include "statement.h" #include "connection.h" #include "module.h" typedef struct { PyObject_HEAD pysqlite_Connection* connection; PyObject* description; PyObject* row_cast_map; int arraysize; PyObject* lastrowid; long rowcount; PyObject* row_factory; pysqlite_Statement* statement; int closed; int reset; int initialized; /* the next row to be returned, NULL if no next row available */ PyObject* next_row; PyObject* in_weakreflist; /* List of weak references */ } pysqlite_Cursor; typedef enum { STATEMENT_INVALID, STATEMENT_INSERT, STATEMENT_DELETE, STATEMENT_UPDATE, STATEMENT_REPLACE, STATEMENT_SELECT, STATEMENT_OTHER } pysqlite_StatementKind; extern PyTypeObject pysqlite_CursorType; PyObject* pysqlite_cursor_execute(pysqlite_Cursor* self, PyObject* args); PyObject* pysqlite_cursor_executemany(pysqlite_Cursor* self, PyObject* args); PyObject* pysqlite_cursor_getiter(pysqlite_Cursor *self); PyObject* pysqlite_cursor_iternext(pysqlite_Cursor *self); PyObject* pysqlite_cursor_fetchone(pysqlite_Cursor* self, PyObject* args); PyObject* pysqlite_cursor_fetchmany(pysqlite_Cursor* self, PyObject* args, PyObject* kwargs); PyObject* pysqlite_cursor_fetchall(pysqlite_Cursor* self, PyObject* args); PyObject* pysqlite_noop(pysqlite_Connection* self, PyObject* args); PyObject* pysqlite_cursor_close(pysqlite_Cursor* self, PyObject* args); int pysqlite_cursor_setup_types(void); #define UNKNOWN (-1) #endif pysqlite-2.6.3/src/microprotocols.c000644 000765 000024 00000010405 11343657406 020345 0ustar00ghaeringstaff000000 000000 /* microprotocols.c - minimalist and non-validating protocols implementation * * Copyright (C) 2003-2004 Federico Di Gregorio * * This file is part of psycopg and was adapted for pysqlite. Federico Di * Gregorio gave the permission to use it within pysqlite under the following * license: * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages * arising from the use of this software. * * Permission is granted to anyone to use this software for any purpose, * including commercial applications, and to alter it and redistribute it * freely, subject to the following restrictions: * * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software * in a product, an acknowledgment in the product documentation would be * appreciated but is not required. * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. */ #include #include #include "cursor.h" #include "microprotocols.h" #include "prepare_protocol.h" /** the adapters registry **/ PyObject *psyco_adapters; /* pysqlite_microprotocols_init - initialize the adapters dictionary */ int pysqlite_microprotocols_init(PyObject *dict) { /* create adapters dictionary and put it in module namespace */ if ((psyco_adapters = PyDict_New()) == NULL) { return -1; } return PyDict_SetItemString(dict, "adapters", psyco_adapters); } /* pysqlite_microprotocols_add - add a reverse type-caster to the dictionary */ int pysqlite_microprotocols_add(PyTypeObject *type, PyObject *proto, PyObject *cast) { PyObject* key; int rc; if (proto == NULL) proto = (PyObject*)&pysqlite_PrepareProtocolType; key = Py_BuildValue("(OO)", (PyObject*)type, proto); if (!key) { return -1; } rc = PyDict_SetItem(psyco_adapters, key, cast); Py_DECREF(key); return rc; } /* pysqlite_microprotocols_adapt - adapt an object to the built-in protocol */ PyObject * pysqlite_microprotocols_adapt(PyObject *obj, PyObject *proto, PyObject *alt) { PyObject *adapter, *key; /* we don't check for exact type conformance as specified in PEP 246 because the pysqlite_PrepareProtocolType type is abstract and there is no way to get a quotable object to be its instance */ /* look for an adapter in the registry */ key = Py_BuildValue("(OO)", (PyObject*)obj->ob_type, proto); if (!key) { return NULL; } adapter = PyDict_GetItem(psyco_adapters, key); Py_DECREF(key); if (adapter) { PyObject *adapted = PyObject_CallFunctionObjArgs(adapter, obj, NULL); return adapted; } /* try to have the protocol adapt this object*/ if (PyObject_HasAttrString(proto, "__adapt__")) { PyObject *adapted = PyObject_CallMethod(proto, "__adapt__", "O", obj); if (adapted) { if (adapted != Py_None) { return adapted; } else { Py_DECREF(adapted); } } if (PyErr_Occurred() && !PyErr_ExceptionMatches(PyExc_TypeError)) return NULL; } /* and finally try to have the object adapt itself */ if (PyObject_HasAttrString(obj, "__conform__")) { PyObject *adapted = PyObject_CallMethod(obj, "__conform__","O", proto); if (adapted) { if (adapted != Py_None) { return adapted; } else { Py_DECREF(adapted); } } if (PyErr_Occurred() && !PyErr_ExceptionMatches(PyExc_TypeError)) { return NULL; } } /* else set the right exception and return NULL */ PyErr_SetString(pysqlite_ProgrammingError, "can't adapt"); return NULL; } /** module-level functions **/ PyObject * pysqlite_adapt(pysqlite_Cursor *self, PyObject *args) { PyObject *obj, *alt = NULL; PyObject *proto = (PyObject*)&pysqlite_PrepareProtocolType; if (!PyArg_ParseTuple(args, "O|OO", &obj, &proto, &alt)) return NULL; return pysqlite_microprotocols_adapt(obj, proto, alt); } pysqlite-2.6.3/src/microprotocols.h000644 000765 000024 00000004106 11343657406 020353 0ustar00ghaeringstaff000000 000000 /* microprotocols.c - definitions for minimalist and non-validating protocols * * Copyright (C) 2003-2004 Federico Di Gregorio * * This file is part of psycopg and was adapted for pysqlite. Federico Di * Gregorio gave the permission to use it within pysqlite under the following * license: * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages * arising from the use of this software. * * Permission is granted to anyone to use this software for any purpose, * including commercial applications, and to alter it and redistribute it * freely, subject to the following restrictions: * * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software * in a product, an acknowledgment in the product documentation would be * appreciated but is not required. * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. */ #ifndef PSYCOPG_MICROPROTOCOLS_H #define PSYCOPG_MICROPROTOCOLS_H 1 #include /** adapters registry **/ extern PyObject *psyco_adapters; /** the names of the three mandatory methods **/ #define MICROPROTOCOLS_GETQUOTED_NAME "getquoted" #define MICROPROTOCOLS_GETSTRING_NAME "getstring" #define MICROPROTOCOLS_GETBINARY_NAME "getbinary" /** exported functions **/ /* used by module.c to init the microprotocols system */ extern int pysqlite_microprotocols_init(PyObject *dict); extern int pysqlite_microprotocols_add( PyTypeObject *type, PyObject *proto, PyObject *cast); extern PyObject *pysqlite_microprotocols_adapt( PyObject *obj, PyObject *proto, PyObject *alt); extern PyObject * pysqlite_adapt(pysqlite_Cursor* self, PyObject *args); #define pysqlite_adapt_doc \ "adapt(obj, protocol, alternate) -> adapt obj to given protocol. Non-standard." #endif /* !defined(PSYCOPG_MICROPROTOCOLS_H) */ pysqlite-2.6.3/src/module.c000644 000765 000024 00000035633 11526453607 016566 0ustar00ghaeringstaff000000 000000 /* module.c - the module itself * * Copyright (C) 2004-2010 Gerhard Häring * * This file is part of pysqlite. * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages * arising from the use of this software. * * Permission is granted to anyone to use this software for any purpose, * including commercial applications, and to alter it and redistribute it * freely, subject to the following restrictions: * * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software * in a product, an acknowledgment in the product documentation would be * appreciated but is not required. * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. */ #include "connection.h" #include "statement.h" #include "cursor.h" #include "cache.h" #include "prepare_protocol.h" #include "microprotocols.h" #include "row.h" #ifdef PYSQLITE_EXPERIMENTAL #include "backup.h" #endif #if SQLITE_VERSION_NUMBER >= 3003003 #define HAVE_SHARED_CACHE #endif /* static objects at module-level */ PyObject* pysqlite_Error, *pysqlite_Warning, *pysqlite_InterfaceError, *pysqlite_DatabaseError, *pysqlite_InternalError, *pysqlite_OperationalError, *pysqlite_ProgrammingError, *pysqlite_IntegrityError, *pysqlite_DataError, *pysqlite_NotSupportedError, *pysqlite_OptimizedUnicode; PyObject* converters; int _enable_callback_tracebacks; int pysqlite_BaseTypeAdapted; static PyObject* module_connect(PyObject* self, PyObject* args, PyObject* kwargs) { /* Python seems to have no way of extracting a single keyword-arg at * C-level, so this code is redundant with the one in connection_init in * connection.c and must always be copied from there ... */ static char *kwlist[] = {"database", "timeout", "detect_types", "isolation_level", "check_same_thread", "factory", "cached_statements", NULL, NULL}; PyObject* database; int detect_types = 0; PyObject* isolation_level; PyObject* factory = NULL; int check_same_thread = 1; int cached_statements; double timeout = 5.0; PyObject* result; if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|diOiOi", kwlist, &database, &timeout, &detect_types, &isolation_level, &check_same_thread, &factory, &cached_statements)) { return NULL; } if (factory == NULL) { factory = (PyObject*)&pysqlite_ConnectionType; } result = PyObject_Call(factory, args, kwargs); return result; } PyDoc_STRVAR(module_connect_doc, "connect(database[, timeout, isolation_level, detect_types, factory])\n\ \n\ Opens a connection to the SQLite database file *database*. You can use\n\ \":memory:\" to open a database connection to a database that resides in\n\ RAM instead of on disk."); static PyObject* module_complete(PyObject* self, PyObject* args, PyObject* kwargs) { static char *kwlist[] = {"statement", NULL, NULL}; char* statement; PyObject* result; if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s", kwlist, &statement)) { return NULL; } if (sqlite3_complete(statement)) { result = Py_True; } else { result = Py_False; } Py_INCREF(result); return result; } PyDoc_STRVAR(module_complete_doc, "complete_statement(sql)\n\ \n\ Checks if a string contains a complete SQL statement. Non-standard."); #ifdef HAVE_SHARED_CACHE static PyObject* module_enable_shared_cache(PyObject* self, PyObject* args, PyObject* kwargs) { static char *kwlist[] = {"do_enable", NULL, NULL}; int do_enable; int rc; if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i", kwlist, &do_enable)) { return NULL; } rc = sqlite3_enable_shared_cache(do_enable); if (rc != SQLITE_OK) { PyErr_SetString(pysqlite_OperationalError, "Changing the shared_cache flag failed"); return NULL; } else { Py_INCREF(Py_None); return Py_None; } } PyDoc_STRVAR(module_enable_shared_cache_doc, "enable_shared_cache(do_enable)\n\ \n\ Enable or disable shared cache mode for the calling thread.\n\ Experimental/Non-standard."); #endif /* HAVE_SHARED_CACHE */ static PyObject* module_register_adapter(PyObject* self, PyObject* args) { PyTypeObject* type; PyObject* caster; int rc; if (!PyArg_ParseTuple(args, "OO", &type, &caster)) { return NULL; } /* a basic type is adapted; there's a performance optimization if that's not the case * (99 % of all usages) */ if (type == &PyInt_Type || type == &PyLong_Type || type == &PyFloat_Type || type == &PyString_Type || type == &PyUnicode_Type || type == &PyBuffer_Type) { pysqlite_BaseTypeAdapted = 1; } rc = pysqlite_microprotocols_add(type, (PyObject*)&pysqlite_PrepareProtocolType, caster); if (rc == -1) return NULL; Py_INCREF(Py_None); return Py_None; } PyDoc_STRVAR(module_register_adapter_doc, "register_adapter(type, callable)\n\ \n\ Registers an adapter with pysqlite's adapter registry. Non-standard."); static PyObject* module_register_converter(PyObject* self, PyObject* args) { PyObject* orig_name; PyObject* name = NULL; PyObject* callable; PyObject* retval = NULL; if (!PyArg_ParseTuple(args, "SO", &orig_name, &callable)) { return NULL; } /* convert the name to upper case */ name = PyObject_CallMethod(orig_name, "upper", ""); if (!name) { goto error; } if (PyDict_SetItem(converters, name, callable) != 0) { goto error; } Py_INCREF(Py_None); retval = Py_None; error: Py_XDECREF(name); return retval; } PyDoc_STRVAR(module_register_converter_doc, "register_converter(typename, callable)\n\ \n\ Registers a converter with pysqlite. Non-standard."); static PyObject* enable_callback_tracebacks(PyObject* self, PyObject* args) { if (!PyArg_ParseTuple(args, "i", &_enable_callback_tracebacks)) { return NULL; } Py_INCREF(Py_None); return Py_None; } PyDoc_STRVAR(enable_callback_tracebacks_doc, "enable_callback_tracebacks(flag)\n\ \n\ Enable or disable callback functions throwing errors to stderr."); static void converters_init(PyObject* dict) { converters = PyDict_New(); if (!converters) { return; } PyDict_SetItemString(dict, "converters", converters); } static PyMethodDef module_methods[] = { {"connect", (PyCFunction)module_connect, METH_VARARGS | METH_KEYWORDS, module_connect_doc}, {"complete_statement", (PyCFunction)module_complete, METH_VARARGS | METH_KEYWORDS, module_complete_doc}, #ifdef HAVE_SHARED_CACHE {"enable_shared_cache", (PyCFunction)module_enable_shared_cache, METH_VARARGS | METH_KEYWORDS, module_enable_shared_cache_doc}, #endif {"register_adapter", (PyCFunction)module_register_adapter, METH_VARARGS, module_register_adapter_doc}, {"register_converter", (PyCFunction)module_register_converter, METH_VARARGS, module_register_converter_doc}, {"adapt", (PyCFunction)pysqlite_adapt, METH_VARARGS, pysqlite_adapt_doc}, {"enable_callback_tracebacks", (PyCFunction)enable_callback_tracebacks, METH_VARARGS, enable_callback_tracebacks_doc}, {NULL, NULL} }; struct _IntConstantPair { char* constant_name; int constant_value; }; typedef struct _IntConstantPair IntConstantPair; static IntConstantPair _int_constants[] = { {"PARSE_DECLTYPES", PARSE_DECLTYPES}, {"PARSE_COLNAMES", PARSE_COLNAMES}, {"SQLITE_OK", SQLITE_OK}, {"SQLITE_DENY", SQLITE_DENY}, {"SQLITE_IGNORE", SQLITE_IGNORE}, {"SQLITE_CREATE_INDEX", SQLITE_CREATE_INDEX}, {"SQLITE_CREATE_TABLE", SQLITE_CREATE_TABLE}, {"SQLITE_CREATE_TEMP_INDEX", SQLITE_CREATE_TEMP_INDEX}, {"SQLITE_CREATE_TEMP_TABLE", SQLITE_CREATE_TEMP_TABLE}, {"SQLITE_CREATE_TEMP_TRIGGER", SQLITE_CREATE_TEMP_TRIGGER}, {"SQLITE_CREATE_TEMP_VIEW", SQLITE_CREATE_TEMP_VIEW}, {"SQLITE_CREATE_TRIGGER", SQLITE_CREATE_TRIGGER}, {"SQLITE_CREATE_VIEW", SQLITE_CREATE_VIEW}, {"SQLITE_DELETE", SQLITE_DELETE}, {"SQLITE_DROP_INDEX", SQLITE_DROP_INDEX}, {"SQLITE_DROP_TABLE", SQLITE_DROP_TABLE}, {"SQLITE_DROP_TEMP_INDEX", SQLITE_DROP_TEMP_INDEX}, {"SQLITE_DROP_TEMP_TABLE", SQLITE_DROP_TEMP_TABLE}, {"SQLITE_DROP_TEMP_TRIGGER", SQLITE_DROP_TEMP_TRIGGER}, {"SQLITE_DROP_TEMP_VIEW", SQLITE_DROP_TEMP_VIEW}, {"SQLITE_DROP_TRIGGER", SQLITE_DROP_TRIGGER}, {"SQLITE_DROP_VIEW", SQLITE_DROP_VIEW}, {"SQLITE_INSERT", SQLITE_INSERT}, {"SQLITE_PRAGMA", SQLITE_PRAGMA}, {"SQLITE_READ", SQLITE_READ}, {"SQLITE_SELECT", SQLITE_SELECT}, {"SQLITE_TRANSACTION", SQLITE_TRANSACTION}, {"SQLITE_UPDATE", SQLITE_UPDATE}, {"SQLITE_ATTACH", SQLITE_ATTACH}, {"SQLITE_DETACH", SQLITE_DETACH}, #if SQLITE_VERSION_NUMBER >= 3002001 {"SQLITE_ALTER_TABLE", SQLITE_ALTER_TABLE}, {"SQLITE_REINDEX", SQLITE_REINDEX}, #endif #if SQLITE_VERSION_NUMBER >= 3003000 {"SQLITE_ANALYZE", SQLITE_ANALYZE}, #endif {(char*)NULL, 0} }; PyMODINIT_FUNC init_sqlite(void) { PyObject *module, *dict; PyObject *tmp_obj; int i; module = Py_InitModule("pysqlite2._sqlite", module_methods); if (!module || (pysqlite_row_setup_types() < 0) || (pysqlite_cursor_setup_types() < 0) || (pysqlite_connection_setup_types() < 0) || (pysqlite_cache_setup_types() < 0) || (pysqlite_statement_setup_types() < 0) || #ifdef PYSQLITE_EXPERIMENTAL (pysqlite_backup_setup_types() < 0) || #endif (pysqlite_prepare_protocol_setup_types() < 0) ) { return; } Py_INCREF(&pysqlite_ConnectionType); PyModule_AddObject(module, "Connection", (PyObject*) &pysqlite_ConnectionType); Py_INCREF(&pysqlite_CursorType); PyModule_AddObject(module, "Cursor", (PyObject*) &pysqlite_CursorType); Py_INCREF(&pysqlite_CacheType); PyModule_AddObject(module, "Statement", (PyObject*)&pysqlite_StatementType); Py_INCREF(&pysqlite_StatementType); PyModule_AddObject(module, "Cache", (PyObject*) &pysqlite_CacheType); Py_INCREF(&pysqlite_PrepareProtocolType); PyModule_AddObject(module, "PrepareProtocol", (PyObject*) &pysqlite_PrepareProtocolType); Py_INCREF(&pysqlite_RowType); PyModule_AddObject(module, "Row", (PyObject*) &pysqlite_RowType); if (!(dict = PyModule_GetDict(module))) { goto error; } /*** Create DB-API Exception hierarchy */ if (!(pysqlite_Error = PyErr_NewException(MODULE_NAME ".Error", PyExc_StandardError, NULL))) { goto error; } PyDict_SetItemString(dict, "Error", pysqlite_Error); if (!(pysqlite_Warning = PyErr_NewException(MODULE_NAME ".Warning", PyExc_StandardError, NULL))) { goto error; } PyDict_SetItemString(dict, "Warning", pysqlite_Warning); /* Error subclasses */ if (!(pysqlite_InterfaceError = PyErr_NewException(MODULE_NAME ".InterfaceError", pysqlite_Error, NULL))) { goto error; } PyDict_SetItemString(dict, "InterfaceError", pysqlite_InterfaceError); if (!(pysqlite_DatabaseError = PyErr_NewException(MODULE_NAME ".DatabaseError", pysqlite_Error, NULL))) { goto error; } PyDict_SetItemString(dict, "DatabaseError", pysqlite_DatabaseError); /* pysqlite_DatabaseError subclasses */ if (!(pysqlite_InternalError = PyErr_NewException(MODULE_NAME ".InternalError", pysqlite_DatabaseError, NULL))) { goto error; } PyDict_SetItemString(dict, "InternalError", pysqlite_InternalError); if (!(pysqlite_OperationalError = PyErr_NewException(MODULE_NAME ".OperationalError", pysqlite_DatabaseError, NULL))) { goto error; } PyDict_SetItemString(dict, "OperationalError", pysqlite_OperationalError); if (!(pysqlite_ProgrammingError = PyErr_NewException(MODULE_NAME ".ProgrammingError", pysqlite_DatabaseError, NULL))) { goto error; } PyDict_SetItemString(dict, "ProgrammingError", pysqlite_ProgrammingError); if (!(pysqlite_IntegrityError = PyErr_NewException(MODULE_NAME ".IntegrityError", pysqlite_DatabaseError,NULL))) { goto error; } PyDict_SetItemString(dict, "IntegrityError", pysqlite_IntegrityError); if (!(pysqlite_DataError = PyErr_NewException(MODULE_NAME ".DataError", pysqlite_DatabaseError, NULL))) { goto error; } PyDict_SetItemString(dict, "DataError", pysqlite_DataError); if (!(pysqlite_NotSupportedError = PyErr_NewException(MODULE_NAME ".NotSupportedError", pysqlite_DatabaseError, NULL))) { goto error; } PyDict_SetItemString(dict, "NotSupportedError", pysqlite_NotSupportedError); /* We just need "something" unique for pysqlite_OptimizedUnicode. It does not really * need to be a string subclass. Just anything that can act as a special * marker for us. So I pulled PyCell_Type out of my magic hat. */ Py_INCREF((PyObject*)&PyCell_Type); pysqlite_OptimizedUnicode = (PyObject*)&PyCell_Type; PyDict_SetItemString(dict, "OptimizedUnicode", pysqlite_OptimizedUnicode); /* Set integer constants */ for (i = 0; _int_constants[i].constant_name != 0; i++) { tmp_obj = PyInt_FromLong(_int_constants[i].constant_value); if (!tmp_obj) { goto error; } PyDict_SetItemString(dict, _int_constants[i].constant_name, tmp_obj); Py_DECREF(tmp_obj); } if (!(tmp_obj = PyString_FromString(PYSQLITE_VERSION))) { goto error; } PyDict_SetItemString(dict, "version", tmp_obj); Py_DECREF(tmp_obj); if (!(tmp_obj = PyString_FromString(sqlite3_libversion()))) { goto error; } PyDict_SetItemString(dict, "sqlite_version", tmp_obj); Py_DECREF(tmp_obj); /* initialize microprotocols layer */ pysqlite_microprotocols_init(dict); /* initialize the default converters */ converters_init(dict); _enable_callback_tracebacks = 0; pysqlite_BaseTypeAdapted = 0; /* Original comment from _bsddb.c in the Python core. This is also still * needed nowadays for Python 2.3/2.4. * * PyEval_InitThreads is called here due to a quirk in python 1.5 * - 2.2.1 (at least) according to Russell Williamson : * The global interpreter lock is not initialized until the first * thread is created using thread.start_new_thread() or fork() is * called. that would cause the ALLOW_THREADS here to segfault due * to a null pointer reference if no threads or child processes * have been created. This works around that and is a no-op if * threads have already been initialized. * (see pybsddb-users mailing list post on 2002-08-07) */ #ifdef WITH_THREAD PyEval_InitThreads(); #endif error: if (PyErr_Occurred()) { PyErr_SetString(PyExc_ImportError, "pysqlite2._sqlite: init failed"); } } pysqlite-2.6.3/src/module.h000644 000765 000024 00000003742 11526730210 016553 0ustar00ghaeringstaff000000 000000 /* module.h - definitions for the module * * Copyright (C) 2004-2010 Gerhard Häring * * This file is part of pysqlite. * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages * arising from the use of this software. * * Permission is granted to anyone to use this software for any purpose, * including commercial applications, and to alter it and redistribute it * freely, subject to the following restrictions: * * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software * in a product, an acknowledgment in the product documentation would be * appreciated but is not required. * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. */ #ifndef PYSQLITE_MODULE_H #define PYSQLITE_MODULE_H #include "Python.h" #define PYSQLITE_VERSION "2.6.3" extern PyObject* pysqlite_Error; extern PyObject* pysqlite_Warning; extern PyObject* pysqlite_InterfaceError; extern PyObject* pysqlite_DatabaseError; extern PyObject* pysqlite_InternalError; extern PyObject* pysqlite_OperationalError; extern PyObject* pysqlite_ProgrammingError; extern PyObject* pysqlite_IntegrityError; extern PyObject* pysqlite_DataError; extern PyObject* pysqlite_NotSupportedError; extern PyObject* pysqlite_OptimizedUnicode; /* the functions time.time() and time.sleep() */ extern PyObject* time_time; extern PyObject* time_sleep; /* A dictionary, mapping colum types (INTEGER, VARCHAR, etc.) to converter * functions, that convert the SQL value to the appropriate Python value. * The key is uppercase. */ extern PyObject* converters; extern int _enable_callback_tracebacks; extern int pysqlite_BaseTypeAdapted; #define PARSE_DECLTYPES 1 #define PARSE_COLNAMES 2 #endif pysqlite-2.6.3/src/prepare_protocol.c000644 000765 000024 00000010504 11343752773 020651 0ustar00ghaeringstaff000000 000000 /* prepare_protocol.c - the protocol for preparing values for SQLite * * Copyright (C) 2005-2010 Gerhard Häring * * This file is part of pysqlite. * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages * arising from the use of this software. * * Permission is granted to anyone to use this software for any purpose, * including commercial applications, and to alter it and redistribute it * freely, subject to the following restrictions: * * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software * in a product, an acknowledgment in the product documentation would be * appreciated but is not required. * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. */ #include "sqlitecompat.h" #include "prepare_protocol.h" int pysqlite_prepare_protocol_init(pysqlite_PrepareProtocol* self, PyObject* args, PyObject* kwargs) { return 0; } void pysqlite_prepare_protocol_dealloc(pysqlite_PrepareProtocol* self) { Py_TYPE(self)->tp_free((PyObject*)self); } PyTypeObject pysqlite_PrepareProtocolType= { PyVarObject_HEAD_INIT(NULL, 0) MODULE_NAME ".PrepareProtocol", /* tp_name */ sizeof(pysqlite_PrepareProtocol), /* tp_basicsize */ 0, /* tp_itemsize */ (destructor)pysqlite_prepare_protocol_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, /* tp_flags */ 0, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ 0, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ (initproc)pysqlite_prepare_protocol_init, /* tp_init */ 0, /* tp_alloc */ 0, /* tp_new */ 0 /* tp_free */ }; extern int pysqlite_prepare_protocol_setup_types(void) { pysqlite_PrepareProtocolType.tp_new = PyType_GenericNew; Py_TYPE(&pysqlite_PrepareProtocolType)= &PyType_Type; return PyType_Ready(&pysqlite_PrepareProtocolType); } pysqlite-2.6.3/src/prepare_protocol.h000644 000765 000024 00000002733 11343727306 020655 0ustar00ghaeringstaff000000 000000 /* prepare_protocol.h - the protocol for preparing values for SQLite * * Copyright (C) 2005-2010 Gerhard Häring * * This file is part of pysqlite. * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages * arising from the use of this software. * * Permission is granted to anyone to use this software for any purpose, * including commercial applications, and to alter it and redistribute it * freely, subject to the following restrictions: * * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software * in a product, an acknowledgment in the product documentation would be * appreciated but is not required. * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. */ #ifndef PYSQLITE_PREPARE_PROTOCOL_H #define PYSQLITE_PREPARE_PROTOCOL_H #include "Python.h" typedef struct { PyObject_HEAD } pysqlite_PrepareProtocol; extern PyTypeObject pysqlite_PrepareProtocolType; int pysqlite_prepare_protocol_init(pysqlite_PrepareProtocol* self, PyObject* args, PyObject* kwargs); void pysqlite_prepare_protocol_dealloc(pysqlite_PrepareProtocol* self); int pysqlite_prepare_protocol_setup_types(void); #define UNKNOWN (-1) #endif pysqlite-2.6.3/src/row.c000644 000765 000024 00000021233 11343727140 016070 0ustar00ghaeringstaff000000 000000 /* row.c - an enhanced tuple for database rows * * Copyright (C) 2005-2010 Gerhard Häring * * This file is part of pysqlite. * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages * arising from the use of this software. * * Permission is granted to anyone to use this software for any purpose, * including commercial applications, and to alter it and redistribute it * freely, subject to the following restrictions: * * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software * in a product, an acknowledgment in the product documentation would be * appreciated but is not required. * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. */ #include "row.h" #include "cursor.h" #include "sqlitecompat.h" void pysqlite_row_dealloc(pysqlite_Row* self) { Py_XDECREF(self->data); Py_XDECREF(self->description); Py_TYPE(self)->tp_free((PyObject*)self); } int pysqlite_row_init(pysqlite_Row* self, PyObject* args, PyObject* kwargs) { PyObject* data; pysqlite_Cursor* cursor; self->data = 0; self->description = 0; if (!PyArg_ParseTuple(args, "OO", &cursor, &data)) { return -1; } if (!PyObject_IsInstance((PyObject*)cursor, (PyObject*)&pysqlite_CursorType)) { PyErr_SetString(PyExc_TypeError, "instance of cursor required for first argument"); return -1; } if (!PyTuple_Check(data)) { PyErr_SetString(PyExc_TypeError, "tuple required for second argument"); return -1; } Py_INCREF(data); self->data = data; Py_INCREF(cursor->description); self->description = cursor->description; return 0; } PyObject* pysqlite_row_subscript(pysqlite_Row* self, PyObject* idx) { long _idx; char* key; int nitems, i; char* compare_key; char* p1; char* p2; PyObject* item; if (PyInt_Check(idx)) { _idx = PyInt_AsLong(idx); item = PyTuple_GetItem(self->data, _idx); Py_XINCREF(item); return item; } else if (PyLong_Check(idx)) { _idx = PyLong_AsLong(idx); item = PyTuple_GetItem(self->data, _idx); Py_XINCREF(item); return item; } else if (PyString_Check(idx)) { key = PyString_AsString(idx); nitems = PyTuple_Size(self->description); for (i = 0; i < nitems; i++) { compare_key = PyString_AsString(PyTuple_GET_ITEM(PyTuple_GET_ITEM(self->description, i), 0)); if (!compare_key) { return NULL; } p1 = key; p2 = compare_key; while (1) { if ((*p1 == (char)0) || (*p2 == (char)0)) { break; } if ((*p1 | 0x20) != (*p2 | 0x20)) { break; } p1++; p2++; } if ((*p1 == (char)0) && (*p2 == (char)0)) { /* found item */ item = PyTuple_GetItem(self->data, i); Py_INCREF(item); return item; } } PyErr_SetString(PyExc_IndexError, "No item with that key"); return NULL; } else if (PySlice_Check(idx)) { PyErr_SetString(PyExc_ValueError, "slices not implemented, yet"); return NULL; } else { PyErr_SetString(PyExc_IndexError, "Index must be int or string"); return NULL; } } Py_ssize_t pysqlite_row_length(pysqlite_Row* self, PyObject* args, PyObject* kwargs) { return PyTuple_GET_SIZE(self->data); } PyObject* pysqlite_row_keys(pysqlite_Row* self, PyObject* args, PyObject* kwargs) { PyObject* list; int nitems, i; list = PyList_New(0); if (!list) { return NULL; } nitems = PyTuple_Size(self->description); for (i = 0; i < nitems; i++) { if (PyList_Append(list, PyTuple_GET_ITEM(PyTuple_GET_ITEM(self->description, i), 0)) != 0) { Py_DECREF(list); return NULL; } } return list; } static int pysqlite_row_print(pysqlite_Row* self, FILE *fp, int flags) { return (&PyTuple_Type)->tp_print(self->data, fp, flags); } static PyObject* pysqlite_iter(pysqlite_Row* self) { return PyObject_GetIter(self->data); } static long pysqlite_row_hash(pysqlite_Row *self) { return PyObject_Hash(self->description) ^ PyObject_Hash(self->data); } static PyObject* pysqlite_row_richcompare(pysqlite_Row *self, PyObject *_other, int opid) { if (opid != Py_EQ && opid != Py_NE) { Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } if (PyType_IsSubtype(Py_TYPE(_other), &pysqlite_RowType)) { pysqlite_Row *other = (pysqlite_Row *)_other; PyObject *res = PyObject_RichCompare(self->description, other->description, opid); if ((opid == Py_EQ && res == Py_True) || (opid == Py_NE && res == Py_False)) { Py_DECREF(res); return PyObject_RichCompare(self->data, other->data, opid); } } Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } PyMappingMethods pysqlite_row_as_mapping = { /* mp_length */ (lenfunc)pysqlite_row_length, /* mp_subscript */ (binaryfunc)pysqlite_row_subscript, /* mp_ass_subscript */ (objobjargproc)0, }; static PyMethodDef pysqlite_row_methods[] = { {"keys", (PyCFunction)pysqlite_row_keys, METH_NOARGS, PyDoc_STR("Returns the keys of the row.")}, {NULL, NULL} }; PyTypeObject pysqlite_RowType = { PyVarObject_HEAD_INIT(NULL, 0) MODULE_NAME ".Row", /* tp_name */ sizeof(pysqlite_Row), /* tp_basicsize */ 0, /* tp_itemsize */ (destructor)pysqlite_row_dealloc, /* tp_dealloc */ (printfunc)pysqlite_row_print, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ (hashfunc)pysqlite_row_hash, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /* tp_flags */ 0, /* tp_doc */ (traverseproc)0, /* tp_traverse */ 0, /* tp_clear */ (richcmpfunc)pysqlite_row_richcompare, /* tp_richcompare */ 0, /* tp_weaklistoffset */ (getiterfunc)pysqlite_iter, /* tp_iter */ 0, /* tp_iternext */ pysqlite_row_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ (initproc)pysqlite_row_init, /* tp_init */ 0, /* tp_alloc */ 0, /* tp_new */ 0 /* tp_free */ }; extern int pysqlite_row_setup_types(void) { pysqlite_RowType.tp_new = PyType_GenericNew; pysqlite_RowType.tp_as_mapping = &pysqlite_row_as_mapping; return PyType_Ready(&pysqlite_RowType); } pysqlite-2.6.3/src/row.h000644 000765 000024 00000002366 11343727313 016105 0ustar00ghaeringstaff000000 000000 /* row.h - an enhanced tuple for database rows * * Copyright (C) 2005-2010 Gerhard Häring * * This file is part of pysqlite. * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages * arising from the use of this software. * * Permission is granted to anyone to use this software for any purpose, * including commercial applications, and to alter it and redistribute it * freely, subject to the following restrictions: * * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software * in a product, an acknowledgment in the product documentation would be * appreciated but is not required. * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. */ #ifndef PYSQLITE_ROW_H #define PYSQLITE_ROW_H #include "Python.h" typedef struct _Row { PyObject_HEAD PyObject* data; PyObject* description; } pysqlite_Row; extern PyTypeObject pysqlite_RowType; int pysqlite_row_setup_types(void); #endif pysqlite-2.6.3/src/sqlitecompat.h000644 000765 000024 00000003631 11343753055 020001 0ustar00ghaeringstaff000000 000000 /* sqlitecompat.h - compatibility macros * * Copyright (C) 2006-2010 Gerhard Häring * * This file is part of pysqlite. * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages * arising from the use of this software. * * Permission is granted to anyone to use this software for any purpose, * including commercial applications, and to alter it and redistribute it * freely, subject to the following restrictions: * * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software * in a product, an acknowledgment in the product documentation would be * appreciated but is not required. * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. */ #include "Python.h" #ifndef PYSQLITE_COMPAT_H #define PYSQLITE_COMPAT_H /* define Py_ssize_t for pre-2.5 versions of Python */ #if PY_VERSION_HEX < 0x02050000 typedef int Py_ssize_t; typedef int (*lenfunc)(PyObject*); #endif /* define PyDict_CheckExact for pre-2.4 versions of Python */ #ifndef PyDict_CheckExact #define PyDict_CheckExact(op) ((op)->ob_type == &PyDict_Type) #endif /* define Py_CLEAR for pre-2.4 versions of Python */ #ifndef Py_CLEAR #define Py_CLEAR(op) \ do { \ if (op) { \ PyObject *tmp = (PyObject *)(op); \ (op) = NULL; \ Py_DECREF(tmp); \ } \ } while (0) #endif #ifndef PyVarObject_HEAD_INIT #define PyVarObject_HEAD_INIT(type, size) \ PyObject_HEAD_INIT(type) size, #endif #ifndef Py_TYPE #define Py_TYPE(ob) ((ob)->ob_type) #endif #endif pysqlite-2.6.3/src/statement.c000644 000765 000024 00000043631 11343745060 017274 0ustar00ghaeringstaff000000 000000 /* statement.c - the statement type * * Copyright (C) 2005-2010 Gerhard Häring * * This file is part of pysqlite. * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages * arising from the use of this software. * * Permission is granted to anyone to use this software for any purpose, * including commercial applications, and to alter it and redistribute it * freely, subject to the following restrictions: * * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software * in a product, an acknowledgment in the product documentation would be * appreciated but is not required. * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. */ #include "statement.h" #include "cursor.h" #include "connection.h" #include "microprotocols.h" #include "prepare_protocol.h" #include "sqlitecompat.h" /* prototypes */ static int pysqlite_check_remaining_sql(const char* tail); typedef enum { LINECOMMENT_1, IN_LINECOMMENT, COMMENTSTART_1, IN_COMMENT, COMMENTEND_1, NORMAL } parse_remaining_sql_state; typedef enum { TYPE_INT, TYPE_LONG, TYPE_FLOAT, TYPE_STRING, TYPE_UNICODE, TYPE_BUFFER, TYPE_UNKNOWN } parameter_type; int pysqlite_statement_create(pysqlite_Statement* self, pysqlite_Connection* connection, PyObject* sql) { const char* tail; int rc; PyObject* sql_str; char* sql_cstr; self->st = NULL; self->in_use = 0; if (PyString_Check(sql)) { sql_str = sql; Py_INCREF(sql_str); } else if (PyUnicode_Check(sql)) { sql_str = PyUnicode_AsUTF8String(sql); if (!sql_str) { rc = PYSQLITE_SQL_WRONG_TYPE; return rc; } } else { rc = PYSQLITE_SQL_WRONG_TYPE; return rc; } self->in_weakreflist = NULL; self->sql = sql_str; sql_cstr = PyString_AsString(sql_str); Py_BEGIN_ALLOW_THREADS rc = sqlite3_prepare(connection->db, sql_cstr, -1, &self->st, &tail); Py_END_ALLOW_THREADS self->db = connection->db; if (rc == SQLITE_OK && pysqlite_check_remaining_sql(tail)) { (void)sqlite3_finalize(self->st); self->st = NULL; rc = PYSQLITE_TOO_MUCH_SQL; } return rc; } int pysqlite_statement_bind_parameter(pysqlite_Statement* self, int pos, PyObject* parameter, int allow_8bit_chars) { int rc = SQLITE_OK; long longval; PY_LONG_LONG longlongval; const char* buffer; char* string; Py_ssize_t buflen; PyObject* stringval; parameter_type paramtype; char* c; if (parameter == Py_None) { rc = sqlite3_bind_null(self->st, pos); goto final; } if (PyInt_CheckExact(parameter)) { paramtype = TYPE_INT; } else if (PyLong_CheckExact(parameter)) { paramtype = TYPE_LONG; } else if (PyFloat_CheckExact(parameter)) { paramtype = TYPE_FLOAT; } else if (PyString_CheckExact(parameter)) { paramtype = TYPE_STRING; } else if (PyUnicode_CheckExact(parameter)) { paramtype = TYPE_UNICODE; } else if (PyBuffer_Check(parameter)) { paramtype = TYPE_BUFFER; } else if (PyInt_Check(parameter)) { paramtype = TYPE_INT; } else if (PyLong_Check(parameter)) { paramtype = TYPE_LONG; } else if (PyFloat_Check(parameter)) { paramtype = TYPE_FLOAT; } else if (PyString_Check(parameter)) { paramtype = TYPE_STRING; } else if (PyUnicode_Check(parameter)) { paramtype = TYPE_UNICODE; } else { paramtype = TYPE_UNKNOWN; } if (paramtype == TYPE_STRING && !allow_8bit_chars) { string = PyString_AS_STRING(parameter); for (c = string; *c != 0; c++) { if (*c & 0x80) { PyErr_SetString(pysqlite_ProgrammingError, "You must not use 8-bit bytestrings unless you use a text_factory that can interpret 8-bit bytestrings (like text_factory = str). It is highly recommended that you instead just switch your application to Unicode strings."); rc = -1; goto final; } } } switch (paramtype) { case TYPE_INT: longval = PyInt_AsLong(parameter); rc = sqlite3_bind_int64(self->st, pos, (sqlite_int64)longval); break; case TYPE_LONG: longlongval = PyLong_AsLongLong(parameter); /* in the overflow error case, longlongval is -1, and an exception is set */ rc = sqlite3_bind_int64(self->st, pos, (sqlite_int64)longlongval); break; case TYPE_FLOAT: rc = sqlite3_bind_double(self->st, pos, PyFloat_AsDouble(parameter)); break; case TYPE_STRING: string = PyString_AS_STRING(parameter); rc = sqlite3_bind_text(self->st, pos, string, -1, SQLITE_TRANSIENT); break; case TYPE_UNICODE: stringval = PyUnicode_AsUTF8String(parameter); string = PyString_AsString(stringval); rc = sqlite3_bind_text(self->st, pos, string, -1, SQLITE_TRANSIENT); Py_DECREF(stringval); break; case TYPE_BUFFER: if (PyObject_AsCharBuffer(parameter, &buffer, &buflen) == 0) { rc = sqlite3_bind_blob(self->st, pos, buffer, buflen, SQLITE_TRANSIENT); } else { PyErr_SetString(PyExc_ValueError, "could not convert BLOB to buffer"); rc = -1; } break; case TYPE_UNKNOWN: rc = -1; } final: return rc; } /* returns 0 if the object is one of Python's internal ones that don't need to be adapted */ static int _need_adapt(PyObject* obj) { if (pysqlite_BaseTypeAdapted) { return 1; } if (PyInt_CheckExact(obj) || PyLong_CheckExact(obj) || PyFloat_CheckExact(obj) || PyString_CheckExact(obj) || PyUnicode_CheckExact(obj) || PyBuffer_Check(obj)) { return 0; } else { return 1; } } void pysqlite_statement_bind_parameters(pysqlite_Statement* self, PyObject* parameters, int allow_8bit_chars) { PyObject* current_param; PyObject* adapted; const char* binding_name; int i; int rc; int num_params_needed; int num_params; Py_BEGIN_ALLOW_THREADS num_params_needed = sqlite3_bind_parameter_count(self->st); Py_END_ALLOW_THREADS if (PyTuple_CheckExact(parameters) || PyList_CheckExact(parameters) || (!PyDict_Check(parameters) && PySequence_Check(parameters))) { /* parameters passed as sequence */ if (PyTuple_CheckExact(parameters)) { num_params = PyTuple_GET_SIZE(parameters); } else if (PyList_CheckExact(parameters)) { num_params = PyList_GET_SIZE(parameters); } else { num_params = PySequence_Size(parameters); } if (num_params != num_params_needed) { PyErr_Format(pysqlite_ProgrammingError, "Incorrect number of bindings supplied. The current statement uses %d, and there are %d supplied.", num_params_needed, num_params); return; } for (i = 0; i < num_params; i++) { if (PyTuple_CheckExact(parameters)) { current_param = PyTuple_GET_ITEM(parameters, i); Py_XINCREF(current_param); } else if (PyList_CheckExact(parameters)) { current_param = PyList_GET_ITEM(parameters, i); Py_XINCREF(current_param); } else { current_param = PySequence_GetItem(parameters, i); } if (!current_param) { return; } if (!_need_adapt(current_param)) { adapted = current_param; } else { adapted = pysqlite_microprotocols_adapt(current_param, (PyObject*)&pysqlite_PrepareProtocolType, NULL); if (adapted) { Py_DECREF(current_param); } else { PyErr_Clear(); adapted = current_param; } } rc = pysqlite_statement_bind_parameter(self, i + 1, adapted, allow_8bit_chars); Py_DECREF(adapted); if (rc != SQLITE_OK) { if (!PyErr_Occurred()) { PyErr_Format(pysqlite_InterfaceError, "Error binding parameter %d - probably unsupported type.", i); } return; } } } else if (PyDict_Check(parameters)) { /* parameters passed as dictionary */ for (i = 1; i <= num_params_needed; i++) { Py_BEGIN_ALLOW_THREADS binding_name = sqlite3_bind_parameter_name(self->st, i); Py_END_ALLOW_THREADS if (!binding_name) { PyErr_Format(pysqlite_ProgrammingError, "Binding %d has no name, but you supplied a dictionary (which has only names).", i); return; } binding_name++; /* skip first char (the colon) */ if (PyDict_CheckExact(parameters)) { current_param = PyDict_GetItemString(parameters, binding_name); Py_XINCREF(current_param); } else { current_param = PyMapping_GetItemString(parameters, (char*)binding_name); } if (!current_param) { PyErr_Format(pysqlite_ProgrammingError, "You did not supply a value for binding %d.", i); return; } if (!_need_adapt(current_param)) { adapted = current_param; } else { adapted = pysqlite_microprotocols_adapt(current_param, (PyObject*)&pysqlite_PrepareProtocolType, NULL); if (adapted) { Py_DECREF(current_param); } else { PyErr_Clear(); adapted = current_param; } } rc = pysqlite_statement_bind_parameter(self, i, adapted, allow_8bit_chars); Py_DECREF(adapted); if (rc != SQLITE_OK) { if (!PyErr_Occurred()) { PyErr_Format(pysqlite_InterfaceError, "Error binding parameter :%s - probably unsupported type.", binding_name); } return; } } } else { PyErr_SetString(PyExc_ValueError, "parameters are of unsupported type"); } } int pysqlite_statement_recompile(pysqlite_Statement* self, PyObject* params) { const char* tail; int rc; char* sql_cstr; sqlite3_stmt* new_st; sql_cstr = PyString_AsString(self->sql); Py_BEGIN_ALLOW_THREADS rc = sqlite3_prepare(self->db, sql_cstr, -1, &new_st, &tail); Py_END_ALLOW_THREADS if (rc == SQLITE_OK) { /* The efficient sqlite3_transfer_bindings is only available in SQLite * version 3.2.2 or later. For older SQLite releases, that might not * even define SQLITE_VERSION_NUMBER, we do it the manual way. */ #ifdef SQLITE_VERSION_NUMBER #if SQLITE_VERSION_NUMBER >= 3002002 /* The check for the number of parameters is necessary to not trigger a * bug in certain SQLite versions (experienced in 3.2.8 and 3.3.4). */ if (sqlite3_bind_parameter_count(self->st) > 0) { (void)sqlite3_transfer_bindings(self->st, new_st); } #endif #else statement_bind_parameters(self, params); #endif (void)sqlite3_finalize(self->st); self->st = new_st; } return rc; } int pysqlite_statement_finalize(pysqlite_Statement* self) { int rc; rc = SQLITE_OK; if (self->st) { Py_BEGIN_ALLOW_THREADS rc = sqlite3_finalize(self->st); Py_END_ALLOW_THREADS self->st = NULL; } self->in_use = 0; return rc; } int pysqlite_statement_reset(pysqlite_Statement* self) { int rc; rc = SQLITE_OK; if (self->in_use && self->st) { Py_BEGIN_ALLOW_THREADS rc = sqlite3_reset(self->st); Py_END_ALLOW_THREADS if (rc == SQLITE_OK) { self->in_use = 0; } } return rc; } void pysqlite_statement_mark_dirty(pysqlite_Statement* self) { self->in_use = 1; } void pysqlite_statement_dealloc(pysqlite_Statement* self) { int rc; if (self->st) { Py_BEGIN_ALLOW_THREADS rc = sqlite3_finalize(self->st); Py_END_ALLOW_THREADS } self->st = NULL; Py_XDECREF(self->sql); if (self->in_weakreflist != NULL) { PyObject_ClearWeakRefs((PyObject*)self); } Py_TYPE(self)->tp_free((PyObject*)self); } /* * Checks if there is anything left in an SQL string after SQLite compiled it. * This is used to check if somebody tried to execute more than one SQL command * with one execute()/executemany() command, which the DB-API and we don't * allow. * * Returns 1 if there is more left than should be. 0 if ok. */ static int pysqlite_check_remaining_sql(const char* tail) { const char* pos = tail; parse_remaining_sql_state state = NORMAL; for (;;) { switch (*pos) { case 0: return 0; case '-': if (state == NORMAL) { state = LINECOMMENT_1; } else if (state == LINECOMMENT_1) { state = IN_LINECOMMENT; } break; case ' ': case '\t': break; case '\n': case 13: if (state == IN_LINECOMMENT) { state = NORMAL; } break; case '/': if (state == NORMAL) { state = COMMENTSTART_1; } else if (state == COMMENTEND_1) { state = NORMAL; } else if (state == COMMENTSTART_1) { return 1; } break; case '*': if (state == NORMAL) { return 1; } else if (state == LINECOMMENT_1) { return 1; } else if (state == COMMENTSTART_1) { state = IN_COMMENT; } else if (state == IN_COMMENT) { state = COMMENTEND_1; } break; default: if (state == COMMENTEND_1) { state = IN_COMMENT; } else if (state == IN_LINECOMMENT) { } else if (state == IN_COMMENT) { } else { return 1; } } pos++; } return 0; } PyTypeObject pysqlite_StatementType = { PyVarObject_HEAD_INIT(NULL, 0) MODULE_NAME ".Statement", /* tp_name */ sizeof(pysqlite_Statement), /* tp_basicsize */ 0, /* tp_itemsize */ (destructor)pysqlite_statement_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */ 0, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ offsetof(pysqlite_Statement, in_weakreflist), /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ 0, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ (initproc)0, /* tp_init */ 0, /* tp_alloc */ 0, /* tp_new */ 0 /* tp_free */ }; extern int pysqlite_statement_setup_types(void) { pysqlite_StatementType.tp_new = PyType_GenericNew; return PyType_Ready(&pysqlite_StatementType); } pysqlite-2.6.3/src/statement.h000644 000765 000024 00000004164 11343727323 017301 0ustar00ghaeringstaff000000 000000 /* statement.h - definitions for the statement type * * Copyright (C) 2005-2010 Gerhard Häring * * This file is part of pysqlite. * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages * arising from the use of this software. * * Permission is granted to anyone to use this software for any purpose, * including commercial applications, and to alter it and redistribute it * freely, subject to the following restrictions: * * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software * in a product, an acknowledgment in the product documentation would be * appreciated but is not required. * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. */ #ifndef PYSQLITE_STATEMENT_H #define PYSQLITE_STATEMENT_H #include "Python.h" #include "connection.h" #include "sqlite3.h" #define PYSQLITE_TOO_MUCH_SQL (-100) #define PYSQLITE_SQL_WRONG_TYPE (-101) typedef struct { PyObject_HEAD sqlite3* db; sqlite3_stmt* st; PyObject* sql; int in_use; PyObject* in_weakreflist; /* List of weak references */ } pysqlite_Statement; extern PyTypeObject pysqlite_StatementType; int pysqlite_statement_create(pysqlite_Statement* self, pysqlite_Connection* connection, PyObject* sql); void pysqlite_statement_dealloc(pysqlite_Statement* self); int pysqlite_statement_bind_parameter(pysqlite_Statement* self, int pos, PyObject* parameter, int allow_8bit_chars); void pysqlite_statement_bind_parameters(pysqlite_Statement* self, PyObject* parameters, int allow_8bit_chars); int pysqlite_statement_recompile(pysqlite_Statement* self, PyObject* parameters); int pysqlite_statement_finalize(pysqlite_Statement* self); int pysqlite_statement_reset(pysqlite_Statement* self); void pysqlite_statement_mark_dirty(pysqlite_Statement* self); int pysqlite_statement_setup_types(void); #endif pysqlite-2.6.3/src/util.c000644 000765 000024 00000006366 11343745075 016257 0ustar00ghaeringstaff000000 000000 /* util.c - various utility functions * * Copyright (C) 2005-2010 Gerhard Häring * * This file is part of pysqlite. * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages * arising from the use of this software. * * Permission is granted to anyone to use this software for any purpose, * including commercial applications, and to alter it and redistribute it * freely, subject to the following restrictions: * * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software * in a product, an acknowledgment in the product documentation would be * appreciated but is not required. * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. */ #include "module.h" #include "connection.h" int pysqlite_step(sqlite3_stmt* statement, pysqlite_Connection* connection) { int rc; if (statement == NULL) { /* this is a workaround for SQLite 3.5 and later. it now apparently * returns NULL for "no-operation" statements */ rc = SQLITE_OK; } else { Py_BEGIN_ALLOW_THREADS rc = sqlite3_step(statement); Py_END_ALLOW_THREADS } return rc; } /** * Checks the SQLite error code and sets the appropriate DB-API exception. * Returns the error code (0 means no error occurred). */ int _pysqlite_seterror(sqlite3* db, sqlite3_stmt* st) { int errorcode; /* SQLite often doesn't report anything useful, unless you reset the statement first */ if (st != NULL) { (void)sqlite3_reset(st); } errorcode = sqlite3_errcode(db); switch (errorcode) { case SQLITE_OK: PyErr_Clear(); break; case SQLITE_INTERNAL: case SQLITE_NOTFOUND: PyErr_SetString(pysqlite_InternalError, sqlite3_errmsg(db)); break; case SQLITE_NOMEM: (void)PyErr_NoMemory(); break; case SQLITE_ERROR: case SQLITE_PERM: case SQLITE_ABORT: case SQLITE_BUSY: case SQLITE_LOCKED: case SQLITE_READONLY: case SQLITE_INTERRUPT: case SQLITE_IOERR: case SQLITE_FULL: case SQLITE_CANTOPEN: case SQLITE_PROTOCOL: case SQLITE_EMPTY: case SQLITE_SCHEMA: PyErr_SetString(pysqlite_OperationalError, sqlite3_errmsg(db)); break; case SQLITE_CORRUPT: PyErr_SetString(pysqlite_DatabaseError, sqlite3_errmsg(db)); break; case SQLITE_TOOBIG: PyErr_SetString(pysqlite_DataError, sqlite3_errmsg(db)); break; case SQLITE_CONSTRAINT: case SQLITE_MISMATCH: PyErr_SetString(pysqlite_IntegrityError, sqlite3_errmsg(db)); break; case SQLITE_MISUSE: PyErr_SetString(pysqlite_ProgrammingError, sqlite3_errmsg(db)); break; default: PyErr_SetString(pysqlite_DatabaseError, sqlite3_errmsg(db)); break; } return errorcode; } pysqlite-2.6.3/src/util.h000644 000765 000024 00000002615 11343727330 016247 0ustar00ghaeringstaff000000 000000 /* util.h - various utility functions * * Copyright (C) 2005-2010 Gerhard Häring * * This file is part of pysqlite. * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages * arising from the use of this software. * * Permission is granted to anyone to use this software for any purpose, * including commercial applications, and to alter it and redistribute it * freely, subject to the following restrictions: * * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software * in a product, an acknowledgment in the product documentation would be * appreciated but is not required. * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. */ #ifndef PYSQLITE_UTIL_H #define PYSQLITE_UTIL_H #include "Python.h" #include "pythread.h" #include "sqlite3.h" #include "connection.h" int pysqlite_step(sqlite3_stmt* statement, pysqlite_Connection* connection); /** * Checks the SQLite error code and sets the appropriate DB-API exception. * Returns the error code (0 means no error occurred). */ int _pysqlite_seterror(sqlite3* db, sqlite3_stmt* st); #endif pysqlite-2.6.3/lib/__init__.py000644 000765 000024 00000001774 11343657406 017224 0ustar00ghaeringstaff000000 000000 #-*- coding: ISO-8859-1 -*- # pysqlite2/__init__.py: the pysqlite2 package. # # Copyright (C) 2005-2007 Gerhard Häring # # This file is part of pysqlite. # # This software is provided 'as-is', without any express or implied # warranty. In no event will the authors be held liable for any damages # arising from the use of this software. # # Permission is granted to anyone to use this software for any purpose, # including commercial applications, and to alter it and redistribute it # freely, subject to the following restrictions: # # 1. The origin of this software must not be misrepresented; you must not # claim that you wrote the original software. If you use this software # in a product, an acknowledgment in the product documentation would be # appreciated but is not required. # 2. Altered source versions must be plainly marked as such, and must not be # misrepresented as being the original software. # 3. This notice may not be removed or altered from any source distribution. pysqlite-2.6.3/lib/dbapi2.py000644 000765 000024 00000005100 11343755340 016605 0ustar00ghaeringstaff000000 000000 #-*- coding: ISO-8859-1 -*- # pysqlite2/dbapi2.py: the DB-API 2.0 interface # # Copyright (C) 2004-2007 Gerhard Häring # # This file is part of pysqlite. # # This software is provided 'as-is', without any express or implied # warranty. In no event will the authors be held liable for any damages # arising from the use of this software. # # Permission is granted to anyone to use this software for any purpose, # including commercial applications, and to alter it and redistribute it # freely, subject to the following restrictions: # # 1. The origin of this software must not be misrepresented; you must not # claim that you wrote the original software. If you use this software # in a product, an acknowledgment in the product documentation would be # appreciated but is not required. # 2. Altered source versions must be plainly marked as such, and must not be # misrepresented as being the original software. # 3. This notice may not be removed or altered from any source distribution. import datetime import time from pysqlite2._sqlite import * paramstyle = "qmark" threadsafety = 1 apilevel = "2.0" Date = datetime.date Time = datetime.time Timestamp = datetime.datetime def DateFromTicks(ticks): return Date(*time.localtime(ticks)[:3]) def TimeFromTicks(ticks): return Time(*time.localtime(ticks)[3:6]) def TimestampFromTicks(ticks): return Timestamp(*time.localtime(ticks)[:6]) version_info = tuple([int(x) for x in version.split(".")]) sqlite_version_info = tuple([int(x) for x in sqlite_version.split(".")]) Binary = buffer def register_adapters_and_converters(): def adapt_date(val): return val.isoformat() def adapt_datetime(val): return val.isoformat(" ") def convert_date(val): return datetime.date(*map(int, val.split("-"))) def convert_timestamp(val): datepart, timepart = val.split(" ") year, month, day = map(int, datepart.split("-")) timepart_full = timepart.split(".") hours, minutes, seconds = map(int, timepart_full[0].split(":")) if len(timepart_full) == 2: microseconds = int(timepart_full[1]) else: microseconds = 0 val = datetime.datetime(year, month, day, hours, minutes, seconds, microseconds) return val register_adapter(datetime.date, adapt_date) register_adapter(datetime.datetime, adapt_datetime) register_converter("date", convert_date) register_converter("timestamp", convert_timestamp) register_adapters_and_converters() # Clean up namespace del(register_adapters_and_converters) pysqlite-2.6.3/lib/dump.py000644 000765 000024 00000004456 11454047653 016432 0ustar00ghaeringstaff000000 000000 # Mimic the sqlite3 console shell's .dump command # Author: Paul Kippes def _iterdump(connection): """ Returns an iterator to the dump of the database in an SQL text format. Used to produce an SQL dump of the database. Useful to save an in-memory database for later restoration. This function should not be called directly but instead called from the Connection method, iterdump(). """ cu = connection.cursor() yield('BEGIN TRANSACTION;') # sqlite_master table contains the SQL CREATE statements for the database. q = """ SELECT name, type, sql FROM sqlite_master WHERE sql NOT NULL AND type == 'table' """ schema_res = cu.execute(q) for table_name, type, sql in schema_res.fetchall(): if table_name == 'sqlite_sequence': yield('DELETE FROM sqlite_sequence;') elif table_name == 'sqlite_stat1': yield('ANALYZE sqlite_master;') elif table_name.startswith('sqlite_'): continue # NOTE: Virtual table support not implemented #elif sql.startswith('CREATE VIRTUAL TABLE'): # qtable = table_name.replace("'", "''") # yield("INSERT INTO sqlite_master(type,name,tbl_name,rootpage,sql)"\ # "VALUES('table','%s','%s',0,'%s');" % # qtable, # qtable, # sql.replace("''")) else: yield('%s;' % sql) # Build the insert statement for each row of the current table res = cu.execute("PRAGMA table_info('%s')" % table_name) column_names = [str(table_info[1]) for table_info in res.fetchall()] q = "SELECT 'INSERT INTO \"%(tbl_name)s\" VALUES(" q += ",".join(["'||quote(" + col + ")||'" for col in column_names]) q += ")' FROM '%(tbl_name)s'" query_res = cu.execute(q % {'tbl_name': table_name}) for row in query_res: yield("%s;" % row[0]) # Now when the type is 'index', 'trigger', or 'view' q = """ SELECT name, type, sql FROM sqlite_master WHERE sql NOT NULL AND type IN ('index', 'trigger', 'view') """ schema_res = cu.execute(q) for name, type, sql in schema_res.fetchall(): yield('%s;' % sql) yield('COMMIT;') pysqlite-2.6.3/lib/test/000755 000765 000024 00000000000 11526730255 016056 5ustar00ghaeringstaff000000 000000 pysqlite-2.6.3/lib/test/__init__.py000644 000765 000024 00000003656 11343657406 020204 0ustar00ghaeringstaff000000 000000 #-*- coding: ISO-8859-1 -*- # pysqlite2/test/__init__.py: the package containing the test suite # # Copyright (C) 2004-2007 Gerhard Häring # # This file is part of pysqlite. # # This software is provided 'as-is', without any express or implied # warranty. In no event will the authors be held liable for any damages # arising from the use of this software. # # Permission is granted to anyone to use this software for any purpose, # including commercial applications, and to alter it and redistribute it # freely, subject to the following restrictions: # # 1. The origin of this software must not be misrepresented; you must not # claim that you wrote the original software. If you use this software # in a product, an acknowledgment in the product documentation would be # appreciated but is not required. # 2. Altered source versions must be plainly marked as such, and must not be # misrepresented as being the original software. # 3. This notice may not be removed or altered from any source distribution. import os, sys import unittest if os.path.exists("extended_setup.py"): print "-" * 75 print "You should not run the test suite from the pysqlite build directory." print "This does not work well because the extension module cannot be found." print "Just run the test suite from somewhere else, please!" print "-" * 75 sys.exit(1) from pysqlite2.test import dbapi, types, userfunctions, factory, transactions,\ hooks, regression, dump from pysqlite2 import dbapi2 as sqlite def suite(): tests = [dbapi.suite(), types.suite(), userfunctions.suite(), factory.suite(), transactions.suite(), hooks.suite(), regression.suite(), dump.suite()] if sys.version_info >= (2, 5, 0): from pysqlite2.test.py25 import py25tests tests.append(py25tests.suite()) return unittest.TestSuite(tuple(tests)) def test(): runner = unittest.TextTestRunner() runner.run(suite()) pysqlite-2.6.3/lib/test/dbapi.py000644 000765 000024 00000072276 11426544661 017530 0ustar00ghaeringstaff000000 000000 #-*- coding: ISO-8859-1 -*- # pysqlite2/test/dbapi.py: tests for DB-API compliance # # Copyright (C) 2004-2009 Gerhard Häring # # This file is part of pysqlite. # # This software is provided 'as-is', without any express or implied # warranty. In no event will the authors be held liable for any damages # arising from the use of this software. # # Permission is granted to anyone to use this software for any purpose, # including commercial applications, and to alter it and redistribute it # freely, subject to the following restrictions: # # 1. The origin of this software must not be misrepresented; you must not # claim that you wrote the original software. If you use this software # in a product, an acknowledgment in the product documentation would be # appreciated but is not required. # 2. Altered source versions must be plainly marked as such, and must not be # misrepresented as being the original software. # 3. This notice may not be removed or altered from any source distribution. import unittest import sys import threading import pysqlite2.dbapi2 as sqlite class ModuleTests(unittest.TestCase): def CheckAPILevel(self): self.assertEqual(sqlite.apilevel, "2.0", "apilevel is %s, should be 2.0" % sqlite.apilevel) def CheckThreadSafety(self): self.assertEqual(sqlite.threadsafety, 1, "threadsafety is %d, should be 1" % sqlite.threadsafety) def CheckParamStyle(self): self.assertEqual(sqlite.paramstyle, "qmark", "paramstyle is '%s', should be 'qmark'" % sqlite.paramstyle) def CheckWarning(self): self.assert_(issubclass(sqlite.Warning, StandardError), "Warning is not a subclass of StandardError") def CheckError(self): self.assertTrue(issubclass(sqlite.Error, StandardError), "Error is not a subclass of StandardError") def CheckInterfaceError(self): self.assertTrue(issubclass(sqlite.InterfaceError, sqlite.Error), "InterfaceError is not a subclass of Error") def CheckDatabaseError(self): self.assertTrue(issubclass(sqlite.DatabaseError, sqlite.Error), "DatabaseError is not a subclass of Error") def CheckDataError(self): self.assertTrue(issubclass(sqlite.DataError, sqlite.DatabaseError), "DataError is not a subclass of DatabaseError") def CheckOperationalError(self): self.assertTrue(issubclass(sqlite.OperationalError, sqlite.DatabaseError), "OperationalError is not a subclass of DatabaseError") def CheckIntegrityError(self): self.assertTrue(issubclass(sqlite.IntegrityError, sqlite.DatabaseError), "IntegrityError is not a subclass of DatabaseError") def CheckInternalError(self): self.assertTrue(issubclass(sqlite.InternalError, sqlite.DatabaseError), "InternalError is not a subclass of DatabaseError") def CheckProgrammingError(self): self.assertTrue(issubclass(sqlite.ProgrammingError, sqlite.DatabaseError), "ProgrammingError is not a subclass of DatabaseError") def CheckNotSupportedError(self): self.assertTrue(issubclass(sqlite.NotSupportedError, sqlite.DatabaseError), "NotSupportedError is not a subclass of DatabaseError") class ConnectionTests(unittest.TestCase): def setUp(self): self.cx = sqlite.connect(":memory:") cu = self.cx.cursor() cu.execute("create table test(id integer primary key, name text)") cu.execute("insert into test(name) values (?)", ("foo",)) def tearDown(self): self.cx.close() def CheckCommit(self): self.cx.commit() def CheckCommitAfterNoChanges(self): """ A commit should also work when no changes were made to the database. """ self.cx.commit() self.cx.commit() def CheckRollback(self): self.cx.rollback() def CheckRollbackAfterNoChanges(self): """ A rollback should also work when no changes were made to the database. """ self.cx.rollback() self.cx.rollback() def CheckCursor(self): cu = self.cx.cursor() def CheckFailedOpen(self): YOU_CANNOT_OPEN_THIS = "/foo/bar/bla/23534/mydb.db" try: con = sqlite.connect(YOU_CANNOT_OPEN_THIS) except sqlite.OperationalError: return self.fail("should have raised an OperationalError") def CheckClose(self): self.cx.close() def CheckExceptions(self): # Optional DB-API extension. self.assertEqual(self.cx.Warning, sqlite.Warning) self.assertEqual(self.cx.Error, sqlite.Error) self.assertEqual(self.cx.InterfaceError, sqlite.InterfaceError) self.assertEqual(self.cx.DatabaseError, sqlite.DatabaseError) self.assertEqual(self.cx.DataError, sqlite.DataError) self.assertEqual(self.cx.OperationalError, sqlite.OperationalError) self.assertEqual(self.cx.IntegrityError, sqlite.IntegrityError) self.assertEqual(self.cx.InternalError, sqlite.InternalError) self.assertEqual(self.cx.ProgrammingError, sqlite.ProgrammingError) self.assertEqual(self.cx.NotSupportedError, sqlite.NotSupportedError) class CursorTests(unittest.TestCase): def setUp(self): self.cx = sqlite.connect(":memory:") self.cu = self.cx.cursor() self.cu.execute("create table test(id integer primary key, name text, income number)") self.cu.execute("insert into test(name) values (?)", ("foo",)) def tearDown(self): self.cu.close() self.cx.close() def CheckExecuteNoArgs(self): self.cu.execute("delete from test") def CheckExecuteIllegalSql(self): try: self.cu.execute("select asdf") self.fail("should have raised an OperationalError") except sqlite.OperationalError: return except: self.fail("raised wrong exception") def CheckExecuteTooMuchSql(self): try: self.cu.execute("select 5+4; select 4+5") self.fail("should have raised a ProgrammingError") except sqlite.ProgrammingError: return except: self.fail("raised wrong exception") def CheckExecuteTooMuchSql2(self): self.cu.execute("select 5+4; -- foo bar") def CheckExecuteTooMuchSql3(self): self.cu.execute(""" select 5+4; /* foo */ """) def CheckExecuteWrongSqlArg(self): try: self.cu.execute(42) self.fail("should have raised a ValueError") except ValueError: return except: self.fail("raised wrong exception.") def CheckExecuteArgInt(self): self.cu.execute("insert into test(id) values (?)", (42,)) def CheckExecuteArgFloat(self): self.cu.execute("insert into test(income) values (?)", (2500.32,)) def CheckExecuteArgString(self): self.cu.execute("insert into test(name) values (?)", ("Hugo",)) def CheckExecuteWrongNoOfArgs1(self): # too many parameters try: self.cu.execute("insert into test(id) values (?)", (17, "Egon")) self.fail("should have raised ProgrammingError") except sqlite.ProgrammingError: pass def CheckExecuteWrongNoOfArgs2(self): # too little parameters try: self.cu.execute("insert into test(id) values (?)") self.fail("should have raised ProgrammingError") except sqlite.ProgrammingError: pass def CheckExecuteWrongNoOfArgs3(self): # no parameters, parameters are needed try: self.cu.execute("insert into test(id) values (?)") self.fail("should have raised ProgrammingError") except sqlite.ProgrammingError: pass def CheckExecuteParamList(self): self.cu.execute("insert into test(name) values ('foo')") self.cu.execute("select name from test where name=?", ["foo"]) row = self.cu.fetchone() self.assertEqual(row[0], "foo") def CheckExecuteParamSequence(self): class L(object): def __len__(self): return 1 def __getitem__(self, x): assert x == 0 return "foo" self.cu.execute("insert into test(name) values ('foo')") self.cu.execute("select name from test where name=?", L()) row = self.cu.fetchone() self.assertEqual(row[0], "foo") def CheckExecuteDictMapping(self): self.cu.execute("insert into test(name) values ('foo')") self.cu.execute("select name from test where name=:name", {"name": "foo"}) row = self.cu.fetchone() self.assertEqual(row[0], "foo") def CheckExecuteDictMapping_Mapping(self): # Test only works with Python 2.5 or later if sys.version_info < (2, 5, 0): return class D(dict): def __missing__(self, key): return "foo" self.cu.execute("insert into test(name) values ('foo')") self.cu.execute("select name from test where name=:name", D()) row = self.cu.fetchone() self.assertEqual(row[0], "foo") def CheckExecuteDictMappingTooLittleArgs(self): self.cu.execute("insert into test(name) values ('foo')") try: self.cu.execute("select name from test where name=:name and id=:id", {"name": "foo"}) self.fail("should have raised ProgrammingError") except sqlite.ProgrammingError: pass def CheckExecuteDictMappingNoArgs(self): self.cu.execute("insert into test(name) values ('foo')") try: self.cu.execute("select name from test where name=:name") self.fail("should have raised ProgrammingError") except sqlite.ProgrammingError: pass def CheckExecuteDictMappingUnnamed(self): self.cu.execute("insert into test(name) values ('foo')") try: self.cu.execute("select name from test where name=?", {"name": "foo"}) self.fail("should have raised ProgrammingError") except sqlite.ProgrammingError: pass def CheckClose(self): self.cu.close() def CheckRowcountExecute(self): self.cu.execute("delete from test") self.cu.execute("insert into test(name) values ('foo')") self.cu.execute("insert into test(name) values ('foo')") self.cu.execute("update test set name='bar'") self.assertEqual(self.cu.rowcount, 2) def CheckRowcountSelect(self): """ pysqlite does not know the rowcount of SELECT statements, because we don't fetch all rows after executing the select statement. The rowcount has thus to be -1. """ self.cu.execute("select 5 union select 6") self.assertEqual(self.cu.rowcount, -1) def CheckRowcountExecutemany(self): self.cu.execute("delete from test") self.cu.executemany("insert into test(name) values (?)", [(1,), (2,), (3,)]) self.assertEqual(self.cu.rowcount, 3) def CheckTotalChanges(self): self.cu.execute("insert into test(name) values ('foo')") self.cu.execute("insert into test(name) values ('foo')") if self.cx.total_changes < 2: self.fail("total changes reported wrong value") # Checks for executemany: # Sequences are required by the DB-API, iterators # enhancements in pysqlite. def CheckExecuteManySequence(self): self.cu.executemany("insert into test(income) values (?)", [(x,) for x in range(100, 110)]) def CheckExecuteManyIterator(self): class MyIter: def __init__(self): self.value = 5 def next(self): if self.value == 10: raise StopIteration else: self.value += 1 return (self.value,) self.cu.executemany("insert into test(income) values (?)", MyIter()) def CheckExecuteManyGenerator(self): def mygen(): for i in range(5): yield (i,) self.cu.executemany("insert into test(income) values (?)", mygen()) def CheckExecuteManyWrongSqlArg(self): try: self.cu.executemany(42, [(3,)]) self.fail("should have raised a ValueError") except ValueError: return except: self.fail("raised wrong exception.") def CheckExecuteManySelect(self): try: self.cu.executemany("select ?", [(3,)]) self.fail("should have raised a ProgrammingError") except sqlite.ProgrammingError: return except: self.fail("raised wrong exception.") def CheckExecuteManyNotIterable(self): try: self.cu.executemany("insert into test(income) values (?)", 42) self.fail("should have raised a TypeError") except TypeError: return except Exception, e: print "raised", e.__class__ self.fail("raised wrong exception.") def CheckFetchIter(self): # Optional DB-API extension. self.cu.execute("delete from test") self.cu.execute("insert into test(id) values (?)", (5,)) self.cu.execute("insert into test(id) values (?)", (6,)) self.cu.execute("select id from test order by id") lst = [] for row in self.cu: lst.append(row[0]) self.assertEqual(lst[0], 5) self.assertEqual(lst[1], 6) def CheckFetchone(self): self.cu.execute("select name from test") row = self.cu.fetchone() self.assertEqual(row[0], "foo") row = self.cu.fetchone() self.assertEqual(row, None) def CheckFetchoneNoStatement(self): cur = self.cx.cursor() row = cur.fetchone() self.assertEqual(row, None) def CheckArraySize(self): # must default ot 1 self.assertEqual(self.cu.arraysize, 1) # now set to 2 self.cu.arraysize = 2 # now make the query return 3 rows self.cu.execute("delete from test") self.cu.execute("insert into test(name) values ('A')") self.cu.execute("insert into test(name) values ('B')") self.cu.execute("insert into test(name) values ('C')") self.cu.execute("select name from test") res = self.cu.fetchmany() self.assertEqual(len(res), 2) def CheckFetchmany(self): self.cu.execute("select name from test") res = self.cu.fetchmany(100) self.assertEqual(len(res), 1) res = self.cu.fetchmany(100) self.assertEqual(res, []) def CheckFetchmanyKwArg(self): """Checks if fetchmany works with keyword arguments""" self.cu.execute("select name from test") res = self.cu.fetchmany(size=100) self.assertEqual(len(res), 1) def CheckFetchall(self): self.cu.execute("select name from test") res = self.cu.fetchall() self.assertEqual(len(res), 1) res = self.cu.fetchall() self.assertEqual(res, []) def CheckSetinputsizes(self): self.cu.setinputsizes([3, 4, 5]) def CheckSetoutputsize(self): self.cu.setoutputsize(5, 0) def CheckSetoutputsizeNoColumn(self): self.cu.setoutputsize(42) def CheckCursorConnection(self): # Optional DB-API extension. self.assertEqual(self.cu.connection, self.cx) def CheckWrongCursorCallable(self): try: def f(): pass cur = self.cx.cursor(f) self.fail("should have raised a TypeError") except TypeError: return self.fail("should have raised a ValueError") def CheckCursorWrongClass(self): class Foo: pass foo = Foo() try: cur = sqlite.Cursor(foo) self.fail("should have raised a ValueError") except TypeError: pass class ThreadTests(unittest.TestCase): def setUp(self): self.con = sqlite.connect(":memory:") self.cur = self.con.cursor() self.cur.execute("create table test(id integer primary key, name text, bin binary, ratio number, ts timestamp)") def tearDown(self): self.cur.close() self.con.close() def CheckConCursor(self): def run(con, errors): try: cur = con.cursor() errors.append("did not raise ProgrammingError") return except sqlite.ProgrammingError: return except: errors.append("raised wrong exception") errors = [] t = threading.Thread(target=run, kwargs={"con": self.con, "errors": errors}) t.start() t.join() if len(errors) > 0: self.fail("\n".join(errors)) def CheckConCommit(self): def run(con, errors): try: con.commit() errors.append("did not raise ProgrammingError") return except sqlite.ProgrammingError: return except: errors.append("raised wrong exception") errors = [] t = threading.Thread(target=run, kwargs={"con": self.con, "errors": errors}) t.start() t.join() if len(errors) > 0: self.fail("\n".join(errors)) def CheckConRollback(self): def run(con, errors): try: con.rollback() errors.append("did not raise ProgrammingError") return except sqlite.ProgrammingError: return except: errors.append("raised wrong exception") errors = [] t = threading.Thread(target=run, kwargs={"con": self.con, "errors": errors}) t.start() t.join() if len(errors) > 0: self.fail("\n".join(errors)) def CheckConClose(self): def run(con, errors): try: con.close() errors.append("did not raise ProgrammingError") return except sqlite.ProgrammingError: return except: errors.append("raised wrong exception") errors = [] t = threading.Thread(target=run, kwargs={"con": self.con, "errors": errors}) t.start() t.join() if len(errors) > 0: self.fail("\n".join(errors)) def CheckCurImplicitBegin(self): def run(cur, errors): try: cur.execute("insert into test(name) values ('a')") errors.append("did not raise ProgrammingError") return except sqlite.ProgrammingError: return except: errors.append("raised wrong exception") errors = [] t = threading.Thread(target=run, kwargs={"cur": self.cur, "errors": errors}) t.start() t.join() if len(errors) > 0: self.fail("\n".join(errors)) def CheckCurClose(self): def run(cur, errors): try: cur.close() errors.append("did not raise ProgrammingError") return except sqlite.ProgrammingError: return except: errors.append("raised wrong exception") errors = [] t = threading.Thread(target=run, kwargs={"cur": self.cur, "errors": errors}) t.start() t.join() if len(errors) > 0: self.fail("\n".join(errors)) def CheckCurExecute(self): def run(cur, errors): try: cur.execute("select name from test") errors.append("did not raise ProgrammingError") return except sqlite.ProgrammingError: return except: errors.append("raised wrong exception") errors = [] self.cur.execute("insert into test(name) values ('a')") t = threading.Thread(target=run, kwargs={"cur": self.cur, "errors": errors}) t.start() t.join() if len(errors) > 0: self.fail("\n".join(errors)) def CheckCurIterNext(self): def run(cur, errors): try: row = cur.fetchone() errors.append("did not raise ProgrammingError") return except sqlite.ProgrammingError: return except: errors.append("raised wrong exception") errors = [] self.cur.execute("insert into test(name) values ('a')") self.cur.execute("select name from test") t = threading.Thread(target=run, kwargs={"cur": self.cur, "errors": errors}) t.start() t.join() if len(errors) > 0: self.fail("\n".join(errors)) class ConstructorTests(unittest.TestCase): def CheckDate(self): d = sqlite.Date(2004, 10, 28) def CheckTime(self): t = sqlite.Time(12, 39, 35) def CheckTimestamp(self): ts = sqlite.Timestamp(2004, 10, 28, 12, 39, 35) def CheckDateFromTicks(self): d = sqlite.DateFromTicks(42) def CheckTimeFromTicks(self): t = sqlite.TimeFromTicks(42) def CheckTimestampFromTicks(self): ts = sqlite.TimestampFromTicks(42) def CheckBinary(self): b = sqlite.Binary(chr(0) + "'") class ExtensionTests(unittest.TestCase): def CheckScriptStringSql(self): con = sqlite.connect(":memory:") cur = con.cursor() cur.executescript(""" -- bla bla /* a stupid comment */ create table a(i); insert into a(i) values (5); """) cur.execute("select i from a") res = cur.fetchone()[0] self.assertEqual(res, 5) def CheckScriptStringUnicode(self): con = sqlite.connect(":memory:") cur = con.cursor() cur.executescript(u""" create table a(i); insert into a(i) values (5); select i from a; delete from a; insert into a(i) values (6); """) cur.execute("select i from a") res = cur.fetchone()[0] self.assertEqual(res, 6) def CheckScriptSyntaxError(self): con = sqlite.connect(":memory:") cur = con.cursor() raised = False try: cur.executescript("create table test(x); asdf; create table test2(x)") except sqlite.OperationalError: raised = True self.assertEqual(raised, True, "should have raised an exception") def CheckScriptErrorNormal(self): con = sqlite.connect(":memory:") cur = con.cursor() raised = False try: cur.executescript("create table test(sadfsadfdsa); select foo from hurz;") except sqlite.OperationalError: raised = True self.assertEqual(raised, True, "should have raised an exception") def CheckConnectionExecute(self): con = sqlite.connect(":memory:") result = con.execute("select 5").fetchone()[0] self.assertEqual(result, 5, "Basic test of Connection.execute") def CheckConnectionExecutemany(self): con = sqlite.connect(":memory:") con.execute("create table test(foo)") con.executemany("insert into test(foo) values (?)", [(3,), (4,)]) result = con.execute("select foo from test order by foo").fetchall() self.assertEqual(result[0][0], 3, "Basic test of Connection.executemany") self.assertEqual(result[1][0], 4, "Basic test of Connection.executemany") def CheckConnectionExecutescript(self): con = sqlite.connect(":memory:") con.executescript("create table test(foo); insert into test(foo) values (5);") result = con.execute("select foo from test").fetchone()[0] self.assertEqual(result, 5, "Basic test of Connection.executescript") class ClosedConTests(unittest.TestCase): def setUp(self): pass def tearDown(self): pass def CheckClosedConCursor(self): con = sqlite.connect(":memory:") con.close() try: cur = con.cursor() self.fail("Should have raised a ProgrammingError") except sqlite.ProgrammingError: pass except: self.fail("Should have raised a ProgrammingError") def CheckClosedConCommit(self): con = sqlite.connect(":memory:") con.close() try: con.commit() self.fail("Should have raised a ProgrammingError") except sqlite.ProgrammingError: pass except: self.fail("Should have raised a ProgrammingError") def CheckClosedConRollback(self): con = sqlite.connect(":memory:") con.close() try: con.rollback() self.fail("Should have raised a ProgrammingError") except sqlite.ProgrammingError: pass except: self.fail("Should have raised a ProgrammingError") def CheckClosedCurExecute(self): con = sqlite.connect(":memory:") cur = con.cursor() con.close() try: cur.execute("select 4") self.fail("Should have raised a ProgrammingError") except sqlite.ProgrammingError: pass except: self.fail("Should have raised a ProgrammingError") def CheckClosedCreateFunction(self): con = sqlite.connect(":memory:") con.close() def f(x): return 17 try: con.create_function("foo", 1, f) self.fail("Should have raised a ProgrammingError") except sqlite.ProgrammingError: pass except: self.fail("Should have raised a ProgrammingError") def CheckClosedCreateAggregate(self): con = sqlite.connect(":memory:") con.close() class Agg: def __init__(self): pass def step(self, x): pass def finalize(self): return 17 try: con.create_aggregate("foo", 1, Agg) self.fail("Should have raised a ProgrammingError") except sqlite.ProgrammingError: pass except: self.fail("Should have raised a ProgrammingError") def CheckClosedSetAuthorizer(self): con = sqlite.connect(":memory:") con.close() def authorizer(*args): return sqlite.DENY try: con.set_authorizer(authorizer) self.fail("Should have raised a ProgrammingError") except sqlite.ProgrammingError: pass except: self.fail("Should have raised a ProgrammingError") def CheckClosedSetProgressCallback(self): con = sqlite.connect(":memory:") con.close() def progress(): pass try: con.set_progress_handler(progress, 100) self.fail("Should have raised a ProgrammingError") except sqlite.ProgrammingError: pass except: self.fail("Should have raised a ProgrammingError") def CheckClosedCall(self): con = sqlite.connect(":memory:") con.close() try: con() self.fail("Should have raised a ProgrammingError") except sqlite.ProgrammingError: pass except: self.fail("Should have raised a ProgrammingError") class ClosedCurTests(unittest.TestCase): def setUp(self): pass def tearDown(self): pass def CheckClosed(self): con = sqlite.connect(":memory:") cur = con.cursor() cur.close() for method_name in ("execute", "executemany", "executescript", "fetchall", "fetchmany", "fetchone"): if method_name in ("execute", "executescript"): params = ("select 4 union select 5",) elif method_name == "executemany": params = ("insert into foo(bar) values (?)", [(3,), (4,)]) else: params = [] try: method = getattr(cur, method_name) method(*params) self.fail("Should have raised a ProgrammingError: method " + method_name) except sqlite.ProgrammingError: pass except: self.fail("Should have raised a ProgrammingError: " + method_name) def suite(): module_suite = unittest.makeSuite(ModuleTests, "Check") connection_suite = unittest.makeSuite(ConnectionTests, "Check") cursor_suite = unittest.makeSuite(CursorTests, "Check") thread_suite = unittest.makeSuite(ThreadTests, "Check") constructor_suite = unittest.makeSuite(ConstructorTests, "Check") ext_suite = unittest.makeSuite(ExtensionTests, "Check") closed_con_suite = unittest.makeSuite(ClosedConTests, "Check") closed_cur_suite = unittest.makeSuite(ClosedCurTests, "Check") return unittest.TestSuite((module_suite, connection_suite, cursor_suite, thread_suite, constructor_suite, ext_suite, closed_con_suite, closed_cur_suite)) def test(): runner = unittest.TextTestRunner() runner.run(suite()) if __name__ == "__main__": test() pysqlite-2.6.3/lib/test/dump.py000644 000765 000024 00000003331 11343755400 017371 0ustar00ghaeringstaff000000 000000 # Author: Paul Kippes import unittest from pysqlite2 import dbapi2 as sqlite class DumpTests(unittest.TestCase): def setUp(self): self.cx = sqlite.connect(":memory:") self.cu = self.cx.cursor() def tearDown(self): self.cx.close() def CheckTableDump(self): expected_sqls = [ "CREATE TABLE t1(id integer primary key, s1 text, " \ "t1_i1 integer not null, i2 integer, unique (s1), " \ "constraint t1_idx1 unique (i2));" , "INSERT INTO \"t1\" VALUES(1,'foo',10,20);" , "INSERT INTO \"t1\" VALUES(2,'foo2',30,30);" , "CREATE TABLE t2(id integer, t2_i1 integer, " \ "t2_i2 integer, primary key (id)," \ "foreign key(t2_i1) references t1(t1_i1));" , "CREATE TRIGGER trigger_1 update of t1_i1 on t1 " \ "begin " \ "update t2 set t2_i1 = new.t1_i1 where t2_i1 = old.t1_i1; " \ "end;" , "CREATE VIEW v1 as select * from t1 left join t2 " \ "using (id);" ] [self.cu.execute(s) for s in expected_sqls] i = self.cx.iterdump() actual_sqls = [s for s in i] expected_sqls = ['BEGIN TRANSACTION;'] + expected_sqls + \ ['COMMIT;'] [self.assertEqual(expected_sqls[i], actual_sqls[i]) for i in xrange(len(expected_sqls))] def suite(): return unittest.TestSuite(unittest.makeSuite(DumpTests, "Check")) def test(): runner = unittest.TextTestRunner() runner.run(suite()) if __name__ == "__main__": test() pysqlite-2.6.3/lib/test/factory.py000644 000765 000024 00000017406 11343723473 020110 0ustar00ghaeringstaff000000 000000 #-*- coding: ISO-8859-1 -*- # pysqlite2/test/factory.py: tests for the various factories in pysqlite # # Copyright (C) 2005-2007 Gerhard Häring # # This file is part of pysqlite. # # This software is provided 'as-is', without any express or implied # warranty. In no event will the authors be held liable for any damages # arising from the use of this software. # # Permission is granted to anyone to use this software for any purpose, # including commercial applications, and to alter it and redistribute it # freely, subject to the following restrictions: # # 1. The origin of this software must not be misrepresented; you must not # claim that you wrote the original software. If you use this software # in a product, an acknowledgment in the product documentation would be # appreciated but is not required. # 2. Altered source versions must be plainly marked as such, and must not be # misrepresented as being the original software. # 3. This notice may not be removed or altered from any source distribution. import unittest import pysqlite2.dbapi2 as sqlite class MyConnection(sqlite.Connection): def __init__(self, *args, **kwargs): sqlite.Connection.__init__(self, *args, **kwargs) def dict_factory(cursor, row): d = {} for idx, col in enumerate(cursor.description): d[col[0]] = row[idx] return d class MyCursor(sqlite.Cursor): def __init__(self, *args, **kwargs): sqlite.Cursor.__init__(self, *args, **kwargs) self.row_factory = dict_factory class ConnectionFactoryTests(unittest.TestCase): def setUp(self): self.con = sqlite.connect(":memory:", factory=MyConnection) def tearDown(self): self.con.close() def CheckIsInstance(self): self.assertTrue(isinstance(self.con, MyConnection), "connection is not instance of MyConnection") class CursorFactoryTests(unittest.TestCase): def setUp(self): self.con = sqlite.connect(":memory:") def tearDown(self): self.con.close() def CheckIsInstance(self): cur = self.con.cursor(factory=MyCursor) self.assertTrue(isinstance(cur, MyCursor), "cursor is not instance of MyCursor") class RowFactoryTestsBackwardsCompat(unittest.TestCase): def setUp(self): self.con = sqlite.connect(":memory:") def CheckIsProducedByFactory(self): cur = self.con.cursor(factory=MyCursor) cur.execute("select 4+5 as foo") row = cur.fetchone() self.assertTrue(isinstance(row, dict), "row is not instance of dict") cur.close() def tearDown(self): self.con.close() class RowFactoryTests(unittest.TestCase): def setUp(self): self.con = sqlite.connect(":memory:") def CheckCustomFactory(self): self.con.row_factory = lambda cur, row: list(row) row = self.con.execute("select 1, 2").fetchone() self.assertTrue(isinstance(row, list), "row is not instance of list") def CheckSqliteRowIndex(self): self.con.row_factory = sqlite.Row row = self.con.execute("select 1 as a, 2 as b").fetchone() self.assertTrue(isinstance(row, sqlite.Row), "row is not instance of sqlite.Row") col1, col2 = row["a"], row["b"] self.assertTrue(col1 == 1, "by name: wrong result for column 'a'") self.assertTrue(col2 == 2, "by name: wrong result for column 'a'") col1, col2 = row["A"], row["B"] self.assertTrue(col1 == 1, "by name: wrong result for column 'A'") self.assertTrue(col2 == 2, "by name: wrong result for column 'B'") col1, col2 = row[0], row[1] self.assertTrue(col1 == 1, "by index: wrong result for column 0") self.assertTrue(col2 == 2, "by index: wrong result for column 1") def CheckSqliteRowIter(self): """Checks if the row object is iterable""" self.con.row_factory = sqlite.Row row = self.con.execute("select 1 as a, 2 as b").fetchone() for col in row: pass def CheckSqliteRowAsTuple(self): """Checks if the row object can be converted to a tuple""" self.con.row_factory = sqlite.Row row = self.con.execute("select 1 as a, 2 as b").fetchone() t = tuple(row) def CheckSqliteRowAsDict(self): """Checks if the row object can be correctly converted to a dictionary""" self.con.row_factory = sqlite.Row row = self.con.execute("select 1 as a, 2 as b").fetchone() d = dict(row) self.assertEqual(d["a"], row["a"]) self.assertEqual(d["b"], row["b"]) def CheckSqliteRowHashCmp(self): """Checks if the row object compares and hashes correctly""" self.con.row_factory = sqlite.Row row_1 = self.con.execute("select 1 as a, 2 as b").fetchone() row_2 = self.con.execute("select 1 as a, 2 as b").fetchone() row_3 = self.con.execute("select 1 as a, 3 as b").fetchone() self.assertTrue(row_1 == row_1) self.assertTrue(row_1 == row_2) self.assertTrue(row_2 != row_3) self.assertFalse(row_1 != row_1) self.assertFalse(row_1 != row_2) self.assertFalse(row_2 == row_3) self.assertEqual(row_1, row_2) self.assertEqual(hash(row_1), hash(row_2)) self.assertNotEqual(row_1, row_3) self.assertNotEqual(hash(row_1), hash(row_3)) def tearDown(self): self.con.close() class TextFactoryTests(unittest.TestCase): def setUp(self): self.con = sqlite.connect(":memory:") def CheckUnicode(self): austria = unicode("Österreich", "latin1") row = self.con.execute("select ?", (austria,)).fetchone() self.assertTrue(type(row[0]) == unicode, "type of row[0] must be unicode") def CheckString(self): self.con.text_factory = str austria = unicode("Österreich", "latin1") row = self.con.execute("select ?", (austria,)).fetchone() self.assertTrue(type(row[0]) == str, "type of row[0] must be str") self.assertTrue(row[0] == austria.encode("utf-8"), "column must equal original data in UTF-8") def CheckCustom(self): self.con.text_factory = lambda x: unicode(x, "utf-8", "ignore") austria = unicode("Österreich", "latin1") row = self.con.execute("select ?", (austria.encode("latin1"),)).fetchone() self.assertTrue(type(row[0]) == unicode, "type of row[0] must be unicode") self.assertTrue(row[0].endswith(u"reich"), "column must contain original data") def CheckOptimizedUnicode(self): self.con.text_factory = sqlite.OptimizedUnicode austria = unicode("Österreich", "latin1") germany = unicode("Deutchland") a_row = self.con.execute("select ?", (austria,)).fetchone() d_row = self.con.execute("select ?", (germany,)).fetchone() self.assertTrue(type(a_row[0]) == unicode, "type of non-ASCII row must be unicode") self.assertTrue(type(d_row[0]) == str, "type of ASCII-only row must be str") def tearDown(self): self.con.close() def suite(): connection_suite = unittest.makeSuite(ConnectionFactoryTests, "Check") cursor_suite = unittest.makeSuite(CursorFactoryTests, "Check") row_suite_compat = unittest.makeSuite(RowFactoryTestsBackwardsCompat, "Check") row_suite = unittest.makeSuite(RowFactoryTests, "Check") text_suite = unittest.makeSuite(TextFactoryTests, "Check") return unittest.TestSuite((connection_suite, cursor_suite, row_suite_compat, row_suite, text_suite)) def test(): runner = unittest.TextTestRunner() runner.run(suite()) if __name__ == "__main__": test() pysqlite-2.6.3/lib/test/hooks.py000644 000765 000024 00000014651 11343722273 017560 0ustar00ghaeringstaff000000 000000 #-*- coding: ISO-8859-1 -*- # pysqlite2/test/hooks.py: tests for various SQLite-specific hooks # # Copyright (C) 2006-2007 Gerhard Häring # # This file is part of pysqlite. # # This software is provided 'as-is', without any express or implied # warranty. In no event will the authors be held liable for any damages # arising from the use of this software. # # Permission is granted to anyone to use this software for any purpose, # including commercial applications, and to alter it and redistribute it # freely, subject to the following restrictions: # # 1. The origin of this software must not be misrepresented; you must not # claim that you wrote the original software. If you use this software # in a product, an acknowledgment in the product documentation would be # appreciated but is not required. # 2. Altered source versions must be plainly marked as such, and must not be # misrepresented as being the original software. # 3. This notice may not be removed or altered from any source distribution. import os, unittest import pysqlite2.dbapi2 as sqlite class CollationTests(unittest.TestCase): def setUp(self): pass def tearDown(self): pass def CheckCreateCollationNotCallable(self): con = sqlite.connect(":memory:") try: con.create_collation("X", 42) self.fail("should have raised a TypeError") except TypeError, e: self.assertEqual(e.args[0], "parameter must be callable") def CheckCreateCollationNotAscii(self): con = sqlite.connect(":memory:") try: con.create_collation("collä", cmp) self.fail("should have raised a ProgrammingError") except sqlite.ProgrammingError, e: pass def CheckCollationIsUsed(self): if sqlite.version_info < (3, 2, 1): # old SQLite versions crash on this test return def mycoll(x, y): # reverse order return -cmp(x, y) con = sqlite.connect(":memory:") con.create_collation("mycoll", mycoll) sql = """ select x from ( select 'a' as x union select 'b' as x union select 'c' as x ) order by x collate mycoll """ result = con.execute(sql).fetchall() if result[0][0] != "c" or result[1][0] != "b" or result[2][0] != "a": self.fail("the expected order was not returned") con.create_collation("mycoll", None) try: result = con.execute(sql).fetchall() self.fail("should have raised an OperationalError") except sqlite.OperationalError, e: self.assertEqual(e.args[0].lower(), "no such collation sequence: mycoll") def CheckCollationRegisterTwice(self): """ Register two different collation functions under the same name. Verify that the last one is actually used. """ con = sqlite.connect(":memory:") con.create_collation("mycoll", cmp) con.create_collation("mycoll", lambda x, y: -cmp(x, y)) result = con.execute(""" select x from (select 'a' as x union select 'b' as x) order by x collate mycoll """).fetchall() if result[0][0] != 'b' or result[1][0] != 'a': self.fail("wrong collation function is used") def CheckDeregisterCollation(self): """ Register a collation, then deregister it. Make sure an error is raised if we try to use it. """ con = sqlite.connect(":memory:") con.create_collation("mycoll", cmp) con.create_collation("mycoll", None) try: con.execute("select 'a' as x union select 'b' as x order by x collate mycoll") self.fail("should have raised an OperationalError") except sqlite.OperationalError, e: if not e.args[0].startswith("no such collation sequence"): self.fail("wrong OperationalError raised") class ProgressTests(unittest.TestCase): def CheckProgressHandlerUsed(self): """ Test that the progress handler is invoked once it is set. """ con = sqlite.connect(":memory:") progress_calls = [] def progress(): progress_calls.append(None) return 0 con.set_progress_handler(progress, 1) con.execute(""" create table foo(a, b) """) self.assertTrue(progress_calls) def CheckOpcodeCount(self): """ Test that the opcode argument is respected. """ con = sqlite.connect(":memory:") progress_calls = [] def progress(): progress_calls.append(None) return 0 con.set_progress_handler(progress, 1) curs = con.cursor() curs.execute(""" create table foo (a, b) """) first_count = len(progress_calls) progress_calls = [] con.set_progress_handler(progress, 2) curs.execute(""" create table bar (a, b) """) second_count = len(progress_calls) self.assertTrue(first_count > second_count) def CheckCancelOperation(self): """ Test that returning a non-zero value stops the operation in progress. """ con = sqlite.connect(":memory:") progress_calls = [] def progress(): progress_calls.append(None) return 1 con.set_progress_handler(progress, 1) curs = con.cursor() self.assertRaises( sqlite.OperationalError, curs.execute, "create table bar (a, b)") def CheckClearHandler(self): """ Test that setting the progress handler to None clears the previously set handler. """ con = sqlite.connect(":memory:") action = 0 def progress(): action = 1 return 0 con.set_progress_handler(progress, 1) con.set_progress_handler(None, 1) con.execute("select 1 union select 2 union select 3").fetchall() self.assertEqual(action, 0, "progress handler was not cleared") def suite(): collation_suite = unittest.makeSuite(CollationTests, "Check") progress_suite = unittest.makeSuite(ProgressTests, "Check") return unittest.TestSuite((collation_suite, progress_suite)) def test(): runner = unittest.TextTestRunner() runner.run(suite()) if __name__ == "__main__": test() pysqlite-2.6.3/lib/test/py25/000755 000765 000024 00000000000 11526730255 016655 5ustar00ghaeringstaff000000 000000 pysqlite-2.6.3/lib/test/regression.py000644 000765 000024 00000022731 11343724514 020613 0ustar00ghaeringstaff000000 000000 #-*- coding: ISO-8859-1 -*- # pysqlite2/test/regression.py: pysqlite regression tests # # Copyright (C) 2006-2009 Gerhard Häring # # This file is part of pysqlite. # # This software is provided 'as-is', without any express or implied # warranty. In no event will the authors be held liable for any damages # arising from the use of this software. # # Permission is granted to anyone to use this software for any purpose, # including commercial applications, and to alter it and redistribute it # freely, subject to the following restrictions: # # 1. The origin of this software must not be misrepresented; you must not # claim that you wrote the original software. If you use this software # in a product, an acknowledgment in the product documentation would be # appreciated but is not required. # 2. Altered source versions must be plainly marked as such, and must not be # misrepresented as being the original software. # 3. This notice may not be removed or altered from any source distribution. import datetime import unittest import pysqlite2.dbapi2 as sqlite class RegressionTests(unittest.TestCase): def setUp(self): self.con = sqlite.connect(":memory:") def tearDown(self): self.con.close() def CheckPragmaUserVersion(self): # This used to crash pysqlite because this pragma command returns NULL for the column name cur = self.con.cursor() cur.execute("pragma user_version") def CheckPragmaSchemaVersion(self): # This still crashed pysqlite <= 2.2.1 con = sqlite.connect(":memory:", detect_types=sqlite.PARSE_COLNAMES) try: cur = self.con.cursor() cur.execute("pragma schema_version") finally: cur.close() con.close() def CheckStatementReset(self): # pysqlite 2.1.0 to 2.2.0 have the problem that not all statements are # reset before a rollback, but only those that are still in the # statement cache. The others are not accessible from the connection object. con = sqlite.connect(":memory:", cached_statements=5) cursors = [con.cursor() for x in xrange(5)] cursors[0].execute("create table test(x)") for i in range(10): cursors[0].executemany("insert into test(x) values (?)", [(x,) for x in xrange(10)]) for i in range(5): cursors[i].execute(" " * i + "select x from test") con.rollback() def CheckColumnNameWithSpaces(self): cur = self.con.cursor() cur.execute('select 1 as "foo bar [datetime]"') self.assertEqual(cur.description[0][0], "foo bar") cur.execute('select 1 as "foo baz"') self.assertEqual(cur.description[0][0], "foo baz") def CheckStatementFinalizationOnCloseDb(self): # pysqlite versions <= 2.3.3 only finalized statements in the statement # cache when closing the database. statements that were still # referenced in cursors weren't closed an could provoke " # "OperationalError: Unable to close due to unfinalised statements". con = sqlite.connect(":memory:") cursors = [] # default statement cache size is 100 for i in range(105): cur = con.cursor() cursors.append(cur) cur.execute("select 1 x union select " + str(i)) con.close() def CheckOnConflictRollback(self): if sqlite.sqlite_version_info < (3, 2, 2): return con = sqlite.connect(":memory:") con.execute("create table foo(x, unique(x) on conflict rollback)") con.execute("insert into foo(x) values (1)") try: con.execute("insert into foo(x) values (1)") except sqlite.DatabaseError: pass con.execute("insert into foo(x) values (2)") try: con.commit() except sqlite.OperationalError: self.fail("pysqlite knew nothing about the implicit ROLLBACK") def CheckWorkaroundForBuggySqliteTransferBindings(self): """ pysqlite would crash with older SQLite versions unless a workaround is implemented. """ self.con.execute("create table foo(bar)") self.con.execute("drop table foo") self.con.execute("create table foo(bar)") def CheckEmptyStatement(self): """ pysqlite used to segfault with SQLite versions 3.5.x. These return NULL for "no-operation" statements """ self.con.execute("") def CheckUnicodeConnect(self): """ With pysqlite 2.4.0 you needed to use a string or a APSW connection object for opening database connections. Formerly, both bytestrings and unicode strings used to work. Let's make sure unicode strings work in the future. """ con = sqlite.connect(u":memory:") con.close() def CheckTypeMapUsage(self): """ pysqlite until 2.4.1 did not rebuild the row_cast_map when recompiling a statement. This test exhibits the problem. """ SELECT = "select * from foo" con = sqlite.connect(":memory:",detect_types=sqlite.PARSE_DECLTYPES) con.execute("create table foo(bar timestamp)") con.execute("insert into foo(bar) values (?)", (datetime.datetime.now(),)) con.execute(SELECT) con.execute("drop table foo") con.execute("create table foo(bar integer)") con.execute("insert into foo(bar) values (5)") con.execute(SELECT) def CheckRegisterAdapter(self): """ See issue 3312. """ self.assertRaises(TypeError, sqlite.register_adapter, {}, None) def CheckSetIsolationLevel(self): """ See issue 3312. """ con = sqlite.connect(":memory:") self.assertRaises(UnicodeEncodeError, setattr, con, "isolation_level", u"\xe9") def CheckCursorConstructorCallCheck(self): """ Verifies that cursor methods check wether base class __init__ was called. """ class Cursor(sqlite.Cursor): def __init__(self, con): pass con = sqlite.connect(":memory:") cur = Cursor(con) try: cur.execute("select 4+5").fetchall() self.fail("should have raised ProgrammingError") except sqlite.ProgrammingError: pass except: self.fail("should have raised ProgrammingError") def CheckConnectionConstructorCallCheck(self): """ Verifies that connection methods check wether base class __init__ was called. """ class Connection(sqlite.Connection): def __init__(self, name): pass con = Connection(":memory:") try: cur = con.cursor() self.fail("should have raised ProgrammingError") except sqlite.ProgrammingError: pass except: self.fail("should have raised ProgrammingError") def CheckCursorRegistration(self): """ Verifies that subclassed cursor classes are correctly registered with the connection object, too. (fetch-across-rollback problem) """ class Connection(sqlite.Connection): def cursor(self): return Cursor(self) class Cursor(sqlite.Cursor): def __init__(self, con): sqlite.Cursor.__init__(self, con) con = Connection(":memory:") cur = con.cursor() cur.execute("create table foo(x)") cur.executemany("insert into foo(x) values (?)", [(3,), (4,), (5,)]) cur.execute("select x from foo") con.rollback() try: cur.fetchall() self.fail("should have raised InterfaceError") except sqlite.InterfaceError: pass except: self.fail("should have raised InterfaceError") def CheckAutoCommit(self): """ Verifies that creating a connection in autocommit mode works. 2.5.3 introduced a regression so that these could no longer be created. """ con = sqlite.connect(":memory:", isolation_level=None) def CheckPragmaAutocommit(self): """ Verifies that running a PRAGMA statement that does an autocommit does work. This did not work in 2.5.3/2.5.4. """ con = sqlite.connect(":memory:") cur = con.cursor() cur.execute("create table foo(bar)") cur.execute("insert into foo(bar) values (5)") cur.execute("pragma page_size") row = cur.fetchone() def CheckSetDict(self): """ See http://bugs.python.org/issue7478 It was possible to successfully register callbacks that could not be hashed. Return codes of PyDict_SetItem were not checked properly. """ class NotHashable: def __call__(self, *args, **kw): pass def __hash__(self): raise TypeError() var = NotHashable() con = sqlite.connect(":memory:") self.assertRaises(TypeError, con.create_function, var) self.assertRaises(TypeError, con.create_aggregate, var) self.assertRaises(TypeError, con.set_authorizer, var) self.assertRaises(TypeError, con.set_progress_handler, var) def suite(): regression_suite = unittest.makeSuite(RegressionTests, "Check") return unittest.TestSuite((regression_suite,)) def test(): runner = unittest.TextTestRunner() runner.run(suite()) if __name__ == "__main__": test() pysqlite-2.6.3/lib/test/transactions.py000644 000765 000024 00000016274 11343722273 021150 0ustar00ghaeringstaff000000 000000 #-*- coding: ISO-8859-1 -*- # pysqlite2/test/transactions.py: tests transactions # # Copyright (C) 2005-2009 Gerhard Häring # # This file is part of pysqlite. # # This software is provided 'as-is', without any express or implied # warranty. In no event will the authors be held liable for any damages # arising from the use of this software. # # Permission is granted to anyone to use this software for any purpose, # including commercial applications, and to alter it and redistribute it # freely, subject to the following restrictions: # # 1. The origin of this software must not be misrepresented; you must not # claim that you wrote the original software. If you use this software # in a product, an acknowledgment in the product documentation would be # appreciated but is not required. # 2. Altered source versions must be plainly marked as such, and must not be # misrepresented as being the original software. # 3. This notice may not be removed or altered from any source distribution. import sys import os, unittest import pysqlite2.dbapi2 as sqlite def get_db_path(): return "sqlite_testdb" class TransactionTests(unittest.TestCase): def setUp(self): try: os.remove(get_db_path()) except OSError: pass self.con1 = sqlite.connect(get_db_path(), timeout=0.1) self.cur1 = self.con1.cursor() self.con2 = sqlite.connect(get_db_path(), timeout=0.1) self.cur2 = self.con2.cursor() def tearDown(self): self.cur1.close() self.con1.close() self.cur2.close() self.con2.close() try: os.unlink(get_db_path()) except OSError: pass def CheckDMLdoesAutoCommitBefore(self): self.cur1.execute("create table test(i)") self.cur1.execute("insert into test(i) values (5)") self.cur1.execute("create table test2(j)") self.cur2.execute("select i from test") res = self.cur2.fetchall() self.assertEqual(len(res), 1) def CheckInsertStartsTransaction(self): self.cur1.execute("create table test(i)") self.cur1.execute("insert into test(i) values (5)") self.cur2.execute("select i from test") res = self.cur2.fetchall() self.assertEqual(len(res), 0) def CheckUpdateStartsTransaction(self): self.cur1.execute("create table test(i)") self.cur1.execute("insert into test(i) values (5)") self.con1.commit() self.cur1.execute("update test set i=6") self.cur2.execute("select i from test") res = self.cur2.fetchone()[0] self.assertEqual(res, 5) def CheckDeleteStartsTransaction(self): self.cur1.execute("create table test(i)") self.cur1.execute("insert into test(i) values (5)") self.con1.commit() self.cur1.execute("delete from test") self.cur2.execute("select i from test") res = self.cur2.fetchall() self.assertEqual(len(res), 1) def CheckReplaceStartsTransaction(self): self.cur1.execute("create table test(i)") self.cur1.execute("insert into test(i) values (5)") self.con1.commit() self.cur1.execute("replace into test(i) values (6)") self.cur2.execute("select i from test") res = self.cur2.fetchall() self.assertEqual(len(res), 1) self.assertEqual(res[0][0], 5) def CheckToggleAutoCommit(self): self.cur1.execute("create table test(i)") self.cur1.execute("insert into test(i) values (5)") self.con1.isolation_level = None self.assertEqual(self.con1.isolation_level, None) self.cur2.execute("select i from test") res = self.cur2.fetchall() self.assertEqual(len(res), 1) self.con1.isolation_level = "DEFERRED" self.assertEqual(self.con1.isolation_level , "DEFERRED") self.cur1.execute("insert into test(i) values (5)") self.cur2.execute("select i from test") res = self.cur2.fetchall() self.assertEqual(len(res), 1) def CheckRaiseTimeout(self): if sqlite.sqlite_version_info < (3, 2, 2): # This will fail (hang) on earlier versions of sqlite. # Determine exact version it was fixed. 3.2.1 hangs. return self.cur1.execute("create table test(i)") self.cur1.execute("insert into test(i) values (5)") try: self.cur2.execute("insert into test(i) values (5)") self.fail("should have raised an OperationalError") except sqlite.OperationalError: pass except: self.fail("should have raised an OperationalError") def CheckLocking(self): """ This tests the improved concurrency with pysqlite 2.3.4. You needed to roll back con2 before you could commit con1. """ if sqlite.sqlite_version_info < (3, 2, 2): # This will fail (hang) on earlier versions of sqlite. # Determine exact version it was fixed. 3.2.1 hangs. return self.cur1.execute("create table test(i)") self.cur1.execute("insert into test(i) values (5)") try: self.cur2.execute("insert into test(i) values (5)") self.fail("should have raised an OperationalError") except sqlite.OperationalError: pass except: self.fail("should have raised an OperationalError") # NO self.con2.rollback() HERE!!! self.con1.commit() def CheckRollbackCursorConsistency(self): """ Checks if cursors on the connection are set into a "reset" state when a rollback is done on the connection. """ con = sqlite.connect(":memory:") cur = con.cursor() cur.execute("create table test(x)") cur.execute("insert into test(x) values (5)") cur.execute("select 1 union select 2 union select 3") con.rollback() try: cur.fetchall() self.fail("InterfaceError should have been raised") except sqlite.InterfaceError, e: pass except: self.fail("InterfaceError should have been raised") class SpecialCommandTests(unittest.TestCase): def setUp(self): self.con = sqlite.connect(":memory:") self.cur = self.con.cursor() def CheckVacuum(self): self.cur.execute("create table test(i)") self.cur.execute("insert into test(i) values (5)") self.cur.execute("vacuum") def CheckDropTable(self): self.cur.execute("create table test(i)") self.cur.execute("insert into test(i) values (5)") self.cur.execute("drop table test") def CheckPragma(self): self.cur.execute("create table test(i)") self.cur.execute("insert into test(i) values (5)") self.cur.execute("pragma count_changes=1") def tearDown(self): self.cur.close() self.con.close() def suite(): default_suite = unittest.makeSuite(TransactionTests, "Check") special_command_suite = unittest.makeSuite(SpecialCommandTests, "Check") return unittest.TestSuite((default_suite, special_command_suite)) def test(): runner = unittest.TextTestRunner() runner.run(suite()) if __name__ == "__main__": test() pysqlite-2.6.3/lib/test/types.py000644 000765 000024 00000034761 11343755504 017610 0ustar00ghaeringstaff000000 000000 #-*- coding: ISO-8859-1 -*- # pysqlite2/test/types.py: tests for type conversion and detection # # Copyright (C) 2005-2007 Gerhard Häring # # This file is part of pysqlite. # # This software is provided 'as-is', without any express or implied # warranty. In no event will the authors be held liable for any damages # arising from the use of this software. # # Permission is granted to anyone to use this software for any purpose, # including commercial applications, and to alter it and redistribute it # freely, subject to the following restrictions: # # 1. The origin of this software must not be misrepresented; you must not # claim that you wrote the original software. If you use this software # in a product, an acknowledgment in the product documentation would be # appreciated but is not required. # 2. Altered source versions must be plainly marked as such, and must not be # misrepresented as being the original software. # 3. This notice may not be removed or altered from any source distribution. import datetime import unittest import pysqlite2.dbapi2 as sqlite import zlib class SqliteTypeTests(unittest.TestCase): def setUp(self): self.con = sqlite.connect(":memory:") self.cur = self.con.cursor() self.cur.execute("create table test(i integer, s varchar, f number, b blob)") def tearDown(self): self.cur.close() self.con.close() def CheckString(self): self.cur.execute("insert into test(s) values (?)", (u"Österreich",)) self.cur.execute("select s from test") row = self.cur.fetchone() self.assertEqual(row[0], u"Österreich") def CheckSmallInt(self): self.cur.execute("insert into test(i) values (?)", (42,)) self.cur.execute("select i from test") row = self.cur.fetchone() self.assertEqual(row[0], 42) def CheckLargeInt(self): num = 2**40 self.cur.execute("insert into test(i) values (?)", (num,)) self.cur.execute("select i from test") row = self.cur.fetchone() self.assertEqual(row[0], num) def CheckFloat(self): val = 3.14 self.cur.execute("insert into test(f) values (?)", (val,)) self.cur.execute("select f from test") row = self.cur.fetchone() self.assertEqual(row[0], val) def CheckBlob(self): val = buffer("Guglhupf") self.cur.execute("insert into test(b) values (?)", (val,)) self.cur.execute("select b from test") row = self.cur.fetchone() self.assertEqual(row[0], val) def CheckUnicodeExecute(self): self.cur.execute(u"select 'Österreich'") row = self.cur.fetchone() self.assertEqual(row[0], u"Österreich") def CheckNonUtf8_Default(self): try: self.cur.execute("select ?", (chr(150),)) self.fail("should have raised a ProgrammingError") except sqlite.ProgrammingError: pass def CheckNonUtf8_TextFactoryString(self): orig_text_factory = self.con.text_factory try: self.con.text_factory = str self.cur.execute("select ?", (chr(150),)) finally: self.con.text_factory = orig_text_factory def CheckNonUtf8_TextFactoryOptimizedUnicode(self): orig_text_factory = self.con.text_factory try: try: self.con.text_factory = sqlite.OptimizedUnicode self.cur.execute("select ?", (chr(150),)) self.fail("should have raised a ProgrammingError") except sqlite.ProgrammingError: pass finally: self.con.text_factory = orig_text_factory class DeclTypesTests(unittest.TestCase): class Foo: def __init__(self, _val): self.val = _val def __cmp__(self, other): if not isinstance(other, DeclTypesTests.Foo): raise ValueError if self.val == other.val: return 0 else: return 1 def __conform__(self, protocol): if protocol is sqlite.PrepareProtocol: return self.val else: return None def __str__(self): return "<%s>" % self.val def setUp(self): self.con = sqlite.connect(":memory:", detect_types=sqlite.PARSE_DECLTYPES) self.cur = self.con.cursor() self.cur.execute("create table test(i int, s str, f float, b bool, u unicode, foo foo, bin blob, n1 number, n2 number(5))") # override float, make them always return the same number sqlite.converters["FLOAT"] = lambda x: 47.2 # and implement two custom ones sqlite.converters["BOOL"] = lambda x: bool(int(x)) sqlite.converters["FOO"] = DeclTypesTests.Foo sqlite.converters["WRONG"] = lambda x: "WRONG" sqlite.converters["NUMBER"] = float def tearDown(self): del sqlite.converters["FLOAT"] del sqlite.converters["BOOL"] del sqlite.converters["FOO"] del sqlite.converters["NUMBER"] self.cur.close() self.con.close() def CheckString(self): # default self.cur.execute("insert into test(s) values (?)", ("foo",)) self.cur.execute('select s as "s [WRONG]" from test') row = self.cur.fetchone() self.assertEqual(row[0], "foo") def CheckSmallInt(self): # default self.cur.execute("insert into test(i) values (?)", (42,)) self.cur.execute("select i from test") row = self.cur.fetchone() self.assertEqual(row[0], 42) def CheckLargeInt(self): # default num = 2**40 self.cur.execute("insert into test(i) values (?)", (num,)) self.cur.execute("select i from test") row = self.cur.fetchone() self.assertEqual(row[0], num) def CheckFloat(self): # custom val = 3.14 self.cur.execute("insert into test(f) values (?)", (val,)) self.cur.execute("select f from test") row = self.cur.fetchone() self.assertEqual(row[0], 47.2) def CheckBool(self): # custom self.cur.execute("insert into test(b) values (?)", (False,)) self.cur.execute("select b from test") row = self.cur.fetchone() self.assertEqual(row[0], False) self.cur.execute("delete from test") self.cur.execute("insert into test(b) values (?)", (True,)) self.cur.execute("select b from test") row = self.cur.fetchone() self.assertEqual(row[0], True) def CheckUnicode(self): # default val = u"\xd6sterreich" self.cur.execute("insert into test(u) values (?)", (val,)) self.cur.execute("select u from test") row = self.cur.fetchone() self.assertEqual(row[0], val) def CheckFoo(self): val = DeclTypesTests.Foo("bla") self.cur.execute("insert into test(foo) values (?)", (val,)) self.cur.execute("select foo from test") row = self.cur.fetchone() self.assertEqual(row[0], val) def CheckUnsupportedSeq(self): class Bar: pass val = Bar() try: self.cur.execute("insert into test(f) values (?)", (val,)) self.fail("should have raised an InterfaceError") except sqlite.InterfaceError: pass except: self.fail("should have raised an InterfaceError") def CheckUnsupportedDict(self): class Bar: pass val = Bar() try: self.cur.execute("insert into test(f) values (:val)", {"val": val}) self.fail("should have raised an InterfaceError") except sqlite.InterfaceError: pass except: self.fail("should have raised an InterfaceError") def CheckBlob(self): # default val = buffer("Guglhupf") self.cur.execute("insert into test(bin) values (?)", (val,)) self.cur.execute("select bin from test") row = self.cur.fetchone() self.assertEqual(row[0], val) def CheckNumber1(self): self.cur.execute("insert into test(n1) values (5)") value = self.cur.execute("select n1 from test").fetchone()[0] # if the converter is not used, it's an int instead of a float self.assertEqual(type(value), float) def CheckNumber2(self): """Checks wether converter names are cut off at '(' characters""" self.cur.execute("insert into test(n2) values (5)") value = self.cur.execute("select n2 from test").fetchone()[0] # if the converter is not used, it's an int instead of a float self.assertEqual(type(value), float) class ColNamesTests(unittest.TestCase): def setUp(self): self.con = sqlite.connect(":memory:", detect_types=sqlite.PARSE_COLNAMES) self.cur = self.con.cursor() self.cur.execute("create table test(x foo)") sqlite.converters["FOO"] = lambda x: "[%s]" % x sqlite.converters["BAR"] = lambda x: "<%s>" % x sqlite.converters["EXC"] = lambda x: 5 // 0 sqlite.converters["B1B1"] = lambda x: "MARKER" def tearDown(self): del sqlite.converters["FOO"] del sqlite.converters["BAR"] del sqlite.converters["EXC"] del sqlite.converters["B1B1"] self.cur.close() self.con.close() def CheckDeclTypeNotUsed(self): """ Assures that the declared type is not used when PARSE_DECLTYPES is not set. """ self.cur.execute("insert into test(x) values (?)", ("xxx",)) self.cur.execute("select x from test") val = self.cur.fetchone()[0] self.assertEqual(val, "xxx") def CheckNone(self): self.cur.execute("insert into test(x) values (?)", (None,)) self.cur.execute("select x from test") val = self.cur.fetchone()[0] self.assertEqual(val, None) def CheckColName(self): self.cur.execute("insert into test(x) values (?)", ("xxx",)) self.cur.execute('select x as "x [bar]" from test') val = self.cur.fetchone()[0] self.assertEqual(val, "") # Check if the stripping of colnames works. Everything after the first # whitespace should be stripped. self.assertEqual(self.cur.description[0][0], "x") def CheckCaseInConverterName(self): self.cur.execute("""select 'other' as "x [b1b1]\"""") val = self.cur.fetchone()[0] self.assertEqual(val, "MARKER") def CheckCursorDescriptionNoRow(self): """ cursor.description should at least provide the column name(s), even if no row returned. """ self.cur.execute("select * from test where 0 = 1") self.assert_(self.cur.description[0][0] == "x") class ObjectAdaptationTests(unittest.TestCase): def cast(obj): return float(obj) cast = staticmethod(cast) def setUp(self): self.con = sqlite.connect(":memory:") try: del sqlite.adapters[int] except: pass sqlite.register_adapter(int, ObjectAdaptationTests.cast) self.cur = self.con.cursor() def tearDown(self): del sqlite.adapters[(int, sqlite.PrepareProtocol)] self.cur.close() self.con.close() def CheckCasterIsUsed(self): self.cur.execute("select ?", (4,)) val = self.cur.fetchone()[0] self.assertEqual(type(val), float) class BinaryConverterTests(unittest.TestCase): def convert(s): return zlib.decompress(s) convert = staticmethod(convert) def setUp(self): self.con = sqlite.connect(":memory:", detect_types=sqlite.PARSE_COLNAMES) sqlite.register_converter("bin", BinaryConverterTests.convert) def tearDown(self): self.con.close() def CheckBinaryInputForConverter(self): testdata = "abcdefg" * 10 result = self.con.execute('select ? as "x [bin]"', (buffer(zlib.compress(testdata)),)).fetchone()[0] self.assertEqual(testdata, result) class DateTimeTests(unittest.TestCase): def setUp(self): self.con = sqlite.connect(":memory:", detect_types=sqlite.PARSE_DECLTYPES) self.cur = self.con.cursor() self.cur.execute("create table test(d date, ts timestamp)") def tearDown(self): self.cur.close() self.con.close() def CheckSqliteDate(self): d = sqlite.Date(2004, 2, 14) self.cur.execute("insert into test(d) values (?)", (d,)) self.cur.execute("select d from test") d2 = self.cur.fetchone()[0] self.assertEqual(d, d2) def CheckSqliteTimestamp(self): ts = sqlite.Timestamp(2004, 2, 14, 7, 15, 0) self.cur.execute("insert into test(ts) values (?)", (ts,)) self.cur.execute("select ts from test") ts2 = self.cur.fetchone()[0] self.assertEqual(ts, ts2) def CheckSqlTimestamp(self): # The date functions are only available in SQLite version 3.1 or later if sqlite.sqlite_version_info < (3, 1): return # SQLite's current_timestamp uses UTC time, while datetime.datetime.now() uses local time. now = datetime.datetime.now() self.cur.execute("insert into test(ts) values (current_timestamp)") self.cur.execute("select ts from test") ts = self.cur.fetchone()[0] self.assertEqual(type(ts), datetime.datetime) self.assertEqual(ts.year, now.year) def CheckDateTimeSubSeconds(self): ts = sqlite.Timestamp(2004, 2, 14, 7, 15, 0, 500000) self.cur.execute("insert into test(ts) values (?)", (ts,)) self.cur.execute("select ts from test") ts2 = self.cur.fetchone()[0] self.assertEqual(ts, ts2) def CheckDateTimeSubSecondsFloatingPoint(self): ts = sqlite.Timestamp(2004, 2, 14, 7, 15, 0, 510241) self.cur.execute("insert into test(ts) values (?)", (ts,)) self.cur.execute("select ts from test") ts2 = self.cur.fetchone()[0] self.assertEqual(ts, ts2) def suite(): sqlite_type_suite = unittest.makeSuite(SqliteTypeTests, "Check") decltypes_type_suite = unittest.makeSuite(DeclTypesTests, "Check") colnames_type_suite = unittest.makeSuite(ColNamesTests, "Check") adaptation_suite = unittest.makeSuite(ObjectAdaptationTests, "Check") bin_suite = unittest.makeSuite(BinaryConverterTests, "Check") date_suite = unittest.makeSuite(DateTimeTests, "Check") return unittest.TestSuite((sqlite_type_suite, decltypes_type_suite, colnames_type_suite, adaptation_suite, bin_suite, date_suite)) def test(): runner = unittest.TextTestRunner() runner.run(suite()) if __name__ == "__main__": test() pysqlite-2.6.3/lib/test/userfunctions.py000644 000765 000024 00000031641 11343755550 021346 0ustar00ghaeringstaff000000 000000 #-*- coding: ISO-8859-1 -*- # pysqlite2/test/userfunctions.py: tests for user-defined functions and # aggregates. # # Copyright (C) 2005-2007 Gerhard Häring # # This file is part of pysqlite. # # This software is provided 'as-is', without any express or implied # warranty. In no event will the authors be held liable for any damages # arising from the use of this software. # # Permission is granted to anyone to use this software for any purpose, # including commercial applications, and to alter it and redistribute it # freely, subject to the following restrictions: # # 1. The origin of this software must not be misrepresented; you must not # claim that you wrote the original software. If you use this software # in a product, an acknowledgment in the product documentation would be # appreciated but is not required. # 2. Altered source versions must be plainly marked as such, and must not be # misrepresented as being the original software. # 3. This notice may not be removed or altered from any source distribution. import unittest import pysqlite2.dbapi2 as sqlite def func_returntext(): return "foo" def func_returnunicode(): return u"bar" def func_returnint(): return 42 def func_returnfloat(): return 3.14 def func_returnnull(): return None def func_returnblob(): return buffer("blob") def func_raiseexception(): 5 // 0 def func_isstring(v): return type(v) is unicode def func_isint(v): return type(v) is int def func_isfloat(v): return type(v) is float def func_isnone(v): return type(v) is type(None) def func_isblob(v): return type(v) is buffer class AggrNoStep: def __init__(self): pass def finalize(self): return 1 class AggrNoFinalize: def __init__(self): pass def step(self, x): pass class AggrExceptionInInit: def __init__(self): 5 // 0 def step(self, x): pass def finalize(self): pass class AggrExceptionInStep: def __init__(self): pass def step(self, x): 5 // 0 def finalize(self): return 42 class AggrExceptionInFinalize: def __init__(self): pass def step(self, x): pass def finalize(self): 5 // 0 class AggrCheckType: def __init__(self): self.val = None def step(self, whichType, val): theType = {"str": unicode, "int": int, "float": float, "None": type(None), "blob": buffer} self.val = int(theType[whichType] is type(val)) def finalize(self): return self.val class AggrSum: def __init__(self): self.val = 0.0 def step(self, val): self.val += val def finalize(self): return self.val class FunctionTests(unittest.TestCase): def setUp(self): self.con = sqlite.connect(":memory:") self.con.create_function("returntext", 0, func_returntext) self.con.create_function("returnunicode", 0, func_returnunicode) self.con.create_function("returnint", 0, func_returnint) self.con.create_function("returnfloat", 0, func_returnfloat) self.con.create_function("returnnull", 0, func_returnnull) self.con.create_function("returnblob", 0, func_returnblob) self.con.create_function("raiseexception", 0, func_raiseexception) self.con.create_function("isstring", 1, func_isstring) self.con.create_function("isint", 1, func_isint) self.con.create_function("isfloat", 1, func_isfloat) self.con.create_function("isnone", 1, func_isnone) self.con.create_function("isblob", 1, func_isblob) def tearDown(self): self.con.close() def CheckFuncErrorOnCreate(self): try: self.con.create_function("bla", -100, lambda x: 2*x) self.fail("should have raised an OperationalError") except sqlite.OperationalError: pass def CheckFuncRefCount(self): def getfunc(): def f(): return 1 return f f = getfunc() globals()["foo"] = f # self.con.create_function("reftest", 0, getfunc()) self.con.create_function("reftest", 0, f) cur = self.con.cursor() cur.execute("select reftest()") def CheckFuncReturnText(self): cur = self.con.cursor() cur.execute("select returntext()") val = cur.fetchone()[0] self.assertEqual(type(val), unicode) self.assertEqual(val, "foo") def CheckFuncReturnUnicode(self): cur = self.con.cursor() cur.execute("select returnunicode()") val = cur.fetchone()[0] self.assertEqual(type(val), unicode) self.assertEqual(val, u"bar") def CheckFuncReturnInt(self): cur = self.con.cursor() cur.execute("select returnint()") val = cur.fetchone()[0] self.assertEqual(type(val), int) self.assertEqual(val, 42) def CheckFuncReturnFloat(self): cur = self.con.cursor() cur.execute("select returnfloat()") val = cur.fetchone()[0] self.assertEqual(type(val), float) if val < 3.139 or val > 3.141: self.fail("wrong value") def CheckFuncReturnNull(self): cur = self.con.cursor() cur.execute("select returnnull()") val = cur.fetchone()[0] self.assertEqual(type(val), type(None)) self.assertEqual(val, None) def CheckFuncReturnBlob(self): cur = self.con.cursor() cur.execute("select returnblob()") val = cur.fetchone()[0] self.assertEqual(type(val), buffer) self.assertEqual(val, buffer("blob")) def CheckFuncException(self): cur = self.con.cursor() try: cur.execute("select raiseexception()") cur.fetchone() self.fail("should have raised OperationalError") except sqlite.OperationalError, e: self.assertEqual(e.args[0], 'user-defined function raised exception') def CheckParamString(self): cur = self.con.cursor() cur.execute("select isstring(?)", ("foo",)) val = cur.fetchone()[0] self.assertEqual(val, 1) def CheckParamInt(self): cur = self.con.cursor() cur.execute("select isint(?)", (42,)) val = cur.fetchone()[0] self.assertEqual(val, 1) def CheckParamFloat(self): cur = self.con.cursor() cur.execute("select isfloat(?)", (3.14,)) val = cur.fetchone()[0] self.assertEqual(val, 1) def CheckParamNone(self): cur = self.con.cursor() cur.execute("select isnone(?)", (None,)) val = cur.fetchone()[0] self.assertEqual(val, 1) def CheckParamBlob(self): cur = self.con.cursor() cur.execute("select isblob(?)", (buffer("blob"),)) val = cur.fetchone()[0] self.assertEqual(val, 1) class AggregateTests(unittest.TestCase): def setUp(self): self.con = sqlite.connect(":memory:") cur = self.con.cursor() cur.execute(""" create table test( t text, i integer, f float, n, b blob ) """) cur.execute("insert into test(t, i, f, n, b) values (?, ?, ?, ?, ?)", ("foo", 5, 3.14, None, buffer("blob"),)) self.con.create_aggregate("nostep", 1, AggrNoStep) self.con.create_aggregate("nofinalize", 1, AggrNoFinalize) self.con.create_aggregate("excInit", 1, AggrExceptionInInit) self.con.create_aggregate("excStep", 1, AggrExceptionInStep) self.con.create_aggregate("excFinalize", 1, AggrExceptionInFinalize) self.con.create_aggregate("checkType", 2, AggrCheckType) self.con.create_aggregate("mysum", 1, AggrSum) def tearDown(self): #self.cur.close() #self.con.close() pass def CheckAggrErrorOnCreate(self): try: self.con.create_function("bla", -100, AggrSum) self.fail("should have raised an OperationalError") except sqlite.OperationalError: pass def CheckAggrNoStep(self): cur = self.con.cursor() try: cur.execute("select nostep(t) from test") self.fail("should have raised an AttributeError") except AttributeError, e: self.assertEqual(e.args[0], "AggrNoStep instance has no attribute 'step'") def CheckAggrNoFinalize(self): cur = self.con.cursor() try: cur.execute("select nofinalize(t) from test") val = cur.fetchone()[0] self.fail("should have raised an OperationalError") except sqlite.OperationalError, e: self.assertEqual(e.args[0], "user-defined aggregate's 'finalize' method raised error") def CheckAggrExceptionInInit(self): cur = self.con.cursor() try: cur.execute("select excInit(t) from test") val = cur.fetchone()[0] self.fail("should have raised an OperationalError") except sqlite.OperationalError, e: self.assertEqual(e.args[0], "user-defined aggregate's '__init__' method raised error") def CheckAggrExceptionInStep(self): cur = self.con.cursor() try: cur.execute("select excStep(t) from test") val = cur.fetchone()[0] self.fail("should have raised an OperationalError") except sqlite.OperationalError, e: self.assertEqual(e.args[0], "user-defined aggregate's 'step' method raised error") def CheckAggrExceptionInFinalize(self): cur = self.con.cursor() try: cur.execute("select excFinalize(t) from test") val = cur.fetchone()[0] self.fail("should have raised an OperationalError") except sqlite.OperationalError, e: self.assertEqual(e.args[0], "user-defined aggregate's 'finalize' method raised error") def CheckAggrCheckParamStr(self): cur = self.con.cursor() cur.execute("select checkType('str', ?)", ("foo",)) val = cur.fetchone()[0] self.assertEqual(val, 1) def CheckAggrCheckParamInt(self): cur = self.con.cursor() cur.execute("select checkType('int', ?)", (42,)) val = cur.fetchone()[0] self.assertEqual(val, 1) def CheckAggrCheckParamFloat(self): cur = self.con.cursor() cur.execute("select checkType('float', ?)", (3.14,)) val = cur.fetchone()[0] self.assertEqual(val, 1) def CheckAggrCheckParamNone(self): cur = self.con.cursor() cur.execute("select checkType('None', ?)", (None,)) val = cur.fetchone()[0] self.assertEqual(val, 1) def CheckAggrCheckParamBlob(self): cur = self.con.cursor() cur.execute("select checkType('blob', ?)", (buffer("blob"),)) val = cur.fetchone()[0] self.assertEqual(val, 1) def CheckAggrCheckAggrSum(self): cur = self.con.cursor() cur.execute("delete from test") cur.executemany("insert into test(i) values (?)", [(10,), (20,), (30,)]) cur.execute("select mysum(i) from test") val = cur.fetchone()[0] self.assertEqual(val, 60) def authorizer_cb(action, arg1, arg2, dbname, source): if action != sqlite.SQLITE_SELECT: return sqlite.SQLITE_DENY if arg2 == 'c2' or arg1 == 't2': return sqlite.SQLITE_DENY return sqlite.SQLITE_OK class AuthorizerTests(unittest.TestCase): def setUp(self): self.con = sqlite.connect(":memory:") self.con.executescript(""" create table t1 (c1, c2); create table t2 (c1, c2); insert into t1 (c1, c2) values (1, 2); insert into t2 (c1, c2) values (4, 5); """) # For our security test: self.con.execute("select c2 from t2") self.con.set_authorizer(authorizer_cb) def tearDown(self): pass def CheckTableAccess(self): try: self.con.execute("select * from t2") except sqlite.DatabaseError, e: if not e.args[0].endswith("prohibited"): self.fail("wrong exception text: %s" % e.args[0]) return self.fail("should have raised an exception due to missing privileges") def CheckColumnAccess(self): try: self.con.execute("select c2 from t1") except sqlite.DatabaseError, e: if not e.args[0].endswith("prohibited"): self.fail("wrong exception text: %s" % e.args[0]) return self.fail("should have raised an exception due to missing privileges") def suite(): function_suite = unittest.makeSuite(FunctionTests, "Check") aggregate_suite = unittest.makeSuite(AggregateTests, "Check") authorizer_suite = unittest.makeSuite(AuthorizerTests, "Check") return unittest.TestSuite((function_suite, aggregate_suite, authorizer_suite)) def test(): runner = unittest.TextTestRunner() runner.run(suite()) if __name__ == "__main__": test() pysqlite-2.6.3/lib/test/py25/__init__.py000644 000765 000024 00000000001 11343657406 020760 0ustar00ghaeringstaff000000 000000 pysqlite-2.6.3/lib/test/py25/py25tests.py000644 000765 000024 00000005271 11343723574 021121 0ustar00ghaeringstaff000000 000000 #-*- coding: ISO-8859-1 -*- # pysqlite2/test/regression.py: pysqlite regression tests # # Copyright (C) 2007 Gerhard Häring # # This file is part of pysqlite. # # This software is provided 'as-is', without any express or implied # warranty. In no event will the authors be held liable for any damages # arising from the use of this software. # # Permission is granted to anyone to use this software for any purpose, # including commercial applications, and to alter it and redistribute it # freely, subject to the following restrictions: # # 1. The origin of this software must not be misrepresented; you must not # claim that you wrote the original software. If you use this software # in a product, an acknowledgment in the product documentation would be # appreciated but is not required. # 2. Altered source versions must be plainly marked as such, and must not be # misrepresented as being the original software. # 3. This notice may not be removed or altered from any source distribution. from __future__ import with_statement import unittest import pysqlite2.dbapi2 as sqlite did_rollback = False class MyConnection(sqlite.Connection): def rollback(self): global did_rollback did_rollback = True sqlite.Connection.rollback(self) class ContextTests(unittest.TestCase): def setUp(self): global did_rollback self.con = sqlite.connect(":memory:", factory=MyConnection) self.con.execute("create table test(c unique)") did_rollback = False def tearDown(self): self.con.close() def CheckContextManager(self): """Can the connection be used as a context manager at all?""" with self.con: pass def CheckContextManagerCommit(self): """Is a commit called in the context manager?""" with self.con: self.con.execute("insert into test(c) values ('foo')") self.con.rollback() count = self.con.execute("select count(*) from test").fetchone()[0] self.assertEqual(count, 1) def CheckContextManagerRollback(self): """Is a rollback called in the context manager?""" global did_rollback self.assertEqual(did_rollback, False) try: with self.con: self.con.execute("insert into test(c) values (4)") self.con.execute("insert into test(c) values (4)") except sqlite.IntegrityError: pass self.assertEqual(did_rollback, True) def suite(): ctx_suite = unittest.makeSuite(ContextTests, "Check") return unittest.TestSuite((ctx_suite,)) def test(): runner = unittest.TextTestRunner() runner.run(suite()) if __name__ == "__main__": test() pysqlite-2.6.3/doc/includes/000755 000765 000024 00000000000 11526730255 016704 5ustar00ghaeringstaff000000 000000 pysqlite-2.6.3/doc/install-source.txt000644 000765 000024 00000014054 11343657406 020612 0ustar00ghaeringstaff000000 000000 ------------------------------------------------- pysqlite installation guide - source distribution ------------------------------------------------- \(c\) 2005 Gerhard Häring Note: For Windows users, it is recommended that you use the win32 binary distribution of pysqlite! Steps: - `Step 1: Satisfy the dependencies`_ - `Step 2: Compile pysqlite`_ - `Step 3: Install pysqlite`_ - `Step 4: Test your pysqlite installation`_ Step 1: Satisfy The Dependencies ================================ pysqlite requires a valid combination of the dependencies in the list below. Detailed instructions on how to install each dependency are beyond the scope of this document; consult the dependency distributor for installation instructions. Dependencies: 1. Operating System and C Compiler - one of: * Linux/FreeBSD/NetBSD/OpenBSD and GCC * Other POSIX-compliant operating system and a C compiler 2. SQLite: * SQLite version 3.0.8 or later (as of pysqlite 2.2.0). This means we need the SQLite library installed - either statically or dynamically linked - and the SQLite header files. On Linux, the chances are very high that your distribution offers packages for SQLite 3. Be sure to verify the package is recent enough (version 3.0.8 or higher) and that you're installing the development package as well, which will be need for building pysqlite. On Debian and derivatives, the package to look for is called libsqlite3-dev. 3. Python: * Python 2.3 or later Step 2: Compile pysqlite ======================== Once you have successfully installed the dependencies, you may proceed with the installation of pysqlite itself. pysqlite has full support for the distutils_, the standard facility for Python package distribution and installation. Full instructions for using the distutils are available in `this section of the Python documentation`_, but you can skip them unless you have an otherwise insoluble problem. Open a command prompt, change to the directory where you decompressed the pysqlite source distribution, and type:: python setup.py build The installation script, setup.py, will attempt to automatically detect the information needed by the C compiler; then it will invoke the distutils to perform the actual compilation. If you installed automatic distributions of the dependencies that place themselves in standard locations (on UNIX-style operating systems), the compilation should proceed without incident. Otherwise you will have to customize the build process. That's what the file *setup.cfg* is meant for. It's contains a few lines that you can customize so your C compiler will find the library and header files and you can also do a few other tweaks, like build pysqlite in debug mode. After you've customized *setup.cfg* appropriately, try invoking ``python setup.py build`` again. If setup.py raises no errors and its output concludes with something like "Creating library...", then you are ready to proceed to the next step. If you receive an error message from the compiler, then try to look at the first error it reports. Other errors will most likely be aftereffects from the first error (like not finding the sqlite3.h header file). Step 3: Install pysqlite ======================== During this step, the setup script moves the *pysqlite2* package (including the newly compiled C extension) to the standard package directory of your Python installation so that Python will be able to import pysqlite2.dbapi2 and pysqlite2.test. In addition to the Python code and shared library files actually used by the Python interpreter, the setup script typically installs some supporting files, such as documentation. Depending on your system configuration, these supporting files may be placed in the same directory or a different directory from the files used by the Python interpreter. Run the following command:: python setup.py install The setup script will install pysqlite, listing each file it installs. Errors during this step are rare because compilation (the finicky part of this process) has already taken place; installation is really just a matter of copying files. However, there will be file system permission errors if the Python installation directory is not writable by the user running the setup script. If you encounter such an error, try one of the following: - Log in as a user who has the required file system permissions and repeat the installation step. - Manually copy the directory build/lib.platform-pyver/pysqlite2 (which contains the Python modules and compiled library files created during the compilation step) to a directory in your PYTHONPATH. This approach will not install the supporting files, but they are for the benefit of the programmer rather than the Python interpreter anyway. Step 4: Test Your pysqlite Installation ======================================= Switch to a directory other than the temporary directory into which you decompressed the source distribution (to avoid conflict between the copy of pysqlite in that directory and the copy placed under the standard Python site-packages directory), then run the pysqlite test suite by starting a Python interpreter for the Python version you installed pysqlite for and entering the following:: >>> from pysqlite2 import test >>> test.test() ..................................................................................................... ---------------------------------------------------------------------- Ran 101 tests in 0.182s If the test suite runs without any errors, you are finished. You should not encounter any errors at this stage since you have already completed the compilation and installation steps successfully. If you do, please report them to the `pysqlite bug tracker`_ or the `pysqlite mailing list`_. .. _distutils: http://www.python.org/sigs/distutils-sig/ .. _this section of the Python documentation: http://www.python.org/doc/current/inst/inst.html .. _pysqlite bug tracker: http://pysqlite.googlecode.com/ .. _pysqlite mailing list: http://itsystementwicklung.de/cgi-bin/mailman/listinfo/list-pysqlite pysqlite-2.6.3/doc/sphinx/000755 000765 000024 00000000000 11526730255 016407 5ustar00ghaeringstaff000000 000000 pysqlite-2.6.3/doc/sphinx/.static/000755 000765 000024 00000000000 11526730255 017754 5ustar00ghaeringstaff000000 000000 pysqlite-2.6.3/doc/sphinx/conf.py000644 000765 000024 00000007676 11344205376 017725 0ustar00ghaeringstaff000000 000000 # -*- coding: utf-8 -*- # # pysqlite documentation build configuration file, created by # sphinx-quickstart.py on Sat Mar 22 02:47:54 2008. # # This file is execfile()d with the current directory set to its containing dir. # # The contents of this file are pickled, so don't put values in the namespace # that aren't pickleable (module imports are okay, they're removed automatically). # # All configuration values have a default value; values that are commented out # serve to show the default value. import sys # If your extensions are in another directory, add it here. #sys.path.append('some/directory') # General configuration # --------------------- # Add any Sphinx extension module names here, as strings. They can be extensions # coming with Sphinx (named 'sphinx.addons.*') or your custom ones. #extensions = [] # Add any paths that contain templates here, relative to this directory. templates_path = ['.templates'] # The suffix of source filenames. source_suffix = '.rst' # The master toctree document. master_doc = 'index' # General substitutions. project = 'pysqlite' copyright = u'2008-2009, Gerhard Häring' # The default replacements for |version| and |release|, also used in various # other places throughout the built documents. # # The short X.Y version. version = '2.6' # The full version, including alpha/beta/rc tags. release = '2.6.0' # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: #today = '' # Else, today_fmt is used as the format for a strftime call. today_fmt = '%B %d, %Y' # List of documents that shouldn't be included in the build. #unused_docs = [] # If true, '()' will be appended to :func: etc. cross-reference text. #add_function_parentheses = True # If true, the current module name will be prepended to all description # unit titles (such as .. function::). #add_module_names = True # If true, sectionauthor and moduleauthor directives will be shown in the # output. They are ignored by default. #show_authors = False # The name of the Pygments (syntax highlighting) style to use. pygments_style = 'sphinx' # Options for HTML output # ----------------------- # The style sheet to use for HTML and HTML Help pages. A file of that name # must exist either in Sphinx' static/ path, or in one of the custom paths # given in html_static_path. html_style = 'default.css' # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ['.static'] # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. html_last_updated_fmt = '%b %d, %Y' # If true, SmartyPants will be used to convert quotes and dashes to # typographically correct entities. #html_use_smartypants = True # Content template for the index page. #html_index = '' # Custom sidebar templates, maps document names to template names. #html_sidebars = {} # Additional templates that should be rendered to pages, maps page names to # template names. #html_additional_pages = {} # If false, no module index is generated. #html_use_modindex = True # If true, the reST sources are included in the HTML build as _sources/. #html_copy_source = True # Output file base name for HTML help builder. htmlhelp_basename = 'pysqlitedoc' # Options for LaTeX output # ------------------------ # The paper size ('letter' or 'a4'). #latex_paper_size = 'letter' # The font size ('10pt', '11pt' or '12pt'). #latex_font_size = '10pt' # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, author, document class [howto/manual]). #latex_documents = [] # Additional stuff for the LaTeX preamble. #latex_preamble = '' # Documents to append as an appendix to all manuals. #latex_appendices = [] # If false, no module index is generated. #latex_use_modindex = True pysqlite-2.6.3/doc/sphinx/index.rst000644 000765 000024 00000000653 11276752444 020262 0ustar00ghaeringstaff000000 000000 .. pysqlite documentation master file, created by sphinx-quickstart.py on Sat Mar 22 02:47:54 2008. You can adapt this file completely to your liking, but it should at least contain the root `toctree` directive. Welcome to pysqlite's documentation! ==================================== Contents: .. toctree:: :maxdepth: 2 Indices and tables ================== * :ref:`genindex` * :ref:`modindex` * :ref:`search` pysqlite-2.6.3/doc/sphinx/Makefile000644 000765 000024 00000004073 11371762611 020052 0ustar00ghaeringstaff000000 000000 # Makefile for Sphinx documentation # # You can set these variables from the command line. SPHINXOPTS = SPHINXBUILD = sphinx-build PAPER = ALLSPHINXOPTS = -d .build/doctrees -D latex_paper_size=$(PAPER) \ $(SPHINXOPTS) . .PHONY: help clean html web htmlhelp latex changes linkcheck help: @echo "Please use \`make ' where is one of" @echo " html to make standalone HTML files" @echo " web to make files usable by Sphinx.web" @echo " htmlhelp to make HTML files and a HTML help project" @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" @echo " changes to make an overview over all changed/added/deprecated items" @echo " linkcheck to check all external links for integrity" clean: -rm -rf .build/* html: mkdir -p .build/html .build/doctrees $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) .build/html @echo @echo "Build finished. The HTML pages are in .build/html." web: mkdir -p .build/web .build/doctrees $(SPHINXBUILD) -b web $(ALLSPHINXOPTS) .build/web @echo @echo "Build finished; now you can run" @echo " python -m sphinx.web .build/web" @echo "to start the server." htmlhelp: mkdir -p .build/htmlhelp .build/doctrees $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) .build/htmlhelp @echo @echo "Build finished; now you can run HTML Help Workshop with the" \ ".hhp project file in .build/htmlhelp." latex: mkdir -p .build/latex .build/doctrees $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) .build/latex @echo @echo "Build finished; the LaTeX files are in .build/latex." @echo "Run \`make all-pdf' or \`make all-ps' in that directory to" \ "run these through (pdf)latex." changes: mkdir -p .build/changes .build/doctrees $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) .build/changes @echo @echo "The overview file is in .build/changes." linkcheck: mkdir -p .build/linkcheck .build/doctrees $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) .build/linkcheck @echo @echo "Link check complete; look for any errors in the above output " \ "or in .build/linkcheck/output.txt." pysqlite-2.6.3/doc/sphinx/sqlite3.rst000644 000765 000024 00000100760 11426725232 020527 0ustar00ghaeringstaff000000 000000 :mod:`sqlite3` --- DB-API 2.0 interface for SQLite databases ============================================================ .. module:: sqlite3 :synopsis: A DB-API 2.0 implementation using SQLite 3.x. .. sectionauthor:: Gerhard Häring SQLite is a C library that provides a lightweight disk-based database that doesn't require a separate server process and allows accessing the database using a nonstandard variant of the SQL query language. Some applications can use SQLite for internal data storage. It's also possible to prototype an application using SQLite and then port the code to a larger database such as PostgreSQL or Oracle. pysqlite was written by Gerhard Häring and provides a SQL interface compliant with the DB-API 2.0 specification described by :pep:`249`. To use the module, you must first create a :class:`Connection` object that represents the database. Here the data will be stored in the :file:`/tmp/example` file:: conn = sqlite3.connect('/tmp/example') You can also supply the special name ``:memory:`` to create a database in RAM. Once you have a :class:`Connection`, you can create a :class:`Cursor` object and call its :meth:`~Cursor.execute` method to perform SQL commands:: c = conn.cursor() # Create table c.execute('''create table stocks (date text, trans text, symbol text, qty real, price real)''') # Insert a row of data c.execute("""insert into stocks values ('2006-01-05','BUY','RHAT',100,35.14)""") # Save (commit) the changes conn.commit() # We can also close the cursor if we are done with it c.close() Usually your SQL operations will need to use values from Python variables. You shouldn't assemble your query using Python's string operations because doing so is insecure; it makes your program vulnerable to an SQL injection attack. Instead, use the DB-API's parameter substitution. Put ``?`` as a placeholder wherever you want to use a value, and then provide a tuple of values as the second argument to the cursor's :meth:`~Cursor.execute` method. (Other database modules may use a different placeholder, such as ``%s`` or ``:1``.) For example:: # Never do this -- insecure! symbol = 'IBM' c.execute("... where symbol = '%s'" % symbol) # Do this instead t = (symbol,) c.execute('select * from stocks where symbol=?', t) # Larger example for t in [('2006-03-28', 'BUY', 'IBM', 1000, 45.00), ('2006-04-05', 'BUY', 'MSOFT', 1000, 72.00), ('2006-04-06', 'SELL', 'IBM', 500, 53.00), ]: c.execute('insert into stocks values (?,?,?,?,?)', t) To retrieve data after executing a SELECT statement, you can either treat the cursor as an :term:`iterator`, call the cursor's :meth:`~Cursor.fetchone` method to retrieve a single matching row, or call :meth:`~Cursor.fetchall` to get a list of the matching rows. This example uses the iterator form:: >>> c = conn.cursor() >>> c.execute('select * from stocks order by price') >>> for row in c: ... print row ... (u'2006-01-05', u'BUY', u'RHAT', 100, 35.14) (u'2006-03-28', u'BUY', u'IBM', 1000, 45.0) (u'2006-04-06', u'SELL', u'IBM', 500, 53.0) (u'2006-04-05', u'BUY', u'MSOFT', 1000, 72.0) >>> .. seealso:: http://code.google.com/p/pysqlite/ The pysqlite web page -- sqlite3 is developed externally under the name "pysqlite". http://www.sqlite.org The SQLite web page; the documentation describes the syntax and the available data types for the supported SQL dialect. :pep:`249` - Database API Specification 2.0 PEP written by Marc-André Lemburg. .. _sqlite3-module-contents: Module functions and constants ------------------------------ .. data:: PARSE_DECLTYPES This constant is meant to be used with the *detect_types* parameter of the :func:`connect` function. Setting it makes the :mod:`sqlite3` module parse the declared type for each column it returns. It will parse out the first word of the declared type, i. e. for "integer primary key", it will parse out "integer", or for "number(10)" it will parse out "number". Then for that column, it will look into the converters dictionary and use the converter function registered for that type there. .. data:: PARSE_COLNAMES This constant is meant to be used with the *detect_types* parameter of the :func:`connect` function. Setting this makes the SQLite interface parse the column name for each column it returns. It will look for a string formed [mytype] in there, and then decide that 'mytype' is the type of the column. It will try to find an entry of 'mytype' in the converters dictionary and then use the converter function found there to return the value. The column name found in :attr:`Cursor.description` is only the first word of the column name, i. e. if you use something like ``'as "x [datetime]"'`` in your SQL, then we will parse out everything until the first blank for the column name: the column name would simply be "x". .. function:: connect(database[, timeout, isolation_level, detect_types, factory]) Opens a connection to the SQLite database file *database*. You can use ``":memory:"`` to open a database connection to a database that resides in RAM instead of on disk. When a database is accessed by multiple connections, and one of the processes modifies the database, the SQLite database is locked until that transaction is committed. The *timeout* parameter specifies how long the connection should wait for the lock to go away until raising an exception. The default for the timeout parameter is 5.0 (five seconds). For the *isolation_level* parameter, please see the :attr:`Connection.isolation_level` property of :class:`Connection` objects. SQLite natively supports only the types TEXT, INTEGER, FLOAT, BLOB and NULL. If you want to use other types you must add support for them yourself. The *detect_types* parameter and the using custom **converters** registered with the module-level :func:`register_converter` function allow you to easily do that. *detect_types* defaults to 0 (i. e. off, no type detection), you can set it to any combination of :const:`PARSE_DECLTYPES` and :const:`PARSE_COLNAMES` to turn type detection on. By default, the :mod:`sqlite3` module uses its :class:`Connection` class for the connect call. You can, however, subclass the :class:`Connection` class and make :func:`connect` use your class instead by providing your class for the *factory* parameter. Consult the section :ref:`sqlite3-types` of this manual for details. The :mod:`sqlite3` module internally uses a statement cache to avoid SQL parsing overhead. If you want to explicitly set the number of statements that are cached for the connection, you can set the *cached_statements* parameter. The currently implemented default is to cache 100 statements. .. function:: register_converter(typename, callable) Registers a callable to convert a bytestring from the database into a custom Python type. The callable will be invoked for all database values that are of the type *typename*. Confer the parameter *detect_types* of the :func:`connect` function for how the type detection works. Note that the case of *typename* and the name of the type in your query must match! .. function:: register_adapter(type, callable) Registers a callable to convert the custom Python type *type* into one of SQLite's supported types. The callable *callable* accepts as single parameter the Python value, and must return a value of the following types: int, long, float, str (UTF-8 encoded), unicode or buffer. .. function:: complete_statement(sql) Returns :const:`True` if the string *sql* contains one or more complete SQL statements terminated by semicolons. It does not verify that the SQL is syntactically correct, only that there are no unclosed string literals and the statement is terminated by a semicolon. This can be used to build a shell for SQLite, as in the following example: .. literalinclude:: ../includes/sqlite3/complete_statement.py .. function:: enable_callback_tracebacks(flag) By default you will not get any tracebacks in user-defined functions, aggregates, converters, authorizer callbacks etc. If you want to debug them, you can call this function with *flag* as True. Afterwards, you will get tracebacks from callbacks on ``sys.stderr``. Use :const:`False` to disable the feature again. .. _sqlite3-connection-objects: Connection Objects ------------------ .. class:: Connection A SQLite database connection has the following attributes and methods: .. attribute:: Connection.isolation_level Get or set the current isolation level. :const:`None` for autocommit mode or one of "DEFERRED", "IMMEDIATE" or "EXCLUSIVE". See section :ref:`sqlite3-controlling-transactions` for a more detailed explanation. .. method:: Connection.cursor([cursorClass]) The cursor method accepts a single optional parameter *cursorClass*. If supplied, this must be a custom cursor class that extends :class:`sqlite3.Cursor`. .. method:: Connection.commit() This method commits the current transaction. If you don't call this method, anything you did since the last call to ``commit()`` is not visible from from other database connections. If you wonder why you don't see the data you've written to the database, please check you didn't forget to call this method. .. method:: Connection.rollback() This method rolls back any changes to the database since the last call to :meth:`commit`. .. method:: Connection.close() This closes the database connection. Note that this does not automatically call :meth:`commit`. If you just close your database connection without calling :meth:`commit` first, your changes will be lost! .. method:: Connection.execute(sql, [parameters]) This is a nonstandard shortcut that creates an intermediate cursor object by calling the cursor method, then calls the cursor's :meth:`execute` method with the parameters given. .. method:: Connection.executemany(sql, [parameters]) This is a nonstandard shortcut that creates an intermediate cursor object by calling the cursor method, then calls the cursor's :meth:`executemany` method with the parameters given. .. method:: Connection.executescript(sql_script) This is a nonstandard shortcut that creates an intermediate cursor object by calling the cursor method, then calls the cursor's :meth:`executescript` method with the parameters given. .. method:: Connection.create_function(name, num_params, func) Creates a user-defined function that you can later use from within SQL statements under the function name *name*. *num_params* is the number of parameters the function accepts, and *func* is a Python callable that is called as the SQL function. The function can return any of the types supported by SQLite: unicode, str, int, long, float, buffer and None. Example: .. literalinclude:: ../includes/sqlite3/md5func.py .. method:: Connection.create_aggregate(name, num_params, aggregate_class) Creates a user-defined aggregate function. The aggregate class must implement a ``step`` method, which accepts the number of parameters *num_params*, and a ``finalize`` method which will return the final result of the aggregate. The ``finalize`` method can return any of the types supported by SQLite: unicode, str, int, long, float, buffer and None. Example: .. literalinclude:: ../includes/sqlite3/mysumaggr.py .. method:: Connection.create_collation(name, callable) Creates a collation with the specified *name* and *callable*. The callable will be passed two string arguments. It should return -1 if the first is ordered lower than the second, 0 if they are ordered equal and 1 if the first is ordered higher than the second. Note that this controls sorting (ORDER BY in SQL) so your comparisons don't affect other SQL operations. Note that the callable will get its parameters as Python bytestrings, which will normally be encoded in UTF-8. The following example shows a custom collation that sorts "the wrong way": .. literalinclude:: ../includes/sqlite3/collation_reverse.py To remove a collation, call ``create_collation`` with None as callable:: con.create_collation("reverse", None) .. method:: Connection.interrupt() You can call this method from a different thread to abort any queries that might be executing on the connection. The query will then abort and the caller will get an exception. .. method:: Connection.set_authorizer(authorizer_callback) This routine registers a callback. The callback is invoked for each attempt to access a column of a table in the database. The callback should return :const:`SQLITE_OK` if access is allowed, :const:`SQLITE_DENY` if the entire SQL statement should be aborted with an error and :const:`SQLITE_IGNORE` if the column should be treated as a NULL value. These constants are available in the :mod:`sqlite3` module. The first argument to the callback signifies what kind of operation is to be authorized. The second and third argument will be arguments or :const:`None` depending on the first argument. The 4th argument is the name of the database ("main", "temp", etc.) if applicable. The 5th argument is the name of the inner-most trigger or view that is responsible for the access attempt or :const:`None` if this access attempt is directly from input SQL code. Please consult the SQLite documentation about the possible values for the first argument and the meaning of the second and third argument depending on the first one. All necessary constants are available in the :mod:`sqlite3` module. .. method:: Connection.set_progress_handler(handler, n) This routine registers a callback. The callback is invoked for every *n* instructions of the SQLite virtual machine. This is useful if you want to get called from SQLite during long-running operations, for example to update a GUI. If you want to clear any previously installed progress handler, call the method with :const:`None` for *handler*. .. method:: Connection.enable_load_extension(enabled) This routine allows/disallows the SQLite engine to load SQLite extensions from shared libraries. SQLite extensions can define new functions, aggregates or whole new virtual table implementations. One well-known extension is the fulltext-search extension distributed with SQLite. .. literalinclude:: ../includes/sqlite3/load_extension.py .. method:: Connection.load_extension(path) This routine loads a SQLite extension from a shared library. You have to enable extension loading with ``enable_load_extension`` before you can use this routine. .. attribute:: Connection.row_factory You can change this attribute to a callable that accepts the cursor and the original row as a tuple and will return the real result row. This way, you can implement more advanced ways of returning results, such as returning an object that can also access columns by name. Example: .. literalinclude:: ../includes/sqlite3/row_factory.py If returning a tuple doesn't suffice and you want name-based access to columns, you should consider setting :attr:`row_factory` to the highly-optimized :class:`sqlite3.Row` type. :class:`Row` provides both index-based and case-insensitive name-based access to columns with almost no memory overhead. It will probably be better than your own custom dictionary-based approach or even a db_row based solution. .. XXX what's a db_row-based solution? .. attribute:: Connection.text_factory Using this attribute you can control what objects are returned for the ``TEXT`` data type. By default, this attribute is set to :class:`unicode` and the :mod:`sqlite3` module will return Unicode objects for ``TEXT``. If you want to return bytestrings instead, you can set it to :class:`str`. For efficiency reasons, there's also a way to return Unicode objects only for non-ASCII data, and bytestrings otherwise. To activate it, set this attribute to :const:`sqlite3.OptimizedUnicode`. You can also set it to any other callable that accepts a single bytestring parameter and returns the resulting object. See the following example code for illustration: .. literalinclude:: ../includes/sqlite3/text_factory.py .. attribute:: Connection.total_changes Returns the total number of database rows that have been modified, inserted, or deleted since the database connection was opened. .. attribute:: Connection.iterdump Returns an iterator to dump the database in an SQL text format. Useful when saving an in-memory database for later restoration. This function provides the same capabilities as the :kbd:`.dump` command in the :program:`sqlite3` shell. Example:: # Convert file existing_db.db to SQL dump file dump.sql import sqlite3, os con = sqlite3.connect('existing_db.db') full_dump = os.linesep.join([line for line in con.iterdump()]) f = open('dump.sql', 'w') f.writelines(full_dump) f.close() .. _sqlite3-cursor-objects: Cursor Objects -------------- A :class:`Cursor` instance has the following attributes and methods: A SQLite database cursor has the following attributes and methods: .. method:: Cursor.execute(sql, [parameters]) Executes an SQL statement. The SQL statement may be parametrized (i. e. placeholders instead of SQL literals). The :mod:`sqlite3` module supports two kinds of placeholders: question marks (qmark style) and named placeholders (named style). This example shows how to use parameters with qmark style: .. literalinclude:: ../includes/sqlite3/execute_1.py This example shows how to use the named style: .. literalinclude:: ../includes/sqlite3/execute_2.py :meth:`execute` will only execute a single SQL statement. If you try to execute more than one statement with it, it will raise a Warning. Use :meth:`executescript` if you want to execute multiple SQL statements with one call. .. method:: Cursor.executemany(sql, seq_of_parameters) Executes an SQL command against all parameter sequences or mappings found in the sequence *sql*. The :mod:`sqlite3` module also allows using an :term:`iterator` yielding parameters instead of a sequence. .. literalinclude:: ../includes/sqlite3/executemany_1.py Here's a shorter example using a :term:`generator`: .. literalinclude:: ../includes/sqlite3/executemany_2.py .. method:: Cursor.executescript(sql_script) This is a nonstandard convenience method for executing multiple SQL statements at once. It issues a ``COMMIT`` statement first, then executes the SQL script it gets as a parameter. *sql_script* can be a bytestring or a Unicode string. Example: .. literalinclude:: ../includes/sqlite3/executescript.py .. method:: Cursor.fetchone() Fetches the next row of a query result set, returning a single sequence, or :const:`None` when no more data is available. .. method:: Cursor.fetchmany([size=cursor.arraysize]) Fetches the next set of rows of a query result, returning a list. An empty list is returned when no more rows are available. The number of rows to fetch per call is specified by the *size* parameter. If it is not given, the cursor's arraysize determines the number of rows to be fetched. The method should try to fetch as many rows as indicated by the size parameter. If this is not possible due to the specified number of rows not being available, fewer rows may be returned. Note there are performance considerations involved with the *size* parameter. For optimal performance, it is usually best to use the arraysize attribute. If the *size* parameter is used, then it is best for it to retain the same value from one :meth:`fetchmany` call to the next. .. method:: Cursor.fetchall() Fetches all (remaining) rows of a query result, returning a list. Note that the cursor's arraysize attribute can affect the performance of this operation. An empty list is returned when no rows are available. .. attribute:: Cursor.rowcount Although the :class:`Cursor` class of the :mod:`sqlite3` module implements this attribute, the database engine's own support for the determination of "rows affected"/"rows selected" is quirky. For ``DELETE`` statements, SQLite reports :attr:`rowcount` as 0 if you make a ``DELETE FROM table`` without any condition. For :meth:`executemany` statements, the number of modifications are summed up into :attr:`rowcount`. As required by the Python DB API Spec, the :attr:`rowcount` attribute "is -1 in case no ``executeXX()`` has been performed on the cursor or the rowcount of the last operation is not determinable by the interface". This includes ``SELECT`` statements because we cannot determine the number of rows a query produced until all rows were fetched. .. attribute:: Cursor.lastrowid This read-only attribute provides the rowid of the last modified row. It is only set if you issued a ``INSERT`` statement using the :meth:`execute` method. For operations other than ``INSERT`` or when :meth:`executemany` is called, :attr:`lastrowid` is set to :const:`None`. .. attribute:: Cursor.description This read-only attribute provides the column names of the last query. To remain compatible with the Python DB API, it returns a 7-tuple for each column where the last six items of each tuple are :const:`None`. It is set for ``SELECT`` statements without any matching rows as well. .. _sqlite3-row-objects: Row Objects ----------- .. class:: Row A :class:`Row` instance serves as a highly optimized :attr:`~Connection.row_factory` for :class:`Connection` objects. It tries to mimic a tuple in most of its features. It supports mapping access by column name and index, iteration, representation, equality testing and :func:`len`. If two :class:`Row` objects have exactly the same columns and their members are equal, they compare equal. .. versionchanged:: 2.6 Added iteration and equality (hashability). .. method:: keys This method returns a tuple of column names. Immediately after a query, it is the first member of each tuple in :attr:`Cursor.description`. .. versionadded:: 2.6 Let's assume we initialize a table as in the example given above:: conn = sqlite3.connect(":memory:") c = conn.cursor() c.execute('''create table stocks (date text, trans text, symbol text, qty real, price real)''') c.execute("""insert into stocks values ('2006-01-05','BUY','RHAT',100,35.14)""") conn.commit() c.close() Now we plug :class:`Row` in:: >>> conn.row_factory = sqlite3.Row >>> c = conn.cursor() >>> c.execute('select * from stocks') >>> r = c.fetchone() >>> type(r) >>> r (u'2006-01-05', u'BUY', u'RHAT', 100.0, 35.14) >>> len(r) 5 >>> r[2] u'RHAT' >>> r.keys() ['date', 'trans', 'symbol', 'qty', 'price'] >>> r['qty'] 100.0 >>> for member in r: print member ... 2006-01-05 BUY RHAT 100.0 35.14 .. _sqlite3-types: SQLite and Python types ----------------------- Introduction ^^^^^^^^^^^^ SQLite natively supports the following types: ``NULL``, ``INTEGER``, ``REAL``, ``TEXT``, ``BLOB``. The following Python types can thus be sent to SQLite without any problem: +-----------------------------+-------------+ | Python type | SQLite type | +=============================+=============+ | :const:`None` | ``NULL`` | +-----------------------------+-------------+ | :class:`int` | ``INTEGER`` | +-----------------------------+-------------+ | :class:`long` | ``INTEGER`` | +-----------------------------+-------------+ | :class:`float` | ``REAL`` | +-----------------------------+-------------+ | :class:`str` (UTF8-encoded) | ``TEXT`` | +-----------------------------+-------------+ | :class:`unicode` | ``TEXT`` | +-----------------------------+-------------+ | :class:`buffer` | ``BLOB`` | +-----------------------------+-------------+ This is how SQLite types are converted to Python types by default: +-------------+----------------------------------------------+ | SQLite type | Python type | +=============+==============================================+ | ``NULL`` | :const:`None` | +-------------+----------------------------------------------+ | ``INTEGER`` | :class:`int` or :class:`long`, | | | depending on size | +-------------+----------------------------------------------+ | ``REAL`` | :class:`float` | +-------------+----------------------------------------------+ | ``TEXT`` | depends on :attr:`~Connection.text_factory`, | | | :class:`unicode` by default | +-------------+----------------------------------------------+ | ``BLOB`` | :class:`buffer` | +-------------+----------------------------------------------+ The type system of the :mod:`sqlite3` module is extensible in two ways: you can store additional Python types in a SQLite database via object adaptation, and you can let the :mod:`sqlite3` module convert SQLite types to different Python types via converters. Using adapters to store additional Python types in SQLite databases ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ As described before, SQLite supports only a limited set of types natively. To use other Python types with SQLite, you must **adapt** them to one of the sqlite3 module's supported types for SQLite: one of NoneType, int, long, float, str, unicode, buffer. The :mod:`sqlite3` module uses Python object adaptation, as described in :pep:`246` for this. The protocol to use is :class:`PrepareProtocol`. There are two ways to enable the :mod:`sqlite3` module to adapt a custom Python type to one of the supported ones. Letting your object adapt itself """""""""""""""""""""""""""""""" This is a good approach if you write the class yourself. Let's suppose you have a class like this:: class Point(object): def __init__(self, x, y): self.x, self.y = x, y Now you want to store the point in a single SQLite column. First you'll have to choose one of the supported types first to be used for representing the point. Let's just use str and separate the coordinates using a semicolon. Then you need to give your class a method ``__conform__(self, protocol)`` which must return the converted value. The parameter *protocol* will be :class:`PrepareProtocol`. .. literalinclude:: ../includes/sqlite3/adapter_point_1.py Registering an adapter callable """"""""""""""""""""""""""""""" The other possibility is to create a function that converts the type to the string representation and register the function with :meth:`register_adapter`. .. note:: The type/class to adapt must be a :term:`new-style class`, i. e. it must have :class:`object` as one of its bases. .. literalinclude:: ../includes/sqlite3/adapter_point_2.py The :mod:`sqlite3` module has two default adapters for Python's built-in :class:`datetime.date` and :class:`datetime.datetime` types. Now let's suppose we want to store :class:`datetime.datetime` objects not in ISO representation, but as a Unix timestamp. .. literalinclude:: ../includes/sqlite3/adapter_datetime.py Converting SQLite values to custom Python types ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Writing an adapter lets you send custom Python types to SQLite. But to make it really useful we need to make the Python to SQLite to Python roundtrip work. Enter converters. Let's go back to the :class:`Point` class. We stored the x and y coordinates separated via semicolons as strings in SQLite. First, we'll define a converter function that accepts the string as a parameter and constructs a :class:`Point` object from it. .. note:: Converter functions **always** get called with a string, no matter under which data type you sent the value to SQLite. :: def convert_point(s): x, y = map(float, s.split(";")) return Point(x, y) Now you need to make the :mod:`sqlite3` module know that what you select from the database is actually a point. There are two ways of doing this: * Implicitly via the declared type * Explicitly via the column name Both ways are described in section :ref:`sqlite3-module-contents`, in the entries for the constants :const:`PARSE_DECLTYPES` and :const:`PARSE_COLNAMES`. The following example illustrates both approaches. .. literalinclude:: ../includes/sqlite3/converter_point.py Default adapters and converters ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ There are default adapters for the date and datetime types in the datetime module. They will be sent as ISO dates/ISO timestamps to SQLite. The default converters are registered under the name "date" for :class:`datetime.date` and under the name "timestamp" for :class:`datetime.datetime`. This way, you can use date/timestamps from Python without any additional fiddling in most cases. The format of the adapters is also compatible with the experimental SQLite date/time functions. The following example demonstrates this. .. literalinclude:: ../includes/sqlite3/pysqlite_datetime.py .. _sqlite3-controlling-transactions: Controlling Transactions ------------------------ By default, the :mod:`sqlite3` module opens transactions implicitly before a Data Modification Language (DML) statement (i.e. ``INSERT``/``UPDATE``/``DELETE``/``REPLACE``), and commits transactions implicitly before a non-DML, non-query statement (i. e. anything other than ``SELECT`` or the aforementioned). So if you are within a transaction and issue a command like ``CREATE TABLE ...``, ``VACUUM``, ``PRAGMA``, the :mod:`sqlite3` module will commit implicitly before executing that command. There are two reasons for doing that. The first is that some of these commands don't work within transactions. The other reason is that pysqlite needs to keep track of the transaction state (if a transaction is active or not). You can control which kind of ``BEGIN`` statements sqlite3 implicitly executes (or none at all) via the *isolation_level* parameter to the :func:`connect` call, or via the :attr:`isolation_level` property of connections. If you want **autocommit mode**, then set :attr:`isolation_level` to None. Otherwise leave it at its default, which will result in a plain "BEGIN" statement, or set it to one of SQLite's supported isolation levels: "DEFERRED", "IMMEDIATE" or "EXCLUSIVE". Using :mod:`sqlite3` efficiently -------------------------------- Using shortcut methods ^^^^^^^^^^^^^^^^^^^^^^ Using the nonstandard :meth:`execute`, :meth:`executemany` and :meth:`executescript` methods of the :class:`Connection` object, your code can be written more concisely because you don't have to create the (often superfluous) :class:`Cursor` objects explicitly. Instead, the :class:`Cursor` objects are created implicitly and these shortcut methods return the cursor objects. This way, you can execute a ``SELECT`` statement and iterate over it directly using only a single call on the :class:`Connection` object. .. literalinclude:: ../includes/sqlite3/shortcut_methods.py Accessing columns by name instead of by index ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ One useful feature of the :mod:`sqlite3` module is the built-in :class:`sqlite3.Row` class designed to be used as a row factory. Rows wrapped with this class can be accessed both by index (like tuples) and case-insensitively by name: .. literalinclude:: ../includes/sqlite3/rowclass.py Using the connection as a context manager ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ With Python 2.5 or higher, connection objects can be used as context managers that automatically commit or rollback transactions. In the event of an exception, the transaction is rolled back; otherwise, the transaction is committed: .. literalinclude:: ../includes/sqlite3/ctx_manager.py Common issues ------------- Multithreading ^^^^^^^^^^^^^^ Older SQLite versions had issues with sharing connections between threads. That's why the Python module disallows sharing connections and cursors between threads. If you still try to do so, you will get an exception at runtime. The only exception is calling the :meth:`~Connection.interrupt` method, which only makes sense to call from a different thread. pysqlite-2.6.3/doc/sphinx/.static/.keepme000644 000765 000024 00000000000 11276752444 021217 0ustar00ghaeringstaff000000 000000 pysqlite-2.6.3/doc/includes/sqlite3/000755 000765 000024 00000000000 11526730255 020270 5ustar00ghaeringstaff000000 000000 pysqlite-2.6.3/doc/includes/sqlite3/adapter_datetime.py000644 000765 000024 00000000510 11343657406 024135 0ustar00ghaeringstaff000000 000000 from pysqlite2 import dbapi2 as sqlite3 import datetime, time def adapt_datetime(ts): return time.mktime(ts.timetuple()) sqlite3.register_adapter(datetime.datetime, adapt_datetime) con = sqlite3.connect(":memory:") cur = con.cursor() now = datetime.datetime.now() cur.execute("select ?", (now,)) print cur.fetchone()[0] pysqlite-2.6.3/doc/includes/sqlite3/adapter_point_1.py000644 000765 000024 00000000600 11343657406 023712 0ustar00ghaeringstaff000000 000000 from pysqlite2 import dbapi2 as sqlite3 class Point(object): def __init__(self, x, y): self.x, self.y = x, y def __conform__(self, protocol): if protocol is sqlite3.PrepareProtocol: return "%f;%f" % (self.x, self.y) con = sqlite3.connect(":memory:") cur = con.cursor() p = Point(4.0, -3.2) cur.execute("select ?", (p,)) print cur.fetchone()[0] pysqlite-2.6.3/doc/includes/sqlite3/adapter_point_2.py000644 000765 000024 00000000553 11343657406 023722 0ustar00ghaeringstaff000000 000000 from pysqlite2 import dbapi2 as sqlite3 class Point(object): def __init__(self, x, y): self.x, self.y = x, y def adapt_point(point): return "%f;%f" % (point.x, point.y) sqlite3.register_adapter(Point, adapt_point) con = sqlite3.connect(":memory:") cur = con.cursor() p = Point(4.0, -3.2) cur.execute("select ?", (p,)) print cur.fetchone()[0] pysqlite-2.6.3/doc/includes/sqlite3/apsw_example.py000644 000765 000024 00000000510 11343657406 023326 0ustar00ghaeringstaff000000 000000 from pysqlite2 import dbapi2 as sqlite3 import apsw apsw_con = apsw.Connection(":memory:") apsw_con.createscalarfunction("times_two", lambda x: 2*x, 1) # Create pysqlite connection from APSW connection con = sqlite3.connect(apsw_con) result = con.execute("select times_two(15)").fetchone()[0] assert result == 30 con.close() pysqlite-2.6.3/doc/includes/sqlite3/authorizer.py000644 000765 000024 00000001434 11343657406 023043 0ustar00ghaeringstaff000000 000000 from pysqlite2 import dbapi2 as sqlite3 def authorizer_callback(action, arg1, arg2, dbname, source): if action != sqlite3.SQLITE_SELECT: return sqlite3.SQLITE_DENY if arg1 == "private_table": return sqlite3.SQLITE_DENY return sqlite3.SQLITE_OK con = sqlite3.connect(":memory:") con.executescript(""" create table public_table(c1, c2); create table private_table(c1, c2); """) con.set_authorizer(authorizer_callback) try: con.execute("select * from private_table") except sqlite3.DatabaseError, e: print "SELECT FROM private_table =>", e.args[0] # access ... prohibited try: con.execute("insert into public_table(c1, c2) values (1, 2)") except sqlite3.DatabaseError, e: print "DML command =>", e.args[0] # access ... prohibited pysqlite-2.6.3/doc/includes/sqlite3/collation_reverse.py000644 000765 000024 00000000651 11343657406 024366 0ustar00ghaeringstaff000000 000000 from pysqlite2 import dbapi2 as sqlite3 def collate_reverse(string1, string2): return -cmp(string1, string2) con = sqlite3.connect(":memory:") con.create_collation("reverse", collate_reverse) cur = con.cursor() cur.execute("create table test(x)") cur.executemany("insert into test(x) values (?)", [("a",), ("b",)]) cur.execute("select x from test order by x collate reverse") for row in cur: print row con.close() pysqlite-2.6.3/doc/includes/sqlite3/complete_statement.py000644 000765 000024 00000001266 11343657406 024546 0ustar00ghaeringstaff000000 000000 # A minimal SQLite shell for experiments from pysqlite2 import dbapi2 as sqlite3 con = sqlite3.connect(":memory:") con.isolation_level = None cur = con.cursor() buffer = "" print "Enter your SQL commands to execute in SQLite." print "Enter a blank line to exit." while True: line = raw_input() if line == "": break buffer += line if sqlite3.complete_statement(buffer): try: buffer = buffer.strip() cur.execute(buffer) if buffer.lstrip().upper().startswith("SELECT"): print cur.fetchall() except sqlite3.Error, e: print "An error occurred:", e.args[0] buffer = "" con.close() pysqlite-2.6.3/doc/includes/sqlite3/connect_db_1.py000644 000765 000024 00000000107 11343657406 023161 0ustar00ghaeringstaff000000 000000 from pysqlite2 import dbapi2 as sqlite3 con = sqlite3.connect("mydb") pysqlite-2.6.3/doc/includes/sqlite3/connect_db_2.py000644 000765 000024 00000000113 11343657406 023157 0ustar00ghaeringstaff000000 000000 from pysqlite2 import dbapi2 as sqlite3 con = sqlite3.connect(":memory:") pysqlite-2.6.3/doc/includes/sqlite3/converter_point.py000644 000765 000024 00000002256 11343657406 024072 0ustar00ghaeringstaff000000 000000 from pysqlite2 import dbapi2 as sqlite3 class Point(object): def __init__(self, x, y): self.x, self.y = x, y def __repr__(self): return "(%f;%f)" % (self.x, self.y) def adapt_point(point): return "%f;%f" % (point.x, point.y) def convert_point(s): x, y = map(float, s.split(";")) return Point(x, y) # Register the adapter sqlite3.register_adapter(Point, adapt_point) # Register the converter sqlite3.register_converter("point", convert_point) p = Point(4.0, -3.2) ######################### # 1) Using declared types con = sqlite3.connect(":memory:", detect_types=sqlite3.PARSE_DECLTYPES) cur = con.cursor() cur.execute("create table test(p point)") cur.execute("insert into test(p) values (?)", (p,)) cur.execute("select p from test") print "with declared types:", cur.fetchone()[0] cur.close() con.close() ####################### # 1) Using column names con = sqlite3.connect(":memory:", detect_types=sqlite3.PARSE_COLNAMES) cur = con.cursor() cur.execute("create table test(p)") cur.execute("insert into test(p) values (?)", (p,)) cur.execute('select p as "p [point]" from test') print "with column names:", cur.fetchone()[0] cur.close() con.close() pysqlite-2.6.3/doc/includes/sqlite3/countcursors.py000644 000765 000024 00000000740 11343657406 023417 0ustar00ghaeringstaff000000 000000 from pysqlite2 import dbapi2 as sqlite3 class CountCursorsConnection(sqlite3.Connection): def __init__(self, *args, **kwargs): sqlite3.Connection.__init__(self, *args, **kwargs) self.numcursors = 0 def cursor(self, *args, **kwargs): self.numcursors += 1 return sqlite3.Connection.cursor(self, *args, **kwargs) con = sqlite3.connect(":memory:", factory=CountCursorsConnection) cur1 = con.cursor() cur2 = con.cursor() print con.numcursors pysqlite-2.6.3/doc/includes/sqlite3/createdb.py000644 000765 000024 00000001150 11343657406 022413 0ustar00ghaeringstaff000000 000000 # Not referenced from the documentation, but builds the database file the other # code snippets expect. from pysqlite2 import dbapi2 as sqlite3 import os DB_FILE = "mydb" if os.path.exists(DB_FILE): os.remove(DB_FILE) con = sqlite3.connect(DB_FILE) cur = con.cursor() cur.execute(""" create table people ( name_last varchar(20), age integer ) """) cur.execute("insert into people (name_last, age) values ('Yeltsin', 72)") cur.execute("insert into people (name_last, age) values ('Putin', 51)") con.commit() cur.close() con.close() pysqlite-2.6.3/doc/includes/sqlite3/ctx_manager.py000644 000765 000024 00000001170 11343657406 023134 0ustar00ghaeringstaff000000 000000 from __future__ import with_statement from pysqlite2 import dbapi2 as sqlite3 con = sqlite3.connect(":memory:") con.execute("create table person (id integer primary key, firstname varchar unique)") # Successful, con.commit() is called automatically afterwards with con: con.execute("insert into person(firstname) values (?)", ("Joe",)) # con.rollback() is called after the with block finishes with an exception, the # exception is still raised and must be catched try: with con: con.execute("insert into person(firstname) values (?)", ("Joe",)) except sqlite3.IntegrityError: print "couldn't add Joe twice" pysqlite-2.6.3/doc/includes/sqlite3/execsql_fetchonerow.py000644 000765 000024 00000000764 11343657406 024723 0ustar00ghaeringstaff000000 000000 from pysqlite2 import dbapi2 as sqlite3 con = sqlite3.connect("mydb") cur = con.cursor() SELECT = "select name_last, age from people order by age, name_last" # 1. Iterate over the rows available from the cursor, unpacking the # resulting sequences to yield their elements (name_last, age): cur.execute(SELECT) for (name_last, age) in cur: print '%s is %d years old.' % (name_last, age) # 2. Equivalently: cur.execute(SELECT) for row in cur: print '%s is %d years old.' % (row[0], row[1]) pysqlite-2.6.3/doc/includes/sqlite3/execsql_printall_1.py000644 000765 000024 00000000567 11343657406 024446 0ustar00ghaeringstaff000000 000000 from pysqlite2 import dbapi2 as sqlite3 # Create a connection to the database file "mydb": con = sqlite3.connect("mydb") # Get a Cursor object that operates in the context of Connection con: cur = con.cursor() # Execute the SELECT statement: cur.execute("select * from people order by age") # Retrieve all rows as a sequence and print that sequence: print cur.fetchall() pysqlite-2.6.3/doc/includes/sqlite3/execute_1.py000644 000765 000024 00000000344 11343657406 022530 0ustar00ghaeringstaff000000 000000 from pysqlite2 import dbapi2 as sqlite3 con = sqlite3.connect("mydb") cur = con.cursor() who = "Yeltsin" age = 72 cur.execute("select name_last, age from people where name_last=? and age=?", (who, age)) print cur.fetchone() pysqlite-2.6.3/doc/includes/sqlite3/execute_2.py000644 000765 000024 00000000374 11343657406 022534 0ustar00ghaeringstaff000000 000000 from pysqlite2 import dbapi2 as sqlite3 con = sqlite3.connect("mydb") cur = con.cursor() who = "Yeltsin" age = 72 cur.execute("select name_last, age from people where name_last=:who and age=:age", {"who": who, "age": age}) print cur.fetchone() pysqlite-2.6.3/doc/includes/sqlite3/execute_3.py000644 000765 000024 00000000354 11343657406 022533 0ustar00ghaeringstaff000000 000000 from pysqlite2 import dbapi2 as sqlite3 con = sqlite3.connect("mydb") cur = con.cursor() who = "Yeltsin" age = 72 cur.execute("select name_last, age from people where name_last=:who and age=:age", locals()) print cur.fetchone() pysqlite-2.6.3/doc/includes/sqlite3/executemany_1.py000644 000765 000024 00000001074 11343657406 023416 0ustar00ghaeringstaff000000 000000 from pysqlite2 import dbapi2 as sqlite3 class IterChars: def __init__(self): self.count = ord('a') def __iter__(self): return self def next(self): if self.count > ord('z'): raise StopIteration self.count += 1 return (chr(self.count - 1),) # this is a 1-tuple con = sqlite3.connect(":memory:") cur = con.cursor() cur.execute("create table characters(c)") theIter = IterChars() cur.executemany("insert into characters(c) values (?)", theIter) cur.execute("select c from characters") print cur.fetchall() pysqlite-2.6.3/doc/includes/sqlite3/executemany_2.py000644 000765 000024 00000000557 11343657406 023424 0ustar00ghaeringstaff000000 000000 from pysqlite2 import dbapi2 as sqlite3 def char_generator(): import string for c in string.letters[:26]: yield (c,) con = sqlite3.connect(":memory:") cur = con.cursor() cur.execute("create table characters(c)") cur.executemany("insert into characters(c) values (?)", char_generator()) cur.execute("select c from characters") print cur.fetchall() pysqlite-2.6.3/doc/includes/sqlite3/executescript.py000644 000765 000024 00000000674 11343657406 023543 0ustar00ghaeringstaff000000 000000 from pysqlite2 import dbapi2 as sqlite3 con = sqlite3.connect(":memory:") cur = con.cursor() cur.executescript(""" create table person( firstname, lastname, age ); create table book( title, author, published ); insert into book(title, author, published) values ( 'Dirk Gently''s Holistic Detective Agency', 'Douglas Adams', 1987 ); """) pysqlite-2.6.3/doc/includes/sqlite3/insert_more_people.py000644 000765 000024 00000000547 11343657406 024545 0ustar00ghaeringstaff000000 000000 from pysqlite2 import dbapi2 as sqlite3 con = sqlite3.connect("mydb") cur = con.cursor() newPeople = ( ('Lebed' , 53), ('Zhirinovsky' , 57), ) for person in newPeople: cur.execute("insert into people (name_last, age) values (?, ?)", person) # The changes will not be saved unless the transaction is committed explicitly: con.commit() pysqlite-2.6.3/doc/includes/sqlite3/load_extension.py000644 000765 000024 00000002010 11343657406 023651 0ustar00ghaeringstaff000000 000000 from pysqlite2 import dbapi2 as sqlite3 con = sqlite3.connect(":memory:") # enable extension loading con.enable_load_extension(True) # Load the fulltext search extension con.execute("select load_extension('./fts3.so')") # alternatively you can load the extension using an API call: # con.load_extension("./fts3.so") # disable extension laoding again con.enable_load_extension(False) # example from SQLite wiki con.execute("create virtual table recipe using fts3(name, ingredients)") con.executescript(""" insert into recipe (name, ingredients) values ('broccoli stew', 'broccoli peppers cheese tomatoes'); insert into recipe (name, ingredients) values ('pumpkin stew', 'pumpkin onions garlic celery'); insert into recipe (name, ingredients) values ('broccoli pie', 'broccoli cheese onions flour'); insert into recipe (name, ingredients) values ('pumpkin pie', 'pumpkin sugar flour butter'); """) for row in con.execute("select rowid, name, ingredients from recipe where name match 'pie'"): print row pysqlite-2.6.3/doc/includes/sqlite3/md5func.py000644 000765 000024 00000000400 11343657406 022200 0ustar00ghaeringstaff000000 000000 from pysqlite2 import dbapi2 as sqlite3 import md5 def md5sum(t): return md5.md5(t).hexdigest() con = sqlite3.connect(":memory:") con.create_function("md5", 1, md5sum) cur = con.cursor() cur.execute("select md5(?)", ("foo",)) print cur.fetchone()[0] pysqlite-2.6.3/doc/includes/sqlite3/mysumaggr.py000644 000765 000024 00000000757 11343657406 022671 0ustar00ghaeringstaff000000 000000 from pysqlite2 import dbapi2 as sqlite3 class MySum: def __init__(self): self.count = 0 def step(self, value): self.count += value def finalize(self): return self.count con = sqlite3.connect(":memory:") con.create_aggregate("mysum", 1, MySum) cur = con.cursor() cur.execute("create table test(i)") cur.execute("insert into test(i) values (1)") cur.execute("insert into test(i) values (2)") cur.execute("select mysum(i) from test") print cur.fetchone()[0] pysqlite-2.6.3/doc/includes/sqlite3/parse_colnames.py000644 000765 000024 00000000404 11343657406 023636 0ustar00ghaeringstaff000000 000000 from pysqlite2 import dbapi2 as sqlite3 import datetime con = sqlite3.connect(":memory:", detect_types=sqlite3.PARSE_COLNAMES) cur = con.cursor() cur.execute('select ? as "x [timestamp]"', (datetime.datetime.now(),)) dt = cur.fetchone()[0] print dt, type(dt) pysqlite-2.6.3/doc/includes/sqlite3/progress.py000644 000765 000024 00000001242 11343657406 022510 0ustar00ghaeringstaff000000 000000 from pysqlite2 import dbapi2 as sqlite3 def progress(): print "Query still executing. Please wait ..." con = sqlite3.connect(":memory:") con.execute("create table test(x)") # Let's create some data con.executemany("insert into test(x) values (?)", [(x,) for x in xrange(300)]) # A progress handler, executed every 10 million opcodes con.set_progress_handler(progress, 10000000) # A particularly long-running query killer_stament = """ select count(*) from ( select t1.x from test t1, test t2, test t3 ) """ con.execute(killer_stament) print "-" * 50 # Clear the progress handler con.set_progress_handler(None, 0) con.execute(killer_stament) pysqlite-2.6.3/doc/includes/sqlite3/pysqlite_datetime.py000644 000765 000024 00000001265 11343657406 024377 0ustar00ghaeringstaff000000 000000 from pysqlite2 import dbapi2 as sqlite3 import datetime con = sqlite3.connect(":memory:", detect_types=sqlite3.PARSE_DECLTYPES|sqlite3.PARSE_COLNAMES) cur = con.cursor() cur.execute("create table test(d date, ts timestamp)") today = datetime.date.today() now = datetime.datetime.now() cur.execute("insert into test(d, ts) values (?, ?)", (today, now)) cur.execute("select d, ts from test") row = cur.fetchone() print today, "=>", row[0], type(row[0]) print now, "=>", row[1], type(row[1]) cur.execute('select current_date as "d [date]", current_timestamp as "ts [timestamp]"') row = cur.fetchone() print "current_date", row[0], type(row[0]) print "current_timestamp", row[1], type(row[1]) pysqlite-2.6.3/doc/includes/sqlite3/row_factory.py000644 000765 000024 00000000474 11343657406 023210 0ustar00ghaeringstaff000000 000000 from pysqlite2 import dbapi2 as sqlite3 def dict_factory(cursor, row): d = {} for idx, col in enumerate(cursor.description): d[col[0]] = row[idx] return d con = sqlite3.connect(":memory:") con.row_factory = dict_factory cur = con.cursor() cur.execute("select 1 as a") print cur.fetchone()["a"] pysqlite-2.6.3/doc/includes/sqlite3/rowclass.py000644 000765 000024 00000000520 11343657406 022477 0ustar00ghaeringstaff000000 000000 from pysqlite2 import dbapi2 as sqlite3 con = sqlite3.connect("mydb") con.row_factory = sqlite3.Row cur = con.cursor() cur.execute("select name_last, age from people") for row in cur: assert row[0] == row["name_last"] assert row["name_last"] == row["nAmE_lAsT"] assert row[1] == row["age"] assert row[1] == row["AgE"] pysqlite-2.6.3/doc/includes/sqlite3/shared_cache.py000644 000765 000024 00000000276 11343657406 023243 0ustar00ghaeringstaff000000 000000 from pysqlite2 import dbapi2 as sqlite3 # The shared cache is only available in SQLite versions 3.3.3 or later # See the SQLite documentaton for details. sqlite3.enable_shared_cache(True) pysqlite-2.6.3/doc/includes/sqlite3/shortcut_methods.py000644 000765 000024 00000001116 11343657406 024242 0ustar00ghaeringstaff000000 000000 from pysqlite2 import dbapi2 as sqlite3 persons = [ ("Hugo", "Boss"), ("Calvin", "Klein") ] con = sqlite3.connect(":memory:") # Create the table con.execute("create table person(firstname, lastname)") # Fill the table con.executemany("insert into person(firstname, lastname) values (?, ?)", persons) # Print the table contents for row in con.execute("select firstname, lastname from person"): print row # Using a dummy WHERE clause to not let SQLite take the shortcut table deletes. print "I just deleted", con.execute("delete from person where 1=1").rowcount, "rows" pysqlite-2.6.3/doc/includes/sqlite3/simple_tableprinter.py000644 000765 000024 00000001322 11343657406 024707 0ustar00ghaeringstaff000000 000000 from pysqlite2 import dbapi2 as sqlite3 FIELD_MAX_WIDTH = 20 TABLE_NAME = 'people' SELECT = 'select * from %s order by age, name_last' % TABLE_NAME con = sqlite3.connect("mydb") cur = con.cursor() cur.execute(SELECT) # Print a header. for fieldDesc in cur.description: print fieldDesc[0].ljust(FIELD_MAX_WIDTH) , print # Finish the header with a newline. print '-' * 78 # For each row, print the value of each field left-justified within # the maximum possible width of that field. fieldIndices = range(len(cur.description)) for row in cur: for fieldIndex in fieldIndices: fieldValue = str(row[fieldIndex]) print fieldValue.ljust(FIELD_MAX_WIDTH) , print # Finish the row with a newline. pysqlite-2.6.3/doc/includes/sqlite3/text_factory.py000644 000765 000024 00000002532 11343657406 023362 0ustar00ghaeringstaff000000 000000 from pysqlite2 import dbapi2 as sqlite3 con = sqlite3.connect(":memory:") cur = con.cursor() # Create the table con.execute("create table person(lastname, firstname)") AUSTRIA = u"\xd6sterreich" # by default, rows are returned as Unicode cur.execute("select ?", (AUSTRIA,)) row = cur.fetchone() assert row[0] == AUSTRIA # but we can make pysqlite always return bytestrings ... con.text_factory = str cur.execute("select ?", (AUSTRIA,)) row = cur.fetchone() assert type(row[0]) == str # the bytestrings will be encoded in UTF-8, unless you stored garbage in the # database ... assert row[0] == AUSTRIA.encode("utf-8") # we can also implement a custom text_factory ... # here we implement one that will ignore Unicode characters that cannot be # decoded from UTF-8 con.text_factory = lambda x: unicode(x, "utf-8", "ignore") cur.execute("select ?", ("this is latin1 and would normally create errors" + u"\xe4\xf6\xfc".encode("latin1"),)) row = cur.fetchone() assert type(row[0]) == unicode # pysqlite offers a builtin optimized text_factory that will return bytestring # objects, if the data is in ASCII only, and otherwise return unicode objects con.text_factory = sqlite3.OptimizedUnicode cur.execute("select ?", (AUSTRIA,)) row = cur.fetchone() assert type(row[0]) == unicode cur.execute("select ?", ("Germany",)) row = cur.fetchone() assert type(row[0]) == str